@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
@@ -0,0 +1,34 @@
1
+ import { commandFill as e, commandStroke as t } from "../../features/patterns/commandPaint.js";
2
+ import { DEFAULT_SHAPE_FILL as n } from "../../util/paint.js";
3
+ import { derivesPath as r } from "./memo.js";
4
+ import { inkReach as i, resolveNodeFill as a, resolveNodeStroke as o, withAnimatedVertexColors as s } from "./nodePaint.js";
5
+ import { boundsOfPath as c } from "@weasel-js/geom";
6
+ //#region src/canvas/nodeShapes/derivedPainter.ts
7
+ var l = {
8
+ id: "kit:derived",
9
+ matches: r,
10
+ paint: (r, i, l) => {
11
+ let u = l?.derivedPath;
12
+ if (u == null) return [];
13
+ let d = c(u), f = r.data, p = o(f?.stroke), m = a(f?.fill, p === null ? n : null), h = m && e(m, d), g = p && t(p, d), _ = {
14
+ kind: "path",
15
+ path: u,
16
+ ...h ? { fill: h } : {},
17
+ ...h && f?.vertexColors ? { vertexColors: f.vertexColors } : {},
18
+ ...g ? { stroke: g } : {}
19
+ };
20
+ return s([_], l);
21
+ },
22
+ silhouette: (e, t, n) => n?.derivedPath ?? null,
23
+ ink: (e, t, r) => {
24
+ let s = e.data, c = o(s?.stroke);
25
+ return {
26
+ filled: a(s?.fill, c === null ? n : null) !== null,
27
+ ...i(c, r?.scale)
28
+ };
29
+ }
30
+ };
31
+ //#endregion
32
+ export { l as DERIVED_PAINTER };
33
+
34
+ //# sourceMappingURL=derivedPainter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derivedPainter.js","names":["DERIVED_PAINTER","derivesPath","path","ctx","box","boundsOfPath","d","node","strokeSpec","resolveNodeStroke","declared","resolveNodeFill","DEFAULT_SHAPE_FILL","fill","commandFill","stroke","commandStroke","cmd","withAnimatedVertexColors","inkReach"],"sources":["../../../src/canvas/nodeShapes/derivedPainter.ts"],"sourcesContent":["import {\n boundsOfPath\n} from '@weasel-js/geom';\nimport type { FillStyle, Stroke } from '@weasel-js/paint';\nimport type { NodeShapeEntry } from 'canvas/NodeShape';\nimport { commandFill, commandStroke } from '../../features/patterns/commandPaint';\nimport type { DrawCommand } from '../../renderer';\nimport { DEFAULT_SHAPE_FILL } from '../../util/paint';\nimport { derivesPath } from './memo';\nimport { inkReach, withAnimatedVertexColors, resolveNodeFill, resolveNodeStroke } from './nodePaint';\n\n// ─── Built-in painters ─────────────────────────────────────────────────\n/**\n * Built-in painter for nodes whose geometry is computed from other nodes'\n * poses. The path itself arrives on the paint context — see\n * {@link NodePaintCtx.derivedPath}.\n *\n * Fill and stroke resolve as `kit:path`'s do, but against the **derived path's\n * own bounds**, not the pose. `kit:path` projects its path into the pose frame\n * first, so there the two boxes are the same one; here the path is already\n * absolute and the pose is typically a zero-sized placeholder, which would\n * collapse a box-relative gradient onto a point.\n *\n * Not memoized on {@link PAINT_SLOT} on purpose: that key is `(node, pose,\n * data)` and cannot see `ctx.derivedPath`, so it would serve one caller's\n * commands to a caller that passed a different path.\n *\n * Rotation still comes from the pose — `wrapNodeOutput` turns the output about\n * the pose AABB's center, which for a zero-sized pose is its origin.\n */\nexport const DERIVED_PAINTER: NodeShapeEntry = {\n id: 'kit:derived',\n // `dependsOn` alone is not enough: the two fields are independent optionals,\n // and `kit:add` restores a node with its `dependsOn` intact when its\n // `derivePath` key is missing from the registry. Claiming that node would paint\n // nothing where the authored appearance is what the warning promises.\n matches: derivesPath,\n paint: (node, _pose, ctx) => {\n const path = ctx?.derivedPath;\n if (path == null) return [];\n const box = boundsOfPath(path);\n const d = node.data as { fill?: FillStyle | null; stroke?: Stroke | null; vertexColors?: number[] } | null;\n const strokeSpec = resolveNodeStroke(d?.stroke);\n const declared = resolveNodeFill(d?.fill, strokeSpec === null ? DEFAULT_SHAPE_FILL : null);\n const fill = declared && commandFill(declared, box);\n const stroke = strokeSpec && commandStroke(strokeSpec, box);\n const cmd: DrawCommand = {\n kind: 'path',\n path,\n ...(fill ? { fill } : {}),\n ...(fill && d?.vertexColors ? { vertexColors: d.vertexColors } : {}),\n ...(stroke ? { stroke } : {}),\n };\n return withAnimatedVertexColors([cmd], ctx);\n },\n // The derived path *is* the silhouette, and it is already absolute — the\n // pose is a placeholder, so nothing here can be recovered from it. Without\n // a `ctx` this reports null, which `shapeCoversPoint` reads as \"no\n // opinion\": picking then falls back to that zero-sized pose.\n silhouette: (_node, _pose, ctx) => ctx?.derivedPath ?? null,\n ink: (node, _pose, ctx) => {\n const d = node.data as { fill?: FillStyle | null; stroke?: Stroke | null } | null;\n const stroke = resolveNodeStroke(d?.stroke);\n return {\n filled: resolveNodeFill(d?.fill, stroke === null ? DEFAULT_SHAPE_FILL : null) !== null,\n ...inkReach(stroke, ctx?.scale),\n };\n },\n};\n"],"mappings":";;;;;;AA8BA,IAAaA,IAAkC;CAC7C,IAAI;CAKJ,SAASC;CACT,QAAQ,GAAM,GAAO,MAAQ;EAC3B,IAAMC,IAAOC,GAAK;EAClB,IAAID,KAAQ,MAAM,OAAO,CAAC;EAC1B,IAAME,IAAMC,EAAaH,CAAI,GACvBI,IAAIC,EAAK,MACTC,IAAaC,EAAkBH,GAAG,MAAM,GACxCI,IAAWC,EAAgBL,GAAG,MAAME,MAAe,OAAOI,IAAqB,IAAI,GACnFC,IAAOH,KAAYI,EAAYJ,GAAUN,CAAG,GAC5CW,IAASP,KAAcQ,EAAcR,GAAYJ,CAAG,GACpDa,IAAmB;GACvB,MAAM;GACN;GACA,GAAIJ,IAAO,EAAE,QAAK,IAAI,CAAC;GACvB,GAAIA,KAAQP,GAAG,eAAe,EAAE,cAAcA,EAAE,aAAa,IAAI,CAAC;GAClE,GAAIS,IAAS,EAAE,UAAO,IAAI,CAAC;EAC7B;EACA,OAAOG,EAAyB,CAACD,CAAG,GAAGd,CAAG;CAC5C;CAKA,aAAa,GAAO,GAAO,MAAQA,GAAK,eAAe;CACvD,MAAM,GAAM,GAAO,MAAQ;EACzB,IAAMG,IAAIC,EAAK,MACTQ,IAASN,EAAkBH,GAAG,MAAM;EAC1C,OAAO;GACL,QAAQK,EAAgBL,GAAG,MAAMS,MAAW,OAAOH,IAAqB,IAAI,MAAM;GAClF,GAAGO,EAASJ,GAAQZ,GAAK,KAAK;EAChC;CACF;AACF"}
@@ -0,0 +1,87 @@
1
+ import { getImageBitmap as e, imageStatus as t } from "../../features/images/imageCache.js";
2
+ import { paintsPose as n, poseBoxBounds as r } from "./poseBox.js";
3
+ import { linePath as i } from "@weasel-js/geom";
4
+ //#region src/canvas/nodeShapes/imagePainter.ts
5
+ function a(e, t) {
6
+ return {
7
+ x: e.x * t.width,
8
+ y: e.y * t.height,
9
+ w: e.width * t.width,
10
+ h: e.height * t.height
11
+ };
12
+ }
13
+ function o(e, t, n) {
14
+ if (n && n > 0) return {
15
+ width: Math.abs(e.width) * n / (t?.width || 1),
16
+ height: Math.abs(e.height) * n / (t?.height || 1)
17
+ };
18
+ }
19
+ var s = {
20
+ id: "kit:image",
21
+ matches: (e) => {
22
+ if (!n(e.pose)) return !1;
23
+ let t = e.data?.image?.src;
24
+ return typeof t == "string" && t.length > 0;
25
+ },
26
+ paint: (n, r, s) => {
27
+ let c = n.data, l = r, u = s?.resolveImage ? s.resolveImage(n) : e(c.image.src, o(l, c.image.source, s?.pixelScale));
28
+ if (u) return [{
29
+ kind: "image",
30
+ image: u,
31
+ x: l.x,
32
+ y: l.y,
33
+ w: l.width,
34
+ h: l.height,
35
+ ...c.image.opacity === void 0 ? {} : { opacity: c.image.opacity },
36
+ ...c.image.source ? { source: a(c.image.source, u) } : {},
37
+ ...c.image.flipX ? { flipX: !0 } : {},
38
+ ...c.image.flipY ? { flipY: !0 } : {}
39
+ }];
40
+ let d = !s?.resolveImage && t(c.image.src) === "error", f = d ? "#d08a8a" : "#bbbbbb", p = [{
41
+ kind: "path",
42
+ path: {
43
+ kind: "rect",
44
+ x: l.x,
45
+ y: l.y,
46
+ width: l.width,
47
+ height: l.height
48
+ },
49
+ stroke: {
50
+ paint: { color: f },
51
+ width: 1
52
+ }
53
+ }];
54
+ return d && p.push({
55
+ kind: "path",
56
+ path: i({
57
+ x: l.x,
58
+ y: l.y
59
+ }, {
60
+ x: l.x + l.width,
61
+ y: l.y + l.height
62
+ }),
63
+ stroke: {
64
+ paint: { color: f },
65
+ width: 1
66
+ }
67
+ }), p;
68
+ },
69
+ silhouette: (e, t) => {
70
+ let n = t;
71
+ return {
72
+ kind: "rect",
73
+ x: n.x,
74
+ y: n.y,
75
+ width: n.width,
76
+ height: n.height
77
+ };
78
+ },
79
+ bounds: (e, t, n) => r(t, c, n)
80
+ }, c = {
81
+ paint: { color: "#000" },
82
+ width: 1
83
+ };
84
+ //#endregion
85
+ export { s as IMAGE_PAINTER, c as IMAGE_PLACEHOLDER_STROKE, o as drawnSize, a as sourceInPixels };
86
+
87
+ //# sourceMappingURL=imagePainter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imagePainter.js","names":["sourceInPixels","s","bmp","drawnSize","pixelScale","pose","source","IMAGE_PAINTER","paintsPose","node","src","d","p","ctx","getImageBitmap","error","imageStatus","color","cmds","linePath","poseBoxBounds","IMAGE_PLACEHOLDER_STROKE"],"sources":["../../../src/canvas/nodeShapes/imagePainter.ts"],"sourcesContent":["import {\n linePath\n} from '@weasel-js/geom';\nimport type { Stroke } from '@weasel-js/paint';\nimport type { NodeShapeEntry } from 'canvas/NodeShape';\nimport type { Node, RectPose } from 'core/scene/types';\nimport {\n getImageBitmap, imageStatus, type ImageNodeData, type ImageRasterSize,\n} from 'features/images/imageCache';\nimport type { DrawCommand } from '../../renderer';\nimport { paintsPose, poseBoxBounds } from './poseBox';\n\n// ─── Built-in painters ─────────────────────────────────────────────────\n\nexport function sourceInPixels(\n s: NonNullable<ImageNodeData['image']['source']>,\n bmp: ImageBitmap,\n): { x: number; y: number; w: number; h: number } {\n return {\n x: s.x * bmp.width, y: s.y * bmp.height, w: s.width * bmp.width, h: s.height * bmp.height,\n };\n}\n\n/** The whole bitmap's size in device pixels when `source` of it fills `pose`. */\nexport function drawnSize(\n pose: RectPose,\n source: ImageNodeData['image']['source'],\n pixelScale: number | undefined,\n): ImageRasterSize | undefined {\n if (!(pixelScale && pixelScale > 0)) return undefined;\n return {\n width: Math.abs(pose.width) * pixelScale / (source?.width || 1),\n height: Math.abs(pose.height) * pixelScale / (source?.height || 1),\n };\n}\n\n/** Raster-image painter. Renders `data.image.src` (URL / blob: / data-URI)\n * via an `ImageDrawCommand` once the bitmap has decoded; until then it paints\n * a faint placeholder outline so the node stays visible + selectable (a\n * reddish outline + slash marks a failed load). The decoded bitmap is owned\n * by `imageCache`, keyed on `src`; the node holds only the serializable `src`.\n * Registered before `kit:rect-fallback` so image nodes don't fall through. */\nexport const IMAGE_PAINTER: NodeShapeEntry<unknown, RectPose> = {\n id: 'kit:image',\n matches: (node) => {\n if (!paintsPose(node.pose)) return false;\n const src = (node.data as { image?: { src?: unknown } } | null)?.image?.src;\n return typeof src === 'string' && src.length > 0;\n },\n paint: (node, pose, ctx) => {\n const d = node.data as ImageNodeData;\n const p = pose;\n const bmp = ctx?.resolveImage\n ? ctx.resolveImage(node as unknown as Node<unknown, string, unknown>)\n : getImageBitmap(d.image.src, drawnSize(p, d.image.source, ctx?.pixelScale));\n if (bmp) {\n return [{\n kind: 'image',\n image: bmp,\n x: p.x, y: p.y, w: p.width, h: p.height,\n ...(d.image.opacity !== undefined ? { opacity: d.image.opacity } : {}),\n ...(d.image.source ? { source: sourceInPixels(d.image.source, bmp) } : {}),\n ...(d.image.flipX ? { flipX: true } : {}),\n ...(d.image.flipY ? { flipY: true } : {}),\n }];\n }\n // Not ready — faint placeholder (grey while loading, reddish + slash on\n // error). With a caller-supplied resolver the fallback is deterministic:\n // always the plain grey outline, no ambient load-status read.\n const error = ctx?.resolveImage ? false : imageStatus(d.image.src) === 'error';\n const color = error ? '#d08a8a' : '#bbbbbb';\n const cmds: DrawCommand[] = [{\n kind: 'path',\n path: { kind: 'rect', x: p.x, y: p.y, width: p.width, height: p.height },\n stroke: { paint: { color }, width: 1 },\n }];\n if (error) {\n cmds.push({\n kind: 'path',\n path: linePath({ x: p.x, y: p.y }, { x: p.x + p.width, y: p.y + p.height }),\n stroke: { paint: { color }, width: 1 },\n });\n }\n return cmds;\n },\n silhouette: (_node, pose) => {\n const p = pose;\n return { kind: 'rect', x: p.x, y: p.y, width: p.width, height: p.height };\n },\n // The placeholder's 1-unit outline is the only thing that leaves the box.\n bounds: (_node, pose, ctx) => poseBoxBounds(pose, IMAGE_PLACEHOLDER_STROKE, ctx),\n};\n\nexport const IMAGE_PLACEHOLDER_STROKE: Stroke = { paint: { color: '#000' }, width: 1 };\n"],"mappings":";;;;AAcA,SAAgBA,EACd,GACA,GACgD;CAChD,OAAO;EACL,GAAGC,EAAE,IAAIC,EAAI;EAAO,GAAGD,EAAE,IAAIC,EAAI;EAAQ,GAAGD,EAAE,QAAQC,EAAI;EAAO,GAAGD,EAAE,SAASC,EAAI;CACrF;AACF;AAGA,SAAgBC,EACd,GACA,GACA,GAC6B;CAC7B,IAAMC,KAAcA,IAAa,GACjC,OAAO;EACL,OAAO,KAAK,IAAIC,EAAK,KAAK,IAAID,KAAcE,GAAQ,SAAS;EAC7D,QAAQ,KAAK,IAAID,EAAK,MAAM,IAAID,KAAcE,GAAQ,UAAU;CAClE;AACF;AAQA,IAAaC,IAAmD;CAC9D,IAAI;CACJ,UAAU,MAAS;EACjB,IAAI,CAACC,EAAWC,EAAK,IAAI,GAAG,OAAO;EACnC,IAAMC,IAAOD,EAAK,MAA+C,OAAO;EACxE,OAAO,OAAOC,KAAQ,YAAYA,EAAI,SAAS;CACjD;CACA,QAAQ,GAAM,GAAM,MAAQ;EAC1B,IAAMC,IAAIF,EAAK,MACTG,IAAIP,GACJH,IAAMW,GAAK,eACbA,EAAI,aAAaJ,CAAiD,IAClEK,EAAeH,EAAE,MAAM,KAAKR,EAAUS,GAAGD,EAAE,MAAM,QAAQE,GAAK,UAAU,CAAC;EAC7E,IAAIX,GACF,OAAO,CAAC;GACN,MAAM;GACN,OAAOA;GACP,GAAGU,EAAE;GAAG,GAAGA,EAAE;GAAG,GAAGA,EAAE;GAAO,GAAGA,EAAE;GACjC,GAAID,EAAE,MAAM,YAAY,KAAA,IAA2C,CAAC,IAAhC,EAAE,SAASA,EAAE,MAAM,QAAQ;GAC/D,GAAIA,EAAE,MAAM,SAAS,EAAE,QAAQX,EAAeW,EAAE,MAAM,QAAQT,CAAG,EAAE,IAAI,CAAC;GACxE,GAAIS,EAAE,MAAM,QAAQ,EAAE,OAAO,GAAK,IAAI,CAAC;GACvC,GAAIA,EAAE,MAAM,QAAQ,EAAE,OAAO,GAAK,IAAI,CAAC;EACzC,CAAC;EAKH,IAAMI,IAAQ,IAAK,gBAAuBC,EAAYL,EAAE,MAAM,GAAG,MAAM,SACjEM,IAAQF,IAAQ,YAAY,WAC5BG,IAAsB,CAAC;GAC3B,MAAM;GACN,MAAM;IAAE,MAAM;IAAQ,GAAGN,EAAE;IAAG,GAAGA,EAAE;IAAG,OAAOA,EAAE;IAAO,QAAQA,EAAE;GAAO;GACvE,QAAQ;IAAE,OAAO,EAAE,SAAM;IAAG,OAAO;GAAE;EACvC,CAAC;EAQD,OAPIG,KACFG,EAAK,KAAK;GACR,MAAM;GACN,MAAMC,EAAS;IAAE,GAAGP,EAAE;IAAG,GAAGA,EAAE;GAAE,GAAG;IAAE,GAAGA,EAAE,IAAIA,EAAE;IAAO,GAAGA,EAAE,IAAIA,EAAE;GAAO,CAAC;GAC1E,QAAQ;IAAE,OAAO,EAAE,SAAM;IAAG,OAAO;GAAE;EACvC,CAAC,GAEIM;CACT;CACA,aAAa,GAAO,MAAS;EAC3B,IAAMN,IAAIP;EACV,OAAO;GAAE,MAAM;GAAQ,GAAGO,EAAE;GAAG,GAAGA,EAAE;GAAG,OAAOA,EAAE;GAAO,QAAQA,EAAE;EAAO;CAC1E;CAEA,SAAS,GAAO,GAAM,MAAQQ,EAAcf,GAAMgB,GAA0BR,CAAG;AACjF,GAEaQ,IAAmC;CAAE,OAAO,EAAE,OAAO,OAAO;CAAG,OAAO;AAAE"}
@@ -0,0 +1,9 @@
1
+ //#region src/canvas/nodeShapes/memo.ts
2
+ var e = "shape:paint";
3
+ function t(e) {
4
+ return (e.dependsOn?.length ?? 0) > 0 && e.derivePath !== void 0;
5
+ }
6
+ //#endregion
7
+ export { e as PAINT_SLOT, t as derivesPath };
8
+
9
+ //# sourceMappingURL=memo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memo.js","names":["PAINT_SLOT","derivesPath","node"],"sources":["../../../src/canvas/nodeShapes/memo.ts"],"sourcesContent":["\n/**\n * Slot for a painter's memoized `paint` output.\n *\n * Distinct from {@link SILHOUETTE_SLOT} even though the two mostly invalidate\n * together: the silhouette bakes `pose.rotation` in (paint does not — the\n * render wrap applies it), and paint alone can depend on `NodePaintCtx` and on\n * ambient readiness. One entry keyed the same way for both would be wrong in\n * both directions.\n *\n * **Only for painters that are a pure function of `(node, pose, data)`.**\n * `kit:shape` and `kit:path` qualify and are also precisely the painters that\n * allocated a fresh `Path` per frame, defeating the tessellation cache in\n * `renderer/cache/cache.ts` (`WeakMap<Path, Mesh>`, keyed on Path identity).\n * `kit:text` and `kit:image` do not qualify — see the tests in\n * `NodeShape.cache.test.ts` that pin their opt-out.\n */\nexport const PAINT_SLOT = 'shape:paint';\n\nexport function derivesPath(node: { dependsOn?: readonly unknown[] | 'children'; derivePath?: unknown }): boolean {\n return (node.dependsOn?.length ?? 0) > 0 && node.derivePath !== undefined;\n}\n"],"mappings":";AAiBA,IAAaA,IAAa;AAE1B,SAAgBC,EAAY,GAAsF;CAChH,QAAQC,EAAK,WAAW,UAAU,KAAK,KAAKA,EAAK,eAAe,KAAA;AAClE"}
@@ -0,0 +1,57 @@
1
+ import { resolveStrokeWidth as e } from "../../features/paths/tessellate/stroke.js";
2
+ import { markerReach as t } from "../../features/paths/markerCommands.js";
3
+ import { countPathAnchors as n } from "../../features/paths/anchors.js";
4
+ //#region src/canvas/nodeShapes/nodePaint.ts
5
+ function r(e, t) {
6
+ return e === void 0 ? t : e;
7
+ }
8
+ function i(e) {
9
+ return e?.paint == null ? null : e;
10
+ }
11
+ function a(n, r) {
12
+ if (n === null) return {
13
+ outset: 0,
14
+ inset: 0
15
+ };
16
+ let i = t(n), a = (e, t) => {
17
+ switch (n.align ?? "center") {
18
+ case "inner": return {
19
+ outset: t,
20
+ inset: e
21
+ };
22
+ case "outer": return {
23
+ outset: e + t,
24
+ inset: 0
25
+ };
26
+ default: return {
27
+ outset: e / 2 + t,
28
+ inset: e / 2
29
+ };
30
+ }
31
+ }, o = n.width ?? 1, s = a(typeof o == "object" ? 0 : e(o, r ?? 1), i.world);
32
+ if (typeof o != "object" && !(i.px > 0)) return s;
33
+ let c = a(typeof o == "object" ? o.px : 0, i.px);
34
+ return {
35
+ outset: s.outset,
36
+ inset: s.inset,
37
+ outsetPx: c.outset,
38
+ insetPx: c.inset
39
+ };
40
+ }
41
+ function o(e, t) {
42
+ let r = t?.vertexColors, i = e[0];
43
+ if (r === void 0 || i?.kind !== "path") return e;
44
+ let a = 4 * n(i.path), o = i.fill ? r("fill", i.vertexColors) : void 0, s = i.stroke ? r("stroke", i.stroke.vertexColors) : void 0, c = o?.length === a && o !== i.vertexColors, l = s?.length === a && s !== i.stroke?.vertexColors;
45
+ return !c && !l ? e : [{
46
+ ...i,
47
+ ...c ? { vertexColors: o } : {},
48
+ ...l ? { stroke: {
49
+ ...i.stroke,
50
+ vertexColors: s
51
+ } } : {}
52
+ }, ...e.slice(1)];
53
+ }
54
+ //#endregion
55
+ export { a as inkReach, r as resolveNodeFill, i as resolveNodeStroke, o as withAnimatedVertexColors };
56
+
57
+ //# sourceMappingURL=nodePaint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodePaint.js","names":["resolveNodeFill","fill","fallback","resolveNodeStroke","stroke","inkReach","heads","markerReach","sides","headReach","width","world","resolveStrokeWidth","scale","px","withAnimatedVertexColors","resolve","ctx","body","cmds","expected","countPathAnchors","fillChanged","strokeChanged"],"sources":["../../../src/canvas/nodeShapes/nodePaint.ts"],"sourcesContent":["import type { FillStyle, Stroke } from '@weasel-js/paint';\nimport type { NodeInk, NodePaintCtx } from 'canvas/NodeShape';\nimport { countPathAnchors } from 'features/paths/anchors';\nimport { markerReach } from 'features/paths/markerCommands';\nimport { resolveStrokeWidth } from 'features/paths/tessellate/stroke';\nimport type { DrawCommand, PathDrawCommand } from '../../renderer';\n\n/**\n * What a node's `data.fill` means to the built-in painters.\n *\n * A {@link FillStyle} is used as-is — which is how a gradient or a pattern\n * reaches the renderer without a consumer registering a painter of its own.\n * `null` is an explicit \"no fill\"; `undefined` takes the painter's fallback.\n * Write one with {@link solid} rather than by hand when all you have is a\n * color.\n */\nexport function resolveNodeFill(\n fill: FillStyle | null | undefined,\n fallback: FillStyle | null,\n): FillStyle | null {\n return fill === undefined ? fallback : fill;\n}\n\n/** The stroke a built-in painter should emit, or `null` for \"no stroke\".\n * `data.stroke` is a whole {@link Stroke} — width, cap, join, dash, miter\n * limit and align all reach the renderer. {@link strokeOf} builds one from a\n * color.\n *\n * A stroke carrying no `paint` reads as no stroke. `Stroke.paint` is\n * required by the type, so this is unreachable from well-formed data — but a\n * document is data, and a stroke assembled a field at a time (a width\n * written onto a node that had none) arrives here without one. Painting it\n * threw out of `fillInPoseFrame`, and the throw escapes the painter and\n * takes the whole frame with it: the page and every other node vanish, and\n * the canvas stays stale until something unrelated requests a redraw. One\n * malformed node must not be able to blank the document. */\nexport function resolveNodeStroke(stroke: Stroke | null | undefined): PaintedStroke | null {\n if (stroke?.paint == null) return null;\n return stroke as PaintedStroke;\n}\n\n/** A stroke that paints — what everything downstream of `resolveNodeStroke`\n * works with. */\nexport type PaintedStroke = Stroke & { paint: FillStyle };\n\n/** Per-side grab reach for a resolved stroke: world units for what the\n * renderer builds in world, screen pixels for what it builds on screen — a\n * `{ px }` width, and each head by its own size's units. */\nexport function inkReach(\n stroke: Stroke | null,\n scale: number | undefined,\n): Pick<NodeInk, 'outset' | 'inset' | 'outsetPx' | 'insetPx'> {\n if (stroke === null) return { outset: 0, inset: 0 };\n // A marker paints past the path's own end, and the kit's rule is that\n // visible chrome is hittable — so the reach has to cover it.\n const heads = markerReach(stroke);\n const sides = (width: number, headReach: number) => {\n switch (stroke.align ?? 'center') {\n case 'inner': return { outset: headReach, inset: width };\n case 'outer': return { outset: width + headReach, inset: 0 };\n default: return { outset: width / 2 + headReach, inset: width / 2 };\n }\n };\n const width = stroke.width ?? 1;\n const world = sides(typeof width === 'object' ? 0 : resolveStrokeWidth(width, scale ?? 1), heads.world);\n if (typeof width !== 'object' && !(heads.px > 0)) return world;\n const px = sides(typeof width === 'object' ? width.px : 0, heads.px);\n return { outset: world.outset, inset: world.inset, outsetPx: px.outset, insetPx: px.inset };\n}\n\n/** Apply {@link NodePaintCtx.vertexColors} to a path painter's body — its first\n * command. Applied outside the paint memo, whose key\n * cannot see an override: `cmds` comes back as-is when nothing changes, and\n * otherwise as a copy, since a memoized list is not ours to edit. Colors whose\n * length does not match the path's anchors are dropped. */\nexport function withAnimatedVertexColors(cmds: DrawCommand[], ctx: NodePaintCtx | undefined): DrawCommand[] {\n const resolve = ctx?.vertexColors;\n const body = cmds[0];\n if (resolve === undefined || body?.kind !== 'path') return cmds;\n const expected = 4 * countPathAnchors(body.path);\n const fill = body.fill ? resolve('fill', body.vertexColors) : undefined;\n const stroke = body.stroke ? resolve('stroke', body.stroke.vertexColors) : undefined;\n const fillChanged = fill?.length === expected && fill !== body.vertexColors;\n const strokeChanged = stroke?.length === expected && stroke !== body.stroke?.vertexColors;\n if (!fillChanged && !strokeChanged) return cmds;\n const next: PathDrawCommand = {\n ...body,\n ...(fillChanged ? { vertexColors: fill as number[] } : {}),\n ...(strokeChanged ? { stroke: { ...body.stroke!, vertexColors: stroke as number[] } } : {}),\n };\n return [next, ...cmds.slice(1)];\n}\n"],"mappings":";;;;AAgBA,SAAgBA,EACd,GACA,GACkB;CAClB,OAAOC,MAAS,KAAA,IAAYC,IAAWD;AACzC;AAeA,SAAgBE,EAAkB,GAAyD;CAEzF,OADIC,GAAQ,SAAS,OAAa,OAC3BA;AACT;AASA,SAAgBC,EACd,GACA,GAC4D;CAC5D,IAAID,MAAW,MAAM,OAAO;EAAE,QAAQ;EAAG,OAAO;CAAE;CAGlD,IAAME,IAAQC,EAAYH,CAAM,GAC1BI,KAAS,GAAe,MAAsB;EAClD,QAAQJ,EAAO,SAAS,UAAxB;GACE,KAAK,SAAS,OAAO;IAAE,QAAQK;IAAW,OAAOC;GAAM;GACvD,KAAK,SAAS,OAAO;IAAE,QAAQA,IAAQD;IAAW,OAAO;GAAE;GAC3D,SAAS,OAAO;IAAE,QAAQC,IAAQ,IAAID;IAAW,OAAOC,IAAQ;GAAE;EACpE;CACF,GACMA,IAAQN,EAAO,SAAS,GACxBO,IAAQH,EAAM,OAAOE,KAAU,WAAW,IAAIE,EAAmBF,GAAOG,KAAS,CAAC,GAAGP,EAAM,KAAK;CACtG,IAAI,OAAOI,KAAU,YAAY,EAAEJ,EAAM,KAAK,IAAI,OAAOK;CACzD,IAAMG,IAAKN,EAAM,OAAOE,KAAU,WAAWA,EAAM,KAAK,GAAGJ,EAAM,EAAE;CACnE,OAAO;EAAE,QAAQK,EAAM;EAAQ,OAAOA,EAAM;EAAO,UAAUG,EAAG;EAAQ,SAASA,EAAG;CAAM;AAC5F;AAOA,SAAgBC,EAAyB,GAAqB,GAA8C;CAC1G,IAAMC,IAAUC,GAAK,cACfC,IAAOC,EAAK;CAClB,IAAIH,MAAY,KAAA,KAAaE,GAAM,SAAS,QAAQ,OAAOC;CAC3D,IAAMC,IAAW,IAAIC,EAAiBH,EAAK,IAAI,GACzCjB,IAAOiB,EAAK,OAAOF,EAAQ,QAAQE,EAAK,YAAY,IAAI,KAAA,GACxDd,IAASc,EAAK,SAASF,EAAQ,UAAUE,EAAK,OAAO,YAAY,IAAI,KAAA,GACrEI,IAAcrB,GAAM,WAAWmB,KAAYnB,MAASiB,EAAK,cACzDK,IAAgBnB,GAAQ,WAAWgB,KAAYhB,MAAWc,EAAK,QAAQ;CAO7E,OANI,CAACI,KAAe,CAACC,IAAsBJ,IAMpC,CAAC;EAJN,GAAGD;EACH,GAAII,IAAc,EAAE,cAAcrB,EAAiB,IAAI,CAAC;EACxD,GAAIsB,IAAgB,EAAE,QAAQ;GAAE,GAAGL,EAAK;GAAS,cAAcd;EAAmB,EAAE,IAAI,CAAC;CAEnF,GAAM,GAAGe,EAAK,MAAM,CAAC,CAAC;AAChC"}
@@ -0,0 +1,38 @@
1
+ import { nodeMemo as e } from "../../core/scene/nodeMemo.js";
2
+ import { commandFill as t, commandStroke as n } from "../../features/patterns/commandPaint.js";
3
+ import { DEFAULT_SHAPE_FILL as r } from "../../util/paint.js";
4
+ import { PAINT_SLOT as i } from "./memo.js";
5
+ import { inkReach as a, resolveNodeFill as o, resolveNodeStroke as s, withAnimatedVertexColors as c } from "./nodePaint.js";
6
+ import { paintsPose as l, poseBoxBounds as u } from "./poseBox.js";
7
+ import { pathInPoseFrame as d } from "../../features/paths/pathInWorld.js";
8
+ //#region src/canvas/nodeShapes/pathPainter.ts
9
+ var f = {
10
+ id: "kit:path",
11
+ matches: (e) => l(e.pose) ? e.data?.path != null : !1,
12
+ paint: (a, l, u) => c(e(a, i, l, () => {
13
+ let e = a.data, i = d(e.path, l), c = s(e.stroke), u = c !== null, f = o(e.fill, u ? null : r), p = f && t(f, l), m = c && n(c, l);
14
+ return [{
15
+ kind: "path",
16
+ path: i,
17
+ ...p ? { fill: p } : {},
18
+ ...p && e.vertexColors ? { vertexColors: e.vertexColors } : {},
19
+ ...m ? { stroke: m } : {}
20
+ }];
21
+ }), u),
22
+ silhouette: (e, t) => {
23
+ let n = e.data;
24
+ return d(n.path, t);
25
+ },
26
+ ink: (e, t, n) => {
27
+ let i = e.data, c = s(i.stroke), l = c !== null;
28
+ return {
29
+ filled: o(i.fill, l ? null : r) !== null,
30
+ ...a(c, n?.scale)
31
+ };
32
+ },
33
+ bounds: (e, t, n) => u(t, s(e.data.stroke), n)
34
+ };
35
+ //#endregion
36
+ export { f as PATH_PAINTER };
37
+
38
+ //# sourceMappingURL=pathPainter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathPainter.js","names":["PATH_PAINTER","paintsPose","node","withAnimatedVertexColors","nodeMemo","PAINT_SLOT","pose","d","projected","pathInPoseFrame","strokeSpec","resolveNodeStroke","hasStroke","declared","resolveNodeFill","DEFAULT_SHAPE_FILL","fill","commandFill","stroke","commandStroke","ctx","inkReach","poseBoxBounds"],"sources":["../../../src/canvas/nodeShapes/pathPainter.ts"],"sourcesContent":["import type {\n Path\n} from '@weasel-js/geom';\nimport type { FillStyle, Stroke } from '@weasel-js/paint';\nimport type { NodeShapeEntry } from 'canvas/NodeShape';\nimport { nodeMemo } from 'core/scene/nodeMemo';\nimport type { RectPose } from 'core/scene/types';\nimport { pathInPoseFrame } from 'features/paths/pathInWorld';\nimport { commandFill, commandStroke } from '../../features/patterns/commandPaint';\nimport type { DrawCommand } from '../../renderer';\nimport { DEFAULT_SHAPE_FILL } from '../../util/paint';\nimport { PAINT_SLOT } from './memo';\nimport { inkReach, withAnimatedVertexColors, resolveNodeFill, resolveNodeStroke } from './nodePaint';\nimport { paintsPose, poseBoxBounds } from './poseBox';\n\n// ─── Built-in painters ─────────────────────────────────────────────────\nexport const PATH_PAINTER: NodeShapeEntry<unknown, RectPose> = {\n id: 'kit:path',\n matches: (node) => {\n if (!paintsPose(node.pose)) return false;\n const d = node.data as { path?: Path } | null;\n return d?.path != null;\n },\n // Memoized: a pure function of `(data, pose)`, and `pathInPoseFrame`\n // allocates on every call but the identity (`kind: 'rect'`) branch. See\n // PAINT_SLOT.\n paint: (node, pose, ctx) => withAnimatedVertexColors(nodeMemo(node, PAINT_SLOT, pose, () => {\n const d = node.data as {\n path: Path;\n fill?: FillStyle | null;\n stroke?: Stroke | null;\n vertexColors?: number[];\n };\n const projected = pathInPoseFrame(d.path, pose);\n const strokeSpec = resolveNodeStroke(d.stroke);\n const hasStroke = strokeSpec !== null;\n // An undeclared fill falls back to the default one only if there's no\n // stroke — otherwise the path is stroke-only (e.g. pencil) and a default\n // fill would be wrong.\n const declared = resolveNodeFill(d.fill, hasStroke ? null : DEFAULT_SHAPE_FILL);\n // The pose is baked into `projected` rather than emitted as a transform,\n // so a box-relative gradient has to be baked onto the same box here or\n // it would arrive in the renderer referring to a frame that never exists.\n const fill = declared && commandFill(declared, pose);\n const stroke = strokeSpec && commandStroke(strokeSpec, pose);\n const cmd: DrawCommand = {\n kind: 'path',\n path: projected,\n ...(fill ? { fill } : {}),\n ...(fill && d.vertexColors ? { vertexColors: d.vertexColors } : {}),\n ...(stroke ? { stroke } : {}),\n };\n return [cmd];\n }), ctx),\n silhouette: (node, pose) => {\n const d = node.data as { path: Path };\n return pathInPoseFrame(d.path, pose);\n },\n // Mirrors the fill/stroke decisions `paint` makes above — same reads, same\n // 'none' handling, same \"no fill declared and a stroke present means\n // stroke-only\" fallback. Kept in step with `paint` by\n // `NodeShape.ink.test.ts`, which asserts the two agree.\n ink: (node, _pose, ctx) => {\n const d = node.data as {\n fill?: FillStyle | null;\n stroke?: Stroke | null;\n };\n const stroke = resolveNodeStroke(d.stroke);\n const hasStroke = stroke !== null;\n return {\n filled: resolveNodeFill(d.fill, hasStroke ? null : DEFAULT_SHAPE_FILL) !== null,\n ...inkReach(stroke, ctx?.scale),\n };\n },\n // `pathInPoseFrame` fits the path's own bounds to the pose box.\n bounds: (node, pose, ctx) =>\n poseBoxBounds(pose, resolveNodeStroke((node.data as { stroke?: Stroke | null }).stroke), ctx),\n};\n"],"mappings":";;;;;;;;AAgBA,IAAaA,IAAkD;CAC7D,IAAI;CACJ,UAAU,MACHC,EAAWC,EAAK,IAAI,IACfA,EAAK,MACL,QAAQ,OAFiB;CAOrC,QAAQ,GAAM,GAAM,MAAQC,EAAyBC,EAASF,GAAMG,GAAYC,SAAY;EAC1F,IAAMC,IAAIL,EAAK,MAMTM,IAAYC,EAAgBF,EAAE,MAAMD,CAAI,GACxCI,IAAaC,EAAkBJ,EAAE,MAAM,GACvCK,IAAYF,MAAe,MAI3BG,IAAWC,EAAgBP,EAAE,MAAMK,IAAY,OAAOG,CAAkB,GAIxEC,IAAOH,KAAYI,EAAYJ,GAAUP,CAAI,GAC7CY,IAASR,KAAcS,EAAcT,GAAYJ,CAAI;EAQ3D,OAAO,CAAC;GANN,MAAM;GACN,MAAME;GACN,GAAIQ,IAAO,EAAE,QAAK,IAAI,CAAC;GACvB,GAAIA,KAAQT,EAAE,eAAe,EAAE,cAAcA,EAAE,aAAa,IAAI,CAAC;GACjE,GAAIW,IAAS,EAAE,UAAO,IAAI,CAAC;EAErB,CAAG;CACb,CAAC,GAAGE,CAAG;CACP,aAAa,GAAM,MAAS;EAC1B,IAAMb,IAAIL,EAAK;EACf,OAAOO,EAAgBF,EAAE,MAAMD,CAAI;CACrC;CAKA,MAAM,GAAM,GAAO,MAAQ;EACzB,IAAMC,IAAIL,EAAK,MAITgB,IAASP,EAAkBJ,EAAE,MAAM,GACnCK,IAAYM,MAAW;EAC7B,OAAO;GACL,QAAQJ,EAAgBP,EAAE,MAAMK,IAAY,OAAOG,CAAkB,MAAM;GAC3E,GAAGM,EAASH,GAAQE,GAAK,KAAK;EAChC;CACF;CAEA,SAAS,GAAM,GAAM,MACnBE,EAAchB,GAAMK,EAAmBT,EAAK,KAAoC,MAAM,GAAGkB,CAAG;AAChG"}
@@ -0,0 +1,20 @@
1
+ import { strokeReachAt as e } from "../../renderer/cullDrawCommands.js";
2
+ import { isRectPose as t } from "../../interactions/actions/resize/autoPoseDescriptor.js";
3
+ //#region src/canvas/nodeShapes/poseBox.ts
4
+ function n(e) {
5
+ return e === void 0 || t(e);
6
+ }
7
+ function r(n, r, i) {
8
+ if (!t(n)) return null;
9
+ let a = r ? e(r, i?.scale ?? 1, i?.leastScale) : 0, o = Math.min(n.x, n.x + n.width), s = Math.min(n.y, n.y + n.height);
10
+ return {
11
+ x: o - a,
12
+ y: s - a,
13
+ width: Math.abs(n.width) + 2 * a,
14
+ height: Math.abs(n.height) + 2 * a
15
+ };
16
+ }
17
+ //#endregion
18
+ export { n as paintsPose, r as poseBoxBounds };
19
+
20
+ //# sourceMappingURL=poseBox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poseBox.js","names":["paintsPose","pose","isRectPose","poseBoxBounds","reach","stroke","strokeReachAt","ctx","x","y"],"sources":["../../../src/canvas/nodeShapes/poseBox.ts"],"sourcesContent":["import type { Stroke } from '@weasel-js/paint';\nimport type { NodeInkCtx } from 'canvas/NodeShape';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { isRectPose } from 'interactions/actions/resize/autoPoseDescriptor';\nimport { strokeReachAt } from '../../renderer/cullDrawCommands';\n\n/** Whether a built-in painter can read this pose. A node that declares none\n * passes: the pose is then the caller's argument, not the node's. */\nexport function paintsPose(pose: unknown): boolean {\n return pose === undefined || isRectPose(pose);\n}\n\n/** The pose rect grown by how far `stroke` can paint outside it — the paint\n * box of every built-in painter whose geometry the pose box contains. */\nexport function poseBoxBounds(pose: unknown, stroke: Stroke | null, ctx: NodeInkCtx | undefined): Bounds | null {\n if (!isRectPose(pose)) return null;\n const reach = stroke ? strokeReachAt(stroke, ctx?.scale ?? 1, ctx?.leastScale) : 0;\n const x = Math.min(pose.x, pose.x + pose.width);\n const y = Math.min(pose.y, pose.y + pose.height);\n return {\n x: x - reach,\n y: y - reach,\n width: Math.abs(pose.width) + 2 * reach,\n height: Math.abs(pose.height) + 2 * reach,\n };\n}\n"],"mappings":";;;AAQA,SAAgBA,EAAW,GAAwB;CACjD,OAAOC,MAAS,KAAA,KAAaC,EAAWD,CAAI;AAC9C;AAIA,SAAgBE,EAAc,GAAe,GAAuB,GAA4C;CAC9G,IAAI,CAACD,EAAWD,CAAI,GAAG,OAAO;CAC9B,IAAMG,IAAQC,IAASC,EAAcD,GAAQE,GAAK,SAAS,GAAGA,GAAK,UAAU,IAAI,GAC3EC,IAAI,KAAK,IAAIP,EAAK,GAAGA,EAAK,IAAIA,EAAK,KAAK,GACxCQ,IAAI,KAAK,IAAIR,EAAK,GAAGA,EAAK,IAAIA,EAAK,MAAM;CAC/C,OAAO;EACL,GAAGO,IAAIJ;EACP,GAAGK,IAAIL;EACP,OAAO,KAAK,IAAIH,EAAK,KAAK,IAAI,IAAIG;EAClC,QAAQ,KAAK,IAAIH,EAAK,MAAM,IAAI,IAAIG;CACtC;AACF"}
@@ -0,0 +1,38 @@
1
+ import { commandFill as e } from "../../features/patterns/commandPaint.js";
2
+ import { DEFAULT_SHAPE_FILL as t } from "../../util/paint.js";
3
+ import { resolveNodeFill as n } from "./nodePaint.js";
4
+ import { paintsPose as r, poseBoxBounds as i } from "./poseBox.js";
5
+ //#region src/canvas/nodeShapes/rectFallbackPainter.ts
6
+ var a = {
7
+ id: "kit:rect-fallback",
8
+ matches: (e) => r(e.pose),
9
+ paint: (r, i) => {
10
+ let a = r.data, o = i, s = n(a?.fill, t), c = s && e(s, o);
11
+ return [{
12
+ kind: "path",
13
+ path: {
14
+ kind: "rect",
15
+ x: o.x,
16
+ y: o.y,
17
+ width: o.width,
18
+ height: o.height
19
+ },
20
+ ...c ? { fill: c } : {}
21
+ }];
22
+ },
23
+ silhouette: (e, t) => {
24
+ let n = t;
25
+ return {
26
+ kind: "rect",
27
+ x: n.x,
28
+ y: n.y,
29
+ width: n.width,
30
+ height: n.height
31
+ };
32
+ },
33
+ bounds: (e, t) => i(t, null, void 0)
34
+ };
35
+ //#endregion
36
+ export { a as RECT_FALLBACK_PAINTER };
37
+
38
+ //# sourceMappingURL=rectFallbackPainter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rectFallbackPainter.js","names":["RECT_FALLBACK_PAINTER","paintsPose","node","d","p","pose","declared","resolveNodeFill","DEFAULT_SHAPE_FILL","fill","commandFill","poseBoxBounds"],"sources":["../../../src/canvas/nodeShapes/rectFallbackPainter.ts"],"sourcesContent":["import type { FillStyle } from '@weasel-js/paint';\nimport type { NodeShapeEntry } from 'canvas/NodeShape';\nimport type { RectPose } from 'core/scene/types';\nimport { commandFill } from '../../features/patterns/commandPaint';\nimport { DEFAULT_SHAPE_FILL } from '../../util/paint';\nimport { resolveNodeFill } from './nodePaint';\nimport { paintsPose, poseBoxBounds } from './poseBox';\n\n// ─── Built-in painters ─────────────────────────────────────────────────\nexport const RECT_FALLBACK_PAINTER: NodeShapeEntry<unknown, RectPose> = {\n // Last-resort painter — matches any rect-posed node, so it must be\n // registered last within `'normal'`. Consumers who want a different\n // fallback should register their own painter at `'high'` priority and let\n // this one never fire (or unregister it explicitly).\n id: 'kit:rect-fallback',\n matches: (node) => paintsPose(node.pose),\n paint: (node, pose) => {\n const d = node.data as { fill?: FillStyle | null } | null;\n const p = pose;\n const declared = resolveNodeFill(d?.fill, DEFAULT_SHAPE_FILL);\n const fill = declared && commandFill(declared, p);\n return [{\n kind: 'path',\n path: { kind: 'rect', x: p.x, y: p.y, width: p.width, height: p.height },\n ...(fill ? { fill } : {}),\n }];\n },\n silhouette: (_node, pose) => {\n const p = pose;\n return { kind: 'rect', x: p.x, y: p.y, width: p.width, height: p.height };\n },\n bounds: (_node, pose) => poseBoxBounds(pose, null, undefined),\n};\n"],"mappings":";;;;;AASA,IAAaA,IAA2D;CAKtE,IAAI;CACJ,UAAU,MAASC,EAAWC,EAAK,IAAI;CACvC,QAAQ,GAAM,MAAS;EACrB,IAAMC,IAAID,EAAK,MACTE,IAAIC,GACJC,IAAWC,EAAgBJ,GAAG,MAAMK,CAAkB,GACtDC,IAAOH,KAAYI,EAAYJ,GAAUF,CAAC;EAChD,OAAO,CAAC;GACN,MAAM;GACN,MAAM;IAAE,MAAM;IAAQ,GAAGA,EAAE;IAAG,GAAGA,EAAE;IAAG,OAAOA,EAAE;IAAO,QAAQA,EAAE;GAAO;GACvE,GAAIK,IAAO,EAAE,QAAK,IAAI,CAAC;EACzB,CAAC;CACH;CACA,aAAa,GAAO,MAAS;EAC3B,IAAML,IAAIC;EACV,OAAO;GAAE,MAAM;GAAQ,GAAGD,EAAE;GAAG,GAAGA,EAAE;GAAG,OAAOA,EAAE;GAAO,QAAQA,EAAE;EAAO;CAC1E;CACA,SAAS,GAAO,MAASO,EAAcN,GAAM,MAAM,KAAA,CAAS;AAC9D"}
@@ -0,0 +1,72 @@
1
+ import { nodeMemo as e } from "../../core/scene/nodeMemo.js";
2
+ import { commandFill as t, commandStroke as n } from "../../features/patterns/commandPaint.js";
3
+ import { DEFAULT_SHAPE_FILL as r } from "../../util/paint.js";
4
+ import { PAINT_SLOT as i } from "./memo.js";
5
+ import { inkReach as a, resolveNodeFill as o, resolveNodeStroke as s, withAnimatedVertexColors as c } from "./nodePaint.js";
6
+ import { paintsPose as l, poseBoxBounds as u } from "./poseBox.js";
7
+ import { ellipsePath as d, regularPolygonPath as f, starPath as p } from "@weasel-js/geom";
8
+ //#region src/canvas/nodeShapes/shapePainter.ts
9
+ var m = {
10
+ id: "kit:shape",
11
+ matches: (e) => {
12
+ if (!l(e.pose)) return !1;
13
+ let t = e.data?.shape;
14
+ return t != null && h.has(t);
15
+ },
16
+ paint: (a, l, u) => c(e(a, i, l, () => {
17
+ let e = a.data, i = g(e, l), c = o(e.fill, r), u = c && t(c, l), d = s(e.stroke), f = d && n(d, l);
18
+ return [{
19
+ kind: "path",
20
+ path: i,
21
+ ...u ? { fill: u } : {},
22
+ ...f ? { stroke: f } : {}
23
+ }];
24
+ }), u),
25
+ silhouette: (e, t) => {
26
+ let n = e.data;
27
+ return g(n, t);
28
+ },
29
+ ink: (e, t, n) => {
30
+ let i = e.data;
31
+ return {
32
+ filled: o(i.fill, r) !== null,
33
+ ...a(s(i.stroke), n?.scale)
34
+ };
35
+ },
36
+ bounds: (e, t, n) => u(t, s(e.data.stroke), n)
37
+ }, h = /* @__PURE__ */ new Set([
38
+ "rect",
39
+ "ellipse",
40
+ "polygon",
41
+ "star"
42
+ ]);
43
+ function g(e, t) {
44
+ switch (e.shape) {
45
+ case "ellipse": return d(t);
46
+ case "polygon": {
47
+ let n = t.x + t.width / 2, r = t.y + t.height / 2, i = Math.min(t.width, t.height) / 2;
48
+ return f({
49
+ x: n,
50
+ y: r
51
+ }, i, e.sides ?? 6);
52
+ }
53
+ case "star": {
54
+ let n = t.x + t.width / 2, r = t.y + t.height / 2, i = Math.min(t.width, t.height) / 2;
55
+ return p({
56
+ x: n,
57
+ y: r
58
+ }, i, e.points ?? 5);
59
+ }
60
+ default: return {
61
+ kind: "rect",
62
+ x: t.x,
63
+ y: t.y,
64
+ width: t.width,
65
+ height: t.height
66
+ };
67
+ }
68
+ }
69
+ //#endregion
70
+ export { h as SHAPE_KINDS, m as SHAPE_PAINTER, g as pathForShape };
71
+
72
+ //# sourceMappingURL=shapePainter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shapePainter.js","names":["SHAPE_PAINTER","paintsPose","node","s","SHAPE_KINDS","withAnimatedVertexColors","nodeMemo","PAINT_SLOT","pose","d","path","pathForShape","declaredFill","resolveNodeFill","DEFAULT_SHAPE_FILL","shapeFill","commandFill","strokeSpec","resolveNodeStroke","stroke","commandStroke","ctx","inkReach","poseBoxBounds","ellipsePath","p","cx","cy","r","regularPolygonPath","starPath"],"sources":["../../../src/canvas/nodeShapes/shapePainter.ts"],"sourcesContent":["import {\n ellipsePath,\n regularPolygonPath,\n starPath,\n type Path\n} from '@weasel-js/geom';\nimport type { FillStyle, Stroke } from '@weasel-js/paint';\nimport type { NodeShapeEntry } from 'canvas/NodeShape';\nimport { nodeMemo } from 'core/scene/nodeMemo';\nimport type { RectPose } from 'core/scene/types';\nimport { commandFill, commandStroke } from '../../features/patterns/commandPaint';\nimport { DEFAULT_SHAPE_FILL } from '../../util/paint';\nimport { PAINT_SLOT } from './memo';\nimport { inkReach, withAnimatedVertexColors, resolveNodeFill, resolveNodeStroke } from './nodePaint';\nimport { paintsPose, poseBoxBounds } from './poseBox';\n\n// ─── Built-in painters ─────────────────────────────────────────────────\n/** Built-in shape dispatcher — matches when `data.shape` names a kit-known\n * shape kind. Computes both paint and silhouette from the pose so consumer\n * scenes can declare clipping/rendering directly in JSON without\n * registering a custom painter. */\nexport const SHAPE_PAINTER: NodeShapeEntry<unknown, RectPose> = {\n id: 'kit:shape',\n matches: (node) => {\n if (!paintsPose(node.pose)) return false;\n const s = (node.data as { shape?: string } | null)?.shape;\n return s != null && SHAPE_KINDS.has(s);\n },\n // Memoized: a pure function of `(data, pose)`, and `pathForShape` builds a\n // fresh `Uint8Array` + `Float32Array` for every ellipse, polygon and star.\n // See PAINT_SLOT.\n paint: (node, pose, ctx) => withAnimatedVertexColors(nodeMemo(node, PAINT_SLOT, pose, () => {\n const d = node.data as { shape: string; fill?: FillStyle | null; stroke?: Stroke | null; sides?: number; points?: number };\n const path = pathForShape(d, pose);\n const declaredFill = resolveNodeFill(d.fill, DEFAULT_SHAPE_FILL);\n const shapeFill = declaredFill && commandFill(declaredFill, pose);\n const strokeSpec = resolveNodeStroke(d.stroke);\n const stroke = strokeSpec && commandStroke(strokeSpec, pose);\n return [{\n kind: 'path',\n path,\n ...(shapeFill ? { fill: shapeFill } : {}),\n ...(stroke ? { stroke } : {}),\n }];\n }), ctx),\n silhouette: (node, pose) => {\n const d = node.data as { shape: string; sides?: number; points?: number };\n return pathForShape(d, pose);\n },\n // `paint` above emits the default fill when none is declared, so a shape\n // is filled unless it declares `fill: null` — unlike `kit:path`, it has no\n // implicit stroke-only form.\n ink: (node, _pose, ctx) => {\n const d = node.data as { fill?: FillStyle | null; stroke?: Stroke | null };\n return {\n filled: resolveNodeFill(d.fill, DEFAULT_SHAPE_FILL) !== null,\n ...inkReach(resolveNodeStroke(d.stroke), ctx?.scale),\n };\n },\n // Every shape kind is inscribed in the pose box.\n bounds: (node, pose, ctx) =>\n poseBoxBounds(pose, resolveNodeStroke((node.data as { stroke?: Stroke | null }).stroke), ctx),\n};\n\nexport const SHAPE_KINDS = new Set(['rect', 'ellipse', 'polygon', 'star']);\n\nexport function pathForShape(\n d: { shape: string; sides?: number; points?: number },\n p: RectPose,\n): Path {\n switch (d.shape) {\n case 'ellipse':\n return ellipsePath(p);\n case 'polygon': {\n const cx = p.x + p.width / 2;\n const cy = p.y + p.height / 2;\n const r = Math.min(p.width, p.height) / 2;\n return regularPolygonPath({ x: cx, y: cy }, r, d.sides ?? 6);\n }\n case 'star': {\n const cx = p.x + p.width / 2;\n const cy = p.y + p.height / 2;\n const r = Math.min(p.width, p.height) / 2;\n return starPath({ x: cx, y: cy }, r, d.points ?? 5);\n }\n case 'rect':\n default:\n return { kind: 'rect', x: p.x, y: p.y, width: p.width, height: p.height };\n }\n}\n"],"mappings":";;;;;;;;AAqBA,IAAaA,IAAmD;CAC9D,IAAI;CACJ,UAAU,MAAS;EACjB,IAAI,CAACC,EAAWC,EAAK,IAAI,GAAG,OAAO;EACnC,IAAMC,IAAKD,EAAK,MAAoC;EACpD,OAAOC,KAAK,QAAQC,EAAY,IAAID,CAAC;CACvC;CAIA,QAAQ,GAAM,GAAM,MAAQE,EAAyBC,EAASJ,GAAMK,GAAYC,SAAY;EAC1F,IAAMC,IAAIP,EAAK,MACTQ,IAAOC,EAAaF,GAAGD,CAAI,GAC3BI,IAAeC,EAAgBJ,EAAE,MAAMK,CAAkB,GACzDC,IAAYH,KAAgBI,EAAYJ,GAAcJ,CAAI,GAC1DS,IAAaC,EAAkBT,EAAE,MAAM,GACvCU,IAASF,KAAcG,EAAcH,GAAYT,CAAI;EAC3D,OAAO,CAAC;GACN,MAAM;GACN;GACA,GAAIO,IAAY,EAAE,MAAMA,EAAU,IAAI,CAAC;GACvC,GAAII,IAAS,EAAE,UAAO,IAAI,CAAC;EAC7B,CAAC;CACH,CAAC,GAAGE,CAAG;CACP,aAAa,GAAM,MAAS;EAC1B,IAAMZ,IAAIP,EAAK;EACf,OAAOS,EAAaF,GAAGD,CAAI;CAC7B;CAIA,MAAM,GAAM,GAAO,MAAQ;EACzB,IAAMC,IAAIP,EAAK;EACf,OAAO;GACL,QAAQW,EAAgBJ,EAAE,MAAMK,CAAkB,MAAM;GACxD,GAAGQ,EAASJ,EAAkBT,EAAE,MAAM,GAAGY,GAAK,KAAK;EACrD;CACF;CAEA,SAAS,GAAM,GAAM,MACnBE,EAAcf,GAAMU,EAAmBhB,EAAK,KAAoC,MAAM,GAAGmB,CAAG;AAChG,GAEajB,oBAAc,IAAI,IAAI;CAAC;CAAQ;CAAW;CAAW;AAAM,CAAC;AAEzE,SAAgBO,EACd,GACA,GACM;CACN,QAAQF,EAAE,OAAV;EACE,KAAK,WACH,OAAOe,EAAYC,CAAC;EACtB,KAAK,WAAW;GACd,IAAMC,IAAKD,EAAE,IAAIA,EAAE,QAAQ,GACrBE,IAAKF,EAAE,IAAIA,EAAE,SAAS,GACtBG,IAAI,KAAK,IAAIH,EAAE,OAAOA,EAAE,MAAM,IAAI;GACxC,OAAOI,EAAmB;IAAE,GAAGH;IAAI,GAAGC;GAAG,GAAGC,GAAGnB,EAAE,SAAS,CAAC;EAC7D;EACA,KAAK,QAAQ;GACX,IAAMiB,IAAKD,EAAE,IAAIA,EAAE,QAAQ,GACrBE,IAAKF,EAAE,IAAIA,EAAE,SAAS,GACtBG,IAAI,KAAK,IAAIH,EAAE,OAAOA,EAAE,MAAM,IAAI;GACxC,OAAOK,EAAS;IAAE,GAAGJ;IAAI,GAAGC;GAAG,GAAGC,GAAGnB,EAAE,UAAU,CAAC;EACpD;EAEA,SACE,OAAO;GAAE,MAAM;GAAQ,GAAGgB,EAAE;GAAG,GAAGA,EAAE;GAAG,OAAOA,EAAE;GAAO,QAAQA,EAAE;EAAO;CAC5E;AACF"}
@@ -0,0 +1,55 @@
1
+ import { nodeMemo as e } from "../../core/scene/nodeMemo.js";
2
+ import { PAINT_SLOT as t } from "./memo.js";
3
+ import { inkReach as n, resolveNodeStroke as r } from "./nodePaint.js";
4
+ import { paintsPose as i } from "./poseBox.js";
5
+ import { textCommandFromPose as a } from "../../features/text/textCommand.js";
6
+ import { PATH_L as o, PATH_M as s, PATH_Z as c } from "@weasel-js/geom";
7
+ import { textLineBoxes as l } from "@weasel-js/text";
8
+ //#region src/canvas/nodeShapes/textPainter.ts
9
+ function u(e, t) {
10
+ return {
11
+ x: t.x,
12
+ y: t.y,
13
+ width: t.width,
14
+ height: t.height,
15
+ text: e.text,
16
+ runs: e.runs,
17
+ style: e.style,
18
+ fill: e.fill,
19
+ stroke: r(e.stroke) ?? void 0,
20
+ verticalAlign: e.verticalAlign
21
+ };
22
+ }
23
+ var d = {
24
+ id: "kit:text",
25
+ matches: (e) => i(e.pose) ? e.data?.text != null : !1,
26
+ paint: (n, r) => e(n, t, r, () => [a(u(n.data, r))]),
27
+ silhouette: (e, t) => {
28
+ let n = l(u(e.data, t));
29
+ return n.length === 0 ? null : f(n);
30
+ },
31
+ ink: (e, t, i) => {
32
+ let a = e.data;
33
+ return {
34
+ filled: !0,
35
+ ...n(r(a.stroke), i?.scale)
36
+ };
37
+ }
38
+ };
39
+ function f(e) {
40
+ let t = new Uint8Array(e.length * 6), n = new Float32Array(e.length * 10), r = 0, i = 0;
41
+ for (let a of e) {
42
+ let { x: e, y: l, width: u, height: d } = a;
43
+ t[i++] = s, n[r++] = e, n[r++] = l, t[i++] = o, n[r++] = e + u, n[r++] = l, t[i++] = o, n[r++] = e + u, n[r++] = l + d, t[i++] = o, n[r++] = e, n[r++] = l + d, t[i++] = o, n[r++] = e, n[r++] = l, t[i++] = c;
44
+ }
45
+ return {
46
+ kind: "polygon",
47
+ commands: t,
48
+ coords: n,
49
+ fillRule: "nonzero"
50
+ };
51
+ }
52
+ //#endregion
53
+ export { d as TEXT_PAINTER, f as rectsToPath, u as textPoseOf };
54
+
55
+ //# sourceMappingURL=textPainter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textPainter.js","names":["textPoseOf","p","d","resolveNodeStroke","TEXT_PAINTER","paintsPose","node","nodeMemo","PAINT_SLOT","pose","textCommandFromPose","boxes","textLineBoxes","rectsToPath","inkReach","ctx","commands","rects","coords","ci","cmd","r","w","h","PATH_M","x","y","PATH_L","PATH_Z"],"sources":["../../../src/canvas/nodeShapes/textPainter.ts"],"sourcesContent":["import {\n PATH_L,\n PATH_M,\n PATH_Z,\n type PolygonPath\n} from '@weasel-js/geom';\nimport type { FillStyle, Stroke } from '@weasel-js/paint';\nimport type { StyledRun, TextPose, TextStyle, TextVerticalAlign } from '@weasel-js/text';\nimport { textLineBoxes } from '@weasel-js/text';\nimport type { NodeShapeEntry } from 'canvas/NodeShape';\nimport { nodeMemo } from 'core/scene/nodeMemo';\nimport type { RectPose } from 'core/scene/types';\nimport { textCommandFromPose } from 'features/text/textCommand';\nimport { PAINT_SLOT } from './memo';\nimport { inkReach, resolveNodeStroke } from './nodePaint';\nimport { paintsPose } from './poseBox';\n\n// ─── Built-in painters ─────────────────────────────────────────────────\n\n/** The `data` a `kit:text` node carries. */\nexport interface TextNodeData {\n text: string;\n style?: TextStyle;\n runs?: readonly StyledRun[];\n fill?: FillStyle | null;\n stroke?: Stroke | null;\n verticalAlign?: TextVerticalAlign;\n}\n\n/** A `kit:text` node as the `TextPose` every text consumer reads. The stroke\n * goes through the same resolver every other node kind's does, so one\n * carrying no paint is dropped here rather than throwing in the renderer. */\nexport function textPoseOf(d: TextNodeData, p: RectPose): TextPose {\n return {\n x: p.x, y: p.y, width: p.width, height: p.height,\n text: d.text,\n runs: d.runs as StyledRun[] | undefined,\n style: d.style,\n fill: d.fill,\n stroke: resolveNodeStroke(d.stroke) ?? undefined,\n verticalAlign: d.verticalAlign,\n };\n}\n\nexport const TEXT_PAINTER: NodeShapeEntry<unknown, RectPose> = {\n id: 'kit:text',\n matches: (node) => {\n if (!paintsPose(node.pose)) return false;\n const d = node.data as { text?: string } | null;\n return d?.text != null;\n },\n // Memoized, and not for its own sake — `resolveTextStyle` + `resolveRuns`\n // are cheap (0.14 ms/frame at 1000 text nodes). It is the enabler: the\n // renderer's layout cache keys on the `ResolvedRun[]` array identity, and\n // `layoutRuns` costs 25.9 ms/frame for 200 wrapped paragraphs. Handing back\n // a fresh runs array per frame would leave that cache missing on every\n // draw, exactly as a fresh `Path` per frame defeated the mesh cache. Both\n // resolvers are pure style merging — no font reads — so `(data, pose)` is\n // the whole key. See PAINT_SLOT.\n //\n // `y` is the top of the first line box, not a baseline — see\n // `TextDrawCommand.y`. Wrap, alignment and run resolution are\n // `textCommandFromPose`'s, which `createTextLayer`, picking, the caret and\n // the edit overlay all share.\n paint: (node, pose) => nodeMemo(node, PAINT_SLOT, pose, () => [\n textCommandFromPose(textPoseOf(node.data as TextNodeData, pose)),\n ]),\n // The pose is a layout box, not a bounding box — \"Away\" in a 300-unit box\n // leaves most of it empty, and a pose-rect silhouette claims all of it. The\n // union of the line boxes is what the node actually covers, so picking,\n // lasso and clipping stop grabbing blank space.\n //\n // `null` rather than an empty path when there are no non-blank lines: an\n // empty text node would otherwise become unpickable, and a caller reading\n // \"no silhouette\" falls back to the pose rect, which is the behavior an\n // empty box wants.\n silhouette: (node, pose) => {\n const boxes = textLineBoxes(textPoseOf(node.data as TextNodeData, pose));\n if (boxes.length === 0) return null;\n return rectsToPath(boxes);\n },\n // `filled` is unconditional, `data.fill: null` included: the silhouette\n // above is line boxes, not glyph ink, so reporting outline-only text as\n // unfilled would leave it grabbable within a stroke width of a box edge and\n // nowhere near the letters. The reach still matters — a heavily outlined\n // glyph was unpickable across the width of its own outline.\n ink: (node, _pose, ctx) => {\n const d = node.data as { stroke?: Stroke | null };\n return { filled: true, ...inkReach(resolveNodeStroke(d.stroke), ctx?.scale) };\n },\n};\n\n/**\n * Union of axis-aligned rects as one multi-contour `PolygonPath`.\n *\n * Every contour winds the same way, so `'nonzero'` reads overlapping rects as\n * covered rather than punching a hole where two lines happen to overlap —\n * which they do the moment `lineHeight` drops below 1.\n */\nexport function rectsToPath(rects: readonly { x: number; y: number; width: number; height: number }[]): PolygonPath {\n const commands = new Uint8Array(rects.length * 6);\n const coords = new Float32Array(rects.length * 10);\n let ci = 0;\n let cmd = 0;\n for (const r of rects) {\n const { x, y, width: w, height: h } = r;\n commands[cmd++] = PATH_M; coords[ci++] = x; coords[ci++] = y;\n commands[cmd++] = PATH_L; coords[ci++] = x + w; coords[ci++] = y;\n commands[cmd++] = PATH_L; coords[ci++] = x + w; coords[ci++] = y + h;\n commands[cmd++] = PATH_L; coords[ci++] = x; coords[ci++] = y + h;\n commands[cmd++] = PATH_L; coords[ci++] = x; coords[ci++] = y;\n commands[cmd++] = PATH_Z;\n }\n return { kind: 'polygon', commands, coords, fillRule: 'nonzero' };\n}\n"],"mappings":";;;;;;;;AAgCA,SAAgBA,EAAW,GAAiB,GAAuB;CACjE,OAAO;EACL,GAAGC,EAAE;EAAG,GAAGA,EAAE;EAAG,OAAOA,EAAE;EAAO,QAAQA,EAAE;EAC1C,MAAMC,EAAE;EACR,MAAMA,EAAE;EACR,OAAOA,EAAE;EACT,MAAMA,EAAE;EACR,QAAQC,EAAkBD,EAAE,MAAM,KAAK,KAAA;EACvC,eAAeA,EAAE;CACnB;AACF;AAEA,IAAaE,IAAkD;CAC7D,IAAI;CACJ,UAAU,MACHC,EAAWC,EAAK,IAAI,IACfA,EAAK,MACL,QAAQ,OAFiB;CAiBrC,QAAQ,GAAM,MAASC,EAASD,GAAME,GAAYC,SAAY,CAC5DC,EAAoBV,EAAWM,EAAK,MAAsBG,CAAI,CAAC,CACjE,CAAC;CAUD,aAAa,GAAM,MAAS;EAC1B,IAAME,IAAQC,EAAcZ,EAAWM,EAAK,MAAsBG,CAAI,CAAC;EAEvE,OADIE,EAAM,WAAW,IAAU,OACxBE,EAAYF,CAAK;CAC1B;CAMA,MAAM,GAAM,GAAO,MAAQ;EACzB,IAAMT,IAAII,EAAK;EACf,OAAO;GAAE,QAAQ;GAAM,GAAGQ,EAASX,EAAkBD,EAAE,MAAM,GAAGa,GAAK,KAAK;EAAE;CAC9E;AACF;AASA,SAAgBF,EAAY,GAAwF;CAClH,IAAMG,IAAW,IAAI,WAAWC,EAAM,SAAS,CAAC,GAC1CC,IAAS,IAAI,aAAaD,EAAM,SAAS,EAAE,GAC7CE,IAAK,GACLC,IAAM;CACV,KAAK,IAAMC,KAAKJ,GAAO;EACrB,IAAM,EAAE,MAAG,MAAG,OAAOK,GAAG,QAAQC,MAAMF;EAMtC,AALA,EAAS,OAASG,GAAQ,EAAO,OAAQC,GAAG,EAAO,OAAQC,GAC3D,EAAS,OAASC,GAAQ,EAAO,OAAQF,IAAIH,GAAG,EAAO,OAAQI,GAC/D,EAAS,OAASC,GAAQ,EAAO,OAAQF,IAAIH,GAAG,EAAO,OAAQI,IAAIH,GACnE,EAAS,OAASI,GAAQ,EAAO,OAAQF,GAAG,EAAO,OAAQC,IAAIH,GAC/D,EAAS,OAASI,GAAQ,EAAO,OAAQF,GAAG,EAAO,OAAQC,GAC3D,EAAS,OAASE;CACpB;CACA,OAAO;EAAE,MAAM;EAAW;EAAU;EAAQ,UAAU;CAAU;AAClE"}
@@ -1 +1 @@
1
- {"version":3,"file":"overlayRoleStrokes.js","names":["OVERLAY_ROLE_STROKES"],"sources":["../../src/canvas/overlayRoleStrokes.ts"],"sourcesContent":["import type { Stroke } from '@weasel-js/paint';\n\n/** How each `polyline` overlay role reads. An action publishes the run and\n * the word; this table is the whole of the paint, for the dispatcher overlay\n * and for any tool previewing the same kind of run between gestures. */\nexport const OVERLAY_ROLE_STROKES: Readonly<Record<string, Stroke>> = {\n cut: { paint: { color: '#e23b3b' }, width: 1, dash: [6, 4] },\n connector: { paint: { color: '#7ba7c7' }, width: 2, dash: [4, 4] },\n};\n"],"mappings":";AAKA,IAAaA,IAAyD;CACpE,KAAK;EAAE,OAAO,EAAE,OAAO,UAAU;EAAG,OAAO;EAAG,MAAM,CAAC,GAAG,CAAC;CAAE;CAC3D,WAAW;EAAE,OAAO,EAAE,OAAO,UAAU;EAAG,OAAO;EAAG,MAAM,CAAC,GAAG,CAAC;CAAE;AACnE"}
1
+ {"version":3,"file":"overlayRoleStrokes.js","names":["OVERLAY_ROLE_STROKES"],"sources":["../../src/canvas/overlayRoleStrokes.ts"],"sourcesContent":["import type { CommandFill, CommandStroke } from '@weasel-js/paint';\n\n/** How each `polyline` overlay role reads. An action publishes the run and\n * the word; this table is the whole of the paint, for the dispatcher overlay\n * and for any tool previewing the same kind of run between gestures. */\nexport const OVERLAY_ROLE_STROKES: Readonly<Record<string, CommandStroke & { paint: CommandFill }>> = {\n cut: { paint: { color: '#e23b3b' }, width: 1, dash: [6, 4] },\n connector: { paint: { color: '#7ba7c7' }, width: 2, dash: [4, 4] },\n};\n"],"mappings":";AAKA,IAAaA,IAAyF;CACpG,KAAK;EAAE,OAAO,EAAE,OAAO,UAAU;EAAG,OAAO;EAAG,MAAM,CAAC,GAAG,CAAC;CAAE;CAC3D,WAAW;EAAE,OAAO,EAAE,OAAO,UAAU;EAAG,OAAO;EAAG,MAAM,CAAC,GAAG,CAAC;CAAE;AACnE"}
@@ -1,20 +1,19 @@
1
1
  import { mat3 as e } from "../renderer/math/mat3.js";
2
2
  import { viewToMat3 as t } from "../renderer/math/viewToMat3.js";
3
3
  import { boundsMissRect as n } from "../renderer/cullDrawCommands.js";
4
- import { poseRotationOf as r } from "../core/geometry/poseRotation.js";
5
- import { rotationMatrixAbout as i } from "./poseRotation.js";
4
+ import { poseFrameOf as r } from "../core/geometry/poseFrame.js";
6
5
  //#region src/canvas/paintCull.ts
7
- function a(a, o, s) {
8
- let c = o, l = t(o);
9
- return (u, d, f = o) => {
10
- f !== c && (c = f, l = t(f));
11
- let p = a(u, d, f);
12
- if (!p) return !1;
13
- let m = r(d), h = m ? e.multiply(l, i(m.cx, m.cy, m.rotation)) : l;
14
- return n(p, h, s);
6
+ function i(i, a, o) {
7
+ let s = a, c = t(a);
8
+ return (l, u, d = a) => {
9
+ d !== s && (s = d, c = t(d));
10
+ let f = i(l, u, d);
11
+ if (!f) return !1;
12
+ let p = r(u), m = p ? e.multiply(c, e.fromAffine(p)) : c;
13
+ return n(f, m, o);
15
14
  };
16
15
  }
17
16
  //#endregion
18
- export { a as paintMissesView };
17
+ export { i as paintMissesView };
19
18
 
20
19
  //# sourceMappingURL=paintCull.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"paintCull.js","names":["paintMissesView","last","view","toScreen","viewToMat3","layerView","b","paintBounds","node","pose","r","poseRotationOf","m","mat3","rotationMatrixAbout","boundsMissRect","rect"],"sources":["../../src/canvas/paintCull.ts"],"sourcesContent":["import type { View } from 'core/viewport/view';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { poseRotationOf } from 'core/geometry/poseRotation';\nimport { boundsMissRect, type CullRect } from '../renderer/cullDrawCommands';\nimport { mat3, type GlMat3 } from '../renderer/math/mat3';\nimport { viewToMat3 } from '../renderer/math/viewToMat3';\nimport { rotationMatrixAbout } from './poseRotation';\n\n/** Where a node's paint can reach, before its pose rotation — the scene\n * slot's `paintBounds`. `null` means unknown, and the node is painted. */\nexport type PaintBoundsFn<TNode, TPose> = (node: TNode, pose: TPose, view: View) => Bounds | null;\n\n/**\n * A predicate true for the nodes whose paint cannot reach `rect` (screen\n * pixels) under `view`, by `paintBounds` taken through the pose rotation\n * `wrapNodeOutput` applies and then the view. A node `paintBounds` cannot\n * bound is never culled.\n */\nexport function paintMissesView<TNode, TPose>(\n paintBounds: PaintBoundsFn<TNode, TPose>,\n view: View,\n rect: CullRect,\n): (node: TNode, pose: TPose, layerView?: View) => boolean {\n // `layerView` is a parallax plane's own view; planes are few, so one slot\n // of memo covers a walk that meets them layer by layer.\n let last = view;\n let toScreen = viewToMat3(view);\n return (node, pose, layerView = view) => {\n if (layerView !== last) { last = layerView; toScreen = viewToMat3(layerView); }\n const b = paintBounds(node, pose, layerView);\n if (!b) return false;\n const r = poseRotationOf(pose);\n const m = r ? mat3.multiply(toScreen, rotationMatrixAbout(r.cx, r.cy, r.rotation) as GlMat3) : toScreen;\n return boundsMissRect(b, m, rect);\n };\n}\n"],"mappings":";;;;;;AAkBA,SAAgBA,EACd,GACA,GACA,GACyD;CAGzD,IAAIC,IAAOC,GACPC,IAAWC,EAAWF,CAAI;CAC9B,QAAQ,GAAM,GAAM,IAAYA,MAAS;EACvC,AAAIG,MAAcJ,MAAQ,IAAOI,GAAW,IAAWD,EAAWC,CAAS;EAC3E,IAAMC,IAAIC,EAAYC,GAAMC,GAAMJ,CAAS;EAC3C,IAAI,CAACC,GAAG,OAAO;EACf,IAAMI,IAAIC,EAAeF,CAAI,GACvBG,IAAIF,IAAIG,EAAK,SAASV,GAAUW,EAAoBJ,EAAE,IAAIA,EAAE,IAAIA,EAAE,QAAQ,CAAW,IAAIP;EAC/F,OAAOY,EAAeT,GAAGM,GAAGI,CAAI;CAClC;AACF"}
1
+ {"version":3,"file":"paintCull.js","names":["paintMissesView","last","view","toScreen","viewToMat3","layerView","b","paintBounds","node","pose","frame","poseFrameOf","mat3","boundsMissRect","rect"],"sources":["../../src/canvas/paintCull.ts"],"sourcesContent":["import type { View } from 'core/viewport/view';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { poseFrameOf } from 'core/geometry/poseFrame';\nimport { boundsMissRect, type CullRect } from '../renderer/cullDrawCommands';\nimport { mat3 } from '../renderer/math/mat3';\nimport { viewToMat3 } from '../renderer/math/viewToMat3';\n\n/** Where a node's paint can reach, before its pose frame — the scene\n * slot's `paintBounds`. `null` means unknown, and the node is painted. */\nexport type PaintBoundsFn<TNode, TPose> = (node: TNode, pose: TPose, view: View) => Bounds | null;\n\n/**\n * A predicate true for the nodes whose paint cannot reach `rect` (screen\n * pixels) under `view`, by `paintBounds` taken through the pose frame\n * (`poseFrameOf`) `wrapNodeOutput` applies and then the view. A node `paintBounds` cannot\n * bound is never culled.\n */\nexport function paintMissesView<TNode, TPose>(\n paintBounds: PaintBoundsFn<TNode, TPose>,\n view: View,\n rect: CullRect,\n): (node: TNode, pose: TPose, layerView?: View) => boolean {\n // `layerView` is a parallax plane's own view; planes are few, so one slot\n // of memo covers a walk that meets them layer by layer.\n let last = view;\n let toScreen = viewToMat3(view);\n return (node, pose, layerView = view) => {\n if (layerView !== last) { last = layerView; toScreen = viewToMat3(layerView); }\n const b = paintBounds(node, pose, layerView);\n if (!b) return false;\n const frame = poseFrameOf(pose);\n const m = frame ? mat3.multiply(toScreen, mat3.fromAffine(frame)) : toScreen;\n return boundsMissRect(b, m, rect);\n };\n}\n"],"mappings":";;;;;AAiBA,SAAgBA,EACd,GACA,GACA,GACyD;CAGzD,IAAIC,IAAOC,GACPC,IAAWC,EAAWF,CAAI;CAC9B,QAAQ,GAAM,GAAM,IAAYA,MAAS;EACvC,AAAIG,MAAcJ,MAAQ,IAAOI,GAAW,IAAWD,EAAWC,CAAS;EAC3E,IAAMC,IAAIC,EAAYC,GAAMC,GAAMJ,CAAS;EAC3C,IAAI,CAACC,GAAG,OAAO;EACf,IAAMI,IAAQC,EAAYF,CAAI,GACxB,IAAIC,IAAQE,EAAK,SAAST,GAAUS,EAAK,WAAWF,CAAK,CAAC,IAAIP;EACpE,OAAOU,EAAeP,GAAG,GAAGQ,CAAI;CAClC;AACF"}