import type { PlotMode } from '../renderer/buildView.js';
import type { Die } from '../core/dies.js';
import type { TestDef, MetadataFieldDef } from '../renderer/buildWaferMap.js';
import type { StatsSeverity } from '../stats/types.js';
export declare function logWmapVersionOnce(): void;
export declare const WMAP_TOKEN_NAMES: readonly ["z", "icon", "icon-hover", "icon-active", "bg-hover", "bg-active", "separator", "surface", "border", "menu-hover", "menu-active", "panel-bg", "text-muted", "text", "text-strong", "warn-bg", "warn-border", "warn-text", "err-bg", "err-border", "err-text", "info-bg", "info-text", "selected", "finding-indicator", "canvas-bg"];
export type WmapTokenName = (typeof WMAP_TOKEN_NAMES)[number];
export declare const CLR: {
    icon: string;
    iconHover: string;
    iconActive: string;
    bgHover: string;
    bgActive: string;
    separator: string;
    menuBg: string;
    menuBorder: string;
    menuHover: string;
    menuActive: string;
    panelBg: string;
    label: string;
    value: string;
    text: string;
    warnBg: string;
    warnBorder: string;
    warnText: string;
    errBg: string;
    errBorder: string;
    errText: string;
    infoBg: string;
    infoText: string;
    findingHighlight: string;
    findingIndicator: string;
};
/**
 * Findings-severity → colour, shared by summaryPanel.ts (severity dots/borders
 * on the findings list) and renderWaferGallery.ts (its own copy drifted from
 * this one only by name, never by value — hoisted here so the two can't
 * silently diverge again).
 */
export declare function sevColor(s: StatsSeverity): string;
export declare const ROTATIONS: Array<0 | 90 | 180 | 270>;
export declare const INLINE_TEST_LIMIT = 6;
/** Above this many rows, a scrollable list (test cascade submenu, chart test picker) gets a filter box. */
export declare const MENU_SEARCH_THRESHOLD = 8;
export declare const DEFAULT_OVERLAY_Z = 6000;
/** `z-index` value string for a base-level overlay (menus, modal backdrop). */
export declare const Z_BASE = "var(--wmap-z, 6000)";
/** One above base — tooltips, submenus, the modal box above its backdrop. */
export declare const Z_ABOVE = "calc(var(--wmap-z, 6000) + 1)";
/** Two above base — controls that must sit above a maximized modal box. */
export declare const Z_ABOVE2 = "calc(var(--wmap-z, 6000) + 2)";
/**
 * Apply a host-supplied `zIndex` to wmap's overlays by writing `--wmap-z` onto
 * `document.documentElement`. Returns a disposer that restores the previous
 * value (called on controller `destroy`). No-op when `zIndex` is undefined, so
 * the safe high default in `Z_BASE`/`Z_ABOVE` applies.
 *
 * `--wmap-z` is set on the document root (not the render container) because
 * several overlays append to `document.body`, outside the container's subtree,
 * and must still inherit the value.
 */
export declare function applyOverlayZ(zIndex: number | undefined): () => void;
/** Copy every `--wmap-*` custom property resolved on `src` onto `dest`, so an
 * element in a different document (e.g. a detached popup's `documentElement`)
 * renders with the same theme as the host page instead of silently reverting
 * to light-mode defaults. */
export declare function copyWmapThemeTokens(src: Element, dest: HTMLElement): void;
/**
 * Keeps a popup's copied `--wmap-*` tokens (`copyWmapThemeTokens`, above) in
 * sync with *later* host theme changes. A one-time copy at open time is a
 * snapshot, not a live link (CSS custom properties can't inherit across
 * documents) — if the host flips theme while the popup is still open (e.g. a
 * dark-mode toggle re-pointing its `--wmap-*` values), nothing would
 * otherwise re-copy them. Watches attribute changes on `themeSource` and
 * `<html>` — the two most common places a host actually changes theme (a
 * toggled class or inline style) — plus the OS light/dark preference. This
 * can't observe a change on some other ancestor further up that isn't
 * `themeSource` or `<html>` itself, but that already covers the realistic
 * cases; watching the whole ancestor chain generically is not something
 * anything else in this codebase does either. `onResync`, if given, fires
 * alongside each re-copy — e.g. to force a live map inside the popup to
 * redraw so its canvas re-resolves the same palette (CSS custom properties
 * update DOM-driven chrome automatically, but a canvas only re-resolves
 * `--wmap-*` at its next draw). Returns a disposer to call when the popup closes.
 */
export declare function syncWmapPopupTheme(themeSource: Element, popupDocumentElement: HTMLElement, onResync?: () => void): () => void;
export type DetachWindowOpener = (label: string) => Window | null;
/** Register a custom opener for gallery card detach windows — e.g. one backed
 * by a Tauri `WebviewWindow`, for hosts where `window.open` is blocked. The
 * opener receives the card's label and must return a `Window`-like handle
 * (with a usable `.document`) to build into, or `null` to decline (treated
 * exactly like a blocked popup — the detach silently no-ops). */
export declare function setDetachWindowOpener(opener: DetachWindowOpener | null): void;
/** Open a blank window for a detached gallery card. Uses the registered
 * `setDetachWindowOpener` opener when present, else falls back to a plain
 * `window.open` popup.
 *
 * Known cosmetic quirk: since this never navigates away from `about:blank`,
 * Chrome's window-title algorithm shows "{title} - Chrome" in the OS window/
 * tab title instead of just the title we set (an un-navigated about:blank
 * window is treated as titleless regardless of `document.title`). Navigating
 * to a real URL would fix it but means either re-running the host page's own
 * script inside the popup (real risk of double side effects) or requiring a
 * dedicated blank same-origin asset — not worth it for a cosmetic issue. */
export declare function openDetachWindow(label: string): Window | null;
export declare const MODE_LABELS: Record<PlotMode, string>;
export declare const BIN_LEGEND_MODES: Set<PlotMode>;
export declare const STACKED_MODES: Set<PlotMode>;
/**
 * Host hook for persisting a rendered PNG. When supplied, the toolbar calls this
 * instead of triggering a browser `<a download>`, letting embedded hosts (Tauri,
 * Electron, WebView2) route the blob through a native save dialog or upload.
 * Receives the PNG `blob` and a `suggestedName` (already includes `.png`).
 */
export type SaveImageHandler = (blob: Blob, suggestedName: string) => void | Promise<void>;
/**
 * Persist a rendered PNG blob. Routes through the host `onSaveImage` hook when
 * provided; otherwise falls back to a browser `<a download>` click. Single
 * source of truth for the save action across `renderWaferMap` and
 * `renderWaferGallery` — neither should reimplement the `<a download>` dance.
 *
 * @param blob          the PNG blob (e.g. from `canvas.toBlob`)
 * @param filename      filename without extension (e.g. `'wafermap'`)
 * @param onSaveImage   optional host hook; when present, bypasses `<a download>`
 */
export declare function saveImageBlob(blob: Blob, filename: string, onSaveImage?: SaveImageHandler): void;
/**
 * Host hook for saving a text file (CSV, etc). Mirrors `SaveImageHandler` —
 * when provided, `saveTextFile` calls this instead of triggering a browser
 * `<a download>`, letting embedded hosts (Tauri, Electron, WebView2) route
 * the text through a native save dialog. Receives the raw `text`, a
 * `suggestedName` (already includes its extension), and the `mimeType`.
 */
export type SaveTextHandler = (text: string, suggestedName: string, mimeType: string) => void | Promise<void>;
/**
 * Persist a text file (e.g. a CSV export). Routes through the host
 * `onSaveText` hook when provided; otherwise falls back to a browser
 * `<a download>` click — the same `<a download>` dance `saveImageBlob` uses
 * for PNG saves, which is silently a no-op in Tauri/Electron/WebView2 (see
 * `saveImageBlob`'s own doc comment), hence the hook.
 *
 * @param text        the file contents
 * @param filename    filename including extension (e.g. `'test-values.csv'`)
 * @param mimeType    e.g. `'text/csv'`
 * @param onSaveText  optional host hook; when present, bypasses `<a download>`
 */
export declare function saveTextFile(text: string, filename: string, mimeType: string, onSaveText?: SaveTextHandler): void;
/**
 * Run `fn` on the next animation frame, falling back to a macrotask in
 * environments without `requestAnimationFrame` (e.g. JSDOM under tests).
 * Used to defer focus moves until the element is laid out, and to schedule
 * re-renders after a resize.
 *
 * Accepts an explicit `ownerWindow` — a bare `requestAnimationFrame` reference
 * resolves to whichever window this MODULE was first evaluated in (the host
 * page's), not necessarily the window whose layout the caller actually cares
 * about. For a gallery card detached into its own popup window, scheduling
 * against the opener's rAF loop means the callback only fires when the OPENER
 * repaints (e.g. on mouse movement there) — not when the popup itself does,
 * which reads as "the map doesn't resize until I move focus back to the main
 * window." Passing the popup's own `window` fixes this.
 */
export declare function nextFrame(fn: () => void, ownerWindow?: Window): void;
export declare function overlayRootFor(anchor: Element): Element;
/** The shared tooltip element for `doc` (default: the host page's own
 * document), lazily created and appended to `doc.body`. */
export declare function getTooltip(doc?: Document): HTMLDivElement;
/** Hide `doc`'s shared tooltip. Deliberately does NOT re-home it to `doc.body`
 * — it stays wherever `reparentTooltip()` last placed it (e.g. inside an open
 * floating window's box). A non-modal floating window can stay open for many
 * ordinary hover/unhover cycles; snapping the tooltip back to `<body>` on
 * every hide (as this used to do) meant the very first unhover after opening
 * a floating window silently evicted the tooltip from the window's stacking
 * context, and it was never reparented back in — every subsequent hover in
 * that window then rendered the tooltip at `<body>`'s z-index, BEHIND the
 * window. Callers that actually close an overlay (see `openOverlay`'s
 * `close()`) are responsible for reparenting the tooltip back to `<body>`
 * themselves once the box that owned it is really going away. */
export declare function hideTooltip(doc?: Document): void;
/**
 * Move `parent`'s document's shared tooltip into `parent` (e.g. a maximized
 * modal box that creates its own stacking/overflow context). Pass nothing to
 * re-home the host page's tooltip to `document.body`.
 */
export declare function reparentTooltip(parent?: HTMLElement): void;
/**
 * Position the shared tooltip near (clientX, clientY), re-homing it under
 * `anchor`'s nearest overlay root first (see overlayRootFor) if it isn't there
 * already. Re-resolving on every call is deliberate and cheap (a short
 * ancestor walk) — anchor's overlay root can change over the tooltip's
 * lifetime (e.g. a host opens its own <dialog> around an already-rendered
 * map), and the `parentElement !==` guard means the DOM is only actually
 * touched when the root has changed, not on every mousemove.
 */
export declare function positionTooltip(tooltip: HTMLDivElement, anchor: Element, clientX: number, clientY: number): void;
export interface ToolbarHelpers {
    makeBtn(iconKey: string, label: string, onClick: () => void): HTMLButtonElement;
    setActive(btn: HTMLButtonElement, active: boolean): void;
    makeSep(): HTMLDivElement;
    makeMenuRow(label: string, active: boolean, indent: boolean, onClick: (e: MouseEvent) => void): HTMLDivElement;
    makeMenuSection(label: string): HTMLDivElement;
    makeDropdown<T extends string>(iconKey: string, title: string, getItems: () => Array<{
        value: T;
        label: string;
    }>, getCurrent: () => T, onPick: (v: T) => void): HTMLButtonElement;
    /**
     * Create a button that opens a persistent checkbox-style dropdown menu.
     * `getRows` is called fresh on each open/replace so active state is always current.
     * `onSync` is called after each row click to update the button's active highlight.
     */
    makeCheckMenuBtn(iconKey: string, label: string, getRows: () => CheckMenuRow[], onSync: (btn: HTMLButtonElement) => void): HTMLButtonElement;
    closeOpenMenu(e: MouseEvent): void;
    /** Read/write the shared open-menu slot — used by custom menus that can't go through makeDropdown. */
    getOpenMenu(): HTMLDivElement | null;
    setOpenMenu(menu: HTMLDivElement | null): void;
}
export type ModeEntry = {
    plotMode: PlotMode;
    activeTest?: number;
    activeMetadataKey?: string;
    label: string;
    logScale?: boolean;
};
/**
 * Which plot modes the data actually supports — the single derivation shared by
 * `renderWaferMap` and `renderWaferGallery`.
 *
 * This is a correctness surface, not a convenience: the library's rule is that UI
 * controls must derive validity from the data the library built, never from a
 * caller-supplied flag. Two copies of that derivation can silently disagree about
 * which modes are offered (and adding a new plot mode means remembering both),
 * so it lives here with the rest of the shared toolbar primitives.
 *
 * `includeStacked` is the one genuine difference between the two callers, and is
 * a deliberate parameter rather than an inferred value: stacked modes are valid
 * for `renderWaferMap` only when the result was built from a `lotStack`
 * (`view.isLotStack`), whereas `renderWaferGallery` aggregates across its own
 * items and can always offer them.
 */
export declare function buildDataModeEntries(dies: Die[], testDefs: TestDef[] | undefined, options: {
    includeStacked: boolean;
}): {
    testEntries: ModeEntry[];
    binEntries: ModeEntry[];
    stackedEntries: ModeEntry[];
};
/**
 * True when at least one die actually carries a value for this metadata key.
 * Presence in `metadataFields` is an opt-in declaration; this is the "and there
 * is data for it" half of the same check, shared so the single map and the
 * gallery can't disagree on which fields to offer.
 */
export declare function metadataKeyHasData(dies: Die[], key: string): boolean;
/** A configured metadata field → its mode-menu entry, with the shared label fallback. */
export declare function metadataModeEntry(field: MetadataFieldDef): ModeEntry;
/**
 * A text input for filtering a list of rows by their label text, meant to sit
 * at the top of a scrollable menu/list once it gets long enough that scanning
 * beats scrolling. Shared by the plot-mode test-value cascade submenu here and
 * the chart test picker (`chartShell.ts`'s `makeSearchableTestSelect`) so both
 * get the same filter-as-you-type box instead of building it twice.
 *
 * `onFilter` receives the lowercased query on every keystroke; the caller
 * owns showing/hiding its own rows. Autofocuses on mount. Click/keydown are
 * stopped from bubbling so typing (including Space/arrow keys) lands in the
 * input rather than triggering the host menu's own keyboard navigation.
 */
export declare function makeMenuSearchBox(onFilter: (query: string) => void, placeholder?: string): HTMLInputElement;
/**
 * Build the plot-mode dropdown menu element.
 * Shared between renderWaferMap and renderWaferGallery.
 * The caller provides data-derived entry arrays and pick/active callbacks.
 */
export declare function buildModeMenuEl(anchorRect: DOMRect, testEntries: ModeEntry[], binEntries: ModeEntry[], stackedEntries: ModeEntry[], isCurrentEntry: (e: ModeEntry) => boolean, pickEntry: (entry: ModeEntry, menu: HTMLElement) => void, helpers: Pick<ToolbarHelpers, 'makeMenuRow' | 'makeMenuSection'>, currentMode: PlotMode, ownerWindow?: Window, metadataEntries?: ModeEntry[]): HTMLDivElement;
/**
 * Mark a button as a menu trigger and reflect its open/closed state. Call with
 * `expanded` on open/close so assistive tech announces the popup state. Public
 * so the adapters can apply it to mode-menu triggers they mount themselves.
 */
export declare function markMenuTrigger(btn: HTMLElement, expanded: boolean): void;
/**
 * Public re-export of the internal roving-focus keyboard wiring, for menus the
 * adapters mount directly (the plot-mode menu). See `wireMenuKeyboard`.
 */
export declare function wireMenuA11y(menu: HTMLElement, trigger: HTMLElement | null, close: () => void): void;
export interface ExpandToggleHandle {
    isOpen(): boolean;
    /** Force-close without toggling — used for e.g. a data refresh that should collapse an open panel. */
    close(): void;
    destroy(): void;
}
/**
 * Shared "click/Enter/Space toggles an expand/collapse state, Escape or an
 * outside click closes it" wiring — the small interaction pattern behind both
 * the metadata badge's own expand (metadataBadge.ts) and the gallery card
 * header's metadata reveal (renderWaferGallery.ts). `trigger` gets
 * `role="button"`/`tabindex` and the event listeners; `onChange(open)` is
 * called whenever the state actually changes (never redundantly) — the
 * caller owns all the resulting DOM (aria-expanded text, panel visibility,
 * content), this only owns the open/closed boolean and its triggers.
 */
export declare function wireExpandToggle(trigger: HTMLElement, onChange: (open: boolean) => void): ExpandToggleHandle;
export type CheckMenuRow = {
    section: string;
} | {
    label: string;
    active: boolean;
    enabled?: boolean;
    onClick: (e: MouseEvent) => void;
};
/**
 * Build a checkbox-style dropdown menu (for overlays/orientation groups).
 * Each row with an `onClick` is a toggleable item; rows with `section` are headers.
 * Stays open after each click so the user can toggle multiple items.
 */
export declare function buildCheckMenuEl(anchorRect: DOMRect, rows: CheckMenuRow[], helpers: Pick<ToolbarHelpers, 'makeMenuRow' | 'makeMenuSection'>, ownerWindow?: Window): HTMLDivElement;
export declare function createToolbarHelpers(tooltip: HTMLDivElement): ToolbarHelpers;
export type OverlayMode = 'modal' | 'window';
export interface OverlayOptions {
    /** Optional title shown in the header left. */
    title?: string;
    mode: OverlayMode;
    /**
     * Called when the maximized state changes — use to reparent tooltips etc. Uses
     * a CSS maximize (the box grows to fill its backdrop/the viewport), not the
     * real Fullscreen API, for macOS WKWebView compatibility.
     */
    onMaximizeChange?: (isMaximized: boolean, box: HTMLElement) => void;
    /** Called when the overlay is closed. */
    onClose: () => void;
    /**
     * The document to build this overlay into — defaults to the bare global
     * `document`. Pass the triggering element's `ownerDocument` when the
     * caller's own container might live in a different document (e.g.
     * `renderWaferMap`'s own expand modal, whose canvas could be inside a
     * gallery card detached into its own popup window) — otherwise the overlay
     * silently builds into the WRONG document, visibly emptying the popup and
     * popping the box up on the host page instead.
     */
    ownerDocument?: Document;
    /**
     * An element from the triggering render's own live DOM subtree — used to
     * resolve the overlay's root via `overlayRootFor` instead of always
     * `doc.body`. Needed so this overlay itself (not just the tooltip/menus)
     * lands inside a host's own native `<dialog>` (shown via `.showModal()`,
     * which promotes it into the browser's top layer — see `overlayRootFor`'s
     * own doc comment) when the map is embedded inside one; without it, the
     * modal/window box would build straight onto `doc.body`, which sits BEHIND
     * that top-layer dialog regardless of z-index. Any still-attached element
     * from the render works equally well — the exact choice doesn't matter,
     * only that it lives in the correct subtree at call time. Omit when no
     * such element exists (e.g. a click handler with no natural anchor); the
     * overlay then falls back to `doc.body`, matching prior behaviour exactly.
     */
    anchor?: Element;
}
export interface OverlayHandle {
    /** null in 'window' mode — there is no backdrop to block the page. */
    backdrop: HTMLDivElement | null;
    box: HTMLDivElement;
    /** Flex container inside the box for the canvas/content area. */
    contentWrap: HTMLDivElement;
    /** Close the overlay — removes DOM, restores scroll, removes all listeners, fires onClose. */
    close: () => void;
    /** Raise this window above other open windows. No-op in 'modal' mode. */
    bringToFront: () => void;
}
/** Create and open a resizable, maximizable, exclusive expand modal — dims and
 * blocks the rest of the page. See `openFloatingWindow` for the non-modal form. */
export declare function openModal(opts: Omit<OverlayOptions, 'mode'>): OverlayHandle;
/** Create and open a resizable, maximizable, non-modal floating window — the
 * rest of the page stays fully interactive, and multiple windows may be open at
 * once. See `openModal` for the exclusive/blocking form. */
export declare function openFloatingWindow(opts: Omit<OverlayOptions, 'mode'>): OverlayHandle;
export interface ReparentModalOptions {
    ownerDocument?: Document;
    title?: string;
    /** Called after the modal has closed and every element has been restored to its original position (or appended back, if its original spot is no longer available — see the stale-reference note above). Runs once, even if nothing was actually moved (the re-entrancy guard tripped). */
    onClosed?: () => void;
}
/**
 * Reparent one or more elements (moved together, in the given order) into a
 * new modal's `contentWrap`, and restore each to its original position when
 * the modal closes. Returns `null` — opening nothing — if any element is
 * already inside a still-open modal from an earlier call; the caller's own
 * trigger should normally be hidden/disabled for that duration anyway (see
 * both call sites), this is defense in depth, not the primary guard.
 */
export declare function openReparentedModal(elements: HTMLElement[], opts?: ReparentModalOptions): OverlayHandle | null;
/**
 * `sync()` hides the button entirely in `'metadata'` mode — that mode never
 * consults `colorFns`/the active colour scheme at all (always the dedicated
 * ordered palette + `MetadataFieldDef.values[].color` overrides, see
 * `pushDieRectangles`), so every scheme choice would be a real control with
 * zero visible effect, not just a restricted one — worse than the existing
 * hardBin/softBin restriction (which still changes the die colours, just from
 * a smaller scheme set).
 */
export declare function makePaletteBtn(helpers: ToolbarHelpers, getPlotMode: () => PlotMode, getColorScheme: () => string, hasCustomColors: () => boolean, setColorScheme: (v: string) => void): {
    btn: HTMLButtonElement;
    sync: () => void;
};
/** Requested pass/fail display, defaulting to 'off' when unset. */
export declare function requestedPassFailDisplay(opts: {
    passFailDisplay?: 'off' | 'spec' | 'test';
}): 'off' | 'spec' | 'test';
/**
 * The two mutually exclusive pass/fail display entries for the overlays menu,
 * shared by renderWaferMap and renderWaferGallery. Each entry appears only when
 * valid for the active test (library-derived): "Spec pass/fail" needs limits,
 * "Test pass/fail" needs at least one recorded verdict. A functional active
 * test returns no entries at all — its value mode IS test pass/fail, there is
 * no alternative display to choose.
 */
export declare function passFailMenuRows(state: {
    functionalActive: boolean;
    hasLimits: boolean;
    hasRecorded: boolean;
    display: 'off' | 'spec' | 'test';
}, setDisplay: (d: 'off' | 'spec' | 'test') => void): CheckMenuRow[];
export declare function makeLogScaleBtn(helpers: ToolbarHelpers, getOpts: () => {
    plotMode?: PlotMode;
    logScale?: boolean;
    passFailDisplay?: 'off' | 'spec' | 'test';
    functionalActive?: boolean;
}, setOpts: (patch: {
    logScale: boolean;
}) => void): {
    btn: HTMLButtonElement;
    sync: () => void;
};
export type LegendPosition = 'default' | 'compact' | 'left' | 'top' | 'bottom' | 'floating';
export declare function makeLegendStyleBtn(helpers: ToolbarHelpers, getOpts: () => {
    plotMode?: PlotMode;
    legendPosition?: LegendPosition;
}, setLegendPosition: (v: LegendPosition) => void): {
    btn: HTMLButtonElement;
    sync: () => void;
};
export declare function makeOverlaysBtn(helpers: ToolbarHelpers, getRows: () => CheckMenuRow[], isAnyOn: () => boolean): HTMLButtonElement;
export declare function makeOrientationBtn(helpers: ToolbarHelpers, getOpts: () => {
    rotation?: number;
    flipX?: boolean;
    flipY?: boolean;
}, setOpts: (patch: {
    rotation?: 0 | 90 | 180 | 270;
    flipX?: boolean;
    flipY?: boolean;
}) => void): HTMLButtonElement;
type GuideApi = {
    buildWaferMap: unknown;
    renderWaferMap: unknown;
    renderWaferGallery: unknown;
    analyzeWaferMap: unknown;
};
/**
 * Host-supplied content inserted into wmap's own embedded user-guide window,
 * so a host app's own documentation and wmap's reference live behind one
 * help button instead of two separate ones.
 */
export interface UserGuideExtension {
    /**
     * Host-provided HTML, inserted before wmap's own guide content. Static
     * content only — must not contain `<script>` tags. wmap re-executes
     * exactly one inline script (its own live-demo bootstrap, always the
     * last element in `html`) by finding the content div's first
     * `<script>` in document order; a `<script>` in this HTML would be
     * found instead, silently breaking wmap's own live demos.
     */
    html: string;
    /**
     * Overrides the window's title text (default `'Wafer Map — User Guide'`).
     * Use this when the host's own content should frame the whole document —
     * wmap's own `<h1>` stays as-is further down the page, so the result
     * reads as one combined guide with the host's section first, not a title
     * rewrite.
     */
    title?: string;
}
/**
 * Open the embedded user-guide window and populate its live demos. Closes any
 * previously open guide window first (at most one may be open at a time).
 * `api` must contain the four library functions the guide demos call at runtime.
 * `html` is USER_GUIDE_HTML — passed in so toolbar.ts has no dependency on userGuideHtml.ts.
 * `extension`, when provided, prepends host content and/or overrides the window title — see `UserGuideExtension`.
 *
 * Opens a real, separate window when available (draggable outside the host
 * window's own bounds), falling back to the in-page floating window when
 * `window.open` is blocked/unavailable — silently returns `null` in some
 * embedded WebViews (Tauri, Electron, WebView2), same gap `openDetachWindow`
 * exists for. Unlike gallery card detach, this doesn't go through
 * `setDetachWindowOpener` — that opener's contract is scoped to per-wafer
 * detach windows a host may have built specifically for that shape of
 * content, and reusing it silently for the guide would broaden it without
 * documentation.
 */
export declare function openUserGuideWindow(api: GuideApi, html: string, extension?: UserGuideExtension, anchor?: Element): void;
export {};
//# sourceMappingURL=toolbar.d.ts.map