@weasel-js/core 1.9.3 → 1.9.4

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 (542) hide show
  1. package/CHANGELOG.md +356 -0
  2. package/README.md +2 -2
  3. package/dist/WeaselProvider.js +5 -5
  4. package/dist/affordances/composeAffordanceLayer.js +10 -20
  5. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  6. package/dist/affordances/cornerResize.js +25 -17
  7. package/dist/affordances/cornerResize.js.map +1 -1
  8. package/dist/affordances/hitAffordanceRegions.js +27 -20
  9. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  10. package/dist/affordances/rotationHandle.js +18 -18
  11. package/dist/affordances/rotationHandle.js.map +1 -1
  12. package/dist/animation/behaviors/momentum.js +93 -55
  13. package/dist/animation/behaviors/momentum.js.map +1 -1
  14. package/dist/animation/loop.js +10 -12
  15. package/dist/animation/loop.js.map +1 -1
  16. package/dist/animation/reflow.js +8 -8
  17. package/dist/animation/reflow.js.map +1 -1
  18. package/dist/animation/stagger.js +64 -56
  19. package/dist/animation/stagger.js.map +1 -1
  20. package/dist/animation/timeline/booking.js +62 -54
  21. package/dist/animation/timeline/booking.js.map +1 -1
  22. package/dist/animation/timeline/createTimeline.js +85 -76
  23. package/dist/animation/timeline/createTimeline.js.map +1 -1
  24. package/dist/animation/timeline/sampleTrack.js +13 -5
  25. package/dist/animation/timeline/sampleTrack.js.map +1 -1
  26. package/dist/animation/useAnimator.js +45 -35
  27. package/dist/animation/useAnimator.js.map +1 -1
  28. package/dist/animation/wrappers/animateLifecycle.js +31 -24
  29. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  30. package/dist/animation/wrappers/animateOnSetPose.js +28 -26
  31. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  32. package/dist/animation/wrappers/instantPose.js +13 -0
  33. package/dist/animation/wrappers/instantPose.js.map +1 -0
  34. package/dist/{poseDescriptor-D-OH-tu5.d.ts → autoPoseDescriptor-Ct7yqivU.d.ts} +28 -3
  35. package/dist/barrel/chrome.js +16 -0
  36. package/dist/barrel/input.js +19 -0
  37. package/dist/barrel/interactions.js +42 -0
  38. package/dist/barrel/paint.js +18 -0
  39. package/dist/barrel/paths.js +19 -0
  40. package/dist/barrel/renderer.js +20 -0
  41. package/dist/barrel/routing.js +51 -0
  42. package/dist/barrel/text.js +18 -0
  43. package/dist/barrel/viewport.js +52 -0
  44. package/dist/builtins-DPcdghtB.d.ts +1223 -0
  45. package/dist/canvas/Canvas.js +363 -448
  46. package/dist/canvas/Canvas.js.map +1 -1
  47. package/dist/canvas/CanvasView.js +164 -165
  48. package/dist/canvas/CanvasView.js.map +1 -1
  49. package/dist/canvas/CursorCoordsHud.js +37 -32
  50. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  51. package/dist/canvas/DrawCanvas.js +49 -43
  52. package/dist/canvas/DrawCanvas.js.map +1 -1
  53. package/dist/canvas/MinimapCanvas.js +26 -25
  54. package/dist/canvas/MinimapCanvas.js.map +1 -1
  55. package/dist/canvas/NodeShape.js +59 -377
  56. package/dist/canvas/NodeShape.js.map +1 -1
  57. package/dist/canvas/PickHud.js +50 -47
  58. package/dist/canvas/PickHud.js.map +1 -1
  59. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +167 -0
  60. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +1 -0
  61. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +13 -13
  62. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +67 -0
  63. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -0
  64. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +16 -0
  65. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +1 -0
  66. package/dist/canvas/SceneCanvas/coordTrace.js +10 -0
  67. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -0
  68. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +112 -70
  69. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  70. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +9 -8
  71. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  72. package/dist/canvas/SceneCanvas/features.js +1 -0
  73. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  74. package/dist/canvas/SceneCanvas/isDev.js +12 -0
  75. package/dist/canvas/SceneCanvas/isDev.js.map +1 -0
  76. package/dist/canvas/SceneCanvas/poseGeometry.js +29 -28
  77. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  78. package/dist/canvas/SceneCanvas/poseRegistrars.js +13 -0
  79. package/dist/canvas/SceneCanvas/poseRegistrars.js.map +1 -0
  80. package/dist/canvas/SceneCanvas/props.js +38 -0
  81. package/dist/canvas/SceneCanvas/props.js.map +1 -0
  82. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +21 -62
  83. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  84. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  85. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +46 -48
  86. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  87. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +33 -33
  88. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  89. package/dist/canvas/SceneCanvas.js +534 -788
  90. package/dist/canvas/SceneCanvas.js.map +1 -1
  91. package/dist/canvas/SceneViewCanvas.js +45 -43
  92. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  93. package/dist/canvas/buildSceneLayer.js +91 -0
  94. package/dist/canvas/buildSceneLayer.js.map +1 -0
  95. package/dist/canvas/buildSceneTree.js +16 -19
  96. package/dist/canvas/buildSceneTree.js.map +1 -1
  97. package/dist/canvas/canvasRenderer.js +68 -52
  98. package/dist/canvas/canvasRenderer.js.map +1 -1
  99. package/dist/canvas/deps/changes.js +13 -0
  100. package/dist/canvas/deps/changes.js.map +1 -0
  101. package/dist/canvas/deps/editAnchors.js +28 -28
  102. package/dist/canvas/deps/insert.js +119 -91
  103. package/dist/canvas/deps/insert.js.map +1 -1
  104. package/dist/canvas/deps/slice.js +46 -45
  105. package/dist/canvas/deps/slice.js.map +1 -1
  106. package/dist/canvas/deps/textEdit.js +10 -9
  107. package/dist/canvas/deps/textEdit.js.map +1 -1
  108. package/dist/canvas/derivedPath.js +46 -23
  109. package/dist/canvas/derivedPath.js.map +1 -1
  110. package/dist/canvas/getNodeAtPoint.js +7 -7
  111. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  112. package/dist/canvas/hud.module.js +1 -1
  113. package/dist/canvas/hud.module.js.map +1 -1
  114. package/dist/canvas/kitRequirements.js +2 -2
  115. package/dist/canvas/kitRequirements.js.map +1 -1
  116. package/dist/canvas/layerOrder.js +13 -6
  117. package/dist/canvas/layerOrder.js.map +1 -1
  118. package/dist/canvas/minimapMath.js +12 -10
  119. package/dist/canvas/minimapMath.js.map +1 -1
  120. package/dist/canvas/nodeShapes/derivedPainter.js +34 -0
  121. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -0
  122. package/dist/canvas/nodeShapes/imagePainter.js +87 -0
  123. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -0
  124. package/dist/canvas/nodeShapes/memo.js +9 -0
  125. package/dist/canvas/nodeShapes/memo.js.map +1 -0
  126. package/dist/canvas/nodeShapes/nodePaint.js +57 -0
  127. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -0
  128. package/dist/canvas/nodeShapes/pathPainter.js +38 -0
  129. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -0
  130. package/dist/canvas/nodeShapes/poseBox.js +20 -0
  131. package/dist/canvas/nodeShapes/poseBox.js.map +1 -0
  132. package/dist/canvas/nodeShapes/rectFallbackPainter.js +38 -0
  133. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -0
  134. package/dist/canvas/nodeShapes/shapePainter.js +72 -0
  135. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -0
  136. package/dist/canvas/nodeShapes/textPainter.js +55 -0
  137. package/dist/canvas/nodeShapes/textPainter.js.map +1 -0
  138. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  139. package/dist/canvas/paintCull.js +10 -11
  140. package/dist/canvas/paintCull.js.map +1 -1
  141. package/dist/canvas/pickWalk.js +52 -63
  142. package/dist/canvas/pickWalk.js.map +1 -1
  143. package/dist/canvas/poseRotation.js +11 -23
  144. package/dist/canvas/poseRotation.js.map +1 -1
  145. package/dist/canvas/renderDebugSnapshot.js +5 -5
  146. package/dist/canvas/renderSceneToPixels.js +3 -1
  147. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  148. package/dist/canvas/sceneAdapter.js +66 -148
  149. package/dist/canvas/sceneAdapter.js.map +1 -1
  150. package/dist/canvas/sceneClipboard.js +112 -0
  151. package/dist/canvas/sceneClipboard.js.map +1 -0
  152. package/dist/canvas/sceneSlotWiring.js +4 -4
  153. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  154. package/dist/canvas/sceneViewRender.js +39 -40
  155. package/dist/canvas/sceneViewRender.js.map +1 -1
  156. package/dist/canvas/useCanvasRenderer.js +14 -6
  157. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  158. package/dist/canvas/useCanvasView.js +58 -0
  159. package/dist/canvas/useCanvasView.js.map +1 -0
  160. package/dist/canvas/useFrameLoop.js +35 -26
  161. package/dist/canvas/useFrameLoop.js.map +1 -1
  162. package/dist/canvas/useSceneLayerList.js +21 -0
  163. package/dist/canvas/useSceneLayerList.js.map +1 -0
  164. package/dist/clipboard.d.ts +10 -6
  165. package/dist/clone.d.ts +4 -3
  166. package/dist/core/adapters/arrayAdapter.js +48 -39
  167. package/dist/core/adapters/arrayAdapter.js.map +1 -1
  168. package/dist/core/device/index.js +5 -4
  169. package/dist/core/device/useDeviceProfile.js +38 -44
  170. package/dist/core/device/useDeviceProfile.js.map +1 -1
  171. package/dist/core/device/watchDevicePixelRatio.js +17 -0
  172. package/dist/core/device/watchDevicePixelRatio.js.map +1 -0
  173. package/dist/core/fillInPoseFrame.js.map +1 -1
  174. package/dist/core/geometry/poseDescriptor.js +21 -19
  175. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  176. package/dist/core/geometry/poseFrame.js +44 -0
  177. package/dist/core/geometry/poseFrame.js.map +1 -0
  178. package/dist/core/geometry/poseRotation.js.map +1 -1
  179. package/dist/core/geometry/regionHit.js +9 -10
  180. package/dist/core/geometry/regionHit.js.map +1 -1
  181. package/dist/core/geometry/unionBounds.js +31 -29
  182. package/dist/core/geometry/unionBounds.js.map +1 -1
  183. package/dist/core/isPlainObject.js +2 -11
  184. package/dist/core/ops/arrange.js +1 -0
  185. package/dist/core/ops/arrange.js.map +1 -1
  186. package/dist/core/ops/create.js +10 -5
  187. package/dist/core/ops/create.js.map +1 -1
  188. package/dist/core/ops/delete.js +12 -24
  189. package/dist/core/ops/delete.js.map +1 -1
  190. package/dist/core/ops/reorder/index.js +43 -40
  191. package/dist/core/ops/reorder/index.js.map +1 -1
  192. package/dist/core/ops/reorder/setChildOrder.js +34 -0
  193. package/dist/core/ops/reorder/setChildOrder.js.map +1 -0
  194. package/dist/core/paintKinds.js +5 -5
  195. package/dist/core/paintKinds.js.map +1 -1
  196. package/dist/core/scene/NodeProperties.js.map +1 -1
  197. package/dist/core/scene/appliedLog.js +37 -0
  198. package/dist/core/scene/appliedLog.js.map +1 -0
  199. package/dist/core/scene/arrivalWindow.js +101 -0
  200. package/dist/core/scene/arrivalWindow.js.map +1 -0
  201. package/dist/core/scene/derivedPath.js.map +1 -1
  202. package/dist/core/scene/historyFacade.js +84 -0
  203. package/dist/core/scene/historyFacade.js.map +1 -0
  204. package/dist/core/scene/kitOps.js +173 -0
  205. package/dist/core/scene/kitOps.js.map +1 -0
  206. package/dist/core/scene/layerStack.js +38 -0
  207. package/dist/core/scene/layerStack.js.map +1 -0
  208. package/dist/core/scene/lockGuard.js +37 -0
  209. package/dist/core/scene/lockGuard.js.map +1 -0
  210. package/dist/core/scene/nodeFnFields.js +5 -6
  211. package/dist/core/scene/nodeFnFields.js.map +1 -1
  212. package/dist/core/scene/nodeMemo.js +45 -19
  213. package/dist/core/scene/nodeMemo.js.map +1 -1
  214. package/dist/core/scene/nodeStore.js +126 -0
  215. package/dist/core/scene/nodeStore.js.map +1 -0
  216. package/dist/core/scene/pickability.js +6 -0
  217. package/dist/core/scene/pickability.js.map +1 -0
  218. package/dist/core/scene/poseFeed.js +38 -38
  219. package/dist/core/scene/poseFeed.js.map +1 -1
  220. package/dist/core/scene/poseOverrides.js +34 -38
  221. package/dist/core/scene/poseOverrides.js.map +1 -1
  222. package/dist/core/scene/renderOrder.js +84 -0
  223. package/dist/core/scene/renderOrder.js.map +1 -0
  224. package/dist/core/scene/scene.js +289 -866
  225. package/dist/core/scene/scene.js.map +1 -1
  226. package/dist/core/scene/serialization.js +68 -0
  227. package/dist/core/scene/serialization.js.map +1 -0
  228. package/dist/core/scene/treeOrder.js +13 -0
  229. package/dist/core/scene/treeOrder.js.map +1 -0
  230. package/dist/core/scene/types.js.map +1 -1
  231. package/dist/core/viewport/meanScale.js +1 -1
  232. package/dist/core/viewport/meanScale.js.map +1 -1
  233. package/dist/core/viewport/view.js +12 -12
  234. package/dist/core/viewport/view.js.map +1 -1
  235. package/dist/core/viewport/zoomBounds.js +10 -8
  236. package/dist/core/viewport/zoomBounds.js.map +1 -1
  237. package/dist/{cornerHandles-BCrDp_mH.d.ts → cornerHandles-CtCb8a3G.d.ts} +1 -1
  238. package/dist/debug/createDebugOverlayLayer.js +14 -14
  239. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  240. package/dist/debug/flag.js +2 -41
  241. package/dist/features/chrome-caps/useHoverTracking.js +22 -17
  242. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  243. package/dist/features/focus/gateLayer.js +3 -4
  244. package/dist/features/focus/gateLayer.js.map +1 -1
  245. package/dist/features/images/imageCache.js +19 -9
  246. package/dist/features/images/imageCache.js.map +1 -1
  247. package/dist/features/ingestion/contentHandlers.js +14 -11
  248. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  249. package/dist/features/ingestion/index.js +1 -1
  250. package/dist/features/ingestion/registerKitHandlers.js +7 -7
  251. package/dist/features/ingestion/weaselJsonHandler.js +17 -14
  252. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  253. package/dist/features/meshPaint/lazyKind.js +201 -35
  254. package/dist/features/meshPaint/lazyKind.js.map +1 -1
  255. package/dist/features/meshPaint/meshPaint.js +82 -79
  256. package/dist/features/meshPaint/meshPaint.js.map +1 -1
  257. package/dist/features/minimap/createMinimapContribution.js +42 -42
  258. package/dist/features/minimap/layers.js +44 -62
  259. package/dist/features/minimap/layers.js.map +1 -1
  260. package/dist/features/parallax/createParallaxPlane.js +10 -14
  261. package/dist/features/parallax/createParallaxPlane.js.map +1 -1
  262. package/dist/features/paths/anchorEdits.js +19 -8
  263. package/dist/features/paths/anchorEdits.js.map +1 -1
  264. package/dist/features/paths/anchors.js +31 -26
  265. package/dist/features/paths/anchors.js.map +1 -1
  266. package/dist/features/paths/booleans.js +2 -2
  267. package/dist/features/paths/index.js +13 -11
  268. package/dist/features/paths/markerCommands.js +37 -36
  269. package/dist/features/paths/markerCommands.js.map +1 -1
  270. package/dist/features/paths/pathInWorld.js +19 -19
  271. package/dist/features/paths/pathInWorld.js.map +1 -1
  272. package/dist/features/paths/pathLayer.js.map +1 -1
  273. package/dist/features/paths/strokeToPath.js +40 -0
  274. package/dist/features/paths/strokeToPath.js.map +1 -0
  275. package/dist/features/paths/tessellate/stroke.js.map +1 -1
  276. package/dist/features/patterns/commandPaint.js +18 -0
  277. package/dist/features/patterns/commandPaint.js.map +1 -0
  278. package/dist/features/patterns/index.js +5 -17
  279. package/dist/features/patterns/index.js.map +1 -1
  280. package/dist/features/patterns/rasterizeTile.js +17 -0
  281. package/dist/features/patterns/rasterizeTile.js.map +1 -0
  282. package/dist/features/patterns/resolveSpec.js +52 -44
  283. package/dist/features/patterns/resolveSpec.js.map +1 -1
  284. package/dist/features/poseRun/usePoseRun.js +8 -3
  285. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  286. package/dist/features/selection/SelectionContext.js +5 -0
  287. package/dist/features/selection/SelectionContext.js.map +1 -1
  288. package/dist/features/selection/overlay.js +18 -18
  289. package/dist/features/selection/overlay.js.map +1 -1
  290. package/dist/features/text/domOffsets.js +82 -0
  291. package/dist/features/text/domOffsets.js.map +1 -0
  292. package/dist/features/text/domRuns.js +103 -131
  293. package/dist/features/text/domRuns.js.map +1 -1
  294. package/dist/features/text/hitTest.js +5 -2
  295. package/dist/features/text/hitTest.js.map +1 -1
  296. package/dist/features/text/isTextData.js +8 -0
  297. package/dist/features/text/isTextData.js.map +1 -0
  298. package/dist/features/text/overlayDirection.js +15 -0
  299. package/dist/features/text/overlayDirection.js.map +1 -0
  300. package/dist/features/text/runs/rangeStyle.js +32 -34
  301. package/dist/features/text/runs/rangeStyle.js.map +1 -1
  302. package/dist/features/text/textCommand.js +34 -33
  303. package/dist/features/text/textCommand.js.map +1 -1
  304. package/dist/features/text/textToPath.js +40 -40
  305. package/dist/features/text/textToPath.js.map +1 -1
  306. package/dist/features/text/useSceneTextEdit.js +76 -82
  307. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  308. package/dist/features/text/useTextEdit.js +184 -160
  309. package/dist/features/text/useTextEdit.js.map +1 -1
  310. package/dist/features/tiling/createTiledLayer.js +24 -22
  311. package/dist/features/tiling/createTiledLayer.js.map +1 -1
  312. package/dist/index.d.ts +11033 -7749
  313. package/dist/index.js +316 -309
  314. package/dist/input/keyState.js +42 -43
  315. package/dist/input/keyState.js.map +1 -1
  316. package/dist/input/useKeyModifiers.js +11 -0
  317. package/dist/input/useKeyModifiers.js.map +1 -0
  318. package/dist/interactions/actions/align/align.js +8 -8
  319. package/dist/interactions/actions/clipboard/clipboardOps.js +34 -32
  320. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  321. package/dist/interactions/actions/clipboard/materializePaste.js +10 -7
  322. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
  323. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  324. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +1 -1
  325. package/dist/interactions/actions/defaultCommitAdapter.js +20 -18
  326. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  327. package/dist/interactions/actions/defaults/align.js +9 -10
  328. package/dist/interactions/actions/defaults/align.js.map +1 -1
  329. package/dist/interactions/actions/defaults/anchorEditing.js +59 -81
  330. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  331. package/dist/interactions/actions/defaults/areaSelect.js +35 -38
  332. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  333. package/dist/interactions/actions/defaults/clipboard.js +26 -10
  334. package/dist/interactions/actions/defaults/clipboard.js.map +1 -1
  335. package/dist/interactions/actions/defaults/clone.js +44 -60
  336. package/dist/interactions/actions/defaults/clone.js.map +1 -1
  337. package/dist/interactions/actions/defaults/copySubtree.js +40 -0
  338. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -0
  339. package/dist/interactions/actions/defaults/distribute.js +14 -13
  340. package/dist/interactions/actions/defaults/distribute.js.map +1 -1
  341. package/dist/interactions/actions/defaults/duplicate.js +17 -57
  342. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  343. package/dist/interactions/actions/defaults/editAnchors.js +18 -18
  344. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  345. package/dist/interactions/actions/defaults/flip.js +52 -46
  346. package/dist/interactions/actions/defaults/flip.js.map +1 -1
  347. package/dist/interactions/actions/defaults/group.js +43 -48
  348. package/dist/interactions/actions/defaults/group.js.map +1 -1
  349. package/dist/interactions/actions/defaults/ingest.js +35 -33
  350. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  351. package/dist/interactions/actions/defaults/insert.js +50 -51
  352. package/dist/interactions/actions/defaults/insert.js.map +1 -1
  353. package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -7
  354. package/dist/interactions/actions/defaults/lassoSelect.js +67 -70
  355. package/dist/interactions/actions/defaults/lassoSelect.js.map +1 -1
  356. package/dist/interactions/actions/defaults/move.js +267 -249
  357. package/dist/interactions/actions/defaults/move.js.map +1 -1
  358. package/dist/interactions/actions/defaults/nudge.js +40 -68
  359. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  360. package/dist/interactions/actions/defaults/nudgeSteps.js +37 -0
  361. package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -0
  362. package/dist/interactions/actions/defaults/reorder.js +2 -0
  363. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  364. package/dist/interactions/actions/defaults/resize.js +104 -98
  365. package/dist/interactions/actions/defaults/resize.js.map +1 -1
  366. package/dist/interactions/actions/defaults/rotate.js +111 -110
  367. package/dist/interactions/actions/defaults/rotate.js.map +1 -1
  368. package/dist/interactions/actions/defaults/setFill.js +7 -7
  369. package/dist/interactions/actions/defaults/setFillOpacity.js +4 -4
  370. package/dist/interactions/actions/defaults/setStroke.js +12 -12
  371. package/dist/interactions/actions/defaults/setStrokeOpacity.js +6 -6
  372. package/dist/interactions/actions/defaults/sliceOps.js +19 -19
  373. package/dist/interactions/actions/defaults/viewportDragPan.js +37 -26
  374. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  375. package/dist/interactions/actions/edit-anchors/geometry.js +28 -23
  376. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  377. package/dist/interactions/actions/flip/helpers.js +30 -17
  378. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  379. package/dist/interactions/actions/hitSelection.js +8 -0
  380. package/dist/interactions/actions/hitSelection.js.map +1 -0
  381. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +14 -18
  382. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -1
  383. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +5 -5
  384. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -1
  385. package/dist/interactions/actions/move/behaviors/snapToContainer.js +32 -21
  386. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  387. package/dist/interactions/actions/move/gestureAdapter.js +32 -15
  388. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  389. package/dist/interactions/actions/move/landedDescendants.js +33 -0
  390. package/dist/interactions/actions/move/landedDescendants.js.map +1 -0
  391. package/dist/interactions/actions/outlines/createOutlines.js +18 -18
  392. package/dist/interactions/actions/poseDescriptorDep.js +16 -4
  393. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  394. package/dist/interactions/actions/poseFrame.js +11 -6
  395. package/dist/interactions/actions/poseFrame.js.map +1 -1
  396. package/dist/interactions/actions/previewOverrides.js +5 -5
  397. package/dist/interactions/actions/previewOverrides.js.map +1 -1
  398. package/dist/interactions/actions/selectionSubtree.js +69 -0
  399. package/dist/interactions/actions/selectionSubtree.js.map +1 -0
  400. package/dist/interactions/actions/useStandardActions.js +66 -62
  401. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  402. package/dist/interactions/gestures/dragGesture/dragGesture.js +4 -7
  403. package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -1
  404. package/dist/interactions/gestures/dragGesture/dragPointOf.js +23 -0
  405. package/dist/interactions/gestures/dragGesture/dragPointOf.js.map +1 -0
  406. package/dist/interactions/gestures/handleDrag/handleDrag.js +21 -26
  407. package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -1
  408. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +8 -6
  409. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  410. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +8 -4
  411. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
  412. package/dist/{math-Drrw4ewZ.d.ts → math-J-ACHyEg.d.ts} +1 -2
  413. package/dist/math.d.ts +2 -3
  414. package/dist/move.d.ts +12 -11
  415. package/dist/{originProjection-DEklpDc_.d.ts → originProjection-gHnOup4e.d.ts} +1 -1
  416. package/dist/{registerProgram-BMZRDgrh.d.ts → registerProgram-T9S_PfAX.d.ts} +18 -7
  417. package/dist/renderer/DrawCommand.js.map +1 -1
  418. package/dist/renderer/WeaselRenderer.js +75 -73
  419. package/dist/renderer/WeaselRenderer.js.map +1 -1
  420. package/dist/renderer/cache/GLImageCache.js +15 -5
  421. package/dist/renderer/cache/GLImageCache.js.map +1 -1
  422. package/dist/renderer/cache/GLMeshCache.js +23 -23
  423. package/dist/renderer/cache/GLMeshCache.js.map +1 -1
  424. package/dist/renderer/cache/GLTextureCache.js +18 -1
  425. package/dist/renderer/cache/GLTextureCache.js.map +1 -1
  426. package/dist/renderer/cache/cache.js.map +1 -1
  427. package/dist/renderer/cache/markerCommandCache.js.map +1 -1
  428. package/dist/renderer/cache/strokeMeshCache.js.map +1 -1
  429. package/dist/renderer/cullDrawCommands.js +11 -11
  430. package/dist/renderer/draw/batch.js +133 -0
  431. package/dist/renderer/draw/batch.js.map +1 -0
  432. package/dist/renderer/draw/clip.js +89 -0
  433. package/dist/renderer/draw/clip.js.map +1 -0
  434. package/dist/renderer/draw/customShader.js +230 -0
  435. package/dist/renderer/draw/customShader.js.map +1 -0
  436. package/dist/renderer/draw/drawTriangles.js +8 -0
  437. package/dist/renderer/draw/drawTriangles.js.map +1 -0
  438. package/dist/renderer/draw/effects.js +28 -0
  439. package/dist/renderer/draw/effects.js.map +1 -0
  440. package/dist/renderer/draw/flushBatch.js +35 -0
  441. package/dist/renderer/draw/flushBatch.js.map +1 -0
  442. package/dist/renderer/draw/gradient.js +90 -0
  443. package/dist/renderer/draw/gradient.js.map +1 -0
  444. package/dist/renderer/draw/image.js +38 -0
  445. package/dist/renderer/draw/image.js.map +1 -0
  446. package/dist/renderer/draw/mesh.js +16 -0
  447. package/dist/renderer/draw/mesh.js.map +1 -0
  448. package/dist/renderer/draw/paintBind.js +70 -0
  449. package/dist/renderer/draw/paintBind.js.map +1 -0
  450. package/dist/renderer/draw/pathPaint.js +142 -0
  451. package/dist/renderer/draw/pathPaint.js.map +1 -0
  452. package/dist/renderer/draw/scratchPass.js +83 -0
  453. package/dist/renderer/draw/scratchPass.js.map +1 -0
  454. package/dist/renderer/draw/stencil.js +28 -0
  455. package/dist/renderer/draw/stencil.js.map +1 -0
  456. package/dist/renderer/draw/text.js +167 -0
  457. package/dist/renderer/draw/text.js.map +1 -0
  458. package/dist/renderer/draw/uniforms.js +77 -0
  459. package/dist/renderer/draw/uniforms.js.map +1 -0
  460. package/dist/renderer/draw.js +60 -1116
  461. package/dist/renderer/draw.js.map +1 -1
  462. package/dist/renderer/effects/EffectTargets.js +3 -0
  463. package/dist/renderer/effects/EffectTargets.js.map +1 -1
  464. package/dist/renderer/effects/composite.js +7 -5
  465. package/dist/renderer/effects/composite.js.map +1 -1
  466. package/dist/renderer/index.js +18 -17
  467. package/dist/renderer/math/color.js +63 -83
  468. package/dist/renderer/math/color.js.map +1 -1
  469. package/dist/renderer/math/mat3.js +15 -11
  470. package/dist/renderer/math/mat3.js.map +1 -1
  471. package/dist/renderer/math/viewToMat3.js +1 -1
  472. package/dist/renderer/math/viewToMat3.js.map +1 -1
  473. package/dist/renderer/shaders/ShaderProgram.js +13 -13
  474. package/dist/renderer/shaders/ShaderProgram.js.map +1 -1
  475. package/dist/renderer/shaders/glyphPaint.js +3 -3
  476. package/dist/renderer/shaders/glyphPaint.js.map +1 -1
  477. package/dist/renderer/shaders/gradFill.js +2 -1
  478. package/dist/renderer/shaders/gradFill.js.map +1 -1
  479. package/dist/renderer/shaders/pathFill.js +2 -1
  480. package/dist/renderer/shaders/pathFill.js.map +1 -1
  481. package/dist/renderer/shaders/patternFill.js +2 -1
  482. package/dist/renderer/shaders/patternFill.js.map +1 -1
  483. package/dist/renderer/shaders/registerProgram.js.map +1 -1
  484. package/dist/renderer/strokeLengths.js.map +1 -1
  485. package/dist/renderer/textures/registerTexture.js +25 -5
  486. package/dist/renderer/textures/registerTexture.js.map +1 -1
  487. package/dist/renderer.d.ts +16 -15
  488. package/dist/renderer.js +17 -16
  489. package/dist/resize.d.ts +5 -6
  490. package/dist/resize.js +5 -5
  491. package/dist/style.css +1 -1
  492. package/dist/test-hook/install.js +12 -6
  493. package/dist/test-hook/install.js.map +1 -1
  494. package/dist/{test-seams-CuIxe0xY.d.ts → test-seams-DM2B87-g.d.ts} +4 -4
  495. package/dist/test-seams.d.ts +2 -2
  496. package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
  497. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  498. package/dist/tools/builtin/hand/useHandTool.js +1 -0
  499. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  500. package/dist/tools/builtin/lasso/useLassoTool.js +11 -11
  501. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  502. package/dist/tools/builtin/line/useLineTool.js +1 -0
  503. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  504. package/dist/tools/builtin/pen/usePenTool.js +153 -103
  505. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  506. package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
  507. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  508. package/dist/tools/builtin/polygon/usePolygonTool.js +13 -8
  509. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  510. package/dist/tools/builtin/rect/useRectTool.js +1 -0
  511. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  512. package/dist/tools/builtin/select/selectionContributions.js +24 -23
  513. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  514. package/dist/tools/builtin/select/useSelectTool.js +51 -48
  515. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  516. package/dist/tools/builtin/shared/pointerFollower.js +17 -0
  517. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -0
  518. package/dist/tools/builtin/slice/useSliceTool.js +49 -54
  519. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  520. package/dist/tools/builtin/star/useStarTool.js +22 -16
  521. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  522. package/dist/tools/builtin/text/useTextTool.js +1 -0
  523. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  524. package/dist/tools/useKeybindings.js +14 -30
  525. package/dist/tools/useKeybindings.js.map +1 -1
  526. package/dist/{types-B_9g6hMM.d.ts → types-B4iJRHC3.d.ts} +5 -1
  527. package/dist/{types-A37hYkeR.d.ts → types-k-5Oqh-U.d.ts} +31 -7
  528. package/dist/util/color.js +3 -3
  529. package/dist/util/color.js.map +1 -1
  530. package/dist/util/paint.js.map +1 -1
  531. package/dist/version.js +1 -1
  532. package/package.json +20 -18
  533. package/dist/autoPoseDescriptor-vCdt55xm.d.ts +0 -27
  534. package/dist/builtins-C-VgUlWI.d.ts +0 -4514
  535. package/dist/core/isPlainObject.js.map +0 -1
  536. package/dist/debug/flag.js.map +0 -1
  537. package/dist/interactions/actions/defaults/freshNodeId.js +0 -10
  538. package/dist/interactions/actions/defaults/freshNodeId.js.map +0 -1
  539. package/dist/renderer/shaders/imageFill.js +0 -14
  540. package/dist/renderer/shaders/imageFill.js.map +0 -1
  541. package/dist/tools/prefs.js +0 -62
  542. package/dist/tools/prefs.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"canvasRenderer.js","names":["TENANTS","shaderKeyOf","shaders","h","registerShaders","handle","free","set","held","leaseCanvasRenderer","bind","size","dpr","tile","options","shared","canvas","width","height","gl","renderer","WeaselRenderer","shaderKey","tileX","tileY","commands","viewToMat3","view","CANVAS_LEASES","paintCanvas","lease","releaseCanvasRenderer"],"sources":["../../src/canvas/canvasRenderer.ts"],"sourcesContent":["/**\n * The one renderer lifetime in core. Every on-screen surface — `<Canvas>`,\n * `<SceneViewCanvas>`, `<MinimapCanvas>`, `<DrawCanvas>` — holds its\n * `WeaselRenderer` through a `leaseCanvasRenderer` lease (the detached ones via\n * `useCanvasRenderer`): created on first paint, resized when the surface's\n * size or density changes, rebuilt when the surface moves to another element,\n * and freed on release.\n *\n * A lease holds its own renderer, so several can share one element: each\n * tenant painting a `tile` of a shared buffer gets a renderer of its own on\n * the element's one context. Release frees only what that renderer created;\n * the context itself is never lost.\n */\nimport { WeaselRenderer, type RenderOptions } from '../renderer/WeaselRenderer';\nimport { viewToMat3 } from '../renderer/math/viewToMat3';\nimport type { ShaderProgramHandle } from '../renderer/shaders/registerProgram';\nimport type { DrawCommand } from '../renderer/DrawCommand';\nimport type { View } from '../core/viewport/view';\n\n/** The live renderers painting into each element, across every lease. */\nconst TENANTS: WeakMap<HTMLCanvasElement, Set<WeaselRenderer>> = new WeakMap();\n\n/** A renderer painting into the canvas, if any lease holds one. Test seam. */\nexport function cachedCanvasRenderer(canvas: HTMLCanvasElement): WeaselRenderer | undefined {\n const set = TENANTS.get(canvas);\n return set ? set.values().next().value : undefined;\n}\n\n/** The size and density to paint a canvas at. `dpr` defaults to\n * `window.devicePixelRatio`, read per paint. */\nexport interface CanvasPaintSize {\n width: number;\n height: number;\n dpr?: number;\n}\n\n/** How one paint reaches the canvas, beyond its size. */\nexport interface CanvasPaintOptions {\n /** Paint a `width × height` tile of a buffer other surfaces share, at this\n * origin in CSS pixels. The buffer is then the caller's to size: the\n * renderer never resizes the element, which would have every co-tenant\n * resize it to its own pane. Omit to own the whole element. */\n tile?: { x: number; y: number } | null;\n /** `WeaselRendererOptions.flattenTolerance`, applied from this paint on. */\n flattenTolerance?: number;\n /** Custom programs to compile on the renderer. Compiled when the renderer\n * is created, and again when the set of ids changes. */\n shaders?: readonly ShaderProgramHandle[];\n}\n\n/** A paint's options, plus what `paint` hands `WeaselRenderer.render`. */\nexport interface CanvasRenderOptions extends CanvasPaintOptions {\n render?: RenderOptions;\n}\n\n/** A canvas renderer held for a surface's lifetime. */\nexport interface CanvasRendererLease {\n /** Draw `commands` into `canvas` — screen-space, one unit per CSS pixel,\n * with `view` passed on as the frame's world→screen transform. `bind`,\n * then render. Returns `false` without painting where `bind` finds no\n * renderer. */\n paint(\n canvas: HTMLCanvasElement,\n commands: DrawCommand[],\n view: View,\n size: CanvasPaintSize,\n options?: CanvasRenderOptions,\n ): boolean;\n /** The renderer that paints `canvas` at `size`, ready to render: created on\n * first use, resized, and given this paint's tile, tolerance and shaders.\n * Frees the previous renderer first if the surface moved to another\n * element, or between owning it whole and painting a tile of it. `null`\n * where no WebGL2 context is available (jsdom, or a failed context\n * creation), so a caller can skip building a frame nobody will see. */\n bind(canvas: HTMLCanvasElement, size: CanvasPaintSize, options?: CanvasPaintOptions): WeaselRenderer | null;\n /** Free the held renderer and every GL object it owns. A later `paint`\n * creates a fresh one. */\n release(): void;\n}\n\ninterface Held {\n canvas: HTMLCanvasElement;\n renderer: WeaselRenderer;\n shared: boolean;\n width: number;\n height: number;\n dpr: number;\n tileX: number | null;\n tileY: number | null;\n flattenTolerance: number | undefined;\n shaderKey: string;\n}\n\nconst shaderKeyOf = (shaders: readonly ShaderProgramHandle[] | undefined): string =>\n shaders?.map((h) => h.id).join('|') ?? '';\n\nfunction registerShaders(renderer: WeaselRenderer, shaders: readonly ShaderProgramHandle[] | undefined): void {\n if (!shaders) return;\n for (const handle of shaders) {\n try {\n renderer.registerProgram(handle);\n } catch (e) {\n console.warn(`weasel: failed to register shader \"${handle.id}\":`, e);\n }\n }\n}\n\nfunction free(held: Held): void {\n const set = TENANTS.get(held.canvas);\n set?.delete(held.renderer);\n if (set && set.size === 0) TENANTS.delete(held.canvas);\n held.renderer.dispose();\n}\n\n/** Hold the renderer of the canvas a surface paints into, until released. */\nexport function leaseCanvasRenderer(): CanvasRendererLease {\n let held: Held | null = null;\n const bind = (canvas: HTMLCanvasElement, size: CanvasPaintSize, options: CanvasPaintOptions = {}): WeaselRenderer | null => {\n const { width, height } = size;\n const dpr = size.dpr ?? (typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1);\n const tile = options.tile ?? null;\n const shared = tile !== null;\n\n if (held && (held.canvas !== canvas || held.shared !== shared)) {\n free(held);\n held = null;\n }\n if (!held) {\n const gl = canvas.getContext('webgl2', { preserveDrawingBuffer: true, stencil: true });\n if (!gl || typeof (gl as Partial<WebGL2RenderingContext>).enable !== 'function') return null;\n let renderer: WeaselRenderer;\n try {\n renderer = new WeaselRenderer({\n gl: gl as WebGL2RenderingContext,\n ...(shared ? {} : { canvas }),\n width, height, dpr,\n flattenTolerance: options.flattenTolerance,\n });\n } catch {\n return null;\n }\n held = { canvas, renderer, shared, width, height, dpr, tileX: null, tileY: null,\n flattenTolerance: options.flattenTolerance, shaderKey: '' };\n let set = TENANTS.get(canvas);\n if (!set) { set = new Set(); TENANTS.set(canvas, set); }\n set.add(renderer);\n } else {\n if (held.width !== width || held.height !== height || held.dpr !== dpr) {\n held.renderer.resize({ width, height, dpr });\n held.width = width;\n held.height = height;\n held.dpr = dpr;\n }\n if (held.flattenTolerance !== options.flattenTolerance) {\n held.renderer.setFlattenTolerance(options.flattenTolerance);\n held.flattenTolerance = options.flattenTolerance;\n }\n }\n\n const { renderer } = held;\n const shaderKey = shaderKeyOf(options.shaders);\n if (shaderKey !== held.shaderKey) {\n registerShaders(renderer, options.shaders);\n held.shaderKey = shaderKey;\n }\n const tileX = tile?.x ?? null;\n const tileY = tile?.y ?? null;\n if (tileX !== held.tileX || tileY !== held.tileY) {\n renderer.setTarget(tile ? { origin: { x: tile.x, y: tile.y } } : null);\n held.tileX = tileX;\n held.tileY = tileY;\n }\n return renderer;\n };\n return {\n bind,\n paint(canvas, commands, view, size, options) {\n const renderer = bind(canvas, size, options);\n if (!renderer) return false;\n renderer.render(commands, viewToMat3(view), options?.render);\n return true;\n },\n release() {\n if (held) free(held);\n held = null;\n },\n };\n}\n\n/** Leases held on a canvas's behalf by `paintCanvas`, one per element. */\nconst CANVAS_LEASES: WeakMap<HTMLCanvasElement, CanvasRendererLease> = new WeakMap();\n\n/**\n * Paint `canvas` through a lease held for the element itself, for callers\n * with no component lifetime of their own (`renderSceneToCanvas`). The\n * renderer lives until `releaseCanvasRenderer(canvas)`.\n */\nexport function paintCanvas(\n canvas: HTMLCanvasElement,\n commands: DrawCommand[],\n view: View,\n size: CanvasPaintSize,\n): boolean {\n let lease = CANVAS_LEASES.get(canvas);\n if (!lease) {\n lease = leaseCanvasRenderer();\n CANVAS_LEASES.set(canvas, lease);\n }\n return lease.paint(canvas, commands, view, size);\n}\n\n/** Free the renderer `paintCanvas` holds for the canvas, and every GL object\n * it owns. The next paint creates a fresh one. Renderers a surface component\n * holds are that component's to free, on unmount. */\nexport function releaseCanvasRenderer(canvas: HTMLCanvasElement): void {\n const lease = CANVAS_LEASES.get(canvas);\n if (!lease) return;\n CANVAS_LEASES.delete(canvas);\n lease.release();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"canvasRenderer.js","names":["TENANTS","REFUSED","shaderKeyOf","shaders","h","registerShaders","handle","free","set","held","leaseCanvasRenderer","restoredSubs","bind","size","dpr","tile","options","shared","canvas","width","height","gl","renderer","WeaselRenderer","mine","fn","shaderKey","tileX","tileY","commands","viewToMat3","view","CANVAS_LEASES","paintCanvas","lease","releaseCanvasRenderer"],"sources":["../../src/canvas/canvasRenderer.ts"],"sourcesContent":["/**\n * The one renderer lifetime in core. Every on-screen surface — `<Canvas>`,\n * `<SceneViewCanvas>`, `<MinimapCanvas>`, `<DrawCanvas>` — holds its\n * `WeaselRenderer` through a `leaseCanvasRenderer` lease (the detached ones via\n * `useCanvasRenderer`): created on first paint, resized when the surface's\n * size or density changes, rebuilt when the surface moves to another element,\n * and freed on release.\n *\n * A lease holds its own renderer, so several can share one element: each\n * tenant painting a `tile` of a shared buffer gets a renderer of its own on\n * the element's one context. Release frees only what that renderer created;\n * the context itself is never lost.\n */\nimport { WeaselRenderer, type RenderOptions } from '../renderer/WeaselRenderer';\nimport { viewToMat3 } from '../renderer/math/viewToMat3';\nimport type { ShaderProgramHandle } from '../renderer/shaders/registerProgram';\nimport type { DrawCommand } from '../renderer/DrawCommand';\nimport type { View } from '../core/viewport/view';\n\n/** The live renderers painting into each element, across every lease. */\nconst TENANTS: WeakMap<HTMLCanvasElement, Set<WeaselRenderer>> = new WeakMap();\n\n/** Canvases whose context the renderer refused, so a redraw does not rebuild\n * and fail again, and the reason is reported once. */\nconst REFUSED: WeakSet<HTMLCanvasElement> = new WeakSet();\n\n/** A renderer painting into the canvas, if any lease holds one. Test seam. */\nexport function cachedCanvasRenderer(canvas: HTMLCanvasElement): WeaselRenderer | undefined {\n const set = TENANTS.get(canvas);\n return set ? set.values().next().value : undefined;\n}\n\n/** The size and density to paint a canvas at. `dpr` defaults to\n * `window.devicePixelRatio`, read per paint. */\nexport interface CanvasPaintSize {\n width: number;\n height: number;\n dpr?: number;\n}\n\n/** How one paint reaches the canvas, beyond its size. */\nexport interface CanvasPaintOptions {\n /** Paint a `width × height` tile of a buffer other surfaces share, at this\n * origin in CSS pixels. The buffer is then the caller's to size: the\n * renderer never resizes the element, which would have every co-tenant\n * resize it to its own pane. Omit to own the whole element. */\n tile?: { x: number; y: number } | null;\n /** `WeaselRendererOptions.flattenTolerance`, applied from this paint on. */\n flattenTolerance?: number;\n /** Custom programs to compile on the renderer. Compiled when the renderer\n * is created, and again when the set of ids changes. */\n shaders?: readonly ShaderProgramHandle[];\n}\n\n/** A paint's options, plus what `paint` hands `WeaselRenderer.render`. */\nexport interface CanvasRenderOptions extends CanvasPaintOptions {\n render?: RenderOptions;\n}\n\n/** A canvas renderer held for a surface's lifetime. */\nexport interface CanvasRendererLease {\n /** Draw `commands` into `canvas` — screen-space, one unit per CSS pixel,\n * with `view` passed on as the frame's world→screen transform. `bind`,\n * then render. Returns `false` without painting where `bind` finds no\n * renderer. */\n paint(\n canvas: HTMLCanvasElement,\n commands: DrawCommand[],\n view: View,\n size: CanvasPaintSize,\n options?: CanvasRenderOptions,\n ): boolean;\n /** The renderer that paints `canvas` at `size`, ready to render: created on\n * first use, resized, and given this paint's tile, tolerance and shaders.\n * Frees the previous renderer first if the surface moved to another\n * element, or between owning it whole and painting a tile of it. `null`\n * where no WebGL2 context is available (jsdom, a failed context creation,\n * or a context that is lost for now), so a caller can skip building a frame\n * nobody will see. */\n bind(canvas: HTMLCanvasElement, size: CanvasPaintSize, options?: CanvasPaintOptions): WeaselRenderer | null;\n /** Run `fn` when the canvas gets a lost context back, after the renderer\n * has rebuilt itself on it. Nothing repaints a restored buffer on its own.\n * Returns an unsubscribe. */\n subscribeRestored(fn: () => void): () => void;\n /** Free the held renderer and every GL object it owns. A later `paint`\n * creates a fresh one. */\n release(): void;\n}\n\ninterface Held {\n canvas: HTMLCanvasElement;\n renderer: WeaselRenderer;\n shared: boolean;\n lost: boolean;\n onLost: () => void;\n onRestored: () => void;\n width: number;\n height: number;\n dpr: number;\n tileX: number | null;\n tileY: number | null;\n flattenTolerance: number | undefined;\n shaderKey: string;\n}\n\nconst shaderKeyOf = (shaders: readonly ShaderProgramHandle[] | undefined): string =>\n shaders?.map((h) => h.id).join('|') ?? '';\n\nfunction registerShaders(renderer: WeaselRenderer, shaders: readonly ShaderProgramHandle[] | undefined): void {\n if (!shaders) return;\n for (const handle of shaders) {\n try {\n renderer.registerProgram(handle);\n } catch (e) {\n console.warn(`weasel: failed to register shader \"${handle.id}\":`, e);\n }\n }\n}\n\nfunction free(held: Held): void {\n const set = TENANTS.get(held.canvas);\n set?.delete(held.renderer);\n held.canvas.removeEventListener('webglcontextlost', held.onLost);\n held.canvas.removeEventListener('webglcontextrestored', held.onRestored);\n if (set && set.size === 0) TENANTS.delete(held.canvas);\n held.renderer.dispose();\n}\n\n/** Hold the renderer of the canvas a surface paints into, until released. */\nexport function leaseCanvasRenderer(): CanvasRendererLease {\n let held: Held | null = null;\n const restoredSubs = new Set<() => void>();\n const bind = (canvas: HTMLCanvasElement, size: CanvasPaintSize, options: CanvasPaintOptions = {}): WeaselRenderer | null => {\n const { width, height } = size;\n const dpr = size.dpr ?? (typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1);\n const tile = options.tile ?? null;\n const shared = tile !== null;\n\n if (held && (held.canvas !== canvas || held.shared !== shared)) {\n free(held);\n held = null;\n }\n if (!held) {\n if (REFUSED.has(canvas)) return null;\n const gl = canvas.getContext('webgl2', { preserveDrawingBuffer: true, stencil: true });\n if (!gl || typeof (gl as Partial<WebGL2RenderingContext>).enable !== 'function') return null;\n let renderer: WeaselRenderer;\n try {\n renderer = new WeaselRenderer({\n gl: gl as WebGL2RenderingContext,\n ...(shared ? {} : { canvas }),\n width, height, dpr,\n flattenTolerance: options.flattenTolerance,\n });\n } catch (e) {\n // A lost context fails to compile and may yet come back; anything\n // else fails the same way next time.\n if (!(gl as Partial<WebGL2RenderingContext>).isContextLost?.()) {\n REFUSED.add(canvas);\n console.warn('weasel: this canvas cannot be painted:', e);\n }\n return null;\n }\n // Added after the renderer's own listeners, so a subscriber runs against\n // a renderer that has already recompiled.\n const mine: Held = held = {\n canvas, renderer, shared, width, height, dpr, tileX: null, tileY: null,\n flattenTolerance: options.flattenTolerance, shaderKey: '',\n lost: false,\n onLost: () => { mine.lost = true; },\n onRestored: () => {\n mine.lost = false;\n for (const fn of [...restoredSubs]) fn();\n },\n };\n canvas.addEventListener('webglcontextlost', held.onLost);\n canvas.addEventListener('webglcontextrestored', held.onRestored);\n let set = TENANTS.get(canvas);\n if (!set) { set = new Set(); TENANTS.set(canvas, set); }\n set.add(renderer);\n } else {\n // React writes the element's `width` and `height` attributes in CSS\n // pixels on every size change, so a size that went away and came back\n // matches the record while the buffer does not.\n const stale = !shared\n && (canvas.width !== Math.round(width * dpr) || canvas.height !== Math.round(height * dpr));\n if (stale || held.width !== width || held.height !== height || held.dpr !== dpr) {\n held.renderer.resize({ width, height, dpr });\n held.width = width;\n held.height = height;\n held.dpr = dpr;\n }\n if (held.flattenTolerance !== options.flattenTolerance) {\n held.renderer.setFlattenTolerance(options.flattenTolerance);\n held.flattenTolerance = options.flattenTolerance;\n }\n }\n\n if (held.lost) return null;\n const { renderer } = held;\n const shaderKey = shaderKeyOf(options.shaders);\n if (shaderKey !== held.shaderKey) {\n registerShaders(renderer, options.shaders);\n held.shaderKey = shaderKey;\n }\n const tileX = tile?.x ?? null;\n const tileY = tile?.y ?? null;\n if (tileX !== held.tileX || tileY !== held.tileY) {\n renderer.setTarget(tile ? { origin: { x: tile.x, y: tile.y } } : null);\n held.tileX = tileX;\n held.tileY = tileY;\n }\n return renderer;\n };\n return {\n bind,\n paint(canvas, commands, view, size, options) {\n const renderer = bind(canvas, size, options);\n if (!renderer) return false;\n renderer.render(commands, viewToMat3(view), options?.render);\n return true;\n },\n subscribeRestored(fn) {\n restoredSubs.add(fn);\n return () => { restoredSubs.delete(fn); };\n },\n release() {\n if (held) free(held);\n held = null;\n },\n };\n}\n\n/** Leases held on a canvas's behalf by `paintCanvas`, one per element. */\nconst CANVAS_LEASES: WeakMap<HTMLCanvasElement, CanvasRendererLease> = new WeakMap();\n\n/**\n * Paint `canvas` through a lease held for the element itself, for callers\n * with no component lifetime of their own (`renderSceneToCanvas`). The\n * renderer lives until `releaseCanvasRenderer(canvas)`.\n */\nexport function paintCanvas(\n canvas: HTMLCanvasElement,\n commands: DrawCommand[],\n view: View,\n size: CanvasPaintSize,\n): boolean {\n let lease = CANVAS_LEASES.get(canvas);\n if (!lease) {\n lease = leaseCanvasRenderer();\n CANVAS_LEASES.set(canvas, lease);\n }\n return lease.paint(canvas, commands, view, size);\n}\n\n/** Free the renderer `paintCanvas` holds for the canvas, and every GL object\n * it owns. The next paint creates a fresh one. Renderers a surface component\n * holds are that component's to free, on unmount. */\nexport function releaseCanvasRenderer(canvas: HTMLCanvasElement): void {\n const lease = CANVAS_LEASES.get(canvas);\n if (!lease) return;\n CANVAS_LEASES.delete(canvas);\n lease.release();\n}\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { useEffect as e } from "react";
2
+ import { useDepRegistry as t } from "@weasel-js/routing/react";
3
+ //#region src/canvas/deps/changes.ts
4
+ function n(n, r) {
5
+ let i = t();
6
+ e(() => n.subscribe(() => i.changed?.()), [n, i]), e(() => {
7
+ i.changed?.();
8
+ }, [i, r]);
9
+ }
10
+ //#endregion
11
+ export { n as useDepChangeNotices };
12
+
13
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.js","names":["useDepChangeNotices","registry","useDepRegistry","useEffect","scene","selected"],"sources":["../../../src/canvas/deps/changes.ts"],"sourcesContent":["/**\n * `useDepChangeNotices` — tells the dep registry when the scene or the\n * selection changed. Sources are thunks, so nothing else lets chrome showing\n * an action's `enabled` or `active` state know to read them again.\n */\nimport { useEffect } from 'react';\nimport { useDepRegistry } from '@weasel-js/routing/react';\n\nexport function useDepChangeNotices(\n scene: { subscribe(listener: () => void): () => void },\n selected: readonly unknown[],\n): void {\n const registry = useDepRegistry();\n useEffect(() => scene.subscribe(() => registry.changed?.()), [scene, registry]);\n useEffect(() => { registry.changed?.(); }, [registry, selected]);\n}\n"],"mappings":";;;AAQA,SAAgBA,EACd,GACA,GACM;CACN,IAAMC,IAAWC,EAAe;CAEhC,AADAC,QAAgBC,EAAM,gBAAgBH,EAAS,UAAU,CAAC,GAAG,CAACG,GAAOH,CAAQ,CAAC,GAC9EE,QAAgB;EAAE,EAAS,UAAU;CAAG,GAAG,CAACF,GAAUI,CAAQ,CAAC;AACjE"}
@@ -1,7 +1,7 @@
1
1
  import { createTransformOp as e } from "../../core/ops/transform.js";
2
- import { createSetDataOp as t } from "../../core/ops/setData.js";
3
- import { isRectPose as n } from "../../interactions/actions/resize/autoPoseDescriptor.js";
4
- import { pathInWorld as r, worldEditToStorage as i } from "../../features/paths/pathInWorld.js";
2
+ import { isRectPose as t } from "../../interactions/actions/resize/autoPoseDescriptor.js";
3
+ import { pathInWorld as n, worldEditToStorage as r } from "../../features/paths/pathInWorld.js";
4
+ import { createSetDataOp as i } from "../../core/ops/setData.js";
5
5
  import { useCallback as a, useState as o } from "react";
6
6
  import { useLatest as s } from "@weasel-js/react";
7
7
  import { recordModeSwitch as c } from "@weasel-js/routing";
@@ -10,48 +10,48 @@ import { useDepSource as l } from "@weasel-js/routing/react";
10
10
  function u(e) {
11
11
  if (!e) return null;
12
12
  if (e.pose?.kind === "polygon") return { kind: "pose" };
13
- let t = e.data;
14
- return t?.path && t.path.kind === "polygon" && n(e.pose) ? {
13
+ let n = e.data;
14
+ return n?.path && n.path.kind === "polygon" && t(e.pose) ? {
15
15
  kind: "data",
16
16
  pose: e.pose,
17
- data: t
17
+ data: n
18
18
  } : null;
19
19
  }
20
20
  function d(e) {
21
21
  if (!e) return null;
22
22
  let t = u(e);
23
- return t ? t.kind === "pose" ? e.pose : r(t.data.path, t.pose) : null;
23
+ return t ? t.kind === "pose" ? e.pose : n(t.data.path, t.pose) : null;
24
24
  }
25
25
  var f = /* @__PURE__ */ new Set();
26
- function p(n, r, p, m, h) {
27
- let g = s(n), _ = s(r), v = s(p), y = s(h?.anchorEditingAllowed), [b, x] = o(""), S = a((e) => {
26
+ function p(t, n, p, m, h) {
27
+ let g = s(t), _ = s(n), v = s(p), y = s(h?.anchorEditingAllowed), [b, x] = o(""), S = a((e) => {
28
28
  x(e ?? "");
29
29
  }, []), C = s(m), w = s(S), T = () => C.current ? C.current.getEditingId() : b;
30
30
  l("editAnchors", () => {
31
- let n = g.current, r = v.current, a = _.current, o = C.current, s = T();
31
+ let t = g.current, n = v.current, a = _.current, o = C.current, s = T();
32
32
  if (s) {
33
- let e = n.get(s), t = a.current.includes(s), r = !y.current || y.current();
34
- (!e || !t || !r) && (s = "");
33
+ let e = t.get(s), n = a.current.includes(s), r = !y.current || y.current();
34
+ (!e || !n || !r) && (s = "");
35
35
  }
36
- let l = s ? o?.getSelectedAnchors() ?? f : f, p = s ? o?.getMarquee() ?? null : null, m = (r, a, o) => {
37
- let s = a, c = n.get(r);
36
+ let l = s ? o?.getSelectedAnchors() ?? f : f, p = s ? o?.getMarquee() ?? null : null, m = (n, a, o) => {
37
+ let s = a, c = t.get(n);
38
38
  if (!c) return [];
39
39
  let l = u(c);
40
40
  if (!l) return [];
41
41
  if (l.kind === "pose") return [e({
42
- id: r,
42
+ id: n,
43
43
  from: c.pose,
44
44
  to: s,
45
45
  label: o
46
46
  })];
47
- let { pose: d, path: f } = i(l.pose, s);
47
+ let { pose: d, path: f } = r(l.pose, s);
48
48
  return [e({
49
- id: r,
49
+ id: n,
50
50
  from: c.pose,
51
51
  to: d,
52
52
  label: o
53
- }), t({
54
- id: r,
53
+ }), i({
54
+ id: n,
55
55
  from: c.data,
56
56
  to: {
57
57
  ...c.data,
@@ -75,21 +75,21 @@ function p(n, r, p, m, h) {
75
75
  s && o?.setMarquee(e);
76
76
  },
77
77
  getEditablePath(e) {
78
- return d(n.get(e));
78
+ return d(t.get(e));
79
79
  },
80
80
  getStorageKind(e) {
81
- return u(n.get(e))?.kind ?? null;
81
+ return u(t.get(e))?.kind ?? null;
82
82
  },
83
83
  getNodeShape(e) {
84
- let t = n.get(e);
85
- return t ? {
86
- pose: t.pose,
87
- data: t.data
84
+ let n = t.get(e);
85
+ return n ? {
86
+ pose: n.pose,
87
+ data: n.data
88
88
  } : null;
89
89
  },
90
- applyEdit(e, t, n) {
91
- let i = m(e, t, n);
92
- i.length > 0 && r.applyOps(i, n);
90
+ applyEdit(e, t, r) {
91
+ let i = m(e, t, r);
92
+ i.length > 0 && n.applyOps(i, r);
93
93
  },
94
94
  editOps: m
95
95
  };
@@ -1,116 +1,144 @@
1
- import { asNodeId as e } from "../../core/scene/types.js";
2
- import { createInsertOp as t } from "../../core/ops/create.js";
3
- import { cycleFill as n, solid as r, strokeOf as i } from "../../util/paint.js";
4
- import { insertPreviewExtent as a } from "../insertPreviewExtent.js";
5
- import { ellipsePath as o, linePath as s, polygonFromPoints as c, rectPath as l, regularPolygonPath as u, schneiderFit as d, starPath as f } from "@weasel-js/geom";
6
- import { useRef as p } from "react";
7
- import { useLatest as m } from "@weasel-js/react";
8
- import { useDepSource as h } from "@weasel-js/routing/react";
1
+ import { insertPreviewExtent as e } from "../insertPreviewExtent.js";
2
+ import { cycleFill as t, solid as n, strokeOf as r } from "../../util/paint.js";
3
+ import { createInsertOp as i } from "../../core/ops/create.js";
4
+ import { ellipsePath as a, linePath as o, polygonFromPoints as s, rectPath as c, regularPolygonPath as l, schneiderFit as u, starPath as d } from "@weasel-js/geom";
5
+ import { useRef as f } from "react";
6
+ import { useLatest as p } from "@weasel-js/react";
7
+ import { useDepSource as m } from "@weasel-js/routing/react";
9
8
  //#region src/canvas/deps/insert.ts
10
- function g(g, _, v) {
11
- let y = m(g), b = m(_), x = m(v), S = p(0);
12
- h("insert", () => {
13
- let p = y.current, m = b.current, h = p.layers[0]?.id ?? "default";
14
- return {
15
- layer: () => h,
16
- commit(g, _) {
17
- let v = _.kind, y = ++S.current, b = e(`kit-${v}-${y}`);
18
- for (; p.get(b) !== void 0;) y = ++S.current, b = e(`kit-${v}-${y}`);
19
- let C = n(y), w = r(C), T = a({
20
- shape: v,
21
- bounds: g,
22
- extras: _
23
- }), E = T.bounds, D = x.current?.[v];
24
- if (D) {
25
- let e = D(g, _);
26
- return e === null ? null : (m.applyOps([t({
9
+ var h = (e, i) => {
10
+ let a = t(i);
11
+ return e === "pencil" ? { stroke: r(a, 2) } : e === "line" || e === "path" ? {
12
+ fill: n(a),
13
+ stroke: r(a, 2)
14
+ } : { fill: n(a) };
15
+ };
16
+ function g(t, n, r, g = h) {
17
+ let _ = p(t), v = p(n), y = p(r), b = p(g), x = f(0), S = f({ gesture: null });
18
+ m("insertLive", () => S.current), m("insert", () => {
19
+ let t = _.current, n = v.current, r = t.layers[0]?.id ?? "default", f = (n, f) => {
20
+ let p = f.kind, m = ++x.current, h = t.mintId(), g = (e = p) => {
21
+ let { fill: t, stroke: n } = b.current(e, m);
22
+ return {
23
+ ...t === void 0 ? {} : { fill: t },
24
+ ...n === void 0 ? {} : { stroke: n }
25
+ };
26
+ }, _ = e({
27
+ shape: p,
28
+ bounds: n,
29
+ extras: f
30
+ }), v = _.bounds, S = y.current?.[p];
31
+ if (S) {
32
+ let e = S(n, f);
33
+ return e === null ? null : {
34
+ id: h,
35
+ ops: [i({
27
36
  node: {
28
- id: b,
37
+ id: h,
29
38
  kind: "leaf",
30
- layer: h,
31
- pose: e.pose ?? E,
39
+ layer: r,
40
+ pose: e.pose ?? v,
32
41
  data: e.data
33
42
  },
34
- label: `Insert ${v}`
35
- })], `Insert ${v}`), b);
43
+ label: `Insert ${p}`
44
+ })]
45
+ };
46
+ }
47
+ let C = _.geometry, w;
48
+ switch (C.kind) {
49
+ case "line":
50
+ w = {
51
+ path: o(C.a, C.b),
52
+ ...g()
53
+ };
54
+ break;
55
+ case "polygon":
56
+ w = {
57
+ path: l(C.center, C.radius, C.sides, C.rotation),
58
+ ...g()
59
+ };
60
+ break;
61
+ case "star":
62
+ w = {
63
+ path: d(C.center, C.outerRadius, C.points, C.innerRadius, C.rotation),
64
+ ...g()
65
+ };
66
+ break;
67
+ case "pencil": {
68
+ let e = C.samples;
69
+ w = e.length >= 4 ? {
70
+ path: u(e, 2),
71
+ ...g()
72
+ } : e.length >= 2 ? {
73
+ path: s(e),
74
+ ...g()
75
+ } : {
76
+ path: c(0, 0, _.bounds.width, _.bounds.height),
77
+ ...g("rect")
78
+ };
79
+ break;
36
80
  }
37
- let O = T.geometry, k;
38
- switch (O.kind) {
39
- case "line":
40
- k = {
41
- path: s(O.a, O.b),
42
- fill: w,
43
- stroke: i(C, 2)
81
+ case "box": switch (p) {
82
+ case "rect":
83
+ w = {
84
+ path: c(0, 0, _.bounds.width, _.bounds.height),
85
+ ...g()
44
86
  };
45
87
  break;
46
- case "polygon":
47
- k = {
48
- path: u(O.center, O.radius, O.sides, O.rotation),
49
- fill: w
88
+ case "ellipse":
89
+ w = {
90
+ path: a(_.bounds),
91
+ ...g()
50
92
  };
51
93
  break;
52
- case "star":
53
- k = {
54
- path: f(O.center, O.outerRadius, O.points, O.innerRadius, O.rotation),
55
- fill: w
56
- };
57
- break;
58
- case "pencil": {
59
- let e = O.samples;
60
- k = e.length >= 4 ? {
61
- path: d(e, 2),
62
- stroke: i(C, 2)
63
- } : e.length >= 2 ? {
64
- path: c(e),
65
- stroke: i(C, 2)
66
- } : {
67
- path: l(0, 0, T.bounds.width, T.bounds.height),
68
- fill: w
94
+ case "path": {
95
+ let e = f;
96
+ w = {
97
+ path: e.path,
98
+ ...g(),
99
+ ...e.closed ? {} : { fill: null }
69
100
  };
70
101
  break;
71
102
  }
72
- case "box": switch (v) {
73
- case "rect":
74
- k = {
75
- path: l(0, 0, T.bounds.width, T.bounds.height),
76
- fill: w
77
- };
78
- break;
79
- case "ellipse":
80
- k = {
81
- path: o(T.bounds),
82
- fill: w
83
- };
84
- break;
85
- case "text":
86
- k = { text: _.text ?? "" };
87
- break;
88
- case "image": {
89
- let e = _;
90
- k = { image: {
91
- src: e.src ?? "",
92
- ...e.opacity === void 0 ? {} : { opacity: e.opacity }
93
- } };
94
- break;
95
- }
96
- default: return console.warn(`weasel insertDep: no factory for kind="${v}". Skipping insert.`), null;
103
+ case "text":
104
+ w = { text: f.text ?? "" };
105
+ break;
106
+ case "image": {
107
+ let e = f;
108
+ w = { image: {
109
+ src: e.src ?? "",
110
+ ...e.opacity === void 0 ? {} : { opacity: e.opacity }
111
+ } };
112
+ break;
97
113
  }
114
+ default: return console.warn(`weasel insertDep: no factory for kind="${p}". Skipping insert.`), null;
98
115
  }
99
- return m.applyOps([t({
116
+ }
117
+ return {
118
+ id: h,
119
+ ops: [i({
100
120
  node: {
101
- id: b,
121
+ id: h,
102
122
  kind: "leaf",
103
- layer: h,
104
- pose: E,
105
- data: k
123
+ layer: r,
124
+ pose: v,
125
+ data: w
106
126
  },
107
- label: `Insert ${v}`
108
- })], `Insert ${v}`), b;
127
+ label: `Insert ${p}`
128
+ })]
129
+ };
130
+ };
131
+ return {
132
+ layer: () => r,
133
+ build: f,
134
+ commit(e, t) {
135
+ let r = f(e, t);
136
+ return r === null ? null : (n.applyOps(r.ops, `Insert ${t.kind}`), r.id);
109
137
  }
110
138
  };
111
139
  });
112
140
  }
113
141
  //#endregion
114
- export { g as useInsertDepSource };
142
+ export { h as paletteInsertPaint, g as useInsertDepSource };
115
143
 
116
144
  //# sourceMappingURL=insert.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"insert.js","names":["e","useInsertDepSource","sceneRef","useLatest","scene","adapterRef","adapter","factoriesRef","factories","insertSeqRef","useRef","sc","ad","layer","kind","extras","seq","id","asNodeId","color","cycleFill","fill","solid","extent","insertPreviewExtent","pose","factory","built","bounds","createInsertOp","geom","data","linePath","strokeOf","regularPolygonPath","starPath","samples","schneiderFit","polygonFromPoints","rectPath","ellipsePath"],"sources":["../../../src/canvas/deps/insert.ts"],"sourcesContent":["/**\n * `useInsertDepSource` — wires the `insert` dep consumed by `insertAction`.\n *\n * Provides kit-side kind→data factories for the 6 builtin shape kinds\n * (`rect`, `ellipse`, `line`, `polygon`, `star`, `pencil`). Acceptable because\n * these kinds are kit-shipped tools; a future phase can expose a\n * `nodeFactories` prop for consumer-defined kinds.\n *\n * `line`, `polygon`, `star` and `pencil` receive the drag AABB from the\n * insertAction invoker, but `extras` may carry richer geometry (endpoints,\n * center+radius+rotation, point trail). `insertPreviewExtent` resolves the\n * two into the node's real extent — the same resolution the live preview\n * and the reported gesture bounds use.\n */\nimport { useRef } from 'react';\nimport { useDepSource } from '@weasel-js/routing/react';\nimport { useLatest } from '@weasel-js/react';\nimport type { InsertDep, InsertExtras } from 'interactions/actions/depSchema';\nimport type { Scene, NodeId } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport type { Op } from 'core/ops/types';\nimport { createInsertOp } from 'core/ops/create';\nimport {\n rectPath,\n ellipsePath,\n regularPolygonPath,\n starPath,\n linePath,\n polygonFromPoints,\n schneiderFit,\n} from '@weasel-js/geom';\nimport { insertPreviewExtent } from '../insertPreviewExtent';\nimport { cycleFill, solid, strokeOf } from '../../util/paint';\n\ninterface OpsApplier {\n applyOps(ops: Op[], label?: string): void;\n}\n\n/**\n * Consumer-supplied node factory for one insert `kind`. Given the drag AABB\n * and the tool's `extras`, returns the node's `data` (in the consumer's own\n * data shape) plus an optional `pose` override — the dep supplies id, layer,\n * and the undoable insert op. Return `null` to reject the insert.\n *\n * A factory registered for a kit kind (`rect`, `line`, …) fully replaces the\n * kit's default `{ path, fill }` factory for that kind; a factory for a novel\n * kind adds support the kit doesn't ship (e.g. `text`). See\n * `SceneCanvas`'s `insertNodeFactories` prop.\n */\nexport type InsertNodeFactory = (\n bounds: { x: number; y: number; width: number; height: number },\n extras: InsertExtras,\n) => { data: unknown; pose?: unknown } | null;\n\nexport function useInsertDepSource(\n scene: Scene<unknown, string, unknown>,\n adapter: OpsApplier,\n factories?: Record<string, InsertNodeFactory>,\n): void {\n const sceneRef = useLatest(scene);\n const adapterRef = useLatest(adapter);\n const factoriesRef = useLatest(factories);\n const insertSeqRef = useRef(0);\n\n useDepSource('insert', (): InsertDep => {\n const sc = sceneRef.current;\n const ad = adapterRef.current;\n\n const layer = (sc.layers[0]?.id ?? 'default') as string;\n return {\n layer: () => layer,\n commit(bounds, extras): NodeId | null {\n const kind = extras.kind;\n // Walk the seq counter forward until we land on an id that doesn't\n // already exist in the scene. Handles two cases:\n // 1. Fresh mount after localStorage rehydration — the scene starts\n // with `kit-${kind}-1` etc. already populated; bare ++seq would\n // collide on the first insert.\n // 2. Hot-reload re-mounts the hook with a reset counter.\n let seq = ++insertSeqRef.current;\n let id = asNodeId(`kit-${kind}-${seq}`);\n while (sc.get(id) !== undefined) {\n seq = ++insertSeqRef.current;\n id = asNodeId(`kit-${kind}-${seq}`);\n }\n const color = cycleFill(seq);\n const fill = solid(color);\n\n // The nascent node's extent — drag AABB reconciled with whatever\n // richer geometry `extras` carries.\n const extent = insertPreviewExtent({ shape: kind, bounds, extras });\n const pose: unknown = extent.bounds;\n\n // Consumer factory wins over the kit default for this kind (and is the\n // only way to insert consumer-defined kinds like `text`). It owns the\n // node's data + optional pose; the dep still supplies id/layer/op.\n const factory = factoriesRef.current?.[kind];\n if (factory) {\n const built = factory(bounds, extras);\n if (built === null) return null;\n ad.applyOps(\n [createInsertOp({ node: { id, kind: 'leaf', layer, pose: built.pose ?? pose, data: built.data } as unknown as { id: string }, label: `Insert ${kind}` })],\n `Insert ${kind}`,\n );\n return id;\n }\n\n const geom = extent.geometry;\n let data: unknown;\n\n switch (geom.kind) {\n case 'line':\n data = { path: linePath(geom.a, geom.b), fill, stroke: strokeOf(color, 2) };\n break;\n case 'polygon':\n data = {\n path: regularPolygonPath(geom.center, geom.radius, geom.sides, geom.rotation),\n fill,\n };\n break;\n case 'star':\n data = {\n path: starPath(geom.center, geom.outerRadius, geom.points, geom.innerRadius, geom.rotation),\n fill,\n };\n break;\n case 'pencil': {\n const samples = geom.samples as { x: number; y: number }[];\n if (samples.length >= 4) {\n data = { path: schneiderFit(samples, 2.0), stroke: strokeOf(color, 2) };\n } else if (samples.length >= 2) {\n data = { path: polygonFromPoints(samples), stroke: strokeOf(color, 2) };\n } else {\n data = { path: rectPath(0, 0, extent.bounds.width, extent.bounds.height), fill };\n }\n break;\n }\n case 'box':\n switch (kind) {\n case 'rect':\n // Geometry-in-local-frame: the rect path lives at the origin and\n // the pose carries position. `pathInPoseFrame` rebases a rect path\n // onto the pose box regardless of the stored coords, so origin vs.\n // duplicated-pose-coords render identically — don't double-count\n // the position. (#13)\n data = { path: rectPath(0, 0, extent.bounds.width, extent.bounds.height), fill };\n break;\n case 'ellipse':\n data = { path: ellipsePath(extent.bounds), fill };\n break;\n case 'text': {\n // The built-in `useTextTool` drags an empty text box you then type\n // into (edit is entered via `enterTextEdit`), so `extras` carries\n // no content and `text` defaults to `''`. The kit:text painter\n // matches on `data.text != null` and applies style defaults at\n // render time, so a bare `{ text }` is a complete, editable node.\n const e = extras as Partial<{ text: string }>;\n data = { text: e.text ?? '' };\n break;\n }\n case 'image': {\n // The bitmap is loaded + cached by `imageCache` keyed on `src`;\n // only the (serializable) `src` lives on the node.\n const e = extras as Partial<{ src: string; opacity: number }>;\n data = {\n image: {\n src: e.src ?? '',\n ...(e.opacity !== undefined ? { opacity: e.opacity } : {}),\n },\n };\n break;\n }\n default:\n console.warn(`weasel insertDep: no factory for kind=\"${kind}\". Skipping insert.`);\n return null;\n }\n break;\n }\n\n ad.applyOps(\n [createInsertOp({ node: { id, kind: 'leaf', layer, pose, data } as unknown as { id: string }, label: `Insert ${kind}` })],\n `Insert ${kind}`,\n );\n return id;\n },\n };\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"insert.js","names":["e","paletteInsertPaint","color","cycleFill","seq","kind","strokeOf","solid","useInsertDepSource","sceneRef","useLatest","scene","adapterRef","adapter","factoriesRef","factories","paintRef","paint","insertSeqRef","useRef","liveRef","useDepSource","sc","ad","layer","build","extras","id","painted","as","fill","stroke","extent","insertPreviewExtent","pose","factory","built","bounds","createInsertOp","geom","data","linePath","regularPolygonPath","starPath","samples","schneiderFit","polygonFromPoints","rectPath","ellipsePath"],"sources":["../../../src/canvas/deps/insert.ts"],"sourcesContent":["/**\n * `useInsertDepSource` — wires the `insert` dep consumed by `insertAction`.\n *\n * Provides kit-side kind→data factories for the 6 builtin shape kinds\n * (`rect`, `ellipse`, `line`, `polygon`, `star`, `pencil`). Acceptable because\n * these kinds are kit-shipped tools; a future phase can expose a\n * `nodeFactories` prop for consumer-defined kinds.\n *\n * `line`, `polygon`, `star` and `pencil` receive the drag AABB from the\n * insertAction invoker, but `extras` may carry richer geometry (endpoints,\n * center+radius+rotation, point trail). `insertPreviewExtent` resolves the\n * two into the node's real extent — the same resolution the live preview\n * and the reported gesture bounds use.\n */\nimport { useRef } from 'react';\nimport { useDepSource } from '@weasel-js/routing/react';\nimport { useLatest } from '@weasel-js/react';\nimport type { InsertDep, InsertExtras, InsertLive } from 'interactions/actions/depSchema';\nimport type { Scene, NodeId } from 'core/scene/types';\nimport type { Op } from 'core/ops/types';\nimport { createInsertOp } from 'core/ops/create';\nimport {\n rectPath,\n ellipsePath,\n regularPolygonPath,\n starPath,\n linePath,\n polygonFromPoints,\n schneiderFit,\n type PolygonPath,\n} from '@weasel-js/geom';\nimport { insertPreviewExtent } from '../insertPreviewExtent';\nimport type { FillStyle, Stroke } from '@weasel-js/paint';\nimport { cycleFill, solid, strokeOf } from '../../util/paint';\n\ninterface OpsApplier {\n applyOps(ops: Op[], label?: string): void;\n}\n\n/**\n * Consumer-supplied node factory for one insert `kind`. Given the drag AABB\n * and the tool's `extras`, returns the node's `data` (in the consumer's own\n * data shape) plus an optional `pose` override — the dep supplies id, layer,\n * and the undoable insert op. Return `null` to reject the insert.\n *\n * A factory registered for a kit kind (`rect`, `line`, …) fully replaces the\n * kit's default `{ path, fill }` factory for that kind; a factory for a novel\n * kind adds support the kit doesn't ship (e.g. `text`). To change only the\n * paint of a kit shape, pass an {@link InsertPaint}. See\n * `SceneCanvas`'s `insertNodeFactories` prop.\n */\nexport type InsertNodeFactory = (\n bounds: { x: number; y: number; width: number; height: number },\n extras: InsertExtras,\n) => { data: unknown; pose?: unknown } | null;\n\n/**\n * The paint a kit-built shape is inserted with. `kind` is the shape being\n * built and `seq` counts this canvas's inserts from 1. A key left out stays\n * off the node, so its painter's default applies; `null` is \"none\". A pencil\n * trail too short to fit is built as a rect and asks as one.\n *\n * It paints only the shapes the kit builds: an `InsertNodeFactory` owns its\n * node's whole `data`. See `SceneCanvas`'s `insertPaint` prop.\n */\nexport type InsertPaint = (kind: string, seq: number) => { fill?: FillStyle | null; stroke?: Stroke | null };\n\n/** The default {@link InsertPaint}: the next color of the kit palette, as a\n * fill on a closed shape, a fill and a stroke on a line or a pen path, and a\n * stroke alone on a pencil trail. */\nexport const paletteInsertPaint: InsertPaint = (kind, seq) => {\n const color = cycleFill(seq);\n if (kind === 'pencil') return { stroke: strokeOf(color, 2) };\n if (kind === 'line' || kind === 'path') return { fill: solid(color), stroke: strokeOf(color, 2) };\n return { fill: solid(color) };\n};\n\nexport function useInsertDepSource(\n scene: Scene<unknown, string, unknown>,\n adapter: OpsApplier,\n factories?: Record<string, InsertNodeFactory>,\n paint: InsertPaint = paletteInsertPaint,\n): void {\n const sceneRef = useLatest(scene);\n const adapterRef = useLatest(adapter);\n const factoriesRef = useLatest(factories);\n const paintRef = useLatest(paint);\n const insertSeqRef = useRef(0);\n const liveRef = useRef<InsertLive>({ gesture: null });\n useDepSource('insertLive', () => liveRef.current);\n\n useDepSource('insert', (): InsertDep => {\n const sc = sceneRef.current;\n const ad = adapterRef.current;\n\n const layer = (sc.layers[0]?.id ?? 'default') as string;\n const build = (\n bounds: { x: number; y: number; width: number; height: number },\n extras: InsertExtras,\n ): { id: NodeId; ops: Op[] } | null => {\n const kind = extras.kind;\n const seq = ++insertSeqRef.current;\n const id = sc.mintId();\n const painted = (as: string = kind): { fill?: FillStyle | null; stroke?: Stroke | null } => {\n const { fill, stroke } = paintRef.current(as, seq);\n return { ...(fill !== undefined ? { fill } : {}), ...(stroke !== undefined ? { stroke } : {}) };\n };\n\n // The nascent node's extent — drag AABB reconciled with whatever\n // richer geometry `extras` carries.\n const extent = insertPreviewExtent({ shape: kind, bounds, extras });\n const pose: unknown = extent.bounds;\n\n // Consumer factory wins over the kit default for this kind (and is the\n // only way to insert consumer-defined kinds like `text`). It owns the\n // node's data + optional pose; the dep still supplies id/layer/op.\n const factory = factoriesRef.current?.[kind];\n if (factory) {\n const built = factory(bounds, extras);\n if (built === null) return null;\n return {\n id,\n ops: [createInsertOp({ node: { id, kind: 'leaf', layer, pose: built.pose ?? pose, data: built.data } as unknown as { id: string }, label: `Insert ${kind}` })],\n };\n }\n\n const geom = extent.geometry;\n let data: unknown;\n\n switch (geom.kind) {\n case 'line':\n data = { path: linePath(geom.a, geom.b), ...painted() };\n break;\n case 'polygon':\n data = {\n path: regularPolygonPath(geom.center, geom.radius, geom.sides, geom.rotation),\n ...painted(),\n };\n break;\n case 'star':\n data = {\n path: starPath(geom.center, geom.outerRadius, geom.points, geom.innerRadius, geom.rotation),\n ...painted(),\n };\n break;\n case 'pencil': {\n const samples = geom.samples as { x: number; y: number }[];\n if (samples.length >= 4) {\n data = { path: schneiderFit(samples, 2.0), ...painted() };\n } else if (samples.length >= 2) {\n data = { path: polygonFromPoints(samples), ...painted() };\n } else {\n data = { path: rectPath(0, 0, extent.bounds.width, extent.bounds.height), ...painted('rect') };\n }\n break;\n }\n case 'box':\n switch (kind) {\n case 'rect':\n // Geometry-in-local-frame: the rect path lives at the origin and\n // the pose carries position. `pathInPoseFrame` rebases a rect path\n // onto the pose box regardless of the stored coords, so origin vs.\n // duplicated-pose-coords render identically — don't double-count\n // the position. (#13)\n data = { path: rectPath(0, 0, extent.bounds.width, extent.bounds.height), ...painted() };\n break;\n case 'ellipse':\n data = { path: ellipsePath(extent.bounds), ...painted() };\n break;\n case 'path': {\n const e = extras as { path: PolygonPath; closed: boolean };\n data = { path: e.path, ...painted(), ...(e.closed ? {} : { fill: null }) };\n break;\n }\n case 'text': {\n // The built-in `useTextTool` drags an empty text box you then type\n // into (edit is entered via `enterTextEdit`), so `extras` carries\n // no content and `text` defaults to `''`. The kit:text painter\n // matches on `data.text != null` and applies style defaults at\n // render time, so a bare `{ text }` is a complete, editable node.\n const e = extras as Partial<{ text: string }>;\n data = { text: e.text ?? '' };\n break;\n }\n case 'image': {\n // The bitmap is loaded + cached by `imageCache` keyed on `src`;\n // only the (serializable) `src` lives on the node.\n const e = extras as Partial<{ src: string; opacity: number }>;\n data = {\n image: {\n src: e.src ?? '',\n ...(e.opacity !== undefined ? { opacity: e.opacity } : {}),\n },\n };\n break;\n }\n default:\n console.warn(`weasel insertDep: no factory for kind=\"${kind}\". Skipping insert.`);\n return null;\n }\n break;\n }\n\n return {\n id,\n ops: [createInsertOp({ node: { id, kind: 'leaf', layer, pose, data } as unknown as { id: string }, label: `Insert ${kind}` })],\n };\n };\n return {\n layer: () => layer,\n build,\n commit(bounds, extras): NodeId | null {\n const built = build(bounds, extras);\n if (built === null) return null;\n ad.applyOps(built.ops, `Insert ${extras.kind}`);\n return built.id;\n },\n };\n });\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { poseDescriptorForNode as e } from "../../core/geometry/poseDescriptor.js";
2
- import { AUTO_POSE_DESCRIPTOR as t } from "../../interactions/actions/resize/autoPoseDescriptor.js";
3
- import { scenePoseFrame as n } from "../../interactions/actions/poseFrame.js";
4
- import { freshNodeId as r } from "../../interactions/actions/defaults/freshNodeId.js";
5
- import { pathInWorld as i, worldEditToStorage as a } from "../../features/paths/pathInWorld.js";
1
+ import { poseLinearOf as e } from "../../core/geometry/poseFrame.js";
2
+ import { poseDescriptorForNode as t } from "../../core/geometry/poseDescriptor.js";
3
+ import { AUTO_POSE_DESCRIPTOR as n } from "../../interactions/actions/resize/autoPoseDescriptor.js";
4
+ import { pathInWorld as r, worldEditToStorage as i } from "../../features/paths/pathInWorld.js";
5
+ import { scenePoseFrame as a } from "../../interactions/actions/poseFrame.js";
6
6
  import { computeSliceOps as o } from "../../interactions/actions/defaults/sliceOps.js";
7
7
  import { useLatest as s } from "@weasel-js/react";
8
8
  import { useDepSource as c } from "@weasel-js/routing/react";
@@ -11,70 +11,71 @@ function l(e) {
11
11
  let t = s(e);
12
12
  c("slice", () => t.current);
13
13
  }
14
- function u(a, l, u, h, g) {
15
- let _ = s(a), v = s(l), y = s(u), b = s(h), x = s(g);
16
- c("slice", () => ({ commit(a) {
17
- let s = _.current, c = n(s, b.current), l = x.current ?? t, u = [], h = /* @__PURE__ */ new Map();
18
- for (let t of s.renderOrderNodes()) {
19
- let n = p(s, t);
14
+ function u(e, i, l, u, h) {
15
+ let g = s(e), _ = s(i), v = s(l), y = s(u), b = s(h);
16
+ c("slice", () => ({ commit(e) {
17
+ let i = g.current, s = a(i, y.current), c = b.current ?? n, l = [], u = /* @__PURE__ */ new Map();
18
+ for (let e of i.renderOrderNodes()) {
19
+ let n = p(i, e);
20
20
  if (!n) continue;
21
- let r = d(e(l, t), c.world(t.id));
22
- r && (h.set(t.id, r), u.push({
23
- node: t,
24
- index: m(s, t),
25
- worldPath: i(n, r.box)
21
+ let a = d(t(c, e), s.world(e.id));
22
+ a && (u.set(e.id, a), l.push({
23
+ node: e,
24
+ index: m(i, e),
25
+ worldPath: r(n, a.box)
26
26
  }));
27
27
  }
28
- let g = v.current, { ops: S, nextSelection: C } = o({
29
- leaves: u,
30
- cut: a,
31
- nextId: r,
32
- selection: g.get(),
28
+ let h = _.current, { ops: x, nextSelection: S } = o({
29
+ leaves: l,
30
+ cut: e,
31
+ nextId: () => i.mintId(),
32
+ selection: h.get(),
33
33
  placePiece: (e, t) => {
34
- let n = f(h.get(e.node.id), t);
34
+ let n = f(u.get(e.node.id), t);
35
35
  return {
36
- pose: c.local(e.node.id, n.pose),
36
+ pose: s.local(e.node.id, n.pose),
37
37
  path: n.path
38
38
  };
39
39
  }
40
40
  });
41
- S.length !== 0 && (y.current.applyOps(S, "Slice"), C && g.set(C));
41
+ x.length !== 0 && (v.current.applyOps(x, "Slice"), S && h.set(S));
42
42
  } }));
43
43
  }
44
- function d(e, t) {
45
- let n = e.getBounds(t);
46
- if (!n || ![
47
- n.x,
48
- n.y,
49
- n.width,
50
- n.height
44
+ function d(t, n) {
45
+ let r = t.getBounds(n);
46
+ if (!r || ![
47
+ r.x,
48
+ r.y,
49
+ r.width,
50
+ r.height
51
51
  ].every(Number.isFinite)) return null;
52
- let r = e.getRotation?.(t) ?? 0;
52
+ let i = t.getRotation?.(n) ?? 0, a = e(n) ?? void 0;
53
53
  return {
54
- world: t,
55
- g: e,
54
+ world: n,
55
+ g: t,
56
56
  box: {
57
- x: n.x,
58
- y: n.y,
59
- width: n.width,
60
- height: n.height,
61
- rotation: r
57
+ x: r.x,
58
+ y: r.y,
59
+ width: r.width,
60
+ height: r.height,
61
+ rotation: i,
62
+ transform: a
62
63
  }
63
64
  };
64
65
  }
65
66
  function f({ world: e, g: t, box: n }, r) {
66
- let i = !!t.withRotation && t.supportsRotation?.(e) !== !1, o = n.rotation ?? 0;
67
- if (o !== 0 && !i) {
68
- let i = a({
67
+ let a = !!t.withRotation && t.supportsRotation?.(e) !== !1, o = n.rotation ?? 0;
68
+ if (o !== 0 && !a) {
69
+ let a = i({
69
70
  ...n,
70
71
  rotation: 0
71
72
  }, r);
72
73
  return {
73
- pose: t.fromBounds(i.pose, e),
74
- path: i.path
74
+ pose: t.fromBounds(a.pose, e),
75
+ path: a.path
75
76
  };
76
77
  }
77
- let { pose: s, path: c } = a(n, r), l = {
78
+ let { pose: s, path: c } = i(n, r), l = {
78
79
  x: s.x,
79
80
  y: s.y,
80
81
  width: s.width,