@weasel-js/labkit 1.4.0-pre.1 → 1.4.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 (120) hide show
  1. package/dist/_dts/{CanvasStackContext-LnCfqNBA.d.ts → CanvasStackContext-BIRUVVGH.d.ts} +1 -1
  2. package/dist/_dts/PrefsForm.d-CgxUequc.d.ts +20 -0
  3. package/dist/_dts/{frac-C-2c72Ij.d.ts → frac-X7mWgd7y.d.ts} +10 -4
  4. package/dist/_dts/{index-BDVzvRzQ.d.ts → index-FEa1MudK.d.ts} +8 -2
  5. package/dist/_dts/{types-DYMaEvM5.d.ts → types-ChVJJHvk.d.ts} +3 -0
  6. package/dist/_dts/{types-D6s4b7if.d.ts → types-lg4TSCb2.d.ts} +3 -1
  7. package/dist/_dts/{useTrialState-gmMvZqPc.d.ts → useTrialState-Cdm13fvl.d.ts} +2 -1
  8. package/dist/_dts/weasel-canvas-FJTFi3ZZ.d.ts +5041 -0
  9. package/dist/canvas/index.d.ts +16 -16
  10. package/dist/canvas/index.js +2 -2
  11. package/dist/chrome/index.d.ts +6 -6
  12. package/dist/chrome/index.js +5 -5
  13. package/dist/chunk-2YILQ7Y5.js +33 -0
  14. package/dist/chunk-2YILQ7Y5.js.map +1 -0
  15. package/dist/{chunk-TO2FUOKF.js → chunk-53AZ2O2N.js} +16 -13
  16. package/dist/chunk-53AZ2O2N.js.map +1 -0
  17. package/dist/{chunk-QB5SM4BM.js → chunk-7TRFMIWX.js} +55 -41
  18. package/dist/chunk-7TRFMIWX.js.map +1 -0
  19. package/dist/{chunk-6OEYTYML.js → chunk-BMQWLKOL.js} +15 -15
  20. package/dist/chunk-BMQWLKOL.js.map +1 -0
  21. package/dist/{chunk-M75ZU6ZZ.js → chunk-D7QIPGEB.js} +3 -3
  22. package/dist/{chunk-M75ZU6ZZ.js.map → chunk-D7QIPGEB.js.map} +1 -1
  23. package/dist/{chunk-L5QJOOLV.js → chunk-DG2IFMLA.js} +1309 -273
  24. package/dist/chunk-DG2IFMLA.js.map +1 -0
  25. package/dist/{chunk-LN6JDUGB.js → chunk-HXXTULDN.js} +2 -2
  26. package/dist/{chunk-LN6JDUGB.js.map → chunk-HXXTULDN.js.map} +1 -1
  27. package/dist/{chunk-RBGKL7NF.js → chunk-J6SBFZYT.js} +1807 -1814
  28. package/dist/chunk-J6SBFZYT.js.map +1 -0
  29. package/dist/{chunk-XJ6N32QP.js → chunk-LJSIUFYD.js} +14 -30
  30. package/dist/chunk-LJSIUFYD.js.map +1 -0
  31. package/dist/{chunk-AE5CNVRU.js → chunk-MIT3ISW4.js} +37 -31
  32. package/dist/chunk-MIT3ISW4.js.map +1 -0
  33. package/dist/{chunk-HHGVISVZ.js → chunk-MSR7EVS6.js} +7 -5
  34. package/dist/chunk-MSR7EVS6.js.map +1 -0
  35. package/dist/{chunk-ESIQNQ6K.js → chunk-OFCBEZMU.js} +12 -6
  36. package/dist/chunk-OFCBEZMU.js.map +1 -0
  37. package/dist/{chunk-HMFODCOX.js → chunk-PP7ZWAMV.js} +83 -75
  38. package/dist/chunk-PP7ZWAMV.js.map +1 -0
  39. package/dist/{chunk-E2UQVZ44.js → chunk-RLOXQZW3.js} +3 -3
  40. package/dist/{chunk-E2UQVZ44.js.map → chunk-RLOXQZW3.js.map} +1 -1
  41. package/dist/controls/index.d.ts +4 -3
  42. package/dist/controls/index.js +3 -3
  43. package/dist/dragdrop/index.d.ts +5 -5
  44. package/dist/dragdrop/index.js +2 -2
  45. package/dist/index.d.ts +57 -77
  46. package/dist/index.js +308 -161
  47. package/dist/index.js.map +1 -1
  48. package/dist/job/index.js +1 -1
  49. package/dist/layers/index.d.ts +6 -6
  50. package/dist/layers/index.js +3 -3
  51. package/dist/loupe/index.d.ts +7 -13
  52. package/dist/loupe/index.js +2 -2
  53. package/dist/passthrough/weasel-canvas.d.ts +3 -343
  54. package/dist/passthrough/weasel-canvas.js +1 -1
  55. package/dist/passthrough/weasel-ui.d.ts +141 -2866
  56. package/dist/passthrough/weasel-ui.js +2 -2
  57. package/dist/primitives/index.js +4 -4
  58. package/dist/state/index.d.ts +3 -3
  59. package/dist/state/index.js +4 -2
  60. package/dist/state/index.js.map +1 -1
  61. package/dist/styles.css +74 -5
  62. package/dist/surface/index.d.ts +17 -2
  63. package/dist/surface/index.js +3 -2
  64. package/dist/ui/layers/index.js +2 -2
  65. package/dist/undo/index.d.ts +6 -5
  66. package/package.json +8 -8
  67. package/src/annotations/AnnotationOverlay.tsx +10 -6
  68. package/src/annotations/Annotations.less +6 -0
  69. package/src/annotations/Annotations.overlay.test.tsx +113 -0
  70. package/src/annotations/MarkList.tsx +3 -2
  71. package/src/canvas/CanvasStack.tsx +8 -13
  72. package/src/canvas/useOrbit.test.ts +93 -1
  73. package/src/canvas/useOrbit.ts +41 -34
  74. package/src/canvas/usePanZoom.test.ts +102 -1
  75. package/src/canvas/usePanZoom.ts +54 -36
  76. package/src/config/builder.test.ts +5 -0
  77. package/src/config/builder.ts +6 -0
  78. package/src/config/types.ts +1 -0
  79. package/src/controls/ControlPanel.test.tsx +23 -0
  80. package/src/controls/ControlPanel.tsx +3 -0
  81. package/src/job/useJob.ts +1 -1
  82. package/src/lab/Lab.surface.test.tsx +8 -3
  83. package/src/lab/LabHeader.test.tsx +12 -0
  84. package/src/lab/LabHeader.tsx +16 -6
  85. package/src/lab/Workspace.tsx +1 -1
  86. package/src/layers/LayerList.test.tsx +72 -1
  87. package/src/layers/LayerList.tsx +40 -32
  88. package/src/passthrough/weasel-ui.test.ts +9 -0
  89. package/src/passthrough/weasel-ui.ts +4 -0
  90. package/src/primitives/FloatingPanel.test.tsx +82 -0
  91. package/src/primitives/FloatingPanel.tsx +59 -41
  92. package/src/primitives/ZoomControl.tsx +2 -0
  93. package/src/state/store.ts +10 -0
  94. package/src/state/types.ts +3 -0
  95. package/src/surface/AGENTS.md +11 -1
  96. package/src/surface/index.ts +7 -1
  97. package/src/surface/useSurfaceTile.ts +20 -2
  98. package/src/surface/useTiledSurface.ts +4 -1
  99. package/src/theme/Interstellar.stories.tsx +4 -3
  100. package/src/theme/base.less +39 -1
  101. package/src/trial/Trial.less +27 -5
  102. package/src/trial/TrialBody.test.tsx +67 -0
  103. package/src/trial/TrialBody.tsx +155 -0
  104. package/src/trial/TrialChrome.tsx +18 -10
  105. package/src/trial/index.ts +2 -0
  106. package/dist/_dts/DrawCommand-B3bskUsC.d.ts +0 -564
  107. package/dist/_dts/PrefsForm-BkUJZx0A.d.ts +0 -204
  108. package/dist/_dts/fitViewToBounds-dZ2UDB6e.d.ts +0 -21
  109. package/dist/_dts/shapeKinds-Cx_rxwsa.d.ts +0 -87
  110. package/dist/_dts/types-C-gh9Ap-.d.ts +0 -695
  111. package/dist/chunk-6OEYTYML.js.map +0 -1
  112. package/dist/chunk-AE5CNVRU.js.map +0 -1
  113. package/dist/chunk-ESIQNQ6K.js.map +0 -1
  114. package/dist/chunk-HHGVISVZ.js.map +0 -1
  115. package/dist/chunk-HMFODCOX.js.map +0 -1
  116. package/dist/chunk-L5QJOOLV.js.map +0 -1
  117. package/dist/chunk-QB5SM4BM.js.map +0 -1
  118. package/dist/chunk-RBGKL7NF.js.map +0 -1
  119. package/dist/chunk-TO2FUOKF.js.map +0 -1
  120. package/dist/chunk-XJ6N32QP.js.map +0 -1
@@ -102,5 +102,5 @@ function useJob({
102
102
  }
103
103
 
104
104
  export { useJob };
105
- //# sourceMappingURL=chunk-LN6JDUGB.js.map
106
- //# sourceMappingURL=chunk-LN6JDUGB.js.map
105
+ //# sourceMappingURL=chunk-HXXTULDN.js.map
106
+ //# sourceMappingURL=chunk-HXXTULDN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/job/useJob.ts"],"names":[],"mappings":"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","file":"chunk-LN6JDUGB.js","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { JobCapability, JobFailure, JobHandle, JobStatus } from './types';\n\nexport interface UseJobOptions<TS, TC, TItem> {\n capability: JobCapability<TS, TC, TItem>;\n config: TC;\n state: TS;\n setState: (next: TS | ((prev: TS) => TS)) => void;\n}\n\ninterface Progress {\n status: JobStatus;\n done: number;\n total: number | null;\n failures: JobFailure[];\n error: string | null;\n}\n\nconst IDLE: Progress = { status: 'idle', done: 0, total: null, failures: [], error: null };\n\nfunction sameKey(a: readonly unknown[] | null, b: readonly unknown[] | null): boolean {\n if (a === null || b === null) return a === b;\n return a.length === b.length && a.every((v, i) => Object.is(v, b[i]));\n}\n\nexport function useJob<TS, TC, TItem>({\n capability,\n config,\n state,\n setState,\n}: UseJobOptions<TS, TC, TItem>): JobHandle {\n const [progress, setProgress] = useState<Progress>(IDLE);\n\n // A run is identified by a token. Every result checks its token before touching\n // state, so a superseded run finishes harmlessly instead of racing the winner.\n const token = useRef(0);\n const abort = useRef<AbortController | null>(null);\n\n // Read through refs: `run` is called once per run and must see the values as of\n // that moment rather than re-subscribing on every render.\n const capRef = useRef(capability);\n capRef.current = capability;\n const configRef = useRef(config);\n configRef.current = config;\n const stateRef = useRef(state);\n stateRef.current = state;\n const setStateRef = useRef(setState);\n setStateRef.current = setState;\n\n const cancel = useCallback(() => {\n token.current += 1;\n abort.current?.abort();\n abort.current = null;\n setProgress(IDLE);\n }, []);\n\n const start = useCallback(() => {\n token.current += 1;\n const mine = token.current;\n abort.current?.abort();\n const controller = new AbortController();\n abort.current = controller;\n setProgress({ ...IDLE, status: 'running' });\n\n void (async () => {\n try {\n const iterable = capRef.current.run({\n config: configRef.current,\n state: stateRef.current,\n signal: controller.signal,\n });\n for await (const event of iterable) {\n if (token.current !== mine) return;\n if (event.kind === 'total') {\n setProgress((p) => ({ ...p, total: event.total }));\n } else if (event.kind === 'failed') {\n setProgress((p) => ({\n ...p,\n failures: [...p.failures, { index: event.index, error: event.error }],\n }));\n } else {\n const fold = capRef.current.onItem;\n const item = event.item;\n setStateRef.current((prev) => fold(item, prev));\n setProgress((p) => ({ ...p, done: p.done + 1 }));\n }\n }\n if (token.current !== mine) return;\n setProgress((p) => ({ ...p, status: 'done' }));\n } catch (err) {\n if (token.current !== mine) return;\n setProgress((p) => ({\n ...p,\n status: 'error',\n error: err instanceof Error ? err.message : String(err),\n }));\n }\n })();\n }, []);\n\n // Re-run when the declared key changes. `auto` covers the first mount too.\n const lastKey = useRef<readonly unknown[] | null>(null);\n const started = useRef(false);\n const auto = capability.auto === true;\n const key = capability.key ? capability.key(config, state) : null;\n // `key` is compared element-wise inside; depending on the array identity here\n // would restart the job on every render.\n useEffect(() => {\n if (!auto) return;\n if (started.current && sameKey(lastKey.current, key)) return;\n lastKey.current = key;\n started.current = true;\n start();\n }, [auto, key, start]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(\n () => () => {\n token.current += 1;\n abort.current?.abort();\n abort.current = null;\n },\n [],\n );\n\n return {\n status: progress.status,\n done: progress.done,\n total: progress.total,\n failures: progress.failures,\n error: progress.error,\n start,\n cancel,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/job/useJob.ts"],"names":[],"mappings":"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","file":"chunk-HXXTULDN.js","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { JobCapability, JobFailure, JobHandle, JobStatus } from './types';\n\nexport interface UseJobOptions<TS, TC, TItem> {\n capability: JobCapability<TS, TC, TItem>;\n config: TC;\n state: TS;\n setState: (next: TS | ((prev: TS) => TS)) => void;\n}\n\ninterface Progress {\n status: JobStatus;\n done: number;\n total: number | null;\n failures: JobFailure[];\n error: string | null;\n}\n\nconst IDLE: Progress = { status: 'idle', done: 0, total: null, failures: [], error: null };\n\nfunction sameKey(a: readonly unknown[] | null, b: readonly unknown[] | null): boolean {\n if (a === null || b === null) return a === b;\n return a.length === b.length && a.every((v, i) => Object.is(v, b[i]));\n}\n\nexport function useJob<TS, TC, TItem>({\n capability,\n config,\n state,\n setState,\n}: UseJobOptions<TS, TC, TItem>): JobHandle {\n const [progress, setProgress] = useState<Progress>(IDLE);\n\n // A run is identified by a token. Every result checks its token before touching\n // state, so a superseded run finishes harmlessly instead of racing the winner.\n const token = useRef(0);\n const abort = useRef<AbortController | null>(null);\n\n // Read through refs: `run` is called once per run and must see the values as of\n // that moment rather than re-subscribing on every render.\n const capRef = useRef(capability);\n capRef.current = capability;\n const configRef = useRef(config);\n configRef.current = config;\n const stateRef = useRef(state);\n stateRef.current = state;\n const setStateRef = useRef(setState);\n setStateRef.current = setState;\n\n const cancel = useCallback(() => {\n token.current += 1;\n abort.current?.abort();\n abort.current = null;\n setProgress(IDLE);\n }, []);\n\n const start = useCallback(() => {\n token.current += 1;\n const mine = token.current;\n abort.current?.abort();\n const controller = new AbortController();\n abort.current = controller;\n setProgress({ ...IDLE, status: 'running' });\n\n void (async () => {\n try {\n const iterable = capRef.current.run({\n config: configRef.current,\n state: stateRef.current,\n signal: controller.signal,\n });\n for await (const event of iterable) {\n if (token.current !== mine) return;\n if (event.kind === 'total') {\n setProgress((p) => ({ ...p, total: event.total }));\n } else if (event.kind === 'failed') {\n setProgress((p) => ({\n ...p,\n failures: [...p.failures, { index: event.index, error: event.error }],\n }));\n } else {\n const fold = capRef.current.onItem;\n const item = event.item;\n setStateRef.current((prev) => fold(item, prev));\n setProgress((p) => ({ ...p, done: p.done + 1 }));\n }\n }\n if (token.current !== mine) return;\n setProgress((p) => ({ ...p, status: 'done' }));\n } catch (err) {\n if (token.current !== mine) return;\n setProgress((p) => ({\n ...p,\n status: 'error',\n error: err instanceof Error ? err.message : String(err),\n }));\n }\n })();\n }, []);\n\n // Re-run when the declared key changes. `auto` covers the first mount too.\n const lastKey = useRef<readonly unknown[] | null>(null);\n const started = useRef(false);\n const auto = capability.auto === true;\n const key = capability.key ? capability.key(config, state) : null;\n // `key` is compared element-wise inside; depending on the array identity here\n // would restart the job on every render.\n useEffect(() => {\n if (!auto) return;\n if (started.current && sameKey(lastKey.current, key)) return;\n lastKey.current = key;\n started.current = true;\n start();\n }, [auto, key, start]);\n\n useEffect(\n () => () => {\n token.current += 1;\n abort.current?.abort();\n abort.current = null;\n },\n [],\n );\n\n return {\n status: progress.status,\n done: progress.done,\n total: progress.total,\n failures: progress.failures,\n error: progress.error,\n start,\n cancel,\n };\n}\n"]}