DocumentationDocumentation
API reference/Page API

Frontend adapters and existing helpers

Explore the repository's existing frontend adapters and file-interaction helpers, including their requirements.

Adapters connect state; they are not component libraries

The framework does not bundle React, Vue, Svelte, or Fabric. Supply third-party libraries through your own build, then load the matching helpers. All three state adapters use the same state.store. They do not turn an ordinary browser into Blender or automatically convert web nodes into Blender nodes.

React: read state snapshots in components

NexusWebUIReactModule
Public definitions
export interface NexusWebUIReactModule {
  createWebUIHooks(react: ReactLikeForWebUI, webui?: NexusWebUI): NexusWebUIReactHooks;
}
NexusWebUIReactHooks
Public definitions
export interface NexusWebUIReactHooks {
  useWebUIState<TItem = Record<string, WebUIJSONValue>>(
    key: string,
    query?: WebUIStateQuery | null,
    options?: WebUIStoreOptions & { shape?: 'list' },
  ): WebUIListStoreSnapshot<TItem>;
  useWebUIState<TItem = Record<string, WebUIJSONValue>>(
    key: string,
    query: WebUIStateQuery | null | undefined,
    options: WebUIStoreOptions & { shape: 'item' },
  ): WebUIItemStoreSnapshot<TItem>;
}

createWebUIHooks(React, webui?) requires useSyncExternalStore from React 18 or later. useWebUIState(key, query?, options?) returns a snapshot and defaults to list shape; specify shape: 'item' for detail state. The adapter creates the store when subscribing and releases it on unmount, avoiding render-time side effects. Changes to key/query/options content rebuild the subscription.

Component code; React and the adapter script are already loaded
javascript
const { useWebUIState } = NexusWebUIReact.createWebUIHooks(React);
function ObjectCount() {
  const state = useWebUIState("blender.objects", { fields: ["id", "name"] });
  if (state.loading) return React.createElement("p", null, "加载中");
  if (state.error) return React.createElement("p", null, state.error.message);
  return React.createElement("p", null, "当前列表:" + state.items.length);
}

Lists may be truncated. items.length is not necessarily the scene's total object count; inspect the snapshot fields for more results.

Vue: shallow reactive snapshots and cleanup

NexusWebUIVueModule
Public definitions
export interface NexusWebUIVueModule {
  createWebUIComposables(vue: VueLikeForWebUI, webui?: NexusWebUI): NexusWebUIVueComposables;
}
NexusWebUIVueComposables
Public definitions
export interface NexusWebUIVueComposables {
  useWebUIState<TItem = Record<string, WebUIJSONValue>>(
    key: string,
    query?: WebUIStateQuery | null,
    options?: WebUIStoreOptions & { shape?: 'list' },
  ): NexusWebUIVueState<WebUIListStoreSnapshot<TItem>>;
  useWebUIState<TItem = Record<string, WebUIJSONValue>>(
    key: string,
    query: WebUIStateQuery | null | undefined,
    options: WebUIStoreOptions & { shape: 'item' },
  ): NexusWebUIVueState<WebUIItemStoreSnapshot<TItem>>;
}
NexusWebUIVueState
Public definitions
export interface NexusWebUIVueState<TSnapshot extends WebUIStoreSnapshotBase = WebUIStoreSnapshot> {
  snapshot: { value: TSnapshot };
  store: WebUIStateStore<TSnapshot>;
  dispose(): void;
}

createWebUIComposables(Vue, webui?) uses Vue 3 shallowRef. useWebUIState returns snapshot, store, and dispose. Read snapshot.value in JavaScript; templates unwrap it according to Vue rules. Cleanup is automatic inside a component scope; outside one, call dispose yourself. Later mutations to a query object are not observed automatically. Recreate the store and dispose the old one when changing the query.

Svelte: subscriptions and resource release are separate

NexusWebUISvelteModule
Public definitions
export interface NexusWebUISvelteModule {
  createWebUIStores(webui?: NexusWebUI): NexusWebUISvelteStores;
}
NexusWebUISvelteStores
Public definitions
export interface NexusWebUISvelteStores {
  stateStore<TItem = Record<string, WebUIJSONValue>>(
    key: string,
    query?: WebUIStateQuery | null,
    options?: WebUIStoreOptions & { shape?: 'list' },
  ): NexusWebUISvelteStore<WebUIListStoreSnapshot<TItem>>;
  stateStore<TItem = Record<string, WebUIJSONValue>>(
    key: string,
    query: WebUIStateQuery | null | undefined,
    options: WebUIStoreOptions & { shape: 'item' },
  ): NexusWebUISvelteStore<WebUIItemStoreSnapshot<TItem>>;
}
NexusWebUISvelteStore
Public definitions
export interface NexusWebUISvelteStore<TSnapshot extends WebUIStoreSnapshotBase = WebUIStoreSnapshot> {
  subscribe(run: (snapshot: TSnapshot) => void): () => void;
  getSnapshot(): TSnapshot;
  dispose(): void;
}

stateStore from createWebUIStores(webui?) returns a Svelte-compatible subscribable without requiring a framework namespace. Subscribers immediately receive the current snapshot. Removing the last view subscription does not destroy the underlying host store; call dispose when its owning component is destroyed.

Files and complex canvas adapters

NexusResourceAdapter
Public definitions
export interface NexusResourceAdapter {
  id: string;
  /** Higher runs first. Built-ins: canvas=10, DOM default=0. User adapters default to 50. */
  priority?: number;
  canHandle(ctx: NexusResourceAdapterContext): boolean;
  import(ctx: NexusResourceAdapterContext): void | Promise<void>;
  export?(ctx: NexusResourceAdapterExportContext): Promise<{ blob: Blob; mime: string; suggestedName?: string }>;
  dispose?(): void;
}
NexusResourceAdapterContext
Public definitions
export interface NexusResourceAdapterContext {
  element: Element;
  importEvent: NexusImportEvent;
  point: NexusImportPoint;
  placement: NexusImportPlacement;
  webui: NexusWebUI;
  /** Converts a page CSS point (defaults to placement.fallbackPoint) into target-element-local coordinates. */
  localPoint(target?: Element): NexusImportPoint;
}
NexusResourceAdapterHandle
Public definitions
export interface NexusResourceAdapterHandle {
  unregister(): void;
}
NexusResourceAdapterFabricModule
Public definitions
export interface NexusResourceAdapterFabricModule {
  readonly NEXUS_RESOURCE_ADAPTER_FABRIC_VERSION: string;
  readonly version: string;
  readonly ADAPTED_LIBRARY: 'fabric';
  readonly ADAPTED_LIBRARY_VERSION_RANGE: string;
  create(options: NexusResourceAdapterFabricOptions): NexusResourceAdapter;
}
NexusResourceAdapterFabricOptions
Public definitions
export interface NexusResourceAdapterFabricOptions {
  canvas: NexusFabricCanvasLike;
  fabric?: NexusFabricNamespaceLike;
  id?: string;
  priority?: number;
}

registerAdapter returns an asynchronous registration result. Save its handle and call unregister on unmount. canHandle identifies owned content; import converts events to the component's data model; export returns a Blob and MIME type; dispose releases resources. Adding an img beside a complex canvas does not import into that component.

Item Usage and limitations
priority Higher values run first. Custom adapters default to 50; built-in canvas uses 10 and DOM uses 0. Make canHandle match only your component.
Coordinates ctx.point uses CSS page coordinates. localPoint converts to element-local coordinates; account for the component's own zoom and pan using its coordinate system.
Fabric Supply the canvas and matching fabric namespace, call create, and pass the adapter to resourceIO.registerAdapter. Supported versions are defined by ADAPTED_LIBRARY_VERSION_RANGE; do not assume all versions work.
Standard interception NexusFileInputTakeover and NexusDownloadTakeover both provide enable/disable and enable on load. Disabling stops only this interception layer; it does not revoke Python permissions.

Maintain one lifecycle

Do not maintain the same state through both an adapter and manual state.subscribe, or leave old DOM handlers after hot reload. Adapters consume snapshots; use the corresponding public APIs for actions, resources, and application logic. See State stores, Resource and file tools, Frontend integration guide.

Back to API reference · All topics