import { m as MarkHandle, k as GroupHandle, Z as Target, H as HighlightOptions, X as SnapMode, A as Anchor, L as LineRect, q as PageTarget, p as MutationCallback, e as Disconnect, R as ReflowCallback, x as RenderEnvironment, F as RendererTierPreference, z as RendererTier, y as Renderer } from './path-DTqnMNYz.js'; export { a as AnimationDirection, b as AnimationOptions, c as AnimationTrigger, B as BlendMode, d as Box, C as ColorValue, D as DEFAULT_OPTIONS, E as EasingValue, f as EdgeCap, g as EdgeOptions, h as EdgeVertex, G as GlowOptions, i as GradientConfig, j as GradientStop, I as InkOptions, l as LineSpeedProfile, M as MarkGeometry, n as MarkType, o as MaskOffset, N as NoiseTile, P as PALETTES, r as Palette, s as PaletteName, t as PaletteSwatch, u as PaperOptions, v as PoolGradient, w as RenderContext, J as ResolvedAnimation, K as ResolvedEdge, O as ResolvedGlow, Q as ResolvedInk, S as ResolvedOptions, T as ResolvedPaper, U as ResolvedSpeedDynamics, V as ResolvedTip, W as ShapeType, Y as SpeedDynamicsOptions, _ as TextTarget, $ as TipOptions, a0 as TipType, a1 as buildClipPath, a2 as buildEdge, a3 as buildMarkGeometry, a4 as buildNoiseTile, a5 as buildNoiseTileDataUrl, a6 as buildPoolGradient, a7 as defaultSwatch, a8 as getPalette, a9 as hashJitter, aa as hashU32, ab as mergeOptions, ac as mulberry, ad as resolveOptions, ae as resolveSwatch } from './path-DTqnMNYz.js'; /** * The public entry points. * * One pipeline, many front doors: every targeting input normalizes to DOM `Range`s, then * per-visual-line rectangles, then absolute-px {@link MarkGeometry} per line, then the selected * renderer tier. The returned handle owns the reflow observer and (for page/selection modes) the * mutation watcher or selection listener, tearing them all down on `remove()`. * * SSR-safe: outside a DOM the entry points return an inert no-op handle. */ /** * Highlight a target: the primary entry point. * * @param target - Any {@link Target}: element, selector, `Range`, `Selection`, text query, or page target. * @param host - Optional positioned element to mount the overlay inside, scoping it to a transformed, * scrolling, or stacked container. Promoted to `position: relative` if static. Defaults to the body. * @returns A {@link MarkHandle}; inert outside a DOM. */ declare function highlight(target: Target, options?: HighlightOptions, host?: HTMLElement | null): MarkHandle; /** * Highlight whole-page / declarative-attribute content. * * Collects `data-highlight` elements and/or a page target (default root `document.body`), honouring * exclusions, and attaches a debounced `MutationObserver` so added nodes get marked and removed nodes * drop their marks without a full rescan. Returns one handle covering all matches. * @returns A {@link MarkHandle}; inert outside a DOM. */ declare function highlightAll(options?: HighlightOptions): MarkHandle; /** * Highlight the user's live selection in real time. * * Drives `selectionchange`-derived ranges into the same pipeline. On coarse pointers it defers to * native selection UI rather than painting an overlay. `remove()` detaches the listener. * * Subtrees marked `data-highlight-exclude` are carved out before painting, so a select-all never * bands over opted-out regions (read-only content, code blocks, and the like). * @returns A {@link MarkHandle}; inert outside a DOM. */ declare function highlightSelection(options?: HighlightOptions): MarkHandle; /** * Bundle handles into a {@link GroupHandle} for sequential show/hide choreography. `show()` * reveals members in array order so their draw-on staggers like a pen down the page. * @param handles - The member handles, in choreography order. */ declare function group(handles: MarkHandle[]): GroupHandle; /** Snap `range` to `mode`. Read-only; returns a (possibly cloned) range. */ declare function snapRangeToBounds(range: Range, mode: SnapMode): Range; /** The normalization front door: every {@link Target} variant collapses to a flat array of DOM `Range`s. Never throws; yields `[]` on no match or no DOM. */ /** * Normalize any {@link Target} to a flat array of DOM `Range`s. Dispatch order is significant: * specific shapes (`Range`, `Selection`, `Element`, {@link TextTarget}) are matched before the * catch-all page-target object, and `string` is a CSS selector. Never throws. */ declare function toRanges(target: Target): Range[]; /** * Range to per-visual-line rectangles: the read-only layout stage. Collect client rects per text node, * coalesce into one rect per visual line, and stamp each line with a layout-stable seed for the * geometry layer's jitter. Per-text-node collection avoids the full-width bbox rects `getClientRects()` * emits at block boundaries; the merge folds same-line fragments but won't merge across large * horizontal gaps (so `justify-between` rows don't fuse into one ghost band). */ /** The top-left-most point of the targeted content's bounding box; the horizontal column-filter origin. `{0, 0}` with nothing to measure. */ declare function computeAnchor(ranges: Range[]): Anchor; interface RangesToLineRectsOptions { /** Only measure text under this element (live-selection reading surface). */ scope?: Element; /** Anchor element bounds for column filtering; when set, both edges come from the host rect. */ columnBounds?: { left: number; right: number; }; } /** Collect per-text-node rects, merge into visual lines, drop rects outside the anchor column, and emit one {@link LineRect} per line with its stable seed. Read-only. */ declare function rangesToLineRects(ranges: Range[], anchor: Anchor, originTop?: number, options?: RangesToLineRectsOptions): LineRect[]; /** Whole-page targeting with include/exclude selectors. Exclusion always wins: a node is dropped the moment any ancestor matches an exclude selector. */ /** Collect every textual `Range` under `target.root` (default `document.body`), honouring include/exclude. Each accepted text node becomes one `Range` over its non-whitespace span. Never throws. */ declare function collectPageRanges(target: PageTarget): Range[]; /** * Text-query targeting: a `Range` per match of a string/`RegExp` under a root, including matches that * span inline element boundaries (e.g. `foobarbaz`). The walk concatenates text nodes into * one flat string, recording each character's source node + offset, then maps matches back onto the nodes. */ /** * Find every match of `query` within `root`, one `Range` per match. * - `string`: literal, case-sensitive, non-overlapping. * - `RegExp`: scanned globally on a copy; case follows the `i` flag; zero-width matches skipped. * Never throws. */ declare function findTextRanges(root: Element | Document, query: string | RegExp): Range[]; /** * The element live selection marks should attach to: the nearest positioned ancestor of the * selection, or the reading surface (`article`, then `main`) when the walk reaches `body` (Cmd+A). * Overlays are children of this node with anchor-relative coordinates, so they scroll natively and * stay aligned when the viewport reflows — mounting on `document.body` drifts from centered columns. */ declare function findSelectionAnchor(node: Node): HTMLElement; /** * Reflow and dynamic-DOM observation. `createReflowObserver` funnels every event that can move a mark * (resize, web-font load) into a single rAF-batched callback. `createMutationWatcher` is the scoped, * debounced `MutationObserver` for page/declarative modes. Both return a leak-free, idempotent `Disconnect`. */ /** Wire reflow observation for `targets` (and their positioned containers), window resize, and web-font load into one rAF-batched `callback`. Leak-free `Disconnect`; inert off-DOM. */ declare function createReflowObserver(targets: Element[], callback: ReflowCallback): Disconnect; /** Scoped, debounced `MutationObserver` on `root`: a mutation burst flushes one `callback` once the DOM is quiet for {@link MUTATION_DEBOUNCE_MS}. Leak-free `Disconnect`; inert off-DOM. */ declare function createMutationWatcher(root: Element | Document, callback: MutationCallback): Disconnect; /** * Capability detection and renderer-tier selection. * * Three tiers sit behind one API; degrade is fidelity-only, a lower tier never moves or recolours a * mark, only simplifies edge organicness and texture. * * - {@link detectEnvironment}: runtime support + accessibility/data preferences. Touches no DOM at import. * - {@link selectTier}: pick a concrete tier from a request, the environment, and the live mark count. */ /** Feature-detect the tiers and read motion/data/pointer preferences into a {@link RenderEnvironment}. SSR-safe; DOM-pure. */ declare function detectEnvironment(): RenderEnvironment; /** * Select the concrete renderer tier for a mark. * * - Pinned (`!== "auto"`): honour the request when supported, else step down to the nearest supported. * - `"auto"`: degrade precedence - reduced-motion/reduced-data and a mark count above the threshold * both step SVG down to the CSS band; an unsupported tier falls through to the next supported. Tier B * is the floor of auto-degrade; Tier C is chosen only when highest supported or explicitly pinned. * * Pure given its inputs; all capability reads happen in {@link detectEnvironment}. * @param markCount - Number of simultaneously visible marks (for the threshold). */ declare function selectTier(requested: RendererTierPreference, env: RenderEnvironment, markCount: number): RendererTier; /** * Tier A renderer: the realistic SVG-filter band. The default tier. * * Each visual line gets a positioned wrapper `
`; inside it at `inset: 0` sit the ink node * (pool gradient, clipped to the tip geometry via `clip-path`, textured by the offset-sampled noise * tile via `mask-image`, run through a shared SVG filter) and an optional glow node. The wrapper * carries no geometry clip-path, only the box position, so the draw-on can wipe it open with * `clip-path: inset(...)` instead of a `scaleX()` that would stretch the texture/wave. * * One shared ``/`` filter block is reused by every mark. Filters are referenced, never * animated: computed once per geometry and reused until reflow, so scrolling never re-filters. * * An optional additive fluorescence layer is a second node in `screen` blend over the multiply ink, * so an enabled mark reads brighter than its background rather than as a darker tint. * * Nodes are pooled by stable line identity; `unmount()` leaves the DOM pristine. */ /** Create a Tier A renderer (`tier: "svg"`). */ declare function createSvgRenderer(): Renderer; /** * Tier B renderer: a CSS `linear-gradient` band. The lightweight tier. * * A per-line wrapper `
` holds a band `
` at `inset: 0` painted with the absolute-px end-pool * gradient and composited with `mix-blend-mode: multiply`. Edges are straight (no wave, no texture), * but colour, opacity, blend, and band position match Tier A, so degrading here changes fidelity not * identity. The wrapper carries only the box position (no clip), structurally identical to Tier A. * * Nodes are pooled by stable line identity; `unmount()` leaves the DOM pristine. */ /** Create a Tier B renderer (`tier: "css"`). */ declare function createCssRenderer(): Renderer; /** * Tier C renderer: the CSS Custom Highlight API (`::highlight()`). The maximally-safe tier. * * Registers the mark's `Range`s with `CSS.highlights` and paints them via a generated `::highlight()` * rule: zero overlay DOM, native multiline, find-in-page/selection unaffected, text nodes untouched. * The trade-off is fidelity (flat colour only), but colour and coverage still match the other tiers. * * Each instance owns one named `Highlight` registration and one CSS rule in a shared `