@eyeauras/workbench-react
v0.3.39
Published
React adapters and reusable controls for @eyeauras/workbench.
Readme
@eyeauras/workbench-react
Optional React context, hooks, grid portals, layouts, and reusable controls over the host-neutral
@eyeauras/workbench core.
Install
npm install @eyeauras/[email protected] @eyeauras/[email protected] react react-dom monaco-editor@^0.52.2 @vscode/codiconsQuickstart
Requires React/React DOM >=18.3.1, the core Monaco peer, and a React-enabled browser bundler with CSS support.
React row rendering is available separately through @eyeauras/workbench-react/tree; see the
tree content guide.
TypeScript applications also install @types/react and @types/react-dom; install @vscode/codicons for icons.
import { createWorkbench } from "@eyeauras/workbench";
import { createReactWorkbenchPage, useWorkbench } from "@eyeauras/workbench-react/core";
import "@vscode/codicons/dist/codicon.css";
function Home() {
const workbench = useWorkbench();
return <button onClick={() => workbench.services.notifications.info("Ready")}>Notify</button>;
}
const host = document.createElement("div");
host.style.cssText = "width:100%;height:600px";
document.body.append(host);
const workbench = createWorkbench(host);
workbench.registerPage(createReactWorkbenchPage({ id: "home", title: "Home", render: () => <Home /> }));
workbench.showPage("home");
export function dispose() { workbench.dispose(); host.remove(); }The page supplies WorkbenchProvider and disposes its React root. For roots you create yourself, wrap
Workbench hooks in <WorkbenchProvider workbench={workbench}>. Standalone controls need
installWorkbenchStyles(document) from @eyeauras/workbench/styles; a provider installs no styles.
The full quickstart includes installation and host setup.
React remains an adapter; the core workbench is not React-owned. See the EyeAuras UI Workbench repository for package guidance and examples.
The @eyeauras/workbench-react/controls subpath includes lifecycle-only React adapters for the core
InputBox, Button, FeedbackButton, Toggle, ProgressBar, SelectBox, ComboBox, and TagEditor controls. Their behavior and
DOM remain owned by @eyeauras/workbench/controls; InputBox/ComboBox/TagEditor forward the native
placeholder watermark plus string prefix/suffix adornments.
Adapter state follows ordinary React contracts: value, checked, selectedIndex, and values are
controlled and are restored when a host rejects an edit; defaultValue / defaultValues are consumed
only at mount. New inline provider, validator, normalizer, or options identities do not dispose and
recreate the underlying control.
TagEditor keeps the core keyboard, inline-editing, accessibility, IME, and styling behavior. Its
editable option only controls renaming; tags remain removable. Put the documented
--ea-tag-editor-* custom properties on the React adapter's className host (or an ancestor); they
inherit into the core control. The stable slot-class list and variable table live in the core package
README. Use ariaDescription when the default English keyboard help must be localized.
WorkbenchFeedbackButton is available from the root and /controls. It uses the core options, with
ReactNode icon slots and an onError(error) callback. Icons are portals; execution and timers remain
in the core. Changing props does not restart a pending action. Put theme tokens on its className host.
The core README documents result semantics, stable sizing and disposal. It does not replace ConfirmButton.
WorkbenchDropdownMenu, WorkbenchButtonWithDropdown and WorkbenchToolbar are available from root and
/controls. Dropdown controls borrow contextMenus; Toolbar receives menus and a menu ID. They adapt
the imperative core and dispose only their own control. Service and secondary variant are construction
dependencies. The repository's docs/ACTIONS.md documents the complete contract.
The established WorkbenchConfirmButton and WorkbenchToggleTextBox exports keep their original root
and dedicated-subpath APIs. Their reusable state and lifetime now come from light core subpaths, while
the React compatibility layer retains the existing JSX, ReactNode slots, native props, SSR output, and
DOM/accessibility contract.
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.
Numeric up/down
WorkbenchNumericUpDown is exported from the package root and /controls. It composes the existing
React-owned WorkbenchNumberField, also used by RandomTimeSpan and ValueMinMaxRange, with numeric
state. It uses the shared workbench input, affix, focus and stepper theme styles.
import { WorkbenchNumericUpDown } from "@eyeauras/workbench-react/controls";
<WorkbenchNumericUpDown
ariaLabel="Probability"
value={probability}
minimum={0}
maximum={100}
step={0.5}
suffix="%"
onValueChange={setProbability}
/>value is a finite controlled number. Optional minimum/maximum are finite bounds; step is positive
and defaults to 1. Typing keeps a local draft until Enter or blur. Empty/invalid drafts and Escape restore
the accepted value. Committing clamps to bounds without snapping typed decimals to the step grid.
ArrowUp/ArrowDown and the buttons step from the draft (or accepted value if the draft is invalid),
commit immediately and preserve focus. The parent may accept, transform or reject a proposed value;
the field reconciles before paint. External value/bound changes replace an in-progress draft.
prefix/suffix are inline, non-editable text. Supply units in ariaLabel when they are needed in the
accessible name. disabled disables the input and both actions; id targets the native input for an
external label. inputClassName adds input chrome and inputTestId identifies the input when needed.
The standard compact field works inside 350–400 px inspectors. The numeric showcase is in the demo's
Random time span section.
WorkbenchNumberField is also exported from the package root and /controls for controlled string-buffer
consumers. Use inputType="text" with inputMode="numeric" or "decimal" to preserve raw drafts such as
- and 12a; the caller owns parsing, validity (ariaInvalid), stepping (onStep) and change timing.
onCommit is optional: without it, blur and Enter acquire no commit policy. The default inputType="number"
retains native numeric editing. Both modes use the same font-frame, affix and stepper layout.
Native form semantics
WorkbenchInputBox forwards id, name, autoComplete, required, and readOnly to its native input without recreating it. autoFocus focuses on mount; selectOnFocus selects a readonly result for copying. onBlur(value) observes the current text and onKeyDown(event) receives the native keyboard event, including preventDefault(). Value changes still use onValueChange; these hooks do not introduce a second commit state machine.
WorkbenchSelectBox.id targets its native select. WorkbenchToggle.id supports an external label htmlFor: the shared control activates and focuses Monaco's non-native checkbox, respecting disabled state and removing the listener on disposal. Its accessible name remains title.
WorkbenchButton is an ordinary action, not a native submit button. Forms requiring implicit Enter submission or browser validation keep their native button type="submit" and existing form handler; do not emulate submission with a second click/keyboard handler.
Scalar slider event timing
WorkbenchValueRange defaults to changeMode="commit": input previews locally; pointer release, supported range-key release or blur emits once and restores the accepted value if rejected. changeMode="input" uses the same onValueChange on slider input; release/blur never send a second command. Pointer cancel restores the current accepted value and cannot undo already accepted live updates. External value changes replace the local draft. Numeric editor commits retain their existing behavior in both modes.
sliderStep defaults to numeric step, but accepts its own positive number or "any". The visual slider domain does not constrain the numeric value; use minimum/maximum only for actual bounds. showValueEditor={false} with showValueReadout keeps a noneditable value and suffix visible.
Confirmation lifetime
WorkbenchConfirmButton and the imperative control share exclusivity through a scope object (owner document by default). Arming another control in that scope cancels the previous one. Use an explicit scope for independent areas; do not add a consumer registry. armTimeoutMs={null} disables self-disarm; zero remains an immediate timeout.
The default policy cancels on focus leaving the control and outside pointerdown. cancelOnFocusLeave={false} and cancelOnOutsidePointer={false} preserve a deliberately persistent confirmation, while disable, unmount, explicit cancel and another arming still disarm. destructive={false} uses neutral theme colors without changing the footprint. Main Delete profile/Close session need the persistent policy; AI uses the default outside/focus policy and no timer. Detach remains immediate.
Native form checkboxes
Use WorkbenchCheckbox for form checkboxes and WorkbenchToggle for Monaco icon toggles. The checkbox keeps the native input, so labels, forms and :disabled behave natively, while the installed Workbench styles draw its box from checkbox tokens in the native footprint. It forwards native input attributes and exposes controlled checked / onCheckedChange. Monaco Toggle's icon-only DIV is not a visual replacement. SelectBox also forwards title and ariaInvalid to its actual select element for input-method health and description.
useWorkbenchConfirm exposes the same controller-backed lifecycle for an existing host presentation. Attach rootRef to its stable wrapper and use armed, activate and cancel; the shared scope and outside-pointer lifetime remain authoritative. Use it when the standard button footprint cannot preserve an existing screen (for example the main-window Close/Cancel pair). Do not reproduce a registry or state machine in the host.
WorkbenchValueRange accepts appearance="native" with a host className for existing native form layouts (percentage and formation sliders). It uses the same input and value lifecycle; browser rendering replaces the workbench track/tooltip, and native percentage readouts keep % adjacent to the number. The default workbench appearance is unchanged.
ValueRange delegates numeric drafts and decimal stepping to WorkbenchNumericUpDown; empty input does not become zero. inputTestId reaches the actual numeric input. Native appearance renders that same numeric control directly in the host layout.
Property/form grid
The light @eyeauras/workbench-react/property-grid entry exports WorkbenchPropertyGrid, WorkbenchPropertyGroup, WorkbenchPropertyRow, WorkbenchPropertyCell, WorkbenchPropertyFields, and WorkbenchPropertyTrailing. Named columns and explicit rows support independent continuations. See Property grid authoring for sizing, accessibility, responsive budgets and examples. Install the existing Workbench styles in the host; the React entry imports no CSS.
Tooltips and hover cards
Import WorkbenchTooltip from @eyeauras/workbench-react/hover and render it under WorkbenchProvider.
It accepts one child with a DOM ref, or a targetRef for an existing element. content is a React node;
set interactive and ariaLabel for cards with actions. position selects the side and alignment
selects start, center or end on the perpendicular axis. Related targets share a groupId.
The adapter uses a portal into the core hover lifecycle, preserving React context, state, draft and
focus across updates. handleRef exposes explicit show/hide/update/dispose control. Alt retains the
card; Alt+ArrowDown enters it and Escape closes it. See the
Hover guide for text and
image/button examples, grouped lists and keyboard behavior. The Controls demo includes Hover / Tooltip
and a separate Hover anchors geometry example.
Active editor group actions
WorkbenchVscodeGridLayout.activeGroupToolbar renders one React command surface beside
the tabs in the actual active group, including groups created by a tab drag/split.
With a controlled activeTabId, the surface waits until that tab belongs to the active
group. A group's explicit toolbar takes precedence. Updates and group switches retain
editor portals; disposing a group disposes its toolbar portal.
The neutral core's renderGroupToolbar(groupId, container) is the fallback renderer for
initial, added/split and restored groups. Explicit group.renderToolbar retains ownership
when supplied. The group owns the returned disposable. This keeps command surface policy
in the consumer while the grid owns physical group lifetime.
