@eyeauras/workbench

中文文档
0.3.44发布于 2026/11/03MITTypeScriptES Module零依赖近 30 天下载 2855

Host-neutral VS Code-shaped workbench services, layouts, and DOM shell.

原始使用文档
文档目录7 节
  1. Quickstart
  2. API and controls
  3. Trees
  4. FeedbackButton
  5. TagEditor keyboard and styling contract
  6. Message boxes and input dialogs
  7. Tooltips and hover cards

@eyeauras/workbench

Host-neutral TypeScript workbench services, contribution points, layouts, styles, and an imperative DOM shell shaped after Visual Studio Code.

Quickstart

Use an ESM browser bundler with CSS-import support (for example Vite), a browser DOM, and a sized host.

npm install @eyeauras/[email protected] monaco-editor@^0.52.2 @vscode/codicons
import { createWorkbench } from "@eyeauras/workbench";
import "@vscode/codicons/dist/codicon.css";
const host = document.createElement("div");
host.style.cssText = "width:100%;height:600px";
document.body.append(host);
const workbench = createWorkbench(host, { productName: "My application" });
workbench.registerView({
  id: "files", title: "Files", location: "sidebar", icon: "files",
  render(container) { container.textContent = "Your files"; },
});
workbench.openEditor({ id: "welcome", title: "Welcome", editorType: "text", data: "Hello" });
// Call on host unmount; renderers may return their own resource disposable.
export function dispose() { workbench.dispose(); host.remove(); }

The shell installs shared styles and observes resizing. Standalone controls require installWorkbenchStyles(document) from @eyeauras/workbench/styles once. Codicon classes also need the font CSS above. Editor workers are only needed by actual Monaco editors. See the full quickstart for React, build prerequisites and package selection.

API and controls

Rich action UI (/controls): WorkbenchDropdownMenu opens a menu from the whole trigger; WorkbenchButtonWithDropdown separates primary action from alternatives; createWorkbenchToolbar provides live VS Code ToolBar rendering. WorkbenchContextMenuService is shared with Problems. Opt the shell in with createWorkbench(host, { actionUI: createWorkbenchActionUI }); existing menus.createToolbar(menu, className?) calls remain compatible. See the repository's Actions guide.

monaco-editor is a required peer dependency because the package reuses VS Code's context-key parser. @vscode/codicons is optional. Import @eyeauras/workbench/vscode-grid, @eyeauras/workbench/controls, or @eyeauras/workbench/problems only when the host bundler can resolve CSS imports from JavaScript. The aggregate @eyeauras/workbench root is a browser-oriented, Monaco-bearing surface and imports grid/splitview CSS.

The owning notification service, toast renderer, split layout, and style installer are also available as independent light subpaths. Each module is Node-loadable without installing a DOM shim; DOM values are required only when invoking the renderer, layout, or style installer that operates on them.

The grid's tab overflow picker uses a borrowed contextMenus service supplied in its create/restore options. The shell supplies its actionUI service; the React grid adapter owns a service for its lifetime. Standalone imperative grids can pass WorkbenchContextMenuService from /controls. Without a menu service the grid renders its tab strip without an overflow picker. Disposing a grid closes its own popup, never the borrowed service.

Set WorkbenchGridGroup.preserveEmpty: true for a document group whose position and size must survive closing or moving its last tab. It keeps the normal empty placeholder and roundtrips through layout serialization/restoration. The default still removes empty groups.

Trees

Use @eyeauras/workbench/tree with optional selection, input, guides and drag/drop subpaths. The consumer supplies a TreeSource and independently bound content VMs; state flows through revisioned channels. See the package guide.

import { WorkbenchNotificationService } from "@eyeauras/workbench/notifications";
import { renderNotificationToasts } from "@eyeauras/workbench/notification-toasts";
import { createWorkbenchSplitLayout } from "@eyeauras/workbench/split-layout";
import { installWorkbenchStyles, workbenchStyles } from "@eyeauras/workbench/styles";
import { WorkbenchComboBox, WorkbenchTagEditor } from "@eyeauras/workbench/controls";
import { WorkbenchConfirmButton } from "@eyeauras/workbench/controls/confirm-button";
import { WorkbenchToggleTextBox } from "@eyeauras/workbench/controls/toggle-text-box";
import { WorkbenchProblemsIndicator, WorkbenchProblemsView } from "@eyeauras/workbench/problems";

The controls subpath wraps VS Code's InputBox, Button, Toggle, ProgressBar, SelectBox, List, and ContextView behind stable framework-neutral APIs. ComboBox<T> adds cancellable suggestions and an accessible disclosure button that opens the complete suggestion set; TagEditor composes it for string tags and normalized duplicate rejection. InputBox's placeholder is its native watermark; string prefix and suffix adorn the field without entering its value. The shared ContextView portal uses native popover="auto" when available, so anchored controls receive one browser-managed top layer, light-dismiss, and Esc contract instead of implementing dismissal themselves.

FeedbackButton

WorkbenchFeedbackButton is a separate control exported from @eyeauras/workbench/controls. It composes the VS Code Button; existing Button and ConfirmButton behavior is unchanged.

import { WorkbenchFeedbackButton } from "@eyeauras/workbench/controls";

const copy = new WorkbenchFeedbackButton(container, {
  action: () => navigator.clipboard.writeText(text),
  idle: { label: "Copy" },
  pending: { label: "Copying…" },
  success: { label: "Copied" },
  error: { label: "Copy failed" },
  resetMs: 3000,
});
copy.onDidFail(error => reportError(error));
// Dispose with the containing view.

Each face accepts label, a decorative icon: Node, and ariaLabel (required when icon-only). Supply distinct icon nodes per face; do not nest interactive content. Result names are announced through a polite live region. Resolving the action means success, including a resolved false; throw/reject for failure. Repeated activation is ignored only while pending or disabled. update changes options without restarting a running action or its result timer; an omitted face uses the default English text, and passing undefined restores that default. dispose removes UI/timers but does not cancel the host operation.

All faces share icon/text columns and reserve layout space from the start, so neither the icon nor the start of the label jumps between states. Pending blocks reentry without applying the host-disabled dimming. The control is constrained by the parent width; long labels truncate with a full tooltip. Style .ea-workbench-feedback-button and its [data-state], .ea-workbench-feedback-face, .ea-workbench-feedback-icon, .ea-workbench-feedback-label slots; use the usual inherited --vscode-button-background, --vscode-button-hoverBackground, --vscode-button-foreground, and --vscode-button-border tokens. The demo Controls tab includes success and failure examples; the compact Problems popup uses it for Copy All.

TagEditor keyboard and styling contract

The field stays on one line. Chips and the existing input share an internal horizontal viewport; keyboard focus reveals the active item without scrolling the hosting document. Scroll buttons keep a stable footprint and move by one viewport width; native scroll limits clamp them at either end. They remain available at the ends and are disabled with the editor. CSS owns sizing and clipping; there is no resize observer or polling to decide the layout.

When its input is empty, ArrowLeft or the first Backspace moves to the final tag without mutating the value. ArrowLeft / ArrowRight then move among tags and back to the input. Enter or a click edits the focused tag in place; Enter or comma commits, Escape cancels, and a valid free-form edit commits on blur. Backspace or Delete removes a keyboard-focused tag. Set editable: false when existing tags may be removed but not renamed. IME composition is never confirmed as a tag.

The default accessible description explains the empty-input shortcuts; set ariaDescription to provide localized instructions. Add, edit, and remove changes are announced through a polite live region. Empty and duplicate edits remain open so the user can correct them.

The following slot classes are stable customization points: .ea-workbench-tag-editor, .ea-workbench-tag-viewport, .ea-workbench-tag-scroll, .ea-workbench-tags, .ea-workbench-tag, .ea-workbench-tag-label, .ea-workbench-tag-remove, and .ea-workbench-tag-input. The tag being edited also carries .ea-workbench-tag.is-editing. The existing ComboBox input is moved into that slot, so customization does not have to account for a second input or a separate editing model. Prefer inherited custom properties for colors:

PropertyPurpose
--ea-tag-editor-backgroundeditor background
--ea-tag-editor-border-coloridle border
--ea-tag-editor-focus-border-colorfocus-within border
--ea-tag-editor-tag-backgroundtag background
--ea-tag-editor-tag-foregroundtag text/remove foreground
--ea-tag-editor-tag-remove-hover-backgroundremove-button hover background

Each property falls back to the matching VS Code theme variable. Internal Monaco classes and DOM beyond the documented slots are not customization API.

ConfirmButton and ToggleTextBox are framework-neutral forms of the established React composites. Expanded confirmation may use an icon-only cancel action by pairing cancelIcon with cancelAriaLabel. Their direct subpaths are intentionally light: they do not import the aggregate CSS-bearing VS Code controls slice.

workbench.services.diagnostics is the shared host-neutral store for validation, compiler, and runtime findings. Publishers identify themselves with a stable owner and publish against an exact resource string; set(owner, resource, diagnostics) replaces one tuple, while replaceOwner(owner, entries) atomically replaces that owner's full snapshot without touching other owners. Reads are immutable and can be filtered by owner, resource, or severity. Monaco marker projection is supplied by @eyeauras/workbench-monaco; other presentations can read the same store independently.

The @eyeauras/workbench/problems subpath supplies two reusable presentations without adding another store. WorkbenchProblemsView is an IDE-style List-backed grid with Severity, Code, Message, File/location, and Source columns, text filtering across displayed fields, severity toggles, stable multi-selection, and a visible Showing X of Y summary. Ctrl/Cmd+C copies the selection; its context/overflow menu also exposes Open, Copy Selected, and Copy All Problems. Copy All always means the current filtered and sorted projection, not only virtualized rows. Truncated cells disclose their full text on hover.

WorkbenchProblemsIndicator is the self-contained presentation for windows and dialogs that cannot fit the full grid. Its indicator shows the highest non-zero severity and opens a native-popover list containing every diagnostic across all severities. maxVisible limits only the viewport before it scrolls; it never truncates the data. The popup activates rows, copies the focused row with Ctrl/Cmd+C, and copies the complete list from its header without requiring a separate Problems view. Both widgets update from onDidChangeDiagnostics, accept an optional openDiagnostic(diagnostic) callback, and accept formatResource(resource) for consumer-owned display labels. The default formatter preserves the exact resource string; the framework never parses it as a path.

const problems = new WorkbenchProblemsView(container, workbench.services.diagnostics, {
  formatResource: (resource) => ({ label: resource }),
  openDiagnostic: (diagnostic) => openResource(diagnostic.resource, diagnostic.range),
  // Optional host boundary and row serialization; navigator.clipboard and IDE-style text are the defaults.
  writeClipboardText: (text) => hostClipboard.writeText(text),
  formatClipboardRow: (row) => `${row.diagnostic.resource}: ${row.diagnostic.message}`,
});

const indicator = new WorkbenchProblemsIndicator(statusHost, workbench.services.diagnostics, {
  openDiagnostic: (diagnostic) => openResource(diagnostic.resource, diagnostic.range),
  maxVisible: 6,
  writeClipboardText: (text) => hostClipboard.writeText(text),
});

Dispose both widgets with their host view. Text and severity filters are presentation state; diagnostics remain owned solely by their publishers.

The package is developed in the EyeAuras UI Workbench repository. See its root README for API orientation, architecture, and consumer requirements.

Message boxes and input dialogs

Use workbench.services.messageBoxes.show() for save prompts and custom dialogs. Content receives a typed action context for validation, guarded form submission and input focus. React consumers can use renderReactMessageBoxContent(context => <YourContent context={context} />) from @eyeauras/workbench-react/core. See the Message-box API and complete React input example.

Tooltips and hover cards

Use workbench.services.hover.setupDelayedHover(target, options, { groupId }), or create a standalone WorkbenchHoverService. Content accepts text, a DOM element or a disposable renderer. Choose a side with position and matching edges or centers with alignment: "start" | "center" | "end". Related targets can share groupId to switch immediately after the first preview appears. Alt keeps the current card open; Alt+ArrowDown enters it and Escape closes it with guarded focus restoration. Dispose registrations with their owning view.

The optional React adapter is WorkbenchTooltip from @eyeauras/workbench-react/hover. See the Hover guide for DOM/React examples, defaults, native Popover fallbacks and lifecycle details. The Controls demo includes Hover / Tooltip and the separate twelve-point Hover anchors example.

Host rail toggles registered with registerToggle accept position: "primary" for the top cluster or "secondary" for the bottom cluster. Omitted placement stays secondary. This changes placement only; host-controlled state and retained button identity are unchanged.

Message boxes accept an optional width in CSS pixels for table-based content; the shell still limits the dialog to the viewport. Other dialogs retain the standard width.

版本与发布记录

@eyeauras/workbench 共发布 21 个版本,首次发布于 2026/10/14;过去 12 个月发布了 21 个版本。

版本发布日期距今
0.3.44latest2026/11/0311 天前
0.3.422026/10/2817 天前
0.3.392026/10/2520 天前
0.3.382026/10/2520 天前
0.3.372026/10/2420 天前
0.3.362026/10/2420 天前

关于 @eyeauras/workbench 的常见问题

@eyeauras/workbench 是什么?

Host-neutral VS Code-shaped workbench services, layouts, and DOM shell.

如何安装 @eyeauras/workbench?

在项目目录运行 npm install @eyeauras/workbench,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:monaco-editor(^0.52.2)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@eyeauras/workbench 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@eyeauras/workbench 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@eyeauras/workbench 可以商用吗?

@eyeauras/workbench 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@eyeauras/workbench 的下载量有多少?

根据 npm 官方下载统计,@eyeauras/workbench 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,855 次,日均约 95 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@eyeauras/workbench 还在维护吗?

最新版本 0.3.44 发布于 2026/11/03(11 天前);至今共发布 21 个版本,其中过去 12 个月发布了 21 个;首次发布于 2026/10/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。