# Classic API

Public composition, context, actions and resource lifetime.

## Presets and instances

`createClassicEditor(options)` returns a product instance. `document` is content; `preset` resolves model/View; `plugins` declare product capabilities; `extensions` add ordinary features; `shell` configures UI; `media` and `host` supply services.

`instance.editor` exists only while mounted. Locale, editability and built-in preset theme updates retain Core and history; structural configuration still rebuilds Core/View. A custom Core workspace uses `editor.changeMode()` for different semantics. See the [instance reference](/en/classic/reference) for settings and methods.

### ClassicEditorPreset

`@quirekit/classic-editor` · AGPL-3.0-only

Reusable product preset resolved independently for every editor instance.

```ts
export interface ClassicEditorPreset {
    readonly id: string;
    readonly features: ClassicEditorFeatureOptions;
    readonly plugins?: readonly ClassicEditorPlugin[] | undefined;
    readonly theme?: QuireKitTheme | undefined;
    readonly shell?: ClassicEditorShellOptions | undefined;
    readonly ui?: ClassicEditorUiProfileOptions | undefined;
    readonly updatePresentation?: ((context: ClassicEditorPresetPresentationContext) => void) | undefined;
    resolveExtensions(context: ClassicEditorPresetContext): readonly QuireAnyExtension[];
}
```

**id** — Stable preset id used by diagnostics.

**features** — Feature defaults merged before instance-level overrides.

**plugins** — Default product plugins installed before instance plugins.

**theme** — Complete shared theme used when the instance does not provide one.

**shell** — Default shell configuration merged before instance overrides.

**ui** — Final composition for action-backed product surfaces.

**updatePresentation** — Refreshes preset-owned paint settings without replacing schema or session state.
Presets without this hook retain structural remounting for theme changes.
@param context - Current retained editor and presentation configuration.

**resolveExtensions** — Resolves ordinary QuireKit extensions for one mounted instance.
@param context - Features, viewport, and backend runtime inputs.
@returns Ordered QuireKit extensions installed into Core.

`preset.resolveExtensions(context)` returns ordinary extensions. Its `plugins` still need a product registry. Consuming only extensions does not install preset file services, license feedback or product keyboard plugins.

A custom preset uses `updatePresentation(context)` to refresh theme/locale-derived paint in a retained session. Update owned presentation, preserve explicit host overrides and refresh cache dependencies. Do not change Schema, install plugins or write content. Call public `updateClassicEditorPresetPresentation(context)` to reuse built-in Canvas/SVG color updates, then refresh custom extensions. Without this hook, theme changes still rebuild Core.

## Plugins

### ClassicEditorPlugin

`@quirekit/classic-editor` · AGPL-3.0-only

Product-level plugin for UI, services, shortcuts, and lifecycle.

```ts
export interface ClassicEditorPlugin {
    readonly id: string;
    readonly audience?: ClassicEditorAudience | undefined;
    readonly contributions?: readonly ClassicEditorContribution[] | undefined;
    readonly extensions?: readonly QuireAnyExtension[] | undefined;
    readonly toolbarItems?: readonly (ClassicEditorToolbarControlContribution | ClassicEditorActionToolbarControlContribution)[] | undefined;
    readonly contextMenuItems?: readonly (ClassicEditorContextMenuItemContribution | ClassicEditorActionContextMenuItemContribution)[] | undefined;
    readonly selectionPopupItems?: readonly (ClassicEditorSelectionPopupItemContribution | ClassicEditorActionSelectionPopupItemContribution | ClassicEditorSelectionPopupWidgetContribution)[] | undefined;
    readonly contextualPopupItems?: readonly ClassicEditorContextualPopupItemContribution[] | undefined;
    readonly sidebarPanels?: readonly ClassicEditorSidebarPanelContribution[] | undefined;
    readonly globalSettingsSections?: readonly ClassicEditorGlobalSettingsSectionContribution[] | undefined;
    readonly keyboardShortcuts?: readonly ClassicEditorKeyboardShortcut[] | undefined;
    readonly services?: readonly ClassicEditorImportExportService[] | undefined;
    readonly onCreate?: ((context: ClassicEditorHookContext) => void) | undefined;
    readonly onMount?: ((context: ClassicEditorHookContext) => void) | undefined;
    readonly onUpdate?: ((context: ClassicEditorHookContext) => void) | undefined;
    readonly onPaste?: ((context: ClassicEditorHookContext, event: QuireEditorPasteEvent) => boolean | void) | undefined;
    readonly onUnmount?: ((context: ClassicEditorHookContext) => void) | undefined;
    readonly onDestroy?: ((context: ClassicEditorHookContext) => void) | undefined;
}
```

**id** — Stable plugin id, unique within one product instance.

**audience** — Surface audience inherited by every declaration owned by this plugin.

**contributions** — Declarative product UI contributions.

**extensions** — Editor extensions installed into Core while this plugin is installed, after preset and instance extensions.

**toolbarItems** — Compact-toolbar contributions declared independently from other surfaces.

**contextMenuItems** — Right-click menu contributions declared independently from other surfaces.

**selectionPopupItems** — Text-selection popup contributions declared independently from other surfaces.

**contextualPopupItems** — Target-keyed contextual Popup Menu items declared independently from other surfaces.

**sidebarPanels** — Sidebar panels declared independently from other surfaces.

**globalSettingsSections** — Global-settings sections declared independently from other surfaces.

**keyboardShortcuts** — Product keyboard bindings.

**services** — Named import/export services.

**onCreate** — Called after the product instance and registry are created.

**onMount** — Called after Core, View, and product shell are mounted.

**onUpdate** — Called after product options or editor state update the shell.

**onPaste** — Intercepts a mounted editor paste before Core applies its fallback slice.

The hook must decide synchronously whether it owns the event. It may start
asynchronous product work after returning `true`.
@param context - Current mounted product authorities.
@param event - Core paste event and parsed or empty slice.
@returns Whether this product plugin consumed the paste.

**onUnmount** — Called before a reusable unmount releases Core, View, and shell resources.

**onDestroy** — Called once during final product destruction.

Plugin IDs are unique per instance. `extensions` supply content capabilities; contributions and independent toolbar/popup/sidebar declarations supply product surfaces; services register formats. Hooks distinguish reusable mounting from final disposal.

## Typed actions

### ClassicEditorActionDefinition

`@quirekit/classic-editor` · AGPL-3.0-only

One typed command definition shared by every projected product surface.

```ts
export interface ClassicEditorActionDefinition {
    readonly id: string;
    readonly label: ClassicEditorText;
    readonly icon?: string | undefined;
    readonly group?: string | undefined;
    readonly order: number;
    readonly shortcut?: ClassicEditorText | undefined;
    readonly isAvailable?: ((context: ClassicEditorActionContext) => boolean) | undefined;
    readonly canExecute?: ((context: ClassicEditorActionContext) => boolean) | undefined;
    readonly isActive?: ((context: ClassicEditorActionContext) => boolean) | undefined;
    readonly disabledReason?: ((context: ClassicEditorActionContext) => ClassicEditorActionReason | undefined) | undefined;
    readonly run: (context: ClassicEditorActionContext) => boolean | Promise<boolean>;
}
```

**id** — Stable action id used for diagnostics, not DOM string dispatch.

**label** — Localized default label available to projected controls.

**icon** — Optional compact icon id available to projected controls.

**group** — Optional semantic action group for catalog presentation.

**order** — Stable action order inside its semantic group.

**shortcut** — Optional visible shortcut hint.

**isAvailable** — Checks whether the installed product provides this action.

**canExecute** — Checks whether the action can mutate the current editor state.

**isActive** — Checks toggle state without mutating the editor.

**disabledReason** — Explains why a visible but disabled action cannot run.

**run** — Executes exactly once through editor commands, chains, or product UI authority.

`run(context)` receives editor, instance, ui, root, locale, backend and trigger. Availability, executability, active state and disabled reasons are read-only queries without commands or requests. Core owns document mutation; `context.ui` owns chrome.

### createClassicEditorRibbonAction

`@quirekit/classic-editor` · AGPL-3.0-only

Projects one direct action onto Ribbon chrome without accepting a behavior.
@param id - Stable contribution id.
@param groupId - Parent ribbon group id.
@param action - Shared direct typed action definition.
@returns Ribbon action contribution.

```ts
function createClassicEditorRibbonAction(id: string, groupId: string, action: ClassicEditorActionDefinition): ClassicEditorActionRibbonControlContribution
```

Reference an installed group ID. IDs are not another command-routing protocol. See [the runnable plugin](/en/build/product-plugin).

## Interactive panels

### ClassicEditorMountedRenderable

`@quirekit/classic-editor` · AGPL-3.0-only

Framework-neutral mounted content returned by an interactive contribution.

```ts
export interface ClassicEditorMountedRenderable {
    readonly element: Node | string | null;
    update?(context: ClassicEditorRenderContext): void;
    destroy(): void;
}
```

**element** — DOM node or text appended to the contribution host.

**update** — Refreshes retained mounted content from the latest product context.
@param context - Latest mounted product render context.

**destroy** — Releases framework roots, listeners, and other mounted resources.

Render acquires resources once; update refreshes retained DOM/Vue roots; destroy cleans up. Keep a current context reference for locale/selection rather than permanently capturing the initial mount context.

## File services

### ClassicEditorImportExportService

`@quirekit/classic-editor` · AGPL-3.0-only

Named import/export service contributed to the product registry.

```ts
export interface ClassicEditorImportExportService {
    readonly id: string;
    readonly label: ClassicEditorText;
    readonly format: ClassicEditorDocumentFormat;
    import?(context: ClassicEditorImportContext, input: ClassicEditorImportArtifact): void | Promise<void>;
    export?(context: ClassicEditorServiceContext): ClassicEditorExportArtifact | Promise<ClassicEditorExportArtifact>;
}
```

**id** — Stable service id.

**label** — Human-readable service label.

**format** — File-format capability exposed by this service.

**import** — Imports external input into the current canonical Core document.
@param context - Mounted product service context.
@param input - User-selected or programmatic file artifact.
@returns Optional asynchronous completion.

**export** — Exports the current canonical Core document.
@param context - Mounted product service context.
@returns Downloadable artifact, optionally asynchronous.

`instance.importDocument(serviceId, artifact)` selects an installed format and supplies text/bytes with filename/MIME. `exportDocument(serviceId)` returns data/fileName/mimeType; the host downloads it. File menus need explicit `document-service` contributions.

Import services receive `ClassicEditorImportContext`. Parse and validate, then perform one synchronous write through `context.commit(() => context.editor.commands.replaceDocument(document, { errorOnInvalidContent: true }))`. Commit checks latest-operation ownership, original Core, document revision, editability and signal. Async callbacks are invalid; a false command result fails. Older services that write directly must migrate; the product cannot roll back arbitrary effects bypassing commit.

Hosts can pass `{ signal }` as the third argument to cancel preparation. New imports, edits, editability updates and unmounts also invalidate preparation. Official DOCX import uses this boundary and stages images until commit. Its export captures the starting document and reports diagnostics through `onReport`; artifacts contain only data/fileName/mimeType. See [files](/en/classic/files) for complete cancellation semantics.
