/** * The ribbon surface — the full editor UI as a mountable module. * * `DocxEditor` (editor.ts) is the document engine: it owns the live `DocxSession`, * the block wiring and every command. It has deliberately no chrome. This module is * the chrome — the tabbed ribbon, the anchor rail, the table picker and the loading * overlay — wired onto exactly that command surface and nothing else. * * It exists because the same UI was hand-written three times (the standalone demo, * the GitHub Pages landing page, the compact iframe player) and drifted. Now the * surface has one owner, and the three hosts differ only in how they obtain the * WASM exports and how much of the chrome they turn on: * * ```ts * // Host that already booted the .NET runtime itself: * const ribbon = mountRibbon(document.querySelector("#app")!, { exports }); * ribbon.open(bytes, "contract.docx"); * * // Host that wants one call and a CDN (see embed.ts): * await createRibbonEditor("#app", "./contract.docx", { chrome: "auto" }); * ``` * * Chrome density is measured from the ROOT ELEMENT, not the viewport: a narrow * embed on a wide desktop page is narrow. See ribbon-chrome.ts for the layout. */ import { DocxEditor } from "./editor.js"; import type { DocxEditorExports, DocxEditorOptions } from "./editor.js"; export { DocxEditor } from "./editor.js"; export type { DocxEditorExports, DocxEditorOptions } from "./editor.js"; /** Which layout the chrome uses. "auto" measures the root and switches at `compactBreakpoint`. */ export type RibbonChromeMode = "full" | "compact" | "auto"; /** The lifecycle the surface reports on its root as `data-state`. */ export type RibbonState = "idle" | "loading" | "ready" | "error"; /** One step of the loading narrative: what is happening, and how far along it is. */ export interface RibbonLoaderStage { title: string; copy: string; /** 0–100. Drives the progress bar. */ progress: number; /** The short machine-side label under the bar. */ label: string; } /** A rotating capability card shown while the engine streams. */ export interface RibbonLoaderFeature { number: string; title: string; copy: string; } export interface RibbonLoaderOptions { /** Replace the four default stages. */ stages?: RibbonLoaderStage[]; /** Replace the rotating cards. Pass `[]` to hide the card entirely. */ features?: RibbonLoaderFeature[]; /** Micro-caps line above the title. */ eyebrow?: string; /** Right-hand label under the progress bar. */ meta?: string; /** Milliseconds between card rotations. Default 1750. */ rotateMs?: number; /** What the Retry button does. Default: reload the page. */ onRetry?: () => void; } export interface RibbonOptions extends DocxEditorOptions { /** WASM exports. Omit to mount chrome first (showing the loader) and call `setExports` later. */ exports?: DocxEditorExports; /** Layout density. Default "auto". */ chrome?: RibbonChromeMode; /** Root width, in px, below which "auto" picks compact. Default 720. */ compactBreakpoint?: number; /** Show the anchor rail (full chrome only). Default true. */ rail?: boolean; /** Show New / Open / Save. Default true. */ fileActions?: boolean; /** * Editing hint above the document: false to hide, or a string to replace it. * Rendered as HTML (the default copy uses ``), so pass author-controlled * markup only. Default true. */ hint?: boolean | string; /** Loading overlay: false to suppress it, or an object to reword it. Default true. */ loader?: boolean | RibbonLoaderOptions; /** Name shown in the title bar and used for the downloaded file. Default "untitled.docx". */ documentName?: string; /** * Element-id prefix. Controls are addressable as `data-dxr=""` always, and * additionally get `id = idPrefix + name`. Omit and the surface uses bare ids when * they are free on the page, falling back to a generated prefix when they are not — * so a second ribbon never collides with the first. */ idPrefix?: string; /** Replace the default Save behaviour (download the bytes). */ onSave?: (bytes: Uint8Array, name: string) => void; /** Called after any document opens, with the live editor. */ onOpen?: (editor: DocxEditor) => void; /** Called whenever the status line changes. */ onStatus?: (text: string) => void; /** Called after every ribbon command, with its label and measured duration. */ onCommand?: (label: string, ms: number) => void; } /** Drives the loading overlay. Safe to call when the loader is disabled — every method no-ops. */ export interface RibbonLoader { /** Re-show the overlay (e.g. before loading a second document). */ show(): void; /** Jump to a numbered stage, or set one inline. */ stage(step: number | Partial): void; /** Move the bar without changing the copy. */ progress(percent: number, label?: string): void; /** Fade the overlay out and stop the rotation. */ done(): void; /** Show the failure state with a Retry button. */ fail(error: unknown): void; } export interface RibbonEditor { /** The mounted root element (carries `data-state` and `data-chrome`). */ readonly element: HTMLElement; /** The element the document renders into. */ readonly surface: HTMLElement; /** The live editor, or null before a document is open. */ readonly editor: DocxEditor | null; /** The density actually in effect right now. */ readonly chrome: "full" | "compact"; /** The loading overlay controller. */ readonly loader: RibbonLoader; /** Supply (or replace) the WASM exports after mounting. */ setExports(exports: DocxEditorExports): void; /** Open a document, replacing any open one. Throws if exports are not set yet. */ open(bytes: Uint8Array, name?: string): DocxEditor; /** Open a fresh blank document. */ openBlank(name?: string): DocxEditor; /** Lossless DOCX bytes, or null when nothing is open. */ save(): Uint8Array | null; /** Save and hand the bytes to `onSave` (default: browser download). */ download(name?: string): void; /** Set the status line. */ setStatus(text: string): void; /** Activate a ribbon tab by name ("home" | "insert" | "layout" | "table"). */ selectTab(name: string): void; /** Force a density, or hand control back to measurement with "auto". */ setChrome(mode: RibbonChromeMode): void; /** Look up a control by its `data-dxr` name. */ control(name: string): T | null; /** Close the session, drop listeners and empty the container. */ destroy(): void; } /** * Mount the ribbon surface into `container`. * * The chrome paints synchronously — including the loading overlay — so a host can * mount before its WASM runtime exists, narrate the boot through `loader`, then call * `setExports` and `open`. */ export declare function mountRibbon(container: string | HTMLElement, options?: RibbonOptions): RibbonEditor; //# sourceMappingURL=ribbon.d.ts.map