import { BoardScene, BoardElement, ShapeElement, TextElement, FrameElement, TextAlign, VerticalAlign, FillStyle, StrokeStyle, Sloppiness, Edges, Arrowhead } from './types.js'; export { ArrowBinding, AudioElement, BoardAppState, BoardElementBase, BoardElementType, CustomElement, FormulaElement, ImageCrop, ImageElement, JsonValue, Measured, SCENE_TYPE, SCENE_VERSION, ShapeKind, StrokeElement, VideoElement } from './types.js'; export { DEFAULT_CANVAS, createEmptyScene, extractMarkdown, isBoardScene } from './scene.js'; import { Point, Rect } from './geometry.js'; export { elementBBox, hitTest, linearPoints, rectCenter, rectHits, rectsIntersect, rotatePoint, unionBBox } from './geometry.js'; export { CustomRenderer, CustomRenderers, RenderSceneOptions, escapeXml, renderElement, renderSceneToSvg, safeUrl, strokeOutlineToPath } from './render.js'; export { BoardOp, applyOp, inverseOp, opChangedIds } from './history.js'; export { ApplyOptions, BoardStore } from './store.js'; export { elementsFromMarkdown, formulasFromMarkdown } from './markdown.js'; export { RenderFormulaOptions, katexStrict, renderFormulaHtml } from './formula.js'; export { PAYLOAD_MIME, decodeScenePayload, encodeScenePayload, extractSceneFromSvg, sceneMetadataBlock } from './payload.js'; /** Serialize a scene to the `.boardraw` source (pretty JSON for readable diffs). */ declare function serializeBoardraw(scene: BoardScene): string; /** * Parse a `.boardraw` file. Tries JSON first (the current format), then falls * back to a legacy self-contained SVG payload. Returns null if neither yields * a valid scene. */ declare function parseBoardraw(text: string): BoardScene | null; /** * Render a `.boardraw` file's bytes to an SVG string for display in a Markdown * document (or anywhere a picture is needed). Returns null for invalid input. */ declare function boardrawToSvg(text: string): string | null; /** * Element grouping. `groupIds` lists memberships innermost-first; selecting * any member selects the whole (outermost) group. All mutators are pure and * return `{ before, after }` for a single `update` op, so group/ungroup is * one undo step. */ /** True when `el` belongs to `groupId`. */ declare function isElementInGroup(el: BoardElement, groupId: string): boolean; /** All elements of the scene belonging to `groupId`. */ declare function getElementsInGroup(scene: BoardScene, groupId: string): BoardElement[]; /** The outermost group id of an element, if any. */ declare function outermostGroupId(el: BoardElement): string | null; /** * Expand a selection so that picking any group member selects every element * of that (outermost) group. Non-grouped ids pass through. */ declare function expandSelectionToGroups(scene: BoardScene, ids: Iterable): Set; /** * Group the given elements under a fresh shared group id (appended outermost, * preserving any existing nested groups). No-op (empty diff) for <2 elements. */ declare function groupElements(els: BoardElement[], newGroupId: string): { before: BoardElement[]; after: BoardElement[]; }; /** * Dissolve each selected element's outermost group. Elements without groups * are left untouched (omitted from the diff). */ declare function ungroupElements(els: BoardElement[]): { before: BoardElement[]; after: BoardElement[]; }; type AlignMode = 'left' | 'centerX' | 'right' | 'top' | 'centerY' | 'bottom'; type DistributeAxis = 'horizontal' | 'vertical'; /** Align ≥2 elements along an edge or center of the selection's union box. */ declare function alignElements(els: BoardElement[], mode: AlignMode): { before: BoardElement[]; after: BoardElement[]; }; /** * Distribute ≥3 elements with equal spacing between neighbors along an axis * (Excalidraw's space-between strategy: first/last stay put). */ declare function distributeElements(els: BoardElement[], axis: DistributeAxis): { before: BoardElement[]; after: BoardElement[]; }; declare const BINDING_GAP = 6; /** Max distance from a shape edge for an arrow endpoint to auto-bind. */ declare const BINDING_THRESHOLD = 12; declare function isBindableTarget(el: BoardElement): boolean; /** * Where a bound endpoint should sit for `target`: on the line from `free` * (the arrow's other endpoint) to the target's center, pulled `gap` back * from the boundary toward `free`. Falls back to the boundary point (or * center) in degenerate cases. */ declare function boundEndpoint(free: Point, target: BoardElement, gap: number): Point; /** * Bind one endpoint of an arrow/line to a target shape. Returns the updated * arrow (with the endpoint snapped to the target's edge + gap), or null when * the element is not linear / target not bindable. */ declare function bindArrow(arrow: ShapeElement, target: BoardElement, end: 'start' | 'end', gap?: number): ShapeElement | null; /** * After elements move/resize, recompute every arrow bound to any of them. * Arrows included in `movedIds` themselves are skipped (they were dragged * as-is). Returns the `update` diff; empty when nothing changed. */ declare function updateBoundArrows(scene: BoardScene, movedIds: Iterable): { before: BoardElement[]; after: BoardElement[]; }; /** * Strip bindings that reference any of `deletedIds` (call before removing * elements so arrows don't point at ghosts). Returns the `update` diff. */ declare function pruneBindings(scene: BoardScene, deletedIds: Iterable): { before: BoardElement[]; after: BoardElement[]; }; /** A shape/image/formula can host a centered label. */ declare function isContainerTarget(el: BoardElement): boolean; /** * Top-left position that places `text` inside `container` (uses measured size). * Horizontally always centered; vertically honors `text.verticalAlign` * (top / middle / bottom), defaulting to middle. */ declare function centeredIn(text: TextElement, container: BoardElement): { x: number; y: number; }; /** * After containers move/resize, recompute the position of every label bound to * any of them. Labels included in `movedIds` themselves are skipped (they were * dragged directly). Returns the `update` diff; empty when nothing changed. */ declare function updateContainerLabels(scene: BoardScene, movedIds: Iterable): { before: BoardElement[]; after: BoardElement[]; }; /** * Labels whose container is in `deletedIds` (call before removing elements so * orphan labels go with them). Returns the label elements to delete. */ declare function pruneContainerLabels(scene: BoardScene, deletedIds: Iterable): TextElement[]; /** The label bound to `containerId`, if any. */ declare function labelOf(scene: BoardScene, containerId: string): TextElement | undefined; /** * Elbow arrows: line/arrow whose `points` are an auto-generated right-angle * (Manhattan) route between the two endpoints. v1 uses a single-jog Z route * split at the midpoint of the dominant axis — no obstacle avoidance, no * heading-aware clearance (a deliberate simplification; boxes can be crossed). * The route is recomputed whenever an endpoint moves (see `binding.reanchor`). */ /** Orthogonal waypoints from `start` to `end`: a right-angle Z (or a straight * segment when the two points already share a row/column). */ declare function routeElbow(start: Point, end: Point): Point[]; /** * Rewrite an elbow line/arrow's `points` as the orthogonal route between its * current endpoints. No-op for non-elbow or non-linear elements. */ declare function reroute(el: ShapeElement): ShapeElement; declare function isFrame(el: BoardElement): el is FrameElement; /** * Which frame (by id) clips each non-frame element: the innermost (smallest) * frame whose bbox contains the element's center. Elements outside every frame * are absent. Used by the renderer to clip frame content to frame bounds. */ declare function frameClipMap(scene: BoardScene): Map; /** `` defs (one per frame) matching each frame's rounded rect. */ declare function frameClipDefs(scene: BoardScene): string; /** Non-frame elements whose bbox center lies inside the given frame. */ declare function frameChildren(scene: BoardScene, frameId: string): BoardElement[]; /** * Object alignment snapping for live drags. Given the moving element's bbox and * the other elements' bboxes, `alignmentSnap` returns the small delta that * snaps the moving box's edges/centers onto a nearby element's edges/centers, * plus the guide lines to draw. Pure — the host applies the delta to the drag * and renders the guides. Threshold is in scene units (host passes ~px/zoom). */ interface AlignGuide { axis: 'x' | 'y'; /** The shared coordinate (x for a vertical guide, y for a horizontal one). */ at: number; /** Extent of the guide line along the other axis. */ start: number; end: number; } interface AlignResult { dx: number; dy: number; guides: AlignGuide[]; } declare function alignmentSnap(moving: Rect, others: Rect[], threshold?: number): AlignResult; /** An equal-gap indicator: two spans of the same length along `axis`, drawn at * perpendicular coordinate `at`. */ interface GapGuide { axis: 'x' | 'y'; at: number; gaps: Array<[number, number]>; } interface DistributionResult { dx: number; dy: number; guides: GapGuide[]; } /** * Equal-gap distribution snapping: while dragging, snap the moving box to sit * centered between two other elements that are in line with it (overlapping on * the perpendicular axis), and report the two equal gaps to draw. Pure. */ declare function distributionSnap(moving: Rect, others: Rect[], threshold?: number): DistributionResult; /** Logical stroke-width buckets (a 3-way control), mapped to units per type. */ type StrokeWidth = 'thin' | 'medium' | 'bold'; declare const STROKE_WIDTHS: Record; /** Font-size buckets (S/M/L/XL) in scene units, for a text-size control. */ type FontSizeKey = 's' | 'm' | 'l' | 'xl'; declare const FONT_SIZES: Record; /** Font-family presets (CSS stacks) shared across hosts. */ declare const FONT_FAMILIES: { readonly sans: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"; readonly serif: "Georgia, 'Times New Roman', serif"; readonly mono: "ui-monospace, SFMono-Regular, Menlo, monospace"; readonly hand: "'Comic Sans MS', 'Segoe Print', 'Bradley Hand', cursive"; }; type FontFamilyKey = keyof typeof FONT_FAMILIES; /** Sentinel meaning "no background fill" (shapes render `fill="none"`). */ declare const NO_FILL = "transparent"; /** * A host's per-tool style: defaults stamped onto new elements, and the shape * read back from a selection to populate the panel. */ interface ToolStyle { /** Stroke/text color (CSS color). */ color: string; /** Shape background (CSS color), or NO_FILL for none. Ignored by non-shapes. */ fill: string; strokeWidth: StrokeWidth; /** 0..1. */ opacity: number; /** Pen capture: true = pressure-varying width, false = uniform. */ pressure: boolean; /** Text: CSS font stack. */ fontFamily: string; /** Text/formula: font size in scene units. */ fontSize: number; /** Text: horizontal alignment. */ textAlign: TextAlign; /** Container-bound text: vertical placement within the shape. */ verticalAlign: VerticalAlign; /** Shape: sketchy fill pattern (applies when sloppiness > 0). */ fillStyle: FillStyle; /** Shape: stroke dash pattern. */ strokeStyle: StrokeStyle; /** Shape: hand-drawn roughness (0 = clean). */ sloppiness: Sloppiness; /** Shape: corner treatment. */ edges: Edges; /** Line/arrow: end decoration. */ arrowhead: Arrowhead; /** Line/arrow: start decoration. */ startArrowhead: Arrowhead; /** Line/arrow: orthogonal (right-angle) routing. */ elbow: boolean; } declare const DEFAULT_TOOL_STYLE: ToolStyle; /** The style controls a given surface exposes. */ type StyleProp = 'color' | 'fill' | 'strokeWidth' | 'pressure' | 'opacity' | 'fontFamily' | 'fontSize' | 'textAlign' | 'verticalAlign' | 'fillStyle' | 'strokeStyle' | 'sloppiness' | 'edges' | 'arrowhead' | 'elbow'; /** * Which controls a tool's panel shows (defaults for the next element). This is * the "layered control" logic: the second toolbox is derived from the tool. * Unknown / non-drawing tools (select, eraser, lasso) return []. */ declare function toolStyleProps(tool: string): StyleProp[]; /** * Which controls apply to an existing element (selection editing). Pressure is * a capture-time choice, so it is never editable after the fact. */ declare function elementStyleProps(el: BoardElement): StyleProp[]; /** * Stamp style fields onto an element, mapping the logical `strokeWidth` bucket * to the right unit per type and `fill` only onto shapes. Fields absent from * `style` are left untouched. Used both to style a freshly-built element and * to edit a selected one (produce the `after` of an `update` op). Pure. */ declare function applyStyle(el: BoardElement, style: Partial): BoardElement; /** Read an element's current style into panel-shaped fields. Pure. */ declare function readStyle(el: BoardElement): Partial; /** * Style fields shared by every element in a selection (multi-select). A field * is present only when all elements agree; differing fields are omitted so a * host can render a "mixed" placeholder. Pure. */ declare function readStyleCommon(els: BoardElement[]): Partial; type LayerMode = 'front' | 'back' | 'forward' | 'backward'; /** * Compute the `update` op (before/after) that reorders `ids` in paint order. * z is reassigned by final position; only elements whose z changes are * returned, so undo stays minimal. Pure. * * Note: `renderSceneToSvg` groups elements by type before z-sorting, so this * reorders WITHIN an element's own type group (a stroke cannot move behind a * shape). Global cross-type layering would require a render change. */ declare function reorder(scene: BoardScene, ids: Iterable, mode: LayerMode): { before: BoardElement[]; after: BoardElement[]; }; declare const bringToFront: (scene: BoardScene, ids: Iterable) => { before: BoardElement[]; after: BoardElement[]; }; declare const sendToBack: (scene: BoardScene, ids: Iterable) => { before: BoardElement[]; after: BoardElement[]; }; declare const bringForward: (scene: BoardScene, ids: Iterable) => { before: BoardElement[]; after: BoardElement[]; }; declare const sendBackward: (scene: BoardScene, ids: Iterable) => { before: BoardElement[]; after: BoardElement[]; }; export { type AlignGuide, type AlignMode, type AlignResult, Arrowhead, BINDING_GAP, BINDING_THRESHOLD, BoardElement, BoardScene, DEFAULT_TOOL_STYLE, type DistributeAxis, type DistributionResult, Edges, FONT_FAMILIES, FONT_SIZES, FillStyle, type FontFamilyKey, type FontSizeKey, FrameElement, type GapGuide, type LayerMode, NO_FILL, Point, Rect, STROKE_WIDTHS, ShapeElement, Sloppiness, StrokeStyle, type StrokeWidth, type StyleProp, TextAlign, TextElement, type ToolStyle, VerticalAlign, alignElements, alignmentSnap, applyStyle, bindArrow, boardrawToSvg, boundEndpoint, bringForward, bringToFront, centeredIn, distributeElements, distributionSnap, elementStyleProps, expandSelectionToGroups, frameChildren, frameClipDefs, frameClipMap, getElementsInGroup, groupElements, isBindableTarget, isContainerTarget, isElementInGroup, isFrame, labelOf, outermostGroupId, parseBoardraw, pruneBindings, pruneContainerLabels, readStyle, readStyleCommon, reorder, reroute, routeElbow, sendBackward, sendToBack, serializeBoardraw, toolStyleProps, ungroupElements, updateBoundArrows, updateContainerLabels };