@weasel-js/labkit 1.7.0 → 1.7.1

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 (208) hide show
  1. package/README.md +3 -3
  2. package/dist/_dts/{CanvasStackContext-D2jnIwfk.d.ts → CanvasStackContext-Cjy6I-Iv.d.ts} +4 -1
  3. package/dist/_dts/{Stage-CCWfQQWM.d.ts → Stage-D6t7o0pF.d.ts} +3 -2
  4. package/dist/_dts/{index-CsYqUHD3.d.ts → index-BTmaRy6a.d.ts} +10 -6
  5. package/dist/_dts/{types-CSm9jgol.d.ts → index-DCMA4Fy1.d.ts} +59 -113
  6. package/dist/_dts/{types-CRPSGFAp.d.ts → types-BUBSIZuV.d.ts} +8 -7
  7. package/dist/_dts/{useTrialState-CTZPgeZ7.d.ts → useTrialState-Bh8bzFgE.d.ts} +1 -1
  8. package/dist/canvas/index.d.ts +8 -6
  9. package/dist/canvas/index.js +6 -6
  10. package/dist/chrome/index.d.ts +7 -5
  11. package/dist/chrome/index.js +10 -9
  12. package/dist/chunk-2ES4W47N.js +8 -0
  13. package/dist/chunk-2ES4W47N.js.map +1 -0
  14. package/dist/{chunk-WPLAANH4.js → chunk-2N7UBSS2.js} +12 -12
  15. package/dist/chunk-2N7UBSS2.js.map +1 -0
  16. package/dist/chunk-4KSC7NXL.js +15491 -0
  17. package/dist/chunk-4KSC7NXL.js.map +1 -0
  18. package/dist/{chunk-7BO7HNGF.js → chunk-CEGFXTBD.js} +8 -61
  19. package/dist/chunk-CEGFXTBD.js.map +1 -0
  20. package/dist/{chunk-275JRRVD.js → chunk-E23Q6A3Y.js} +232 -37
  21. package/dist/chunk-E23Q6A3Y.js.map +1 -0
  22. package/dist/{chunk-GOZLNM4L.js → chunk-E6NARGU7.js} +5 -5
  23. package/dist/{chunk-GOZLNM4L.js.map → chunk-E6NARGU7.js.map} +1 -1
  24. package/dist/{chunk-IJJUK4FU.js → chunk-EESJUSYR.js} +5 -6
  25. package/dist/chunk-EESJUSYR.js.map +1 -0
  26. package/dist/{chunk-HXXTULDN.js → chunk-EFXRM6XQ.js} +8 -11
  27. package/dist/chunk-EFXRM6XQ.js.map +1 -0
  28. package/dist/chunk-F4ACIK7Z.js +210 -0
  29. package/dist/chunk-F4ACIK7Z.js.map +1 -0
  30. package/dist/{chunk-FMK7UQ6V.js → chunk-FB4MIZOO.js} +61 -44
  31. package/dist/chunk-FB4MIZOO.js.map +1 -0
  32. package/dist/{chunk-AWQG7FCC.js → chunk-FG3EXZDV.js} +3 -3
  33. package/dist/{chunk-AWQG7FCC.js.map → chunk-FG3EXZDV.js.map} +1 -1
  34. package/dist/{chunk-I5DUQ5HM.js → chunk-GAHELLJT.js} +75 -72
  35. package/dist/chunk-GAHELLJT.js.map +1 -0
  36. package/dist/{chunk-YT75VYRD.js → chunk-IBVRMHW5.js} +5 -5
  37. package/dist/{chunk-YT75VYRD.js.map → chunk-IBVRMHW5.js.map} +1 -1
  38. package/dist/{chunk-T5IBSPAM.js → chunk-JFOJESJF.js} +33 -23
  39. package/dist/chunk-JFOJESJF.js.map +1 -0
  40. package/dist/{chunk-RWNDDKOH.js → chunk-PMLZP7RT.js} +18 -15
  41. package/dist/chunk-PMLZP7RT.js.map +1 -0
  42. package/dist/{chunk-Y23G2VZL.js → chunk-READTDQX.js} +2 -2
  43. package/dist/chunk-READTDQX.js.map +1 -0
  44. package/dist/{chunk-JVBYV6TL.js → chunk-ROGJWDQA.js} +3 -3
  45. package/dist/{chunk-JVBYV6TL.js.map → chunk-ROGJWDQA.js.map} +1 -1
  46. package/dist/{chunk-ZIFPHIWZ.js → chunk-T6DLGEJB.js} +12 -14
  47. package/dist/chunk-T6DLGEJB.js.map +1 -0
  48. package/dist/{chunk-24W5VEJW.js → chunk-ULYYNWGP.js} +2 -2
  49. package/dist/{chunk-24W5VEJW.js.map → chunk-ULYYNWGP.js.map} +1 -1
  50. package/dist/{chunk-UNAZSLWE.js → chunk-VYVGVBGY.js} +17 -20
  51. package/dist/chunk-VYVGVBGY.js.map +1 -0
  52. package/dist/{chunk-KMJ7RWD3.js → chunk-WLMDTI2Q.js} +3 -3
  53. package/dist/{chunk-KMJ7RWD3.js.map → chunk-WLMDTI2Q.js.map} +1 -1
  54. package/dist/{chunk-J7OWWTCW.js → chunk-XE5HJOPL.js} +5 -6
  55. package/dist/chunk-XE5HJOPL.js.map +1 -0
  56. package/dist/chunk-XVUKDSYV.js +38 -0
  57. package/dist/chunk-XVUKDSYV.js.map +1 -0
  58. package/dist/{chunk-FZ7YFQN7.js → chunk-YCFKW5RX.js} +3 -3
  59. package/dist/chunk-YCFKW5RX.js.map +1 -0
  60. package/dist/{chunk-CQLQPQ4P.js → chunk-ZQIHJXP4.js} +2 -2
  61. package/dist/chunk-ZQIHJXP4.js.map +1 -0
  62. package/dist/config/index.d.ts +18 -10
  63. package/dist/config/index.js +4 -4
  64. package/dist/controls/index.d.ts +4 -7
  65. package/dist/controls/index.js +6 -5
  66. package/dist/dragdrop/index.d.ts +23 -3
  67. package/dist/dragdrop/index.js +4 -3
  68. package/dist/fonts/oswald-tabular-digits.woff2 +0 -0
  69. package/dist/index.d.ts +60 -714
  70. package/dist/index.js +357 -334
  71. package/dist/index.js.map +1 -1
  72. package/dist/job/index.d.ts +8 -0
  73. package/dist/job/index.js +1 -1
  74. package/dist/layers/index.d.ts +6 -5
  75. package/dist/layers/index.js +3 -2
  76. package/dist/loupe/index.d.ts +100 -30
  77. package/dist/loupe/index.js +585 -6
  78. package/dist/loupe/index.js.map +1 -1
  79. package/dist/overview/index.d.ts +4 -2
  80. package/dist/overview/index.js +15 -14
  81. package/dist/overview/index.js.map +1 -1
  82. package/dist/passthrough/weasel-canvas.d.ts +2 -0
  83. package/dist/passthrough/weasel-ui.d.ts +2 -2871
  84. package/dist/passthrough/weasel-ui.js +3 -2
  85. package/dist/primitives/index.d.ts +213 -3
  86. package/dist/primitives/index.js +8 -7
  87. package/dist/state/index.d.ts +7 -5
  88. package/dist/state/index.js +6 -6
  89. package/dist/styles.css +60 -44
  90. package/dist/surface/index.d.ts +10 -2
  91. package/dist/surface/index.js +1 -1
  92. package/dist/undo/index.d.ts +5 -3
  93. package/package.json +11 -11
  94. package/src/annotations/AnnotationOverlay.abandon.test.tsx +143 -0
  95. package/src/annotations/AnnotationOverlay.tsx +50 -31
  96. package/src/annotations/Annotations.overlay.test.tsx +31 -0
  97. package/src/annotations/capture.browser.test.ts +41 -0
  98. package/src/annotations/capture.ts +14 -7
  99. package/src/annotations/drawOne.ts +2 -2
  100. package/src/annotations/frac.test.ts +44 -1
  101. package/src/annotations/frac.ts +46 -18
  102. package/src/annotations/index.ts +1 -0
  103. package/src/annotations/paint.test.ts +74 -33
  104. package/src/annotations/paint.ts +70 -32
  105. package/src/annotations/store.test.ts +212 -2
  106. package/src/annotations/store.ts +130 -27
  107. package/src/annotations/svgNodes.test.ts +22 -10
  108. package/src/annotations/svgNodes.ts +3 -3
  109. package/src/annotations/types.ts +29 -10
  110. package/src/canvas/CameraInput.test.tsx +30 -0
  111. package/src/canvas/CameraInput.tsx +16 -15
  112. package/src/canvas/CanvasStack.tsx +5 -5
  113. package/src/canvas/CanvasStackContext.ts +4 -1
  114. package/src/canvas/Stage.tsx +3 -3
  115. package/src/canvas/cameraRegistry.ts +1 -0
  116. package/src/canvas/worldSpec.ts +3 -1
  117. package/src/chrome/builtins.test.ts +7 -6
  118. package/src/chrome/builtins.tsx +5 -1
  119. package/src/chrome/index.ts +1 -1
  120. package/src/chrome/merge.test.ts +5 -0
  121. package/src/chrome/merge.ts +4 -2
  122. package/src/chrome/regions/PaletteRegion.test.tsx +2 -3
  123. package/src/chrome/regions/PaletteRegion.tsx +3 -4
  124. package/src/chrome/regions/ViewportRegion.browser.test.less +6 -0
  125. package/src/chrome/regions/ViewportRegion.browser.test.tsx +38 -0
  126. package/src/chrome/regions/ViewportRegion.less +6 -0
  127. package/src/chrome/regions/ViewportRegion.tsx +10 -4
  128. package/src/chrome/types.ts +4 -2
  129. package/src/config/auto.ts +1 -0
  130. package/src/config/builder.ts +6 -0
  131. package/src/config/types.ts +2 -1
  132. package/src/controls/ControlPanel.test.tsx +37 -3
  133. package/src/controls/ControlPanel.tsx +12 -3
  134. package/src/dragdrop/DragDropRuntime.tsx +22 -13
  135. package/src/dragdrop/DragGhost.tsx +3 -0
  136. package/src/dragdrop/Palette.tsx +2 -0
  137. package/src/index.test.ts +5 -0
  138. package/src/index.ts +1 -1
  139. package/src/instrument/types.ts +0 -6
  140. package/src/job/useJob.ts +14 -9
  141. package/src/lab/Lab.tsx +5 -1
  142. package/src/lab/LabShell.less +1 -0
  143. package/src/lab/LabSwitcher.browser.test.tsx +27 -0
  144. package/src/lab/LabSwitcher.less +2 -0
  145. package/src/lab/LabZoom.tsx +4 -4
  146. package/src/lab/Workspace.tsx +48 -52
  147. package/src/loupe/AGENTS.md +28 -15
  148. package/src/loupe/CanvasLoupe.tsx +2 -3
  149. package/src/loupe/DomLoupe.tsx +1 -7
  150. package/src/loupe/Loupe.less +16 -0
  151. package/src/loupe/TrialLoupe.tsx +120 -57
  152. package/src/loupe/index.ts +1 -6
  153. package/src/loupe/types.test.ts +3 -3
  154. package/src/loupe/types.ts +24 -27
  155. package/src/loupe/useLoupe.test.tsx +29 -4
  156. package/src/loupe/useLoupe.ts +20 -17
  157. package/src/overview/OverviewMarks.tsx +12 -4
  158. package/src/overview/TrialOverview.tsx +3 -3
  159. package/src/passthrough/weasel-ui.test.ts +1 -1
  160. package/src/passthrough/weasel-ui.ts +1 -1
  161. package/src/primitives/FloatingPanel.tsx +7 -3
  162. package/src/primitives/JobProgress.less +1 -0
  163. package/src/primitives/Readout.test.tsx +2 -2
  164. package/src/primitives/Split.tsx +69 -41
  165. package/src/primitives/Toolbar.tsx +3 -3
  166. package/src/primitives/ZoomControl.less +1 -2
  167. package/src/specimen/Specimen.tsx +0 -1
  168. package/src/state/undock.ts +3 -0
  169. package/src/state/useOpenOnce.ts +20 -16
  170. package/src/state/view.ts +1 -0
  171. package/src/surface/index.ts +1 -1
  172. package/src/surface/useTiledSurface.test.tsx +14 -0
  173. package/src/surface/useTiledSurface.ts +11 -3
  174. package/src/trial/Trial.annotations.test.tsx +73 -0
  175. package/src/trial/Trial.less +0 -16
  176. package/src/trial/Trial.loupe.test.tsx +28 -11
  177. package/src/trial/Trial.tsx +74 -62
  178. package/src/trial/TrialChrome.tsx +6 -3
  179. package/src/trial/index.ts +2 -0
  180. package/src/trial/loupeSwitch.ts +15 -0
  181. package/dist/_dts/LayerList.d-DiuEArKq.d.ts +0 -83
  182. package/dist/_dts/PrefsRow.d-TOZ7BgD9.d.ts +0 -79
  183. package/dist/_dts/PropertyPanel.d-D-1paCbE.d.ts +0 -141
  184. package/dist/_dts/Select.d-Bensr_MT.d.ts +0 -579
  185. package/dist/_dts/index-B2Yj5aA0.d.ts +0 -274
  186. package/dist/chunk-275JRRVD.js.map +0 -1
  187. package/dist/chunk-4LJSC7MB.js +0 -143
  188. package/dist/chunk-4LJSC7MB.js.map +0 -1
  189. package/dist/chunk-7BO7HNGF.js.map +0 -1
  190. package/dist/chunk-CQLQPQ4P.js.map +0 -1
  191. package/dist/chunk-FMK7UQ6V.js.map +0 -1
  192. package/dist/chunk-FZ7YFQN7.js.map +0 -1
  193. package/dist/chunk-HXXTULDN.js.map +0 -1
  194. package/dist/chunk-I5DUQ5HM.js.map +0 -1
  195. package/dist/chunk-IJJUK4FU.js.map +0 -1
  196. package/dist/chunk-J7OWWTCW.js.map +0 -1
  197. package/dist/chunk-M7HP3FTK.js +0 -549
  198. package/dist/chunk-M7HP3FTK.js.map +0 -1
  199. package/dist/chunk-MIM5R4ZT.js +0 -14972
  200. package/dist/chunk-MIM5R4ZT.js.map +0 -1
  201. package/dist/chunk-RWNDDKOH.js.map +0 -1
  202. package/dist/chunk-T5IBSPAM.js.map +0 -1
  203. package/dist/chunk-UNAZSLWE.js.map +0 -1
  204. package/dist/chunk-WPLAANH4.js.map +0 -1
  205. package/dist/chunk-Y23G2VZL.js.map +0 -1
  206. package/dist/chunk-ZIFPHIWZ.js.map +0 -1
  207. package/src/primitives/useRovingTabIndex.test.ts +0 -48
  208. package/src/primitives/useRovingTabIndex.ts +0 -88
@@ -1,9 +1,10 @@
1
- import { screenToWorld } from './chunk-AWQG7FCC.js';
2
- import { resolveFrame } from './chunk-24W5VEJW.js';
1
+ import { screenToWorld } from './chunk-FG3EXZDV.js';
2
+ import { resolveFrame } from './chunk-ULYYNWGP.js';
3
+ import { boxContainsPoint } from './chunk-XVUKDSYV.js';
3
4
  import { useState, useEffect, useRef, useCallback } from 'react';
4
5
  import { createPortal } from 'react-dom';
5
6
  import { jsx } from 'react/jsx-runtime';
6
- import { useVisibleRaf, openPointerSession } from '@weasel-js/core';
7
+ import { useLatest, useVisibleRaf, openPointerSession } from '@weasel-js/core';
7
8
 
8
9
  function DragGhost({ item, screenPos }) {
9
10
  const [mounted, setMounted] = useState(false);
@@ -30,17 +31,15 @@ function useDragDrop({
30
31
  }) {
31
32
  const [drag, setDrag] = useState(null);
32
33
  const dragRef = useRef(null);
33
- dragRef.current = drag;
34
34
  const pendingPos = useRef(null);
35
35
  const sessionRef = useRef(null);
36
- const liveRef = useRef({ capability, state, config, setState, emit, view, worldSpec });
37
- liveRef.current = { capability, state, config, setState, emit, view, worldSpec };
36
+ const liveRef = useLatest({ capability, state, config, setState, emit, view, worldSpec });
38
37
  const isOverCanvas = useCallback(
39
38
  (screenPos) => {
40
39
  const el = canvasContainerRef.current;
41
40
  if (!el) return false;
42
41
  const r = el.getBoundingClientRect();
43
- return screenPos.x >= r.left && screenPos.x <= r.right && screenPos.y >= r.top && screenPos.y <= r.bottom;
42
+ return boxContainsPoint([r.left, r.top, r.right, r.bottom], screenPos.x, screenPos.y);
44
43
  },
45
44
  [canvasContainerRef]
46
45
  );
@@ -56,7 +55,7 @@ function useDragDrop({
56
55
  frame
57
56
  );
58
57
  },
59
- [canvasContainerRef]
58
+ [canvasContainerRef, liveRef]
60
59
  );
61
60
  const frameLoop = useVisibleRaf(() => {
62
61
  const screenPos = pendingPos.current;
@@ -69,7 +68,8 @@ function useDragDrop({
69
68
  const world = screenToWorldFromContainer(screenPos);
70
69
  if (world) feedback = live.capability.onDragOver(world, active.item, live.state, live.config);
71
70
  }
72
- setDrag({ ...active, screenPos, feedback });
71
+ dragRef.current = { ...active, screenPos, feedback };
72
+ setDrag(dragRef.current);
73
73
  });
74
74
  const clearDrag = useCallback(() => {
75
75
  pendingPos.current = null;
@@ -113,7 +113,7 @@ function useDragDrop({
113
113
  onCancel: clearDrag
114
114
  });
115
115
  },
116
- [clearDrag, frameLoop, isOverCanvas, screenToWorldFromContainer]
116
+ [clearDrag, frameLoop, isOverCanvas, liveRef, screenToWorldFromContainer]
117
117
  );
118
118
  useEffect(() => () => sessionRef.current?.cancel(), []);
119
119
  return { drag, startDrag };
@@ -139,5 +139,5 @@ function Palette({ items, onDragStart, className }) {
139
139
  }
140
140
 
141
141
  export { DragGhost, DragOverlay, Palette, useDragDrop };
142
- //# sourceMappingURL=chunk-WPLAANH4.js.map
143
- //# sourceMappingURL=chunk-WPLAANH4.js.map
142
+ //# sourceMappingURL=chunk-2N7UBSS2.js.map
143
+ //# sourceMappingURL=chunk-2N7UBSS2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dragdrop/DragGhost.tsx","../src/dragdrop/DragDropRuntime.tsx","../src/dragdrop/Palette.tsx"],"names":["useState","useEffect","jsx"],"mappings":"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","file":"chunk-2N7UBSS2.js","sourcesContent":["import { type ReactPortal, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { PaletteItem, Point } from '../instrument/types';\n\n/** Props for `DragGhost`. `screenPos` is in client pixels. */\nexport interface DragGhostProps {\n item: PaletteItem;\n screenPos: Point;\n}\n\n/** The dragged item's label, portaled to `document.body` just below-right of\n * `screenPos`. Renders nothing until mounted, so it is SSR-safe. */\nexport function DragGhost({ item, screenPos }: DragGhostProps): ReactPortal | null {\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n if (!mounted || typeof document === 'undefined') return null;\n const style = {\n left: `${screenPos.x + 12}px`,\n top: `${screenPos.y + 12}px`,\n };\n return createPortal(\n <div className=\"lk-drag-ghost\" style={style}>\n <span className=\"lk-drag-ghost__label\">{item.label}</span>\n </div>,\n document.body,\n );\n}\n","import { openPointerSession, type PointerSession, useLatest, useVisibleRaf } from '@weasel-js/core';\nimport { boxContainsPoint } from '@weasel-js/geom';\nimport {\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { screenToWorld } from '../canvas/canvasCoords';\nimport { resolveFrame, type WorldSpec } from '../canvas/worldSpec';\nimport type {\n DragDropCapability,\n DragFeedback,\n PaletteItem,\n Point,\n ViewTransform,\n} from '../instrument/types';\nimport { DragGhost } from './DragGhost';\n\n/** A palette drag in progress. `screenPos` is in client pixels; `feedback` is\n * the last `onDragOver` answer — `null` off the canvas or without one. */\nexport interface DragState {\n item: PaletteItem;\n screenPos: Point;\n feedback: DragFeedback | null;\n}\n\n/** Inputs to `useDragDrop`: the capability, the element that counts as the\n * drop target, and the trial state a drop rewrites. */\nexport interface UseDragDropArgs<TS, TC> {\n capability: DragDropCapability<TS, TC>;\n canvasContainerRef: RefObject<HTMLElement | null>;\n view: ViewTransform;\n /** The instrument's coordinate system, resolved against the container each\n * time a screen point is converted — the container is what knows its size. */\n worldSpec?: WorldSpec;\n state: TS;\n config: TC;\n setState: (next: TS | ((prev: TS) => TS)) => void;\n emit: (event: string) => void;\n}\n\n/** The live drag, and the handler a palette item calls on pointerdown. */\nexport interface UseDragDropResult {\n drag: DragState | null;\n startDrag: (item: PaletteItem, e: ReactPointerEvent) => void;\n}\n\n/**\n * Run palette-to-canvas drags for a `DragDropCapability`. Releasing over the\n * container converts the pointer to world coordinates, applies `onDrop`'s\n * state and emits `'canvas.itemAdded'`; releasing anywhere else, or a canceled\n * gesture, drops nothing. `onDragOver` is probed at most once per frame.\n */\nexport function useDragDrop<TS, TC>({\n capability,\n canvasContainerRef,\n view,\n state,\n config,\n setState,\n emit,\n worldSpec,\n}: UseDragDropArgs<TS, TC>): UseDragDropResult {\n const [drag, setDrag] = useState<DragState | null>(null);\n // Owned by the handlers below, which write it alongside every `setDrag`.\n const dragRef = useRef<DragState | null>(null);\n /** The move the next frame will resolve. Doubles as the throttle's flag:\n * non-null means a frame is already queued. */\n const pendingPos = useRef<Point | null>(null);\n const sessionRef = useRef<PointerSession | null>(null);\n\n /** A session keeps the closure it was opened with, so everything the drop\n * reads has to come from here rather than from that closure. */\n const liveRef = useLatest({ capability, state, config, setState, emit, view, worldSpec });\n\n const isOverCanvas = useCallback(\n (screenPos: Point): boolean => {\n const el = canvasContainerRef.current;\n if (!el) return false;\n const r = el.getBoundingClientRect();\n return boxContainsPoint([r.left, r.top, r.right, r.bottom], screenPos.x, screenPos.y);\n },\n [canvasContainerRef],\n );\n\n const screenToWorldFromContainer = useCallback(\n (screenPos: Point): Point | null => {\n const el = canvasContainerRef.current;\n if (!el) return null;\n const r = el.getBoundingClientRect();\n const frame = resolveFrame(liveRef.current.worldSpec, { width: r.width, height: r.height });\n return screenToWorld(\n { x: screenPos.x - r.left, y: screenPos.y - r.top },\n liveRef.current.view,\n frame,\n );\n },\n [canvasContainerRef, liveRef],\n );\n\n const frameLoop = useVisibleRaf(() => {\n const screenPos = pendingPos.current;\n pendingPos.current = null;\n const active = dragRef.current;\n if (!active || !screenPos) return;\n const live = liveRef.current;\n let feedback: DragFeedback | null = null;\n if (live.capability.onDragOver && isOverCanvas(screenPos)) {\n const world = screenToWorldFromContainer(screenPos);\n if (world) feedback = live.capability.onDragOver(world, active.item, live.state, live.config);\n }\n dragRef.current = { ...active, screenPos, feedback };\n setDrag(dragRef.current);\n });\n\n const clearDrag = useCallback(() => {\n pendingPos.current = null;\n frameLoop.cancel();\n sessionRef.current = null;\n dragRef.current = null;\n setDrag(null);\n }, [frameLoop]);\n\n const startDrag = useCallback(\n (item: PaletteItem, e: ReactPointerEvent) => {\n if (sessionRef.current) return;\n const next: DragState = { item, screenPos: { x: e.clientX, y: e.clientY }, feedback: null };\n dragRef.current = next;\n setDrag(next);\n sessionRef.current = openPointerSession(e.currentTarget, e, {\n onMove: (ev) => {\n const screenPos = { x: ev.clientX, y: ev.clientY };\n const current = dragRef.current;\n if (!current) return;\n if (pendingPos.current !== null) {\n // A frame is already queued: keep the ghost under the cursor and\n // let that frame probe the drop target from the newest position.\n pendingPos.current = screenPos;\n dragRef.current = { ...current, screenPos };\n setDrag(dragRef.current);\n return;\n }\n pendingPos.current = screenPos;\n frameLoop.request();\n },\n onEnd: (ev) => {\n const screenPos = { x: ev.clientX, y: ev.clientY };\n const active = dragRef.current;\n clearDrag();\n if (!active || !isOverCanvas(screenPos)) return;\n const world = screenToWorldFromContainer(screenPos);\n if (!world) return;\n const live = liveRef.current;\n live.setState(live.capability.onDrop(world, active.item, live.state, live.config));\n live.emit('canvas.itemAdded');\n },\n // An interrupted gesture never named a destination, so it drops nothing.\n onCancel: clearDrag,\n });\n },\n [clearDrag, frameLoop, isOverCanvas, liveRef, screenToWorldFromContainer],\n );\n\n useEffect(() => () => sessionRef.current?.cancel(), []);\n\n return { drag, startDrag };\n}\n\n/** Props for `DragOverlay`. */\nexport interface DragOverlayProps {\n drag: DragState | null;\n}\n\n/** The ghost for `drag`, or nothing when no drag is live. */\nexport function DragOverlay({ drag }: DragOverlayProps) {\n if (!drag) return null;\n return <DragGhost item={drag.item} screenPos={drag.screenPos} />;\n}\n","import type { PointerEvent as ReactPointerEvent } from 'react';\nimport type { PaletteItem } from '../instrument/types';\n\n/** Props for `Palette`. `onDragStart` is usually `useDragDrop`'s `startDrag`. */\nexport interface PaletteProps {\n items: PaletteItem[];\n onDragStart: (item: PaletteItem, e: ReactPointerEvent) => void;\n className?: string;\n}\n\n/** One button per item, each starting a drag on pointerdown. */\nexport function Palette({ items, onDragStart, className }: PaletteProps) {\n return (\n <div className={className ? `lk-palette ${className}` : 'lk-palette'}>\n {items.map((item) => (\n <button\n type=\"button\"\n key={item.id}\n className=\"lk-palette__item\"\n onPointerDown={(e) => {\n e.preventDefault();\n onDragStart(item, e);\n }}\n >\n <span className=\"lk-palette__label\">{item.label}</span>\n </button>\n ))}\n </div>\n );\n}\n"]}