@weasel-js/core 1.8.1 → 1.9.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 (129) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +9 -5
  3. package/dist/{builtins-CMEh6-Oc.d.ts → builtins-CQcvcLXh.d.ts} +98 -31
  4. package/dist/canvas/DrawCanvas.js +33 -33
  5. package/dist/canvas/DrawCanvas.js.map +1 -1
  6. package/dist/canvas/MinimapCanvas.js +29 -29
  7. package/dist/canvas/MinimapCanvas.js.map +1 -1
  8. package/dist/canvas/NodeShape.js +63 -54
  9. package/dist/canvas/NodeShape.js.map +1 -1
  10. package/dist/canvas/SceneCanvas/features.js +26 -5
  11. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  12. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +3 -2
  13. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  14. package/dist/canvas/SceneCanvas.js +526 -529
  15. package/dist/canvas/SceneCanvas.js.map +1 -1
  16. package/dist/canvas/SceneViewCanvas.js +35 -35
  17. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  18. package/dist/canvas/defaultDrawOne.js +6 -1
  19. package/dist/canvas/defaultDrawOne.js.map +1 -1
  20. package/dist/canvas/pickWalk.js.map +1 -1
  21. package/dist/canvas/sceneAdapter.js.map +1 -1
  22. package/dist/canvas/useHitObserver.js +23 -0
  23. package/dist/canvas/useHitObserver.js.map +1 -0
  24. package/dist/canvas/useHostAnchor.js.map +1 -1
  25. package/dist/core/device/useDeviceProfile.js.map +1 -1
  26. package/dist/core/scene/derivedPath.js.map +1 -1
  27. package/dist/core/scene/effectivePose.js.map +1 -1
  28. package/dist/core/scene/kitRegistry.js.map +1 -1
  29. package/dist/core/scene/scene.js.map +1 -1
  30. package/dist/core/scene/types.js.map +1 -1
  31. package/dist/core/scene/useScene.js.map +1 -1
  32. package/dist/core/viewport/fitViewToBounds.js +3 -3
  33. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  34. package/dist/core/viewport/screenSlop.js +8 -2
  35. package/dist/core/viewport/screenSlop.js.map +1 -1
  36. package/dist/features/minimap/actions.js.map +1 -1
  37. package/dist/features/paths/markerCommands.js +95 -63
  38. package/dist/features/paths/markerCommands.js.map +1 -1
  39. package/dist/features/paths/tessellate/dash.js +52 -0
  40. package/dist/features/paths/tessellate/dash.js.map +1 -0
  41. package/dist/features/paths/tessellate/insets.js +32 -0
  42. package/dist/features/paths/tessellate/insets.js.map +1 -0
  43. package/dist/features/paths/tessellate/metric.js +72 -0
  44. package/dist/features/paths/tessellate/metric.js.map +1 -0
  45. package/dist/features/paths/tessellate/stroke.js +74 -134
  46. package/dist/features/paths/tessellate/stroke.js.map +1 -1
  47. package/dist/features/paths/tessellate/vertexWidths.js +32 -0
  48. package/dist/features/paths/tessellate/vertexWidths.js.map +1 -0
  49. package/dist/features/pointer/PointerContext.js +2 -2
  50. package/dist/features/pointer/PointerContext.js.map +1 -1
  51. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  52. package/dist/features/text/useTextEdit.js +86 -84
  53. package/dist/features/text/useTextEdit.js.map +1 -1
  54. package/dist/index.d.ts +78 -39
  55. package/dist/index.js +148 -148
  56. package/dist/interactions/actions/defaults/align.js.map +1 -1
  57. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  58. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  59. package/dist/interactions/actions/defaults/booleans.js.map +1 -1
  60. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  61. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  62. package/dist/interactions/actions/defaults/clipboard.js.map +1 -1
  63. package/dist/interactions/actions/defaults/clone.js.map +1 -1
  64. package/dist/interactions/actions/defaults/createOutlines.js +1 -1
  65. package/dist/interactions/actions/defaults/createOutlines.js.map +1 -1
  66. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  67. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  68. package/dist/interactions/actions/defaults/distribute.js.map +1 -1
  69. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  70. package/dist/interactions/actions/defaults/editAnchors.js.map +1 -1
  71. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  72. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  73. package/dist/interactions/actions/defaults/escape.js +1 -1
  74. package/dist/interactions/actions/defaults/escape.js.map +1 -1
  75. package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
  76. package/dist/interactions/actions/defaults/flip.js.map +1 -1
  77. package/dist/interactions/actions/defaults/group.js.map +1 -1
  78. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  79. package/dist/interactions/actions/defaults/insert.js.map +1 -1
  80. package/dist/interactions/actions/defaults/insertPathAnchor.js +1 -1
  81. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  82. package/dist/interactions/actions/defaults/lassoSelect.js.map +1 -1
  83. package/dist/interactions/actions/defaults/move.js.map +1 -1
  84. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  85. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  86. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  87. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  88. package/dist/interactions/actions/defaults/resize.js.map +1 -1
  89. package/dist/interactions/actions/defaults/rotate.js.map +1 -1
  90. package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
  91. package/dist/interactions/actions/defaults/slice.js.map +1 -1
  92. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  93. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  94. package/dist/interactions/actions/defaults/undoRedo.js +1 -1
  95. package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
  96. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  97. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  98. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  99. package/dist/interactions/actions/planeInput.js.map +1 -1
  100. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  101. package/dist/{registerProgram-ateHDGjw.d.ts → registerProgram-BMZRDgrh.d.ts} +4 -0
  102. package/dist/renderer/cache/markerCommandCache.js +46 -42
  103. package/dist/renderer/cache/markerCommandCache.js.map +1 -1
  104. package/dist/renderer/cache/outlineStrokeMeshCache.js +30 -25
  105. package/dist/renderer/cache/outlineStrokeMeshCache.js.map +1 -1
  106. package/dist/renderer/cache/strokeMeshCache.js +42 -31
  107. package/dist/renderer/cache/strokeMeshCache.js.map +1 -1
  108. package/dist/renderer/cullDrawCommands.js +32 -31
  109. package/dist/renderer/cullDrawCommands.js.map +1 -1
  110. package/dist/renderer/draw.js +315 -362
  111. package/dist/renderer/draw.js.map +1 -1
  112. package/dist/renderer/glyphOutlineMesh.js +67 -0
  113. package/dist/renderer/glyphOutlineMesh.js.map +1 -0
  114. package/dist/renderer/math/mat3.js +8 -3
  115. package/dist/renderer/math/mat3.js.map +1 -1
  116. package/dist/renderer/strokeLengths.js +50 -0
  117. package/dist/renderer/strokeLengths.js.map +1 -0
  118. package/dist/renderer.d.ts +2 -2
  119. package/dist/{test-seams-fYf6m5pu.d.ts → test-seams-CuIxe0xY.d.ts} +1 -1
  120. package/dist/test-seams.d.ts +2 -2
  121. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  122. package/dist/tools/builtin/pen/usePenTool.js +1 -1
  123. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  124. package/dist/tools/builtin/select/selectionContributions.js +43 -23
  125. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  126. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  127. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  128. package/dist/version.js +1 -1
  129. package/package.json +17 -17
@@ -3,13 +3,13 @@ import { AUTO_POSE_DESCRIPTOR as t } from "../interactions/actions/resize/autoPo
3
3
  import { usePointerContext as n, usePointerPosition as r } from "../features/pointer/PointerContext.js";
4
4
  import { PointerProviderIfRoot as i } from "./SceneCanvas/PointerProviderIfRoot.js";
5
5
  import { accentColorOf as a } from "./accentColor.js";
6
- import { SceneViewCanvas as ee } from "./SceneViewCanvas.js";
7
- import { MINIMAP_CENTER as o, MINIMAP_PAN as s, minimapCenterAction as c, minimapPanAction as l } from "../features/minimap/actions.js";
8
- import { createLinkedCursorLayer as u } from "../features/minimap/layers.js";
9
- import { computeFitView as d, computeIndicatorCommand as f } from "./minimapMath.js";
10
- import { useCallback as p, useEffect as m, useMemo as h, useRef as g, useSyncExternalStore as _ } from "react";
11
- import { useLatest as v } from "@weasel-js/react";
12
- import { ActionsProvider as y, ActiveToolContextProvider as b, DepRegistryProvider as x, useActionsRegistry as S, useDepSource as C, useGestureDispatcher as te } from "@weasel-js/routing/react";
6
+ import { SceneViewCanvas as o } from "./SceneViewCanvas.js";
7
+ import { MINIMAP_CENTER as s, MINIMAP_PAN as c, minimapCenterAction as l, minimapPanAction as u } from "../features/minimap/actions.js";
8
+ import { createLinkedCursorLayer as d } from "../features/minimap/layers.js";
9
+ import { computeFitView as f, computeIndicatorCommand as p } from "./minimapMath.js";
10
+ import { useCallback as m, useEffect as h, useMemo as g, useRef as ee, useSyncExternalStore as te } from "react";
11
+ import { assignRef as _, useLatest as v } from "@weasel-js/react";
12
+ import { ActionsProvider as y, ActiveToolContextProvider as b, DepRegistryProvider as x, useActionsRegistry as S, useDepSource as C, useGestureDispatcher as ne } from "@weasel-js/routing/react";
13
13
  import { jsx as w } from "react/jsx-runtime";
14
14
  //#region src/canvas/MinimapCanvas.tsx
15
15
  var T = {
@@ -17,10 +17,10 @@ var T = {
17
17
  eligibility: { always: !0 },
18
18
  bindings: [{
19
19
  spec: { kind: "pointerDown" },
20
- actionId: o
20
+ actionId: s
21
21
  }, {
22
22
  spec: { kind: "drag" },
23
- actionId: s
23
+ actionId: c
24
24
  }]
25
25
  }, E = /* @__PURE__ */ new Map([[T.id, T]]), D = {
26
26
  wheel: !1,
@@ -29,21 +29,21 @@ var T = {
29
29
  ingest: !1
30
30
  };
31
31
  function O(i) {
32
- let { scene: o, mainView: s, mainViewDims: y, onMainViewChange: b, width: x, height: T, drawOne: O, alphaFor: k, layerVisibility: A, layerOrder: j, animator: ne, fit: M = "scene", poseDescriptor: N, indicatorStyle: P, className: F, canvasRef: I, id: L = "minimap" } = i, R = e(s), z = _(o.subscribe, o.getVersion, o.getVersion), B = N ?? t, V = h(() => d(o, {
32
+ let { scene: s, mainView: c, mainViewDims: y, onMainViewChange: b, width: x, height: T, drawOne: O, alphaFor: k, layerVisibility: A, layerOrder: j, animator: M, fit: N = "scene", poseDescriptor: re, indicatorStyle: P, className: F, canvasRef: I, id: L = "minimap" } = i, R = e(c), z = te(s.subscribe, s.getVersion, s.getVersion), B = re ?? t, V = g(() => f(s, {
33
33
  width: x,
34
34
  height: T
35
- }, M, B), [
36
- o,
35
+ }, N, B), [
36
+ s,
37
37
  z,
38
38
  x,
39
39
  T,
40
- M,
40
+ N,
41
41
  B
42
- ]), H = h(() => f(R, y, P), [
42
+ ]), H = g(() => p(R, y, P), [
43
43
  R,
44
44
  y,
45
45
  P
46
- ]), U = g(null), W = v(R), G = v(y), K = v(b), q = v(V), J = h(() => ({
46
+ ]), U = ee(null), W = v(R), G = v(y), K = v(b), q = v(V), J = g(() => ({
47
47
  get: () => W.current,
48
48
  set: (e) => K.current(e),
49
49
  hostSize: () => G.current
@@ -54,21 +54,21 @@ function O(i) {
54
54
  ]);
55
55
  C("rootView", () => J);
56
56
  let Y = S();
57
- m(() => {
57
+ h(() => {
58
58
  if (!Y) return;
59
- let e = [Y.register(c()), Y.register(l())];
59
+ let e = [Y.register(l()), Y.register(u())];
60
60
  return () => {
61
61
  for (let t of e) t();
62
62
  };
63
63
  }, [Y]);
64
- let X = p((e, t) => {
64
+ let X = m((e, t) => {
65
65
  let n = U.current?.getBoundingClientRect(), r = q.current;
66
66
  return {
67
67
  x: r.x + (e - (n?.left ?? 0)) / r.scale.x,
68
68
  y: r.y + (t - (n?.top ?? 0)) / r.scale.y
69
69
  };
70
70
  }, [q]);
71
- te({
71
+ ne({
72
72
  canvasRef: U,
73
73
  actions: Y,
74
74
  entriesById: E,
@@ -77,7 +77,7 @@ function O(i) {
77
77
  channels: D
78
78
  });
79
79
  let Z = n();
80
- m(() => {
80
+ h(() => {
81
81
  let e = U.current;
82
82
  if (!e || !Z) return;
83
83
  let t = (e) => {
@@ -98,11 +98,11 @@ function O(i) {
98
98
  X,
99
99
  L
100
100
  ]);
101
- let Q = r(), $ = h(() => u({
101
+ let Q = r(), $ = g(() => d({
102
102
  id: `${L}.cursor`,
103
103
  pointer: () => Q,
104
104
  color: () => a(U.current)
105
- }), [L, Q]), re = h(() => [H, ...$.draw({ viewId: L }, V, {
105
+ }), [L, Q]), ie = g(() => [H, ...$.draw({ viewId: L }, V, {
106
106
  width: x,
107
107
  height: T
108
108
  })], [
@@ -112,22 +112,22 @@ function O(i) {
112
112
  V,
113
113
  x,
114
114
  T
115
- ]), ie = p((e) => {
116
- U.current = e, typeof I == "function" ? I(e) : I && typeof I == "object" && (I.current = e);
115
+ ]), ae = m((e) => {
116
+ U.current = e, _(I, e);
117
117
  }, [I]);
118
- return /* @__PURE__ */ w(ee, {
119
- scene: o,
118
+ return /* @__PURE__ */ w(o, {
119
+ scene: s,
120
120
  view: V,
121
121
  width: x,
122
122
  height: T,
123
123
  drawOne: O,
124
- extraCommands: re,
124
+ extraCommands: ie,
125
125
  alphaFor: k,
126
126
  layerVisibility: A,
127
127
  layerOrder: j,
128
- animator: ne,
128
+ animator: M,
129
129
  className: F,
130
- canvasRef: ie
130
+ canvasRef: ae
131
131
  });
132
132
  }
133
133
  function k(e) {
@@ -1 +1 @@
1
- {"version":3,"file":"MinimapCanvas.js","names":["MINIMAP_INPUT","MINIMAP_CENTER","MINIMAP_PAN","TOOLS_BY_ID","CHANNELS","MinimapCanvasInner","mainViewProp","props","mainView","normalizeView","sceneVersion","useSyncExternalStore","scene","descriptor","poseDescriptor","AUTO_POSE_DESCRIPTOR","fitView","useMemo","computeFitView","fit","width","height","indicatorCmd","computeIndicatorCommand","mainViewDims","indicatorStyle","localCanvasRef","useRef","mainViewRef","useLatest","mainViewDimsRef","onMainViewChangeRef","onMainViewChange","fitViewRef","rootView","v","actions","useActionsRegistry","off","minimapCenterAction","minimapPanAction","u","clientToWorld","useCallback","rect","fv","cx","cy","pointerStore","usePointerContext","el","onMove","w","id","onLeave","pointer","usePointerPosition","cursorLayer","createLinkedCursorLayer","accentColorOf","extraCommands","setCanvasRef","canvasRef","SceneViewCanvas","MinimapCanvas","DepRegistryProvider","ActionsProvider","ActiveToolContextProvider","PointerProviderIfRoot"],"sources":["../../src/canvas/MinimapCanvas.tsx"],"sourcesContent":["/**\n * `<MinimapCanvas>` — opinionated minimap on a canvas of its own, built on\n * `<SceneViewCanvas>`.\n *\n * Renders the same `scene` the main canvas is showing, through a derived\n * \"fit\" view, and overlays a dashed visible-window indicator showing where\n * the main canvas is currently looking. Press anywhere in the minimap to\n * recenter the main view on that world point; drag to pan continuously.\n *\n * Input runs on a dispatcher of its own, through the same `minimap.center` /\n * `minimap.pan` actions the in-surface minimap (`createMinimapContribution`)\n * binds. It publishes its pointer into the pointer store in scope, and draws a\n * crosshair wherever that store says the pointer is on another surface — put\n * one `<PointerContextProvider>` around it and the main canvas for linked\n * cursors both ways.\n */\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\nimport type { Ref } from 'react';\nimport {\n ActionsProvider,\n ActiveToolContextProvider,\n DepRegistryProvider,\n useActionsRegistry,\n useDepSource,\n useGestureDispatcher,\n} from '@weasel-js/routing/react';\nimport { useLatest } from '@weasel-js/react';\nimport type { Tool } from '@weasel-js/routing';\nimport { PointerProviderIfRoot } from './SceneCanvas/PointerProviderIfRoot';\nimport { usePointerContext, usePointerPosition } from 'features/pointer/PointerContext';\nimport {\n MINIMAP_CENTER, MINIMAP_PAN, minimapCenterAction, minimapPanAction,\n} from 'features/minimap/actions';\nimport { createLinkedCursorLayer } from 'features/minimap/layers';\nimport type { ViewApi } from 'interactions/actions/depSchema';\nimport { SceneViewCanvas } from './SceneViewCanvas';\nimport {\n computeFitView,\n computeIndicatorCommand,\n} from './minimapMath';\nimport type { IndicatorStyle, MinimapFit } from './minimapMath';\nimport type { SceneViewDrawOne, SceneViewLayers } from './sceneViewRender';\nimport type { DrawCommand } from '../renderer/DrawCommand';\nimport { normalizeView, type View } from '../core/viewport/view';\nimport type { Scene } from '../core/scene/types';\nimport type { PoseDescriptor } from '../core/geometry/poseDescriptor';\nimport type { Animator } from '../animation/types';\nimport { AUTO_POSE_DESCRIPTOR } from '../interactions/actions/resize/autoPoseDescriptor';\nimport { accentColorOf } from './accentColor';\n\n/** Props for `<MinimapCanvas>`. */\nexport interface MinimapCanvasProps<TData, TLayer extends string, TPose> {\n /** Same scene the main canvas is rendering. */\n scene: Scene<TData, TLayer, TPose>;\n /** Main canvas's view — used to position the visible-window indicator and\n * to preserve `scale` when the minimap recenters. */\n mainView: View;\n /** Main canvas's CSS-pixel dims. Used to compute the visible-window rect\n * and the recenter offset. */\n mainViewDims: { width: number; height: number };\n /** Setter called on click (single recenter) and during drag (continuous\n * recenter). Receives a `View` with the same `scale` as `mainView` and\n * `(x, y)` shifted so the pointer's world point lands at the main\n * canvas's center. */\n onMainViewChange: (next: View) => void;\n /** Minimap's own CSS-pixel dims. */\n width: number;\n height: number;\n /** Consumer's draw callback. Applied through the derived fit view; same\n * signature as `<SceneCanvas>`'s scene-slot `drawOne` so the consumer\n * can reuse it (typically simplified — just colored AABBs). */\n drawOne: SceneViewDrawOne<TData, TLayer, TPose>;\n /** Fit policy. Defaults to `\"scene\"` (AABB union of leaf poses). See\n * `MinimapFit` for the full shape.\n *\n * Framing is derived from **document** poses, not `scene.overrides` — a\n * node moved by an override paints where the override puts it, outside the\n * frame if it goes there, rather than making the whole minimap rescale on\n * every frame of a drag or a settle. */\n fit?: MinimapFit<TData, TLayer, TPose>;\n /** How to read poses. Default `AUTO_POSE_DESCRIPTOR`. */\n poseDescriptor?: PoseDescriptor<TPose>;\n /** Optional per-id alpha multiplier, mirroring `<SceneCanvas>`'s scene-slot\n * `alphaFor`. Pass the same function the main canvas uses so a\n * scoping-dim treatment shows up in the minimap too. */\n alphaFor?: (id: string) => number;\n /** Hide scene layers in the minimap, keyed `scene:<layerId>` as on\n * `<SceneCanvas>` — pass the main canvas's map so both show the same set. */\n layerVisibility?: SceneViewLayers['layerVisibility'];\n /** Paint order for the minimap, keyed as `layerVisibility`. */\n layerOrder?: SceneViewLayers['layerOrder'];\n /** Optional animator: the minimap repaints on its ticks and paints its\n * `colorOverrides`. Pass the main canvas's animator so both show the same\n * colors. */\n animator?: Animator;\n /** Visual tuning of the indicator stroke. */\n indicatorStyle?: IndicatorStyle;\n /** CSS class for sizing / positioning the canvas. */\n className?: string;\n /** Forwarded ref to the underlying `<canvas>`. */\n canvasRef?: Ref<HTMLCanvasElement>;\n /** The view id this minimap publishes its pointer under. Default\n * `'minimap'`. */\n id?: string;\n}\n\n/** The minimap's own bindings. Unscoped: this dispatcher routes no views, so\n * every input on it is the minimap's. */\nconst MINIMAP_INPUT: Tool = {\n id: 'minimap',\n eligibility: { always: true },\n bindings: [\n { spec: { kind: 'pointerDown' }, actionId: MINIMAP_CENTER },\n { spec: { kind: 'drag' }, actionId: MINIMAP_PAN },\n ],\n};\nconst TOOLS_BY_ID: ReadonlyMap<string, Tool> = new Map([[MINIMAP_INPUT.id, MINIMAP_INPUT]]);\nconst CHANNELS = { wheel: false, pinch: false, contextMenu: false, ingest: false } as const;\n\nfunction MinimapCanvasInner<TData, TLayer extends string, TPose>(\n props: MinimapCanvasProps<TData, TLayer, TPose>,\n) {\n const {\n scene,\n mainView: mainViewProp,\n mainViewDims,\n onMainViewChange,\n width,\n height,\n drawOne,\n alphaFor,\n layerVisibility,\n layerOrder,\n animator,\n fit = 'scene',\n poseDescriptor,\n indicatorStyle,\n className,\n canvasRef,\n id = 'minimap',\n } = props;\n const mainView = normalizeView(mainViewProp);\n\n // Subscribe to scene version so the fit view recomputes when the scene\n // mutates. `<SceneViewCanvas>` also subscribes, but it owns its own\n // rendering; we need the version *here* to invalidate the memoized fit.\n const sceneVersion = useSyncExternalStore(\n scene.subscribe,\n scene.getVersion,\n scene.getVersion,\n );\n\n const descriptor = (poseDescriptor ?? AUTO_POSE_DESCRIPTOR) as PoseDescriptor<TPose>;\n\n const fitView = useMemo<View>(() => {\n return computeFitView(scene, { width, height }, fit, descriptor);\n // `sceneVersion` participates so the memo re-evaluates after scene mutations.\n // `descriptor` is stable when the prop is omitted.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [scene, sceneVersion, width, height, fit, descriptor]);\n\n const indicatorCmd = useMemo<DrawCommand>(() => {\n return computeIndicatorCommand(mainView, mainViewDims, indicatorStyle);\n }, [mainView, mainViewDims, indicatorStyle]);\n\n // -------------------------------------------------------------------------\n // Input\n // -------------------------------------------------------------------------\n //\n // The \"latest\" pattern (refs holding the current mainView / dims / setter\n // / fitView) lets the dep and the listeners read up-to-date values without\n // re-binding every frame.\n\n const localCanvasRef = useRef<HTMLCanvasElement | null>(null);\n const mainViewRef = useLatest(mainView);\n const mainViewDimsRef = useLatest(mainViewDims);\n const onMainViewChangeRef = useLatest(onMainViewChange);\n const fitViewRef = useLatest(fitView);\n\n // The main canvas's camera, which is what the minimap's actions move.\n const rootView = useMemo<ViewApi>(() => ({\n get: () => mainViewRef.current,\n set: (v) => onMainViewChangeRef.current(v),\n hostSize: () => mainViewDimsRef.current,\n }), [mainViewRef, onMainViewChangeRef, mainViewDimsRef]);\n useDepSource('rootView', () => rootView);\n\n const actions = useActionsRegistry();\n useEffect(() => {\n if (!actions) return;\n const off = [actions.register(minimapCenterAction()), actions.register(minimapPanAction())];\n return () => { for (const u of off) u(); };\n }, [actions]);\n\n /** Client point → world, through the fit camera. */\n const clientToWorld = useCallback((cx: number, cy: number) => {\n const rect = localCanvasRef.current?.getBoundingClientRect();\n const fv = fitViewRef.current;\n return {\n x: fv.x + (cx - (rect?.left ?? 0)) / fv.scale.x,\n y: fv.y + (cy - (rect?.top ?? 0)) / fv.scale.y,\n };\n }, [fitViewRef]);\n\n useGestureDispatcher({\n canvasRef: localCanvasRef,\n actions: actions!,\n entriesById: TOOLS_BY_ID,\n clientToWorld,\n keyboard: false,\n channels: CHANNELS,\n });\n\n // -------------------------------------------------------------------------\n // Linked cursor\n // -------------------------------------------------------------------------\n\n const pointerStore = usePointerContext();\n useEffect(() => {\n const el = localCanvasRef.current;\n if (!el || !pointerStore) return;\n const onMove = (e: PointerEvent): void => {\n const w = clientToWorld(e.clientX, e.clientY);\n pointerStore.set({ worldX: w.x, worldY: w.y, viewId: id });\n };\n const onLeave = (e: PointerEvent): void => {\n if (e.buttons !== 0) return;\n if (pointerStore.get()?.viewId === id) pointerStore.set(null);\n };\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerleave', onLeave);\n return () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerleave', onLeave);\n };\n }, [pointerStore, clientToWorld, id]);\n\n const pointer = usePointerPosition();\n const cursorLayer = useMemo(() => createLinkedCursorLayer({\n id: `${id}.cursor`,\n pointer: () => pointer,\n color: () => accentColorOf(localCanvasRef.current),\n }), [id, pointer]);\n\n const extraCommands = useMemo<DrawCommand[]>(() => [\n indicatorCmd,\n ...cursorLayer.draw({ viewId: id }, fitView, { width, height }),\n ], [indicatorCmd, cursorLayer, id, fitView, width, height]);\n\n // `<SceneViewCanvas>` doesn't expose its element except via `canvasRef`, so\n // we route both our internal ref and the consumer's ref through one setter.\n const setCanvasRef = useCallback((el: HTMLCanvasElement | null) => {\n localCanvasRef.current = el;\n if (typeof canvasRef === 'function') {\n canvasRef(el);\n } else if (canvasRef && typeof canvasRef === 'object') {\n (canvasRef as { current: HTMLCanvasElement | null }).current = el;\n }\n }, [canvasRef]);\n\n return (\n <SceneViewCanvas\n scene={scene}\n view={fitView}\n width={width}\n height={height}\n drawOne={drawOne}\n extraCommands={extraCommands}\n alphaFor={alphaFor}\n layerVisibility={layerVisibility}\n layerOrder={layerOrder}\n animator={animator}\n className={className}\n canvasRef={setCanvasRef}\n />\n );\n}\n\n/**\n * Opinionated minimap. See `MinimapCanvasProps` for the full surface and\n * the module docstring for the rendering / input model.\n *\n * Its dispatcher, actions and deps are its own, so it never competes with\n * the main canvas for input. The pointer store is shared when one is in scope.\n *\n * `forwardRef` is not used because the component is generic over\n * `<TData, TLayer, TPose>` and React's `forwardRef` erases generics. The\n * `canvasRef` prop is the plain-prop equivalent.\n */\nexport function MinimapCanvas<TData, TLayer extends string, TPose>(\n props: MinimapCanvasProps<TData, TLayer, TPose>,\n) {\n return (\n <DepRegistryProvider>\n <ActionsProvider>\n <ActiveToolContextProvider>\n <PointerProviderIfRoot>\n <MinimapCanvasInner {...props} />\n </PointerProviderIfRoot>\n </ActiveToolContextProvider>\n </ActionsProvider>\n </DepRegistryProvider>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MinimapCanvas.js","names":["MINIMAP_INPUT","MINIMAP_CENTER","MINIMAP_PAN","TOOLS_BY_ID","CHANNELS","MinimapCanvasInner","mainViewProp","props","mainView","normalizeView","sceneVersion","useSyncExternalStore","scene","descriptor","poseDescriptor","AUTO_POSE_DESCRIPTOR","fitView","useMemo","computeFitView","fit","width","height","indicatorCmd","computeIndicatorCommand","mainViewDims","indicatorStyle","localCanvasRef","useRef","mainViewRef","useLatest","mainViewDimsRef","onMainViewChangeRef","onMainViewChange","fitViewRef","rootView","v","actions","useActionsRegistry","off","minimapCenterAction","minimapPanAction","u","clientToWorld","useCallback","rect","fv","cx","cy","pointerStore","usePointerContext","el","onMove","w","id","onLeave","pointer","usePointerPosition","cursorLayer","createLinkedCursorLayer","accentColorOf","extraCommands","setCanvasRef","assignRef","canvasRef","SceneViewCanvas","MinimapCanvas","DepRegistryProvider","ActionsProvider","ActiveToolContextProvider","PointerProviderIfRoot"],"sources":["../../src/canvas/MinimapCanvas.tsx"],"sourcesContent":["/**\n * `<MinimapCanvas>` — opinionated minimap on a canvas of its own, built on\n * `<SceneViewCanvas>`.\n *\n * Renders the same `scene` the main canvas is showing, through a derived\n * \"fit\" view, and overlays a dashed visible-window indicator showing where\n * the main canvas is currently looking. Press anywhere in the minimap to\n * recenter the main view on that world point; drag to pan continuously.\n *\n * Input runs on a dispatcher of its own, through the same `minimap.center` /\n * `minimap.pan` actions the in-surface minimap (`createMinimapContribution`)\n * binds. It publishes its pointer into the pointer store in scope, and draws a\n * crosshair wherever that store says the pointer is on another surface — put\n * one `<PointerContextProvider>` around it and the main canvas for linked\n * cursors both ways.\n */\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\nimport type { Ref } from 'react';\nimport {\n ActionsProvider,\n ActiveToolContextProvider,\n DepRegistryProvider,\n useActionsRegistry,\n useDepSource,\n useGestureDispatcher,\n} from '@weasel-js/routing/react';\nimport { assignRef, useLatest } from '@weasel-js/react';\nimport type { Tool } from '@weasel-js/routing';\nimport { PointerProviderIfRoot } from './SceneCanvas/PointerProviderIfRoot';\nimport { usePointerContext, usePointerPosition } from 'features/pointer/PointerContext';\nimport {\n MINIMAP_CENTER, MINIMAP_PAN, minimapCenterAction, minimapPanAction,\n} from 'features/minimap/actions';\nimport { createLinkedCursorLayer } from 'features/minimap/layers';\nimport type { ViewApi } from 'interactions/actions/depSchema';\nimport { SceneViewCanvas } from './SceneViewCanvas';\nimport {\n computeFitView,\n computeIndicatorCommand,\n} from './minimapMath';\nimport type { IndicatorStyle, MinimapFit } from './minimapMath';\nimport type { SceneViewDrawOne, SceneViewLayers } from './sceneViewRender';\nimport type { DrawCommand } from '../renderer/DrawCommand';\nimport { normalizeView, type View } from '../core/viewport/view';\nimport type { Scene } from '../core/scene/types';\nimport type { PoseDescriptor } from '../core/geometry/poseDescriptor';\nimport type { Animator } from '../animation/types';\nimport { AUTO_POSE_DESCRIPTOR } from '../interactions/actions/resize/autoPoseDescriptor';\nimport { accentColorOf } from './accentColor';\n\n/** Props for `<MinimapCanvas>`. */\nexport interface MinimapCanvasProps<TData, TLayer extends string, TPose> {\n /** Same scene the main canvas is rendering. */\n scene: Scene<TData, TLayer, TPose>;\n /** Main canvas's view — used to position the visible-window indicator and\n * to preserve `scale` when the minimap recenters. */\n mainView: View;\n /** Main canvas's CSS-pixel dims. Used to compute the visible-window rect\n * and the recenter offset. */\n mainViewDims: { width: number; height: number };\n /** Setter called on click (single recenter) and during drag (continuous\n * recenter). Receives a `View` with the same `scale` as `mainView` and\n * `(x, y)` shifted so the pointer's world point lands at the main\n * canvas's center. */\n onMainViewChange: (next: View) => void;\n /** Minimap's own CSS-pixel dims. */\n width: number;\n height: number;\n /** Consumer's draw callback. Applied through the derived fit view; same\n * signature as `<SceneCanvas>`'s scene-slot `drawOne` so the consumer\n * can reuse it (typically simplified — just colored AABBs). */\n drawOne: SceneViewDrawOne<TData, TLayer, TPose>;\n /** Fit policy. Defaults to `\"scene\"` (AABB union of leaf poses). See\n * `MinimapFit` for the full shape.\n *\n * Framing is derived from **document** poses, not `scene.overrides` — a\n * node moved by an override paints where the override puts it, outside the\n * frame if it goes there, rather than making the whole minimap rescale on\n * every frame of a drag or a settle. */\n fit?: MinimapFit<TData, TLayer, TPose>;\n /** How to read poses. Default `AUTO_POSE_DESCRIPTOR`. */\n poseDescriptor?: PoseDescriptor<TPose>;\n /** Optional per-id alpha multiplier, mirroring `<SceneCanvas>`'s scene-slot\n * `alphaFor`. Pass the same function the main canvas uses so a\n * scoping-dim treatment shows up in the minimap too. */\n alphaFor?: (id: string) => number;\n /** Hide scene layers in the minimap, keyed `scene:<layerId>` as on\n * `<SceneCanvas>` — pass the main canvas's map so both show the same set. */\n layerVisibility?: SceneViewLayers['layerVisibility'];\n /** Paint order for the minimap, keyed as `layerVisibility`. */\n layerOrder?: SceneViewLayers['layerOrder'];\n /** Optional animator: the minimap repaints on its ticks and paints its\n * `colorOverrides`. Pass the main canvas's animator so both show the same\n * colors. */\n animator?: Animator;\n /** Visual tuning of the indicator stroke. */\n indicatorStyle?: IndicatorStyle;\n /** CSS class for sizing / positioning the canvas. */\n className?: string;\n /** Forwarded ref to the underlying `<canvas>`. */\n canvasRef?: Ref<HTMLCanvasElement>;\n /** The view id this minimap publishes its pointer under. Default\n * `'minimap'`. */\n id?: string;\n}\n\n/** The minimap's own bindings. Unscoped: this dispatcher routes no views, so\n * every input on it is the minimap's. */\nconst MINIMAP_INPUT: Tool = {\n id: 'minimap',\n eligibility: { always: true },\n bindings: [\n { spec: { kind: 'pointerDown' }, actionId: MINIMAP_CENTER },\n { spec: { kind: 'drag' }, actionId: MINIMAP_PAN },\n ],\n};\nconst TOOLS_BY_ID: ReadonlyMap<string, Tool> = new Map([[MINIMAP_INPUT.id, MINIMAP_INPUT]]);\nconst CHANNELS = { wheel: false, pinch: false, contextMenu: false, ingest: false } as const;\n\nfunction MinimapCanvasInner<TData, TLayer extends string, TPose>(\n props: MinimapCanvasProps<TData, TLayer, TPose>,\n) {\n const {\n scene,\n mainView: mainViewProp,\n mainViewDims,\n onMainViewChange,\n width,\n height,\n drawOne,\n alphaFor,\n layerVisibility,\n layerOrder,\n animator,\n fit = 'scene',\n poseDescriptor,\n indicatorStyle,\n className,\n canvasRef,\n id = 'minimap',\n } = props;\n const mainView = normalizeView(mainViewProp);\n\n // Subscribe to scene version so the fit view recomputes when the scene\n // mutates. `<SceneViewCanvas>` also subscribes, but it owns its own\n // rendering; we need the version *here* to invalidate the memoized fit.\n const sceneVersion = useSyncExternalStore(\n scene.subscribe,\n scene.getVersion,\n scene.getVersion,\n );\n\n const descriptor = (poseDescriptor ?? AUTO_POSE_DESCRIPTOR) as PoseDescriptor<TPose>;\n\n const fitView = useMemo<View>(() => {\n return computeFitView(scene, { width, height }, fit, descriptor);\n // `sceneVersion` participates so the memo re-evaluates after scene mutations.\n // `descriptor` is stable when the prop is omitted.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [scene, sceneVersion, width, height, fit, descriptor]);\n\n const indicatorCmd = useMemo<DrawCommand>(() => {\n return computeIndicatorCommand(mainView, mainViewDims, indicatorStyle);\n }, [mainView, mainViewDims, indicatorStyle]);\n\n // -------------------------------------------------------------------------\n // Input\n // -------------------------------------------------------------------------\n //\n // The \"latest\" pattern (refs holding the current mainView / dims / setter\n // / fitView) lets the dep and the listeners read up-to-date values without\n // re-binding every frame.\n\n const localCanvasRef = useRef<HTMLCanvasElement | null>(null);\n const mainViewRef = useLatest(mainView);\n const mainViewDimsRef = useLatest(mainViewDims);\n const onMainViewChangeRef = useLatest(onMainViewChange);\n const fitViewRef = useLatest(fitView);\n\n // The main canvas's camera, which is what the minimap's actions move.\n const rootView = useMemo<ViewApi>(() => ({\n get: () => mainViewRef.current,\n set: (v) => onMainViewChangeRef.current(v),\n hostSize: () => mainViewDimsRef.current,\n }), [mainViewRef, onMainViewChangeRef, mainViewDimsRef]);\n useDepSource('rootView', () => rootView);\n\n const actions = useActionsRegistry();\n useEffect(() => {\n if (!actions) return;\n const off = [actions.register(minimapCenterAction()), actions.register(minimapPanAction())];\n return () => { for (const u of off) u(); };\n }, [actions]);\n\n /** Client point → world, through the fit camera. */\n const clientToWorld = useCallback((cx: number, cy: number) => {\n const rect = localCanvasRef.current?.getBoundingClientRect();\n const fv = fitViewRef.current;\n return {\n x: fv.x + (cx - (rect?.left ?? 0)) / fv.scale.x,\n y: fv.y + (cy - (rect?.top ?? 0)) / fv.scale.y,\n };\n }, [fitViewRef]);\n\n useGestureDispatcher({\n canvasRef: localCanvasRef,\n actions: actions!,\n entriesById: TOOLS_BY_ID,\n clientToWorld,\n keyboard: false,\n channels: CHANNELS,\n });\n\n // -------------------------------------------------------------------------\n // Linked cursor\n // -------------------------------------------------------------------------\n\n const pointerStore = usePointerContext();\n useEffect(() => {\n const el = localCanvasRef.current;\n if (!el || !pointerStore) return;\n const onMove = (e: PointerEvent): void => {\n const w = clientToWorld(e.clientX, e.clientY);\n pointerStore.set({ worldX: w.x, worldY: w.y, viewId: id });\n };\n const onLeave = (e: PointerEvent): void => {\n if (e.buttons !== 0) return;\n if (pointerStore.get()?.viewId === id) pointerStore.set(null);\n };\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerleave', onLeave);\n return () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerleave', onLeave);\n };\n }, [pointerStore, clientToWorld, id]);\n\n const pointer = usePointerPosition();\n const cursorLayer = useMemo(() => createLinkedCursorLayer({\n id: `${id}.cursor`,\n pointer: () => pointer,\n color: () => accentColorOf(localCanvasRef.current),\n }), [id, pointer]);\n\n const extraCommands = useMemo<DrawCommand[]>(() => [\n indicatorCmd,\n ...cursorLayer.draw({ viewId: id }, fitView, { width, height }),\n ], [indicatorCmd, cursorLayer, id, fitView, width, height]);\n\n // `<SceneViewCanvas>` doesn't expose its element except via `canvasRef`, so\n // we route both our internal ref and the consumer's ref through one setter.\n const setCanvasRef = useCallback((el: HTMLCanvasElement | null) => {\n localCanvasRef.current = el;\n assignRef(canvasRef, el);\n }, [canvasRef]);\n\n return (\n <SceneViewCanvas\n scene={scene}\n view={fitView}\n width={width}\n height={height}\n drawOne={drawOne}\n extraCommands={extraCommands}\n alphaFor={alphaFor}\n layerVisibility={layerVisibility}\n layerOrder={layerOrder}\n animator={animator}\n className={className}\n canvasRef={setCanvasRef}\n />\n );\n}\n\n/**\n * Opinionated minimap. See `MinimapCanvasProps` for the full surface and\n * the module docstring for the rendering / input model.\n *\n * Its dispatcher, actions and deps are its own, so it never competes with\n * the main canvas for input. The pointer store is shared when one is in scope.\n *\n * `forwardRef` is not used because the component is generic over\n * `<TData, TLayer, TPose>` and React's `forwardRef` erases generics. The\n * `canvasRef` prop is the plain-prop equivalent.\n */\nexport function MinimapCanvas<TData, TLayer extends string, TPose>(\n props: MinimapCanvasProps<TData, TLayer, TPose>,\n) {\n return (\n <DepRegistryProvider>\n <ActionsProvider>\n <ActiveToolContextProvider>\n <PointerProviderIfRoot>\n <MinimapCanvasInner {...props} />\n </PointerProviderIfRoot>\n </ActiveToolContextProvider>\n </ActionsProvider>\n </DepRegistryProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAkHA,IAAMA,IAAsB;CAC1B,IAAI;CACJ,aAAa,EAAE,QAAQ,GAAK;CAC5B,UAAU,CACR;EAAE,MAAM,EAAE,MAAM,cAAc;EAAG,UAAUC;CAAe,GAC1D;EAAE,MAAM,EAAE,MAAM,OAAO;EAAG,UAAUC;CAAY,CAClD;AACF,GACMC,oBAAyC,IAAI,IAAI,CAAC,CAACH,EAAc,IAAIA,CAAa,CAAC,CAAC,GACpFI,IAAW;CAAE,OAAO;CAAO,OAAO;CAAO,aAAa;CAAO,QAAQ;AAAM;AAEjF,SAASC,EACP,GACA;CACA,IAAM,EACJ,UACA,UAAUC,GACV,iBACA,qBACA,UACA,WACA,YACA,aACA,oBACA,eACA,aACA,SAAM,SACN,oBACA,mBACA,cACA,cACA,QAAK,cACHC,GACEC,IAAWC,EAAcH,CAAY,GAKrCI,IAAeC,GACnBC,EAAM,WACNA,EAAM,YACNA,EAAM,UACR,GAEMC,IAAcC,MAAkBC,GAEhCC,IAAUC,QACPC,EAAeN,GAAO;EAAE;EAAO;CAAO,GAAGO,GAAKN,CAAU,GAI9D;EAACD;EAAOF;EAAcU;EAAOC;EAAQF;EAAKN;CAAU,CAAC,GAElDS,IAAeL,QACZM,EAAwBf,GAAUgB,GAAcC,CAAc,GACpE;EAACjB;EAAUgB;EAAcC;CAAc,CAAC,GAUrCC,IAAiBC,GAAiC,IAAI,GACtDC,IAAcC,EAAUrB,CAAQ,GAChCsB,IAAkBD,EAAUL,CAAY,GACxCO,IAAsBF,EAAUG,CAAgB,GAChDC,IAAaJ,EAAUb,CAAO,GAG9BkB,IAAWjB,SAAwB;EACvC,WAAWW,EAAY;EACvB,MAAM,MAAMG,EAAoB,QAAQI,CAAC;EACzC,gBAAgBL,EAAgB;CAClC,IAAI;EAACF;EAAaG;EAAqBD;CAAe,CAAC;CACvD,EAAa,kBAAkBI,CAAQ;CAEvC,IAAME,IAAUC,EAAmB;CACnC,QAAgB;EACd,IAAI,CAACD,GAAS;EACd,IAAME,IAAM,CAACF,EAAQ,SAASG,EAAoB,CAAC,GAAGH,EAAQ,SAASI,EAAiB,CAAC,CAAC;EAC1F,aAAa;GAAE,KAAK,IAAMC,KAAKH,GAAK,EAAE;EAAG;CAC3C,GAAG,CAACF,CAAO,CAAC;CAGZ,IAAMM,IAAgBC,GAAa,GAAY,MAAe;EAC5D,IAAMC,IAAOlB,EAAe,SAAS,sBAAsB,GACrDmB,IAAKZ,EAAW;EACtB,OAAO;GACL,GAAGY,EAAG,KAAKC,KAAMF,GAAM,QAAQ,MAAMC,EAAG,MAAM;GAC9C,GAAGA,EAAG,KAAKE,KAAMH,GAAM,OAAO,MAAMC,EAAG,MAAM;EAC/C;CACF,GAAG,CAACZ,CAAU,CAAC;CAEf,GAAqB;EACnB,WAAWP;EACF;EACT,aAAavB;EACb;EACA,UAAU;EACV,UAAUC;CACZ,CAAC;CAMD,IAAM4C,IAAeC,EAAkB;CACvC,QAAgB;EACd,IAAMC,IAAKxB,EAAe;EAC1B,IAAI,CAACwB,KAAM,CAACF,GAAc;EAC1B,IAAMG,KAAU,MAA0B;GACxC,IAAMC,IAAIV,EAAc,EAAE,SAAS,EAAE,OAAO;GAC5C,EAAa,IAAI;IAAE,QAAQU,EAAE;IAAG,QAAQA,EAAE;IAAG,QAAQC;GAAG,CAAC;EAC3D,GACMC,KAAW,MAA0B;GACzC,AAAI,EAAE,YAAY,KACdN,EAAa,IAAI,CAAC,EAAE,WAAWK,KAAIL,EAAa,IAAI,IAAI;EAC9D;EAGA,OAFAE,EAAG,iBAAiB,eAAeC,CAAM,GACzCD,EAAG,iBAAiB,gBAAgBI,CAAO,SAC9B;GAEX,AADAJ,EAAG,oBAAoB,eAAeC,CAAM,GAC5CD,EAAG,oBAAoB,gBAAgBI,CAAO;EAChD;CACF,GAAG;EAACN;EAAcN;EAAeW;CAAE,CAAC;CAEpC,IAAME,IAAUC,EAAmB,GAC7BC,IAAcxC,QAAcyC,EAAwB;EACxD,IAAI,GAAGL,EAAG;EACV,eAAeE;EACf,aAAaI,EAAcjC,EAAe,OAAO;CACnD,CAAC,GAAG,CAAC2B,GAAIE,CAAO,CAAC,GAEXK,KAAgB3C,QAA6B,CACjDK,GACA,GAAGmC,EAAY,KAAK,EAAE,QAAQJ,EAAG,GAAGrC,GAAS;EAAE;EAAO;CAAO,CAAC,CAChE,GAAG;EAACM;EAAcmC;EAAaJ;EAAIrC;EAASI;EAAOC;CAAM,CAAC,GAIpDwC,KAAelB,GAAa,MAAiC;EAEjE,AADA,EAAe,UAAUO,GACzBY,EAAUC,GAAWb,CAAE;CACzB,GAAG,CAACa,CAAS,CAAC;CAEd,OACE,kBAACC,GAAD;EACS;EACP,MAAMhD;EACC;EACC;EACC;EACM;EACL;EACO;EACL;EACF;EACC;EACX,WAAW6C;CACZ,CAAA;AAEL;AAaA,SAAgBI,EACd,GACA;CACA,OACE,kBAACC,GAAD,EAAA,UACE,kBAACC,GAAD,EAAA,UACE,kBAACC,GAAD,EAAA,UACE,kBAACC,GAAD,EAAA,UACE,kBAAChE,GAAD,EAAoB,GAAIE,EAAQ,CAAA,EACX,CAAA,EACE,CAAA,EACZ,CAAA,EACE,CAAA;AAEzB"}
@@ -10,10 +10,10 @@ import { DEFAULT_SHAPE_FILL as u } from "../util/paint.js";
10
10
  import { fillInPoseFrame as d } from "../core/fillInPoseFrame.js";
11
11
  import { resolveFillPattern as f } from "../features/patterns/resolveSpec.js";
12
12
  import { textCommandFromPose as p } from "../features/text/textCommand.js";
13
- import { hasSlop as m, slopForStrokeHit as ee } from "../core/viewport/screenSlop.js";
14
- import { getImageBitmap as h, imageStatus as g } from "../features/images/imageCache.js";
15
- import { PATH_L as _, PATH_M as v, PATH_Z as y, boundsOfPath as b, ellipsePath as x, linePath as S, pathContainsPoint as C, regularPolygonPath as w, starPath as T, strokeHitTest as E } from "@weasel-js/geom";
16
- import { textLineBoxes as D } from "@weasel-js/text";
13
+ import { hasSlop as ee, slopForStrokeHit as m, widenSlop as h } from "../core/viewport/screenSlop.js";
14
+ import { getImageBitmap as g, imageStatus as _ } from "../features/images/imageCache.js";
15
+ import { PATH_L as v, PATH_M as y, PATH_Z as b, boundsOfPath as x, ellipsePath as S, linePath as C, pathContainsPoint as w, regularPolygonPath as T, starPath as E, strokeHitTest as D } from "@weasel-js/geom";
16
+ import { textLineBoxes as te } from "@weasel-js/text";
17
17
  //#region src/canvas/NodeShape.ts
18
18
  function O(e) {
19
19
  return e === void 0 || s(e);
@@ -57,7 +57,7 @@ function B(e, t, n) {
57
57
  }
58
58
  function V(e, t, n) {
59
59
  if (!s(e)) return null;
60
- let r = t ? i(t, n ?? 1) : 0, a = Math.min(e.x, e.x + e.width), o = Math.min(e.y, e.y + e.height);
60
+ let r = t ? i(t, n?.scale ?? 1, n?.leastScale) : 0, a = Math.min(e.x, e.x + e.width), o = Math.min(e.y, e.y + e.height);
61
61
  return {
62
62
  x: a - r,
63
63
  y: o - r,
@@ -68,10 +68,10 @@ function V(e, t, n) {
68
68
  function H(e, t, n, r, i = {}) {
69
69
  let a = R(e, t, { derivedPath: i.derivedPath });
70
70
  if (a === null) return !0;
71
- let o = z(e, t, { scale: i.scale }) ?? k, s = C(a, n, r);
71
+ let o = z(e, t, { scale: i.scale }) ?? k, s = w(a, n, r);
72
72
  if (o.filled && s) return !0;
73
- let { extra: c, opts: l } = ee(i.tolerance), u = (s ? o.inset : o.outset) + c;
74
- return (u > 0 || m(i.tolerance)) && E(a, n, r, u, l);
73
+ let c = h(i.tolerance, (s ? o.insetPx : o.outsetPx) ?? 0, i.scale), { extra: l, opts: u } = m(c), d = (s ? o.inset : o.outset) + l;
74
+ return (d > 0 || ee(c)) && D(a, n, r, d, u);
75
75
  }
76
76
  function U() {
77
77
  return [...A.high, ...A.normal];
@@ -90,13 +90,13 @@ function W(e, t) {
90
90
  verticalAlign: e.verticalAlign
91
91
  };
92
92
  }
93
- var G = {
93
+ var ne = {
94
94
  id: "kit:text",
95
95
  matches: (e) => O(e.pose) ? e.data?.text != null : !1,
96
96
  paint: (e, n) => t(e, F, n, () => [p(W(e.data, n))]),
97
97
  silhouette: (e, t) => {
98
- let n = D(W(e.data, t));
99
- return n.length === 0 ? null : te(n);
98
+ let n = te(W(e.data, t));
99
+ return n.length === 0 ? null : G(n);
100
100
  },
101
101
  ink: (e, t, n) => {
102
102
  let r = e.data;
@@ -106,11 +106,11 @@ var G = {
106
106
  };
107
107
  }
108
108
  };
109
- function te(e) {
109
+ function G(e) {
110
110
  let t = new Uint8Array(e.length * 6), n = new Float32Array(e.length * 10), r = 0, i = 0;
111
111
  for (let a of e) {
112
112
  let { x: e, y: o, width: s, height: c } = a;
113
- t[i++] = v, n[r++] = e, n[r++] = o, t[i++] = _, n[r++] = e + s, n[r++] = o, t[i++] = _, n[r++] = e + s, n[r++] = o + c, t[i++] = _, n[r++] = e, n[r++] = o + c, t[i++] = _, n[r++] = e, n[r++] = o, t[i++] = y;
113
+ t[i++] = y, n[r++] = e, n[r++] = o, t[i++] = v, n[r++] = e + s, n[r++] = o, t[i++] = v, n[r++] = e + s, n[r++] = o + c, t[i++] = v, n[r++] = e, n[r++] = o + c, t[i++] = v, n[r++] = e, n[r++] = o, t[i++] = b;
114
114
  }
115
115
  return {
116
116
  kind: "polygon",
@@ -137,21 +137,30 @@ function Y(e, t) {
137
137
  outset: 0,
138
138
  inset: 0
139
139
  };
140
- let i = n(e.width ?? 1, t ?? 1), a = r(e, i, t);
141
- switch (e.align ?? "center") {
142
- case "inner": return {
143
- outset: a,
144
- inset: i
145
- };
146
- case "outer": return {
147
- outset: i + a,
148
- inset: 0
149
- };
150
- default: return {
151
- outset: i / 2 + a,
152
- inset: i / 2
153
- };
154
- }
140
+ let i = r(e), a = (t, n) => {
141
+ switch (e.align ?? "center") {
142
+ case "inner": return {
143
+ outset: n,
144
+ inset: t
145
+ };
146
+ case "outer": return {
147
+ outset: t + n,
148
+ inset: 0
149
+ };
150
+ default: return {
151
+ outset: t / 2 + n,
152
+ inset: t / 2
153
+ };
154
+ }
155
+ }, o = e.width ?? 1, s = a(typeof o == "object" ? 0 : n(o, t ?? 1), i.world);
156
+ if (typeof o != "object" && !(i.px > 0)) return s;
157
+ let c = a(typeof o == "object" ? o.px : 0, i.px);
158
+ return {
159
+ outset: s.outset,
160
+ inset: s.inset,
161
+ outsetPx: c.outset,
162
+ insetPx: c.inset
163
+ };
155
164
  }
156
165
  function X(e, t) {
157
166
  let n = t?.vertexColors, r = e[0];
@@ -190,16 +199,16 @@ var Z = {
190
199
  ...Y(i, n?.scale)
191
200
  };
192
201
  },
193
- bounds: (e, t, n) => V(t, q(e.data.stroke), n?.scale)
194
- }, Q = {
202
+ bounds: (e, t, n) => V(t, q(e.data.stroke), n)
203
+ }, re = {
195
204
  id: "kit:shape",
196
205
  matches: (e) => {
197
206
  if (!O(e.pose)) return !1;
198
207
  let t = e.data?.shape;
199
- return t != null && ne.has(t);
208
+ return t != null && ie.has(t);
200
209
  },
201
210
  paint: (e, n, r) => X(t(e, F, n, () => {
202
- let t = e.data, r = $(t, n), i = K(t.fill, u), a = i && f(d(i, n)), o = q(t.stroke), s = o && J(o, n);
211
+ let t = e.data, r = Q(t, n), i = K(t.fill, u), a = i && f(d(i, n)), o = q(t.stroke), s = o && J(o, n);
203
212
  return [{
204
213
  kind: "path",
205
214
  path: r,
@@ -209,7 +218,7 @@ var Z = {
209
218
  }), r),
210
219
  silhouette: (e, t) => {
211
220
  let n = e.data;
212
- return $(n, t);
221
+ return Q(n, t);
213
222
  },
214
223
  ink: (e, t, n) => {
215
224
  let r = e.data;
@@ -218,26 +227,26 @@ var Z = {
218
227
  ...Y(q(r.stroke), n?.scale)
219
228
  };
220
229
  },
221
- bounds: (e, t, n) => V(t, q(e.data.stroke), n?.scale)
222
- }, ne = /* @__PURE__ */ new Set([
230
+ bounds: (e, t, n) => V(t, q(e.data.stroke), n)
231
+ }, ie = /* @__PURE__ */ new Set([
223
232
  "rect",
224
233
  "ellipse",
225
234
  "polygon",
226
235
  "star"
227
236
  ]);
228
- function $(e, t) {
237
+ function Q(e, t) {
229
238
  switch (e.shape) {
230
- case "ellipse": return x(t);
239
+ case "ellipse": return S(t);
231
240
  case "polygon": {
232
241
  let n = t.x + t.width / 2, r = t.y + t.height / 2, i = Math.min(t.width, t.height) / 2;
233
- return w({
242
+ return T({
234
243
  x: n,
235
244
  y: r
236
245
  }, i, e.sides ?? 6);
237
246
  }
238
247
  case "star": {
239
248
  let n = t.x + t.width / 2, r = t.y + t.height / 2, i = Math.min(t.width, t.height) / 2;
240
- return T({
249
+ return E({
241
250
  x: n,
242
251
  y: r
243
252
  }, i, e.points ?? 5);
@@ -251,7 +260,7 @@ function $(e, t) {
251
260
  };
252
261
  }
253
262
  }
254
- function re(e, t) {
263
+ function ae(e, t) {
255
264
  return {
256
265
  x: e.x * t.width,
257
266
  y: e.y * t.height,
@@ -259,13 +268,13 @@ function re(e, t) {
259
268
  h: e.height * t.height
260
269
  };
261
270
  }
262
- function ie(e, t, n) {
271
+ function oe(e, t, n) {
263
272
  if (n && n > 0) return {
264
273
  width: Math.abs(e.width) * n / (t?.width || 1),
265
274
  height: Math.abs(e.height) * n / (t?.height || 1)
266
275
  };
267
276
  }
268
- var ae = {
277
+ var $ = {
269
278
  id: "kit:image",
270
279
  matches: (e) => {
271
280
  if (!O(e.pose)) return !1;
@@ -273,7 +282,7 @@ var ae = {
273
282
  return typeof t == "string" && t.length > 0;
274
283
  },
275
284
  paint: (e, t, n) => {
276
- let r = e.data, i = t, a = n?.resolveImage ? n.resolveImage(e) : h(r.image.src, ie(i, r.image.source, n?.pixelScale));
285
+ let r = e.data, i = t, a = n?.resolveImage ? n.resolveImage(e) : g(r.image.src, oe(i, r.image.source, n?.pixelScale));
277
286
  if (a) return [{
278
287
  kind: "image",
279
288
  image: a,
@@ -282,11 +291,11 @@ var ae = {
282
291
  w: i.width,
283
292
  h: i.height,
284
293
  ...r.image.opacity === void 0 ? {} : { opacity: r.image.opacity },
285
- ...r.image.source ? { source: re(r.image.source, a) } : {},
294
+ ...r.image.source ? { source: ae(r.image.source, a) } : {},
286
295
  ...r.image.flipX ? { flipX: !0 } : {},
287
296
  ...r.image.flipY ? { flipY: !0 } : {}
288
297
  }];
289
- let o = !n?.resolveImage && g(r.image.src) === "error", s = o ? "#d08a8a" : "#bbbbbb", c = [{
298
+ let o = !n?.resolveImage && _(r.image.src) === "error", s = o ? "#d08a8a" : "#bbbbbb", c = [{
290
299
  kind: "path",
291
300
  path: {
292
301
  kind: "rect",
@@ -302,7 +311,7 @@ var ae = {
302
311
  }];
303
312
  return o && c.push({
304
313
  kind: "path",
305
- path: S({
314
+ path: C({
306
315
  x: i.x,
307
316
  y: i.y
308
317
  }, {
@@ -325,17 +334,17 @@ var ae = {
325
334
  height: n.height
326
335
  };
327
336
  },
328
- bounds: (e, t, n) => V(t, oe, n?.scale)
329
- }, oe = {
337
+ bounds: (e, t, n) => V(t, se, n)
338
+ }, se = {
330
339
  paint: { color: "#000" },
331
340
  width: 1
332
- }, se = {
341
+ }, ce = {
333
342
  id: "kit:derived",
334
343
  matches: (e) => (e.dependsOn?.length ?? 0) > 0 && e.derivePath !== void 0,
335
344
  paint: (e, t, n) => {
336
345
  let r = n?.derivedPath;
337
346
  if (r == null) return [];
338
- let i = b(r), a = e.data, o = q(a?.stroke), s = K(a?.fill, o === null ? u : null), c = s && f(d(s, i)), l = o && J(o, i);
347
+ let i = x(r), a = e.data, o = q(a?.stroke), s = K(a?.fill, o === null ? u : null), c = s && f(d(s, i)), l = o && J(o, i);
339
348
  return X([{
340
349
  kind: "path",
341
350
  path: r,
@@ -352,7 +361,7 @@ var ae = {
352
361
  ...Y(i, n?.scale)
353
362
  };
354
363
  }
355
- }, ce = {
364
+ }, le = {
356
365
  id: "kit:rect-fallback",
357
366
  matches: (e) => O(e.pose),
358
367
  paint: (e, t) => {
@@ -381,10 +390,10 @@ var ae = {
381
390
  },
382
391
  bounds: (e, t) => V(t, null, void 0)
383
392
  };
384
- function le() {
385
- j(G), j(se), j(Z), j(Q), j(ae), j(ce);
393
+ function ue() {
394
+ j(ne), j(ce), j(Z), j(re), j($), j(le);
386
395
  }
387
- le();
396
+ ue();
388
397
  //#endregion
389
398
  export { k as DEFAULT_INK, I as findNodeShape, B as findShapeBounds, z as findShapeInk, R as findShapeSilhouette, U as getNodeShapes, j as registerNodeShape, H as shapeCoversPoint };
390
399