@weasel-js/labkit 1.3.0 → 1.4.0-pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +226 -55
  2. package/dist/_dts/CanvasStackContext-LnCfqNBA.d.ts +42 -0
  3. package/dist/_dts/DrawCommand-B3bskUsC.d.ts +564 -0
  4. package/dist/_dts/{PrefsForm-BYa6cWnO.d.ts → PrefsForm-BkUJZx0A.d.ts} +4 -1
  5. package/dist/_dts/fitViewToBounds-dZ2UDB6e.d.ts +21 -0
  6. package/dist/_dts/frac-C-2c72Ij.d.ts +735 -0
  7. package/dist/_dts/index-BDVzvRzQ.d.ts +236 -0
  8. package/dist/_dts/shapeKinds-Cx_rxwsa.d.ts +87 -0
  9. package/dist/_dts/{DrawCommand-DBB45NfN.d.ts → types-C-gh9Ap-.d.ts} +1 -582
  10. package/dist/_dts/{types-DCGEcMO_.d.ts → types-D6s4b7if.d.ts} +1 -1
  11. package/dist/_dts/{types-1Sdxy_Pv.d.ts → types-DYMaEvM5.d.ts} +26 -1
  12. package/dist/_dts/{useTrialState-CsGMjhu9.d.ts → useTrialState-gmMvZqPc.d.ts} +7 -2
  13. package/dist/canvas/index.d.ts +110 -26
  14. package/dist/canvas/index.js +5 -4
  15. package/dist/chrome/index.d.ts +9 -6
  16. package/dist/chrome/index.js +6 -6
  17. package/dist/chunk-2AYGEN57.js +32 -0
  18. package/dist/chunk-2AYGEN57.js.map +1 -0
  19. package/dist/chunk-6OEYTYML.js +669 -0
  20. package/dist/chunk-6OEYTYML.js.map +1 -0
  21. package/dist/{chunk-BMW4TDP5.js → chunk-AE5CNVRU.js} +3 -3
  22. package/dist/{chunk-BMW4TDP5.js.map → chunk-AE5CNVRU.js.map} +1 -1
  23. package/dist/{chunk-CPUJ3QXL.js → chunk-CQLQPQ4P.js} +2 -2
  24. package/dist/chunk-CQLQPQ4P.js.map +1 -0
  25. package/dist/chunk-CTRKTLYZ.js +33 -0
  26. package/dist/chunk-CTRKTLYZ.js.map +1 -0
  27. package/dist/chunk-E2UQVZ44.js +458 -0
  28. package/dist/chunk-E2UQVZ44.js.map +1 -0
  29. package/dist/{chunk-LGKRIUSW.js → chunk-ESIQNQ6K.js} +32 -7
  30. package/dist/chunk-ESIQNQ6K.js.map +1 -0
  31. package/dist/{chunk-JDROYQM3.js → chunk-HHGVISVZ.js} +130 -131
  32. package/dist/chunk-HHGVISVZ.js.map +1 -0
  33. package/dist/{chunk-BDJXIBRZ.js → chunk-HMFODCOX.js} +126 -29
  34. package/dist/chunk-HMFODCOX.js.map +1 -0
  35. package/dist/{chunk-QCICIHEO.js → chunk-L5QJOOLV.js} +839 -320
  36. package/dist/chunk-L5QJOOLV.js.map +1 -0
  37. package/dist/{chunk-3XXPU73K.js → chunk-M75ZU6ZZ.js} +9 -7
  38. package/dist/chunk-M75ZU6ZZ.js.map +1 -0
  39. package/dist/{chunk-QRYPXSGP.js → chunk-QB5SM4BM.js} +16 -8
  40. package/dist/chunk-QB5SM4BM.js.map +1 -0
  41. package/dist/chunk-RBGKL7NF.js +7128 -0
  42. package/dist/chunk-RBGKL7NF.js.map +1 -0
  43. package/dist/{chunk-WTI26YTM.js → chunk-TO2FUOKF.js} +40 -13
  44. package/dist/chunk-TO2FUOKF.js.map +1 -0
  45. package/dist/{chunk-4TMMVIDM.js → chunk-XJ6N32QP.js} +50 -6
  46. package/dist/chunk-XJ6N32QP.js.map +1 -0
  47. package/dist/controls/index.d.ts +4 -28
  48. package/dist/controls/index.js +3 -3
  49. package/dist/dragdrop/index.d.ts +9 -5
  50. package/dist/dragdrop/index.js +3 -3
  51. package/dist/index.d.ts +517 -234
  52. package/dist/index.js +1769 -143
  53. package/dist/index.js.map +1 -1
  54. package/dist/layers/index.d.ts +6 -5
  55. package/dist/layers/index.js +3 -3
  56. package/dist/loupe/index.d.ts +187 -0
  57. package/dist/loupe/index.js +7 -0
  58. package/dist/loupe/index.js.map +1 -0
  59. package/dist/passthrough/weasel-canvas.d.ts +3 -1
  60. package/dist/passthrough/weasel-canvas.js +1 -1
  61. package/dist/passthrough/weasel-ui.d.ts +138 -91
  62. package/dist/passthrough/weasel-ui.js +2 -2
  63. package/dist/primitives/index.d.ts +3 -1
  64. package/dist/primitives/index.js +5 -5
  65. package/dist/state/index.d.ts +3 -3
  66. package/dist/state/index.js +2 -2
  67. package/dist/styles.css +229 -1
  68. package/dist/surface/index.d.ts +18 -2
  69. package/dist/surface/index.js +2 -2
  70. package/dist/ui/layers/index.js +2 -2
  71. package/dist/undo/index.d.ts +5 -4
  72. package/package.json +14 -7
  73. package/src/annotations/AnnotationOverlay.tsx +205 -0
  74. package/src/annotations/AnnotationTargets.tsx +37 -0
  75. package/src/annotations/Annotations.less +129 -0
  76. package/src/annotations/Annotations.meaning.test.tsx +111 -0
  77. package/src/annotations/Annotations.overlay.test.tsx +142 -0
  78. package/src/annotations/AnnotationsContext.ts +49 -0
  79. package/src/annotations/ExportMenu.test.tsx +86 -0
  80. package/src/annotations/ExportMenu.tsx +182 -0
  81. package/src/annotations/MarkList.tsx +75 -0
  82. package/src/annotations/capture.test.ts +140 -0
  83. package/src/annotations/capture.ts +237 -0
  84. package/src/annotations/drawOne.test.ts +56 -0
  85. package/src/annotations/drawOne.ts +47 -0
  86. package/src/annotations/frac.test.ts +59 -0
  87. package/src/annotations/frac.ts +66 -0
  88. package/src/annotations/history.test.ts +82 -0
  89. package/src/annotations/history.ts +118 -0
  90. package/src/annotations/index.ts +37 -0
  91. package/src/annotations/paint.test.ts +125 -0
  92. package/src/annotations/paint.ts +130 -0
  93. package/src/annotations/staleness.test.ts +56 -0
  94. package/src/annotations/staleness.ts +41 -0
  95. package/src/annotations/store.test.ts +247 -0
  96. package/src/annotations/store.ts +347 -0
  97. package/src/annotations/svgNodes.test.ts +77 -0
  98. package/src/annotations/svgNodes.ts +74 -0
  99. package/src/annotations/toolMap.test.ts +36 -0
  100. package/src/annotations/toolMap.ts +54 -0
  101. package/src/annotations/types.ts +229 -0
  102. package/src/annotations/view.test.ts +37 -0
  103. package/src/annotations/view.ts +40 -0
  104. package/src/canvas/AGENTS.md +55 -5
  105. package/src/canvas/CanvasStack.test.tsx +27 -1
  106. package/src/canvas/CanvasStack.tsx +29 -4
  107. package/src/canvas/CanvasStackContext.ts +23 -4
  108. package/src/canvas/camera.test.ts +78 -0
  109. package/src/canvas/camera.ts +62 -0
  110. package/src/canvas/canvasCoords.test.ts +26 -0
  111. package/src/canvas/canvasCoords.ts +20 -7
  112. package/src/canvas/index.ts +16 -1
  113. package/src/canvas/useLayerScheduler.ts +7 -3
  114. package/src/canvas/usePanZoom.test.ts +36 -5
  115. package/src/canvas/usePanZoom.ts +20 -15
  116. package/src/canvas/worldSpec.test.ts +63 -0
  117. package/src/canvas/worldSpec.ts +48 -0
  118. package/src/chrome/builtins.test.ts +31 -1
  119. package/src/chrome/builtins.tsx +63 -19
  120. package/src/chrome/regions/PaletteRegion.test.tsx +22 -1
  121. package/src/chrome/regions/PaletteRegion.tsx +4 -0
  122. package/src/chrome/regions/SidebarRegion.tsx +37 -13
  123. package/src/chrome/regions/ToolbarRegion.tsx +2 -1
  124. package/src/chrome/regions/ViewportRegion.tsx +9 -1
  125. package/src/chrome/regions/regions.test.tsx +6 -1
  126. package/src/chrome/types.ts +20 -0
  127. package/src/controls/ControlPanel.test.tsx +38 -0
  128. package/src/controls/ControlPanel.tsx +50 -3
  129. package/src/dragdrop/DragDropRuntime.tsx +8 -2
  130. package/src/dragdrop/dragDrop.test.tsx +29 -2
  131. package/src/index.test.ts +23 -0
  132. package/src/index.ts +93 -4
  133. package/src/instrument/SineWave.smoke.test.tsx +1 -0
  134. package/src/instrument/types.ts +24 -1
  135. package/src/lab/Lab.surface.test.tsx +162 -0
  136. package/src/lab/Lab.tsx +102 -17
  137. package/src/lab/Lab.undock.test.tsx +85 -0
  138. package/src/lab/LabFullChrome.stories.tsx +20 -0
  139. package/src/lab/LabShell.less +11 -0
  140. package/src/lab/Workspace.less +73 -0
  141. package/src/lab/Workspace.surface.test.tsx +2 -0
  142. package/src/lab/Workspace.tsx +97 -8
  143. package/src/lab/index.ts +1 -1
  144. package/src/lab/panelHost.ts +37 -0
  145. package/src/loupe/AGENTS.md +49 -0
  146. package/src/loupe/CanvasLoupe.tsx +83 -0
  147. package/src/loupe/DomLoupe.tsx +62 -0
  148. package/src/loupe/Loupe.less +38 -0
  149. package/src/loupe/LoupeBubble.tsx +32 -0
  150. package/src/loupe/TrialLoupe.tsx +93 -0
  151. package/src/loupe/canvasLens.test.ts +205 -0
  152. package/src/loupe/canvasLens.ts +141 -0
  153. package/src/loupe/index.ts +19 -0
  154. package/src/loupe/types.test.ts +29 -0
  155. package/src/loupe/types.ts +90 -0
  156. package/src/loupe/useHostSize.ts +30 -0
  157. package/src/loupe/useLoupe.test.tsx +197 -0
  158. package/src/loupe/useLoupe.ts +189 -0
  159. package/src/passthrough/weasel-ui.ts +3 -0
  160. package/src/primitives/FloatingPanel.test.tsx +76 -1
  161. package/src/primitives/FloatingPanel.tsx +19 -3
  162. package/src/primitives/ScaleIndicator.test.tsx +7 -2
  163. package/src/primitives/Sidebar.less +18 -0
  164. package/src/primitives/Toolbar.less +8 -0
  165. package/src/primitives/Toolbar.tsx +5 -0
  166. package/src/primitives/useRovingTabIndex.test.ts +21 -0
  167. package/src/primitives/useRovingTabIndex.ts +26 -17
  168. package/src/state/document.test.ts +23 -0
  169. package/src/state/document.ts +14 -2
  170. package/src/state/index.ts +2 -0
  171. package/src/state/store.test.ts +24 -0
  172. package/src/state/store.ts +35 -1
  173. package/src/state/types.ts +11 -0
  174. package/src/state/undock.test.ts +40 -0
  175. package/src/state/undock.ts +39 -0
  176. package/src/styles.less +2 -0
  177. package/src/surface/SurfaceContext.ts +4 -0
  178. package/src/surface/index.ts +8 -3
  179. package/src/surface/useSurfaceTile.test.tsx +2 -0
  180. package/src/surface/useSurfaceTile.ts +7 -1
  181. package/src/surface/useTiledSurface.test.tsx +58 -0
  182. package/src/surface/useTiledSurface.ts +38 -3
  183. package/src/trial/Trial.annotations.persist.test.tsx +166 -0
  184. package/src/trial/Trial.annotations.test.tsx +121 -0
  185. package/src/trial/Trial.canvas.test.tsx +76 -1
  186. package/src/trial/Trial.less +19 -0
  187. package/src/trial/Trial.loupe.test.tsx +128 -0
  188. package/src/trial/Trial.stories.tsx +1 -0
  189. package/src/trial/Trial.test.tsx +12 -0
  190. package/src/trial/Trial.trialId.test.tsx +36 -0
  191. package/src/trial/Trial.tsx +215 -40
  192. package/src/trial/TrialChrome.tsx +35 -0
  193. package/src/trial/UndockedSections.tsx +65 -0
  194. package/src/trial/trialOps.test.ts +21 -0
  195. package/src/trial/trialOps.ts +5 -3
  196. package/dist/_dts/types-BttTIent.d.ts +0 -314
  197. package/dist/chunk-3XXPU73K.js.map +0 -1
  198. package/dist/chunk-4TMMVIDM.js.map +0 -1
  199. package/dist/chunk-6X5RBC6G.js +0 -366
  200. package/dist/chunk-6X5RBC6G.js.map +0 -1
  201. package/dist/chunk-BDJXIBRZ.js.map +0 -1
  202. package/dist/chunk-CPUJ3QXL.js.map +0 -1
  203. package/dist/chunk-JDROYQM3.js.map +0 -1
  204. package/dist/chunk-LGKRIUSW.js.map +0 -1
  205. package/dist/chunk-QCICIHEO.js.map +0 -1
  206. package/dist/chunk-QRYPXSGP.js.map +0 -1
  207. package/dist/chunk-RGT4EJIB.js +0 -6961
  208. package/dist/chunk-RGT4EJIB.js.map +0 -1
  209. package/dist/chunk-T66HU3HX.js +0 -17
  210. package/dist/chunk-T66HU3HX.js.map +0 -1
  211. package/dist/chunk-WTI26YTM.js.map +0 -1
@@ -1,17 +0,0 @@
1
- // src/canvas/canvasCoords.ts
2
- function worldToScreen(world, view) {
3
- return {
4
- x: world.x * view.zoom + view.pan.x,
5
- y: world.y * view.zoom + view.pan.y
6
- };
7
- }
8
- function screenToWorld(screen, view) {
9
- return {
10
- x: (screen.x - view.pan.x) / view.zoom,
11
- y: (screen.y - view.pan.y) / view.zoom
12
- };
13
- }
14
-
15
- export { screenToWorld, worldToScreen };
16
- //# sourceMappingURL=chunk-T66HU3HX.js.map
17
- //# sourceMappingURL=chunk-T66HU3HX.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/canvas/canvasCoords.ts"],"names":[],"mappings":";AAGO,SAAS,aAAA,CAAc,OAAc,IAAA,EAA4B;AACtE,EAAA,OAAO;AAAA,IACL,GAAG,KAAA,CAAM,CAAA,GAAI,IAAA,CAAK,IAAA,GAAO,KAAK,GAAA,CAAI,CAAA;AAAA,IAClC,GAAG,KAAA,CAAM,CAAA,GAAI,IAAA,CAAK,IAAA,GAAO,KAAK,GAAA,CAAI;AAAA,GACpC;AACF;AAGO,SAAS,aAAA,CAAc,QAAe,IAAA,EAA4B;AACvE,EAAA,OAAO;AAAA,IACL,IAAI,MAAA,CAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,CAAK,IAAA;AAAA,IAClC,IAAI,MAAA,CAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,CAAK;AAAA,GACpC;AACF","file":"chunk-T66HU3HX.js","sourcesContent":["import type { Point, ViewTransform } from '../instrument/types';\n\n/** Project a world point into screen coordinates under a view. */\nexport function worldToScreen(world: Point, view: ViewTransform): Point {\n return {\n x: world.x * view.zoom + view.pan.x,\n y: world.y * view.zoom + view.pan.y,\n };\n}\n\n/** Unproject a screen point back to world coordinates under a view. */\nexport function screenToWorld(screen: Point, view: ViewTransform): Point {\n return {\n x: (screen.x - view.pan.x) / view.zoom,\n y: (screen.y - view.pan.y) / view.zoom,\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/fromConfigField.ts","../src/config/visible.ts","../src/controls/ControlPanel.tsx"],"names":["S","b","value"],"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;;;AChEO,SAAS,aAAA,CACd,QAAA,EACA,IAAA,EACA,MAAA,EACA,aAAa,KAAA,EACJ;AACT,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA;AACzC,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;ACsBO,SAAS,YAAA,CAAiD;AAAA,EAC/D,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA,GAAa,KAAA;AAAA,EACb;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,MAAM,MAAA,IAAU,gBAAA,CAAiB,MAAA,IAAU,EAAE,CAAA,EAAG,CAAC,MAAA,EAAQ,MAAM,CAAC,CAAA;AAEzF,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,MAAM,QAAQ,CAAA;AACjD,EAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,CAAC,CAAA;AACnE,EAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,CAAC,MAAM,CAAC,SAAA,CAAU,GAAA,CAAI,CAAC,CAAC,CAAA;AAEnD,EAAA,MAAM,GAAA,GAAM,CAAC,IAAA,qBACX,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MAEC,IAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA,KAAA;AAAA,IANK;AAAA,GAOP;AAGF,EAAA,4BACGA,EAAA,EAAA,EAAa,SAAA,EAAW,YAAY,CAAA,iBAAA,EAAoB,SAAS,KAAK,kBAAA,EACpE,QAAA,EAAA;AAAA,IAAA,KAAA,CAAM,IAAI,GAAG,CAAA;AAAA,IACb,SAAS,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,yBACrBC,EAAA,EAAA,EAAkC,KAAA,EAAO,OAAA,CAAQ,KAAA,EAC/C,kBAAQ,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,EAAA,EADJ,OAAA,CAAQ,KAE5B,CACD;AAAA,GAAA,EACH,CAAA;AAEJ;AAaA,SAAS,KAAA,CAAS,MAAgB,GAAA,EAA4B;AAC5D,EAAA,OAAQ,KAAkD,GAAG,CAAA;AAC/D;AAEA,SAAS,UAAA,CAA+C;AAAA,EACtD,IAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAwB;AACtB,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA;AACzC,EAAA,IAAI,CAAC,IAAA,IAAQ,EAAE,MAAA,IAAU,OAAO,OAAO,IAAA;AACvC,EAAA,IAAI,CAAC,aAAA,CAAc,QAAA,EAAU,MAAM,MAAA,EAAmC,UAAU,GAAG,OAAO,IAAA;AAE1F,EAAA,MAAM,KAAA,GAAQ,CAACC,MAAAA,KAAyB,SAAA,CAAU,MAAkBA,MAAK,CAAA;AACzE,EAAA,MAAM,QAAA,GAAW,KAAA,CAAe,IAAA,EAAM,SAAS,CAAA;AAC/C,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAI,CAAA,IAAK,QAAA;AAI9B,EAAA,MAAM,MAAA,GAAS,SAAA,GAAY,IAAI,CAAA,IAAK,QAAA,CAAS,UAAU,IAAI,CAAA,IAAK,SAAA,GAAY,IAAA,CAAK,IAAI,CAAA;AACrF,EAAA,IAAI,MAAA,EAAQ,OAAO,MAAA,CAAO,EAAE,IAAA,EAAM,MAAM,IAAA,EAAM,KAAA,EAAO,QAAA,EAAU,KAAA,EAAO,CAAA;AAEtE,EAAA,MAAM,QAAQ,IAAA,CAAK,IAAA;AACnB,EAAA,MAAM,cAAc,IAAA,CAAK,WAAA;AACzB,EAAA,MAAM,OAAO,MAAa,KAAA;AAE1B,EAAA,IAAI,CAAC,kBAAkB,IAAI,CAAA;AACzB,IAAA,2BAAQ,UAAA,EAAA,EAAW,KAAA,EAAc,IAAA,EAAM,IAAA,CAAK,MAAM,WAAA,EAA0B,CAAA;AAE9E,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,QAAA,EAAU;AACb,MAAA,MAAM,GAAA,GAAM,KAAA,CAAc,IAAA,EAAM,KAAK,CAAA;AACrC,MAAA,MAAM,GAAA,GAAM,KAAA,CAAc,IAAA,EAAM,KAAK,CAAA;AACrC,MAAA,MAAM,IAAA,GAAO,KAAA,CAAc,IAAA,EAAM,MAAM,CAAA;AACvC,MAAA,IAAI,KAAA,CAAc,MAAM,SAAS,CAAA,KAAM,YAAY,GAAA,KAAQ,MAAA,IAAa,QAAQ,MAAA,EAAW;AACzF,QAAA,uBACE,GAAA;AAAA,UAAC,CAAA;AAAA,UAAA;AAAA,YACC,KAAA;AAAA,YACA,OAAO,IAAA,EAAa;AAAA,YACpB,GAAA;AAAA,YACA,GAAA;AAAA,YACA,IAAA;AAAA,YACA,QAAA,EAAU,KAAA;AAAA,YACV;AAAA;AAAA,SACF;AAAA,MAEJ;AAIA,MAAA,MAAM,EAAA,GAAK,OAAO,MAAA,CAAO,iBAAA;AACzB,MAAA,MAAM,EAAA,GAAK,OAAO,MAAA,CAAO,iBAAA;AACzB,MAAA,uBACE,GAAA;AAAA,QAAC,CAAA;AAAA,QAAA;AAAA,UACC,KAAA;AAAA,UACA,OAAO,IAAA,EAAa;AAAA,UACpB,GAAA;AAAA,UACA,GAAA;AAAA,UACA,IAAA;AAAA,UACA,QAAA,EAAU,CAAC,CAAA,KAAM,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AAAA,UACpD;AAAA;AAAA,OACF;AAAA,IAEJ;AAAA,IACA,KAAK,SAAA;AACH,MAAA,uBACE,GAAA;AAAA,QAAC,CAAA;AAAA,QAAA;AAAA,UACC,KAAA;AAAA,UACA,OAAO,IAAA,EAAc;AAAA,UACrB,QAAA,EAAU,KAAA;AAAA,UACV;AAAA;AAAA,OACF;AAAA,IAEJ,KAAK,MAAA,EAAQ;AACX,MAAA,MAAM,OAAA,GAAU,KAAA,CAAmD,IAAA,EAAM,SAAS,KAAK,EAAC;AACxF,MAAA,MAAM,MAAM,KAAA,CAAc,IAAA,EAAM,SAAS,CAAA,KAAM,UAAU,CAAA,GAAY,CAAA;AACrE,MAAA,uBACE,GAAA;AAAA,QAAC,GAAA;AAAA,QAAA;AAAA,UACC,KAAA;AAAA,UACA,OAAO,IAAA,EAAa;AAAA,UACpB,OAAA;AAAA,UACA,QAAA,EAAU,KAAA;AAAA,UACV;AAAA;AAAA,OACF;AAAA,IAEJ;AAAA,IACA,KAAK,QAAA;AACH,MAAA,uBACE,GAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UACC,IAAA;AAAA,UACA,KAAA;AAAA,UACA,OAAO,IAAA,EAAa;AAAA,UACpB,KAAA;AAAA,UACA;AAAA;AAAA,OACF;AAAA,IAEJ,KAAK,OAAA;AACH,MAAA,uBACE,GAAA,CAAC,KAAS,KAAA,EAAc,KAAA,EAAO,MAAa,EAAG,QAAA,EAAU,OAAO,WAAA,EAA0B,CAAA;AAAA,IAE9F,KAAK,OAAA;AAAA,IACL,KAAK,QAAA;AAIH,MAAA,2BAAQ,UAAA,EAAA,EAAW,KAAA,EAAc,IAAA,EAAM,IAAA,CAAK,MAAM,WAAA,EAA0B,CAAA;AAAA,IAC9E,SAAS;AAGP,MAAA,MAAM,WAAA,GAAqB,IAAA;AAC3B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,iDAAA,EAAqD,YAAiC,IAAI,CAAA,CAAA;AAAA,OAC5F;AAAA,IACF;AAAA;AAEJ;AAIA,SAAS,UAAA,CAAW;AAAA,EAClB,KAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAA,EAIG;AACD,EAAA,2BACG,CAAA,EAAA,EAAY,KAAA,EAAc,aACzB,QAAA,kBAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,2BAAA,EAA4B,QAAA,EAAA;AAAA,IAAA,uBAAA;AAAA,IAAiB,IAAA;AAAA,IAAK;AAAA,GAAA,EAAC,CAAA,EACrE,CAAA;AAEJ;AAKA,SAAS,gBAAA,CAAiB;AAAA,EACxB,IAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAMG;AACD,EAAA,MAAM,UAAA,GAAa,KAAA,CAAc,IAAA,EAAM,YAAY,CAAA,IAAK,GAAA;AACxD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,KAAK,CAAA;AACxC,EAAA,MAAM,KAAA,GAAQ,OAA6C,IAAI,CAAA;AAC/D,EAAA,MAAM,YAAA,GAAe,OAAO,KAAK,CAAA;AAEjC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAA,KAAU,aAAa,OAAA,EAAS;AAClC,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AACvB,MAAA,QAAA,CAAS,KAAK,CAAA;AAAA,IAChB;AAAA,EACF,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,SAAA;AAAA,IACE,MAAM,MAAM;AACV,MAAA,IAAI,KAAA,CAAM,OAAA,EAAS,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA;AAAA,IAC/C,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,CAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAA,EAAO,KAAA;AAAA,MACP,WAAA,EAAa,KAAA,CAAc,IAAA,EAAM,aAAa,CAAA;AAAA,MAC9C,SAAA,EAAW,KAAA,CAAc,IAAA,EAAM,WAAW,CAAA;AAAA,MAC1C,QAAA,EAAU,CAAC,IAAA,KAAS;AAClB,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,IAAI,KAAA,CAAM,OAAA,EAAS,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA;AAC7C,QAAA,MAAM,SAAS,MAAM;AACnB,UAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,UAAA,KAAA,CAAM,IAAI,CAAA;AAAA,QACZ,CAAA;AACA,QAAA,IAAI,UAAA,KAAe,GAAG,MAAA,EAAO;AAAA,aACxB,KAAA,CAAM,OAAA,GAAU,UAAA,CAAW,MAAA,EAAQ,UAAU,CAAA;AAAA,MACpD;AAAA;AAAA,GACF;AAEJ","file":"chunk-WTI26YTM.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 type { ResolvedConfig } from './types';\n\n/**\n * Whether a leaf's row should be drawn right now.\n *\n * `hidden` is the leaf'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 leaf = resolved.group.children[path];\n if (leaf && 'hidden' in leaf && leaf.hidden === true && !showHidden) return false;\n const predicate = resolved.showIf.get(path);\n return predicate ? predicate(config) : true;\n}\n","import { isBuiltinToolPref } from '@weasel-js/core';\nimport {\n CheckboxRow,\n ColorRow,\n NumberRow,\n type PrefLeaf,\n PropertyGroup,\n PropertyList,\n PropertyRow,\n SelectRow,\n SliderRow,\n TextRow,\n ToggleRow,\n} from '@weasel-js/ui';\nimport { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';\nimport { fromConfigFields } from '../config/fromConfigField';\nimport type { ControlRenderer, ResolvedConfig } from '../config/types';\nimport { isLeafVisible } from '../config/visible';\nimport type { ConfigField } from './types';\n\nexport interface ControlPanelProps<TC extends Record<string, unknown>> {\n /** The instrument's resolved config schema. */\n schema?: ResolvedConfig;\n /** @deprecated Pass `schema`. A field list is adapted into one internally. */\n fields?: ConfigField[];\n config: TC;\n setConfig: (key: keyof TC, value: unknown) => void;\n /**\n * Control overrides and app-defined kinds, PrefsForm-style. Keys are config\n * paths (checked first) or leaf kinds. A renderer returning `null` collapses\n * the row; entries override the built-in rows on collision.\n */\n renderers?: Record<string, ControlRenderer>;\n /** Draw leaves marked `hidden`. */\n showHidden?: boolean;\n className?: string;\n}\n\n/** Render an instrument's config schema as a stack of controls, each writing\n * back through `setConfig`. Built on the property rows, so a lab's controls\n * are the same aligned, themed rows the rest of the kit uses. */\nexport function ControlPanel<TC extends Record<string, unknown>>({\n schema,\n fields,\n config,\n setConfig,\n renderers,\n showHidden = false,\n className,\n}: ControlPanelProps<TC>) {\n const resolved = useMemo(() => schema ?? fromConfigFields(fields ?? []), [schema, fields]);\n\n const paths = Object.keys(resolved.group.children);\n const sectioned = new Set(resolved.sections.flatMap((s) => s.paths));\n const loose = paths.filter((p) => !sectioned.has(p));\n\n const row = (path: string): ReactNode => (\n <ControlRow\n key={path}\n path={path}\n resolved={resolved}\n config={config}\n setConfig={setConfig}\n renderers={renderers}\n showHidden={showHidden}\n />\n );\n\n return (\n <PropertyList className={className ? `lk-control-panel ${className}` : 'lk-control-panel'}>\n {loose.map(row)}\n {resolved.sections.map((section) => (\n <PropertyGroup key={section.label} title={section.label}>\n {section.paths.map(row)}\n </PropertyGroup>\n ))}\n </PropertyList>\n );\n}\n\ninterface ControlRowProps<TC extends Record<string, unknown>> {\n path: string;\n resolved: ResolvedConfig;\n config: TC;\n setConfig: (key: keyof TC, value: unknown) => void;\n renderers?: Record<string, ControlRenderer>;\n showHidden: boolean;\n}\n\n/** Reads a labkit-only extra off a leaf. `PrefLeaf` has no field for these,\n * and extra keys survive the resolve pass at runtime. */\nfunction extra<T>(leaf: PrefLeaf, key: string): T | undefined {\n return (leaf as unknown as Record<string, T | undefined>)[key];\n}\n\nfunction ControlRow<TC extends Record<string, unknown>>({\n path,\n resolved,\n config,\n setConfig,\n renderers,\n showHidden,\n}: ControlRowProps<TC>) {\n const leaf = resolved.group.children[path] as PrefLeaf | undefined;\n if (!leaf || !('kind' in leaf)) return null;\n if (!isLeafVisible(resolved, path, config as Record<string, unknown>, showHidden)) return null;\n\n const write = (value: unknown): void => setConfig(path as keyof TC, value);\n const fallback = extra<unknown>(leaf, 'default');\n const value = config[path] ?? fallback;\n\n // Most specific wins, and within a tier the lab's entry beats the\n // instrument's: controls[path] -> node .render -> controls[kind] -> built-in.\n const custom = renderers?.[path] ?? resolved.renderers[path] ?? renderers?.[leaf.kind];\n if (custom) return custom({ path, pref: leaf, value, setValue: write });\n\n const label = leaf.name;\n const description = leaf.description;\n const read = <T,>(): T => value as T;\n\n if (!isBuiltinToolPref(leaf))\n return <UnwiredRow label={label} kind={leaf.kind} description={description} />;\n\n switch (leaf.kind) {\n case 'number': {\n const min = extra<number>(leaf, 'min');\n const max = extra<number>(leaf, 'max');\n const step = extra<number>(leaf, 'step');\n if (extra<string>(leaf, 'control') === 'slider' && min !== undefined && max !== undefined) {\n return (\n <SliderRow\n label={label}\n value={read<number>()}\n min={min}\n max={max}\n step={step}\n onChange={write}\n description={description}\n />\n );\n }\n // NumberRow commits every keystroke and does not clamp, so the bounds a\n // schema declares are enforced here — an instrument should never be\n // handed a config value outside the range it asked for.\n const lo = min ?? Number.NEGATIVE_INFINITY;\n const hi = max ?? Number.POSITIVE_INFINITY;\n return (\n <NumberRow\n label={label}\n value={read<number>()}\n min={min}\n max={max}\n step={step}\n onChange={(n) => write(Math.min(hi, Math.max(lo, n)))}\n description={description}\n />\n );\n }\n case 'boolean':\n return (\n <CheckboxRow\n label={label}\n value={read<boolean>()}\n onChange={write}\n description={description}\n />\n );\n case 'enum': {\n const options = extra<readonly { value: string; label: string }[]>(leaf, 'options') ?? [];\n const Row = extra<string>(leaf, 'control') === 'radio' ? ToggleRow : SelectRow;\n return (\n <Row\n label={label}\n value={read<string>()}\n options={options}\n onChange={write}\n description={description}\n />\n );\n }\n case 'string':\n return (\n <DebouncedTextRow\n leaf={leaf}\n label={label}\n value={read<string>()}\n write={write}\n description={description}\n />\n );\n case 'color':\n return (\n <ColorRow label={label} value={read<string>()} onChange={write} description={description} />\n );\n case 'paint':\n case 'object':\n // Declined: a hex swatch would write a solid over a gradient, and a flat\n // row would write one field into a half-built object. Override with\n // `render` to edit either.\n return <UnwiredRow label={label} kind={leaf.kind} description={description} />;\n default: {\n // Not reachable while every built-in kind has an arm — and a new kind\n // that lacks one is a compile error here, never a blank row.\n const _exhaustive: never = leaf;\n throw new Error(\n `ControlPanel: no control for built-in pref kind \"${(_exhaustive as { kind: string }).kind}\"`,\n );\n }\n }\n}\n\n/** A leaf this panel has no control for is named rather than dropped: a silent\n * gap reads as \"this control does not exist\". */\nfunction UnwiredRow({\n label,\n kind,\n description,\n}: {\n label: string;\n kind: string;\n description?: string;\n}) {\n return (\n <PropertyRow label={label} description={description}>\n <span className=\"lk-control-panel__unknown\">no control for “{kind}”</span>\n </PropertyRow>\n );\n}\n\n/** Text writes are debounced so typing does not re-run the instrument on every\n * keystroke, which means the row is locally controlled between commits and has\n * to notice when the config changes underneath it. */\nfunction DebouncedTextRow({\n leaf,\n label,\n value,\n write,\n description,\n}: {\n leaf: PrefLeaf;\n label: string;\n value: string;\n write: (value: unknown) => void;\n description?: string;\n}) {\n const debounceMs = extra<number>(leaf, 'debounceMs') ?? 150;\n const [local, setLocal] = useState(value);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastExternal = useRef(value);\n\n useEffect(() => {\n if (value !== lastExternal.current) {\n lastExternal.current = value;\n setLocal(value);\n }\n }, [value]);\n\n useEffect(\n () => () => {\n if (timer.current) clearTimeout(timer.current);\n },\n [],\n );\n\n return (\n <TextRow\n label={label}\n description={description}\n value={local}\n placeholder={extra<string>(leaf, 'placeholder')}\n maxLength={extra<number>(leaf, 'maxLength')}\n onChange={(next) => {\n setLocal(next);\n if (timer.current) clearTimeout(timer.current);\n const commit = () => {\n lastExternal.current = next;\n write(next);\n };\n if (debounceMs === 0) commit();\n else timer.current = setTimeout(commit, debounceMs);\n }}\n />\n );\n}\n"]}