@weasel-js/core 1.9.2 → 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 +393 -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 +146 -92
  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 +11010 -7700
  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 +13 -2
  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 -47
  542. package/dist/tools/prefs.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"gradFill.js","names":["GRAD_VERT_SRC","GRAD_PAINT_GLSL","GRAD_FRAG_SRC","GRAD_FILL_UNIFORMS","GRAD_FILL_ATTRIBUTES"],"sources":["../../../src/renderer/shaders/gradFill.ts"],"sourcesContent":["/**\n * GLSL ES 3.0 sources for gradient-fill paths (linear, radial, conic).\n *\n * Three gradient kinds via u_gradKind (0=linear, 1=radial, 2=conic).\n * The branch value is uniform across all fragments in one draw call — GPU\n * branch predictor handles uniform-value branches without warp divergence.\n *\n * Output convention §2: PREMULTIPLIED alpha.\n *\n * `u_ramp` is `GradientRampAtlas`'s texture, which holds every baked ramp in\n * the frame, one per row; `u_rampV` picks this fill's row.\n *\n * Step-4 limitation: u_worldInv is identity in v1 since draw.ts doesn't yet\n * receive a view matrix. Gradient coords therefore render in screen space.\n * Step 7 (port createPathLayer) wires the actual view-inverse through layers.\n */\n\nexport const GRAD_VERT_SRC = /* glsl */ `#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform mat3 u_worldInv;\nout vec2 v_world;\nvoid main() {\n vec3 screen = u_model * vec3(a_position, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vec3 world = u_worldInv * vec3(screen.xy, 1.0);\n v_world = world.xy;\n}\n`;\n\n/**\n * The gradient's color at a gradient-space point, premultiplied — the whole\n * of the fragment stage but the point it is asked about, so the glyph program\n * can mask the same paint the path program draws.\n */\nexport const GRAD_PAINT_GLSL = /* glsl */ `\nuniform sampler2D u_ramp;\nuniform float u_rampV;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nuniform float u_opacity;\nuniform int u_gradKind;\nuniform vec2 u_gradP0;\nuniform vec2 u_gradDir;\nuniform float u_gradLen;\nuniform float u_gradRadius;\nuniform float u_gradAngle;\n\nconst float PI = 3.14159265358979323846;\n\nvec4 shadePaint(vec2 world) {\n float t;\n if (u_gradKind == 0) {\n vec2 d = world - u_gradP0;\n t = dot(d, u_gradDir) / max(u_gradLen, 0.0001);\n } else if (u_gradKind == 1) {\n t = length(world - u_gradP0) / max(u_gradRadius, 0.0001);\n } else {\n float a = atan(world.y - u_gradP0.y, world.x - u_gradP0.x) - u_gradAngle;\n t = fract(a / (2.0 * PI));\n }\n t = clamp(t, 0.0, 1.0);\n vec4 rampColor = texture(u_ramp, vec2(t, u_rampV));\n // Fill opacity into the alpha channel before the matrix, which is where the\n // batch program's vertex alpha sits. The two have to agree, since a linear\n // gradient goes through that one and a radial through this.\n vec4 src = vec4(rampColor.rgb, rampColor.a * u_opacity);\n vec4 mapped = clamp(u_colorMatrix * src + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n return vec4(mapped.rgb * a, a);\n}\n`;\n\nexport const GRAD_FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nin vec2 v_world;\n${GRAD_PAINT_GLSL}\nout vec4 outColor;\nvoid main() {\n outColor = shadePaint(v_world);\n}\n`;\n\nexport const GRAD_FILL_UNIFORMS = [\n 'u_proj', 'u_model', 'u_worldInv', 'u_ramp', 'u_rampV',\n 'u_alpha', 'u_opacity', 'u_colorMatrix', 'u_colorBias',\n 'u_gradKind', 'u_gradP0', 'u_gradDir', 'u_gradLen', 'u_gradRadius', 'u_gradAngle',\n] as const;\n\nexport const GRAD_FILL_ATTRIBUTES = ['a_position'] as const;\n"],"mappings":";AAiBA,IAAaA,IAA2B,6WAoB3BC,IAA6B,uuCAuC7BC,IAA2B;;;EAGtCD,EAAgB;;;;;GAOLE,IAAqB;CAChC;CAAU;CAAW;CAAc;CAAU;CAC7C;CAAW;CAAa;CAAiB;CACzC;CAAc;CAAY;CAAa;CAAa;CAAgB;AACtE,GAEaC,IAAuB,CAAC,YAAY"}
1
+ {"version":3,"file":"gradFill.js","names":["GRAD_VERT_SRC","GRAD_PAINT_GLSL","GRAD_FRAG_SRC","GRAD_FILL_UNIFORMS","GRAD_FILL_ATTRIBUTES"],"sources":["../../../src/renderer/shaders/gradFill.ts"],"sourcesContent":["/**\n * GLSL ES 3.0 sources for gradient-fill paths (linear, radial, conic).\n *\n * Three gradient kinds via u_gradKind (0=linear, 1=radial, 2=conic).\n * The branch value is uniform across all fragments in one draw call — GPU\n * branch predictor handles uniform-value branches without warp divergence.\n *\n * Output convention §2: PREMULTIPLIED alpha.\n *\n * `u_ramp` is `GradientRampAtlas`'s texture, which holds every baked ramp in\n * the frame, one per row; `u_rampV` picks this fill's row.\n */\n\nexport const GRAD_VERT_SRC = /* glsl */ `#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform vec2 u_origin;\nuniform mat3 u_worldInv;\nout vec2 v_world;\nvoid main() {\n vec3 screen = u_model * vec3(a_position - u_origin, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vec3 world = u_worldInv * vec3(screen.xy, 1.0);\n v_world = world.xy;\n}\n`;\n\n/**\n * The gradient's color at a gradient-space point, premultiplied — the whole\n * of the fragment stage but the point it is asked about, so the glyph program\n * can mask the same paint the path program draws.\n */\nexport const GRAD_PAINT_GLSL = /* glsl */ `\nuniform sampler2D u_ramp;\nuniform float u_rampV;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nuniform float u_opacity;\nuniform int u_gradKind;\nuniform vec2 u_gradP0;\nuniform vec2 u_gradDir;\nuniform float u_gradLen;\nuniform float u_gradRadius;\nuniform float u_gradAngle;\n\nconst float PI = 3.14159265358979323846;\n\nvec4 shadePaint(vec2 world) {\n float t;\n if (u_gradKind == 0) {\n vec2 d = world - u_gradP0;\n t = dot(d, u_gradDir) / max(u_gradLen, 0.0001);\n } else if (u_gradKind == 1) {\n t = length(world - u_gradP0) / max(u_gradRadius, 0.0001);\n } else {\n float a = atan(world.y - u_gradP0.y, world.x - u_gradP0.x) - u_gradAngle;\n t = fract(a / (2.0 * PI));\n }\n t = clamp(t, 0.0, 1.0);\n vec4 rampColor = texture(u_ramp, vec2(t, u_rampV));\n // Fill opacity into the alpha channel before the matrix, which is where the\n // batch program's vertex alpha sits. The two have to agree, since a linear\n // gradient goes through that one and a radial through this.\n vec4 src = vec4(rampColor.rgb, rampColor.a * u_opacity);\n vec4 mapped = clamp(u_colorMatrix * src + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n return vec4(mapped.rgb * a, a);\n}\n`;\n\nexport const GRAD_FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nin vec2 v_world;\n${GRAD_PAINT_GLSL}\nout vec4 outColor;\nvoid main() {\n outColor = shadePaint(v_world);\n}\n`;\n\nexport const GRAD_FILL_UNIFORMS = [\n 'u_proj', 'u_model', 'u_origin', 'u_worldInv', 'u_ramp', 'u_rampV',\n 'u_alpha', 'u_opacity', 'u_colorMatrix', 'u_colorBias',\n 'u_gradKind', 'u_gradP0', 'u_gradDir', 'u_gradLen', 'u_gradRadius', 'u_gradAngle',\n] as const;\n\nexport const GRAD_FILL_ATTRIBUTES = ['a_position'] as const;\n"],"mappings":";AAaA,IAAaA,IAA2B,gZAqB3BC,IAA6B,uuCAuC7BC,IAA2B;;;EAGtCD,EAAgB;;;;;GAOLE,IAAqB;CAChC;CAAU;CAAW;CAAY;CAAc;CAAU;CACzD;CAAW;CAAa;CAAiB;CACzC;CAAc;CAAY;CAAa;CAAa;CAAgB;AACtE,GAEaC,IAAuB,CAAC,YAAY"}
@@ -1,7 +1,8 @@
1
1
  //#region src/renderer/shaders/pathFill.ts
2
- var e = "#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nvoid main() {\n vec3 screen = u_model * vec3(a_position, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n}\n", t = "#version 300 es\nprecision highp float;\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\nvoid main() {\n vec4 mapped = clamp(u_colorMatrix * u_color + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n outColor = vec4(mapped.rgb * a, a);\n}\n", n = "#version 300 es\nin vec2 a_position;\nin vec4 a_vertexColor;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nout vec4 v_vertexColor;\nvoid main() {\n vec3 screen = u_model * vec3(a_position, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n v_vertexColor = a_vertexColor;\n}\n", r = "#version 300 es\nprecision highp float;\nin vec4 v_vertexColor;\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\nvoid main() {\n vec4 src = u_color * v_vertexColor;\n vec4 mapped = clamp(u_colorMatrix * src + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n outColor = vec4(mapped.rgb * a, a);\n}\n", i = [
2
+ var e = "#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform vec2 u_origin;\nvoid main() {\n vec3 screen = u_model * vec3(a_position - u_origin, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n}\n", t = "#version 300 es\nprecision highp float;\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\nvoid main() {\n vec4 mapped = clamp(u_colorMatrix * u_color + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n outColor = vec4(mapped.rgb * a, a);\n}\n", n = "#version 300 es\nin vec2 a_position;\nin vec4 a_vertexColor;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform vec2 u_origin;\nout vec4 v_vertexColor;\nvoid main() {\n vec3 screen = u_model * vec3(a_position - u_origin, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n v_vertexColor = a_vertexColor;\n}\n", r = "#version 300 es\nprecision highp float;\nin vec4 v_vertexColor;\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\nvoid main() {\n vec4 src = u_color * v_vertexColor;\n vec4 mapped = clamp(u_colorMatrix * src + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n outColor = vec4(mapped.rgb * a, a);\n}\n", i = [
3
3
  "u_proj",
4
4
  "u_model",
5
+ "u_origin",
5
6
  "u_color",
6
7
  "u_alpha",
7
8
  "u_colorMatrix",
@@ -1 +1 @@
1
- {"version":3,"file":"pathFill.js","names":["VERT_SRC","FRAG_SRC","VCOLOR_VERT_SRC","VCOLOR_FRAG_SRC","PATH_FILL_UNIFORMS","PATH_FILL_ATTRIBUTES","PATH_FILL_VCOLOR_ATTRIBUTES"],"sources":["../../../src/renderer/shaders/pathFill.ts"],"sourcesContent":["/**\n * GLSL ES 3.0 sources for the built-in solid-fill path shader.\n *\n * Two variants:\n * - Flat: VERT_SRC + FRAG_SRC, uses uniform color only.\n * - VColor: VCOLOR_VERT_SRC + VCOLOR_FRAG_SRC, multiplies a per-vertex\n * `a_vertexColor` attribute with `u_color`.\n *\n * Both variants take `u_colorMatrix` (mat4) + `u_colorBias` (vec4); the\n * color transform is applied to the straight-alpha SRC color BEFORE\n * premultiplication. Identity matrix + zero bias = pass-through.\n *\n * Output (both variants): PREMULTIPLIED alpha.\n * Blend: caller sets `gl.blendFunc(ONE, ONE_MINUS_SRC_ALPHA)`.\n */\n\nexport const VERT_SRC = /* glsl */ `#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nvoid main() {\n vec3 screen = u_model * vec3(a_position, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n}\n`;\n\nexport const FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\nvoid main() {\n vec4 mapped = clamp(u_colorMatrix * u_color + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n outColor = vec4(mapped.rgb * a, a);\n}\n`;\n\nexport const VCOLOR_VERT_SRC = /* glsl */ `#version 300 es\nin vec2 a_position;\nin vec4 a_vertexColor;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nout vec4 v_vertexColor;\nvoid main() {\n vec3 screen = u_model * vec3(a_position, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n v_vertexColor = a_vertexColor;\n}\n`;\n\nexport const VCOLOR_FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nin vec4 v_vertexColor;\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\nvoid main() {\n vec4 src = u_color * v_vertexColor;\n vec4 mapped = clamp(u_colorMatrix * src + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n outColor = vec4(mapped.rgb * a, a);\n}\n`;\n\n/** Uniforms shared between flat and vertex-color variants. */\nexport const PATH_FILL_UNIFORMS = [\n 'u_proj', 'u_model', 'u_color', 'u_alpha',\n 'u_colorMatrix', 'u_colorBias',\n] as const;\n\n/** Attributes for the flat variant. */\nexport const PATH_FILL_ATTRIBUTES = ['a_position'] as const;\n\n/** Attributes for the vertex-color variant. */\nexport const PATH_FILL_VCOLOR_ATTRIBUTES = ['a_position', 'a_vertexColor'] as const;\n"],"mappings":";AAgBA,IAAaA,IAAsB,mPAWtBC,IAAsB,2UActBC,IAA6B,sUAc7BC,IAA6B,sYAiB7BC,IAAqB;CAChC;CAAU;CAAW;CAAW;CAChC;CAAiB;AACnB,GAGaC,IAAuB,CAAC,YAAY,GAGpCC,IAA8B,CAAC,cAAc,eAAe"}
1
+ {"version":3,"file":"pathFill.js","names":["VERT_SRC","FRAG_SRC","VCOLOR_VERT_SRC","VCOLOR_FRAG_SRC","PATH_FILL_UNIFORMS","PATH_FILL_ATTRIBUTES","PATH_FILL_VCOLOR_ATTRIBUTES"],"sources":["../../../src/renderer/shaders/pathFill.ts"],"sourcesContent":["/**\n * GLSL ES 3.0 sources for the built-in solid-fill path shader.\n *\n * Two variants:\n * - Flat: VERT_SRC + FRAG_SRC, uses uniform color only.\n * - VColor: VCOLOR_VERT_SRC + VCOLOR_FRAG_SRC, multiplies a per-vertex\n * `a_vertexColor` attribute with `u_color`.\n *\n * Both variants take `u_colorMatrix` (mat4) + `u_colorBias` (vec4); the\n * color transform is applied to the straight-alpha SRC color BEFORE\n * premultiplication. Identity matrix + zero bias = pass-through.\n *\n * Output (both variants): PREMULTIPLIED alpha.\n * Blend: caller sets `gl.blendFunc(ONE, ONE_MINUS_SRC_ALPHA)`.\n */\n\nexport const VERT_SRC = /* glsl */ `#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform vec2 u_origin;\nvoid main() {\n vec3 screen = u_model * vec3(a_position - u_origin, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n}\n`;\n\nexport const FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\nvoid main() {\n vec4 mapped = clamp(u_colorMatrix * u_color + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n outColor = vec4(mapped.rgb * a, a);\n}\n`;\n\nexport const VCOLOR_VERT_SRC = /* glsl */ `#version 300 es\nin vec2 a_position;\nin vec4 a_vertexColor;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform vec2 u_origin;\nout vec4 v_vertexColor;\nvoid main() {\n vec3 screen = u_model * vec3(a_position - u_origin, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n v_vertexColor = a_vertexColor;\n}\n`;\n\nexport const VCOLOR_FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nin vec4 v_vertexColor;\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\nvoid main() {\n vec4 src = u_color * v_vertexColor;\n vec4 mapped = clamp(u_colorMatrix * src + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha;\n outColor = vec4(mapped.rgb * a, a);\n}\n`;\n\n/** Uniforms shared between flat and vertex-color variants. */\nexport const PATH_FILL_UNIFORMS = [\n 'u_proj', 'u_model', 'u_origin', 'u_color', 'u_alpha',\n 'u_colorMatrix', 'u_colorBias',\n] as const;\n\n/** Attributes for the flat variant. */\nexport const PATH_FILL_ATTRIBUTES = ['a_position'] as const;\n\n/** Attributes for the vertex-color variant. */\nexport const PATH_FILL_VCOLOR_ATTRIBUTES = ['a_position', 'a_vertexColor'] as const;\n"],"mappings":";AAgBA,IAAaA,IAAsB,sRAYtBC,IAAsB,2UActBC,IAA6B,yWAe7BC,IAA6B,sYAiB7BC,IAAqB;CAChC;CAAU;CAAW;CAAY;CAAW;CAC5C;CAAiB;AACnB,GAGaC,IAAuB,CAAC,YAAY,GAGpCC,IAA8B,CAAC,cAAc,eAAe"}
@@ -1,5 +1,5 @@
1
1
  //#region src/renderer/shaders/patternFill.ts
2
- var e = "#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform mat3 u_worldInv;\nout vec2 v_world;\nvoid main() {\n vec3 screen = u_model * vec3(a_position, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vec3 world = u_worldInv * vec3(screen.xy, 1.0);\n v_world = world.xy;\n}\n", t = "\nuniform sampler2D u_sampler;\nuniform vec2 u_tileSize;\nuniform float u_opacity;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nvec4 shadePaint(vec2 world) {\n vec2 uv = world / max(u_tileSize, vec2(0.0001));\n vec4 texel = texture(u_sampler, uv);\n vec4 mapped = clamp(u_colorMatrix * texel + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_opacity * u_alpha;\n return vec4(mapped.rgb * a, a);\n}\n", n = `#version 300 es
2
+ var e = "#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform vec2 u_origin;\nuniform mat3 u_worldInv;\nout vec2 v_world;\nvoid main() {\n vec3 screen = u_model * vec3(a_position - u_origin, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vec3 world = u_worldInv * vec3(screen.xy, 1.0);\n v_world = world.xy;\n}\n", t = "\nuniform sampler2D u_sampler;\nuniform vec2 u_tileSize;\nuniform float u_opacity;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nvec4 shadePaint(vec2 world) {\n vec2 uv = world / max(u_tileSize, vec2(0.0001));\n vec4 texel = texture(u_sampler, uv);\n vec4 mapped = clamp(u_colorMatrix * texel + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_opacity * u_alpha;\n return vec4(mapped.rgb * a, a);\n}\n", n = `#version 300 es
3
3
  precision highp float;
4
4
  in vec2 v_world;
5
5
  ${t}
@@ -10,6 +10,7 @@ void main() {
10
10
  `, r = [
11
11
  "u_proj",
12
12
  "u_model",
13
+ "u_origin",
13
14
  "u_worldInv",
14
15
  "u_sampler",
15
16
  "u_tileSize",
@@ -1 +1 @@
1
- {"version":3,"file":"patternFill.js","names":["PATTERN_VERT_SRC","PATTERN_PAINT_GLSL","PATTERN_FRAG_SRC","PATTERN_FILL_UNIFORMS","PATTERN_FILL_ATTRIBUTES"],"sources":["../../../src/renderer/shaders/patternFill.ts"],"sourcesContent":["/**\n * GLSL ES 3.0 sources for pattern-fill paths.\n *\n * The vertex stage is `gradFill`'s: a path fill mesh carries `a_position`\n * only, so tile-space coordinates are recovered per fragment from the\n * screen position via `u_worldInv` rather than read from a UV attribute.\n * That matrix also carries the tile's origin and transform\n * (`patternTileSpace`). `u_tileSize` then converts to texture space, and\n * `REPEAT` wrapping (set at upload) tiles the result.\n *\n * Output convention §2: PREMULTIPLIED alpha.\n */\n\nexport const PATTERN_VERT_SRC = /* glsl */ `#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform mat3 u_worldInv;\nout vec2 v_world;\nvoid main() {\n vec3 screen = u_model * vec3(a_position, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vec3 world = u_worldInv * vec3(screen.xy, 1.0);\n v_world = world.xy;\n}\n`;\n\n/**\n * The pattern's color at a paint-space point, premultiplied — the whole of the\n * fragment stage but the point it is asked about, so the glyph program can\n * mask the same paint the path program draws.\n */\nexport const PATTERN_PAINT_GLSL = /* glsl */ `\nuniform sampler2D u_sampler;\nuniform vec2 u_tileSize;\nuniform float u_opacity;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nvec4 shadePaint(vec2 world) {\n vec2 uv = world / max(u_tileSize, vec2(0.0001));\n vec4 texel = texture(u_sampler, uv);\n vec4 mapped = clamp(u_colorMatrix * texel + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_opacity * u_alpha;\n return vec4(mapped.rgb * a, a);\n}\n`;\n\nexport const PATTERN_FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nin vec2 v_world;\n${PATTERN_PAINT_GLSL}\nout vec4 outColor;\nvoid main() {\n outColor = shadePaint(v_world);\n}\n`;\n\nexport const PATTERN_FILL_UNIFORMS = [\n 'u_proj', 'u_model', 'u_worldInv', 'u_sampler',\n 'u_tileSize', 'u_opacity', 'u_alpha',\n 'u_colorMatrix', 'u_colorBias',\n] as const;\n\nexport const PATTERN_FILL_ATTRIBUTES = ['a_position'] as const;\n"],"mappings":";AAaA,IAAaA,IAA8B,6WAoB9BC,IAAgC,gcAgBhCC,IAA8B;;;EAGzCD,EAAmB;;;;;GAORE,IAAwB;CACnC;CAAU;CAAW;CAAc;CACnC;CAAc;CAAa;CAC3B;CAAiB;AACnB,GAEaC,IAA0B,CAAC,YAAY"}
1
+ {"version":3,"file":"patternFill.js","names":["PATTERN_VERT_SRC","PATTERN_PAINT_GLSL","PATTERN_FRAG_SRC","PATTERN_FILL_UNIFORMS","PATTERN_FILL_ATTRIBUTES"],"sources":["../../../src/renderer/shaders/patternFill.ts"],"sourcesContent":["/**\n * GLSL ES 3.0 sources for pattern-fill paths.\n *\n * The vertex stage is `gradFill`'s: a path fill mesh carries `a_position`\n * only, so tile-space coordinates are recovered per fragment from the\n * screen position via `u_worldInv` rather than read from a UV attribute.\n * That matrix also carries the tile's origin and transform\n * (`patternTileSpace`). `u_tileSize` then converts to texture space, and\n * `REPEAT` wrapping (set at upload) tiles the result.\n *\n * Output convention §2: PREMULTIPLIED alpha.\n */\n\nexport const PATTERN_VERT_SRC = /* glsl */ `#version 300 es\nin vec2 a_position;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nuniform vec2 u_origin;\nuniform mat3 u_worldInv;\nout vec2 v_world;\nvoid main() {\n vec3 screen = u_model * vec3(a_position - u_origin, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vec3 world = u_worldInv * vec3(screen.xy, 1.0);\n v_world = world.xy;\n}\n`;\n\n/**\n * The pattern's color at a paint-space point, premultiplied — the whole of the\n * fragment stage but the point it is asked about, so the glyph program can\n * mask the same paint the path program draws.\n */\nexport const PATTERN_PAINT_GLSL = /* glsl */ `\nuniform sampler2D u_sampler;\nuniform vec2 u_tileSize;\nuniform float u_opacity;\nuniform float u_alpha;\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nvec4 shadePaint(vec2 world) {\n vec2 uv = world / max(u_tileSize, vec2(0.0001));\n vec4 texel = texture(u_sampler, uv);\n vec4 mapped = clamp(u_colorMatrix * texel + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_opacity * u_alpha;\n return vec4(mapped.rgb * a, a);\n}\n`;\n\nexport const PATTERN_FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nin vec2 v_world;\n${PATTERN_PAINT_GLSL}\nout vec4 outColor;\nvoid main() {\n outColor = shadePaint(v_world);\n}\n`;\n\nexport const PATTERN_FILL_UNIFORMS = [\n 'u_proj', 'u_model', 'u_origin', 'u_worldInv', 'u_sampler',\n 'u_tileSize', 'u_opacity', 'u_alpha',\n 'u_colorMatrix', 'u_colorBias',\n] as const;\n\nexport const PATTERN_FILL_ATTRIBUTES = ['a_position'] as const;\n"],"mappings":";AAaA,IAAaA,IAA8B,gZAqB9BC,IAAgC,gcAgBhCC,IAA8B;;;EAGzCD,EAAmB;;;;;GAORE,IAAwB;CACnC;CAAU;CAAW;CAAY;CAAc;CAC/C;CAAc;CAAa;CAC3B;CAAiB;AACnB,GAEaC,IAA0B,CAAC,YAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"registerProgram.js","names":["registry","createReflectable","programSourceRegistry","getProgramSource","id","isDev","registerProgram"],"sources":["../../../src/renderer/shaders/registerProgram.ts"],"sourcesContent":["/**\n * registerProgram — public API for registering custom shader programs.\n *\n * Stores raw GLSL source strings in a module-level registry. GL compilation\n * happens on each WeaselRenderer via WeaselRenderer.registerProgram(), which\n * calls getProgramSource() and compiles the result. This keeps registerProgram\n * GL-context-agnostic — identical pattern to registerFont storing ImageBitmap.\n *\n * Module-level state = source strings only; compiled GL\n * programs live on each renderer's programRegistry (Map<id, ShaderProgram>).\n *\n * Lifecycle: program sources live for the module lifetime. No unregister in v1.\n */\n\nimport { createReflectable, type Reflection } from '@weasel-js/registry';\nimport { type TextureHandle } from '../textures/registerTexture';\n\nexport type { TextureHandle };\n\n/** Opaque handle to a compiled custom shader program. */\nexport interface ShaderProgramHandle {\n readonly id: string;\n}\n\n/**\n * A value for one uniform in `ShaderDrawCommand.uniforms`.\n *\n * | TS type | GL call |\n * |-------------------------|--------------------------------------|\n * | number | uniform1f |\n * | [n, n] | uniform2fv |\n * | [n, n, n] | uniform3fv |\n * | [n, n, n, n] | uniform4fv |\n * | Float32Array length 9 | uniformMatrix3fv (column-major) |\n * | Float32Array length 16 | uniformMatrix4fv (column-major) |\n * | TextureHandle | bind to next tex unit + uniform1i |\n *\n * **Array uniforms.** Keyed by an array's bare name (`u_ripples` for\n * `uniform vec3 u_ripples[8]`), a flat `number[]`, `Float32Array`,\n * `Int32Array` or `Uint32Array` fills the array from slot 0 in one\n * `uniform*v` call chosen by the declared element type (`vec3` →\n * `uniform3fv`, `ivec2` → `uniform2iv`, `mat4` → `uniformMatrix4fv`, …).\n * Its length must be a whole number of elements and at most the declared\n * size; a shorter value leaves the remaining slots as they were. Per-slot\n * keys (`u_ripples[2]`) keep working and take the table above.\n */\nexport type ShaderUniform =\n | number\n | [number, number]\n | [number, number, number]\n | [number, number, number, number]\n | readonly number[]\n | Float32Array\n | Int32Array\n | Uint32Array\n | TextureHandle;\n\n/** A registered program's GLSL source. An empty `vert` means the kit's default vertex shader. */\nexport interface ProgramSource {\n vert: string;\n frag: string;\n}\n\nconst registry = createReflectable<ProgramSource>();\n\n/** Every registered program's GLSL source, keyed by program id. */\nexport const programSourceRegistry: Reflection<ProgramSource> = registry.reflection;\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetProgramRegistryForTests(): void {\n registry.clear();\n}\n\nexport function getProgramSource(id: string): ProgramSource | null {\n return registry.get(id) ?? null;\n}\n\nconst isDev = (): boolean =>\n typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n\n/**\n * Register a custom shader program by id.\n *\n * Pass an empty string for `vert` to use the kit's default vertex shader\n * (recommended). The kit's vertex shader exposes `v_uv`, `v_screen`, and\n * `v_world` varyings plus `u_bounds` and `u_view` uniforms.\n *\n * **IMPORTANT — Premultiplied alpha:**\n * Your fragment shader MUST output premultiplied alpha:\n * `outColor = vec4(rgb * a, a);` ← correct\n * `outColor = vec4(rgb, a);` ← WRONG — over-brightens translucent regions\n *\n * The renderer uses `gl.blendFunc(ONE, ONE_MINUS_SRC_ALPHA)` to match.\n * Opaque fragments (a=1) are unaffected; only fragments with a < 1 differ.\n *\n * **Re-registration behavior:**\n * - Dev mode (`NODE_ENV !== 'production'`): calling with an existing id and new\n * source replaces it (hot reload). Every renderer that compiled the old source\n * recompiles on its next frame and deletes the program it replaces; a\n * `<Canvas shaders>` naming the id repaints to show it. If the new source fails\n * to compile, the renderer logs the error once and keeps drawing the old one.\n * - Prod mode: calling with an existing id throws.\n *\n * Actual GL compilation and `ShaderCompileError` throwing happen in\n * `WeaselRenderer.registerProgram()`, not here.\n *\n * @experimental API may break before v2.\n */\nexport function registerProgram(\n id: string,\n vert: string,\n frag: string,\n): ShaderProgramHandle {\n if (registry.has(id) && !isDev()) {\n throw new Error(`weasel registerProgram: duplicate program id \"${id}\". ` +\n `In production, re-registration is not allowed. Pass a unique id or call in dev mode.`);\n }\n registry.set(id, { vert, frag });\n return { id };\n}\n"],"mappings":";;AA+DA,IAAMA,IAAWC,EAAiC,GAGrCC,IAAmDF,EAAS;AAOzE,SAAgBG,EAAiB,GAAkC;CACjE,OAAOH,EAAS,IAAII,CAAE,KAAK;AAC7B;AAEA,IAAMC,UACJ,OAAO,UAAY,MAAA,QAAA,IAAA,aAAuC,eAAe;AA8B3E,SAAgBC,EACd,GACA,GACA,GACqB;CACrB,IAAIN,EAAS,IAAII,CAAE,KAAK,CAACC,EAAM,GAC7B,MAAU,MAAM,iDAAiDD,EAAG,wFACoB;CAG1F,OADAJ,EAAS,IAAII,GAAI;EAAE;EAAM;CAAK,CAAC,GACxB,EAAE,MAAG;AACd"}
1
+ {"version":3,"file":"registerProgram.js","names":["registry","createReflectable","programSourceRegistry","getProgramSource","id","isDev","registerProgram"],"sources":["../../../src/renderer/shaders/registerProgram.ts"],"sourcesContent":["/**\n * registerProgram — public API for registering custom shader programs.\n *\n * Stores raw GLSL source strings in a module-level registry. GL compilation\n * happens on each WeaselRenderer via WeaselRenderer.registerProgram(), which\n * calls getProgramSource() and compiles the result. This keeps registerProgram\n * GL-context-agnostic — identical pattern to registerFont storing ImageBitmap.\n *\n * Module-level state = source strings only; compiled GL\n * programs live on each renderer's programRegistry (Map<id, ShaderProgram>).\n *\n * Lifecycle: program sources live for the module lifetime. No unregister in v1.\n */\n\nimport { createReflectable, type Reflection } from '@weasel-js/registry';\nimport { type TextureHandle } from '../textures/registerTexture';\n\nexport type { TextureHandle };\n\n/** Opaque handle to a compiled custom shader program. */\nexport interface ShaderProgramHandle {\n readonly id: string;\n}\n\n/**\n * A value for one uniform in `ShaderDrawCommand.uniforms`.\n *\n * | TS type | GL call |\n * |-------------------------|--------------------------------------|\n * | number | uniform1f |\n * | [n, n] | uniform2fv |\n * | [n, n, n] | uniform3fv |\n * | [n, n, n, n] | uniform4fv |\n * | Float32Array length 9 | uniformMatrix3fv (column-major) |\n * | Float64Array | as the Float32Array of its values |\n * | Float32Array length 16 | uniformMatrix4fv (column-major) |\n * | TextureHandle | bind to next tex unit + uniform1i |\n *\n * **Array uniforms.** Keyed by an array's bare name (`u_ripples` for\n * `uniform vec3 u_ripples[8]`), a flat `number[]`, `Float32Array`,\n * `Int32Array` or `Uint32Array` fills the array from slot 0 in one\n * `uniform*v` call chosen by the declared element type (`vec3` →\n * `uniform3fv`, `ivec2` → `uniform2iv`, `mat4` → `uniformMatrix4fv`, …).\n * Its length must be a whole number of elements and at most the declared\n * size; a shorter value leaves the remaining slots as they were. Per-slot\n * keys (`u_ripples[2]`) keep working and take the table above.\n */\nexport type ShaderUniform =\n | number\n | [number, number]\n | [number, number, number]\n | [number, number, number, number]\n | readonly number[]\n | Float32Array\n | Float64Array\n | Int32Array\n | Uint32Array\n | TextureHandle;\n\n/** A registered program's GLSL source. An empty `vert` means the kit's default vertex shader. */\nexport interface ProgramSource {\n vert: string;\n frag: string;\n}\n\nconst registry = createReflectable<ProgramSource>();\n\n/** Every registered program's GLSL source, keyed by program id. */\nexport const programSourceRegistry: Reflection<ProgramSource> = registry.reflection;\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetProgramRegistryForTests(): void {\n registry.clear();\n}\n\nexport function getProgramSource(id: string): ProgramSource | null {\n return registry.get(id) ?? null;\n}\n\nconst isDev = (): boolean =>\n typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n\n/**\n * Register a custom shader program by id.\n *\n * Pass an empty string for `vert` to use the kit's default vertex shader\n * (recommended). The kit's vertex shader exposes `v_uv`, `v_screen`, and\n * `v_world` varyings plus `u_bounds` and `u_view` uniforms.\n *\n * **IMPORTANT — Premultiplied alpha:**\n * Your fragment shader MUST output premultiplied alpha:\n * `outColor = vec4(rgb * a, a);` ← correct\n * `outColor = vec4(rgb, a);` ← WRONG — over-brightens translucent regions\n *\n * The renderer uses `gl.blendFunc(ONE, ONE_MINUS_SRC_ALPHA)` to match.\n * Opaque fragments (a=1) are unaffected; only fragments with a < 1 differ.\n *\n * **Re-registration behavior:**\n * - Dev mode (`NODE_ENV !== 'production'`): calling with an existing id and new\n * source replaces it (hot reload). Every renderer that compiled the old source\n * recompiles on its next frame and deletes the program it replaces; a\n * `<Canvas shaders>` naming the id repaints to show it. If the new source fails\n * to compile, the renderer logs the error once and keeps drawing the old one.\n * - Prod mode: calling with an existing id throws.\n *\n * Actual GL compilation and `ShaderCompileError` throwing happen in\n * `WeaselRenderer.registerProgram()`, not here.\n *\n * @experimental API may break before v2.\n */\nexport function registerProgram(\n id: string,\n vert: string,\n frag: string,\n): ShaderProgramHandle {\n if (registry.has(id) && !isDev()) {\n throw new Error(`weasel registerProgram: duplicate program id \"${id}\". ` +\n `In production, re-registration is not allowed. Pass a unique id or call in dev mode.`);\n }\n registry.set(id, { vert, frag });\n return { id };\n}\n"],"mappings":";;AAiEA,IAAMA,IAAWC,EAAiC,GAGrCC,IAAmDF,EAAS;AAOzE,SAAgBG,EAAiB,GAAkC;CACjE,OAAOH,EAAS,IAAII,CAAE,KAAK;AAC7B;AAEA,IAAMC,UACJ,OAAO,UAAY,MAAA,QAAA,IAAA,aAAuC,eAAe;AA8B3E,SAAgBC,EACd,GACA,GACA,GACqB;CACrB,IAAIN,EAAS,IAAII,CAAE,KAAK,CAACC,EAAM,GAC7B,MAAU,MAAM,iDAAiDD,EAAG,wFACoB;CAG1F,OADAJ,EAAS,IAAII,GAAI;EAAE;EAAM;CAAK,CAAC,GACxB,EAAE,MAAG;AACd"}
@@ -1 +1 @@
1
- {"version":3,"file":"strokeLengths.js","names":["WORLD","resolveStrokeLengths","stroke","cmd","isPxMarker","markerStart","markerMid","markerEnd","resolved","strokeSpaceOf","transform","screen","metric","ribbon","pxPerUnit","quantizeStrokeScale","scale","resolveStrokeWidth","d","head","ref","spaces","resolvedMarker","resolveMarkerSize"],"sources":["../../src/renderer/strokeLengths.ts"],"sourcesContent":["import type { FillStyle, MarkerRef, Stroke } from '@weasel-js/paint';\nimport type { PathDrawCommand } from './DrawCommand';\nimport type { GlMat3 } from './math/mat3';\nimport { resolveStrokeWidth } from 'features/paths/tessellate/stroke';\nimport {\n strokeSpaceOf, type ScreenSpace, type StrokeSpaces,\n} from 'features/paths/tessellate/metric';\nimport { quantizeStrokeScale } from './cache/strokeMeshCache';\nimport { resolveMarkerSize } from '../core/markerInset';\n\n/** A path command whose stroke paints. */\nexport type StrokedPathCommand = PathDrawCommand & { stroke: Stroke & { paint: FillStyle } };\n\n/** A stroke command ready to tessellate, and the spaces to tessellate it in. */\nexport interface ResolvedStrokeCommand {\n cmd: StrokedPathCommand;\n /** Where the ribbon and each head are built; every length in `cmd` is\n * measured in the space of the part it belongs to. */\n spaces: StrokeSpaces;\n}\n\nconst WORLD: StrokeSpaces = {};\n\n/**\n * `cmd` with its `{ px }` lengths — the stroke width, any marker size, and on a\n * `{ px }` stroke its dashes — resolved against the accumulated transform's\n * quantized scale, so everything downstream (the ribbon cache key, the insets,\n * the heads) sees plain numbers.\n *\n * Under a transform that stretches one direction more than another, each\n * screen-sized part is also built in the transform's stretch, where lengths\n * measure as they do on screen, so it is exact across, down and on every\n * diagonal rather than right only on average. World-sized parts stay in world.\n */\nexport function resolveStrokeLengths(transform: GlMat3, cmd: StrokedPathCommand): ResolvedStrokeCommand {\n const stroke = cmd.stroke;\n const { markerStart, markerMid, markerEnd } = stroke;\n if (typeof stroke.width !== 'object' && !isPxMarker(markerStart)\n && !isPxMarker(markerMid) && !isPxMarker(markerEnd)) {\n return { cmd, spaces: WORLD };\n }\n const resolved: Stroke & { paint: FillStyle } = { ...stroke };\n const { scale, metric } = strokeSpaceOf(transform[0], transform[1], transform[3], transform[4]);\n const screen = (pxPerUnit: number): ScreenSpace | undefined =>\n metric === null ? undefined : { metric, pxPerUnit };\n let ribbon: ScreenSpace | undefined;\n if (typeof stroke.width === 'object') {\n const pxPerUnit = quantizeStrokeScale(stroke.width.px, scale);\n resolved.width = resolveStrokeWidth(stroke.width, pxPerUnit);\n if (stroke.dash && pxPerUnit > 0) resolved.dash = stroke.dash.map((d) => d / pxPerUnit);\n ribbon = screen(pxPerUnit);\n }\n const head = (ref: MarkerRef | undefined): ScreenSpace | undefined => {\n if (ref === undefined || typeof ref === 'string' || ref.size === undefined) return ribbon;\n if (typeof ref.size === 'number') return undefined;\n return screen(quantizeStrokeScale(ref.size.px, scale));\n };\n const spaces = { ribbon, start: head(markerStart), mid: head(markerMid), end: head(markerEnd) };\n if (isPxMarker(markerStart)) resolved.markerStart = resolvedMarker(markerStart, scale);\n if (isPxMarker(markerMid)) resolved.markerMid = resolvedMarker(markerMid, scale);\n if (isPxMarker(markerEnd)) resolved.markerEnd = resolvedMarker(markerEnd, scale);\n return { cmd: { ...cmd, stroke: resolved }, spaces };\n}\n\ntype PxMarker = Exclude<MarkerRef, string> & { size: { px: number } };\n\nfunction isPxMarker(ref: MarkerRef | undefined): ref is PxMarker {\n return typeof ref === 'object' && typeof ref.size === 'object';\n}\n\nfunction resolvedMarker(ref: PxMarker, scale: number): MarkerRef {\n return { ...ref, size: resolveMarkerSize(ref, 0, quantizeStrokeScale(ref.size.px, scale)) };\n}\n"],"mappings":";;;;;AAqBA,IAAMA,IAAsB,CAAC;AAa7B,SAAgBC,EAAqB,GAAmB,GAAgD;CACtG,IAAMC,IAASC,EAAI,QACb,EAAE,gBAAa,cAAW,iBAAcD;CAC9C,IAAI,OAAOA,EAAO,SAAU,YAAY,CAACE,EAAWC,CAAW,KAC1D,CAACD,EAAWE,CAAS,KAAK,CAACF,EAAWG,CAAS,GAClD,OAAO;EAAE;EAAK,QAAQP;CAAM;CAE9B,IAAMQ,IAA0C,EAAE,GAAGN,EAAO,GACtD,EAAE,UAAO,cAAWO,EAAcC,EAAU,IAAIA,EAAU,IAAIA,EAAU,IAAIA,EAAU,EAAE,GACxFC,KAAU,MACdC,MAAW,OAAO,KAAA,IAAY;EAAE;EAAQ;CAAU,GAChDC;CACJ,IAAI,OAAOX,EAAO,SAAU,UAAU;EACpC,IAAMY,IAAYC,EAAoBb,EAAO,MAAM,IAAIc,CAAK;EAG5D,AAFA,EAAS,QAAQC,EAAmBf,EAAO,OAAOY,CAAS,GACvDZ,EAAO,QAAQY,IAAY,MAAG,EAAS,OAAOZ,EAAO,KAAK,KAAK,MAAMgB,IAAIJ,CAAS,IACtF,IAASH,EAAOG,CAAS;CAC3B;CACA,IAAMK,KAAQ,MAAwD;EACpE,IAAIC,MAAQ,KAAA,KAAa,OAAOA,KAAQ,YAAYA,EAAI,SAAS,KAAA,GAAW,OAAOP;EACnF,IAAI,OAAOO,EAAI,QAAS,UACxB,OAAOT,EAAOI,EAAoBK,EAAI,KAAK,IAAIJ,CAAK,CAAC;CACvD,GACMK,IAAS;EAAE;EAAQ,OAAOF,EAAKd,CAAW;EAAG,KAAKc,EAAKb,CAAS;EAAG,KAAKa,EAAKZ,CAAS;CAAE;CAI9F,OAHIH,EAAWC,CAAW,MAAG,EAAS,cAAciB,EAAejB,GAAaW,CAAK,IACjFZ,EAAWE,CAAS,MAAG,EAAS,YAAYgB,EAAehB,GAAWU,CAAK,IAC3EZ,EAAWG,CAAS,MAAG,EAAS,YAAYe,EAAef,GAAWS,CAAK,IACxE;EAAE,KAAK;GAAE,GAAGb;GAAK,QAAQK;EAAS;EAAG;CAAO;AACrD;AAIA,SAASJ,EAAW,GAA6C;CAC/D,OAAO,OAAOgB,KAAQ,YAAY,OAAOA,EAAI,QAAS;AACxD;AAEA,SAASE,EAAe,GAAe,GAA0B;CAC/D,OAAO;EAAE,GAAGF;EAAK,MAAMG,EAAkBH,GAAK,GAAGL,EAAoBK,EAAI,KAAK,IAAIJ,CAAK,CAAC;CAAE;AAC5F"}
1
+ {"version":3,"file":"strokeLengths.js","names":["WORLD","resolveStrokeLengths","stroke","cmd","isPxMarker","markerStart","markerMid","markerEnd","resolved","strokeSpaceOf","transform","screen","metric","ribbon","pxPerUnit","quantizeStrokeScale","scale","resolveStrokeWidth","d","head","ref","spaces","resolvedMarker","resolveMarkerSize"],"sources":["../../src/renderer/strokeLengths.ts"],"sourcesContent":["import type { CommandFill, MarkerRef, CommandStroke } from '@weasel-js/paint';\nimport type { PathDrawCommand } from './DrawCommand';\nimport type { GlMat3 } from './math/mat3';\nimport { resolveStrokeWidth } from 'features/paths/tessellate/stroke';\nimport {\n strokeSpaceOf, type ScreenSpace, type StrokeSpaces,\n} from 'features/paths/tessellate/metric';\nimport { quantizeStrokeScale } from './cache/strokeMeshCache';\nimport { resolveMarkerSize } from '../core/markerInset';\n\n/** A path command whose stroke paints. */\nexport type StrokedPathCommand = PathDrawCommand & { stroke: CommandStroke & { paint: CommandFill } };\n\n/** A stroke command ready to tessellate, and the spaces to tessellate it in. */\nexport interface ResolvedStrokeCommand {\n cmd: StrokedPathCommand;\n /** Where the ribbon and each head are built; every length in `cmd` is\n * measured in the space of the part it belongs to. */\n spaces: StrokeSpaces;\n}\n\nconst WORLD: StrokeSpaces = {};\n\n/**\n * `cmd` with its `{ px }` lengths — the stroke width, any marker size, and on a\n * `{ px }` stroke its dashes — resolved against the accumulated transform's\n * quantized scale, so everything downstream (the ribbon cache key, the insets,\n * the heads) sees plain numbers.\n *\n * Under a transform that stretches one direction more than another, each\n * screen-sized part is also built in the transform's stretch, where lengths\n * measure as they do on screen, so it is exact across, down and on every\n * diagonal rather than right only on average. World-sized parts stay in world.\n */\nexport function resolveStrokeLengths(transform: GlMat3, cmd: StrokedPathCommand): ResolvedStrokeCommand {\n const stroke = cmd.stroke;\n const { markerStart, markerMid, markerEnd } = stroke;\n if (typeof stroke.width !== 'object' && !isPxMarker(markerStart)\n && !isPxMarker(markerMid) && !isPxMarker(markerEnd)) {\n return { cmd, spaces: WORLD };\n }\n const resolved: CommandStroke & { paint: CommandFill } = { ...stroke };\n const { scale, metric } = strokeSpaceOf(transform[0], transform[1], transform[3], transform[4]);\n const screen = (pxPerUnit: number): ScreenSpace | undefined =>\n metric === null ? undefined : { metric, pxPerUnit };\n let ribbon: ScreenSpace | undefined;\n if (typeof stroke.width === 'object') {\n const pxPerUnit = quantizeStrokeScale(stroke.width.px, scale);\n resolved.width = resolveStrokeWidth(stroke.width, pxPerUnit);\n if (stroke.dash && pxPerUnit > 0) resolved.dash = stroke.dash.map((d) => d / pxPerUnit);\n ribbon = screen(pxPerUnit);\n }\n const head = (ref: MarkerRef | undefined): ScreenSpace | undefined => {\n if (ref === undefined || typeof ref === 'string' || ref.size === undefined) return ribbon;\n if (typeof ref.size === 'number') return undefined;\n return screen(quantizeStrokeScale(ref.size.px, scale));\n };\n const spaces = { ribbon, start: head(markerStart), mid: head(markerMid), end: head(markerEnd) };\n if (isPxMarker(markerStart)) resolved.markerStart = resolvedMarker(markerStart, scale);\n if (isPxMarker(markerMid)) resolved.markerMid = resolvedMarker(markerMid, scale);\n if (isPxMarker(markerEnd)) resolved.markerEnd = resolvedMarker(markerEnd, scale);\n return { cmd: { ...cmd, stroke: resolved }, spaces };\n}\n\ntype PxMarker = Exclude<MarkerRef, string> & { size: { px: number } };\n\nfunction isPxMarker(ref: MarkerRef | undefined): ref is PxMarker {\n return typeof ref === 'object' && typeof ref.size === 'object';\n}\n\nfunction resolvedMarker(ref: PxMarker, scale: number): MarkerRef {\n return { ...ref, size: resolveMarkerSize(ref, 0, quantizeStrokeScale(ref.size.px, scale)) };\n}\n"],"mappings":";;;;;AAqBA,IAAMA,IAAsB,CAAC;AAa7B,SAAgBC,EAAqB,GAAmB,GAAgD;CACtG,IAAMC,IAASC,EAAI,QACb,EAAE,gBAAa,cAAW,iBAAcD;CAC9C,IAAI,OAAOA,EAAO,SAAU,YAAY,CAACE,EAAWC,CAAW,KAC1D,CAACD,EAAWE,CAAS,KAAK,CAACF,EAAWG,CAAS,GAClD,OAAO;EAAE;EAAK,QAAQP;CAAM;CAE9B,IAAMQ,IAAmD,EAAE,GAAGN,EAAO,GAC/D,EAAE,UAAO,cAAWO,EAAcC,EAAU,IAAIA,EAAU,IAAIA,EAAU,IAAIA,EAAU,EAAE,GACxFC,KAAU,MACdC,MAAW,OAAO,KAAA,IAAY;EAAE;EAAQ;CAAU,GAChDC;CACJ,IAAI,OAAOX,EAAO,SAAU,UAAU;EACpC,IAAMY,IAAYC,EAAoBb,EAAO,MAAM,IAAIc,CAAK;EAG5D,AAFA,EAAS,QAAQC,EAAmBf,EAAO,OAAOY,CAAS,GACvDZ,EAAO,QAAQY,IAAY,MAAG,EAAS,OAAOZ,EAAO,KAAK,KAAK,MAAMgB,IAAIJ,CAAS,IACtF,IAASH,EAAOG,CAAS;CAC3B;CACA,IAAMK,KAAQ,MAAwD;EACpE,IAAIC,MAAQ,KAAA,KAAa,OAAOA,KAAQ,YAAYA,EAAI,SAAS,KAAA,GAAW,OAAOP;EACnF,IAAI,OAAOO,EAAI,QAAS,UACxB,OAAOT,EAAOI,EAAoBK,EAAI,KAAK,IAAIJ,CAAK,CAAC;CACvD,GACMK,IAAS;EAAE;EAAQ,OAAOF,EAAKd,CAAW;EAAG,KAAKc,EAAKb,CAAS;EAAG,KAAKa,EAAKZ,CAAS;CAAE;CAI9F,OAHIH,EAAWC,CAAW,MAAG,EAAS,cAAciB,EAAejB,GAAaW,CAAK,IACjFZ,EAAWE,CAAS,MAAG,EAAS,YAAYgB,EAAehB,GAAWU,CAAK,IAC3EZ,EAAWG,CAAS,MAAG,EAAS,YAAYe,EAAef,GAAWS,CAAK,IACxE;EAAE,KAAK;GAAE,GAAGb;GAAK,QAAQK;EAAS;EAAG;CAAO;AACrD;AAIA,SAASJ,EAAW,GAA6C;CAC/D,OAAO,OAAOgB,KAAQ,YAAY,OAAOA,EAAI,QAAS;AACxD;AAEA,SAASE,EAAe,GAAe,GAA0B;CAC/D,OAAO;EAAE,GAAGF;EAAK,MAAMG,EAAkBH,GAAK,GAAGL,EAAoBK,EAAI,KAAK,IAAIJ,CAAK,CAAC;CAAE;AAC5F"}
@@ -1,14 +1,34 @@
1
1
  import { createReflectable as e } from "@weasel-js/registry";
2
2
  //#region src/renderer/textures/registerTexture.ts
3
- var t = 0, n = e(), r = n.reflection;
4
- function i(e) {
5
- return n.get(e) ?? null;
3
+ var t = 0, n = e(), r = n.reflection, i = [];
4
+ function a(e, t) {
5
+ let n = {
6
+ prefix: e,
7
+ owner: t
8
+ };
9
+ return i.push(n), () => {
10
+ let e = i.indexOf(n);
11
+ e !== -1 && i.splice(e, 1);
12
+ };
6
13
  }
7
- function a(e) {
14
+ function o(e) {
15
+ for (let t = 0; t < i.length; t++) if (e.startsWith(i[t].prefix)) return i[t].owner;
16
+ }
17
+ function s(e) {
18
+ let t = i.length > 0 ? o(e) : void 0, r = n.get(e);
19
+ return r ? (t?.touched?.(e), r) : t ? (t.revive(e), n.get(e) ?? null) : null;
20
+ }
21
+ function c(e) {
8
22
  let r = `tex_${++t}`;
9
23
  return n.set(r, { source: e }), { id: r };
10
24
  }
25
+ function l(e, t) {
26
+ return n.set(e, { source: t }), { id: e };
27
+ }
28
+ function u(e) {
29
+ return n.delete(e.id);
30
+ }
11
31
  //#endregion
12
- export { i as getTexture, a as registerTexture, r as textureRegistry };
32
+ export { s as getTexture, a as ownTextureIds, c as registerTexture, l as registerTextureAs, r as textureRegistry, u as unregisterTexture };
13
33
 
14
34
  //# sourceMappingURL=registerTexture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registerTexture.js","names":["counter","registry","createReflectable","textureRegistry","getTexture","id","registerTexture","image"],"sources":["../../../src/renderer/textures/registerTexture.ts"],"sourcesContent":["/**\n * registerTexture — accepts an image source, assigns an opaque id, stores in\n * a module-level registry. Actual GL upload happens lazily at draw time in\n * drawShader() via GLTextureCache.upload (which is idempotent).\n *\n * Lifecycle: textures live for the renderer's lifetime. No unregister in v1.\n *\n * Convention §9: this registry stores image data only — no per-renderer state.\n * Each WeaselRenderer's GLTextureCache does its own dedup via has(id).\n */\n\nimport type { TextureHandle } from '@weasel-js/paint';\nimport { createReflectable, type Reflection } from '@weasel-js/registry';\n\nexport type { TextureHandle };\n\n/** A registered texture's image source, uploaded to GL lazily at first draw. */\nexport interface TextureEntry {\n source: HTMLImageElement | ImageBitmap;\n}\n\nlet counter = 0;\nconst registry = createReflectable<TextureEntry>();\n\n/** Every registered texture, keyed by its handle id. */\nexport const textureRegistry: Reflection<TextureEntry> = registry.reflection;\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetTextureRegistryForTests(): void {\n registry.clear();\n counter = 0;\n}\n\nexport function getTexture(id: string): TextureEntry | null {\n return registry.get(id) ?? null;\n}\n\n/**\n * Register an image for use as a shader texture uniform.\n *\n * Returns a TextureHandle whose `id` can be passed as a ShaderUniform value.\n * The handle is valid for the lifetime of the renderer it will be used with.\n *\n * @param image The image to register. HTMLImageElement must be fully loaded.\n * @returns Opaque TextureHandle.\n */\nexport function registerTexture(\n image: HTMLImageElement | ImageBitmap,\n): TextureHandle {\n const id = `tex_${++counter}`;\n registry.set(id, { source: image });\n return { id };\n}\n"],"mappings":";;AAqBA,IAAIA,IAAU,GACRC,IAAWC,EAAgC,GAGpCC,IAA4CF,EAAS;AAQlE,SAAgBG,EAAW,GAAiC;CAC1D,OAAOH,EAAS,IAAII,CAAE,KAAK;AAC7B;AAWA,SAAgBC,EACd,GACe;CACf,IAAMD,IAAK,OAAO,EAAEL;CAEpB,OADAC,EAAS,IAAII,GAAI,EAAE,QAAQE,EAAM,CAAC,GAC3B,EAAE,MAAG;AACd"}
1
+ {"version":3,"file":"registerTexture.js","names":["counter","registry","createReflectable","textureRegistry","owners","ownTextureIds","claim","i","ownerOf","id","getTexture","owner","hit","registerTexture","image","registerTextureAs","unregisterTexture","handle"],"sources":["../../../src/renderer/textures/registerTexture.ts"],"sourcesContent":["/**\n * registerTexture — accepts an image source, assigns an opaque id, stores in\n * a module-level registry. Actual GL upload happens lazily at draw time in\n * drawShader() via GLTextureCache.upload (which is idempotent).\n *\n * Lifecycle: a texture lives until `unregisterTexture`. Each renderer frees\n * its own GL copy at the top of its next frame.\n *\n * Convention §9: this registry stores image data only — no per-renderer state.\n * Each WeaselRenderer's GLTextureCache does its own dedup by id and source.\n */\n\nimport type { TextureHandle } from '@weasel-js/paint';\nimport { createReflectable, type Reflection } from '@weasel-js/registry';\n\nexport type { TextureHandle };\n\n/** A registered texture's image source, uploaded to GL lazily at first draw. */\nexport interface TextureEntry {\n source: HTMLImageElement | ImageBitmap;\n}\n\nlet counter = 0;\nconst registry = createReflectable<TextureEntry>();\n\n/** Every registered texture, keyed by its handle id. */\nexport const textureRegistry: Reflection<TextureEntry> = registry.reflection;\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetTextureRegistryForTests(): void {\n registry.clear();\n counter = 0;\n}\n\n/**\n * Whoever mints the ids under one prefix and can rebuild any of them.\n * @internal\n */\nexport interface TextureIdOwner {\n /** Register `id` again if it can be rebuilt; do nothing otherwise. */\n revive(id: string): void;\n /** `id` was looked up and found: something is about to draw it. */\n touched?(id: string): void;\n}\n\nconst owners: { prefix: string; owner: TextureIdOwner }[] = [];\n\n/**\n * Claim every texture id starting with `prefix`. Returns the release.\n * @internal\n */\nexport function ownTextureIds(prefix: string, owner: TextureIdOwner): () => void {\n const claim = { prefix, owner };\n owners.push(claim);\n return () => {\n const i = owners.indexOf(claim);\n if (i !== -1) owners.splice(i, 1);\n };\n}\n\nfunction ownerOf(id: string): TextureIdOwner | undefined {\n for (let i = 0; i < owners.length; i++) {\n if (id.startsWith(owners[i].prefix)) return owners[i].owner;\n }\n return undefined;\n}\n\n/**\n * The entry for `id`, as a draw looks it up. An owned id that was\n * unregistered is rebuilt by its owner first, so a handle held past its\n * texture's eviction still draws.\n */\nexport function getTexture(id: string): TextureEntry | null {\n const owner = owners.length > 0 ? ownerOf(id) : undefined;\n const hit = registry.get(id);\n if (hit) {\n owner?.touched?.(id);\n return hit;\n }\n if (!owner) return null;\n owner.revive(id);\n return registry.get(id) ?? null;\n}\n\n/**\n * Register an image for use as a shader texture uniform.\n *\n * Returns a TextureHandle whose `id` can be passed as a ShaderUniform value.\n * The handle is valid for the lifetime of the renderer it will be used with.\n *\n * @param image The image to register. HTMLImageElement must be fully loaded.\n * @returns Opaque TextureHandle.\n */\nexport function registerTexture(\n image: HTMLImageElement | ImageBitmap,\n): TextureHandle {\n const id = `tex_${++counter}`;\n registry.set(id, { source: image });\n return { id };\n}\n\n/**\n * Register an image under an id its caller chose.\n * @internal\n */\nexport function registerTextureAs(\n id: string,\n image: HTMLImageElement | ImageBitmap,\n): TextureHandle {\n registry.set(id, { source: image });\n return { id };\n}\n\n/**\n * Drop a registered texture. Every renderer that uploaded it frees its GL\n * copy at the top of its next frame; a draw command still holding the handle\n * then draws nothing and warns. The image itself is the caller's to release.\n *\n * @returns Whether the handle was registered.\n */\nexport function unregisterTexture(handle: TextureHandle): boolean {\n return registry.delete(handle.id);\n}\n"],"mappings":";;AAsBA,IAAIA,IAAU,GACRC,IAAWC,EAAgC,GAGpCC,IAA4CF,EAAS,YAmB5DG,IAAsD,CAAC;AAM7D,SAAgBC,EAAc,GAAgB,GAAmC;CAC/E,IAAMC,IAAQ;EAAE;EAAQ;CAAM;CAE9B,OADAF,EAAO,KAAKE,CAAK,SACJ;EACX,IAAMC,IAAIH,EAAO,QAAQE,CAAK;EAC9B,AAAIC,MAAM,MAAIH,EAAO,OAAOG,GAAG,CAAC;CAClC;AACF;AAEA,SAASC,EAAQ,GAAwC;CACvD,KAAK,IAAID,IAAI,GAAGA,IAAIH,EAAO,QAAQ,KACjC,IAAIK,EAAG,WAAWL,EAAOG,EAAE,CAAC,MAAM,GAAG,OAAOH,EAAOG,EAAE,CAAC;AAG1D;AAOA,SAAgBG,EAAW,GAAiC;CAC1D,IAAMC,IAAQP,EAAO,SAAS,IAAII,EAAQC,CAAE,IAAI,KAAA,GAC1CG,IAAMX,EAAS,IAAIQ,CAAE;CAO3B,OANIG,KACFD,GAAO,UAAUF,CAAE,GACZG,KAEJD,KACLA,EAAM,OAAOF,CAAE,GACRR,EAAS,IAAIQ,CAAE,KAAK,QAFR;AAGrB;AAWA,SAAgBI,EACd,GACe;CACf,IAAMJ,IAAK,OAAO,EAAET;CAEpB,OADAC,EAAS,IAAIQ,GAAI,EAAE,QAAQK,EAAM,CAAC,GAC3B,EAAE,MAAG;AACd;AAMA,SAAgBC,EACd,GACA,GACe;CAEf,OADAd,EAAS,IAAIQ,GAAI,EAAE,QAAQK,EAAM,CAAC,GAC3B,EAAE,MAAG;AACd;AASA,SAAgBE,EAAkB,GAAgC;CAChE,OAAOf,EAAS,OAAOgB,EAAO,EAAE;AAClC"}
@@ -1,31 +1,24 @@
1
- export { C as CullRect, D as DrawCommand, E as Effect, G as GroupDrawCommand, I as IDENTITY_COLOR_MATRIX, a as ImageDrawCommand, b as ImageMinification, P as PathDrawCommand, R as RenderOptions, c as RenderSpan, d as RenderSpanStats, e as RenderStats, f as RenderTarget, S as SPRITE_STRIDE, g as ShaderDrawCommand, h as SolidPaint, i as SpriteSheet, j as SpritesDrawCommand, k as StrokeOptions, T as TextDrawCommand, W as WeaselRenderer, l as WeaselRendererOptions, m as blur, n as buildGradientRamp, o as cullDrawCommands, p as frameRect, r as registerEffect, t as tessellateStroke, v as viewToMat3, q as vignette } from './builtins-C-VgUlWI.js';
2
- export { G as GlMat3, P as ProgramSource, S as ShaderCompileError, a as ShaderProgramHandle, b as ShaderUniform, m as mat3, p as programSourceRegistry, r as registerProgram } from './registerProgram-BMZRDgrh.js';
1
+ export { C as CullRect, D as DrawCommand, E as Effect, G as GroupDrawCommand, I as IDENTITY_COLOR_MATRIX, a as ImageDrawCommand, b as ImageMinification, P as PathDrawCommand, R as RenderOptions, c as RenderSpan, d as RenderSpanStats, e as RenderStats, f as RenderTarget, S as SPRITE_STRIDE, g as ShaderDrawCommand, h as SolidPaint, i as SpriteSheet, j as SpritesDrawCommand, k as StrokeOptions, T as TextDrawCommand, W as WeaselRenderer, l as WeaselRendererOptions, m as blur, n as buildGradientRamp, o as cullDrawCommands, p as frameRect, r as registerEffect, q as releaseImageSource, t as tessellateStroke, v as viewToMat3, s as vignette } from './builtins-DPcdghtB.js';
2
+ import { TextureHandle } from '@weasel-js/paint';
3
+ export { CommandFill, CommandPaintUnits, CommandStroke, PosedFill, SolidFill, TextureHandle } from '@weasel-js/paint';
4
+ export { G as GlMat3, P as ProgramSource, S as ShaderCompileError, a as ShaderProgramHandle, b as ShaderUniform, m as mat3, p as programSourceRegistry, r as registerProgram } from './registerProgram-T9S_PfAX.js';
3
5
  export { Mesh, TessellateOptions, tessellate } from '@weasel-js/geom/tessellate';
4
6
  export { RegisterFontOptions, canQueryLocalFonts, cssFontFamily, cssFontFamilyLoading, enableLocalFontOutlines, fontOutlineRegistry, fontRegistry, hasFontOutlines, isCanvasFont, listFontOutlines, loadFontOutlines, outlineStatus, registerCanvasFont, registerFont, registerFontOutlines, subscribeGlyphReady, unregisterCanvasFont, unregisterFontOutlines } from '@weasel-js/font';
5
- import { TextureHandle } from '@weasel-js/paint';
6
- export { TextureHandle } from '@weasel-js/paint';
7
7
  import { Reflection } from '@weasel-js/registry';
8
8
  export { View as ViewLike } from '@weasel-js/routing';
9
9
  import '@weasel-js/geom';
10
- import 'react';
11
- import '@weasel-js/history';
12
- import './types-A37hYkeR.js';
13
10
  import '@weasel-js/text';
14
- import './poseDescriptor-D-OH-tu5.js';
15
- import '@weasel-js/routing/react';
16
- import './types-B_9g6hMM.js';
17
- import '@weasel-js/cursor';
18
- import '@weasel-js/gestures';
19
11
 
20
12
  /**
21
13
  * registerTexture — accepts an image source, assigns an opaque id, stores in
22
14
  * a module-level registry. Actual GL upload happens lazily at draw time in
23
15
  * drawShader() via GLTextureCache.upload (which is idempotent).
24
16
  *
25
- * Lifecycle: textures live for the renderer's lifetime. No unregister in v1.
17
+ * Lifecycle: a texture lives until `unregisterTexture`. Each renderer frees
18
+ * its own GL copy at the top of its next frame.
26
19
  *
27
20
  * Convention §9: this registry stores image data only — no per-renderer state.
28
- * Each WeaselRenderer's GLTextureCache does its own dedup via has(id).
21
+ * Each WeaselRenderer's GLTextureCache does its own dedup by id and source.
29
22
  */
30
23
 
31
24
  /** A registered texture's image source, uploaded to GL lazily at first draw. */
@@ -44,6 +37,14 @@ declare const textureRegistry: Reflection<TextureEntry>;
44
37
  * @returns Opaque TextureHandle.
45
38
  */
46
39
  declare function registerTexture(image: HTMLImageElement | ImageBitmap): TextureHandle;
40
+ /**
41
+ * Drop a registered texture. Every renderer that uploaded it frees its GL
42
+ * copy at the top of its next frame; a draw command still holding the handle
43
+ * then draws nothing and warns. The image itself is the caller's to release.
44
+ *
45
+ * @returns Whether the handle was registered.
46
+ */
47
+ declare function unregisterTexture(handle: TextureHandle): boolean;
47
48
 
48
49
  /**
49
50
  * On-screen glyph size (CSS px) at or above which a face with registered
@@ -88,4 +89,4 @@ declare const EFFECT_VERT_SRC = "#version 300 es\nin vec2 a_position;\nin vec2 a
88
89
  * redeclare them with different meanings; it may leave any of them out. */
89
90
  declare const EFFECT_KIT_UNIFORMS: readonly ["u_source", "u_resolution", "u_texel"];
90
91
 
91
- export { EFFECT_KIT_UNIFORMS, EFFECT_VERT_SRC, OUTLINE_MIN_SCREEN_PX, type TextureEntry, registerTexture, textureRegistry };
92
+ export { EFFECT_KIT_UNIFORMS, EFFECT_VERT_SRC, OUTLINE_MIN_SCREEN_PX, type TextureEntry, registerTexture, textureRegistry, unregisterTexture };
package/dist/renderer.js CHANGED
@@ -1,18 +1,19 @@
1
1
  import { ShaderCompileError as e } from "./renderer/shaders/ShaderProgram.js";
2
- import { buildGradientRamp as t } from "./renderer/cache/GradientRampAtlas.js";
3
- import { mat3 as n } from "./renderer/math/mat3.js";
4
- import { IDENTITY_COLOR_MATRIX as r } from "./renderer/state/GroupState.js";
5
- import { registerTexture as i, textureRegistry as a } from "./renderer/textures/registerTexture.js";
6
- import { programSourceRegistry as o, registerProgram as s } from "./renderer/shaders/registerProgram.js";
7
- import { SPRITE_STRIDE as c } from "./renderer/DrawCommand.js";
8
- import { tessellateStroke as l } from "./features/paths/tessellate/stroke.js";
2
+ import { registerTexture as t, textureRegistry as n, unregisterTexture as r } from "./renderer/textures/registerTexture.js";
3
+ import { releaseImageSource as i } from "./renderer/cache/GLImageCache.js";
4
+ import { buildGradientRamp as a } from "./renderer/cache/GradientRampAtlas.js";
5
+ import { mat3 as o } from "./renderer/math/mat3.js";
6
+ import { IDENTITY_COLOR_MATRIX as s } from "./renderer/state/GroupState.js";
7
+ import { programSourceRegistry as c, registerProgram as l } from "./renderer/shaders/registerProgram.js";
9
8
  import { EFFECT_KIT_UNIFORMS as u, EFFECT_VERT_SRC as d } from "./renderer/effects/effectPrelude.js";
10
- import { OUTLINE_MIN_SCREEN_PX as f } from "./renderer/draw.js";
11
- import { WeaselRenderer as p } from "./renderer/WeaselRenderer.js";
12
- import { frameRect as m } from "./renderer/spriteSheet.js";
13
- import { viewToMat3 as h } from "./renderer/math/viewToMat3.js";
14
- import { cullDrawCommands as g } from "./renderer/cullDrawCommands.js";
15
- import { registerEffect as _ } from "./renderer/effects/types.js";
16
- import { blur as v, vignette as y } from "./renderer/effects/builtins.js";
17
- import { canQueryLocalFonts as b, cssFontFamily as x, cssFontFamilyLoading as S, enableLocalFontOutlines as C, fontOutlineRegistry as w, fontRegistry as T, hasFontOutlines as E, isCanvasFont as D, listFontOutlines as O, loadFontOutlines as k, outlineStatus as A, registerCanvasFont as j, registerFont as M, registerFontOutlines as N, subscribeGlyphReady as P, tessellate as F, unregisterCanvasFont as I, unregisterFontOutlines as L } from "./renderer/index.js";
18
- export { u as EFFECT_KIT_UNIFORMS, d as EFFECT_VERT_SRC, r as IDENTITY_COLOR_MATRIX, f as OUTLINE_MIN_SCREEN_PX, c as SPRITE_STRIDE, e as ShaderCompileError, p as WeaselRenderer, v as blur, t as buildGradientRamp, b as canQueryLocalFonts, x as cssFontFamily, S as cssFontFamilyLoading, g as cullDrawCommands, C as enableLocalFontOutlines, w as fontOutlineRegistry, T as fontRegistry, m as frameRect, E as hasFontOutlines, D as isCanvasFont, O as listFontOutlines, k as loadFontOutlines, n as mat3, A as outlineStatus, o as programSourceRegistry, j as registerCanvasFont, _ as registerEffect, M as registerFont, N as registerFontOutlines, s as registerProgram, i as registerTexture, P as subscribeGlyphReady, F as tessellate, l as tessellateStroke, a as textureRegistry, I as unregisterCanvasFont, L as unregisterFontOutlines, h as viewToMat3, y as vignette };
9
+ import { tessellateStroke as f } from "./features/paths/tessellate/stroke.js";
10
+ import { OUTLINE_MIN_SCREEN_PX as p } from "./renderer/draw/text.js";
11
+ import { SPRITE_STRIDE as m } from "./renderer/DrawCommand.js";
12
+ import { WeaselRenderer as h } from "./renderer/WeaselRenderer.js";
13
+ import { frameRect as g } from "./renderer/spriteSheet.js";
14
+ import { viewToMat3 as _ } from "./renderer/math/viewToMat3.js";
15
+ import { cullDrawCommands as v } from "./renderer/cullDrawCommands.js";
16
+ import { registerEffect as y } from "./renderer/effects/types.js";
17
+ import { blur as b, vignette as x } from "./renderer/effects/builtins.js";
18
+ import { canQueryLocalFonts as S, cssFontFamily as C, cssFontFamilyLoading as w, enableLocalFontOutlines as T, fontOutlineRegistry as E, fontRegistry as D, hasFontOutlines as O, isCanvasFont as k, listFontOutlines as A, loadFontOutlines as j, outlineStatus as M, registerCanvasFont as N, registerFont as P, registerFontOutlines as F, subscribeGlyphReady as I, tessellate as L, unregisterCanvasFont as R, unregisterFontOutlines as z } from "./renderer/index.js";
19
+ export { u as EFFECT_KIT_UNIFORMS, d as EFFECT_VERT_SRC, s as IDENTITY_COLOR_MATRIX, p as OUTLINE_MIN_SCREEN_PX, m as SPRITE_STRIDE, e as ShaderCompileError, h as WeaselRenderer, b as blur, a as buildGradientRamp, S as canQueryLocalFonts, C as cssFontFamily, w as cssFontFamilyLoading, v as cullDrawCommands, T as enableLocalFontOutlines, E as fontOutlineRegistry, D as fontRegistry, g as frameRect, O as hasFontOutlines, k as isCanvasFont, A as listFontOutlines, j as loadFontOutlines, o as mat3, M as outlineStatus, c as programSourceRegistry, N as registerCanvasFont, y as registerEffect, P as registerFont, F as registerFontOutlines, l as registerProgram, t as registerTexture, i as releaseImageSource, I as subscribeGlyphReady, L as tessellate, f as tessellateStroke, n as textureRegistry, R as unregisterCanvasFont, z as unregisterFontOutlines, r as unregisterTexture, _ as viewToMat3, x as vignette };
package/dist/resize.d.ts CHANGED
@@ -1,11 +1,10 @@
1
- export { C as CORNER_ANCHORS, a as CornerAnchor, b as CornerHandle, U as UseResizeOptions, c as cornerPoint, d as cornerResizeHandles, f as fixedCornerOf, h as hitCornerHandle } from './cornerHandles-BCrDp_mH.js';
2
- export { P as PoseDescriptor, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR, p as poseDescriptorForNode } from './poseDescriptor-D-OH-tu5.js';
3
- import { B as BoundsConstraint } from './types-B_9g6hMM.js';
1
+ export { C as CORNER_ANCHORS, a as CornerAnchor, b as CornerHandle, U as UseResizeOptions, c as cornerPoint, d as cornerResizeHandles, f as fixedCornerOf, h as hitCornerHandle } from './cornerHandles-CtCb8a3G.js';
2
+ export { A as AUTO_POSE_DESCRIPTOR, P as PoseDescriptor, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR, i as isPathLike, b as isRectPose, p as poseDescriptorForNode } from './autoPoseDescriptor-Ct7yqivU.js';
3
+ import { B as BoundsConstraint } from './types-B4iJRHC3.js';
4
4
  import { Bounds, ModifierState } from '@weasel-js/routing';
5
- export { A as AUTO_POSE_DESCRIPTOR, i as isPathLike, a as isRectPose } from './autoPoseDescriptor-vCdt55xm.js';
6
- import './types-A37hYkeR.js';
7
- import '@weasel-js/history';
8
5
  import '@weasel-js/geom';
6
+ import './types-k-5Oqh-U.js';
7
+ import '@weasel-js/history';
9
8
 
10
9
  /** Resize constraint that stops a node shrinking past a minimum. The anchored
11
10
  * edge stays put, so clamping pushes the dragged edge back rather than moving
package/dist/resize.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { RECT_POSE_DESCRIPTOR as e, ROTATED_POSE_DESCRIPTOR as t, poseDescriptorForNode as n } from "./core/geometry/poseDescriptor.js";
2
2
  import { AUTO_POSE_DESCRIPTOR as r, isPathLike as i, isRectPose as a } from "./interactions/actions/resize/autoPoseDescriptor.js";
3
- import { clampMinSize as o } from "./interactions/actions/resize/behaviors/clampMinSize.js";
4
- import { lockAspectWithModifier as s } from "./interactions/actions/resize/behaviors/lockAspect.js";
5
- import { DEFAULT_RESIZE_BEHAVIORS as c } from "./interactions/actions/resize/behaviors/index.js";
6
- import { CORNER_ANCHORS as l, cornerPoint as u, cornerResizeHandles as d, fixedCornerOf as f, hitCornerHandle as p } from "./interactions/actions/resize/cornerHandles.js";
7
- export { r as AUTO_POSE_DESCRIPTOR, l as CORNER_ANCHORS, c as DEFAULT_RESIZE_BEHAVIORS, e as RECT_POSE_DESCRIPTOR, t as ROTATED_POSE_DESCRIPTOR, o as clampMinSize, u as cornerPoint, d as cornerResizeHandles, f as fixedCornerOf, p as hitCornerHandle, i as isPathLike, a as isRectPose, s as lockAspectWithModifier, n as poseDescriptorForNode };
3
+ import { CORNER_ANCHORS as o, cornerPoint as s, cornerResizeHandles as c, fixedCornerOf as l, hitCornerHandle as u } from "./interactions/actions/resize/cornerHandles.js";
4
+ import { clampMinSize as d } from "./interactions/actions/resize/behaviors/clampMinSize.js";
5
+ import { lockAspectWithModifier as f } from "./interactions/actions/resize/behaviors/lockAspect.js";
6
+ import { DEFAULT_RESIZE_BEHAVIORS as p } from "./interactions/actions/resize/behaviors/index.js";
7
+ export { r as AUTO_POSE_DESCRIPTOR, o as CORNER_ANCHORS, p as DEFAULT_RESIZE_BEHAVIORS, e as RECT_POSE_DESCRIPTOR, t as ROTATED_POSE_DESCRIPTOR, d as clampMinSize, s as cornerPoint, c as cornerResizeHandles, l as fixedCornerOf, u as hitCornerHandle, i as isPathLike, a as isRectPose, f as lockAspectWithModifier, n as poseDescriptorForNode };
package/dist/style.css CHANGED
@@ -1,2 +1,2 @@
1
- ._numeric_zns9n_4{font-family:var(--wzl-font-numeric);font-variant-numeric:tabular-nums}._hud_1hv8c_3{z-index:10000;color:#e8e8e8;pointer-events:none;text-align:right;background:#000000b3;border-radius:4px;padding:6px 8px;font:11px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;position:fixed}._sized_1hv8c_17{min-width:120px;max-width:260px}._readings_1hv8c_22{grid-template-columns:auto auto;column-gap:8px;margin:0;display:grid}._readings_1hv8c_22 dt{text-align:left}._readings_1hv8c_22 dd{white-space:nowrap;margin:0}._muted_1hv8c_39{color:#888}._absent_1hv8c_44{color:#888;font-style:italic}._header_1hv8c_49{margin-bottom:2px}._list_1hv8c_53{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}._item_1hv8c_62{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}._itemBest_1hv8c_68{font-weight:700}._row_1hv8c_72{white-space:nowrap;justify-content:flex-end;gap:8px;display:flex}._stack_1hv8c_79{flex-direction:column;align-items:flex-end;display:flex}
1
+ ._numeric_25fd0b{font-family:var(--wzl-font-numeric);font-variant-numeric:tabular-nums}._hud_4467cb{z-index:900;color:#e8e8e8;pointer-events:none;text-align:right;background:#000000b3;border-radius:4px;padding:6px 8px;font:11px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;position:fixed}._sized_4467cb{min-width:120px;max-width:260px}._readings_4467cb{grid-template-columns:auto auto;column-gap:8px;margin:0;display:grid}._readings_4467cb dt{text-align:left}._readings_4467cb dd{white-space:nowrap;margin:0}._muted_4467cb{color:#888}._absent_4467cb{color:#888;font-style:italic}._header_4467cb{margin-bottom:2px}._list_4467cb{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}._item_4467cb{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}._itemBest_4467cb{font-weight:700}._row_4467cb{white-space:nowrap;justify-content:flex-end;gap:8px;display:flex}._stack_4467cb{flex-direction:column;align-items:flex-end;display:flex}
2
2
  /*$vite$:1*/
@@ -1,12 +1,18 @@
1
1
  import { createTestHook as e } from "./createTestHook.js";
2
2
  //#region src/test-hook/install.ts
3
- function t(t) {
4
- if (typeof window > "u" || typeof process < "u" && process.env.NODE_ENV === "production" || new URLSearchParams(window.location.search).get("test") !== "1") return null;
5
- if (window.__weaselTest) return window.__weaselTest;
6
- let n = e(t);
7
- return window.__weaselTest = n, n;
3
+ var t = [];
4
+ function n(n) {
5
+ if (typeof window > "u" || typeof process < "u" && process.env.NODE_ENV === "production" || new URLSearchParams(window.location.search).get("test") !== "1" || window.__weaselTest && window.__weaselTest !== t[0]) return null;
6
+ let r = e(n);
7
+ return t.push(r), window.__weaselTest = t[0], r;
8
+ }
9
+ function r(e) {
10
+ let n = t.indexOf(e);
11
+ if (n < 0) return;
12
+ let r = typeof window < "u" && window.__weaselTest === e;
13
+ t.splice(n, 1), r && (t.length > 0 ? window.__weaselTest = t[0] : delete window.__weaselTest);
8
14
  }
9
15
  //#endregion
10
- export { t as installTestHookIfRequested };
16
+ export { n as installTestHookIfRequested, r as releaseTestHook };
11
17
 
12
18
  //# sourceMappingURL=install.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","names":["installTestHookIfRequested","hook","createTestHook","refs"],"sources":["../../src/test-hook/install.ts"],"sourcesContent":["// src/test-hook/install.ts\nimport { createTestHook } from './createTestHook';\nimport type { TestHookRefs, WeaselTestHook } from './types';\n\n/** Attach `window.__weaselTest` and return the hook iff\n * - `process.env.NODE_ENV !== 'production'` (never in production consumer\n * builds — paired with a call-site gate in SceneCanvas so the entire\n * module DCEs out), AND\n * - the URL contains `?test=1`.\n * Otherwise returns null and does not touch `window`. */\nexport function installTestHookIfRequested(refs: TestHookRefs): WeaselTestHook | null {\n if (typeof window === 'undefined') return null;\n // Defense in depth: even if the call-site gate is bypassed, never expose\n // the hook in production.\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return null;\n const params = new URLSearchParams(window.location.search);\n if (params.get('test') !== '1') return null;\n // If a hook is already installed (HMR), keep it.\n if (window.__weaselTest) return window.__weaselTest;\n const hook = createTestHook(refs);\n window.__weaselTest = hook;\n return hook;\n}\n"],"mappings":";;AAUA,SAAgBA,EAA2B,GAA2C;CAMpF,IALI,OAAO,SAAW,OAGlB,OAAO,UAAY,OAAA,QAAA,IAAA,aAAyC,gBAE5D,IADe,gBAAgB,OAAO,SAAS,MAC/C,CAAA,CAAO,IAAI,MAAM,MAAM,KAAK,OAAO;CAEvC,IAAI,OAAO,cAAc,OAAO,OAAO;CACvC,IAAMC,IAAOC,EAAeC,CAAI;CAEhC,OADA,OAAO,eAAeF,GACfA;AACT"}
1
+ {"version":3,"file":"install.js","names":["live","installTestHookIfRequested","hook","createTestHook","refs","releaseTestHook","i","owned"],"sources":["../../src/test-hook/install.ts"],"sourcesContent":["// src/test-hook/install.ts\nimport { createTestHook } from './createTestHook';\nimport type { TestHookRefs, WeaselTestHook } from './types';\n\n/** Hooks of the canvases mounted now, oldest first. `window.__weaselTest` is the first. */\nconst live: WeaselTestHook[] = [];\n\n/** Make a hook for this canvas and return it iff\n * - `process.env.NODE_ENV !== 'production'` (never in production consumer\n * builds — paired with a call-site gate in SceneCanvas so the entire\n * module DCEs out), AND\n * - the URL contains `?test=1`, AND\n * - `window.__weaselTest` is not held by something other than a canvas.\n * Otherwise returns null and does not touch `window`. `window.__weaselTest`\n * answers for the earliest canvas still mounted; the caller hands its hook to\n * `releaseTestHook` when it unmounts. */\nexport function installTestHookIfRequested(refs: TestHookRefs): WeaselTestHook | null {\n if (typeof window === 'undefined') return null;\n // Defense in depth: even if the call-site gate is bypassed, never expose\n // the hook in production.\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return null;\n const params = new URLSearchParams(window.location.search);\n if (params.get('test') !== '1') return null;\n if (window.__weaselTest && window.__weaselTest !== live[0]) return null;\n const hook = createTestHook(refs);\n live.push(hook);\n window.__weaselTest = live[0];\n return hook;\n}\n\n/** Drop `hook`; if it held `window.__weaselTest`, the next canvas's hook takes over. */\nexport function releaseTestHook(hook: WeaselTestHook): void {\n const i = live.indexOf(hook);\n if (i < 0) return;\n const owned = typeof window !== 'undefined' && window.__weaselTest === hook;\n live.splice(i, 1);\n if (!owned) return;\n if (live.length > 0) window.__weaselTest = live[0];\n else delete window.__weaselTest;\n}\n"],"mappings":";;AAKA,IAAMA,IAAyB,CAAC;AAWhC,SAAgBC,EAA2B,GAA2C;CAOpF,IANI,OAAO,SAAW,OAGlB,OAAO,UAAY,OAAA,QAAA,IAAA,aAAyC,gBAE5D,IADe,gBAAgB,OAAO,SAAS,MAC/C,CAAA,CAAO,IAAI,MAAM,MAAM,OACvB,OAAO,gBAAgB,OAAO,iBAAiBD,EAAK,IAAI,OAAO;CACnE,IAAME,IAAOC,EAAeC,CAAI;CAGhC,OAFAJ,EAAK,KAAKE,CAAI,GACd,OAAO,eAAeF,EAAK,IACpBE;AACT;AAGA,SAAgBG,EAAgB,GAA4B;CAC1D,IAAMC,IAAIN,EAAK,QAAQE,CAAI;CAC3B,IAAII,IAAI,GAAG;CACX,IAAMC,IAAQ,OAAO,SAAW,OAAe,OAAO,iBAAiBL;CAEvE,AADAF,EAAK,OAAOM,GAAG,CAAC,GACXC,MACDP,EAAK,SAAS,IAAG,OAAO,eAAeA,EAAK,KAC3C,OAAO,OAAO;AACrB"}
@@ -1,7 +1,7 @@
1
- import { FillStyle, GradientUnits, GradStop, ColorSpace, MarkerKey, Stroke } from '@weasel-js/paint';
1
+ import { FillStyle, PosedFill, GradientUnits, GradStop, ColorSpace, MarkerKey, Stroke } from '@weasel-js/paint';
2
2
  import { ComponentType } from 'react';
3
3
  import { Reflection } from '@weasel-js/registry';
4
- import { c as ShaderProgram, G as GlMat3, P as ProgramSource } from './registerProgram-BMZRDgrh.js';
4
+ import { c as ShaderProgram, G as GlMat3, P as ProgramSource } from './registerProgram-T9S_PfAX.js';
5
5
  import { Path } from '@weasel-js/geom';
6
6
 
7
7
  /**
@@ -34,7 +34,7 @@ interface FillPoseBox {
34
34
  * so a non-square box cannot make it the ellipse SVG would — this keeps the
35
35
  * radius proportionate instead.
36
36
  */
37
- declare function fillInPoseFrame(fill: FillStyle, box: FillPoseBox): FillStyle;
37
+ declare function fillInPoseFrame(fill: FillStyle, box: FillPoseBox): PosedFill;
38
38
  /**
39
39
  * Inverse of {@link fillInPoseFrame}: express a gradient already positioned
40
40
  * in `box`'s frame as `0..1` fractions of that box (`units: 'bounds'`), so
@@ -155,7 +155,7 @@ interface PaintKindEntry {
155
155
  id: string;
156
156
  label: string;
157
157
  /** Glyph naming this kind in an editor's kind bar, as an icon name the UI
158
- * layer resolves — the same indirection `ToolPrefBase.icon` uses. A kind
158
+ * layer resolves — the same indirection `PrefBase.icon` uses. A kind
159
159
  * without one is named by its `label`. */
160
160
  icon?: string;
161
161
  /** A paint of this kind seeded from a color — what an editor writes when a
@@ -1,6 +1,6 @@
1
- export { _ as _resetMarkersForTests, z as _resetPaintKindsForTests } from './test-seams-CuIxe0xY.js';
1
+ export { _ as _resetMarkersForTests, z as _resetPaintKindsForTests } from './test-seams-DM2B87-g.js';
2
2
  import '@weasel-js/paint';
3
3
  import 'react';
4
4
  import '@weasel-js/registry';
5
- import './registerProgram-BMZRDgrh.js';
5
+ import './registerProgram-T9S_PfAX.js';
6
6
  import '@weasel-js/geom';
@@ -9,6 +9,7 @@ function o(o = {}) {
9
9
  let { behaviors: s } = o;
10
10
  return r(() => e({
11
11
  id: "ellipse",
12
+ keybinding: { key: "E" },
12
13
  capabilities: ["creates-shapes"],
13
14
  hookName: "useEllipseTool",
14
15
  cursor: a("crosshairEllipse", { fallback: "crosshair" }),
@@ -1 +1 @@
1
- {"version":3,"file":"useEllipseTool.js","names":["EllipseIcon","useEllipseTool","options","useMemo","defineTool","cursorFor","insertBindingBehaviors","behaviors"],"sources":["../../../../src/tools/builtin/ellipse/useEllipseTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport { EllipseIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\n\n/**\n * Drag-to-draw ellipse tool. Mirrors `useRectTool`: the `drag` binding\n * routes to `insertAction`, which owns the live preview and commits\n * through the `insert` dep. Alt toggles from-corner ⇄ from-center\n * mid-drag via the action's live modifier read.\n */\nexport function useEllipseTool(options: InsertToolOptions = {}): Tool<null> {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool<null>({\n id: 'ellipse',\n capabilities: ['creates-shapes'],\n hookName: 'useEllipseTool',\n cursor: cursorFor('crosshairEllipse', { fallback: 'crosshair' }),\n presentation: {\n label: 'Ellipse',\n group: 'shape',\n icon: <EllipseIcon />,\n },\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { params: { kind: 'ellipse' } , ...insertBindingBehaviors(behaviors) },\n },\n ],\n }),\n [behaviors],\n );\n}\n"],"mappings":";;;;;;;AAaA,SAAgBC,EAAe,IAA6B,CAAC,GAAe;CAC1E,IAAM,EAAE,iBAAcC;CACtB,OAAOC,QAEHC,EAAiB;EACf,IAAI;EACJ,cAAc,CAAC,gBAAgB;EAC/B,UAAU;EACV,QAAQC,EAAU,oBAAoB,EAAE,UAAU,YAAY,CAAC;EAC/D,cAAc;GACZ,OAAO;GACP,OAAO;GACP,MAAM,kBAACL,GAAD,CAAc,CAAA;EACtB;EACA,UAAU,CACR;GACE,MAAM,EAAE,MAAM,OAAO;GACrB,UAAU;GACV,MAAM;IAAE,QAAQ,EAAE,MAAM,UAAU;IAAI,GAAGM,EAAuBC,CAAS;GAAE;EAC7E,CACF;CACF,CAAC,GACH,CAACA,CAAS,CACZ;AACF"}
1
+ {"version":3,"file":"useEllipseTool.js","names":["EllipseIcon","useEllipseTool","options","useMemo","defineTool","cursorFor","insertBindingBehaviors","behaviors"],"sources":["../../../../src/tools/builtin/ellipse/useEllipseTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport { EllipseIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\n\n/**\n * Drag-to-draw ellipse tool. Mirrors `useRectTool`: the `drag` binding\n * routes to `insertAction`, which owns the live preview and commits\n * through the `insert` dep. Alt toggles from-corner ⇄ from-center\n * mid-drag via the action's live modifier read.\n */\nexport function useEllipseTool(options: InsertToolOptions = {}): Tool<null> {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool<null>({\n id: 'ellipse',\n keybinding: { key: 'E' },\n capabilities: ['creates-shapes'],\n hookName: 'useEllipseTool',\n cursor: cursorFor('crosshairEllipse', { fallback: 'crosshair' }),\n presentation: {\n label: 'Ellipse',\n group: 'shape',\n icon: <EllipseIcon />,\n },\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { params: { kind: 'ellipse' } , ...insertBindingBehaviors(behaviors) },\n },\n ],\n }),\n [behaviors],\n );\n}\n"],"mappings":";;;;;;;AAaA,SAAgBC,EAAe,IAA6B,CAAC,GAAe;CAC1E,IAAM,EAAE,iBAAcC;CACtB,OAAOC,QAEHC,EAAiB;EACf,IAAI;EACJ,YAAY,EAAE,KAAK,IAAI;EACvB,cAAc,CAAC,gBAAgB;EAC/B,UAAU;EACV,QAAQC,EAAU,oBAAoB,EAAE,UAAU,YAAY,CAAC;EAC/D,cAAc;GACZ,OAAO;GACP,OAAO;GACP,MAAM,kBAACL,GAAD,CAAc,CAAA;EACtB;EACA,UAAU,CACR;GACE,MAAM,EAAE,MAAM,OAAO;GACrB,UAAU;GACV,MAAM;IAAE,QAAQ,EAAE,MAAM,UAAU;IAAI,GAAGM,EAAuBC,CAAS;GAAE;EAC7E,CACF;CACF,CAAC,GACH,CAACA,CAAS,CACZ;AACF"}
@@ -7,6 +7,7 @@ function a(a = {}) {
7
7
  let o = i(a);
8
8
  return r(() => Object.assign(e({
9
9
  id: "hand",
10
+ keybinding: { key: "H" },
10
11
  capabilities: ["navigation"],
11
12
  hotkey: "space",
12
13
  hookName: "useHandTool",
@@ -1 +1 @@
1
- {"version":3,"file":"useHandTool.js","names":["HandIcon","useHandTool","optsRef","useLatest","opts","useMemo","defineTool","createElement"],"sources":["../../../../src/tools/builtin/hand/useHandTool.ts"],"sourcesContent":["import { useMemo, createElement } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport { HandIcon } from '../../../icons';\nimport type { View } from 'core/viewport/view';\nimport type { InertiaConfig } from 'core/viewport/useDecayLoop';\n\nexport type { InertiaConfig };\n\n/** Options for `useHandTool`. Both are forwarded to `viewport.dragPan` as\n * binding params; momentum additionally needs a `view` dep publishing\n * `decay`, which `<SceneCanvas>` wires. */\nexport interface UseHandToolOptions {\n /** Momentum after release. Omit or pass `false` for none. */\n inertia?: false | InertiaConfig;\n /**\n * Which axes the drag responds to. Default `'both'`.\n *\n * - `'both'` — pan both axes (default).\n * - `'x'` — drag only changes `view.x`. Inertia (if enabled) also stays on x.\n * - `'y'` — drag only changes `view.y`. Inertia stays on y.\n *\n * Locks drag panning to a single axis. The former `useWheelPanTool` /\n * `useWheelZoomTool` / `useKeyboardZoomTool` axis option is dissolved.\n */\n axis?: 'both' | 'x' | 'y';\n}\n\n/** @internal */\ninterface HandScratch {\n startView: View;\n startScreenPoint: { x: number; y: number };\n}\n\n/**\n * Pan-on-drag tool. Registered in both the active slot (sticky, `H` key)\n * and the hotkey slot (momentary, hold `space`).\n *\n * Drag handlers compute pan deltas inline. View is read from ctx.view at\n * gesture start and written via ctx.setView on every move — so the tool\n * works with both controlled and uncontrolled Canvas viewport modes\n * without any extra wiring.\n *\n * Sign convention: dragging the mouse right moves the canvas content right\n * relative to the viewport — i.e. the camera moves *left*. So the new view\n * is `{ x: startView.x - dx, y: startView.y - dy }`.\n */\nexport function useHandTool(opts: UseHandToolOptions = {}): Tool<HandScratch | null> {\n // Read through a ref from a params thunk rather than closing over the\n // values: a consumer passing `inertia={{ friction: 0.9 }}` inline would\n // otherwise mint a new tool identity on every render.\n const optsRef = useLatest(opts);\n return useMemo(\n () =>\n Object.assign(defineTool<HandScratch>({\n id: 'hand',\n capabilities: ['navigation'],\n hotkey: 'space',\n hookName: 'useHandTool',\n presentation: {\n label: 'Hand',\n icon: createElement(HandIcon),\n group: 'view',\n },\n cursor: 'grab',\n }), {\n // Declarative binding routes drag through the dispatcher +\n // viewportDragPanAction, which also owns the grabbing cursor\n // (`Action.activeCursor`) the tool used to declare as an `engaged`\n // phase entry.\n bindings: [{\n spec: { kind: 'drag' as const },\n actionId: 'viewport.dragPan',\n opts: {\n params: () => ({\n axis: optsRef.current.axis ?? 'both',\n inertia: optsRef.current.inertia,\n }),\n },\n }],\n }) as Tool<HandScratch | null>,\n [optsRef],\n );\n}\n"],"mappings":";;;;;AAgDA,SAAgBC,EAAY,IAA2B,CAAC,GAA6B;CAInF,IAAMC,IAAUC,EAAUC,CAAI;CAC9B,OAAOC,QAEH,OAAO,OAAOC,EAAwB;EACpC,IAAI;EACJ,cAAc,CAAC,YAAY;EAC3B,QAAQ;EACR,UAAU;EACV,cAAc;GACZ,OAAO;GACP,MAAMC,EAAcP,CAAQ;GAC5B,OAAO;EACT;EACA,QAAQ;CACV,CAAC,GAAG,EAKF,UAAU,CAAC;EACT,MAAM,EAAE,MAAM,OAAgB;EAC9B,UAAU;EACV,MAAM,EACJ,eAAe;GACb,MAAME,EAAQ,QAAQ,QAAQ;GAC9B,SAASA,EAAQ,QAAQ;EAC3B,GACF;CACF,CAAC,EACH,CAAC,GACH,CAACA,CAAO,CACV;AACF"}
1
+ {"version":3,"file":"useHandTool.js","names":["HandIcon","useHandTool","optsRef","useLatest","opts","useMemo","defineTool","createElement"],"sources":["../../../../src/tools/builtin/hand/useHandTool.ts"],"sourcesContent":["import { useMemo, createElement } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport { HandIcon } from '../../../icons';\nimport type { InertiaConfig } from 'core/viewport/useDecayLoop';\n\nexport type { InertiaConfig };\n\n/** Options for `useHandTool`. Both are forwarded to `viewport.dragPan` as\n * binding params; momentum additionally needs a `view` dep publishing\n * `decay`, which `<SceneCanvas>` wires. */\nexport interface UseHandToolOptions {\n /** Momentum after release. Omit or pass `false` for none. */\n inertia?: false | InertiaConfig;\n /**\n * Which axes the drag responds to. Default `'both'`.\n *\n * - `'both'` — pan both axes (default).\n * - `'x'` — drag only changes `view.x`. Inertia (if enabled) also stays on x.\n * - `'y'` — drag only changes `view.y`. Inertia stays on y.\n *\n * Locks drag panning to a single axis. The former `useWheelPanTool` /\n * `useWheelZoomTool` / `useKeyboardZoomTool` axis option is dissolved.\n */\n axis?: 'both' | 'x' | 'y';\n}\n\n/**\n * Pan-on-drag tool. Registered in both the active slot (sticky, `H` key)\n * and the hotkey slot (momentary, hold `space`).\n *\n * A declarative shell: its one binding routes a drag to the\n * `viewport.dragPan` action, which owns the gesture, the view writes, and\n * the grabbing cursor. The tool only passes `axis` and `inertia` along.\n */\nexport function useHandTool(opts: UseHandToolOptions = {}): Tool<null> {\n // Read through a ref from a params thunk rather than closing over the\n // values: a consumer passing `inertia={{ friction: 0.9 }}` inline would\n // otherwise mint a new tool identity on every render.\n const optsRef = useLatest(opts);\n return useMemo(\n () =>\n Object.assign(defineTool<null>({\n id: 'hand',\n keybinding: { key: 'H' },\n capabilities: ['navigation'],\n hotkey: 'space',\n hookName: 'useHandTool',\n presentation: {\n label: 'Hand',\n icon: createElement(HandIcon),\n group: 'view',\n },\n cursor: 'grab',\n }), {\n // Declarative binding routes drag through the dispatcher +\n // viewportDragPanAction, which also owns the grabbing cursor\n // (`Action.activeCursor`) the tool used to declare as an `engaged`\n // phase entry.\n bindings: [{\n spec: { kind: 'drag' as const },\n actionId: 'viewport.dragPan',\n opts: {\n params: () => ({\n axis: optsRef.current.axis ?? 'both',\n inertia: optsRef.current.inertia,\n }),\n },\n }],\n }) as Tool<null>,\n [optsRef],\n );\n}\n"],"mappings":";;;;;AAoCA,SAAgBC,EAAY,IAA2B,CAAC,GAAe;CAIrE,IAAMC,IAAUC,EAAUC,CAAI;CAC9B,OAAOC,QAEH,OAAO,OAAOC,EAAiB;EAC7B,IAAI;EACJ,YAAY,EAAE,KAAK,IAAI;EACvB,cAAc,CAAC,YAAY;EAC3B,QAAQ;EACR,UAAU;EACV,cAAc;GACZ,OAAO;GACP,MAAMC,EAAcP,CAAQ;GAC5B,OAAO;EACT;EACA,QAAQ;CACV,CAAC,GAAG,EAKF,UAAU,CAAC;EACT,MAAM,EAAE,MAAM,OAAgB;EAC9B,UAAU;EACV,MAAM,EACJ,eAAe;GACb,MAAME,EAAQ,QAAQ,QAAQ;GAC9B,SAASA,EAAQ,QAAQ;EAC3B,GACF;CACF,CAAC,EACH,CAAC,GACH,CAACA,CAAO,CACV;AACF"}
@@ -3,16 +3,16 @@ import t from "../../../icons/LassoIcon.js";
3
3
  import { createElement as n, useMemo as r } from "react";
4
4
  import { useLatest as i } from "@weasel-js/react";
5
5
  //#region src/tools/builtin/lasso/useLassoTool.ts
6
- function a(a, o = {}) {
7
- let s = i({
8
- mode: o.mode ?? "intersect",
9
- ...o.minVertexSpacing === void 0 ? {} : { minVertexSpacing: o.minVertexSpacing }
10
- }), { behaviors: c } = o;
6
+ function a(a = {}) {
7
+ let o = i({
8
+ mode: a.mode ?? "intersect",
9
+ ...a.minVertexSpacing === void 0 ? {} : { minVertexSpacing: a.minVertexSpacing }
10
+ }), { behaviors: s } = a;
11
11
  return r(() => e({
12
12
  id: "lasso",
13
13
  capabilities: ["creates-selection"],
14
14
  hookName: "useLassoTool",
15
- ...o.keybinding === null ? {} : { keybinding: o.keybinding ?? { key: "L" } },
15
+ ...a.keybinding === null ? {} : { keybinding: a.keybinding ?? { key: "L" } },
16
16
  cursor: "crosshair",
17
17
  presentation: {
18
18
  label: "Lasso",
@@ -26,14 +26,14 @@ function a(a, o = {}) {
26
26
  },
27
27
  actionId: "lassoSelect",
28
28
  opts: {
29
- params: () => s.current,
30
- ...c ? { behaviors: c } : {}
29
+ params: () => o.current,
30
+ ...s ? { behaviors: s } : {}
31
31
  }
32
32
  }]
33
33
  }), [
34
- o.keybinding,
35
- c,
36
- s
34
+ a.keybinding,
35
+ s,
36
+ o
37
37
  ]);
38
38
  }
39
39
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useLassoTool.js","names":["LassoIcon","useLassoTool","paramsRef","useLatest","options","useMemo","defineTool","createElement","behaviors"],"sources":["../../../../src/tools/builtin/lasso/useLassoTool.ts"],"sourcesContent":["import { useMemo, createElement } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport { LassoIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport type { UseLassoSelectOptions } from 'interactions/actions/lasso-select/options';\nimport type { LassoHitMode, LassoSelectAdapter } from 'core/adapters/types';\nimport type { ToolKeybinding } from '@weasel-js/routing';\n\n/** Options for `useLassoTool` — the lasso-select action's options plus the\n * tool's own hit mode and activation key. */\nexport interface UseLassoToolOptions extends UseLassoSelectOptions {\n /** Hit mode for the action's own selection commit, which runs when no\n * behavior claims the gesture. A behavior carries its own, as\n * `selectFromLasso({ mode })` does. Default 'intersect'. */\n mode?: LassoHitMode;\n /** Override the default keybinding (`{ key: 'L' }`). Pass `null` to omit. */\n keybinding?: ToolKeybinding | null;\n}\n\n/** Free-form polygon select Tool. Drag is handled entirely by the gesture\n * dispatcher via the `lassoSelect` action binding below; the dispatcher\n * overlay layer (`useDispatcherOverlayLayer`) paints the live polyline +\n * dashed close-line while the gesture is in flight. Esc cancels through\n * the dispatcher's standard cancel pipeline.\n *\n * The legacy `useLassoSelect` hook is removed — all gesture\n * state, overlay rendering, and selection commit live in\n * `lassoSelectAction` (see `src/interactions/actions/defaults/lassoSelect.ts`). */\nexport function useLassoTool(\n _adapter: LassoSelectAdapter,\n options: UseLassoToolOptions = {},\n): Tool<undefined> {\n const paramsRef = useLatest<{ mode: LassoHitMode; minVertexSpacing?: number }>({\n mode: options.mode ?? 'intersect',\n ...(options.minVertexSpacing !== undefined ? { minVertexSpacing: options.minVertexSpacing } : {}),\n });\n const { behaviors } = options;\n\n return useMemo(() => {\n return defineTool<undefined>({\n id: 'lasso',\n capabilities: ['creates-selection'],\n hookName: 'useLassoTool',\n ...(options.keybinding === null ? {} : { keybinding: options.keybinding ?? { key: 'L' } }),\n cursor: 'crosshair',\n presentation: {\n label: 'Lasso',\n icon: createElement(LassoIcon),\n group: 'select',\n },\n // Declarative drag binding for the new gesture dispatcher. The\n // dispatcher invokes `lassoSelectAction`, which owns vertex buffering,\n // overlay state, and the commit-on-end selection write.\n bindings: [\n {\n spec: { kind: 'drag', mods: { shift: 'optional' } },\n actionId: 'lassoSelect',\n // Thunked so a mode or spacing change reaches the next gesture\n // without rebuilding the tool.\n opts: {\n params: () => paramsRef.current,\n ...(behaviors ? { behaviors } : {}),\n },\n },\n ],\n });\n }, [options.keybinding, behaviors, paramsRef]);\n}\n"],"mappings":";;;;;AA6BA,SAAgBC,EACd,GACA,IAA+B,CAAC,GACf;CACjB,IAAMC,IAAYC,EAA6D;EAC7E,MAAMC,EAAQ,QAAQ;EACtB,GAAIA,EAAQ,qBAAqB,KAAA,IAA6D,CAAC,IAAlD,EAAE,kBAAkBA,EAAQ,iBAAiB;CAC5F,CAAC,GACK,EAAE,iBAAcA;CAEtB,OAAOC,QACEC,EAAsB;EAC3B,IAAI;EACJ,cAAc,CAAC,mBAAmB;EAClC,UAAU;EACV,GAAIF,EAAQ,eAAe,OAAO,CAAC,IAAI,EAAE,YAAYA,EAAQ,cAAc,EAAE,KAAK,IAAI,EAAE;EACxF,QAAQ;EACR,cAAc;GACZ,OAAO;GACP,MAAMG,EAAcP,CAAS;GAC7B,OAAO;EACT;EAIA,UAAU,CACR;GACE,MAAM;IAAE,MAAM;IAAQ,MAAM,EAAE,OAAO,WAAW;GAAE;GAClD,UAAU;GAGV,MAAM;IACJ,cAAcE,EAAU;IACxB,GAAIM,IAAY,EAAE,aAAU,IAAI,CAAC;GACnC;EACF,CACF;CACF,CAAC,GACA;EAACJ,EAAQ;EAAYI;EAAWN;CAAS,CAAC;AAC/C"}
1
+ {"version":3,"file":"useLassoTool.js","names":["LassoIcon","useLassoTool","paramsRef","useLatest","options","useMemo","defineTool","createElement","behaviors"],"sources":["../../../../src/tools/builtin/lasso/useLassoTool.ts"],"sourcesContent":["import { useMemo, createElement } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport { LassoIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport type { UseLassoSelectOptions } from 'interactions/actions/lasso-select/options';\nimport type { LassoHitMode } from 'core/adapters/types';\nimport type { ToolKeybinding } from '@weasel-js/routing';\n\n/** Options for `useLassoTool` — the lasso-select action's options plus the\n * tool's own hit mode and activation key. */\nexport interface UseLassoToolOptions extends UseLassoSelectOptions {\n /** Hit mode for the action's own selection commit, which runs when no\n * behavior claims the gesture. A behavior carries its own, as\n * `selectFromLasso({ mode })` does. Default 'intersect'. */\n mode?: LassoHitMode;\n /** Override the default keybinding (`{ key: 'L' }`). Pass `null` to omit. */\n keybinding?: ToolKeybinding | null;\n}\n\n/** Free-form polygon select Tool. Drag is handled entirely by the gesture\n * dispatcher via the `lassoSelect` action binding below; the dispatcher\n * overlay layer (`useDispatcherOverlayLayer`) paints the live polyline +\n * dashed close-line while the gesture is in flight. Esc cancels through\n * the dispatcher's standard cancel pipeline.\n *\n * The legacy `useLassoSelect` hook is removed — all gesture\n * state, overlay rendering, and selection commit live in\n * `lassoSelectAction` (see `src/interactions/actions/defaults/lassoSelect.ts`). */\nexport function useLassoTool(options: UseLassoToolOptions = {}): Tool<undefined> {\n const paramsRef = useLatest<{ mode: LassoHitMode; minVertexSpacing?: number }>({\n mode: options.mode ?? 'intersect',\n ...(options.minVertexSpacing !== undefined ? { minVertexSpacing: options.minVertexSpacing } : {}),\n });\n const { behaviors } = options;\n\n return useMemo(() => {\n return defineTool<undefined>({\n id: 'lasso',\n capabilities: ['creates-selection'],\n hookName: 'useLassoTool',\n ...(options.keybinding === null ? {} : { keybinding: options.keybinding ?? { key: 'L' } }),\n cursor: 'crosshair',\n presentation: {\n label: 'Lasso',\n icon: createElement(LassoIcon),\n group: 'select',\n },\n // Declarative drag binding for the new gesture dispatcher. The\n // dispatcher invokes `lassoSelectAction`, which owns vertex buffering,\n // overlay state, and the commit-on-end selection write.\n bindings: [\n {\n spec: { kind: 'drag', mods: { shift: 'optional' } },\n actionId: 'lassoSelect',\n // Thunked so a mode or spacing change reaches the next gesture\n // without rebuilding the tool.\n opts: {\n params: () => paramsRef.current,\n ...(behaviors ? { behaviors } : {}),\n },\n },\n ],\n });\n }, [options.keybinding, behaviors, paramsRef]);\n}\n"],"mappings":";;;;;AA6BA,SAAgBC,EAAa,IAA+B,CAAC,GAAoB;CAC/E,IAAMC,IAAYC,EAA6D;EAC7E,MAAMC,EAAQ,QAAQ;EACtB,GAAIA,EAAQ,qBAAqB,KAAA,IAA6D,CAAC,IAAlD,EAAE,kBAAkBA,EAAQ,iBAAiB;CAC5F,CAAC,GACK,EAAE,iBAAcA;CAEtB,OAAOC,QACEC,EAAsB;EAC3B,IAAI;EACJ,cAAc,CAAC,mBAAmB;EAClC,UAAU;EACV,GAAIF,EAAQ,eAAe,OAAO,CAAC,IAAI,EAAE,YAAYA,EAAQ,cAAc,EAAE,KAAK,IAAI,EAAE;EACxF,QAAQ;EACR,cAAc;GACZ,OAAO;GACP,MAAMG,EAAcP,CAAS;GAC7B,OAAO;EACT;EAIA,UAAU,CACR;GACE,MAAM;IAAE,MAAM;IAAQ,MAAM,EAAE,OAAO,WAAW;GAAE;GAClD,UAAU;GAGV,MAAM;IACJ,cAAcE,EAAU;IACxB,GAAIM,IAAY,EAAE,aAAU,IAAI,CAAC;GACnC;EACF,CACF;CACF,CAAC,GACA;EAACJ,EAAQ;EAAYI;EAAWN;CAAS,CAAC;AAC/C"}
@@ -9,6 +9,7 @@ function o(o = {}) {
9
9
  let { behaviors: s } = o;
10
10
  return r(() => e({
11
11
  id: "line",
12
+ keybinding: { key: "\\" },
12
13
  capabilities: ["creates-shapes"],
13
14
  hookName: "useLineTool",
14
15
  cursor: a("crosshairLine", { fallback: "crosshair" }),