import { D as DesignCanvasProps, c as createSceneCommandStack, E as ExportTriggerOptions, a as DesignCanvasMode } from '../command-stack-TNPWJCzW.js';
export { A as ApplySceneResult, b as EditorSceneState, S as SCENE_COMMAND_HISTORY_LIMIT, d as SceneCommand, e as SceneCommandStack, f as SceneCommandStackWithReapply, g as SnapEngine, h as SnapResult, i as SnapTarget, j as SnapTargetKind, k as SnapTargets, Z as ZoomPanMath } from '../command-stack-TNPWJCzW.js';
import { InsertPageGeometry, InsertTemplate, MultiSetAttrsEntry } from './engine.js';
export { AddElementInput, AddPageInput, BindSlotInput, DEFAULT_INSERT_TEMPLATES, DUPLICATE_OFFSET, DeleteElementInput, DeletePageInput, DuplicatePageInput, ExportViewSnapshot, GroupElementsInput, MAX_INSERT_DIMENSION, MarqueeSelectOptions, NudgeDelta, ReorderElementInput, ReorderPageInput, ResolvedExportParams, SetAttrsInput, SetDocumentTitleInput, SetPageGuidesInput, SetPagePropsInput, UngroupElementInput, ZoomPanConfig, addElementCommand, addPageCommand, bindSlotCommand, buildInsertImageOp, centeredPosition, collectGridTargets, createSnapEngine, createZoomPanMath, deleteElementCommand, deletePageCommand, documentCropToStageCoords, duplicatePageCommand, fittedSize, groupElementsCommand, hitTestPoint, identifyTaintedSrc, isCrossOriginSrc, isExportHiddenNodeName, marqueeSelect, mintElementId, multiSetAttrsCommand, nudgeDelta, reorderElementCommand, reorderPageCommand, resolveExportParams, setAttrsCommand, setDocumentTitleCommand, setPageGuidesCommand, setPagePropsCommand, ungroupElementCommand } from './engine.js';
import { c as SceneDocument, S as ScenePage, a as SceneElement, P as PageBleed, b as PageGuides } from '../model-DnfO_PdJ.js';
import { f as ExportPreset } from '../export-presets-mgVulRaV.js';
export { d as ExportCropRect, h as bleedAwareExportBounds, s as scaleForPreset } from '../export-presets-mgVulRaV.js';
export { D as DesignCanvas, a as DesignCanvasChromeLazy, b as DesignCanvasEditor, c as DesignCanvasFullProps, d as DesignCanvasLazy } from '../lazy-DrkVyDpe.js';
import * as react from 'react';
import { ButtonHTMLAttributes } from 'react';
import { S as SceneOperation, h as SceneAttrsPatch } from '../operations-ByJ6yXOW.js';
import { CanvasRenderPalette } from '../theme/index.js';
import Konva from 'konva';

/**
 * Client-side export for design-canvas pages: raster (PNG/JPEG via Konva
 * stage.toDataURL) and JSON (document serialisation).
 *
 * The heavy lifting — crop math, pixel ratio resolution, CORS taint detection
 * — lives in export-math.ts where it can be unit-tested without a canvas
 * context. This file is the thin Konva-wiring layer: hide overlays, call
 * toDataURL, restore, handle the SecurityError.
 *
 * Konva is an OPTIONAL peer. Import this file only from browser-context code
 * that has konva wired in. The types are written against a minimal structural
 * interface so the file compiles even when konva's types are absent.
 */

interface KonvaNodeLike {
    name(): string;
    visible(): boolean;
    visible(v: boolean): void;
    getAttr(key: string): unknown;
}
interface KonvaLayerLike {
    getChildren(): KonvaNodeLike[];
}
interface KonvaStageLike {
    scaleX(): number;
    scaleY(): number;
    x(): number;
    y(): number;
    getLayers(): KonvaLayerLike[];
    toDataURL(params: {
        mimeType: string;
        quality?: number;
        pixelRatio: number;
        x: number;
        y: number;
        width: number;
        height: number;
    }): string;
}
/** Define options to export a page as a data URL with format, pixel ratio, bleed, and preset settings */
interface ExportPageDataUrlOptions {
    format: 'png' | 'jpeg';
    pixelRatio?: number;
    includeBleed?: boolean;
    preset?: ExportPreset;
}
/**
 * Render a single page to a data URL.
 *
 * The function temporarily hides every node whose name starts with 'overlay:'
 * plus any Transformer node, computes the crop rect and pixel ratio from the
 * page model and options, calls stage.toDataURL, then restores all prior view
 * state exactly — zoom, pan, and node visibility.
 *
 * Rejects with a descriptive error when a CORS-tainted image source causes
 * the SecurityError, naming the offending src so the caller can surface it.
 *
 * The `stage` argument must be the Konva stage with the page content already
 * rendered. The caller is responsible for ensuring all async image loads have
 * settled before calling this function.
 */
declare function exportPageDataUrl(stage: KonvaStageLike, page: ScenePage, opts: ExportPageDataUrlOptions): Promise<string>;
/**
 * Serialize a scene document to pretty-printed JSON with schemaVersion
 * asserted. Throws when the document's schemaVersion does not match
 * SCENE_SCHEMA_VERSION — the caller must not smuggle stale documents through.
 */
declare function exportDocumentJson(document: SceneDocument): string;
/**
 * Trigger a browser download for a data URL. Safe to import in SSR — the
 * function is a no-op when `document` is not defined (e.g. server-side render
 * or test environment without a DOM). The integrator must not rely on the
 * download executing in those contexts.
 */
declare function downloadDataUrl(dataUrl: string, filename: string): void;

/** An already-generated image the panel can offer for one-click insertion. */
interface InsertGeneration {
    id: string;
    /** The image url to insert. Must satisfy the scene media boundary
     *  (http(s) or rooted `/api/`); rejected otherwise at insert time. */
    url: string;
    /** Optional prompt/label shown as the tile's title. */
    label?: string;
}
interface CanvasInsertPanelProps {
    canWrite: boolean;
    /** The active page new elements are added to. */
    page: InsertPageGeometry;
    /** Submit operations through the host's apply pipeline. */
    onInsert(operations: SceneOperation[]): Promise<unknown>;
    /** Store an uploaded file and return its src (http(s) or rooted `/api/`). */
    onUploadImage?(file: File): Promise<string>;
    /** Optional provider for the Generations tab; omit to hide it. */
    loadGenerations?(): Promise<InsertGeneration[]>;
    /** Drop-in templates; defaults to the built-in starter set. */
    templates?: readonly InsertTemplate[];
    /** Accepted upload mime types. Default: PNG/JPEG/GIF/WebP. */
    accept?: string;
    className?: string;
}
declare function CanvasInsertPanel({ canWrite, page, onInsert, onUploadImage, loadGenerations, templates, accept, className, }: CanvasInsertPanelProps): react.JSX.Element;

interface WorkspaceViewProps {
    /** The command stack this view commits gestures through. Must be the same
     *  instance the chrome (DesignCanvasEditor) owns so undo/redo and layers-
     *  panel selection are coherent. */
    stack: ReturnType<typeof createSceneCommandStack>;
    /** Active page resolved before render — WorkspaceView has no conditional
     *  hook guards; the caller ensures this is never null. */
    activePage: ScenePage;
    canWrite: boolean;
    onApplyOperations: DesignCanvasProps['onApplyOperations'];
    onSelectionChange?: DesignCanvasProps['onSelectionChange'];
    className?: string;
    /** Ref the chrome fills with a fit-page callback. The chrome calls it on F /
     *  Fit button; when injected via DesignCanvasEditor the ref is shared. */
    onFitRef?: React.MutableRefObject<(() => void) | null>;
    /** Host export hook. When set, the workspace fills `onExportRef` with a
     *  callback that renders the stage to a data URL and forwards the result. */
    onExport?: DesignCanvasProps['onExport'];
    /** Ref the workspace fills with an export callback `(opts) => void`. The
     *  chrome's Export control calls it; the workspace owns the Konva stage so it
     *  produces the data URL here. Filled only when `onExport` is also set. */
    onExportRef?: React.MutableRefObject<((opts: ExportTriggerOptions) => void) | null>;
    /** Fit the active page to the viewport once, on the first non-zero measurement. Default true. */
    fitOnMount?: boolean;
    /** Called once after the first real (non-zero) measurement, after the initial fit is applied (or skipped). */
    onReady?(): void;
    /** Konva render palette. Omitted → light defaults (byte-identical history). */
    render?: CanvasRenderPalette;
    /** Show the branded in-canvas empty state (three doors) while the active page
     *  has no elements and the user can write. Default true. Set false to keep a
     *  bare blank stage (e.g. when restoring a saved-but-intentionally-empty page). */
    showEmptyState?: boolean;
    /** Focus/open the agent from the empty state's "Ask the agent" door. When
     *  omitted that door is hidden — there is no agent surface to send them to. */
    onAskAgent?(): void;
}
declare function WorkspaceView({ canWrite, onApplyOperations, onSelectionChange, className, stack, activePage, onFitRef, onExport, onExportRef, fitOnMount, onReady, render, showEmptyState, onAskAgent, }: WorkspaceViewProps): react.JSX.Element;
/**
 * Self-contained Konva workspace that creates its own command stack. Mount
 * this when you want the canvas without the toolbar/rulers/pages-strip chrome.
 *
 * Products that want the full editor (chrome + workspace sharing one stack)
 * should mount `DesignCanvasEditor` instead.
 */
declare function Workspace(props: DesignCanvasProps): react.JSX.Element | null;

/**
 * In-canvas empty state — the first move on a blank design. Shown by
 * WorkspaceView as a centered overlay while the active page has no user
 * content, so a fresh canvas reads as "ready to start" rather than "broken or
 * empty". Three doors cover the two ways people begin and the agent path:
 *   - Start with a template — drop a starter element via the same command stack.
 *   - Add an element — insert a text block by hand.
 *   - Ask the agent — surfaced only when the host wires `onAskAgent` (an agent
 *     panel exists); otherwise the door is omitted rather than rendered dead.
 *
 * Token-styled only (CSS-var tokens + Tailwind semantic names) and stamped with
 * the Tangle mark so the blank state is on-brand. Pointer-events stay scoped to
 * the card: clicking the surrounding canvas still starts a marquee.
 */
interface CanvasEmptyStateProps {
    /** Drop a starter template element through the command stack. */
    onStartTemplate(): void;
    /** Insert a single editable element by hand. */
    onAddElement(): void;
    /** Focus the agent panel / open the agent. Omitted → the door is hidden. */
    onAskAgent?(): void;
    /** Heading copy. Overridable; defaults to the cold-open prompt. */
    title?: string;
    /** Supporting line under the heading. Overridable. */
    subtitle?: string;
    className?: string;
}
/**
 * The three-door empty state. Each door is a real action wired to the editor's
 * command stack (or the agent), never a placeholder.
 */
declare function CanvasEmptyState({ onStartTemplate, onAddElement, onAskAgent, title, subtitle, className, }: CanvasEmptyStateProps): react.JSX.Element;

interface SelectionLayerProps {
    /** Konva stage reference to look up selected nodes by name. */
    stageRef: React.RefObject<Konva.Stage | null>;
    /** Selected element ids from editor state. */
    selectedIds: string[];
    /** The model elements corresponding to selectedIds (pre-gesture snapshot). */
    selectedElements: SceneElement[];
    /** Whether the canvas is writable. False → transformer renders but is not interactive. */
    canWrite: boolean;
    /** Emitted when a transform gesture completes with final attrs per element. */
    onTransformEnd(entries: MultiSetAttrsEntry[]): void;
    /** Active page id — every entry in onTransformEnd carries this. */
    pageId: string;
    /** Theme render palette. Omitted → light defaults (byte-identical history). */
    render?: CanvasRenderPalette;
}
declare function SelectionLayer({ stageRef, selectedIds, selectedElements, canWrite, onTransformEnd, pageId, render, }: SelectionLayerProps): react.JSX.Element;

interface PagesStripProps {
    pages: ScenePage[];
    activePageId: string;
    canWrite: boolean;
    /**
     * The host provides this to generate thumbnail data-URLs. The strip calls it
     * on mount and debounces re-calls on document changes. Returns null when the
     * thumbnail is not yet available (the strip renders a placeholder instead).
     */
    renderThumbnail(page: ScenePage): Promise<string | null>;
    onSelectPage(pageId: string): void;
    onAddPage(): void;
    onDuplicatePage(pageId: string): void;
    onDeletePage(pageId: string): void;
    onReorderPage(pageId: string, toIndex: number): void;
    /** Show page-management affordances (add / duplicate / delete). Default true.
     *  The review surface passes false: pages are navigated, not authored. */
    canManagePages?: boolean;
    /** Heading shown above the strip so it reads as page management. Overridable;
     *  defaults to "Pages". Set to '' to hide the visible label (the container
     *  keeps its accessible name regardless). */
    label?: string;
}
declare function PagesStrip({ pages, activePageId, canWrite, renderThumbnail, onSelectPage, onAddPage, onDuplicatePage, onDeletePage, onReorderPage, canManagePages, label, }: PagesStripProps): react.JSX.Element;

interface LayersPanelProps {
    page: ScenePage;
    selectedElementIds: string[];
    canWrite: boolean;
    /** Emit a set_attrs command for the given element. */
    onSetAttrs(elementId: string, attrs: Partial<Pick<SceneElement, 'name' | 'visible' | 'locked'>>): void;
    /** Emit a reorder_element command. */
    onReorder(elementId: string, toIndex: number): void;
    onSelect(elementId: string, additive: boolean): void;
}
declare function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder, onSelect }: LayersPanelProps): react.JSX.Element;

interface ToolbarProps {
    page: ScenePage;
    selectedElements: SceneElement[];
    canWrite: boolean;
    /** Capability mode. `'review'` (the lean reviewer) hides the view toggles,
     *  page-props controls, and the destructive/structural selection controls
     *  (z-order, group/ungroup, lock, slot, delete), keeping only safe direct
     *  edits: text content, image fit/replace, opacity/rotation, undo/redo.
     *  Defaults to `'edit'` (the full authoring toolbar). */
    mode?: DesignCanvasMode;
    canUndo: boolean;
    canRedo: boolean;
    gridEnabled: boolean;
    snapEnabled: boolean;
    showRulers: boolean;
    showBleed: boolean;
    onUndo(): void;
    onRedo(): void;
    onToggleGrid(): void;
    onToggleSnap(): void;
    onToggleRulers(): void;
    onToggleBleed(): void;
    /** Emit attrs patch for each selected element. */
    onSetAttrs(elementId: string, attrs: SceneAttrsPatch): void;
    onSetPageProps(props: {
        name?: string;
        width?: number;
        height?: number;
        background?: string;
        bleed?: PageBleed | null;
    }): void;
    onSetPageGuides(guides: {
        vertical: number[];
        horizontal: number[];
    }): void;
    onReorder(elementId: string, toIndex: number, ownerLength: number, direction: 'front' | 'back' | 'forward' | 'backward'): void;
    onGroup(elementIds: string[]): void;
    onUngroup(groupId: string): void;
    onDelete(elementIds: string[]): void;
    onBindSlot(elementId: string, slot: string | null): void;
    /** Field label for the page-size control. Defaults to the clearer "Page size";
     *  overridable for consumers that want the older "Preset" wording. */
    pageSizeLabel?: string;
    /** Title for the "turn on print bleed" action. Defaults to "Show print bleed"
     *  (the outcome) rather than the print-shop term "bleed". */
    enableBleedLabel?: string;
}
declare function Toolbar({ page, selectedElements, canWrite, mode, canUndo, canRedo, gridEnabled, snapEnabled, showRulers, showBleed, onUndo, onRedo, onToggleGrid, onToggleSnap, onToggleRulers, onToggleBleed, onSetAttrs, onSetPageProps, onSetPageGuides, onReorder, onGroup, onUngroup, onDelete, onBindSlot, pageSizeLabel, enableBleedLabel, }: ToolbarProps): react.JSX.Element;

/**
 * Canvas zoom controls: fit-to-page, 100%, zoom-out/in buttons, and a percent
 * readout. Stateless — zoom lives in the editor's view state, updated through
 * onZoom.
 */
interface ZoomControlsProps {
    zoom: number;
    onZoom(zoom: number): void;
    onFit(): void;
    /** Label/aria for the fit action. Defaults to "Fit to screen" — shorter and
     *  matching every other tool's wording for the same action. */
    fitLabel?: string;
}
declare function ZoomControls({ zoom, onZoom, onFit, fitLabel }: ZoomControlsProps): react.JSX.Element;

/** 28px square (h-7) — used by the main toolbar. */
declare const BTN = "flex h-7 w-7 items-center justify-center rounded border border-[var(--border-default)] text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-input)] disabled:cursor-default disabled:opacity-40";
declare const BTN_ACTIVE: string;
/** 24px square (h-6) — used by the zoom controls and pages strip. */
declare const BTN_SM = "flex h-6 w-6 items-center justify-center rounded border border-[var(--border-default)] text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-input)] disabled:cursor-default disabled:opacity-40";
declare const BTN_SM_ACTIVE: string;
interface IconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
    /** Render the active (brand-colored) variant. */
    active?: boolean;
    /** 'md' = 28px (toolbar), 'sm' = 24px (zoom/pages). */
    size?: 'md' | 'sm';
}
declare const IconButton: react.ForwardRefExoticComponent<IconButtonProps & react.RefAttributes<HTMLButtonElement>>;

interface ExportControlProps {
    /** Pre-selected format/scale when the popover opens. Default PNG @ 1x. */
    defaults?: ExportTriggerOptions;
    /** Called with the chosen format/scale when the user confirms. */
    onExport(opts: ExportTriggerOptions): void;
    className?: string;
}
declare function ExportControl({ defaults, onExport, className }: ExportControlProps): react.JSX.Element;

interface ElementNodeProps {
    element: SceneElement;
    isSelected: boolean;
    zoom: number;
    /** Theme render palette. Omitted → light defaults (byte-identical history). */
    render?: CanvasRenderPalette;
    onClick?(elementId: string): void;
    onDragStart?(elementId: string): void;
    onDragMove?(elementId: string, dx: number, dy: number): void;
    onDragEnd?(elementId: string, finalX: number, finalY: number): void;
    onDoubleClick?(elementId: string): void;
}
declare function ElementNodeImpl(props: ElementNodeProps): react.JSX.Element | null;
/**
 * Memoized so a `stack.notify()` (fired ~120/s during a pan/marquee) that
 * re-renders WorkspaceView does NOT re-render every element. With stable
 * handler identities supplied by WorkspaceView, an ElementNode re-renders only
 * when its OWN `element` reference, `isSelected`, `zoom`, or `render` palette
 * change — i.e. when it actually moved, was (de)selected, or the view scaled.
 * Pan-only frames change none of these props, so the N nodes stay reconciled.
 */
declare const ElementNode: react.MemoExoticComponent<typeof ElementNodeImpl>;

/**
 * Grid overlay rendered beneath page content. The whole grid is painted by a
 * SINGLE Konva node — a custom Shape whose `sceneFunc` strokes every grid line
 * in one pass — rather than one Konva.Line per line. At ~hundreds of lines on a
 * page this turns a per-pan-frame reconciliation of hundreds of React/Konva
 * nodes into a single node whose only changing props are the transform; panning
 * no longer churns the scene graph.
 *
 * Grid lines are skipped entirely when they would be closer than 4 screen
 * pixels apart — below that density the grid becomes visual noise rather than
 * guidance (gridVisible density-skip, unchanged).
 *
 * COORDINATE SYSTEM: the lines are authored in document space and wrapped in a
 * Group carrying the SAME (panX, panY, zoom) transform the content layer uses,
 * so the grid tracks the page exactly on pan and zoom. A Konva.Layer cannot
 * live inside a Group, so the transform is applied to an inner Group, not the
 * Layer. The grid is its own Layer (not merged into the content Layer) so the
 * content draws on top without per-frame z-ordering churn.
 *
 * EXPORT EXCLUSION: the Layer carries the name prefix 'overlay:' and the Shape
 * is named 'overlay:grid-shape' so export logic excludes the whole grid from
 * rasterization.
 */
interface GridLayerProps {
    /** Page width in document px. */
    pageWidth: number;
    /** Page height in document px. */
    pageHeight: number;
    /** Document px between grid lines. */
    gridSize: number;
    /** Screen px per document px. */
    zoom: number;
    /** Horizontal pan offset in screen px (content Group x). */
    panX: number;
    /** Vertical pan offset in screen px (content Group y). */
    panY: number;
    /** Grid line color. */
    color?: string;
    /** Grid line opacity (0–1). */
    opacity?: number;
}
declare function GridLayer({ pageWidth, pageHeight, gridSize, zoom, panX, panY, color, opacity, }: GridLayerProps): react.JSX.Element | null;

interface RulersProps {
    /** Page width in document px. */
    pageWidth: number;
    /** Page height in document px. */
    pageHeight: number;
    zoom: number;
    /** How many doc-px of the canvas are scrolled off-screen left/top. */
    scrollLeft: number;
    scrollTop: number;
    showRulers: boolean;
    guides: PageGuides;
    /** Emitted when the user drops a guide or deletes one back into the ruler. */
    onGuidesChange(guides: PageGuides): void;
}
declare function Rulers({ pageWidth, pageHeight, zoom, scrollLeft, scrollTop, showRulers, guides, onGuidesChange }: RulersProps): react.JSX.Element | null;

/**
 * Pure layer-tree helpers: flatten a page's element array into an ordered list
 * for the LayersPanel, preserving group nesting. Extracted so render order,
 * depth, and selection math can be unit-tested independently of React.
 */

/** Describe a layer row with its element, depth, grouping, ownership, and parent group details */
interface LayerRow {
    element: SceneElement;
    depth: number;
    /** True when this row is a group whose children follow it in the list. */
    isGroup: boolean;
    /** Index within its owner (page.elements or group.children). */
    ownerIndex: number;
    /** Length of the owner array — needed for z-order bound math. */
    ownerLength: number;
    /** Id of the containing group, or null for page-root elements. */
    parentGroupId: string | null;
}
/**
 * Flatten `page.elements` into display order for the layers panel.
 *
 * Z-order is bottom→top in the element array; the layers panel shows
 * top→bottom (highest z-index first). A group row precedes its children
 * (the group is "above" its children in the panel, reflecting that the group
 * node itself paints last in Konva when empty; children paint inside it).
 *
 * Depth increases by 1 for each group level, starting at 0 for page-root
 * elements. Groups are expanded; collapsed state is a view concern the caller
 * tracks separately.
 */
declare function flattenLayerTree(page: ScenePage): LayerRow[];
/** The maximum number of rows the layers panel renders before truncating. */
declare const LAYERS_PANEL_ROW_LIMIT = 500;

/**
 * Pure geometry helpers extracted from component drag/transform logic so
 * every interactive math path is unit-testable without Konva or a DOM.
 *
 * Invariants:
 * - All inputs and outputs are in document-coordinate pixels unless noted.
 * - Rotation angles are degrees, clockwise, matching the Konva + model convention.
 * - "Baking" scale into width/height resets Konva's scaleX/scaleY to 1; that
 *   is required so the model's width/height always reflects true size, never a
 *   scaled-but-uncollapsed state.
 */
interface TransformerNode {
    x: number;
    y: number;
    width: number;
    height: number;
    /** Konva's scale after the transformer gesture; 1 when already baked. */
    scaleX: number;
    scaleY: number;
    rotation: number;
}
/** Define baked node attributes including position, size, and rotation with collapsed scale */
interface BakedNodeAttrs {
    x: number;
    y: number;
    /** True pixel size after scale is collapsed into dimensions. */
    width: number;
    height: number;
    rotation: number;
}
/**
 * Collapse Konva scaleX/scaleY into width/height so the model always stores
 * true pixel dimensions. The transformer mutates scale on drag; we bake it
 * once at dragend/transformend and emit width/height — scale resets to 1
 * implicitly (the emitted attrs do not include scale, so the next render
 * starts from scaleX=1).
 *
 * Konva rotates about the top-left origin and also shifts x/y to compensate
 * for scale — the transformer gives us the post-rotation, post-scale x/y
 * directly, so no further rotation math is needed here.
 */
declare function bakeRectTransform(node: TransformerNode): BakedNodeAttrs;
/**
 * Lines store points as a flat [x0, y0, x1, y1, ...] array relative to the
 * line element's (x, y). When the transformer scales the group containing the
 * line, we bake scaleX into every x-component of points and scaleY into every
 * y-component, then reset scale to 1. The element x/y is the Konva group
 * origin and is taken directly from the transformer output.
 */
declare function bakeLineTransform(node: TransformerNode & {
    points: number[];
}): BakedNodeAttrs & {
    points: number[];
};
/**
 * Text nodes have a fixed wrap width; scaling that width is what the
 * transformer controls. Height is content-derived and is NOT baked here —
 * it re-derives from text content at render time via estimateTextHeight.
 * Only scaleX is baked into width; scaleY into fontSize so text scales
 * proportionally when the user resizes with keepRatio.
 */
declare function bakeTextTransform(node: TransformerNode & {
    fontSize: number;
}): BakedNodeAttrs & {
    fontSize: number;
};

/**
 * Pure ruler tick-step and label math for the canvas rulers. Nothing here
 * touches React or the DOM — all interaction geometry is extracted so it can
 * be unit-tested without a browser.
 *
 * Canvas rulers show document-coordinate values (CSS px). Tick density adapts
 * to the current zoom so major ticks never sit closer than `minMajorSpacingPx`
 * screen pixels apart. The step table covers typical design zoom ranges; beyond
 * the table the step grows by doubling the last candidate.
 */
/** Define spacing and visibility rules for major and minor ticks in a coordinate system */
interface TickStep {
    /** Document-coordinate step between major ticks. */
    major: number;
    /** Document-coordinate step between minor ticks (major / 5). */
    minor: number;
    /** True when minor ticks should be drawn (they sit ≥ minMinorSpacingPx apart). */
    drawMinor: boolean;
}
/**
 * Select the major tick step that keeps major ticks ≥ minMajorSpacingPx apart
 * at the given zoom. Minor ticks are rendered when they'd clear minMinorSpacingPx.
 *
 * Both spacing thresholds are SCREEN pixels — the caller provides `zoom` (screen
 * px per document px) so the result is zoom-independent.
 */
declare function selectTickStep(input: {
    zoom: number;
    minMajorSpacingPx?: number;
    minMinorSpacingPx?: number;
}): TickStep;
/** Define a ruler tick with a position and optional label for measurement markings */
interface RulerTick {
    /** Position in document coordinates. */
    position: number;
    /** Label text, or null for a minor tick. */
    label: string | null;
}
/**
 * Generate all ticks visible in a ruler of `documentLength` document-px,
 * given the current tick step. The caller clips to the viewport; this produces
 * all ticks for the full document extent so the ruler can be rendered
 * declaratively without a separate clipping pass.
 */
declare function buildRulerTicks(input: {
    documentLength: number;
    step: TickStep;
}): RulerTick[];
/** Format a document-px position as a compact label: integers stay whole,
 *  decimals are rounded to 1 place. Values ≥ 1000 are compacted to "1k" etc. */
declare function formatRulerLabel(value: number): string;

export { BTN, BTN_ACTIVE, BTN_SM, BTN_SM_ACTIVE, type BakedNodeAttrs, CanvasEmptyState, type CanvasEmptyStateProps, CanvasInsertPanel, type CanvasInsertPanelProps, DesignCanvasMode, DesignCanvasProps, ElementNode, type ElementNodeProps, ExportControl, type ExportControlProps, type ExportPageDataUrlOptions, ExportPreset, ExportTriggerOptions, GridLayer, type GridLayerProps, IconButton, type IconButtonProps, type InsertGeneration, InsertPageGeometry, InsertTemplate, LAYERS_PANEL_ROW_LIMIT, type LayerRow, LayersPanel, type LayersPanelProps, MultiSetAttrsEntry, PagesStrip, type PagesStripProps, type RulerTick, Rulers, type RulersProps, SelectionLayer, type SelectionLayerProps, type TickStep, Toolbar, type ToolbarProps, type TransformerNode, Workspace, WorkspaceView, type WorkspaceViewProps, ZoomControls, type ZoomControlsProps, bakeLineTransform, bakeRectTransform, bakeTextTransform, buildRulerTicks, createSceneCommandStack, downloadDataUrl, exportDocumentJson, exportPageDataUrl, flattenLayerTree, formatRulerLabel, selectTickStep };
