@weasel-js/labkit 1.5.0 → 1.5.2

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 (206) hide show
  1. package/README.md +41 -4
  2. package/dist/_dts/{CanvasStackContext-CqkxkFJW.d.ts → CanvasStackContext-CMMo180l.d.ts} +1 -1
  3. package/dist/_dts/{PrefsForm.d-DDHFANkc.d.ts → PrefsForm.d-DPy9I8It.d.ts} +4 -0
  4. package/dist/_dts/Select.d-ZTiwzYyT.d.ts +479 -0
  5. package/dist/_dts/{frac-8R6UmlvN.d.ts → frac-B4hFJMiN.d.ts} +54 -6
  6. package/dist/_dts/{index-retnAut7.d.ts → index-8LiKe3A-.d.ts} +77 -10
  7. package/dist/_dts/{index-B8uu2ba7.d.ts → index-DlKolEIZ.d.ts} +20 -8
  8. package/dist/_dts/{types-Ca2LCnPq.d.ts → types-Db-3NNk1.d.ts} +28 -4
  9. package/dist/_dts/{usePanZoom-nS798rOF.d.ts → usePanZoom-SSTZe410.d.ts} +4 -47
  10. package/dist/_dts/{useTrialState-jcx_TdU6.d.ts → useTrialState-pnAE-UBD.d.ts} +1 -1
  11. package/dist/canvas/index.d.ts +5 -5
  12. package/dist/canvas/index.js +1 -1
  13. package/dist/chrome/index.d.ts +4 -4
  14. package/dist/chrome/index.js +7 -7
  15. package/dist/chunk-6BUQ77ZV.js +18 -0
  16. package/dist/chunk-6BUQ77ZV.js.map +1 -0
  17. package/dist/{chunk-KJALCDWE.js → chunk-753Y6HE6.js} +9 -9
  18. package/dist/chunk-753Y6HE6.js.map +1 -0
  19. package/dist/{chunk-6ZDGOZQV.js → chunk-A2ACAGW6.js} +72 -20
  20. package/dist/chunk-A2ACAGW6.js.map +1 -0
  21. package/dist/{chunk-NS64DXMN.js → chunk-CKUKF72R.js} +44 -21
  22. package/dist/chunk-CKUKF72R.js.map +1 -0
  23. package/dist/{chunk-MUKOW3TC.js → chunk-D35PFTS7.js} +4 -4
  24. package/dist/{chunk-MUKOW3TC.js.map → chunk-D35PFTS7.js.map} +1 -1
  25. package/dist/{chunk-UU3NJO6N.js → chunk-EMXAIRUJ.js} +3 -3
  26. package/dist/{chunk-UU3NJO6N.js.map → chunk-EMXAIRUJ.js.map} +1 -1
  27. package/dist/{chunk-ZPH5WTWF.js → chunk-ERFMC6WU.js} +142 -66
  28. package/dist/chunk-ERFMC6WU.js.map +1 -0
  29. package/dist/chunk-FKLT3ITC.js +590 -0
  30. package/dist/chunk-FKLT3ITC.js.map +1 -0
  31. package/dist/{chunk-QLSV2N3G.js → chunk-IJJUK4FU.js} +25 -13
  32. package/dist/chunk-IJJUK4FU.js.map +1 -0
  33. package/dist/{chunk-EKIICY6X.js → chunk-KJCUERQF.js} +37 -25
  34. package/dist/chunk-KJCUERQF.js.map +1 -0
  35. package/dist/chunk-LASCBWW7.js +13456 -0
  36. package/dist/chunk-LASCBWW7.js.map +1 -0
  37. package/dist/{chunk-67SJLMC7.js → chunk-LRI3MBGR.js} +45 -12
  38. package/dist/chunk-LRI3MBGR.js.map +1 -0
  39. package/dist/chunk-REOBGYMC.js +150 -0
  40. package/dist/chunk-REOBGYMC.js.map +1 -0
  41. package/dist/{chunk-PGETSEDK.js → chunk-TT5C5S6R.js} +11 -90
  42. package/dist/chunk-TT5C5S6R.js.map +1 -0
  43. package/dist/{chunk-NDRYLVOW.js → chunk-Z76KEZAX.js} +2 -2
  44. package/dist/chunk-Z76KEZAX.js.map +1 -0
  45. package/dist/config/index.d.ts +62 -19
  46. package/dist/config/index.js +6 -4
  47. package/dist/controls/index.d.ts +3 -3
  48. package/dist/controls/index.js +4 -4
  49. package/dist/dragdrop/index.d.ts +3 -3
  50. package/dist/index.d.ts +230 -62
  51. package/dist/index.js +1367 -1698
  52. package/dist/index.js.map +1 -1
  53. package/dist/layers/index.d.ts +4 -4
  54. package/dist/layers/index.js +2 -2
  55. package/dist/loupe/index.d.ts +67 -16
  56. package/dist/loupe/index.js +1 -1
  57. package/dist/passthrough/weasel-ui.d.ts +57 -230
  58. package/dist/passthrough/weasel-ui.js +1 -1
  59. package/dist/primitives/index.d.ts +3 -1
  60. package/dist/primitives/index.js +3 -3
  61. package/dist/state/index.d.ts +5 -5
  62. package/dist/state/index.js +5 -3
  63. package/dist/state/index.js.map +1 -1
  64. package/dist/styles.css +266 -57
  65. package/dist/surface/index.js +1 -1
  66. package/dist/ui/layers/index.js +1 -1
  67. package/dist/undo/index.d.ts +3 -3
  68. package/package.json +9 -9
  69. package/src/annotations/AnnotationOverlay.tsx +3 -0
  70. package/src/annotations/Annotations.less +4 -0
  71. package/src/annotations/Annotations.overlay.test.tsx +20 -0
  72. package/src/annotations/svgNodes.ts +1 -0
  73. package/src/annotations/toolMap.test.ts +9 -5
  74. package/src/annotations/toolMap.ts +3 -0
  75. package/src/canvas/CanvasStack.stories.tsx +1 -1
  76. package/src/canvas/index.ts +0 -9
  77. package/src/canvas/usePanZoom.test.ts +28 -0
  78. package/src/canvas/usePanZoom.ts +11 -4
  79. package/src/chrome/ChromeRegions.stories.tsx +1 -1
  80. package/src/chrome/LabChrome.tsx +21 -5
  81. package/src/chrome/builtins.test.ts +1 -0
  82. package/src/chrome/builtins.tsx +1 -0
  83. package/src/chrome/index.ts +1 -0
  84. package/src/chrome/labTypes.ts +3 -3
  85. package/src/chrome/regions/PaletteRegion.test.tsx +18 -0
  86. package/src/chrome/regions/PaletteRegion.tsx +6 -10
  87. package/src/chrome/regions/SidebarRegion.stories.tsx +44 -0
  88. package/src/chrome/regions/TitleBarRegion.tsx +1 -1
  89. package/src/chrome/regions/ToolbarRegion.tsx +11 -7
  90. package/src/chrome/types.ts +11 -2
  91. package/src/config/auto.test.ts +12 -0
  92. package/src/config/auto.ts +15 -0
  93. package/src/config/autoConfig.test.ts +107 -0
  94. package/src/config/autoConfig.ts +153 -0
  95. package/src/config/builder.test.ts +38 -0
  96. package/src/config/builder.ts +55 -11
  97. package/src/config/index.ts +3 -0
  98. package/src/config/path.ts +7 -2
  99. package/src/config/resolve.test.ts +25 -0
  100. package/src/config/resolve.ts +17 -1
  101. package/src/config/types.ts +32 -2
  102. package/src/config/useResolvedConfig.ts +26 -0
  103. package/src/controls/AutoControls.stories.tsx +88 -0
  104. package/src/controls/ControlPanel.less +23 -0
  105. package/src/controls/ControlPanel.stories.tsx +83 -1
  106. package/src/controls/ControlPanel.test.tsx +457 -4
  107. package/src/controls/ControlPanel.tsx +534 -73
  108. package/src/index.test.ts +0 -2
  109. package/src/index.ts +33 -11
  110. package/src/instrument/serializers.ts +29 -1
  111. package/src/lab/Lab.chrome.test.tsx +16 -0
  112. package/src/lab/Lab.stories.tsx +1 -1
  113. package/src/lab/Lab.surface.test.tsx +7 -2
  114. package/src/lab/Lab.test.tsx +79 -1
  115. package/src/lab/Lab.tsx +124 -16
  116. package/src/lab/LabContext.ts +8 -0
  117. package/src/lab/LabFit.stories.tsx +4 -4
  118. package/src/lab/LabFullChrome.stories.tsx +1 -1
  119. package/src/lab/LabHeader.tsx +0 -1
  120. package/src/lab/LabRoot.test.tsx +56 -0
  121. package/src/lab/LabRoot.tsx +47 -0
  122. package/src/lab/LabShell.less +24 -3
  123. package/src/lab/LabShell.stories.tsx +50 -1
  124. package/src/lab/LabShell.tsx +18 -27
  125. package/src/lab/LabSwitcher.less +10 -10
  126. package/src/lab/LabSwitcher.test.tsx +14 -9
  127. package/src/lab/LabSwitcher.tsx +8 -4
  128. package/src/lab/Workspace.less +1 -1
  129. package/src/lab/Workspace.stories.tsx +1 -1
  130. package/src/lab/Workspace.surface.test.tsx +1 -1
  131. package/src/lab/index.ts +2 -0
  132. package/src/layers/LayerList.less +1 -1
  133. package/src/layers/LayerList.stories.tsx +2 -2
  134. package/src/loupe/AGENTS.md +16 -4
  135. package/src/loupe/LoupeGestures.tsx +67 -0
  136. package/src/loupe/TrialLoupe.tsx +43 -28
  137. package/src/loupe/index.ts +4 -0
  138. package/src/loupe/loupeActions.ts +98 -0
  139. package/src/loupe/useLoupe.test.tsx +59 -2
  140. package/src/loupe/useLoupe.ts +28 -48
  141. package/src/passthrough/weasel-ui.ts +3 -3
  142. package/src/primitives/FloatingPanel.stories.tsx +1 -1
  143. package/src/primitives/FpsMeter.less +6 -1
  144. package/src/primitives/FpsMeter.stories.tsx +1 -1
  145. package/src/primitives/FpsMeter.test.tsx +12 -4
  146. package/src/primitives/FpsMeter.tsx +6 -1
  147. package/src/primitives/JobProgress.stories.tsx +2 -2
  148. package/src/primitives/Legend.stories.tsx +1 -1
  149. package/src/primitives/ScaleIndicator.stories.tsx +1 -1
  150. package/src/primitives/Sidebar.less +7 -0
  151. package/src/primitives/Sidebar.stories.tsx +1 -1
  152. package/src/primitives/Split.test.tsx +25 -0
  153. package/src/primitives/Split.tsx +36 -20
  154. package/src/primitives/StatusBar.less +6 -0
  155. package/src/primitives/StatusBar.stories.tsx +1 -1
  156. package/src/primitives/Toolbar.stories.tsx +1 -1
  157. package/src/specimen/Specimen.less +95 -0
  158. package/src/specimen/Specimen.stories.tsx +13 -0
  159. package/src/specimen/Specimen.test.tsx +13 -0
  160. package/src/specimen/Specimen.tsx +888 -0
  161. package/src/state/Persistence.stories.tsx +4 -4
  162. package/src/state/store.test.ts +65 -0
  163. package/src/state/store.ts +32 -8
  164. package/src/state/types.ts +31 -2
  165. package/src/state/useTrialState.test.tsx +85 -0
  166. package/src/state/useTrialState.ts +9 -1
  167. package/src/state/view.test.ts +4 -4
  168. package/src/styles.less +1 -0
  169. package/src/surface/index.ts +1 -1
  170. package/src/surface/useSurfaceTile.test.tsx +1 -1
  171. package/src/surface/useTiledSurface.test.tsx +65 -10
  172. package/src/surface/useTiledSurface.ts +23 -11
  173. package/src/theme/Interstellar.stories.tsx +2 -2
  174. package/src/theme/interstellar.test.ts +16 -5
  175. package/src/theme/interstellar.theme.json +180 -0
  176. package/src/theme/interstellar.ts +8 -5
  177. package/src/tools/labTool.ts +3 -3
  178. package/src/trial/Trial.annotations.test.tsx +13 -4
  179. package/src/trial/Trial.canvas.test.tsx +36 -0
  180. package/src/trial/Trial.config.test.tsx +75 -2
  181. package/src/trial/Trial.less +4 -0
  182. package/src/trial/Trial.stories.tsx +4 -1
  183. package/src/trial/Trial.test.tsx +3 -0
  184. package/src/trial/Trial.tsx +21 -14
  185. package/src/trial/TrialChrome.tsx +17 -3
  186. package/src/trial/trialOps.test.ts +101 -1
  187. package/src/trial/trialOps.ts +62 -4
  188. package/dist/_dts/ToggleBar.d-DbHoWKIA.d.ts +0 -116
  189. package/dist/chunk-67SJLMC7.js.map +0 -1
  190. package/dist/chunk-6ZDGOZQV.js.map +0 -1
  191. package/dist/chunk-E44SU6XS.js +0 -50
  192. package/dist/chunk-E44SU6XS.js.map +0 -1
  193. package/dist/chunk-EKIICY6X.js.map +0 -1
  194. package/dist/chunk-KJALCDWE.js.map +0 -1
  195. package/dist/chunk-NDRYLVOW.js.map +0 -1
  196. package/dist/chunk-NS64DXMN.js.map +0 -1
  197. package/dist/chunk-PGETSEDK.js.map +0 -1
  198. package/dist/chunk-QLSV2N3G.js.map +0 -1
  199. package/dist/chunk-S2SHZRD7.js +0 -7681
  200. package/dist/chunk-S2SHZRD7.js.map +0 -1
  201. package/dist/chunk-TQBBYTAF.js +0 -280
  202. package/dist/chunk-TQBBYTAF.js.map +0 -1
  203. package/dist/chunk-ZPH5WTWF.js.map +0 -1
  204. package/src/canvas/useOrbit.test.ts +0 -167
  205. package/src/canvas/useOrbit.ts +0 -156
  206. package/src/theme/interstellar.tokens.json +0 -61
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/annotations/AnnotationsContext.ts","../src/annotations/ExportMenu.tsx","../src/annotations/MarkList.tsx","../src/chrome/builtins.tsx","../src/tools/labTool.ts","../src/chrome/merge.ts","../src/chrome/regions/SidebarRegion.tsx","../src/chrome/regions/StatusRegion.tsx","../src/chrome/regions/ToolbarRegion.tsx","../src/chrome/LabChrome.tsx","../src/chrome/regions/PaletteRegion.tsx","../src/chrome/regions/TitleBarRegion.tsx","../src/chrome/regions/ViewportRegion.tsx"],"names":["g","jsx","jsxs","u","l","useContext","n","o","renderEntry"],"mappings":"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","file":"chunk-CKUKF72R.js","sourcesContent":["import { createContext, useCallback, useContext, useRef, useSyncExternalStore } from 'react';\nimport type { AnnotationsApi } from './types';\n\n/** Null in a trial whose instrument declares no `annotations`. */\nexport const AnnotationsContext = createContext<AnnotationsApi | null>(null);\n\n/** Re-render the caller whenever any of the store's scenes changes.\n *\n * The API is a stable facade over mutable scenes, so nothing about its\n * identity says a mark was added — a component reading `query()` without this\n * renders one answer and never revises it. */\nfunction useMarkVersion(api: AnnotationsApi | null): void {\n const version = useRef(0);\n useSyncExternalStore(\n useCallback(\n (fn: () => void) =>\n api?.subscribe(() => {\n version.current += 1;\n fn();\n }) ?? (() => {}),\n [api],\n ),\n useCallback(() => version.current, []),\n () => 0,\n );\n}\n\n/** The marks on this trial's targets. Reached through a hook rather than the\n * chrome context, which carries no instrument state — a sidebar panel listing\n * marks pulls it the way `useTrialState()` does. Throws outside a trial whose\n * instrument declares the capability. */\nexport function useAnnotations(): AnnotationsApi {\n const api = useContext(AnnotationsContext);\n useMarkVersion(api);\n if (!api) {\n throw new Error(\n '[labkit] useAnnotations requires an instrument that declares the `annotations` capability',\n );\n }\n return api;\n}\n\n/** The marks on this trial's targets, or null. For chrome that renders in\n * every trial and does something else where there are none. */\nexport function useAnnotationsOptional(): AnnotationsApi | null {\n const api = useContext(AnnotationsContext);\n useMarkVersion(api);\n return api;\n}\n","import { ExportIcon } from '@weasel-js/ui';\nimport { useId, useState } from 'react';\nimport { Callout } from '../passthrough/weasel-ui';\nimport { Toolbar } from '../primitives/Toolbar';\nimport { useAnnotationsOptional } from './AnnotationsContext';\nimport type { CaptureResult } from './types';\n\nconst SCALES = [1, 2, 4] as const;\nconst FORMATS = [\n { id: 'png', label: 'PNG' },\n { id: 'svg', label: 'SVG' },\n] as const;\n\ntype Format = (typeof FORMATS)[number]['id'];\n\nfunction fileName(result: CaptureResult): string {\n return `${result.target.replace(/[^a-z0-9._-]+/gi, '-')}.${result.format}`;\n}\n\n/** A blob the person asked for, handed to the browser's own save flow. The\n * object URL is revoked on the next turn — revoking it synchronously races\n * the navigation the click starts. */\nfunction download(result: CaptureResult): void {\n const url = URL.createObjectURL(result.blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = fileName(result);\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\n/** PNG goes to the clipboard as an image. SVG goes as text: `image/svg+xml`\n * needs Chromium's `web ` prefix and nothing else reads it, while the markup\n * is what a person pasting a vector export actually wants. */\nasync function copy(result: CaptureResult): Promise<void> {\n if (result.format === 'svg') {\n await navigator.clipboard.writeText(await result.blob.text());\n return;\n }\n await navigator.clipboard.write([new ClipboardItem({ 'image/png': result.blob })]);\n}\n\n/**\n * Export a target's picture with its marks on it.\n *\n * A panel rather than a button because a mark belongs to a target: with more\n * than one pane, \"export\" on its own does not say what.\n *\n * Reads the store through the hook the way `<MarkList>` does — the chrome\n * context carries no instrument state and is not the route to it.\n */\nexport function ExportMenu() {\n const marks = useAnnotationsOptional();\n const [anchor, setAnchor] = useState<HTMLSpanElement | null>(null);\n const [open, setOpen] = useState(false);\n const [target, setTarget] = useState<string | null>(null);\n const [format, setFormat] = useState<Format>('png');\n const [scale, setScale] = useState<number>(2);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const titleId = useId();\n\n if (!marks) return null;\n const targets = marks.targets();\n const chosen = target ?? targets[0]?.id ?? null;\n\n const run = async (then: (r: CaptureResult) => void | Promise<void>): Promise<void> => {\n if (!chosen) return;\n setBusy(true);\n setError(null);\n try {\n await then(await marks.capture(chosen, { format, scale }));\n setOpen(false);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <span className=\"lk-export\" ref={setAnchor}>\n <Toolbar.Button\n iconOnly\n pressed={open}\n aria-label=\"Export\"\n title=\"Export\"\n onClick={() => setOpen((was) => !was)}\n >\n <ExportIcon size={16} />\n </Toolbar.Button>\n <Callout\n triggerRef={{ current: anchor }}\n isOpen={open}\n onOpenChange={setOpen}\n onDismiss={() => setOpen(false)}\n placement=\"bottom end\"\n aria-labelledby={titleId}\n >\n <div className=\"lk-export__panel\">\n <span className=\"lk-export__title\" id={titleId}>\n Export\n </span>\n\n <label className=\"lk-export__row\">\n <span>Target</span>\n {/* Native controls: role, name and keyboard operability for free,\n and a five-control panel is not the place to rebuild them. */}\n <select\n aria-label=\"Target\"\n value={chosen ?? ''}\n onChange={(e) => setTarget(e.target.value)}\n >\n {targets.map((t) => (\n <option key={t.id} value={t.id}>\n {t.id}\n </option>\n ))}\n </select>\n </label>\n\n {/* A <fieldset>/<legend> cannot do this: a legend is outside its\n fieldset's grid formatting context, so it will not take a grid\n column and every choice row drops below its own label. */}\n <div className=\"lk-export__row\">\n <span>Format</span>\n <span className=\"lk-export__choices\" role=\"radiogroup\" aria-label=\"Format\">\n {FORMATS.map((f) => (\n <label key={f.id}>\n <input\n type=\"radio\"\n name=\"lk-export-format\"\n checked={format === f.id}\n onChange={() => setFormat(f.id)}\n />\n {f.label}\n </label>\n ))}\n </span>\n </div>\n\n <div className=\"lk-export__row\">\n <span>Scale</span>\n <span className=\"lk-export__choices\" role=\"radiogroup\" aria-label=\"Scale\">\n {SCALES.map((s) => (\n <label key={s}>\n <input\n type=\"radio\"\n name=\"lk-export-scale\"\n checked={scale === s}\n onChange={() => setScale(s)}\n />\n {s}×\n </label>\n ))}\n </span>\n </div>\n\n <div className=\"lk-export__actions\">\n <button type=\"button\" disabled={busy || !chosen} onClick={() => run(download)}>\n Download\n </button>\n <button type=\"button\" disabled={busy || !chosen} onClick={() => run(copy)}>\n Copy\n </button>\n </div>\n\n {error ? (\n <p className=\"lk-export__error\" role=\"alert\">\n {error}\n </p>\n ) : null}\n </div>\n </Callout>\n </span>\n );\n}\n","import { Input } from '../passthrough/weasel-ui';\nimport { useAnnotations } from './AnnotationsContext';\nimport type { AnnotationMeaning } from './types';\n\n/** Props for `<MarkList>`. */\nexport interface MarkListProps {\n /** The instrument's vocabulary. Omitted, rows carry no status control —\n * a host that declared none owns what a mark means. */\n meaning?: AnnotationMeaning;\n /** The live config, for answering staleness. */\n config: unknown;\n}\n\n/** Every mark on this trial's targets: what it says, and whether it still\n * describes the picture under it.\n *\n * Reads the store through the hook, which re-renders on every mutation — so a\n * mark drawn on a pane appears here without anything wiring the two. */\nexport function MarkList({ meaning, config }: MarkListProps) {\n const marks = useAnnotations();\n const all = marks.query();\n const statuses = meaning?.statuses ?? [];\n\n if (all.length === 0) {\n return <div className=\"lk-mark-list__empty\">No marks yet</div>;\n }\n\n return (\n <ul className=\"lk-mark-list\">\n {all.map((a) => {\n const stale = marks.isStale(a, config);\n return (\n <li className=\"lk-mark-list__row\" key={a.id}>\n <div className=\"lk-mark-list__head\">\n <span className=\"lk-mark-list__kind\">{a.kind}</span>\n <span className=\"lk-mark-list__target\">{a.target}</span>\n {stale ? <span className=\"lk-mark-list__stale\">stale</span> : null}\n <button\n type=\"button\"\n className=\"lk-mark-list__drop\"\n aria-label={`Remove ${a.kind} on ${a.target}`}\n onClick={() => marks.remove(a.id)}\n >\n ×\n </button>\n </div>\n <Input\n className=\"lk-mark-list__title\"\n aria-label={`Title of ${a.kind} on ${a.target}`}\n value={a.title ?? ''}\n placeholder=\"Untitled\"\n onChange={(next) => marks.update(a.id, { title: next })}\n />\n {statuses.length > 0 ? (\n // A native select: it carries role, name and keyboard operability\n // for free, and a sidebar row is not the place to rebuild them.\n <select\n className=\"lk-mark-list__status\"\n aria-label={`Status of ${a.kind} on ${a.target}`}\n value={a.status ?? ''}\n onChange={(e) => marks.update(a.id, { status: e.target.value })}\n >\n <option value=\"\">—</option>\n {statuses.map((s) => (\n <option key={s.id} value={s.id}>\n {s.label}\n </option>\n ))}\n </select>\n ) : null}\n </li>\n );\n })}\n </ul>\n );\n}\n","import {\n CloneIcon,\n CloseIcon,\n FitIcon,\n LoupeIcon,\n RedoIcon,\n ResetIcon,\n SnapshotIcon,\n UndoIcon,\n ZoomInIcon,\n ZoomOutIcon,\n} from '@weasel-js/ui';\nimport { ExportMenu } from '../annotations/ExportMenu';\nimport { MarkList } from '../annotations/MarkList';\nimport type { ControlRenderer } from '../config/types';\nimport { ControlPanel } from '../controls/ControlPanel';\nimport type { Instrument } from '../instrument/types';\nimport { MenuButton } from '../passthrough/weasel-ui';\nimport { FpsMeter } from '../primitives/FpsMeter';\nimport { ScaleIndicator } from '../primitives/ScaleIndicator';\nimport { ZoomControl } from '../primitives/ZoomControl';\nimport type { TrialChromeContext, TrialContribution } from './types';\n\nconst ZOOM_STEP = 1.25;\n\n/** The property groups inside a contribution are folded under keys prefixed\n * with that contribution's id, so a group called `marks` cannot fold the\n * sidebar section of the same name. `ControlPanel` keys by bare label, so the\n * prefix goes on here and comes off again. */\nfunction groupFolds(\n collapsedSections: Readonly<Record<string, boolean>>,\n id: string,\n): Record<string, boolean> {\n const prefix = `${id}/`;\n const out: Record<string, boolean> = {};\n for (const [key, value] of Object.entries(collapsedSections)) {\n if (key.startsWith(prefix)) out[key.slice(prefix.length)] = value;\n }\n return out;\n}\n\n/**\n * The contributions a trial gets from what its instrument declared. This is\n * the whole \"declaring a capability provides the chrome\" rule — it replaces\n * the presence checks that used to be spread across the runtime.\n */\nexport function builtinContributions(\n instrument: Instrument,\n ctx: TrialChromeContext,\n controls?: Record<string, ControlRenderer>,\n): TrialContribution[] {\n const out: TrialContribution[] = [];\n const zoom = ctx.zoom;\n\n // Weasel history is the undo authority for marks, so declaring `annotations`\n // gets the buttons whether or not the instrument also declares `undo`.\n if (instrument.undo != null || instrument.annotations != null) {\n out.push({\n id: 'undo',\n region: 'toolbar',\n group: 'history',\n item: {\n icon: UndoIcon,\n label: 'Undo',\n shortcut: 'Mod+Z',\n disabled: !ctx.canUndo,\n onActivate: ctx.undo,\n },\n });\n out.push({\n id: 'redo',\n region: 'toolbar',\n group: 'history',\n item: {\n icon: RedoIcon,\n label: 'Redo',\n shortcut: 'Mod+Shift+Z',\n disabled: !ctx.canRedo,\n onActivate: ctx.redo,\n },\n });\n }\n\n // A tool id shares the contribution namespace, so a tool called `close`\n // collides with the built-in close button and throws. Annotation tools are\n // not here: the lab's rail carries them.\n for (const t of instrument.tools?.tools ?? []) {\n out.push({\n id: t.id,\n region: 'palette',\n group: t.group,\n item: { icon: t.icon, label: t.label, shortcut: t.shortcut },\n });\n }\n\n if (instrument.loupe != null) {\n out.push({\n id: 'loupe',\n region: 'toolbar',\n group: 'view',\n item: {\n icon: LoupeIcon,\n label: 'Loupe',\n pressed: ctx.loupeOn,\n onActivate: ctx.toggleLoupe,\n },\n });\n }\n\n // Zoom acts on the view of the trial, so it is a viewport control. A trial\n // holding a non-2D view reports zoom as null and gets none of this.\n if ((instrument.canvas != null || instrument.stage != null) && zoom !== null) {\n out.push({\n id: 'zoom-out',\n region: 'viewport',\n group: 'zoom',\n item: {\n icon: ZoomOutIcon,\n label: 'Zoom out',\n onActivate: () => ctx.setZoom(zoom / ZOOM_STEP),\n },\n });\n out.push({\n id: 'zoom-in',\n region: 'viewport',\n group: 'zoom',\n item: {\n icon: ZoomInIcon,\n label: 'Zoom in',\n onActivate: () => ctx.setZoom(zoom * ZOOM_STEP),\n },\n });\n out.push({\n id: 'actual-size',\n region: 'viewport',\n group: 'zoom',\n item: { icon: FitIcon, label: 'Actual size', onActivate: () => ctx.setZoom(1) },\n });\n out.push({\n id: 'zoom-control',\n region: 'viewport',\n group: 'zoom',\n render: (c) => <ZoomControl zoom={c.zoom ?? 1} onZoomChange={c.setZoom} />,\n });\n out.push({\n id: 'scale',\n region: 'status',\n group: 'view',\n render: (c) => <ScaleIndicator zoom={c.zoom ?? 1} />,\n });\n if (instrument.canvas != null) {\n out.push({\n id: 'fps',\n region: 'status',\n group: 'view',\n end: true,\n render: () => <FpsMeter />,\n });\n }\n }\n\n if (instrument.annotations != null) {\n // A popover, so it takes the `render` escape: the panel picks a target,\n // and an icon button cannot ask which one.\n out.push({\n id: 'export',\n region: 'toolbar',\n group: 'trial',\n end: true,\n render: () => <ExportMenu />,\n });\n out.push({\n id: 'marks',\n region: 'sidebar',\n item: {\n title: 'Marks',\n body: <MarkList meaning={instrument.annotations.meaning} config={ctx.config} />,\n },\n });\n }\n\n if (Object.keys(ctx.configSchema.group.children).length > 0) {\n out.push({\n id: 'settings',\n region: 'sidebar',\n item: {\n title: 'Settings',\n body: (\n <ControlPanel\n schema={ctx.configSchema}\n config={ctx.config as Record<string, unknown>}\n auto={ctx.auto}\n setConfig={(key, value) => ctx.setConfig(String(key), value)}\n renderers={controls}\n collapsed={groupFolds(ctx.collapsedSections, 'settings')}\n onCollapse={(label, next) => ctx.setSectionCollapsed(`settings/${label}`, next)}\n />\n ),\n },\n });\n }\n\n if (ctx.savedSnapshots.length > 0) {\n // A menu is not an icon button, so it takes the render escape.\n out.push({\n id: 'snapshot-load',\n region: 'toolbar',\n group: 'trial',\n end: true,\n render: (c) => (\n <MenuButton\n aria-label=\"Load snapshot\"\n label=\"Load…\"\n items={c.savedSnapshots.map((sn) => ({ value: sn.id, label: sn.name }))}\n onAction={(id) => c.loadSnapshot(id)}\n />\n ),\n });\n }\n out.push({\n id: 'clone',\n region: 'titlebar',\n end: true,\n item: { icon: CloneIcon, label: 'Clone trial', onActivate: ctx.clone },\n });\n out.push({\n id: 'reset',\n region: 'titlebar',\n end: true,\n item: { icon: ResetIcon, label: 'Reset trial', onActivate: ctx.reset },\n });\n out.push({\n id: 'snapshot',\n region: 'titlebar',\n end: true,\n item: {\n icon: SnapshotIcon,\n label: 'Save snapshot',\n shortcut: 'Mod+S',\n onActivate: () => ctx.saveSnapshot(),\n },\n });\n out.push({\n id: 'close',\n region: 'titlebar',\n end: true,\n item: {\n icon: CloseIcon,\n label: ctx.isLastTrial ? 'Cannot close the last trial' : 'Close trial',\n danger: true,\n disabled: ctx.isLastTrial,\n onActivate: ctx.close,\n },\n });\n\n return out;\n}\n","import type { InstrumentList } from '../instrument/types';\n\n/**\n * The tool the lab's slot holds, once its default is applied: a lab with any\n * annotating instrument starts in `pointer`, so a first click reaches the\n * instrument rather than the marks over it.\n */\nexport function resolveLabTool(slot: string | null, instruments: InstrumentList): string | null {\n if (slot !== null) return slot;\n return instruments.some((i) => i.annotations != null) ? 'pointer' : null;\n}\n","/**\n * Concatenate contribution bundles into one list, preserving order — order\n * decides how a region lays its contributions out, so it is part of the\n * result, not an accident of it.\n *\n * Throws on a duplicate id rather than dropping one: a contribution silently\n * losing to a later bundle is the failure a registry exists to prevent.\n */\nexport function mergeContributions<T extends { id: string }>(\n ...bundles: readonly (readonly T[])[]\n): T[] {\n const out: T[] = [];\n const seen = new Set<string>();\n for (const bundle of bundles) {\n for (const entry of bundle) {\n if (seen.has(entry.id)) {\n throw new Error(\n `[labkit] mergeContributions: duplicate contribution id \"${entry.id}\". ` +\n 'Two bundles registered the same id; rename one, or suppress the ' +\n 'built-in before adding yours.',\n );\n }\n seen.add(entry.id);\n out.push(entry);\n }\n }\n return out;\n}\n\n/**\n * Drop contributions by id. Throws when an id is not present: a typo that\n * silently suppresses nothing is the same class of bug as a duplicate id\n * silently winning.\n */\nexport function suppressContributions<T extends { id: string }>(\n bundle: readonly T[],\n ids: readonly string[],\n): T[] {\n const present = new Set(bundle.map((c) => c.id));\n for (const id of ids) {\n if (!present.has(id)) {\n throw new Error(\n `[labkit] cannot suppress \"${id}\": no contribution with that id. ` +\n `Present ids: ${[...present].join(', ')}`,\n );\n }\n }\n const drop = new Set(ids);\n return bundle.filter((c) => !drop.has(c.id));\n}\n","import type { ReactNode } from 'react';\nimport type {\n RegionContribution,\n SidebarSection,\n SidebarSlotContext,\n TrialChromeContext,\n} from '../types';\n\n/** Props for `<SidebarRegion>`. */\nexport interface SidebarRegionProps<TCtx extends SidebarSlotContext = TrialChromeContext> {\n contributions: readonly RegionContribution<NoInfer<TCtx>>[];\n ctx: TCtx;\n /** Which region's items to lay out. */\n region?: string;\n}\n\nfunction Section({\n title,\n collapsed,\n onCollapsedChange,\n onUndock,\n children,\n}: {\n title: string;\n collapsed: boolean;\n onCollapsedChange: (collapsed: boolean) => void;\n onUndock?: () => void;\n children: ReactNode;\n}) {\n return (\n <section className=\"lk-sidebar-section\">\n <div className=\"lk-sidebar-section__bar\">\n <button\n type=\"button\"\n className=\"lk-sidebar-section__head\"\n aria-expanded={!collapsed}\n onClick={() => onCollapsedChange(!collapsed)}\n >\n {title}\n </button>\n {onUndock ? (\n <button\n type=\"button\"\n className=\"lk-sidebar-section__undock\"\n aria-label={`Undock ${title}`}\n title={`Undock ${title}`}\n onClick={onUndock}\n >\n ⧉\n </button>\n ) : null}\n </div>\n {collapsed ? null : <div className=\"lk-sidebar-section__body\">{children}</div>}\n </section>\n );\n}\n\n/** Lays `sidebar` contributions out as titled, collapsible sections — a\n * trial's, or the lab's. A section the trial has torn out is not rendered\n * here — `Trial` portals its body into the workspace instead. A context with\n * no `undockPanel` offers no tear-out. */\nexport function SidebarRegion<TCtx extends SidebarSlotContext = TrialChromeContext>({\n contributions,\n ctx,\n region = 'sidebar',\n}: SidebarRegionProps<TCtx>) {\n if (contributions.length === 0) return null;\n return (\n <>\n {contributions.map((c) => {\n if (c.render) return <div key={c.id}>{c.render(ctx)}</div>;\n if (c.region !== region || !c.item) return null;\n if (ctx.undockedPanels?.includes(c.id)) return null;\n const item = c.item as SidebarSection;\n return (\n <Section\n key={c.id}\n title={item.title}\n collapsed={ctx.collapsedSections[c.id] ?? item.defaultCollapsed ?? false}\n onCollapsedChange={(next) => ctx.setSectionCollapsed(c.id, next)}\n onUndock={\n ctx.undockPanel && item.undockable !== false\n ? () => ctx.undockPanel?.(c.id, item.undockAs ?? 'tile')\n : undefined\n }\n >\n {item.body}\n </Section>\n );\n })}\n </>\n );\n}\n","import { StatusBar } from '../../primitives/StatusBar';\nimport type { RegionContribution, StatusReadout, TrialChromeContext } from '../types';\n\n/** Props for `<StatusRegion>`. */\nexport interface StatusRegionProps<TCtx = TrialChromeContext> {\n contributions: readonly RegionContribution<NoInfer<TCtx>>[];\n ctx: TCtx;\n /** Which region's readouts to lay out; the lab's footer is `footer`. */\n region?: string;\n}\n\n/** Lays a bar's readouts out. */\nexport function StatusRegion<TCtx = TrialChromeContext>({\n contributions,\n ctx,\n region = 'status',\n}: StatusRegionProps<TCtx>) {\n if (contributions.length === 0) return null;\n return (\n <StatusBar>\n {contributions.map((c) => {\n if (c.render)\n return (\n <StatusBar.Section key={c.id} end={c.end}>\n {c.render(ctx)}\n </StatusBar.Section>\n );\n if (c.region !== region || !c.item) return null;\n const item = c.item as StatusReadout;\n return (\n <StatusBar.Section key={c.id} end={c.end}>\n <span title={item.title}>{item.text}</span>\n </StatusBar.Section>\n );\n })}\n </StatusBar>\n );\n}\n","import type { ReactNode } from 'react';\nimport { Toolbar } from '../../primitives/Toolbar';\nimport type { RegionContribution, ToolbarItem, TrialChromeContext } from '../types';\n\n/** Props for `<ToolbarRegion>`. */\nexport interface ToolbarRegionProps<TCtx = TrialChromeContext> {\n contributions: readonly RegionContribution<NoInfer<TCtx>>[];\n ctx: TCtx;\n /** Which region's items to lay out; the lab's action bar is `header`. */\n region?: string;\n /** The bar's accessible name. */\n label?: string;\n}\n\ninterface Group<TCtx> {\n key: string;\n end: boolean;\n entries: RegionContribution<TCtx>[];\n}\n\n/** Bucket by group, preserving first-appearance order. Ungrouped\n * contributions each become their own bucket so they stay in place. */\nfunction groupsOf<TCtx>(contributions: readonly RegionContribution<TCtx>[]): Group<TCtx>[] {\n const groups: Group<TCtx>[] = [];\n const byKey = new Map<string, Group<TCtx>>();\n for (const c of contributions) {\n if (c.group == null) {\n groups.push({ key: c.id, end: c.end ?? false, entries: [c] });\n continue;\n }\n let g = byKey.get(c.group);\n if (!g) {\n g = { key: c.group, end: c.end ?? false, entries: [] };\n byKey.set(c.group, g);\n groups.push(g);\n }\n g.entries.push(c);\n }\n return groups;\n}\n\nfunction renderEntry<TCtx>(c: RegionContribution<TCtx>, ctx: TCtx, region: string): ReactNode {\n if (c.render) return <span key={c.id}>{c.render(ctx)}</span>;\n if (c.region !== region || !c.item) return null;\n const {\n icon: Icon,\n label,\n shortcut,\n disabled,\n danger,\n showLabel,\n pressed,\n onActivate,\n } = c.item as ToolbarItem<TCtx>;\n return (\n <Toolbar.Button\n key={c.id}\n iconOnly={!showLabel}\n variant={danger ? 'danger' : 'default'}\n disabled={disabled}\n pressed={pressed}\n aria-label={label}\n title={shortcut ? `${label} (${shortcut})` : label}\n onClick={() => onActivate(ctx)}\n >\n <Icon size={16} />\n {showLabel ? <span>{label}</span> : null}\n </Toolbar.Button>\n );\n}\n\n/** Lays a bar's contributions out, grouped by their `group`. */\nexport function ToolbarRegion<TCtx = TrialChromeContext>({\n contributions,\n ctx,\n region = 'toolbar',\n label = 'Trial actions',\n}: ToolbarRegionProps<TCtx>) {\n if (contributions.length === 0) return null;\n const groups = groupsOf(contributions);\n return (\n <Toolbar aria-label={label}>\n {groups.map((g) => (\n <Toolbar.Group key={g.key} end={g.end} aria-label={g.key}>\n {g.entries.map((c) => renderEntry(c, ctx, region))}\n </Toolbar.Group>\n ))}\n </Toolbar>\n );\n}\n","import { useContext, useMemo } from 'react';\nimport { useStore } from 'zustand/react';\nimport { useLabContext } from '../lab/LabContext';\nimport { LabStoreContext } from '../state/context';\nimport { usePersistedState } from '../state/usePersistedState';\nimport { resolveLabTool } from '../tools/labTool';\nimport type { TrialTool } from '../tools/types';\nimport type { LabChromeContext, LabContribution, LabRegion } from './labTypes';\nimport { mergeContributions } from './merge';\nimport { SidebarRegion } from './regions/SidebarRegion';\nimport { StatusRegion } from './regions/StatusRegion';\nimport { ToolbarRegion } from './regions/ToolbarRegion';\n\n/** The lab's chrome context: the lab itself, plus the lab's tool slot. Throws\n * outside a `<Lab>`. */\nexport function useLabChromeContext(): LabChromeContext {\n const lab = useLabContext();\n const storeCtx = useContext(LabStoreContext);\n if (!storeCtx) throw new Error('[labkit] lab chrome requires <LabStoreProvider>');\n const slot = useStore(storeCtx.store, (s) => s.activeToolId);\n const storeInstruments = useStore(storeCtx.store, (s) => s.instruments);\n const activeToolId = resolveLabTool(slot, storeInstruments ?? lab.instruments);\n const setLabTool = useStore(storeCtx.store, (s) => s.setLabTool);\n return useMemo(\n () => ({ ...lab, activeToolId, setActiveTool: setLabTool }),\n [lab, activeToolId, setLabTool],\n );\n}\n\n/** The lab's contributions for one region, in declaration order. */\nexport function contributionsIn<TCtx = LabChromeContext>(\n contributions: readonly LabContribution<TCtx>[],\n region: LabRegion,\n): LabContribution<TCtx>[] {\n return contributions.filter((c) => c.region === region);\n}\n\n/** The palette contributions a lab's `tools` stand for. Declaring a tool is\n * shorthand for contributing a palette item that writes the lab's tool\n * slot. */\nexport function toolContributions(tools: readonly TrialTool[]): LabContribution[] {\n return tools.map((t) => ({\n id: t.id,\n region: 'palette' as const,\n ...(t.group === undefined ? {} : { group: t.group }),\n item: {\n icon: t.icon,\n label: t.label,\n ...(t.shortcut === undefined ? {} : { shortcut: t.shortcut }),\n },\n }));\n}\n\n/** Everything the lab's chrome renders, from both of the ways a lab declares\n * it. Tools and contributions share one id namespace, so a tool colliding\n * with a contribution throws here rather than one of them silently losing. */\nexport function labContributions(\n tools: readonly TrialTool[] | undefined,\n chrome: readonly LabContribution[] | undefined,\n): LabContribution[] {\n return mergeContributions<LabContribution>(toolContributions(tools ?? []), [...(chrome ?? [])]);\n}\n\n/** Props shared by the lab's region mounts. Each takes the lab's whole\n * contribution list and lays out the part addressed to it. */\nexport interface LabRegionProps {\n contributions: readonly LabContribution[];\n}\n\n/** The lab's action bar, in the shell header beside the title. */\nexport function LabHeaderRegion({ contributions }: LabRegionProps) {\n const ctx = useLabChromeContext();\n return (\n <ToolbarRegion\n region=\"header\"\n label=\"Lab actions\"\n contributions={contributionsIn(contributions, 'header')}\n ctx={ctx}\n />\n );\n}\n\nfunction LabSections({ contributions, region }: LabRegionProps & { region: 'sidebar' | 'aside' }) {\n const lab = useLabChromeContext();\n const [collapsedSections, setFolds] = usePersistedState<Record<string, boolean>>(\n `lk-lab-${region}-folds`,\n {},\n { scope: 'lab' },\n );\n const ctx = useMemo(\n () => ({\n ...lab,\n collapsedSections,\n setSectionCollapsed: (key: string, collapsed: boolean) =>\n setFolds((f) => ({ ...f, [key]: collapsed })),\n }),\n [lab, collapsedSections, setFolds],\n );\n return (\n <SidebarRegion\n contributions={contributionsIn(contributions, region)}\n ctx={ctx}\n region={region}\n />\n );\n}\n\n/** The lab's sidebar sections. Fold state is a lab-scoped persisted value, so it\n * survives a reload in a stored lab and lasts the session in an unstored one. */\nexport function LabSidebarRegion({ contributions }: LabRegionProps) {\n return <LabSections contributions={contributions} region=\"sidebar\" />;\n}\n\n/** The lab's aside sections, on the far side of the workspace from the sidebar.\n * Fold state persists the way the sidebar's does. */\nexport function LabAsideRegion({ contributions }: LabRegionProps) {\n return <LabSections contributions={contributions} region=\"aside\" />;\n}\n\n/** The lab's readouts, in the shell footer below the workspace. */\nexport function LabFooterRegion({ contributions }: LabRegionProps) {\n const ctx = useLabChromeContext();\n return (\n <StatusRegion\n region=\"footer\"\n contributions={contributionsIn(contributions, 'footer')}\n ctx={ctx}\n />\n );\n}\n","import { ToolButton, ToolGroup } from '../../passthrough/weasel-ui';\nimport { useRovingTabIndex } from '../../primitives/useRovingTabIndex';\nimport type { RegionContribution, ToolItem, ToolSlotContext, TrialChromeContext } from '../types';\n\n/** Props for `<PaletteRegion>`. */\nexport interface PaletteRegionProps<TCtx extends ToolSlotContext = TrialChromeContext> {\n contributions: readonly RegionContribution<NoInfer<TCtx>>[];\n ctx: TCtx;\n /** Which region's items to lay out. The lab's rail names the same box\n * `palette` too, so this only moves for a chrome that does not. */\n region?: string;\n}\n\n/** A tool strip: a trial's, or the lab's. Selection lives in whichever tool\n * slot the context carries; this region only reflects it. An item carrying\n * `onActivate` is a command instead — it presses, and never latches. */\nexport function PaletteRegion<TCtx extends ToolSlotContext = TrialChromeContext>({\n contributions,\n ctx,\n region = 'palette',\n}: PaletteRegionProps<TCtx>) {\n const { ref, onKeyDown } = useRovingTabIndex<HTMLDivElement>('vertical');\n if (contributions.length === 0) return null;\n return (\n <div\n ref={ref}\n className=\"lk-palette-region\"\n role=\"toolbar\"\n aria-label=\"Tools\"\n aria-orientation=\"vertical\"\n onKeyDown={onKeyDown}\n >\n <ToolGroup orientation=\"vertical\">\n {contributions.map((c) => {\n if (c.render) return <span key={c.id}>{c.render(ctx)}</span>;\n if (c.region !== region || !c.item) return null;\n const { icon: Icon, label, shortcut, disabled, onActivate } = c.item as ToolItem<TCtx>;\n return (\n <ToolButton\n key={c.id}\n icon={<Icon size={16} />}\n label={label}\n shortcut={shortcut}\n active={onActivate ? false : ctx.activeToolId === c.id}\n disabled={disabled}\n onClick={onActivate ? () => onActivate(ctx) : () => ctx.setActiveTool(c.id)}\n />\n );\n })}\n </ToolGroup>\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport type { TrialChromeContext, TrialContribution } from '../types';\n\n/** Which end of the title bar a `<TitleBarRegion>` lays out: `'lead'` renders\n * the contributions that leave `end` unset, before the title; `'actions'`\n * renders the ones that set it, after everything else. */\nexport type TitleBarPlacement = 'lead' | 'actions';\n\n/** Props for `<TitleBarRegion>`. */\nexport interface TitleBarRegionProps {\n contributions: readonly TrialContribution[];\n ctx: TrialChromeContext;\n /** Defaults to `'actions'`, where the built-ins live. */\n placement?: TitleBarPlacement;\n}\n\nfunction renderEntry(c: TrialContribution, ctx: TrialChromeContext): ReactNode {\n if (c.render) return <span key={c.id}>{c.render(ctx)}</span>;\n if (c.region !== 'titlebar' || !c.item) return null;\n const { icon: Icon, label, shortcut, disabled, danger, onActivate } = c.item;\n return (\n <button\n key={c.id}\n type=\"button\"\n className={`lk-titlebar-button${danger ? ' lk-titlebar-button--danger' : ''}`}\n disabled={disabled}\n aria-label={label}\n title={shortcut ? `${label} (${shortcut})` : label}\n onClick={() => onActivate(ctx)}\n // The bar behind these buttons is the window drag surface, so a press\n // that lands here must not also start a drag.\n onPointerDown={(e) => e.stopPropagation()}\n onMouseDown={(e) => e.stopPropagation()}\n >\n <Icon size={16} />\n </button>\n );\n}\n\n/** Lays a trial's `titlebar` contributions out at one end of the bar. */\nexport function TitleBarRegion({ contributions, ctx, placement = 'actions' }: TitleBarRegionProps) {\n const wanted = placement === 'actions';\n const mine = contributions.filter((c) => (c.end ?? false) === wanted);\n if (mine.length === 0) return null;\n return (\n <span className={wanted ? 'lk-trial__titlebar-actions' : 'lk-trial__titlebar-lead'}>\n {mine.map((c) => renderEntry(c, ctx))}\n </span>\n );\n}\n","import { useRovingTabIndex } from '../../primitives/useRovingTabIndex';\nimport type { TrialChromeContext, TrialContribution } from '../types';\n\n/** Props for `<ViewportRegion>`. */\nexport interface ViewportRegionProps {\n contributions: readonly TrialContribution[];\n ctx: TrialChromeContext;\n}\n\n/**\n * Controls acting on the view of a trial. Anchored inside the content well\n * rather than in the toolbar, which acts on the trial itself.\n */\nexport function ViewportRegion({ contributions, ctx }: ViewportRegionProps) {\n const { ref, onKeyDown } = useRovingTabIndex<HTMLDivElement>();\n if (contributions.length === 0) return null;\n return (\n <div\n ref={ref}\n className=\"lk-viewport-controls\"\n role=\"toolbar\"\n aria-label=\"View\"\n onKeyDown={onKeyDown}\n >\n {contributions.map((c) => {\n if (c.render) return <span key={c.id}>{c.render(ctx)}</span>;\n if (c.region !== 'viewport' || !c.item) return null;\n const { icon: Icon, label, disabled, onActivate } = c.item;\n return (\n <button\n key={c.id}\n type=\"button\"\n className=\"lk-viewport-controls__button\"\n aria-label={label}\n title={label}\n disabled={disabled}\n onClick={() => onActivate(ctx)}\n >\n <Icon size={16} />\n </button>\n );\n })}\n </div>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { r5, n4 } from './chunk-S2SHZRD7.js';
1
+ import { r6, n4 } from './chunk-LASCBWW7.js';
2
2
  import { openPointerSession } from '@weasel-js/core';
3
3
  import { useState, useRef, useId, useEffect, Fragment as Fragment$1 } from 'react';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -119,7 +119,7 @@ function LayerList({
119
119
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
120
120
  /* @__PURE__ */ jsxs("div", { className: cls.join(" "), children: [
121
121
  nested && (kids.length > 0 ? /* @__PURE__ */ jsx(
122
- r5,
122
+ r6,
123
123
  {
124
124
  open,
125
125
  onToggle: () => toggleCollapsed(layer.id),
@@ -166,5 +166,5 @@ function LayerList({
166
166
  }
167
167
 
168
168
  export { LayerList };
169
- //# sourceMappingURL=chunk-MUKOW3TC.js.map
170
- //# sourceMappingURL=chunk-MUKOW3TC.js.map
169
+ //# sourceMappingURL=chunk-D35PFTS7.js.map
170
+ //# sourceMappingURL=chunk-D35PFTS7.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/layers/LayerList.tsx"],"names":["n","Fragment","r"],"mappings":"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","file":"chunk-MUKOW3TC.js","sourcesContent":["import { openPointerSession, type PointerSession } from '@weasel-js/core';\nimport { Disclosure } from '@weasel-js/ui';\nimport {\n Fragment,\n type ReactNode,\n type PointerEvent as ReactPointerEvent,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport type { LayerDescriptor } from '../instrument/types';\nimport { DragHandleGlyph } from '../passthrough/weasel-ui';\n\n/** A layer that may itself contain layers. A plain `LayerDescriptor` is one\n * of these with no children, so a flat list needs no change. */\nexport interface LayerTreeNode extends LayerDescriptor {\n children?: LayerTreeNode[];\n /** Render this node's children hidden on first paint. Ignored once\n * `collapsedIds` is supplied. */\n defaultCollapsed?: boolean;\n}\n\n/** Props for `<LayerList>`. */\nexport interface LayerListProps {\n layers: LayerTreeNode[];\n visibility: Record<string, boolean>;\n /** The whole tree, with the dragged node moved. Reordering is scoped to a\n * node's siblings: a drag never changes which parent a layer sits under. */\n onReorder: (newOrder: LayerTreeNode[]) => void;\n onToggle: (id: string, visible: boolean) => void;\n /** Ids whose children are hidden. Supplying it makes collapse controlled;\n * without it the list keeps its own, seeded from `defaultCollapsed`. */\n collapsedIds?: readonly string[];\n onCollapsedChange?: (ids: string[]) => void;\n className?: string;\n}\n\ninterface DragState {\n /** Id of the dragged row's parent, or null at the top level. */\n parentId: string | null;\n fromIndex: number;\n toIndex: number;\n startY: number;\n /** Row height plus row gap, measured when the drag starts. */\n pitch: number;\n}\n\n/** Which row the drag currently marks. */\ninterface DragMark {\n parentId: string | null;\n index: number;\n}\n\nfunction findNode(nodes: LayerTreeNode[], id: string): LayerTreeNode | null {\n for (const node of nodes) {\n if (node.id === id) return node;\n const hit = node.children ? findNode(node.children, id) : null;\n if (hit) return hit;\n }\n return null;\n}\n\nfunction siblingsOf(layers: LayerTreeNode[], parentId: string | null): LayerTreeNode[] {\n if (parentId === null) return layers;\n return findNode(layers, parentId)?.children ?? [];\n}\n\nfunction withChildren(\n nodes: LayerTreeNode[],\n parentId: string | null,\n next: LayerTreeNode[],\n): LayerTreeNode[] {\n if (parentId === null) return next;\n return nodes.map((node) => {\n if (node.id === parentId) return { ...node, children: next };\n if (node.children) return { ...node, children: withChildren(node.children, parentId, next) };\n return node;\n });\n}\n\nfunction collectCollapsed(nodes: LayerTreeNode[], into: Set<string>): Set<string> {\n for (const node of nodes) {\n if (node.defaultCollapsed) into.add(node.id);\n if (node.children) collectCollapsed(node.children, into);\n }\n return into;\n}\n\nfunction anyNested(nodes: LayerTreeNode[]): boolean {\n return nodes.some((n) => (n.children?.length ?? 0) > 0);\n}\n\n/** A reorderable list of layers with per-layer visibility toggles. Layers\n * marked `alwaysOn` are pinned and cannot be reordered or hidden. Layers with\n * `children` render as an expandable subtree. */\nexport function LayerList({\n layers,\n visibility,\n onReorder,\n onToggle,\n collapsedIds,\n onCollapsedChange,\n className,\n}: LayerListProps) {\n const [dragMark, setDragMark] = useState<DragMark | null>(null);\n const [ownCollapsed, setOwnCollapsed] = useState<Set<string>>(() =>\n collectCollapsed(layers, new Set()),\n );\n const dragRef = useRef<DragState | null>(null);\n const sessionRef = useRef<PointerSession | null>(null);\n const uid = useId();\n // The session's callbacks outlive the render that opened them, so the commit\n // reads its inputs here rather than from that render's closure.\n const commitRef = useRef({ layers, onReorder });\n commitRef.current = { layers, onReorder };\n\n useEffect(() => () => sessionRef.current?.cancel(), []);\n\n const collapsed = collapsedIds ? new Set(collapsedIds) : ownCollapsed;\n\n const toggleCollapsed = (id: string) => {\n const next = new Set(collapsed);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n if (!collapsedIds) setOwnCollapsed(next);\n onCollapsedChange?.([...next]);\n };\n\n if (layers.length === 0) {\n return (\n <div className={className ? `lk-layer-list ${className}` : 'lk-layer-list'}>\n <div className=\"lk-layer-list__empty\">No layers</div>\n </div>\n );\n }\n\n const clearDrag = () => {\n dragRef.current = null;\n sessionRef.current = null;\n setDragMark(null);\n };\n\n const startDrag = (e: ReactPointerEvent<HTMLElement>, parentId: string | null, index: number) => {\n // Measured at grab time rather than hardcoded: a restyle that changes row\n // height or gap would otherwise silently skew every drag distance.\n const row = e.currentTarget.closest('.lk-layer-list__row');\n const list = row?.parentElement;\n const gap = list ? Number.parseFloat(getComputedStyle(list).rowGap) || 0 : 0;\n const pitch = row ? row.getBoundingClientRect().height + gap : 0;\n const drag: DragState = {\n parentId,\n fromIndex: index,\n toIndex: index,\n startY: e.clientY,\n pitch: pitch > 0 ? pitch : 1,\n };\n dragRef.current = drag;\n setDragMark({ parentId, index });\n sessionRef.current = openPointerSession(e.currentTarget, e, {\n onMove: (ev) => {\n const delta = Math.round((ev.clientY - drag.startY) / drag.pitch);\n const siblings = siblingsOf(commitRef.current.layers, parentId);\n const last = siblings.filter((l) => !l.alwaysOn).length - 1;\n drag.toIndex = Math.min(last, Math.max(0, drag.fromIndex + delta));\n setDragMark({ parentId, index: drag.toIndex });\n },\n onEnd: () => {\n const { layers: tree, onReorder: commit } = commitRef.current;\n const { fromIndex, toIndex } = drag;\n clearDrag();\n if (toIndex === fromIndex) return;\n const siblings = siblingsOf(tree, parentId);\n const rows = siblings.filter((l) => !l.alwaysOn);\n const locked = siblings.filter((l) => l.alwaysOn);\n const next = [...rows];\n const [moved] = next.splice(fromIndex, 1);\n if (moved) next.splice(toIndex, 0, moved);\n commit(withChildren(tree, parentId, [...next, ...locked]));\n },\n // An interrupted drag never named a destination, so it reorders nothing.\n onCancel: clearDrag,\n });\n };\n\n // A twisty column on every row keeps labels aligned across depths, but a\n // flat list would only be paying 20px for it.\n const nested = anyNested(layers);\n\n function renderRow(\n layer: LayerTreeNode,\n parentId: string | null,\n index: number,\n path: string,\n pinned: boolean,\n ): ReactNode {\n const kids = layer.children ?? [];\n const open = kids.length > 0 && !collapsed.has(layer.id);\n const bodyId = `${uid}${path}`;\n const dragging = !pinned && dragMark?.parentId === parentId && dragMark.index === index;\n const cls = ['lk-layer-list__row'];\n if (dragging) cls.push('lk-layer-list__row--dragging');\n if (pinned) cls.push('lk-layer-list__row--pinned');\n return (\n <Fragment key={layer.id}>\n <div className={cls.join(' ')}>\n {nested &&\n (kids.length > 0 ? (\n <Disclosure\n open={open}\n onToggle={() => toggleCollapsed(layer.id)}\n label={`${layer.label} sublayers`}\n controls={bodyId}\n />\n ) : (\n <span className=\"lk-layer-list__twisty-gap\" />\n ))}\n {pinned ? (\n <span className=\"lk-layer-list__lock\" role=\"img\" aria-label=\"Always on\">\n 🔒\n </span>\n ) : (\n <>\n <button\n type=\"button\"\n className=\"lk-layer-list__handle\"\n aria-label={`Reorder ${layer.label}`}\n onPointerDown={(e) => startDrag(e, parentId, index)}\n >\n <DragHandleGlyph size={13} />\n </button>\n <input\n className=\"lk-layer-list__check\"\n type=\"checkbox\"\n checked={visibility[layer.id] !== false}\n onChange={(e) => onToggle(layer.id, e.target.checked)}\n aria-label={`Toggle ${layer.label}`}\n />\n </>\n )}\n <span className=\"lk-layer-list__label\">{layer.label}</span>\n </div>\n {open && (\n <div id={bodyId} className=\"lk-layer-list__children\">\n {renderLevel(kids, layer.id, path)}\n </div>\n )}\n </Fragment>\n );\n }\n\n function renderLevel(nodes: LayerTreeNode[], parentId: string | null, path: string): ReactNode {\n const reorderable = nodes.filter((l) => !l.alwaysOn);\n const pinned = nodes.filter((l) => l.alwaysOn);\n return (\n <>\n {reorderable.map((layer, i) => renderRow(layer, parentId, i, `${path}-${i}`, false))}\n {pinned.map((layer, i) => renderRow(layer, parentId, i, `${path}-p${i}`, true))}\n </>\n );\n }\n\n return (\n <div className={className ? `lk-layer-list ${className}` : 'lk-layer-list'}>\n {renderLevel(layers, null, '')}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/layers/LayerList.tsx"],"names":["n","Fragment","r"],"mappings":"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","file":"chunk-D35PFTS7.js","sourcesContent":["import { openPointerSession, type PointerSession } from '@weasel-js/core';\nimport { Disclosure } from '@weasel-js/ui';\nimport {\n Fragment,\n type ReactNode,\n type PointerEvent as ReactPointerEvent,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport type { LayerDescriptor } from '../instrument/types';\nimport { DragHandleGlyph } from '../passthrough/weasel-ui';\n\n/** A layer that may itself contain layers. A plain `LayerDescriptor` is one\n * of these with no children, so a flat list needs no change. */\nexport interface LayerTreeNode extends LayerDescriptor {\n children?: LayerTreeNode[];\n /** Render this node's children hidden on first paint. Ignored once\n * `collapsedIds` is supplied. */\n defaultCollapsed?: boolean;\n}\n\n/** Props for `<LayerList>`. */\nexport interface LayerListProps {\n layers: LayerTreeNode[];\n visibility: Record<string, boolean>;\n /** The whole tree, with the dragged node moved. Reordering is scoped to a\n * node's siblings: a drag never changes which parent a layer sits under. */\n onReorder: (newOrder: LayerTreeNode[]) => void;\n onToggle: (id: string, visible: boolean) => void;\n /** Ids whose children are hidden. Supplying it makes collapse controlled;\n * without it the list keeps its own, seeded from `defaultCollapsed`. */\n collapsedIds?: readonly string[];\n onCollapsedChange?: (ids: string[]) => void;\n className?: string;\n}\n\ninterface DragState {\n /** Id of the dragged row's parent, or null at the top level. */\n parentId: string | null;\n fromIndex: number;\n toIndex: number;\n startY: number;\n /** Row height plus row gap, measured when the drag starts. */\n pitch: number;\n}\n\n/** Which row the drag currently marks. */\ninterface DragMark {\n parentId: string | null;\n index: number;\n}\n\nfunction findNode(nodes: LayerTreeNode[], id: string): LayerTreeNode | null {\n for (const node of nodes) {\n if (node.id === id) return node;\n const hit = node.children ? findNode(node.children, id) : null;\n if (hit) return hit;\n }\n return null;\n}\n\nfunction siblingsOf(layers: LayerTreeNode[], parentId: string | null): LayerTreeNode[] {\n if (parentId === null) return layers;\n return findNode(layers, parentId)?.children ?? [];\n}\n\nfunction withChildren(\n nodes: LayerTreeNode[],\n parentId: string | null,\n next: LayerTreeNode[],\n): LayerTreeNode[] {\n if (parentId === null) return next;\n return nodes.map((node) => {\n if (node.id === parentId) return { ...node, children: next };\n if (node.children) return { ...node, children: withChildren(node.children, parentId, next) };\n return node;\n });\n}\n\nfunction collectCollapsed(nodes: LayerTreeNode[], into: Set<string>): Set<string> {\n for (const node of nodes) {\n if (node.defaultCollapsed) into.add(node.id);\n if (node.children) collectCollapsed(node.children, into);\n }\n return into;\n}\n\nfunction anyNested(nodes: LayerTreeNode[]): boolean {\n return nodes.some((n) => (n.children?.length ?? 0) > 0);\n}\n\n/** A reorderable list of layers with per-layer visibility toggles. Layers\n * marked `alwaysOn` are pinned and cannot be reordered or hidden. Layers with\n * `children` render as an expandable subtree. */\nexport function LayerList({\n layers,\n visibility,\n onReorder,\n onToggle,\n collapsedIds,\n onCollapsedChange,\n className,\n}: LayerListProps) {\n const [dragMark, setDragMark] = useState<DragMark | null>(null);\n const [ownCollapsed, setOwnCollapsed] = useState<Set<string>>(() =>\n collectCollapsed(layers, new Set()),\n );\n const dragRef = useRef<DragState | null>(null);\n const sessionRef = useRef<PointerSession | null>(null);\n const uid = useId();\n // The session's callbacks outlive the render that opened them, so the commit\n // reads its inputs here rather than from that render's closure.\n const commitRef = useRef({ layers, onReorder });\n commitRef.current = { layers, onReorder };\n\n useEffect(() => () => sessionRef.current?.cancel(), []);\n\n const collapsed = collapsedIds ? new Set(collapsedIds) : ownCollapsed;\n\n const toggleCollapsed = (id: string) => {\n const next = new Set(collapsed);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n if (!collapsedIds) setOwnCollapsed(next);\n onCollapsedChange?.([...next]);\n };\n\n if (layers.length === 0) {\n return (\n <div className={className ? `lk-layer-list ${className}` : 'lk-layer-list'}>\n <div className=\"lk-layer-list__empty\">No layers</div>\n </div>\n );\n }\n\n const clearDrag = () => {\n dragRef.current = null;\n sessionRef.current = null;\n setDragMark(null);\n };\n\n const startDrag = (e: ReactPointerEvent<HTMLElement>, parentId: string | null, index: number) => {\n // Measured at grab time rather than hardcoded: a restyle that changes row\n // height or gap would otherwise silently skew every drag distance.\n const row = e.currentTarget.closest('.lk-layer-list__row');\n const list = row?.parentElement;\n const gap = list ? Number.parseFloat(getComputedStyle(list).rowGap) || 0 : 0;\n const pitch = row ? row.getBoundingClientRect().height + gap : 0;\n const drag: DragState = {\n parentId,\n fromIndex: index,\n toIndex: index,\n startY: e.clientY,\n pitch: pitch > 0 ? pitch : 1,\n };\n dragRef.current = drag;\n setDragMark({ parentId, index });\n sessionRef.current = openPointerSession(e.currentTarget, e, {\n onMove: (ev) => {\n const delta = Math.round((ev.clientY - drag.startY) / drag.pitch);\n const siblings = siblingsOf(commitRef.current.layers, parentId);\n const last = siblings.filter((l) => !l.alwaysOn).length - 1;\n drag.toIndex = Math.min(last, Math.max(0, drag.fromIndex + delta));\n setDragMark({ parentId, index: drag.toIndex });\n },\n onEnd: () => {\n const { layers: tree, onReorder: commit } = commitRef.current;\n const { fromIndex, toIndex } = drag;\n clearDrag();\n if (toIndex === fromIndex) return;\n const siblings = siblingsOf(tree, parentId);\n const rows = siblings.filter((l) => !l.alwaysOn);\n const locked = siblings.filter((l) => l.alwaysOn);\n const next = [...rows];\n const [moved] = next.splice(fromIndex, 1);\n if (moved) next.splice(toIndex, 0, moved);\n commit(withChildren(tree, parentId, [...next, ...locked]));\n },\n // An interrupted drag never named a destination, so it reorders nothing.\n onCancel: clearDrag,\n });\n };\n\n // A twisty column on every row keeps labels aligned across depths, but a\n // flat list would only be paying 20px for it.\n const nested = anyNested(layers);\n\n function renderRow(\n layer: LayerTreeNode,\n parentId: string | null,\n index: number,\n path: string,\n pinned: boolean,\n ): ReactNode {\n const kids = layer.children ?? [];\n const open = kids.length > 0 && !collapsed.has(layer.id);\n const bodyId = `${uid}${path}`;\n const dragging = !pinned && dragMark?.parentId === parentId && dragMark.index === index;\n const cls = ['lk-layer-list__row'];\n if (dragging) cls.push('lk-layer-list__row--dragging');\n if (pinned) cls.push('lk-layer-list__row--pinned');\n return (\n <Fragment key={layer.id}>\n <div className={cls.join(' ')}>\n {nested &&\n (kids.length > 0 ? (\n <Disclosure\n open={open}\n onToggle={() => toggleCollapsed(layer.id)}\n label={`${layer.label} sublayers`}\n controls={bodyId}\n />\n ) : (\n <span className=\"lk-layer-list__twisty-gap\" />\n ))}\n {pinned ? (\n <span className=\"lk-layer-list__lock\" role=\"img\" aria-label=\"Always on\">\n 🔒\n </span>\n ) : (\n <>\n <button\n type=\"button\"\n className=\"lk-layer-list__handle\"\n aria-label={`Reorder ${layer.label}`}\n onPointerDown={(e) => startDrag(e, parentId, index)}\n >\n <DragHandleGlyph size={13} />\n </button>\n <input\n className=\"lk-layer-list__check\"\n type=\"checkbox\"\n checked={visibility[layer.id] !== false}\n onChange={(e) => onToggle(layer.id, e.target.checked)}\n aria-label={`Toggle ${layer.label}`}\n />\n </>\n )}\n <span className=\"lk-layer-list__label\">{layer.label}</span>\n </div>\n {open && (\n <div id={bodyId} className=\"lk-layer-list__children\">\n {renderLevel(kids, layer.id, path)}\n </div>\n )}\n </Fragment>\n );\n }\n\n function renderLevel(nodes: LayerTreeNode[], parentId: string | null, path: string): ReactNode {\n const reorderable = nodes.filter((l) => !l.alwaysOn);\n const pinned = nodes.filter((l) => l.alwaysOn);\n return (\n <>\n {reorderable.map((layer, i) => renderRow(layer, parentId, i, `${path}-${i}`, false))}\n {pinned.map((layer, i) => renderRow(layer, parentId, i, `${path}-p${i}`, true))}\n </>\n );\n }\n\n return (\n <div className={className ? `lk-layer-list ${className}` : 'lk-layer-list'}>\n {renderLevel(layers, null, '')}\n </div>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { schemaNodeAtPath } from './chunk-E44SU6XS.js';
1
+ import { schemaNodeAtPath } from './chunk-REOBGYMC.js';
2
2
 
3
3
  // src/config/fromConfigField.ts
4
4
  function toLeaf(field) {
@@ -68,5 +68,5 @@ function isLeafVisible(resolved, path, config, showHidden = false) {
68
68
  }
69
69
 
70
70
  export { fromConfigFields, isLeafVisible };
71
- //# sourceMappingURL=chunk-UU3NJO6N.js.map
72
- //# sourceMappingURL=chunk-UU3NJO6N.js.map
71
+ //# sourceMappingURL=chunk-EMXAIRUJ.js.map
72
+ //# sourceMappingURL=chunk-EMXAIRUJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config/fromConfigField.ts","../src/config/visible.ts"],"names":[],"mappings":";;;AAOA,SAAS,OAAO,KAAA,EAA+B;AAC7C,EAAA,MAAM,OAAO,EAAE,IAAA,EAAM,KAAA,CAAM,KAAA,EAAO,aAAa,EAAA,EAAG;AAClD,EAAA,QAAQ,MAAM,IAAA;AAAM,IAClB,KAAK,QAAA;AACH,MAAA,OAAO;AAAA,QACL,GAAG,IAAA;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,QAAA;AAAA,QACT,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,MAAM,KAAA,CAAM;AAAA,OACd;AAAA,IACF,KAAK,QAAA;AACH,MAAA,OAAO;AAAA,QACL,GAAG,IAAA;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,OAAA;AAAA,QACT,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,MAAM,KAAA,CAAM;AAAA,OACd;AAAA,IACF,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,SAAS,UAAA,EAAW;AAAA,IACzD,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,MAAM,MAAA,EAAQ,OAAA,EAAS,MAAM,OAAA,EAAQ;AAAA,IACzD,KAAK,MAAA;AACH,MAAA,OAAO;AAAA,QACL,GAAG,IAAA;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,YAAY,KAAA,CAAM;AAAA,OACpB;AAAA,IACF,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,IAAA,EAAM,OAAA,EAAQ;AAAA,IAClC;AAGE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,IAAA,EAAO,MAAsB,IAAA,EAAK;AAAA;AAE1D;AASO,SAAS,iBAAiB,MAAA,EAAgD;AAC/E,EAAA,MAAM,WAAqC,EAAC;AAC5C,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA;AAC1B,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AACpC,MAAA,IAAK,KAAA,CAAkC,GAAG,CAAA,KAAM,MAAA,EAAW;AACzD,QAAA,OAAQ,MAAkC,GAAG,CAAA;AAAA,MAC/C;AAAA,IACF;AACA,IAAA,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,GAAI,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,MAAM,OAAA,EAAQ;AAAA,EAC3D;AACA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,EAAE,IAAA,EAAM,EAAA,EAAI,QAAA,EAAS;AAAA,IAC5B,UAAU,EAAC;AAAA,IACX,MAAA,sBAAY,GAAA,EAAI;AAAA,IAChB,WAAW;AAAC,GACd;AACF;;;AC9DO,SAAS,aAAA,CACd,QAAA,EACA,IAAA,EACA,MAAA,EACA,aAAa,KAAA,EACJ;AACT,EAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,QAAA,CAAS,KAAA,EAAO,IAAI,CAAA;AAClD,EAAA,IAAI,IAAA,IAAQ,YAAY,IAAA,IAAQ,IAAA,CAAK,WAAW,IAAA,IAAQ,CAAC,YAAY,OAAO,KAAA;AAC5E,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA;AAC1C,EAAA,OAAO,SAAA,GAAY,SAAA,CAAU,MAAM,CAAA,GAAI,IAAA;AACzC","file":"chunk-UU3NJO6N.js","sourcesContent":["import type { PrefLeaf } from '@weasel-js/ui';\nimport type { ConfigField } from '../controls/types';\nimport type { LeafPatch, ResolvedConfig } from './types';\n\n/** One `ConfigField` as the `Pref*` vocabulary spells it. The two describe the\n * same thing; `ConfigField` just keys on the control where `PrefLeaf`\n * separates the value's kind from how it is presented. */\nfunction toLeaf(field: ConfigField): LeafPatch {\n const base = { name: field.label, description: '' };\n switch (field.type) {\n case 'slider':\n return {\n ...base,\n kind: 'number',\n control: 'slider',\n min: field.min,\n max: field.max,\n step: field.step,\n };\n case 'number':\n return {\n ...base,\n kind: 'number',\n control: 'input',\n min: field.min,\n max: field.max,\n step: field.step,\n };\n case 'checkbox':\n return { ...base, kind: 'boolean', control: 'checkbox' };\n case 'select':\n return { ...base, kind: 'enum', options: field.options };\n case 'text':\n return {\n ...base,\n kind: 'string',\n placeholder: field.placeholder,\n maxLength: field.maxLength,\n debounceMs: field.debounceMs,\n };\n case 'color':\n return { ...base, kind: 'color' };\n default:\n // A schema can arrive from outside TypeScript. Carry the kind through\n // so a lab-supplied renderer can still claim it.\n return { ...base, kind: (field as ConfigField).type };\n }\n}\n\n/**\n * Adapt a legacy `configSchema(): ConfigField[]` into the resolved shape, so\n * both instrument paths reach one renderer.\n *\n * Rules do not run here: a hand-written `ConfigField` already states its label\n * and control, which is everything the rule chain would have inferred.\n */\nexport function fromConfigFields(fields: readonly ConfigField[]): ResolvedConfig {\n const children: Record<string, PrefLeaf> = {};\n for (const field of fields) {\n const patch = toLeaf(field);\n for (const key of Object.keys(patch)) {\n if ((patch as Record<string, unknown>)[key] === undefined) {\n delete (patch as Record<string, unknown>)[key];\n }\n }\n children[field.key] = { ...patch, default: field.default } as PrefLeaf;\n }\n return {\n group: { name: '', children },\n sections: [],\n showIf: new Map(),\n renderers: {},\n };\n}\n","import { schemaNodeAtPath } from './path';\nimport type { ResolvedConfig } from './types';\n\n/**\n * Whether the row at a dotted path should be drawn right now. A group answers\n * for its whole subtree — hiding one hides everything under it.\n *\n * `hidden` is the node's own static flag; `showIf` is the schema's predicate\n * over the live config. Both are presentational — a hidden leaf keeps its\n * value and the instrument still reads it.\n */\nexport function isLeafVisible(\n resolved: ResolvedConfig,\n path: string,\n config: Record<string, unknown>,\n showHidden = false,\n): boolean {\n const node = schemaNodeAtPath(resolved.group, path);\n if (node && 'hidden' in node && node.hidden === true && !showHidden) return false;\n const predicate = resolved.showIf.get(path);\n return predicate ? predicate(config) : true;\n}\n"]}
1
+ {"version":3,"sources":["../src/config/fromConfigField.ts","../src/config/visible.ts"],"names":[],"mappings":";;;AAOA,SAAS,OAAO,KAAA,EAA+B;AAC7C,EAAA,MAAM,OAAO,EAAE,IAAA,EAAM,KAAA,CAAM,KAAA,EAAO,aAAa,EAAA,EAAG;AAClD,EAAA,QAAQ,MAAM,IAAA;AAAM,IAClB,KAAK,QAAA;AACH,MAAA,OAAO;AAAA,QACL,GAAG,IAAA;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,QAAA;AAAA,QACT,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,MAAM,KAAA,CAAM;AAAA,OACd;AAAA,IACF,KAAK,QAAA;AACH,MAAA,OAAO;AAAA,QACL,GAAG,IAAA;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,OAAA;AAAA,QACT,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,MAAM,KAAA,CAAM;AAAA,OACd;AAAA,IACF,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,SAAS,UAAA,EAAW;AAAA,IACzD,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,MAAM,MAAA,EAAQ,OAAA,EAAS,MAAM,OAAA,EAAQ;AAAA,IACzD,KAAK,MAAA;AACH,MAAA,OAAO;AAAA,QACL,GAAG,IAAA;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,YAAY,KAAA,CAAM;AAAA,OACpB;AAAA,IACF,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,IAAA,EAAM,OAAA,EAAQ;AAAA,IAClC;AAGE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,IAAA,EAAO,MAAsB,IAAA,EAAK;AAAA;AAE1D;AASO,SAAS,iBAAiB,MAAA,EAAgD;AAC/E,EAAA,MAAM,WAAqC,EAAC;AAC5C,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA;AAC1B,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AACpC,MAAA,IAAK,KAAA,CAAkC,GAAG,CAAA,KAAM,MAAA,EAAW;AACzD,QAAA,OAAQ,MAAkC,GAAG,CAAA;AAAA,MAC/C;AAAA,IACF;AACA,IAAA,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,GAAI,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,MAAM,OAAA,EAAQ;AAAA,EAC3D;AACA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,EAAE,IAAA,EAAM,EAAA,EAAI,QAAA,EAAS;AAAA,IAC5B,UAAU,EAAC;AAAA,IACX,MAAA,sBAAY,GAAA,EAAI;AAAA,IAChB,WAAW;AAAC,GACd;AACF;;;AC9DO,SAAS,aAAA,CACd,QAAA,EACA,IAAA,EACA,MAAA,EACA,aAAa,KAAA,EACJ;AACT,EAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,QAAA,CAAS,KAAA,EAAO,IAAI,CAAA;AAClD,EAAA,IAAI,IAAA,IAAQ,YAAY,IAAA,IAAQ,IAAA,CAAK,WAAW,IAAA,IAAQ,CAAC,YAAY,OAAO,KAAA;AAC5E,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA;AAC1C,EAAA,OAAO,SAAA,GAAY,SAAA,CAAU,MAAM,CAAA,GAAI,IAAA;AACzC","file":"chunk-EMXAIRUJ.js","sourcesContent":["import type { PrefLeaf } from '@weasel-js/ui';\nimport type { ConfigField } from '../controls/types';\nimport type { LeafPatch, ResolvedConfig } from './types';\n\n/** One `ConfigField` as the `Pref*` vocabulary spells it. The two describe the\n * same thing; `ConfigField` just keys on the control where `PrefLeaf`\n * separates the value's kind from how it is presented. */\nfunction toLeaf(field: ConfigField): LeafPatch {\n const base = { name: field.label, description: '' };\n switch (field.type) {\n case 'slider':\n return {\n ...base,\n kind: 'number',\n control: 'slider',\n min: field.min,\n max: field.max,\n step: field.step,\n };\n case 'number':\n return {\n ...base,\n kind: 'number',\n control: 'input',\n min: field.min,\n max: field.max,\n step: field.step,\n };\n case 'checkbox':\n return { ...base, kind: 'boolean', control: 'checkbox' };\n case 'select':\n return { ...base, kind: 'enum', options: field.options };\n case 'text':\n return {\n ...base,\n kind: 'string',\n placeholder: field.placeholder,\n maxLength: field.maxLength,\n debounceMs: field.debounceMs,\n };\n case 'color':\n return { ...base, kind: 'color' };\n default:\n // A schema can arrive from outside TypeScript. Carry the kind through\n // so a lab-supplied renderer can still claim it.\n return { ...base, kind: (field as ConfigField).type };\n }\n}\n\n/**\n * Adapt a legacy `configSchema(): ConfigField[]` into the resolved shape, so\n * both instrument paths reach one renderer.\n *\n * Rules do not run here: a hand-written `ConfigField` already states its label\n * and control, which is everything the rule chain would have inferred.\n */\nexport function fromConfigFields(fields: readonly ConfigField[]): ResolvedConfig {\n const children: Record<string, PrefLeaf> = {};\n for (const field of fields) {\n const patch = toLeaf(field);\n for (const key of Object.keys(patch)) {\n if ((patch as Record<string, unknown>)[key] === undefined) {\n delete (patch as Record<string, unknown>)[key];\n }\n }\n children[field.key] = { ...patch, default: field.default } as PrefLeaf;\n }\n return {\n group: { name: '', children },\n sections: [],\n showIf: new Map(),\n renderers: {},\n };\n}\n","import { schemaNodeAtPath } from './path';\nimport type { ResolvedConfig } from './types';\n\n/**\n * Whether the row at a dotted path should be drawn right now. A group answers\n * for its whole subtree — hiding one hides everything under it.\n *\n * `hidden` is the node's own static flag; `showIf` is the schema's predicate\n * over the live config. Both are presentational — a hidden leaf keeps its\n * value and the instrument still reads it.\n */\nexport function isLeafVisible(\n resolved: ResolvedConfig,\n path: string,\n config: Record<string, unknown>,\n showHidden = false,\n): boolean {\n const node = schemaNodeAtPath(resolved.group, path);\n if (node && 'hidden' in node && node.hidden === true && !showHidden) return false;\n const predicate = resolved.showIf.get(path);\n return predicate ? predicate(config) : true;\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  import { centerOn, zoomAt } from './chunk-H6ZAOWNE.js';
2
2
  import { resolveFrame, screenToWorld, DEFAULT_FRAME } from './chunk-2AYGEN57.js';
3
3
  import { CanvasStackContext } from './chunk-CQLQPQ4P.js';
4
- import { useVisibleRaf, normalizeZoom } from '@weasel-js/core';
4
+ import { useVisibleRaf, useActionsRegistry, WeaselProvider, useGestureDispatcher, normalizeZoom } from '@weasel-js/core';
5
5
  import { useRef, useEffect, useReducer, useCallback, useContext, useMemo, useState } from 'react';
6
- import { jsx } from 'react/jsx-runtime';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
 
8
8
  // src/loupe/canvasLens.ts
9
9
  function lensCamera(aim, outer, outerFrame, factor, diameter, worldSpec) {
@@ -157,6 +157,95 @@ function LoupeBubble({ aim, diameter, hostRef, children }) {
157
157
  };
158
158
  return /* @__PURE__ */ jsx("div", { ref: hostRef, className: "lk-loupe", style, "aria-hidden": "true", children });
159
159
  }
160
+
161
+ // src/loupe/loupeActions.ts
162
+ var LOUPE_PEEK_ID = "loupe.peek";
163
+ var LOUPE_MAGNIFY_ID = "loupe.magnify";
164
+ var WHEEL_RATE = 2e-3;
165
+ function createLoupeActions(input, peekKey) {
166
+ const magnify = {
167
+ id: LOUPE_MAGNIFY_ID,
168
+ label: "Magnify (loupe)",
169
+ group: "loupe",
170
+ // Every modifier optional: the lens claims the wheel whenever it is up,
171
+ // which is what the hand-rolled capture-phase listener did. A bare spec
172
+ // would forbid modifiers and hand Cmd+wheel back to the lab mid-peek.
173
+ defaultBinding: [
174
+ {
175
+ spec: {
176
+ kind: "wheel",
177
+ mods: { alt: "optional", ctrl: "optional", meta: "optional", shift: "optional" }
178
+ },
179
+ opts: {}
180
+ }
181
+ ],
182
+ enabled: () => input.shown() ? true : "not-applicable",
183
+ invoker: {
184
+ timing: "immediate",
185
+ run(_deps, params) {
186
+ input.magnifyBy(params?.deltaY ?? 0);
187
+ }
188
+ }
189
+ };
190
+ if (peekKey === null) return [magnify];
191
+ const peek = {
192
+ id: LOUPE_PEEK_ID,
193
+ label: "Peek (loupe)",
194
+ group: "loupe",
195
+ // Hotkey scope: peeking must beat whatever the lab's active tool binds to
196
+ // the same key, the way every other held-key trigger does.
197
+ scope: "hotkey",
198
+ // Every modifier optional because the peek key may BE one: the keydown
199
+ // that carries `Alt` — the default — also reports `altKey: true`, and the
200
+ // matcher forbids any modifier a spec does not name.
201
+ defaultBinding: [
202
+ {
203
+ spec: {
204
+ kind: "key-held",
205
+ key: peekKey,
206
+ mods: { alt: "optional", ctrl: "optional", meta: "optional", shift: "optional" }
207
+ },
208
+ opts: {}
209
+ }
210
+ ],
211
+ invoker: {
212
+ timing: "ongoing",
213
+ start() {
214
+ input.setPeeking(true);
215
+ return { onEnd: () => input.setPeeking(false) };
216
+ }
217
+ }
218
+ };
219
+ return [peek, magnify];
220
+ }
221
+ var NO_TOOLS = /* @__PURE__ */ new Map();
222
+ var CHANNELS = { pointer: false, contextMenu: false, ingest: false };
223
+ function LoupeDispatch({
224
+ hostRef,
225
+ input,
226
+ peekKey,
227
+ registry
228
+ }) {
229
+ const actions = useMemo(() => createLoupeActions(input, peekKey), [input, peekKey]);
230
+ useEffect(() => {
231
+ const offs = actions.map((a) => registry.register(a));
232
+ return () => {
233
+ for (const off of offs) off();
234
+ };
235
+ }, [registry, actions]);
236
+ useGestureDispatcher({
237
+ canvasRef: hostRef,
238
+ actions: registry,
239
+ toolsById: NO_TOOLS,
240
+ channels: CHANNELS
241
+ });
242
+ return null;
243
+ }
244
+ function LoupeGestures(props) {
245
+ const registry = useActionsRegistry();
246
+ if (!registry) return null;
247
+ return /* @__PURE__ */ jsx(LoupeDispatch, { ...props, registry });
248
+ }
160
249
  var ZERO = { width: 0, height: 0 };
161
250
  function useHostSize(ref) {
162
251
  const [size, setSize] = useState(ZERO);
@@ -264,7 +353,6 @@ function createLoupeModel(opts) {
264
353
  dispose: teardown
265
354
  };
266
355
  }
267
- var WHEEL_RATE = 2e-3;
268
356
  function useLoupe({ capability, hostRef, enabled, sample }) {
269
357
  const [, bump] = useReducer((n) => n + 1, 0);
270
358
  const overRef = useRef(false);
@@ -330,45 +418,28 @@ function useLoupe({ capability, hostRef, enabled, sample }) {
330
418
  overRef.current = false;
331
419
  bump();
332
420
  };
333
- const onWheel = (e) => {
334
- if (!shown()) return;
335
- e.preventDefault();
336
- e.stopPropagation();
337
- model.setFactor(model.factor * Math.exp(-e.deltaY * WHEEL_RATE));
338
- };
339
421
  host.addEventListener("pointermove", onPointerMove);
340
422
  host.addEventListener("pointerleave", onPointerLeave);
341
- host.addEventListener("wheel", onWheel, { capture: true, passive: false });
342
423
  return () => {
343
424
  host.removeEventListener("pointermove", onPointerMove);
344
425
  host.removeEventListener("pointerleave", onPointerLeave);
345
- host.removeEventListener("wheel", onWheel, { capture: true });
346
426
  };
347
427
  }, [hostRef, model, shown]);
348
- const peekKey = capability.peekKey;
349
- useEffect(() => {
350
- if (peekKey == null) return;
351
- const setPeeking = (next) => {
352
- if (peekingRef.current === next) return;
353
- peekingRef.current = next;
354
- bump();
355
- };
356
- const onKeyDown = (e) => {
357
- if (e.key === peekKey) setPeeking(true);
358
- };
359
- const onKeyUp = (e) => {
360
- if (e.key === peekKey) setPeeking(false);
361
- };
362
- const onBlur = () => setPeeking(false);
363
- window.addEventListener("keydown", onKeyDown);
364
- window.addEventListener("keyup", onKeyUp);
365
- window.addEventListener("blur", onBlur);
366
- return () => {
367
- window.removeEventListener("keydown", onKeyDown);
368
- window.removeEventListener("keyup", onKeyUp);
369
- window.removeEventListener("blur", onBlur);
428
+ const inputRef = useRef(null);
429
+ if (inputRef.current === null) {
430
+ inputRef.current = {
431
+ shown,
432
+ setPeeking: (on) => {
433
+ if (peekingRef.current === on) return;
434
+ peekingRef.current = on;
435
+ bump();
436
+ },
437
+ magnifyBy: (deltaY) => {
438
+ const m = modelRef.current;
439
+ if (m) m.setFactor(m.factor * Math.exp(-deltaY * WHEEL_RATE));
440
+ }
370
441
  };
371
- }, [peekKey]);
442
+ }
372
443
  return {
373
444
  visible: shown(),
374
445
  aim: model.aim,
@@ -377,7 +448,8 @@ function useLoupe({ capability, hostRef, enabled, sample }) {
377
448
  color: model.color,
378
449
  setMode: model.setMode,
379
450
  setFactor: model.setFactor,
380
- pick: model.pick
451
+ pick: model.pick,
452
+ input: inputRef.current
381
453
  };
382
454
  }
383
455
  var NO_HOST = { current: null };
@@ -403,34 +475,38 @@ function TrialLoupe({
403
475
  const loupe = useLoupe({ capability, hostRef: host, enabled, sample });
404
476
  const measured = useHostSize(host);
405
477
  const size = surface?.size ?? measured;
406
- if (!loupe.visible) return null;
407
- return /* @__PURE__ */ jsx(LoupeBubble, { aim: loupe.aim, diameter: capability.diameter, children: capability.render ? /* @__PURE__ */ jsx(
408
- DomLoupe,
409
- {
410
- aim: loupe.aim,
411
- factor: loupe.factor,
412
- mode: loupe.mode,
413
- diameter: capability.diameter,
414
- size,
415
- view,
416
- frame: stack?.frame,
417
- state,
418
- config,
419
- render: capability.render
420
- }
421
- ) : surface && stack ? /* @__PURE__ */ jsx(
422
- CanvasLoupe,
423
- {
424
- aim: loupe.aim,
425
- factor: loupe.factor,
426
- mode: loupe.mode,
427
- diameter: capability.diameter,
428
- surface,
429
- view: stack.view,
430
- frame: stack.frame,
431
- worldSpec
432
- }
433
- ) : null });
478
+ const gestures = /* @__PURE__ */ jsx(WeaselProvider, { isolate: true, children: /* @__PURE__ */ jsx(LoupeGestures, { hostRef: host, input: loupe.input, peekKey: capability.peekKey ?? null }) });
479
+ if (!loupe.visible) return gestures;
480
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
481
+ gestures,
482
+ /* @__PURE__ */ jsx(LoupeBubble, { aim: loupe.aim, diameter: capability.diameter, children: capability.render ? /* @__PURE__ */ jsx(
483
+ DomLoupe,
484
+ {
485
+ aim: loupe.aim,
486
+ factor: loupe.factor,
487
+ mode: loupe.mode,
488
+ diameter: capability.diameter,
489
+ size,
490
+ view,
491
+ frame: stack?.frame,
492
+ state,
493
+ config,
494
+ render: capability.render
495
+ }
496
+ ) : surface && stack ? /* @__PURE__ */ jsx(
497
+ CanvasLoupe,
498
+ {
499
+ aim: loupe.aim,
500
+ factor: loupe.factor,
501
+ mode: loupe.mode,
502
+ diameter: capability.diameter,
503
+ surface,
504
+ view: stack.view,
505
+ frame: stack.frame,
506
+ worldSpec
507
+ }
508
+ ) : null })
509
+ ] });
434
510
  }
435
511
 
436
512
  // src/loupe/types.ts
@@ -459,6 +535,6 @@ function resolveLoupe(declared) {
459
535
  };
460
536
  }
461
537
 
462
- export { CanvasLoupe, DomLoupe, LOUPE_DEFAULTS, LoupeBubble, TrialLoupe, drawCanvasLens, lensCamera, lensSourceRect, resolveLoupe, sampleStack, useLoupe };
463
- //# sourceMappingURL=chunk-ZPH5WTWF.js.map
464
- //# sourceMappingURL=chunk-ZPH5WTWF.js.map
538
+ export { CanvasLoupe, DomLoupe, LOUPE_DEFAULTS, LOUPE_MAGNIFY_ID, LOUPE_PEEK_ID, LoupeBubble, LoupeGestures, TrialLoupe, createLoupeActions, drawCanvasLens, lensCamera, lensSourceRect, resolveLoupe, sampleStack, useLoupe };
539
+ //# sourceMappingURL=chunk-ERFMC6WU.js.map
540
+ //# sourceMappingURL=chunk-ERFMC6WU.js.map