@weasel-js/labkit 1.4.0-pre.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +226 -55
  2. package/dist/_dts/{CanvasStackContext-DtAn_3O-.d.ts → CanvasStackContext-D6M0o8cQ.d.ts} +1 -1
  3. package/dist/_dts/{frac-Cp3NivlC.d.ts → frac-QS7XzvpG.d.ts} +11 -4
  4. package/dist/_dts/{index-BDVzvRzQ.d.ts → index-B2X21G1c.d.ts} +8 -2
  5. package/dist/_dts/{types-D6s4b7if.d.ts → types-C1Zw7s5P.d.ts} +1 -0
  6. package/dist/_dts/{types-DYMaEvM5.d.ts → types-ChVJJHvk.d.ts} +3 -0
  7. package/dist/_dts/{useTrialState-gmMvZqPc.d.ts → useTrialState-Cdm13fvl.d.ts} +2 -1
  8. package/dist/canvas/index.d.ts +75 -9
  9. package/dist/canvas/index.js +2 -2
  10. package/dist/chrome/index.d.ts +4 -4
  11. package/dist/chrome/index.js +5 -5
  12. package/dist/chunk-2YILQ7Y5.js +33 -0
  13. package/dist/chunk-2YILQ7Y5.js.map +1 -0
  14. package/dist/{chunk-3P5TTTA7.js → chunk-4AMN4MMB.js} +5 -5
  15. package/dist/{chunk-3P5TTTA7.js.map → chunk-4AMN4MMB.js.map} +1 -1
  16. package/dist/{chunk-ROQDRXKW.js → chunk-7VW3S44V.js} +621 -51
  17. package/dist/chunk-7VW3S44V.js.map +1 -0
  18. package/dist/{chunk-4EY67BKJ.js → chunk-B5VWJBWM.js} +12 -6
  19. package/dist/chunk-B5VWJBWM.js.map +1 -0
  20. package/dist/{chunk-HEORBLVT.js → chunk-L5WBGUVR.js} +1664 -1628
  21. package/dist/chunk-L5WBGUVR.js.map +1 -0
  22. package/dist/{chunk-XJ6N32QP.js → chunk-LJSIUFYD.js} +14 -30
  23. package/dist/chunk-LJSIUFYD.js.map +1 -0
  24. package/dist/{chunk-6JMU56CU.js → chunk-QR5V3AFG.js} +6 -4
  25. package/dist/chunk-QR5V3AFG.js.map +1 -0
  26. package/dist/{chunk-LITE5YFB.js → chunk-UD7TEHZT.js} +15 -15
  27. package/dist/chunk-UD7TEHZT.js.map +1 -0
  28. package/dist/{chunk-3ZELRRBV.js → chunk-VHFQKAUL.js} +86 -6
  29. package/dist/chunk-VHFQKAUL.js.map +1 -0
  30. package/dist/{chunk-YQJNT4XQ.js → chunk-W3KSUXXR.js} +16 -13
  31. package/dist/chunk-W3KSUXXR.js.map +1 -0
  32. package/dist/{chunk-JDDIZSLL.js → chunk-XCBCZEBO.js} +3 -3
  33. package/dist/{chunk-JDDIZSLL.js.map → chunk-XCBCZEBO.js.map} +1 -1
  34. package/dist/{chunk-EQIB2PGC.js → chunk-Y2HK44TG.js} +3 -3
  35. package/dist/{chunk-EQIB2PGC.js.map → chunk-Y2HK44TG.js.map} +1 -1
  36. package/dist/{chunk-5TCEVMPI.js → chunk-YQGQUBKA.js} +3 -3
  37. package/dist/{chunk-5TCEVMPI.js.map → chunk-YQGQUBKA.js.map} +1 -1
  38. package/dist/controls/index.d.ts +2 -2
  39. package/dist/controls/index.js +3 -3
  40. package/dist/dragdrop/index.d.ts +3 -3
  41. package/dist/dragdrop/index.js +2 -2
  42. package/dist/index.d.ts +57 -59
  43. package/dist/index.js +335 -240
  44. package/dist/index.js.map +1 -1
  45. package/dist/layers/index.d.ts +4 -4
  46. package/dist/layers/index.js +3 -3
  47. package/dist/loupe/index.d.ts +5 -5
  48. package/dist/loupe/index.js +2 -2
  49. package/dist/passthrough/weasel-canvas.js +1 -1
  50. package/dist/passthrough/weasel-ui.d.ts +336 -15
  51. package/dist/passthrough/weasel-ui.js +2 -2
  52. package/dist/primitives/index.js +4 -4
  53. package/dist/state/index.d.ts +3 -3
  54. package/dist/state/index.js +4 -2
  55. package/dist/state/index.js.map +1 -1
  56. package/dist/styles.css +64 -5
  57. package/dist/surface/index.d.ts +17 -2
  58. package/dist/surface/index.js +3 -2
  59. package/dist/ui/layers/index.js +2 -2
  60. package/dist/undo/index.d.ts +3 -3
  61. package/package.json +8 -8
  62. package/src/annotations/AnnotationOverlay.tsx +10 -6
  63. package/src/annotations/Annotations.less +6 -0
  64. package/src/annotations/Annotations.overlay.test.tsx +113 -0
  65. package/src/annotations/MarkList.tsx +3 -2
  66. package/src/annotations/store.test.ts +72 -0
  67. package/src/annotations/store.ts +30 -0
  68. package/src/annotations/types.ts +9 -2
  69. package/src/canvas/index.ts +11 -0
  70. package/src/config/builder.test.ts +5 -0
  71. package/src/config/builder.ts +6 -0
  72. package/src/config/types.ts +1 -0
  73. package/src/controls/ControlPanel.test.tsx +23 -0
  74. package/src/controls/ControlPanel.tsx +3 -0
  75. package/src/index.test.ts +1 -0
  76. package/src/index.ts +13 -9
  77. package/src/lab/Lab.surface.test.tsx +8 -3
  78. package/src/lab/LabHeader.test.tsx +12 -0
  79. package/src/lab/LabHeader.tsx +16 -6
  80. package/src/passthrough/weasel-ui.test.ts +9 -0
  81. package/src/passthrough/weasel-ui.ts +4 -0
  82. package/src/primitives/ZoomControl.tsx +2 -0
  83. package/src/state/store.ts +10 -0
  84. package/src/state/types.ts +3 -0
  85. package/src/surface/AGENTS.md +11 -1
  86. package/src/surface/index.ts +7 -1
  87. package/src/surface/useSurfaceTile.ts +20 -2
  88. package/src/surface/useTiledSurface.ts +4 -1
  89. package/src/theme/Interstellar.stories.tsx +4 -3
  90. package/src/theme/base.less +39 -1
  91. package/src/trial/Trial.less +27 -5
  92. package/src/trial/TrialBody.test.tsx +67 -0
  93. package/src/trial/TrialBody.tsx +155 -0
  94. package/src/trial/TrialChrome.tsx +18 -10
  95. package/src/trial/index.ts +2 -0
  96. package/dist/chunk-3ZELRRBV.js.map +0 -1
  97. package/dist/chunk-4EY67BKJ.js.map +0 -1
  98. package/dist/chunk-6JMU56CU.js.map +0 -1
  99. package/dist/chunk-HEORBLVT.js.map +0 -1
  100. package/dist/chunk-LITE5YFB.js.map +0 -1
  101. package/dist/chunk-ROQDRXKW.js.map +0 -1
  102. package/dist/chunk-XJ6N32QP.js.map +0 -1
  103. package/dist/chunk-YQJNT4XQ.js.map +0 -1
@@ -1 +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-5TCEVMPI.js","sourcesContent":["import { type ReactPortal, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { PaletteItem, Point } from '../instrument/types';\n\nexport interface DragGhostProps {\n item: PaletteItem;\n screenPos: Point;\n}\n\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 { useVisibleRaf } from '@weasel-js/core';\nimport { type RefObject, useCallback, useEffect, useRef, useState } 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\nexport interface DragState {\n item: PaletteItem;\n screenPos: Point;\n feedback: DragFeedback | null;\n}\n\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\nexport interface UseDragDropResult {\n drag: DragState | null;\n startDrag: (item: PaletteItem, originScreenPos: Point) => void;\n}\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 const dragRef = useRef<DragState | null>(null);\n dragRef.current = drag;\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\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 (\n screenPos.x >= r.left &&\n screenPos.x <= r.right &&\n screenPos.y >= r.top &&\n screenPos.y <= r.bottom\n );\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(worldSpec, { width: r.width, height: r.height });\n return screenToWorld({ x: screenPos.x - r.left, y: screenPos.y - r.top }, view, frame);\n },\n [canvasContainerRef, view, worldSpec],\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 let feedback: DragFeedback | null = null;\n if (capability.onDragOver && isOverCanvas(screenPos)) {\n const world = screenToWorldFromContainer(screenPos);\n if (world) feedback = capability.onDragOver(world, active.item, state, config);\n }\n setDrag({ ...active, screenPos, feedback });\n });\n\n useEffect(() => {\n if (!drag) return;\n const handleMove = (e: PointerEvent) => {\n const screenPos = { x: e.clientX, y: e.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 let\n // 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 const handleUp = (e: PointerEvent) => {\n const screenPos = { x: e.clientX, y: e.clientY };\n const active = dragRef.current;\n if (!active) return;\n pendingPos.current = null;\n frameLoop.cancel();\n if (isOverCanvas(screenPos)) {\n const world = screenToWorldFromContainer(screenPos);\n if (world) {\n const nextState = capability.onDrop(world, active.item, state, config);\n setState(nextState);\n emit('canvas.itemAdded');\n }\n }\n setDrag(null);\n };\n window.addEventListener('pointermove', handleMove);\n window.addEventListener('pointerup', handleUp);\n return () => {\n window.removeEventListener('pointermove', handleMove);\n window.removeEventListener('pointerup', handleUp);\n };\n }, [\n drag,\n capability,\n state,\n config,\n setState,\n emit,\n frameLoop,\n isOverCanvas,\n screenToWorldFromContainer,\n ]);\n\n const startDrag = useCallback((item: PaletteItem, originScreenPos: Point) => {\n setDrag({ item, screenPos: originScreenPos, feedback: null });\n }, []);\n\n return { drag, startDrag };\n}\n\nexport interface DragOverlayProps {\n drag: DragState | null;\n}\n\nexport function DragOverlay({ drag }: DragOverlayProps) {\n if (!drag) return null;\n return <DragGhost item={drag.item} screenPos={drag.screenPos} />;\n}\n","import type { PaletteItem, Point } from '../instrument/types';\n\nexport interface PaletteProps {\n items: PaletteItem[];\n onDragStart: (item: PaletteItem, originScreenPos: Point) => void;\n className?: string;\n}\n\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, { x: e.clientX, y: e.clientY });\n }}\n >\n <span className=\"lk-palette__label\">{item.label}</span>\n </button>\n ))}\n </div>\n );\n}\n"]}
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-YQGQUBKA.js","sourcesContent":["import { type ReactPortal, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { PaletteItem, Point } from '../instrument/types';\n\nexport interface DragGhostProps {\n item: PaletteItem;\n screenPos: Point;\n}\n\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 { useVisibleRaf } from '@weasel-js/core';\nimport { type RefObject, useCallback, useEffect, useRef, useState } 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\nexport interface DragState {\n item: PaletteItem;\n screenPos: Point;\n feedback: DragFeedback | null;\n}\n\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\nexport interface UseDragDropResult {\n drag: DragState | null;\n startDrag: (item: PaletteItem, originScreenPos: Point) => void;\n}\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 const dragRef = useRef<DragState | null>(null);\n dragRef.current = drag;\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\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 (\n screenPos.x >= r.left &&\n screenPos.x <= r.right &&\n screenPos.y >= r.top &&\n screenPos.y <= r.bottom\n );\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(worldSpec, { width: r.width, height: r.height });\n return screenToWorld({ x: screenPos.x - r.left, y: screenPos.y - r.top }, view, frame);\n },\n [canvasContainerRef, view, worldSpec],\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 let feedback: DragFeedback | null = null;\n if (capability.onDragOver && isOverCanvas(screenPos)) {\n const world = screenToWorldFromContainer(screenPos);\n if (world) feedback = capability.onDragOver(world, active.item, state, config);\n }\n setDrag({ ...active, screenPos, feedback });\n });\n\n useEffect(() => {\n if (!drag) return;\n const handleMove = (e: PointerEvent) => {\n const screenPos = { x: e.clientX, y: e.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 let\n // 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 const handleUp = (e: PointerEvent) => {\n const screenPos = { x: e.clientX, y: e.clientY };\n const active = dragRef.current;\n if (!active) return;\n pendingPos.current = null;\n frameLoop.cancel();\n if (isOverCanvas(screenPos)) {\n const world = screenToWorldFromContainer(screenPos);\n if (world) {\n const nextState = capability.onDrop(world, active.item, state, config);\n setState(nextState);\n emit('canvas.itemAdded');\n }\n }\n setDrag(null);\n };\n window.addEventListener('pointermove', handleMove);\n window.addEventListener('pointerup', handleUp);\n return () => {\n window.removeEventListener('pointermove', handleMove);\n window.removeEventListener('pointerup', handleUp);\n };\n }, [\n drag,\n capability,\n state,\n config,\n setState,\n emit,\n frameLoop,\n isOverCanvas,\n screenToWorldFromContainer,\n ]);\n\n const startDrag = useCallback((item: PaletteItem, originScreenPos: Point) => {\n setDrag({ item, screenPos: originScreenPos, feedback: null });\n }, []);\n\n return { drag, startDrag };\n}\n\nexport interface DragOverlayProps {\n drag: DragState | null;\n}\n\nexport function DragOverlay({ drag }: DragOverlayProps) {\n if (!drag) return null;\n return <DragGhost item={drag.item} screenPos={drag.screenPos} />;\n}\n","import type { PaletteItem, Point } from '../instrument/types';\n\nexport interface PaletteProps {\n items: PaletteItem[];\n onDragStart: (item: PaletteItem, originScreenPos: Point) => void;\n className?: string;\n}\n\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, { x: e.clientX, y: e.clientY });\n }}\n >\n <span className=\"lk-palette__label\">{item.label}</span>\n </button>\n ))}\n </div>\n );\n}\n"]}
@@ -1,5 +1,5 @@
1
- export { d as ControlPanel } from '../_dts/index-BDVzvRzQ.js';
2
- export { g as CheckboxField, h as ColorField, C as ConfigField, j as ConfigFieldType, m as NumberField, n as SelectField, o as SelectOption, p as SliderField, T as TextField } from '../_dts/types-D6s4b7if.js';
1
+ export { d as ControlPanel } from '../_dts/index-B2X21G1c.js';
2
+ export { g as CheckboxField, h as ColorField, C as ConfigField, j as ConfigFieldType, m as NumberField, n as SelectField, o as SelectOption, p as SliderField, T as TextField } from '../_dts/types-C1Zw7s5P.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
5
5
  import '../_dts/PrefsForm-BkUJZx0A.js';
@@ -1,5 +1,5 @@
1
- export { ControlPanel } from '../chunk-YQJNT4XQ.js';
2
- import '../chunk-HEORBLVT.js';
3
- import '../chunk-ROQDRXKW.js';
1
+ export { ControlPanel } from '../chunk-W3KSUXXR.js';
2
+ import '../chunk-L5WBGUVR.js';
3
+ import '../chunk-7VW3S44V.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
@@ -1,9 +1,9 @@
1
- import { P as PaletteItem, a as Point, D as DragFeedback, b as DragDropCapability, V as ViewTransform, c as WorldSpec } from '../_dts/frac-Cp3NivlC.js';
1
+ import { P as PaletteItem, a as Point, D as DragFeedback, b as DragDropCapability, V as ViewTransform, c as WorldSpec } from '../_dts/frac-QS7XzvpG.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { RefObject, ReactPortal } from 'react';
4
- import '../_dts/types-D6s4b7if.js';
4
+ import '../_dts/types-C1Zw7s5P.js';
5
5
  import '../_dts/PrefsForm-BkUJZx0A.js';
6
- import '../_dts/types-DYMaEvM5.js';
6
+ import '../_dts/types-ChVJJHvk.js';
7
7
  import '../_dts/types-DJ79Tg5J.js';
8
8
  import '../_dts/types-C-gh9Ap-.js';
9
9
 
@@ -1,5 +1,5 @@
1
- export { DragGhost, DragOverlay, Palette, useDragDrop } from '../chunk-5TCEVMPI.js';
1
+ export { DragGhost, DragOverlay, Palette, useDragDrop } from '../chunk-YQGQUBKA.js';
2
2
  import '../chunk-2AYGEN57.js';
3
- import '../chunk-ROQDRXKW.js';
3
+ import '../chunk-7VW3S44V.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.d.ts CHANGED
@@ -1,29 +1,29 @@
1
1
  export { LayerStack, LayerStackItem, LayerStackProps } from './ui/layers/index.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import * as react from 'react';
4
- import { ReactNode, WheelEvent, PointerEvent } from 'react';
5
- export { C as CheckboxRow, a as CheckboxRowProps, b as ColorRow, c as ColorRowProps, d as ControlPanel, N as NumberRow, e as NumberRowProps, P as PropertyList, f as PropertyListPack, g as PropertyListProps, h as PropertyOption, i as PropertyPanel, j as PropertyPanelProps, k as PropertyRow, l as PropertyRowLayout, m as PropertyRowProps, n as PropertyRowVariant, o as PropertySpan, p as PropertySpanProps, S as SelectRow, q as SelectRowProps, r as SliderRow, s as SliderRowProps, T as TextRow, t as TextRowProps, u as ToggleRow, v as ToggleRowProps } from './_dts/index-BDVzvRzQ.js';
4
+ import { ReactNode } from 'react';
5
+ export { C as CheckboxRow, a as CheckboxRowProps, b as ColorRow, c as ColorRowProps, d as ControlPanel, N as NumberRow, e as NumberRowProps, P as PropertyList, f as PropertyListPack, g as PropertyListProps, h as PropertyOption, i as PropertyPanel, j as PropertyPanelProps, k as PropertyRow, l as PropertyRowLayout, m as PropertyRowProps, n as PropertyRowVariant, o as PropertySpan, p as PropertySpanProps, S as SelectRow, q as SelectRowProps, r as SliderRow, s as SliderRowProps, T as TextRow, t as TextRowProps, u as ToggleRow, v as ToggleRowProps } from './_dts/index-B2X21G1c.js';
6
6
  import { N as Node, P as Path } from './_dts/types-C-gh9Ap-.js';
7
7
  import { F as FillStyle, S as Stroke, D as DrawCommand, V as View, T as TextStyle } from './_dts/DrawCommand-B3bskUsC.js';
8
- import { d as WorldRect, A as AnnotationData, e as AnnotationMeaning, M as MarkScene, C as CaptureSource, f as CaptureOptions, g as CaptureResult, h as AnnotationTarget, i as AnnotationsApi, j as AnnotationsCapability, T as TrialTool, k as AnnotationKind, V as ViewTransform, I as Instrument, l as InstrumentList, m as TrialContribution } from './_dts/frac-Cp3NivlC.js';
9
- export { n as Annotation, o as AnnotationInit, p as AnnotationPatch, q as AnnotationQuery, r as AnnotationStatus, s as AnnotationStoreOptions, t as AnnotationTargetInfo, u as CanvasCapability, v as CanvasLayer, w as CaptureDeps, x as DEFAULT_FRAME, b as DragDropCapability, D as DragFeedback, F as FracPoint, y as FracRect, H as HitResult, z as IconComponent, L as LOUPE_DEFAULTS, B as LayerCapability, E as LayerDescriptor, G as LoupeCapability, J as LoupeDeclaration, K as LoupeRenderArgs, P as PaletteItem, a as Point, R as RenderContext, N as ResolvedLoupe, S as SerializedAnnotations, O as SidebarSection, Q as StatusReadout, U as SystemEvent, X as ToolCapability, Y as ToolItem, Z as ToolbarItem, _ as TrialChromeContext, $ as TrialRegion, a0 as UndoCapability, a1 as ViewportControl, a2 as ViewportSize, W as WorldFrame, c as WorldSpec, a3 as annotationsFromJSON, a4 as applyCamera, a5 as createAnnotationScene, a6 as createAnnotationStore, a7 as fracContains, a8 as fracIntersects, a9 as fracToWorld, aa as resolveFrame, ab as resolveLoupe, ac as roundFrac, ad as worldToFrac } from './_dts/frac-Cp3NivlC.js';
8
+ import { d as WorldRect, A as AnnotationData, e as AnnotationMeaning, M as MarkScene, C as CaptureSource, f as CaptureOptions, g as CaptureResult, h as AnnotationTarget, i as AnnotationsApi, j as AnnotationsCapability, T as TrialTool, k as AnnotationKind, V as ViewTransform, I as Instrument, l as InstrumentList, m as TrialContribution } from './_dts/frac-QS7XzvpG.js';
9
+ export { n as Annotation, o as AnnotationInit, p as AnnotationPatch, q as AnnotationQuery, r as AnnotationStatus, s as AnnotationStoreOptions, t as AnnotationTargetInfo, u as CanvasCapability, v as CanvasLayer, w as CaptureDeps, x as DEFAULT_FRAME, b as DragDropCapability, D as DragFeedback, F as FracPoint, y as FracRect, H as HitResult, z as IconComponent, L as LOUPE_DEFAULTS, B as LayerCapability, E as LayerDescriptor, G as LoupeCapability, J as LoupeDeclaration, K as LoupeRenderArgs, P as PaletteItem, a as Point, R as RenderContext, N as ResolvedLoupe, S as SerializedAnnotations, O as SidebarSection, Q as StatusReadout, U as SystemEvent, X as ToolCapability, Y as ToolItem, Z as ToolbarItem, _ as TrialChromeContext, $ as TrialRegion, a0 as UndoCapability, a1 as ViewportControl, a2 as ViewportSize, W as WorldFrame, c as WorldSpec, a3 as annotationsFromJSON, a4 as applyCamera, a5 as createAnnotationScene, a6 as createAnnotationStore, a7 as fracContains, a8 as fracIntersects, a9 as fracToWorld, aa as resolveFrame, ab as resolveLoupe, ac as roundFrac, ad as worldToFrac } from './_dts/frac-QS7XzvpG.js';
10
10
  import { B as BuiltinShapeToolId } from './_dts/shapeKinds-Cx_rxwsa.js';
11
- export { CanvasStack, CanvasStackProps, ZoomAtOptions, centerOn, screenToWorld, worldToScreen, zoomAt } from './canvas/index.js';
12
- export { C as CanvasLayerDescriptor, a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from './_dts/CanvasStackContext-DtAn_3O-.js';
11
+ export { CanvasStack, CanvasStackProps, OrbitHandlers, OrbitView, PITCH_LIMIT, PanZoomHandlers, UseOrbitOptions, UsePanZoomOptions, Vec3, ZoomAtOptions, centerOn, clampPitch, orbitAfterDrag, orbitAfterWheel, screenToWorld, useOrbit, usePanZoom, worldToScreen, wrapYaw, zoomAt } from './canvas/index.js';
12
+ export { C as CanvasLayerDescriptor, a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from './_dts/CanvasStackContext-D6M0o8cQ.js';
13
13
  export { PaletteRegion, PaletteRegionProps, SidebarRegion, SidebarRegionProps, StatusRegion, StatusRegionProps, TitleBarRegion, TitleBarRegionProps, ToolbarRegion, ToolbarRegionProps, ViewportRegion, ViewportRegionProps, builtinContributions, mergeContributions, suppressContributions } from './chrome/index.js';
14
14
  import { T as ToolPrefLeaf } from './_dts/PrefsForm-BkUJZx0A.js';
15
- import { b as ConfigNode, A as Annotations, N as NodeOptions, c as ControlRenderer, d as ConfigOption, a as ConfigSchema, I as InferConfig, C as ConfigField, R as ResolvedConfig, e as ConfigRule, L as LeafPatch, f as ConfigRuleContext } from './_dts/types-D6s4b7if.js';
16
- export { g as CheckboxField, h as ColorField, i as ConfigFieldBase, j as ConfigFieldType, k as ConfigOf, l as NodeValue, m as NumberField, S as SectionSpec, n as SelectField, o as SelectOption, p as SliderField, T as TextField } from './_dts/types-D6s4b7if.js';
15
+ import { b as ConfigNode, A as Annotations, N as NodeOptions, c as ControlRenderer, d as ConfigOption, a as ConfigSchema, I as InferConfig, C as ConfigField, R as ResolvedConfig, e as ConfigRule, L as LeafPatch, f as ConfigRuleContext } from './_dts/types-C1Zw7s5P.js';
16
+ export { g as CheckboxField, h as ColorField, i as ConfigFieldBase, j as ConfigFieldType, k as ConfigOf, l as NodeValue, m as NumberField, S as SectionSpec, n as SelectField, o as SelectOption, p as SliderField, T as TextField } from './_dts/types-C1Zw7s5P.js';
17
17
  import { J as JobHandle } from './_dts/types-DJ79Tg5J.js';
18
18
  export { a as JobCapability, b as JobEvent, c as JobFailure, d as JobStatus } from './_dts/types-DJ79Tg5J.js';
19
19
  export { UseJobOptions, useJob } from './job/index.js';
20
- import { a as StorageAdapter, h as LabMode, T as TrialRecord, c as SavedSnapshot } from './_dts/types-DYMaEvM5.js';
21
- export { C as CreateLabStoreOptions, L as LabDocument, b as LabStoreState, S as SerializedTrial, d as TrialStateHandle, U as UndoStack, e as UndockedPanel, f as UndockedPanels, g as dockPanel, p as panelKey, u as undockPanel } from './_dts/types-DYMaEvM5.js';
20
+ import { a as StorageAdapter, h as LabMode, T as TrialRecord, c as SavedSnapshot } from './_dts/types-ChVJJHvk.js';
21
+ export { C as CreateLabStoreOptions, L as LabDocument, b as LabStoreState, S as SerializedTrial, d as TrialStateHandle, U as UndoStack, e as UndockedPanel, f as UndockedPanels, g as dockPanel, p as panelKey, u as undockPanel } from './_dts/types-ChVJJHvk.js';
22
22
  export { LayerList, LayerListProps } from './layers/index.js';
23
23
  export { CanvasLoupe, CanvasLoupeProps, DomLoupe, DomLoupeProps, LensCamera, LoupeBubble, LoupeBubbleProps, LoupeState, SourceRect, TrialLoupe, TrialLoupeProps, UseLoupeOptions, drawCanvasLens, lensCamera, lensSourceRect, sampleStack, useLoupe } from './loupe/index.js';
24
24
  export { FloatingPanel, FloatingPanelProps, FpsMeter, JobProgress, JobProgressProps, Legend, LegendEntry, LegendMark, LegendProps, ScaleIndicator, ScaleIndicatorProps, Sidebar, SidebarProps, StatusBar, StatusBarProps, StatusBarSectionProps, Toolbar, ToolbarButtonProps, ToolbarGroupProps, ToolbarProps, ZoomControl, ZoomControlProps } from './primitives/index.js';
25
- export { C as CURRENT_DOCUMENT_VERSION, b as LabStoreContext, c as LabStoreProvider, T as TrialIdContext, d as TrialIdProvider, f as createMemoryAdapter, l as labDocumentKey, g as localStorageAdapter, n as noneAdapter, q as quarantineKey, s as sessionStorageAdapter, u as urlHashAdapter, h as useLabStore, i as useTrialId, j as useTrialState } from './_dts/useTrialState-gmMvZqPc.js';
26
- export { Box, Rect, SurfaceCanvasContext, SurfaceContext, SurfaceFrame, SurfaceHandle, TilePainter, UseTiledSurfaceOptions, composeRects, rectsEqual, toDeviceRect, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTiledSurface } from './surface/index.js';
25
+ export { C as CURRENT_DOCUMENT_VERSION, b as LabStoreContext, c as LabStoreProvider, T as TrialIdContext, d as TrialIdProvider, f as createMemoryAdapter, l as labDocumentKey, g as localStorageAdapter, n as noneAdapter, q as quarantineKey, s as sessionStorageAdapter, u as urlHashAdapter, h as useLabStore, i as useTrialId, j as useTrialState } from './_dts/useTrialState-Cdm13fvl.js';
26
+ export { Box, Rect, SurfaceCanvasContext, SurfaceContext, SurfaceFrame, SurfaceHandle, TilePainter, UseTiledSurfaceOptions, composeRects, rectsEqual, toDeviceRect, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId, useTiledSurface } from './surface/index.js';
27
27
  export { EventBus, EventListener, clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './undo/index.js';
28
28
  import 'windease';
29
29
  import 'zustand/vanilla';
@@ -645,51 +645,6 @@ declare function fromWeaselView(v: View): ViewTransform;
645
645
  */
646
646
  declare function fitView(content: ContentSize, pane: PaneSize): ViewTransform;
647
647
 
648
- /** A point in the space the instrument works in. */
649
- interface Vec3 {
650
- x: number;
651
- y: number;
652
- z: number;
653
- }
654
- /** An orbit camera as a trial view: where it looks from, and what it looks at.
655
- * labkit does not turn this into a matrix — the host's renderer does. */
656
- interface OrbitView {
657
- yaw: number;
658
- pitch: number;
659
- distance: number;
660
- target: Vec3;
661
- }
662
- /** Just short of the pole. At exactly ±PI/2 the azimuth is undefined and the
663
- * camera rolls, which reads as the model jumping rather than as a limit. */
664
- declare const PITCH_LIMIT: number;
665
- declare function clampPitch(pitch: number): number;
666
- declare function wrapYaw(yaw: number): number;
667
- /** The view a drag of (dx, dy) from `start` produces. Absolute against the drag
668
- * start, so it can be re-applied any number of times without compounding. */
669
- declare function orbitAfterDrag(start: OrbitView, dx: number, dy: number): OrbitView;
670
- /** Multiplicative, so one notch covers the same proportion of the distance
671
- * whether the camera is near or far. */
672
- declare function orbitAfterWheel(view: OrbitView, deltaY: number, minDistance: number, maxDistance: number): OrbitView;
673
- interface UseOrbitOptions {
674
- view: OrbitView;
675
- onViewChange: (v: OrbitView) => void;
676
- /** Restored on double-click. Defaults to the view the hook first saw. */
677
- home?: OrbitView;
678
- minDistance?: number;
679
- maxDistance?: number;
680
- }
681
- interface OrbitHandlers {
682
- onWheel: (e: WheelEvent<HTMLElement>) => void;
683
- onPointerDown: (e: PointerEvent<HTMLElement>) => void;
684
- onPointerMove: (e: PointerEvent<HTMLElement>) => void;
685
- onPointerUp: (e: PointerEvent<HTMLElement>) => void;
686
- onDoubleClick: () => void;
687
- isDragging: () => boolean;
688
- }
689
- /** Pointer gestures over an orbit view: drag to turn, wheel or pinch to dolly,
690
- * double-click to go home. The 3D peer of `usePanZoom`. */
691
- declare function useOrbit({ view, onViewChange, home, minDistance, maxDistance, }: UseOrbitOptions): OrbitHandlers;
692
-
693
648
  /** Shared chaining surface. Every method clones, so a node can be reused as a
694
649
  * base for several leaves without one bleeding into the next. */
695
650
  declare abstract class BaseNode<T> implements ConfigNode<T> {
@@ -724,6 +679,9 @@ declare class NumberNode extends BaseNode<number> {
724
679
  /** Bound the value. A number with both bounds renders as a slider. */
725
680
  range(min: number, max: number): this;
726
681
  step(step: number): this;
682
+ /** A display suffix for the value — `'px'`, `'ms'`, `'°'`. Presentation only:
683
+ * it is never parsed, and the stored value stays a plain number. */
684
+ suffix(suffix: string): this;
727
685
  /** Force a slider even without both bounds. */
728
686
  slider(): this;
729
687
  /** Force a typed input even when both bounds are set. */
@@ -1093,6 +1051,46 @@ interface TrialProps {
1093
1051
  * instrument, and mounts the instrument inside the trial chrome. */
1094
1052
  declare function Trial({ id, chrome, suppress }: TrialProps): react_jsx_runtime.JSX.Element;
1095
1053
 
1054
+ /** Props for `<TrialBody>`. */
1055
+ interface TrialBodyProps {
1056
+ /** The sidebar region's sections. */
1057
+ sidebar: ReactNode;
1058
+ /** The instrument's own output. */
1059
+ children: ReactNode;
1060
+ /** Extra class on the content pane — `Trial` marks a canvas instrument's
1061
+ * well flush. */
1062
+ contentClassName?: string;
1063
+ /** The sidebar's current extent in pixels. Omit for an unpersisted lab: the
1064
+ * seam still works, its result just does not outlive the mount. */
1065
+ width?: number;
1066
+ /** Where the sidebar starts before anyone drags it. */
1067
+ defaultWidth?: number;
1068
+ minWidth?: number;
1069
+ maxWidth?: number;
1070
+ /** How little the instrument may be squeezed to. Reported as the seam's
1071
+ * reachable maximum, so the drag stops there rather than clamping silently. */
1072
+ contentMinWidth?: number;
1073
+ /** Fires through the drag, not on release: the pane is already there. */
1074
+ onWidthChange?: (width: number) => void;
1075
+ /**
1076
+ * Fixed extent. Omit in an app — the strip measures its own box. Supply it
1077
+ * where nothing measures, notably jsdom, or both panes lay out at zero.
1078
+ */
1079
+ viewport?: {
1080
+ w: number;
1081
+ h: number;
1082
+ };
1083
+ }
1084
+ /**
1085
+ * A trial's sidebar and content as a two-pane strip with a draggable seam.
1086
+ *
1087
+ * The seam is `stripStrategy`'s own resize affordance, so it arrives as a
1088
+ * `role="separator"` carrying the reachable range, operable by pointer and by
1089
+ * arrows / Home / End, and clamped against the content pane's floor rather
1090
+ * than against the sidebar's alone.
1091
+ */
1092
+ declare function TrialBody({ sidebar, children, contentClassName, width, defaultWidth, minWidth, maxWidth, contentMinWidth, onWidthChange, viewport, }: TrialBodyProps): react_jsx_runtime.JSX.Element;
1093
+
1096
1094
  /** The trial's loupe as its chrome sees it: a switch and its position. */
1097
1095
  interface LoupeBindings {
1098
1096
  on: boolean;
@@ -1153,5 +1151,5 @@ declare function resetTrial(trials: TrialRecord[], id: string, instruments: Inst
1153
1151
  */
1154
1152
  declare function reorderTrials(trials: TrialRecord[], ids: readonly string[]): TrialRecord[];
1155
1153
 
1156
- export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationData, AnnotationKind, AnnotationMeaning, AnnotationOverlay, AnnotationTarget, AnnotationTargets, Annotations, AnnotationsApi, AnnotationsCapability, AnnotationsContext, CaptureOptions, CaptureResult, CaptureSource, ConfigField, ConfigNode, ConfigOption, ConfigRule, ConfigRuleContext, ConfigSchema, ControlRenderer, CurveField, DEFAULT_VIEW, EffectCard, EffectCardList, ExportMenu, InferConfig, Instrument, InstrumentList, JobHandle, Lab, LabContext, LabMode, LabPalette, LabShell, LeafPatch, MarkList, MarkScene, NodeOptions, PITCH_LIMIT, PropertyGroup, ResolvedConfig, SavedSnapshot, StorageAdapter, Subpanel, Trial, TrialChrome, TrialContribution, TrialRecord, TrialTool, ViewTransform, Workspace, WorldRect, addTrial, annotationToolInfo, applyRules, as2DView, builtinRules, capturePlan, captureTarget, clampPitch, cloneTrial, closeTrial, composeCaptureSvg, createMarkDrawOne, defineInstrument, f, fitView, fromConfigFields, fromWeaselView, interstellarTheme, isLeafVisible, isStale, markCommands, markSvgNodes, orbitAfterDrag, orbitAfterWheel, reorderTrials, resetTrial, resolveConfigSchema, resolveMarkStyle, seenFrom, titleCase, toWeaselView, useAnnotations, useAnnotationsOptional, useConfigSchema, useLabContext, useOrbit, validateConfigSchema, wrapYaw };
1157
- export type { AnnotationOverlayProps, AnnotationTargetsProps, AnnotationToolInfo, CaptureArgs, CapturePlan, ComposeSvgArgs, ContentSize, CurveFieldProps, CurveMark, EffectCardListItem, EffectCardListProps, EffectCardProps, InstrumentSpec, LabContextValue, LabPaletteProps, LabProps, LabShellProps, MarkDrawOptions, MarkListProps, MarkStyle, OrbitHandlers, OrbitView, PaintableMark, PaneSize, PanelDescriptor, PropertyGroupProps, SubpanelProps, TrialChromeProps, TrialLayout, TrialProps, UndoBindings, UseOrbitOptions, ValidationResult, Vec3, ViewTransform2D, WorkspaceProps };
1154
+ export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationData, AnnotationKind, AnnotationMeaning, AnnotationOverlay, AnnotationTarget, AnnotationTargets, Annotations, AnnotationsApi, AnnotationsCapability, AnnotationsContext, CaptureOptions, CaptureResult, CaptureSource, ConfigField, ConfigNode, ConfigOption, ConfigRule, ConfigRuleContext, ConfigSchema, ControlRenderer, CurveField, DEFAULT_VIEW, EffectCard, EffectCardList, ExportMenu, InferConfig, Instrument, InstrumentList, JobHandle, Lab, LabContext, LabMode, LabPalette, LabShell, LeafPatch, MarkList, MarkScene, NodeOptions, PropertyGroup, ResolvedConfig, SavedSnapshot, StorageAdapter, Subpanel, Trial, TrialBody, TrialChrome, TrialContribution, TrialRecord, TrialTool, ViewTransform, Workspace, WorldRect, addTrial, annotationToolInfo, applyRules, as2DView, builtinRules, capturePlan, captureTarget, cloneTrial, closeTrial, composeCaptureSvg, createMarkDrawOne, defineInstrument, f, fitView, fromConfigFields, fromWeaselView, interstellarTheme, isLeafVisible, isStale, markCommands, markSvgNodes, reorderTrials, resetTrial, resolveConfigSchema, resolveMarkStyle, seenFrom, titleCase, toWeaselView, useAnnotations, useAnnotationsOptional, useConfigSchema, useLabContext, validateConfigSchema };
1155
+ export type { AnnotationOverlayProps, AnnotationTargetsProps, AnnotationToolInfo, CaptureArgs, CapturePlan, ComposeSvgArgs, ContentSize, CurveFieldProps, CurveMark, EffectCardListItem, EffectCardListProps, EffectCardProps, InstrumentSpec, LabContextValue, LabPaletteProps, LabProps, LabShellProps, MarkDrawOptions, MarkListProps, MarkStyle, PaintableMark, PaneSize, PanelDescriptor, PropertyGroupProps, SubpanelProps, TrialBodyProps, TrialChromeProps, TrialLayout, TrialProps, UndoBindings, ValidationResult, ViewTransform2D, WorkspaceProps };