@weasel-js/core 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +266 -0
  2. package/README.md +24 -4
  3. package/dist/{depSchema-BhgZc0-Q.d.ts → builtins-DLn2lCr_.d.ts} +693 -53
  4. package/dist/{chunk-BJN5ZRIJ.js → chunk-3TY6FHAF.js} +7 -4
  5. package/dist/chunk-3TY6FHAF.js.map +1 -0
  6. package/dist/{chunk-H6N2JSZ3.js → chunk-DGWNNKGD.js} +3 -3
  7. package/dist/{chunk-H6N2JSZ3.js.map → chunk-DGWNNKGD.js.map} +1 -1
  8. package/dist/{chunk-THCSDHII.js → chunk-G4ZGQMY7.js} +2453 -1264
  9. package/dist/chunk-G4ZGQMY7.js.map +1 -0
  10. package/dist/{chunk-HPFJUUTF.js → chunk-LU4IJ52W.js} +5 -61
  11. package/dist/chunk-LU4IJ52W.js.map +1 -0
  12. package/dist/{chunk-D4AAWR64.js → chunk-M24CLARN.js} +4 -4
  13. package/dist/{chunk-D4AAWR64.js.map → chunk-M24CLARN.js.map} +1 -1
  14. package/dist/{chunk-4RJP2N2L.js → chunk-NE27EOLP.js} +8 -5
  15. package/dist/chunk-NE27EOLP.js.map +1 -0
  16. package/dist/{chunk-DOBSZOPR.js → chunk-UPZY4ART.js} +3 -3
  17. package/dist/{chunk-DOBSZOPR.js.map → chunk-UPZY4ART.js.map} +1 -1
  18. package/dist/{chunk-T3UQ3F6R.js → chunk-WPNA6L5O.js} +47 -13
  19. package/dist/chunk-WPNA6L5O.js.map +1 -0
  20. package/dist/{chunk-44EWMJV2.js → chunk-XMAWPGTK.js} +5 -5
  21. package/dist/{chunk-44EWMJV2.js.map → chunk-XMAWPGTK.js.map} +1 -1
  22. package/dist/clipboard.d.ts +1 -1
  23. package/dist/clipboard.js +3 -3
  24. package/dist/clone.d.ts +2 -2
  25. package/dist/clone.js +3 -3
  26. package/dist/grid-CY5UKlZh.d.ts +98 -0
  27. package/dist/index.css +11 -35
  28. package/dist/index.css.map +1 -1
  29. package/dist/index.d.ts +912 -1148
  30. package/dist/index.js +9 -9
  31. package/dist/insert.d.ts +2 -3
  32. package/dist/insert.js +1 -1
  33. package/dist/math.d.ts +1 -1
  34. package/dist/move.d.ts +5 -4
  35. package/dist/move.js +4 -4
  36. package/dist/move.js.map +1 -1
  37. package/dist/patterns-builtin.js +1 -1
  38. package/dist/{pointSnapToGrid-7mCcm6qG.d.ts → pointSnapToGrid-Dp2IxLGb.d.ts} +53 -60
  39. package/dist/renderer.css +11 -35
  40. package/dist/renderer.css.map +1 -1
  41. package/dist/renderer.d.ts +17 -8
  42. package/dist/renderer.js +9 -9
  43. package/dist/resize.d.ts +3 -3
  44. package/dist/resize.js +2 -2
  45. package/dist/routing.d.ts +1 -1
  46. package/dist/routing.js +1 -1
  47. package/dist/{types-CxC8P6W0.d.ts → types-D-9QWBy5.d.ts} +9 -6
  48. package/dist/{types-D_74YlWs.d.ts → types-qYpyTAiZ.d.ts} +4 -7
  49. package/package.json +15 -12
  50. package/dist/chunk-4RJP2N2L.js.map +0 -1
  51. package/dist/chunk-BJN5ZRIJ.js.map +0 -1
  52. package/dist/chunk-HPFJUUTF.js.map +0 -1
  53. package/dist/chunk-T3UQ3F6R.js.map +0 -1
  54. package/dist/chunk-THCSDHII.js.map +0 -1
  55. package/dist/grid-Dx2gQbNv.d.ts +0 -158
  56. package/dist/options-CzjxFoYZ.d.ts +0 -67
  57. package/dist/{math-DRa6HBBs.d.ts → math-MCQcf_gc.d.ts} +111 -111
@@ -1,14 +1,18 @@
1
1
  import { GradStop, ColorSpace, TextureHandle, FillStyle, Stroke, ScreenLength } from '@weasel-js/paint';
2
- import { NodeId, Bounds, View, SelectionApi, ActionDeps, IngestItem, DragSample, Point2 } from '@weasel-js/routing';
2
+ import { NodeId, Bounds, View, ModifierState, SelectionApi, ActionDeps, IngestItem, DragSample, Point2, AnyToolOf, Contribution as Contribution$1, ContributionChrome as ContributionChrome$1, Tool as Tool$1, ToolDef as ToolDef$1 } from '@weasel-js/routing';
3
3
  import { P as Path } from './path-JEV2c5If.js';
4
- import { ResolvedRun, TextStyle, TextVerticalAlign } from '@weasel-js/text';
5
- import { Mat3 } from '@weasel-js/geom';
4
+ import { ReactNode } from 'react';
6
5
  import * as _weasel_js_history from '@weasel-js/history';
7
6
  import { Op, History, SerializedHistory } from '@weasel-js/history';
8
- import { a as SceneAdapter, L as LayoutStrategy, b as LayoutDropTargetMode, I as InsertAdapter } from './types-CxC8P6W0.js';
7
+ import { a as SceneAdapter, L as LayoutStrategy, b as LayoutDropTargetMode, I as InsertAdapter } from './types-D-9QWBy5.js';
9
8
  import { P as PoseDescriptor } from './poseDescriptor-rZa9W5hJ.js';
10
- import { ActiveToolContextValue } from '@weasel-js/routing/react';
11
- import { B as BoundsConstraint, P as PointSnapBehavior } from './types-D_74YlWs.js';
9
+ import { ActiveToolContextValue, ToolsApi as ToolsApi$1, UseToolsOptions as UseToolsOptions$1 } from '@weasel-js/routing/react';
10
+ import { B as BoundsConstraint, P as PointSnapBehavior } from './types-qYpyTAiZ.js';
11
+ import { Mat3 } from '@weasel-js/geom';
12
+ import { ResolvedRun, TextStyle, TextVerticalAlign } from '@weasel-js/text';
13
+ import { CursorSpec } from '@weasel-js/cursor';
14
+ import { ClaimableGesture } from '@weasel-js/gestures';
15
+ import { Reflection } from '@weasel-js/registry';
12
16
 
13
17
  /**
14
18
  * Axis-aligned rectangle pose with optional rotation. The canonical pose
@@ -1100,6 +1104,12 @@ interface ShaderProgramHandle {
1100
1104
  * | TextureHandle | bind to next tex unit + uniform1i |
1101
1105
  */
1102
1106
  type ShaderUniform = number | [number, number] | [number, number, number] | [number, number, number, number] | Float32Array | TextureHandle;
1107
+ interface ProgramSource {
1108
+ vert: string;
1109
+ frag: string;
1110
+ }
1111
+ /** Every registered program's GLSL source, keyed by program id. */
1112
+ declare const programSourceRegistry: Reflection<ProgramSource>;
1103
1113
  /**
1104
1114
  * Register a custom shader program by id.
1105
1115
  *
@@ -1773,64 +1783,511 @@ interface CullRect {
1773
1783
  */
1774
1784
  declare function cullDrawCommands(cmds: DrawCommand[], transform: GlMat3, rect: CullRect): DrawCommand[];
1775
1785
 
1776
- /** Options for stroke tessellation. */
1777
- interface StrokeOptions {
1778
- flattenTolerance?: number;
1786
+ interface ChromeState {
1787
+ /** Currently selected ids. Live; reflects useSelection's React state. */
1788
+ readonly selection: readonly NodeId[];
1789
+ /** True when the canvas is in multi-mode AND >= 2 ids are selected. */
1790
+ readonly multiActive: boolean;
1791
+ /** Bounds for any selection member id. Honors active-tool overlay state
1792
+ * (move/resize/rotate ghosts → ghost bounds; otherwise → committed
1793
+ * pose bounds). Returns null for unknown ids or ids whose bounds aren't
1794
+ * computable. */
1795
+ boundsOf(id: string): Bounds | null;
1796
+ /** Multi-union AABB when `multiActive`. Recomputed from `boundsOf` over
1797
+ * every selected id on each read, expanding rotated members to the extent
1798
+ * of their ink; null otherwise. */
1799
+ readonly unionBounds: Bounds | null;
1800
+ /** Active modifier state at the moment of the call. */
1801
+ readonly modifiers: ModifierState;
1802
+ /** True iff the node's pose-descriptor declares it can carry a rotation.
1803
+ * Affordances consult this to decide whether to expose rotate cursors /
1804
+ * drag-bands. Defaults to `true` when the descriptor doesn't declare
1805
+ * (back-compat) or when the id is unknown — the rotation gesture will
1806
+ * no-op visually for poses without AABB fields, but the affordance
1807
+ * doesn't lie about the cursor. Optional on the interface so unit-test
1808
+ * call sites that construct `ChromeState` by hand keep compiling;
1809
+ * affordances should treat an absent predicate as "true". */
1810
+ canRotate?(id: string): boolean;
1811
+ }
1812
+
1813
+ /**
1814
+ * @experimental
1815
+ * A single interactive piece of chrome. Pure functions; the kit composes
1816
+ * multiple affordances into a single RenderLayer per tool via
1817
+ * `composeAffordanceLayer`.
1818
+ *
1819
+ * Affordances declare interactive regions in a target's *local* frame.
1820
+ * The framework (`composeAffordanceLayer`) composes the target's bounds
1821
+ * transform (rotation around the AABB center, when present) for both paint
1822
+ * and hit-test, so the affordance never touches rotation, view.scale, or
1823
+ * world↔screen math.
1824
+ */
1825
+ interface Affordance {
1826
+ /** Stable id for debug overlays + visibility maps. */
1827
+ id: string;
1828
+ /** Enumerate this affordance's interactive regions. Each region lives in
1829
+ * some target id's local frame (or in the world frame when `targetId`
1830
+ * is `null`). Returning `[]` means "no chrome for this state" (no
1831
+ * selection, multi-mode disabled, etc.). */
1832
+ regions(state: ChromeState): readonly AffordanceRegion[];
1833
+ /** Optional non-interactive decoration (e.g., a leader line drawn from
1834
+ * a bounds edge to a handle — visual only, not draggable). Receives
1835
+ * raw state + view because the decoration may live outside any single
1836
+ * target's local frame. Most affordances leave this undefined. */
1837
+ decorate?(state: ChromeState, view: View): DrawCommand[];
1838
+ }
1839
+ /**
1840
+ * @experimental
1841
+ * One interactive region produced by an affordance. The framework owns
1842
+ * the local↔world transform for `targetId` (when non-null), so `shape`,
1843
+ * `paint.sizePx`, and `hitRadiusPx` are always specified in coordinates
1844
+ * the affordance can reason about directly.
1845
+ */
1846
+ interface AffordanceRegion<TScratch = unknown> {
1847
+ /** Stable id, e.g. `corner-min-min`. Used for debug overlays + a11y. */
1848
+ id: string;
1849
+ /** Target id whose `state.boundsOf(targetId)` defines this region's
1850
+ * local frame. `bounds.rotation` (if present) is the only transform
1851
+ * applied — translation is the AABB origin; scale is identity. Pass
1852
+ * `null` for affordances anchored to the viewport / world frame
1853
+ * (identity transform). */
1854
+ targetId: string | null;
1855
+ /** Region geometry, expressed in the target's local frame.
1856
+ *
1857
+ * - `point` — circular hit (`hitRadiusPx` is screen-space).
1858
+ * - `rect` — axis-aligned rect (target rotation applies).
1859
+ * - `annulus` — outer ellipse minus inner rect cutout. Used for
1860
+ * invisible zones that sit *around* the AABB (e.g. rotate-on-
1861
+ * hover band). The outer ellipse is defined by world-space
1862
+ * semi-axes `rx` / `ry` around `(cx, cy)`; the inner rect is the
1863
+ * same target-local rect that defines the AABB. Hit-test:
1864
+ * inside outer ellipse AND outside inner rect. */
1865
+ shape: {
1866
+ kind: 'point';
1867
+ x: number;
1868
+ y: number;
1869
+ hitRadiusPx: number;
1870
+ } | {
1871
+ kind: 'rect';
1872
+ x: number;
1873
+ y: number;
1874
+ width: number;
1875
+ height: number;
1876
+ } | {
1877
+ kind: 'annulus';
1878
+ /** Outer-ellipse center (target-local). */
1879
+ cx: number;
1880
+ cy: number;
1881
+ /** Outer-ellipse semi-axes (target-local). */
1882
+ rx: number;
1883
+ ry: number;
1884
+ /** Inner rect (target-local) — the cutout. Typically the
1885
+ * selection's AABB. */
1886
+ innerX: number;
1887
+ innerY: number;
1888
+ innerWidth: number;
1889
+ innerHeight: number;
1890
+ /** Minimum band thickness outside the inner rect, in **screen**
1891
+ * pixels. The framework widens `rx`/`ry` to at least
1892
+ * `innerHalfExtent + minBandPx / meanScale(view.scale)` for both
1893
+ * paint and hit-test.
1894
+ *
1895
+ * This exists because the clamp has to know the view and the
1896
+ * affordance doesn't: `ChromeState` carries no scale. Expressing the
1897
+ * floor in world units instead (which is what the rotate ring used
1898
+ * to do) makes the band shrink on screen as you zoom in, until the
1899
+ * ring around a small shape is too thin to hover. */
1900
+ minBandPx?: number;
1901
+ };
1902
+ /** Optional paint. World position is derived from `shape` + target
1903
+ * transform; visual size stays in screen pixels (so handles don't
1904
+ * warp under zoom or non-uniform scale). Omit for hit-only regions.
1905
+ *
1906
+ * - `square` — small fixed-size square (only valid over `point` shapes).
1907
+ * - `annulus` — fill + stroke the annulus ring (only valid over
1908
+ * `annulus` shapes). Uses even-odd fill rule to punch the inner-rect
1909
+ * cutout.
1910
+ * - `custom` — emit arbitrary draw commands; receives a {@link CustomPaintContext}. */
1911
+ paint?: {
1912
+ kind: 'square';
1913
+ sizePx: number;
1914
+ fill?: FillStyle;
1915
+ stroke?: Stroke;
1916
+ } | {
1917
+ kind: 'annulus';
1918
+ fill?: FillStyle;
1919
+ stroke?: Stroke;
1920
+ insetPx?: number;
1921
+ } | {
1922
+ kind: 'custom';
1923
+ draw: (ctx: CustomPaintContext) => DrawCommand[];
1924
+ };
1925
+ /** Discriminator a press on this region reports as `AffordanceHit.kind` —
1926
+ * the string routing specs match on (`'handle:top-left'`,
1927
+ * `'rotate-handle'`, `'anchor:3'`). Omit for regions that only exist
1928
+ * inside a consumer-registered layer, where the layer id is the
1929
+ * discriminator; `buildAffordanceAt` falls back to
1930
+ * `<affordanceId>:<regionId>`. */
1931
+ hitKind?: string;
1932
+ /** Cursor to show while hovering this region. Read by the hover-cursor
1933
+ * pump in `useGestureDispatcher` via `AffordanceHit.cursor`, which
1934
+ * `buildAffordanceAt` fills in from the region the walk landed on. */
1935
+ cursor?: CursorSpec;
1936
+ /** `'exclusive'` bars every binding whose target doesn't consult the
1937
+ * affordance. Read only when the affordance is composed into a
1938
+ * consumer-registered layer; kit chrome routes through
1939
+ * `buildAffordanceAt`, which reports `'shared'`. */
1940
+ strength?: 'exclusive' | 'shared';
1941
+ /** Which gestures an exclusive claim bars. Omitted bars all of them. */
1942
+ claimedKinds?: readonly ClaimableGesture[];
1943
+ /** Drag binding produced when this region is hit. Lazily called so
1944
+ * affordances don't pay binding-construction cost on every paint frame —
1945
+ * state snapshots (e.g., capturing per-leaf poses at click time) belong
1946
+ * inside `bind()`, not inside `regions()`. */
1947
+ bind(): AffordanceBinding<TScratch>;
1948
+ }
1949
+ /** Context passed to a region's `paint.kind === 'custom'` draw callback.
1950
+ * Provides both the world-space anchor (already transformed) and the
1951
+ * original local shape, for affordances that want to do additional
1952
+ * geometry themselves. */
1953
+ interface CustomPaintContext {
1954
+ /** World-space mapping of `shape`. For `point`, only `x`/`y` are set.
1955
+ * For `rect`, all four fields are set. */
1956
+ world: {
1957
+ x: number;
1958
+ y: number;
1959
+ width?: number;
1960
+ height?: number;
1961
+ };
1962
+ /** The original local shape (same object identity as `region.shape`). */
1963
+ local: AffordanceRegion['shape'];
1964
+ view: View;
1965
+ state: ChromeState;
1966
+ }
1967
+ /**
1968
+ * @experimental
1969
+ * Result of an affordance hit — what the region computed about itself.
1970
+ *
1971
+ * `initialScratch` is the payload: what the region already knows (which
1972
+ * corner, which target id) so the action that picks up the drag doesn't
1973
+ * re-derive it. `<SceneCanvas>` reads it out of the layer hit-test and packs
1974
+ * it into `AffordanceHit`, which flows to the matching action through
1975
+ * `InvocationCtx.drag.affordance`.
1976
+ *
1977
+ * This used to also carry a `drag: DragChannel` naming the handlers the
1978
+ * tool-routing dispatcher should wire up. Every implementation supplied a
1979
+ * no-op stub that claimed, because the real routing had already moved to
1980
+ * bindings; the field went with that dispatcher.
1981
+ */
1982
+ interface AffordanceBinding<TScratch = unknown> {
1983
+ initialScratch?: TScratch;
1984
+ }
1985
+ /**
1986
+ * The fields `buildAffordanceAt` lifts out of a region's `initialScratch`
1987
+ * when it turns a region hit into an `AffordanceHit`.
1988
+ *
1989
+ * Scratch is otherwise opaque — whatever the affordance wants to hand the
1990
+ * action that picks up the drag. These few names are the exception: they mean
1991
+ * the same thing to every affordance, and the actions that consume them
1992
+ * (`resizeAction`, `rotateAction`) read them off `AffordanceHit` rather than
1993
+ * out of scratch. An affordance that doesn't set them simply produces a hit
1994
+ * without those fields.
1995
+ */
1996
+ interface CommonAffordanceScratch {
1997
+ /** The node (or `MULTI_RESIZE_TARGET_ID`) this chrome acts on. Becomes
1998
+ * `AffordanceHit.targetIds`. */
1999
+ targetId?: string;
2000
+ /** For resize chrome: which corner stays pinned. Mirrors the kit's
2001
+ * `ResizeAnchor`, spelled inline so `affordances/` doesn't take a type
2002
+ * dependency on the gesture layer for one field. */
2003
+ anchor?: {
2004
+ x: 'min' | 'max' | 'free';
2005
+ y: 'min' | 'max' | 'free';
2006
+ };
2007
+ /** World-space invariant point of the transform — the fixed corner for a
2008
+ * resize, the pivot for a rotation. */
2009
+ fixedPoint?: {
2010
+ x: number;
2011
+ y: number;
2012
+ };
2013
+ }
2014
+ /**
2015
+ * What a **registered layer's** `hitTest` returns. Extends `AffordanceBinding`
2016
+ * so existing implementations keep typechecking; the added fields are how a
2017
+ * consumer's own chrome says the things kit chrome says through
2018
+ * `AffordanceRegion` — which cursor to show, and whether it owns the point
2019
+ * outright.
2020
+ */
2021
+ interface LayerHit<TScratch = unknown> extends AffordanceBinding<TScratch> {
2022
+ /** Cursor while the pointer is over this hit. Reaches the hover-cursor
2023
+ * pump as `AffordanceHit.cursor`, the same path kit chrome uses. */
2024
+ cursor?: CursorSpec;
2025
+ /** `'exclusive'` bars every binding whose target doesn't consult the
2026
+ * affordance. Omitted means `'shared'` — today's behavior. Same name and
2027
+ * meaning as `AffordanceHit.strength`, which it becomes. */
2028
+ strength?: 'exclusive' | 'shared';
2029
+ /** Which gestures an exclusive claim bars. Omitted bars all of them. */
2030
+ claimedKinds?: readonly ClaimableGesture[];
2031
+ }
2032
+
2033
+ /**
2034
+ * Canvas size in CSS pixels — passed to `draw` for layers that anchor to
2035
+ * canvas edges (e.g. the debug overlay's layer-list panel). The GL backend
2036
+ * supplies it explicitly so layers don't have to know about DPR.
2037
+ */
2038
+ interface Dims {
2039
+ width: number;
2040
+ height: number;
2041
+ }
2042
+ /**
2043
+ * What a layer's `draw` threw, and which layer threw it.
2044
+ *
2045
+ * A `draw` runs on the frame loop, so a throw that escapes it surfaces as an
2046
+ * uncaught `requestAnimationFrame` error on the window and takes the whole
2047
+ * frame with it — every other layer included. One broken layer painting
2048
+ * nothing, named in the console, is the lesser wrong.
2049
+ */
2050
+ interface LayerDrawFailure {
2051
+ layerId: string;
2052
+ error: unknown;
2053
+ }
2054
+ /**
2055
+ * Several consecutive layers composited as one.
2056
+ *
2057
+ * A layer's own `effects` run over that layer alone, which is the wrong
2058
+ * picture whenever a pass reads neighboring pixels: `blur(A over B)` is not
2059
+ * `blur(A) over blur(B)`, and it costs a buffer and a pass chain per layer. A
2060
+ * group draws its members into one buffer, runs one chain over it, and
2061
+ * composites the result back once.
2062
+ *
2063
+ * Membership is by `RenderLayer.id` — the same names `layerOrder` and
2064
+ * `layerVisibility` use, not the `layers` map's slot keys.
2065
+ *
2066
+ * Only *consecutive* members share a buffer, because anything drawn between
2067
+ * two members has to land between them. A group whose members are separated in
2068
+ * the render order is drawn as one bracket per run, with a warning: the
2069
+ * picture is right, the declaration almost certainly is not.
2070
+ *
2071
+ * This is a render-stack bracket, not a scene `ContainerNode` — it holds no
2072
+ * ids, survives no reload, and nothing in the scene knows about it.
2073
+ */
2074
+ interface LayerGroup {
2075
+ /** Names the group in warnings; not a layer id and never drawn. */
2076
+ id: string;
1779
2077
  /**
1780
- * Shorten each open subpath by this much at its start / end, in the same
1781
- * world units as the path. Stroke markers use this so a filled head is not
1782
- * speared by its own line; the caller resolves the distance, because this
1783
- * layer knows nothing about the marker registry.
2078
+ * Member layer ids. Order here is ignored — the render order decides.
2079
+ *
2080
+ * A name claims that layer and every layer under it in the `:` namespace, so
2081
+ * `'scene'` covers the `scene:<layerId>` layers a scene with declared layers
2082
+ * draws as — the same set `before`/`after: 'scene'` anchors against. The
2083
+ * separator is required: `'scene'` does not reach `scenery`. A name matching
2084
+ * no layer being drawn is warned about rather than ignored.
1784
2085
  */
1785
- startInset?: number;
1786
- endInset?: number;
2086
+ layers: readonly string[];
2087
+ /**
2088
+ * Passes over the group's combined pixels, in order. A thunk is re-read on
2089
+ * every frame, so an animating radius costs no React render; an array is
2090
+ * read once per frame either way.
2091
+ */
2092
+ effects?: readonly Effect[] | ((view: View, dims: Dims) => readonly Effect[]);
2093
+ /** Opacity applied to the group's composited result, not to each member. */
2094
+ alpha?: number;
2095
+ /** 4×5 color matrix (row-major, 20 numbers) applied to the composited
2096
+ * result. See `GroupDrawCommand.colorMatrix`. */
2097
+ colorMatrix?: number[];
1787
2098
  }
1788
- /** Resolve a stroke width to world units. A number is already world units;
1789
- * `{ px }` is screen pixels divided by the accumulated scale, so it holds its
1790
- * on-screen thickness as the view zooms. */
1791
- declare function resolveStrokeWidth(width: ScreenLength, scale: number): number;
2099
+ /** One layer's memoized output, keyed by layer id. Owned by the canvas that
2100
+ * calls `drawLayers`, not by `drawLayers` itself — the function is pure. */
2101
+ type LayerCommandCache = Map<string, {
2102
+ deps: readonly unknown[];
2103
+ cmds: DrawCommand[];
2104
+ }>;
1792
2105
  /**
1793
- * Build a triangle-mesh ribbon from a stroked Path.
2106
+ * A single named render sub-layer within a canvas renderer.
1794
2107
  *
1795
- * Supports:
1796
- * - cap: 'butt' | 'round' | 'square'
1797
- * - join: 'miter' | 'round' | 'bevel'
1798
- * - center alignment directly; RectPath inner/outer alignment via a
1799
- * pre-shifted rect; PolygonPath inner/outer alignment via stencil at the
1800
- * renderer level
1801
- * - dash splitting
2108
+ * @template TData - The data object passed to each draw call.
1802
2109
  */
1803
- declare function tessellateStroke(path: Path, stroke: Stroke, opts?: StrokeOptions): Mesh;
1804
-
2110
+ /** Something outside React whose changes a paint reads — a mode registry, a
2111
+ * scoping lookup. A notification repaints the canvas; the listener takes no
2112
+ * arguments and the returned function unsubscribes. */
2113
+ interface RedrawSource {
2114
+ subscribe(listener: () => void): () => void;
2115
+ }
2116
+ /** The `subscribe` for a layer that draws `sources`: it notifies whenever any
2117
+ * of them does. A thunk is read when the subscription is made. Every layer
2118
+ * that draws other layers declares this, so wrapping never silences what
2119
+ * repaints a source. */
2120
+ declare function subscribeToSources(sources: readonly {
2121
+ subscribe?: RedrawSource['subscribe'];
2122
+ }[] | (() => readonly {
2123
+ subscribe?: RedrawSource['subscribe'];
2124
+ }[])): RedrawSource['subscribe'];
2125
+ interface RenderLayer<TData> {
2126
+ /** Unique identifier used in visibility maps and ordering arrays. When a
2127
+ * cache is in use, an id must identify the same logical layer across
2128
+ * frames — reusing it for a different layer can serve cross-layer commands. */
2129
+ id: string;
2130
+ /** Human-readable name for UI toggles. */
2131
+ label: string;
2132
+ /**
2133
+ * Emit a DrawCommand tree for the GL backend to dispatch.
2134
+ *
2135
+ * For world-space layers (the default), emit commands in WORLD COORDS —
2136
+ * `drawLayers` automatically wraps them in `{ kind: 'group', transform:
2137
+ * viewToMat3(view), ... }` before handing them to the renderer. Do NOT
2138
+ * apply the view transform yourself.
2139
+ *
2140
+ * For screen-space layers (`space: 'screen'`), emit commands in CSS-pixel
2141
+ * coords directly; `drawLayers` passes them through unchanged. If part
2142
+ * of a screen-space layer's output needs to track the view, wrap that
2143
+ * subset manually with `viewToMat3(view)`.
2144
+ */
2145
+ draw: (data: TData, view: View, dims: Dims) => DrawCommand[];
2146
+ /**
2147
+ * Optional cache key. When present and a `LayerCommandCache` is supplied to
2148
+ * `drawLayers`, the layer's previous `DrawCommand[]` is reused as long as
2149
+ * every entry is `Object.is`-equal to the previous call's. A layer with no
2150
+ * `deps` rebuilds on every frame.
2151
+ *
2152
+ * **The returned commands must be treated as immutable.** A cached tree is
2153
+ * handed to the renderer again on later frames, so mutating a tree you
2154
+ * previously returned corrupts the cache silently rather than erroring.
2155
+ *
2156
+ * **Screen-space layers are not protected against a stale `view`/`dims`
2157
+ * the way world-space layers are** (see `space` below) — include them in
2158
+ * `deps` if `draw` reads them.
2159
+ */
2160
+ deps?: (data: TData, view: View, dims: Dims) => readonly unknown[];
2161
+ /**
2162
+ * Whether the layer is shown when no explicit visibility entry exists.
2163
+ * Defaults to `true` when absent.
2164
+ */
2165
+ defaultVisible?: boolean;
2166
+ /**
2167
+ * When true, the layer is always drawn regardless of the visibility map.
2168
+ * Useful for layers that must never be hidden (e.g. base grid).
2169
+ */
2170
+ alwaysOn?: boolean;
2171
+ /**
2172
+ * Coordinate space the layer draws in.
2173
+ *
2174
+ * - `'world'` (default): the layer's `draw` returns world-space commands;
2175
+ * `drawLayers` wraps them in a `kind: 'group'` with `viewToMat3(view)`
2176
+ * automatically.
2177
+ * - `'screen'`: the layer's `draw` returns screen-space (CSS-pixel)
2178
+ * commands; `drawLayers` passes them through unchanged. World-anchored
2179
+ * chrome inside a screen-space layer must call `worldToScreen` or wrap
2180
+ * the relevant subset with `viewToMat3(view)` manually.
2181
+ */
2182
+ space?: 'world' | 'screen';
2183
+ /**
2184
+ * Where the layer learns that state `draw` reads, outside the scene and the
2185
+ * props, has changed. The canvas painting it subscribes while the layer is
2186
+ * mounted and repaints on every notification, so a layer reading a mode
2187
+ * registry needs no consumer code to follow a mode switch.
2188
+ */
2189
+ subscribe?: RedrawSource['subscribe'];
2190
+ /**
2191
+ * Full-screen passes run over this layer's own pixels before it joins the
2192
+ * frame — a blur here blurs the world and leaves the HUD drawn above it
2193
+ * sharp, which is the thing a CSS `filter` on the `<canvas>` cannot do.
2194
+ *
2195
+ * Costs nothing while empty: the renderer allocates no offscreen buffer
2196
+ * until a layer actually declares one. See `GroupDrawCommand.effects` for
2197
+ * what a pass may read, and {@link LayerGroup} to run one chain over
2198
+ * several layers at once instead of one chain each.
2199
+ */
2200
+ effects?: readonly Effect[];
2201
+ /**
2202
+ * Optional hit-test for **consumer-attached** layers.
2203
+ *
2204
+ * Only layers registered through `CanvasExtensionApi.registerLayer` are
2205
+ * hit-tested: `hitTestExtras` walks them last-registered-first on
2206
+ * pointerdown, and `<SceneCanvas>` folds the result into its `affordanceAt`
2207
+ * thunk ahead of the kit's own selection chrome. First non-null result
2208
+ * wins; null means "I don't claim this hit, try the next layer."
2209
+ *
2210
+ * Layers that reach the draw stack some other way — a `Tool.overlay`, an
2211
+ * entry in the `layers` map — are painted but never hit-tested, so defining
2212
+ * `hitTest` on one has no effect. (The kit's own chrome doesn't need it: it
2213
+ * goes through `buildAffordanceAt`.)
2214
+ *
2215
+ * Coordinates are world-space. The `data` arg is the layer's
2216
+ * configured data slot (same as `draw`); `view` and `dims` mirror
2217
+ * `draw`'s arguments.
2218
+ */
2219
+ hitTest?: (worldX: number, worldY: number, data: TData, view: View, dims: Dims,
2220
+ /** Chrome-caps visibility predicate. When supplied, the layer must
2221
+ * not return a hit from any chrome element whose id reports
2222
+ * `false`. Absent → every element is hittable. */
2223
+ isVisible?: (id: string) => boolean) => LayerHit | null;
2224
+ /**
2225
+ * Called on every pointermove when no gesture is currently captured.
2226
+ * Lets layers (e.g. HUD widgets) track hover state without participating
2227
+ * in the drag pipeline. Coords are world-space; the layer is responsible
2228
+ * for any further conversion (e.g. world→screen for screen-space layers)
2229
+ * and for its own throttling.
2230
+ */
2231
+ onUncapturedMove?: (worldX: number, worldY: number, evt: PointerEvent, view: View, dims: Dims) => void;
2232
+ /**
2233
+ * Called when the cursor leaves the canvas element. Lets layers clear
2234
+ * any hover state they're holding.
2235
+ */
2236
+ onUncapturedLeave?: () => void;
2237
+ }
1805
2238
  /**
1806
- * Effects that ship with the kit.
2239
+ * Walk visible layers and concatenate their emitted DrawCommand arrays into
2240
+ * one flat list, ready to feed to `WeaselRenderer.render(commands)`.
1807
2241
  *
1808
- * Each is a function returning `Effect[]`, not a single `Effect`, because a
1809
- * separable kernel is genuinely two passes and hiding that behind one entry
1810
- * would make the cost invisible at the callsite:
2242
+ * Visibility resolution order:
2243
+ * 1. `alwaysOn` — always drawn, ignores visibility map.
2244
+ * 2. Explicit entry in `visibility` map — overrides default.
2245
+ * 3. `layer.defaultVisible` — falls back to `true` when absent.
1811
2246
  *
1812
- * effects={[...blur({ radius: 4 }), ...vignette({ amount: 0.6 })]}
2247
+ * Transform composition: world-space layers (the default; `space` unset or
2248
+ * `'world'`) have their commands wrapped in a `kind: 'group'` with
2249
+ * `viewToMat3(view)` before they reach the renderer. Screen-space layers
2250
+ * (`space: 'screen'`) pass through unchanged.
2251
+ *
2252
+ * A layer whose `draw` throws is dropped for the frame and reported through
2253
+ * `onLayerError` — the rest of the frame still paints.
2254
+ *
2255
+ * `groups` brackets runs of consecutive layers so they composite as one — see
2256
+ * `LayerGroup`. A layer named by no group is emitted exactly as it was before
2257
+ * groups existed, and a frame that declares none allocates nothing.
1813
2258
  */
1814
-
2259
+ declare function drawLayers<TData>(layers: RenderLayer<TData>[], data: TData, visibility: Record<string, boolean>, order: string[] | undefined, view: View | undefined, dims: Dims, cache?: LayerCommandCache, onLayerError?: (failure: LayerDrawFailure) => void, groups?: readonly LayerGroup[]): DrawCommand[];
1815
2260
  /**
1816
- * Gaussian blur, as a horizontal pass followed by a vertical one.
2261
+ * Resolve one layer's visibility: `alwaysOn` wins, then an explicit entry in
2262
+ * `visibility`, then `defaultVisible`, defaulting to shown.
2263
+ */
2264
+ declare function isLayerVisible<TData>(layer: RenderLayer<TData>, visibility: Record<string, boolean>): boolean;
2265
+ /**
2266
+ * Does this layer reach the screen at all — both gates, in the order
2267
+ * `drawLayers` applies them.
1817
2268
  *
1818
- * `radius` is in device pixels and is the distance of the outermost tap, not a
1819
- * standard deviation — 0 is a copy, and the falloff is the same nine-tap
1820
- * kernel at every radius, so a large one is a wide blur rather than a better
1821
- * one. Two passes at O(9) beat one at O(81) and look the same.
2269
+ * **A listed `order` is the whole list**, so omission from it drops a layer
2270
+ * that `visibility` would have shown, and `alwaysOn` does not rescue it.
2271
+ * Hit-testing asks this, not `isLayerVisible`: a layer that is not painted
2272
+ * but still claims pointer events is a pointer landing on nothing the user
2273
+ * can see.
1822
2274
  */
1823
- declare function blur({ radius }: {
1824
- radius: number;
1825
- }): Effect[];
2275
+ declare function isLayerPainted<TData>(layer: RenderLayer<TData>, visibility: Record<string, boolean>, order: string[] | undefined): boolean;
1826
2276
  /**
1827
- * Darken toward the corners. `amount` is how dark the corner gets (0..1) and
1828
- * `feather` how much of the radius the falloff occupies.
2277
+ * Draw one layer and put its commands in the space its `space` declares:
2278
+ * world-space output wrapped in a `viewToMat3(view)` group, screen-space
2279
+ * output passed through.
2280
+ *
2281
+ * Anything rendering layers through a view — the canvas itself, a viewport
2282
+ * node's inner pass — goes through here. A second copy of this rule that
2283
+ * forgets the wrap draws world content at raw world coords, which looks
2284
+ * plausible at the identity view and wrong everywhere else.
2285
+ *
2286
+ * A `draw` that throws yields no commands, and `onLayerError` is told which
2287
+ * layer it was. The layer's cache entry goes with it, so the next frame is a
2288
+ * real re-attempt rather than a stale tree served under fresh deps.
1829
2289
  */
1830
- declare function vignette({ amount, feather }: {
1831
- amount: number;
1832
- feather?: number;
1833
- }): Effect[];
2290
+ declare function drawOneLayer<TData>(layer: RenderLayer<TData>, data: TData, view: View, dims: Dims, cache?: LayerCommandCache, onLayerError?: (failure: LayerDrawFailure) => void): DrawCommand[];
1834
2291
 
1835
2292
  /** Per-axis limits on a view's position. Any side may be left open. */
1836
2293
  interface PanBounds {
@@ -2573,6 +3030,66 @@ declare function useViewAnimation(view: ViewChannel, animator?: Animator): ViewA
2573
3030
  * animator of its own, so the camera runs on exactly the one passed. */
2574
3031
  declare function useViewAnimationOn(view: ViewChannel, animator: Animator): ViewAnimationApi;
2575
3032
 
3033
+ /**
3034
+ * @experimental
3035
+ * PointerContext — the world-space position of the canvas pointer, and the
3036
+ * view it is over, refreshed on every `pointermove` and cleared on
3037
+ * `pointerleave`.
3038
+ *
3039
+ * It is an external store rather than React state: cursor moves fire dozens of
3040
+ * times per second, and a consumer that only reads on demand (paste at the
3041
+ * pointer) must not re-render for each one. Readers that do need to follow it
3042
+ * — a linked cursor — subscribe, or use `usePointerPosition()`.
3043
+ *
3044
+ * `<SceneCanvas>` publishes automatically, and defers to a provider already in
3045
+ * scope, so several surfaces under one provider share one pointer: a detached
3046
+ * minimap and its main canvas each see where the other's pointer is.
3047
+ */
3048
+
3049
+ /** @experimental World-space pointer position and the view it is over — a
3050
+ * view id, or `null` for a surface's own camera. `null` as a whole when the
3051
+ * pointer is over no publishing surface. */
3052
+ type PointerWorldPos = {
3053
+ worldX: number;
3054
+ worldY: number;
3055
+ viewId: string | null;
3056
+ } | null;
3057
+ /** @experimental */
3058
+ interface PointerContextValue {
3059
+ /** The latest position. */
3060
+ get(): PointerWorldPos;
3061
+ /** Publish a position. Subscribers hear only a changed value. */
3062
+ set(next: PointerWorldPos): void;
3063
+ /** Called after every change; returns the unsubscribe. */
3064
+ subscribe(fn: () => void): () => void;
3065
+ /** Bumps on every change. */
3066
+ getVersion(): number;
3067
+ /** `get()` as a stable thunk, for hooks taking a drop-point option. */
3068
+ readonly getDropPoint: () => PointerWorldPos;
3069
+ }
3070
+ /** @experimental A pointer store with no provider around it. */
3071
+ declare function createPointerStore(): PointerContextValue;
3072
+ /**
3073
+ * @experimental
3074
+ * Wrap the part of the React tree that should share one pointer. Usually at
3075
+ * the app root, alongside `<ActionsProvider>` and `<SelectionContextProvider>`.
3076
+ *
3077
+ * Most consumers don't need to mount this directly — `<SceneCanvas>` mounts
3078
+ * one when none is in scope. Mount it yourself when two surfaces should share
3079
+ * a pointer. Pass `store` to publish into one you hold elsewhere
3080
+ * (`createPointerStore()`).
3081
+ */
3082
+ declare function PointerContextProvider({ children, store }: {
3083
+ children: ReactNode;
3084
+ store?: PointerContextValue;
3085
+ }): ReactNode;
3086
+ /** @experimental The surrounding pointer store, or `null` when no provider is
3087
+ * in scope. */
3088
+ declare function usePointerContext(): PointerContextValue | null;
3089
+ /** @experimental The pointer, re-rendering the caller whenever it changes.
3090
+ * `null` outside a provider. */
3091
+ declare function usePointerPosition(): PointerWorldPos;
3092
+
2576
3093
  /**
2577
3094
  * Pose composition for hierarchical scene graphs.
2578
3095
  *
@@ -2842,6 +3359,33 @@ interface ContentHandlerEntry {
2842
3359
  /** Register a content handler. Returns a disposer that removes it. */
2843
3360
  declare function registerContentHandler(entry: ContentHandlerEntry): () => void;
2844
3361
 
3362
+ /**
3363
+ * The lifecycle the ongoing transform actions (`move`, `resize`, `rotate`)
3364
+ * share: what their committed batch is called in history, whether it is
3365
+ * recorded at all, and the callbacks fired as the gesture opens and closes.
3366
+ *
3367
+ * Move and rotate read it from their binding's params; resize reads it from
3368
+ * the `resizePolicy` dep, where the rest of its options already live.
3369
+ */
3370
+
3371
+ /** The lifecycle options, as a binding's params or the resize policy carry
3372
+ * them. */
3373
+ interface GestureLifecycleOptions {
3374
+ /** History label for the committed batch. Unset, the batch takes its first
3375
+ * op's label (a layout drop or a behavior names its own), else the
3376
+ * action's. */
3377
+ label?: string;
3378
+ /** Commit through `scene.untracked`: the edit lands, but no undo entry
3379
+ * records it and the consumer `applyOps` hook is bypassed. Unset, any
3380
+ * behavior's `defaultTransient: true` turns it on. */
3381
+ transient?: boolean;
3382
+ /** Fired once the gesture starts changing poses, with the ids it moves. */
3383
+ onGestureStart?(ids: string[]): void;
3384
+ /** Fired once per `onGestureStart`: `true` when the gesture wrote to the
3385
+ * document, `false` on cancel, abort, or a release with nothing to write. */
3386
+ onGestureEnd?(committed: boolean): void;
3387
+ }
3388
+
2845
3389
  /** Optional consumer seam: given a node and the affine `m` that a pose-transform
2846
3390
  * action applied to the node's POSE, return updated `data` with the node's
2847
3391
  * data-held geometry transformed by `m`, or `null` if this node has no
@@ -3237,7 +3781,7 @@ interface InsertDep {
3237
3781
  * The generic is erased to `unknown` at the schema entry; consumers cast at
3238
3782
  * the call site (mirrors the `scene` entry's convention).
3239
3783
  */
3240
- interface ResizePolicy<TPose> {
3784
+ interface ResizePolicy<TPose> extends GestureLifecycleOptions {
3241
3785
  /** Bounds-frame constraints. Constrained to `TPose extends Bounds` since
3242
3786
  * constraints read/write `{x,y,width,height}`. For non-rect TPose pass `[]`. */
3243
3787
  constraints: TPose extends Bounds ? BoundsConstraint<TPose>[] : never[];
@@ -3307,7 +3851,7 @@ interface ClipboardDep {
3307
3851
  /**
3308
3852
  * Consumer-supplied commit for the Slice action. `commit` receives the finite
3309
3853
  * slice segment (world coords); the consumer scans the scene, splits crossed
3310
- * paths via `splitPathByLine`, and applies the result as one undoable batch.
3854
+ * paths via `splitPathBySegment`, and applies the result as one undoable batch.
3311
3855
  */
3312
3856
  interface SliceDep {
3313
3857
  commit(a: Point2, b: Point2): void;
@@ -3444,7 +3988,7 @@ declare module '@weasel-js/routing' {
3444
3988
  * Slice dep — consumer-supplied commit for the Slice action.
3445
3989
  *
3446
3990
  * Receives the finite slice segment in world coordinates; the consumer
3447
- * scans the scene, splits crossed paths via `splitPathByLine`, and
3991
+ * scans the scene, splits crossed paths via `splitPathBySegment`, and
3448
3992
  * applies the result as one undoable batch.
3449
3993
  *
3450
3994
  * Optional: when absent, `sliceAction` is a no-op.
@@ -3497,7 +4041,103 @@ declare module '@weasel-js/routing' {
3497
4041
  * consults this seam (rotation lives on the pose, baked at render).
3498
4042
  */
3499
4043
  geometryProjection?: GeometryProjection;
4044
+ /**
4045
+ * The surface's own camera. Inside a `<CanvasView>`, `view` answers that
4046
+ * view's camera and this one does not change: an action bound in a view
4047
+ * that must move the main camera — a minimap's pan — reads this.
4048
+ */
4049
+ rootView: ViewApi;
4050
+ /**
4051
+ * The pointer store in scope: where the pointer is, in which view. Shared
4052
+ * by every surface under one `<PointerContextProvider>`.
4053
+ */
4054
+ pointer?: PointerContextValue;
3500
4055
  }
3501
4056
  }
3502
4057
 
3503
- export { type DerivedDep as $, type SliceDep as A, type VertexColorChannel as B, type CullRect as C, type DrawCommand as D, type Effect as E, type InsertExtras as F, type GlMat3 as G, type SerializedScene as H, IDENTITY_COLOR_MATRIX as I, type GeometryProjection as J, type ContentHandlerEntry as K, type SvgIngestOptions as L, type Mesh as M, type Node as N, type PanBounds as O, type PathDrawCommand as P, type Animator as Q, type RenderTarget as R, SPRITE_STRIDE as S, type TextDrawCommand as T, ColorOverrideRegistry as U, type ViewAnimationOptions as V, WeaselRenderer as W, type UseSceneOptions as X, type SceneRegistry as Y, type RegisteredOp as Z, type PoseOverrides as _, type GroupDrawCommand as a, type StaggerSpringPoseOptions as a$, type ViewportDims as a0, ShaderProgram as a1, type BooleansAdapter as a2, type UseAnimatorOptions as a3, type SpringPresetName as a4, type EasingSpec as a5, type AnimationHandle as a6, type SampledTrack as a7, type AddLayerSpec as a8, type AddNodeSpec as a9, type Keyframe as aA, type LassoSelectDep as aB, type LayerRecord as aC, type LayoutDep as aD, type LeafNode as aE, type LoopFactory as aF, type LoopOptions as aG, type NestedTimeline as aH, type NodeAtPointDep as aI, type PhysicsHandle as aJ, type PhysicsOptions as aK, type PoseAdapter as aL, type PoseClosure as aM, type PoseOverride as aN, RECT_POSE_COMPOSITION as aO, RIGID_POSE_COMPOSITION as aP, type ResizePolicy as aQ, SPRING_PRESETS as aR, type SerializedNode as aS, type SnapDep as aT, type SpringOptions as aU, type SpringPreset as aV, type StaggerBuilder as aW, type StaggerDelay as aX, type StaggerFactory as aY, type StaggerOptions as aZ, type StaggerPerItem as a_, type AnimateToBoundsOptions as aa, type AreaSelectDep as ab, type BezierEasing as ac, type BooleanOp as ad, type BooleanOpResult as ae, type ClipboardDep as af, type ClipboardIngestCtx as ag, type ColorOverride as ah, type ColorOverrideFn as ai, type ContainerNode as aj, type DecayLoopConfig as ak, type DecayOptions as al, EASINGS as am, type EasingFn as an, type EasingName as ao, type EditAnchorsDep as ap, type EventBooking as aq, type EventBookingHandle as ar, type EventTrack as as, type FitViewToBoundsOptions as at, IDENTITY_POSE_COMPOSITION as au, type IngestCtx as av, type IngestionDep as aw, type InsertDep as ax, type Interpolate as ay, type InterpolatorFactory as az, type ImageDrawCommand as b, resolveEasing as b$, type StaggerTweenOptions as b0, type SvgUnpacker as b1, type SystemLayerRecord as b2, type SystemLayerSpec as b3, type TextEditDep as b4, type TimelineClock as b5, type TimelineEvent as b6, type TimelineHandle as b7, type TimelineOptions as b8, type TimelineTrack as b9, easeInOutCirc as bA, easeInOutCubic as bB, easeInOutElastic as bC, easeInOutExpo as bD, easeInOutQuad as bE, easeInOutQuart as bF, easeInOutQuint as bG, easeInOutSine as bH, easeInQuad as bI, easeInQuart as bJ, easeInQuint as bK, easeInSine as bL, easeOut as bM, easeOutBack as bN, easeOutBounce as bO, easeOutCirc as bP, easeOutCubic as bQ, easeOutElastic as bR, easeOutExpo as bS, easeOutQuad as bT, easeOutQuart as bU, easeOutQuint as bV, easeOutSine as bW, fitViewToBounds as bX, linear as bY, rebaseLocalPose as bZ, registerContentHandler as b_, type Track as ba, type TweenLoopOptions as bb, type TweenOptions as bc, type UserLayerRecord as bd, VIEW_ANIMATION_KEY as be, type ViewAnimationApi as bf, type ViewApi as bg, type ViewChannel as bh, applyBooleanOp as bi, asNodeId as bj, composeRectPose as bk, composeRigidPose as bl, composeWorldPose as bm, cubicBezierEasing as bn, decomposeRectPose as bo, decomposeRigidPose as bp, easeIn as bq, easeInBack as br, easeInBounce as bs, easeInCirc as bt, easeInCubic as bu, easeInElastic as bv, easeInExpo as bw, easeInOut as bx, easeInOutBack as by, easeInOutBounce as bz, type ImageMinification as c, resolveStrokeWidth as c0, translateRectPose as c1, useDecayLoop as c2, useViewAnimation as c3, useViewAnimationOn as c4, worldPoseLookup as c5, ShaderCompileError as d, type ShaderDrawCommand as e, type ShaderProgramHandle as f, type ShaderUniform as g, type SolidPaint as h, type SpriteSheet as i, type SpritesDrawCommand as j, type StrokeOptions as k, type WeaselRendererOptions as l, blur as m, buildGradientRamp as n, cullDrawCommands as o, frameRect as p, mat3 as q, registerEffect as r, registerProgram as s, tessellateStroke as t, vignette as u, viewToMat3 as v, type Scene as w, type RectPose as x, type InertiaConfig as y, type PoseComposition as z };
4058
+ /**
4059
+ * The routing types that carry an overlay, bound to the kit's `RenderLayer`.
4060
+ *
4061
+ * `@weasel-js/routing` never reads an overlay — it collects the live ones and
4062
+ * hands them back in scope order — so it leaves the element type open. What a
4063
+ * weasel canvas draws is a `RenderLayer`, and every kit call site should see
4064
+ * that rather than `unknown`, so core binds the parameter once, here, and
4065
+ * re-exports these names under the ones they have always had.
4066
+ */
4067
+
4068
+ /** What a canvas overlay is, at this layer. */
4069
+ type Overlay = RenderLayer<unknown>;
4070
+ declare module '@weasel-js/routing' {
4071
+ interface OverlaySchema {
4072
+ overlay: RenderLayer<unknown>;
4073
+ }
4074
+ }
4075
+ type Contribution = Contribution$1<Overlay>;
4076
+ type ContributionChrome = ContributionChrome$1<Overlay>;
4077
+ type Tool<TScratch = unknown> = Tool$1<TScratch, Overlay>;
4078
+ type AnyTool = AnyToolOf<Overlay>;
4079
+ type ToolDef<TScratch = void> = ToolDef$1<TScratch, Overlay>;
4080
+ type ToolsApi = ToolsApi$1<Overlay>;
4081
+ type UseToolsOptions = UseToolsOptions$1<Overlay>;
4082
+ declare const useTools: (opts: UseToolsOptions) => ToolsApi;
4083
+
4084
+ /** Options for stroke tessellation. */
4085
+ interface StrokeOptions {
4086
+ flattenTolerance?: number;
4087
+ /**
4088
+ * Shorten each open subpath by this much at its start / end, in the same
4089
+ * world units as the path. Stroke markers use this so a filled head is not
4090
+ * speared by its own line; the caller resolves the distance, because this
4091
+ * layer knows nothing about the marker registry.
4092
+ */
4093
+ startInset?: number;
4094
+ endInset?: number;
4095
+ }
4096
+ /** Resolve a stroke width to world units. A number is already world units;
4097
+ * `{ px }` is screen pixels divided by the accumulated scale, so it holds its
4098
+ * on-screen thickness as the view zooms. */
4099
+ declare function resolveStrokeWidth(width: ScreenLength, scale: number): number;
4100
+ /**
4101
+ * Build a triangle-mesh ribbon from a stroked Path.
4102
+ *
4103
+ * Supports:
4104
+ * - cap: 'butt' | 'round' | 'square'
4105
+ * - join: 'miter' | 'round' | 'bevel'
4106
+ * - center alignment directly; RectPath inner/outer alignment via a
4107
+ * pre-shifted rect; PolygonPath inner/outer alignment via stencil at the
4108
+ * renderer level
4109
+ * - dash splitting
4110
+ */
4111
+ declare function tessellateStroke(path: Path, stroke: Stroke, opts?: StrokeOptions): Mesh;
4112
+
4113
+ /**
4114
+ * Effects that ship with the kit.
4115
+ *
4116
+ * Each is a function returning `Effect[]`, not a single `Effect`, because a
4117
+ * separable kernel is genuinely two passes and hiding that behind one entry
4118
+ * would make the cost invisible at the callsite:
4119
+ *
4120
+ * effects={[...blur({ radius: 4 }), ...vignette({ amount: 0.6 })]}
4121
+ */
4122
+
4123
+ /**
4124
+ * Gaussian blur, as a horizontal pass followed by a vertical one.
4125
+ *
4126
+ * `radius` is in device pixels and is the distance of the outermost tap, not a
4127
+ * standard deviation — 0 is a copy, and the falloff is the same nine-tap
4128
+ * kernel at every radius, so a large one is a wide blur rather than a better
4129
+ * one. Two passes at O(9) beat one at O(81) and look the same.
4130
+ */
4131
+ declare function blur({ radius }: {
4132
+ radius: number;
4133
+ }): Effect[];
4134
+ /**
4135
+ * Darken toward the corners. `amount` is how dark the corner gets (0..1) and
4136
+ * `feather` how much of the radius the falloff occupies.
4137
+ */
4138
+ declare function vignette({ amount, feather }: {
4139
+ amount: number;
4140
+ feather?: number;
4141
+ }): Effect[];
4142
+
4143
+ export { type InsertExtras as $, type Scene as A, type RectPose as B, type CullRect as C, type DrawCommand as D, type Effect as E, type InertiaConfig as F, type GlMat3 as G, type GestureLifecycleOptions as H, IDENTITY_COLOR_MATRIX as I, type PoseComposition as J, type SliceDep as K, type ToolsApi as L, type Mesh as M, type Node as N, type Tool as O, type PathDrawCommand as P, type Contribution as Q, type RenderTarget as R, SPRITE_STRIDE as S, type TextDrawCommand as T, type LayerHit as U, type ViewAnimationOptions as V, WeaselRenderer as W, type ChromeState as X, type VertexColorChannel as Y, type RedrawSource as Z, type LayerGroup as _, type GroupDrawCommand as a, type LoopFactory as a$, type SerializedScene as a0, type GeometryProjection as a1, type ContentHandlerEntry as a2, type SvgIngestOptions as a3, type AnyTool as a4, type PanBounds as a5, type Animator as a6, ColorOverrideRegistry as a7, type UseSceneOptions as a8, type SceneRegistry as a9, type ColorOverrideFn as aA, type ContainerNode as aB, type ContributionChrome as aC, type CustomPaintContext as aD, type DecayLoopConfig as aE, type DecayOptions as aF, EASINGS as aG, type EasingFn as aH, type EasingName as aI, type EditAnchorsDep as aJ, type EventBooking as aK, type EventBookingHandle as aL, type EventTrack as aM, type FitViewToBoundsOptions as aN, IDENTITY_POSE_COMPOSITION as aO, type IngestCtx as aP, type IngestionDep as aQ, type InsertDep as aR, type Interpolate as aS, type InterpolatorFactory as aT, type Keyframe as aU, type LassoSelectDep as aV, type LayerCommandCache as aW, type LayerDrawFailure as aX, type LayerRecord as aY, type LayoutDep as aZ, type LeafNode as a_, type RegisteredOp as aa, type PoseOverrides as ab, type DerivedDep as ac, type ViewportDims as ad, type ViewApi as ae, type Affordance as af, type AffordanceRegion as ag, type AffordanceBinding as ah, type CommonAffordanceScratch as ai, ShaderProgram as aj, type BooleansAdapter as ak, type UseAnimatorOptions as al, type SpringPresetName as am, type EasingSpec as an, type AnimationHandle as ao, type SampledTrack as ap, type AddLayerSpec as aq, type AddNodeSpec as ar, type AnimateToBoundsOptions as as, type AreaSelectDep as at, type BezierEasing as au, type BooleanOp as av, type BooleanOpResult as aw, type ClipboardDep as ax, type ClipboardIngestCtx as ay, type ColorOverride as az, type ImageDrawCommand as b, easeInOutBack as b$, type LoopOptions as b0, type NestedTimeline as b1, type NodeAtPointDep as b2, type PhysicsHandle as b3, type PhysicsOptions as b4, PointerContextProvider as b5, type PointerContextValue as b6, type PointerWorldPos as b7, type PoseAdapter as b8, type PoseClosure as b9, type Track as bA, type TweenLoopOptions as bB, type TweenOptions as bC, type UseToolsOptions as bD, type UserLayerRecord as bE, VIEW_ANIMATION_KEY as bF, type ViewAnimationApi as bG, type ViewChannel as bH, applyBooleanOp as bI, asNodeId as bJ, composeRectPose as bK, composeRigidPose as bL, composeWorldPose as bM, createPointerStore as bN, cubicBezierEasing as bO, decomposeRectPose as bP, decomposeRigidPose as bQ, drawLayers as bR, drawOneLayer as bS, easeIn as bT, easeInBack as bU, easeInBounce as bV, easeInCirc as bW, easeInCubic as bX, easeInElastic as bY, easeInExpo as bZ, easeInOut as b_, type PoseOverride as ba, RECT_POSE_COMPOSITION as bb, RIGID_POSE_COMPOSITION as bc, type ResizePolicy as bd, SPRING_PRESETS as be, type SerializedNode as bf, type SnapDep as bg, type SpringOptions as bh, type SpringPreset as bi, type StaggerBuilder as bj, type StaggerDelay as bk, type StaggerFactory as bl, type StaggerOptions as bm, type StaggerPerItem as bn, type StaggerSpringPoseOptions as bo, type StaggerTweenOptions as bp, type SvgUnpacker as bq, type SystemLayerRecord as br, type SystemLayerSpec as bs, type TextEditDep as bt, type TimelineClock as bu, type TimelineEvent as bv, type TimelineHandle as bw, type TimelineOptions as bx, type TimelineTrack as by, type ToolDef as bz, type ImageMinification as c, easeInOutBounce as c0, easeInOutCirc as c1, easeInOutCubic as c2, easeInOutElastic as c3, easeInOutExpo as c4, easeInOutQuad as c5, easeInOutQuart as c6, easeInOutQuint as c7, easeInOutSine as c8, easeInQuad as c9, usePointerPosition as cA, useTools as cB, useViewAnimation as cC, useViewAnimationOn as cD, worldPoseLookup as cE, easeInQuart as ca, easeInQuint as cb, easeInSine as cc, easeOut as cd, easeOutBack as ce, easeOutBounce as cf, easeOutCirc as cg, easeOutCubic as ch, easeOutElastic as ci, easeOutExpo as cj, easeOutQuad as ck, easeOutQuart as cl, easeOutQuint as cm, easeOutSine as cn, fitViewToBounds as co, isLayerPainted as cp, isLayerVisible as cq, linear as cr, rebaseLocalPose as cs, registerContentHandler as ct, resolveEasing as cu, resolveStrokeWidth as cv, subscribeToSources as cw, translateRectPose as cx, useDecayLoop as cy, usePointerContext as cz, type ProgramSource as d, ShaderCompileError as e, type ShaderDrawCommand as f, type ShaderProgramHandle as g, type ShaderUniform as h, type SolidPaint as i, type SpriteSheet as j, type SpritesDrawCommand as k, type StrokeOptions as l, type WeaselRendererOptions as m, blur as n, buildGradientRamp as o, cullDrawCommands as p, frameRect as q, mat3 as r, programSourceRegistry as s, registerEffect as t, registerProgram as u, tessellateStroke as v, viewToMat3 as w, vignette as x, type RenderLayer as y, type Dims as z };