@weasel-js/labkit 1.4.4 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -2
- package/dist/_dts/{CanvasStackContext-kTEZvEgE.d.ts → CanvasStackContext-CqkxkFJW.d.ts} +1 -1
- package/dist/_dts/ToggleBar.d-DbHoWKIA.d.ts +116 -0
- package/dist/_dts/{frac-z7ker2Vx.d.ts → frac-8R6UmlvN.d.ts} +253 -31
- package/dist/_dts/index-B8uu2ba7.d.ts +237 -0
- package/dist/_dts/{index-Blv9uQzu.d.ts → index-retnAut7.d.ts} +18 -10
- package/dist/_dts/{types-B9_zrHmb.d.ts → types-Ca2LCnPq.d.ts} +65 -2
- package/dist/_dts/usePanZoom-nS798rOF.d.ts +160 -0
- package/dist/_dts/useTrialState-jcx_TdU6.d.ts +212 -0
- package/dist/canvas/index.d.ts +17 -128
- package/dist/canvas/index.js +4 -2
- package/dist/chrome/index.d.ts +4 -92
- package/dist/chrome/index.js +9 -5
- package/dist/chunk-67SJLMC7.js +704 -0
- package/dist/chunk-67SJLMC7.js.map +1 -0
- package/dist/chunk-6ZDGOZQV.js +310 -0
- package/dist/chunk-6ZDGOZQV.js.map +1 -0
- package/dist/{chunk-MOM3GOVY.js → chunk-EKIICY6X.js} +111 -25
- package/dist/chunk-EKIICY6X.js.map +1 -0
- package/dist/{chunk-CTRKTLYZ.js → chunk-H6ZAOWNE.js} +11 -11
- package/dist/chunk-H6ZAOWNE.js.map +1 -0
- package/dist/{chunk-SMHP6XZ4.js → chunk-KJALCDWE.js} +9 -7
- package/dist/chunk-KJALCDWE.js.map +1 -0
- package/dist/{chunk-BKFVHKJH.js → chunk-MUKOW3TC.js} +3 -3
- package/dist/{chunk-BKFVHKJH.js.map → chunk-MUKOW3TC.js.map} +1 -1
- package/dist/chunk-NDRYLVOW.js +15 -0
- package/dist/chunk-NDRYLVOW.js.map +1 -0
- package/dist/{chunk-64ZCN3DA.js → chunk-NS64DXMN.js} +226 -159
- package/dist/chunk-NS64DXMN.js.map +1 -0
- package/dist/{chunk-I6JCVE24.js → chunk-PGETSEDK.js} +135 -13
- package/dist/chunk-PGETSEDK.js.map +1 -0
- package/dist/{chunk-FQMJUVHJ.js → chunk-QLSV2N3G.js} +32 -37
- package/dist/chunk-QLSV2N3G.js.map +1 -0
- package/dist/chunk-RWNDDKOH.js +682 -0
- package/dist/chunk-RWNDDKOH.js.map +1 -0
- package/dist/chunk-S2SHZRD7.js +7681 -0
- package/dist/chunk-S2SHZRD7.js.map +1 -0
- package/dist/{chunk-U3IYHIAE.js → chunk-TQBBYTAF.js} +19 -82
- package/dist/chunk-TQBBYTAF.js.map +1 -0
- package/dist/chunk-UU3NJO6N.js +72 -0
- package/dist/chunk-UU3NJO6N.js.map +1 -0
- package/dist/chunk-WIG6XHJ7.js +35 -0
- package/dist/chunk-WIG6XHJ7.js.map +1 -0
- package/dist/{chunk-TJ7QY3OC.js → chunk-ZPH5WTWF.js} +21 -15
- package/dist/chunk-ZPH5WTWF.js.map +1 -0
- package/dist/config/index.d.ts +232 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/controls/index.d.ts +2 -3
- package/dist/controls/index.js +3 -2
- package/dist/dragdrop/index.d.ts +2 -4
- package/dist/index.d.ts +110 -381
- package/dist/index.js +691 -817
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +3 -5
- package/dist/layers/index.js +2 -2
- package/dist/loupe/index.d.ts +6 -8
- package/dist/loupe/index.js +2 -2
- package/dist/passthrough/weasel-ui.d.ts +164 -122
- package/dist/passthrough/weasel-ui.js +1 -1
- package/dist/primitives/index.d.ts +53 -6
- package/dist/primitives/index.js +6 -4
- package/dist/state/index.d.ts +12 -7
- package/dist/state/index.js +16 -13
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +84 -50
- package/dist/surface/index.d.ts +44 -7
- package/dist/surface/index.js +2 -1
- package/dist/ui/layers/index.js +1 -1
- package/dist/undo/index.d.ts +2 -4
- package/package.json +15 -8
- package/src/annotations/AnnotationOverlay.tsx +53 -5
- package/src/annotations/Annotations.overlay.test.tsx +85 -6
- package/src/annotations/drawOne.test.ts +1 -1
- package/src/annotations/drawOne.ts +2 -2
- package/src/annotations/paint.test.ts +2 -2
- package/src/annotations/paint.ts +1 -1
- package/src/annotations/preload.ts +6 -0
- package/src/annotations/store.test.ts +18 -0
- package/src/annotations/store.ts +5 -4
- package/src/annotations/svgNodes.test.ts +2 -2
- package/src/annotations/toolMap.ts +3 -3
- package/src/annotations/types.ts +6 -3
- package/src/canvas/CameraWheelContext.ts +12 -0
- package/src/canvas/CanvasStack.test.tsx +25 -0
- package/src/canvas/CanvasStack.tsx +31 -4
- package/src/canvas/Stage.less +18 -0
- package/src/canvas/Stage.test.tsx +186 -0
- package/src/canvas/Stage.tsx +134 -0
- package/src/canvas/camera.test.ts +17 -2
- package/src/canvas/camera.ts +9 -9
- package/src/canvas/index.ts +4 -0
- package/src/canvas/usePanZoom.ts +10 -5
- package/src/chrome/ChromeRegions.stories.tsx +0 -3
- package/src/chrome/LabChrome.tsx +114 -0
- package/src/chrome/builtins.tsx +20 -31
- package/src/chrome/index.ts +15 -0
- package/src/chrome/labRegions.test.tsx +208 -0
- package/src/chrome/labTypes.ts +50 -0
- package/src/chrome/merge.ts +7 -9
- package/src/chrome/regions/PaletteRegion.test.tsx +6 -4
- package/src/chrome/regions/PaletteRegion.tsx +21 -9
- package/src/chrome/regions/SidebarRegion.tsx +25 -13
- package/src/chrome/regions/StatusRegion.tsx +15 -8
- package/src/chrome/regions/ToolbarRegion.tsx +30 -16
- package/src/chrome/types.ts +47 -20
- package/src/config/builder.test.ts +4 -0
- package/src/config/builder.ts +16 -10
- package/src/config/declarationEmit.fixture.ts +11 -0
- package/src/config/declarationEmit.test.ts +51 -0
- package/src/config/entry.test.ts +46 -0
- package/src/config/index.ts +13 -1
- package/src/config/nodeClasses.test.ts +18 -0
- package/src/config/types.ts +3 -1
- package/src/controls/ControlPanel.test.tsx +16 -0
- package/src/controls/ControlPanel.tsx +5 -2
- package/src/fake-indexeddb-auto.d.ts +5 -0
- package/src/index.test.ts +7 -0
- package/src/index.ts +38 -5
- package/src/instrument/serializers.test.ts +22 -0
- package/src/instrument/serializers.ts +11 -0
- package/src/instrument/types.ts +25 -1
- package/src/lab/Lab.less +4 -13
- package/src/lab/Lab.persist.test.tsx +147 -0
- package/src/lab/Lab.stories.tsx +0 -2
- package/src/lab/Lab.surface.test.tsx +66 -3
- package/src/lab/Lab.test.tsx +91 -17
- package/src/lab/Lab.tsx +337 -124
- package/src/lab/LabFit.stories.less +18 -0
- package/src/lab/LabFit.stories.tsx +219 -0
- package/src/lab/LabFullChrome.stories.tsx +0 -3
- package/src/lab/LabHeader.test.tsx +40 -9
- package/src/lab/LabHeader.tsx +7 -13
- package/src/lab/LabPalette.tsx +13 -26
- package/src/lab/LabShell.less +49 -12
- package/src/lab/LabSwitcher.less +8 -1
- package/src/lab/Workspace.surface.test.tsx +2 -1
- package/src/lab/fitCheck.test.ts +57 -0
- package/src/lab/fitCheck.ts +125 -0
- package/src/loupe/AGENTS.md +1 -1
- package/src/loupe/Loupe.less +1 -1
- package/src/loupe/canvasLens.ts +1 -1
- package/src/loupe/types.ts +1 -1
- package/src/loupe/useLoupe.test.tsx +1 -1
- package/src/loupe/useLoupe.ts +1 -1
- package/src/passthrough/weasel-ui.ts +9 -0
- package/src/primitives/FloatingPanel.stories.tsx +13 -1
- package/src/primitives/FloatingPanel.test.tsx +47 -16
- package/src/primitives/FloatingPanel.tsx +11 -25
- package/src/primitives/Split.less +14 -0
- package/src/primitives/Split.test.tsx +108 -0
- package/src/primitives/Split.tsx +159 -0
- package/src/primitives/ZoomControl.tsx +5 -2
- package/src/primitives/index.ts +2 -0
- package/src/state/Persistence.stories.tsx +75 -0
- package/src/state/Persistence.tsx +33 -0
- package/src/state/SingletonExperiment.test.tsx +47 -53
- package/src/state/SingletonExperiment.tsx +24 -13
- package/src/state/adapterContract.ts +116 -0
- package/src/state/adapters.test.ts +113 -61
- package/src/state/adapters.ts +328 -69
- package/src/state/document.test.ts +71 -96
- package/src/state/document.ts +66 -52
- package/src/state/helpers.test.ts +1 -1
- package/src/state/index.ts +8 -0
- package/src/state/labRecords.test.ts +105 -0
- package/src/state/labRecords.ts +160 -0
- package/src/state/openLabStore.test.ts +658 -0
- package/src/state/openLabStore.ts +403 -0
- package/src/state/records.test.ts +234 -0
- package/src/state/records.ts +219 -0
- package/src/state/store.test.ts +104 -635
- package/src/state/store.ts +116 -157
- package/src/state/toolSlot.test.ts +1 -1
- package/src/state/types.ts +39 -15
- package/src/state/useOpenOnce.ts +68 -0
- package/src/state/usePersistedState.test.tsx +125 -0
- package/src/state/usePersistedState.ts +66 -0
- package/src/state/useTrialState.test.tsx +2 -3
- package/src/state/view.test.ts +49 -15
- package/src/state/view.ts +18 -1
- package/src/styles.less +2 -0
- package/src/surface/AGENTS.md +39 -7
- package/src/surface/SurfaceContext.ts +26 -3
- package/src/surface/index.ts +2 -0
- package/src/surface/useSurfaceTile.test.tsx +2 -1
- package/src/surface/useSurfaceTile.ts +6 -5
- package/src/surface/useTiledSurface.test.tsx +175 -0
- package/src/surface/useTiledSurface.ts +54 -5
- package/src/theme/Interstellar.stories.tsx +7 -7
- package/src/theme/interstellar.test.ts +1 -1
- package/src/theme/interstellar.tokens.json +2 -2
- package/src/tools/labTool.ts +11 -0
- package/src/trial/Trial.annotations.persist.test.tsx +100 -58
- package/src/trial/Trial.annotations.test.tsx +47 -4
- package/src/trial/Trial.job.test.tsx +3 -3
- package/src/trial/Trial.less +1 -26
- package/src/trial/Trial.stories.tsx +1 -2
- package/src/trial/Trial.test.tsx +28 -4
- package/src/trial/Trial.trialId.test.tsx +23 -1
- package/src/trial/Trial.tsx +118 -38
- package/src/trial/TrialBody.tsx +17 -141
- package/src/trial/TrialChrome.tsx +7 -4
- package/src/trial/trialOps.ts +5 -3
- package/dist/_dts/types-BP2OCcpg.d.ts +0 -155
- package/dist/_dts/types-x92Kfeme.d.ts +0 -62
- package/dist/_dts/useTrialState-D6Vb3T-g.d.ts +0 -99
- package/dist/chunk-2P6PP5N4.js +0 -553
- package/dist/chunk-2P6PP5N4.js.map +0 -1
- package/dist/chunk-64ZCN3DA.js.map +0 -1
- package/dist/chunk-CTRKTLYZ.js.map +0 -1
- package/dist/chunk-FQMJUVHJ.js.map +0 -1
- package/dist/chunk-I6JCVE24.js.map +0 -1
- package/dist/chunk-MOM3GOVY.js.map +0 -1
- package/dist/chunk-SMHP6XZ4.js.map +0 -1
- package/dist/chunk-TJ7QY3OC.js.map +0 -1
- package/dist/chunk-U3IYHIAE.js.map +0 -1
- package/dist/chunk-W3ECWC2K.js +0 -7335
- package/dist/chunk-W3ECWC2K.js.map +0 -1
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { LabDocument, SavedSnapshot, SerializedTrial } from './types';
|
|
2
|
+
|
|
3
|
+
/** Every record of the lab stored under `storageKey` starts with this. The key
|
|
4
|
+
* is URI-encoded, so it holds no `:` and one lab's prefix can never reach into
|
|
5
|
+
* another lab's records. */
|
|
6
|
+
export function labPrefix(storageKey: string): string {
|
|
7
|
+
return `lk:${encodeURIComponent(storageKey)}:`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const META_RECORD = 'meta';
|
|
11
|
+
export const LAYOUT_RECORD = 'layout';
|
|
12
|
+
export const UNDOCK_RECORD = 'undock';
|
|
13
|
+
|
|
14
|
+
export function trialRecord(id: string): string {
|
|
15
|
+
return `trial:${encodeURIComponent(id)}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function saveRecord(id: string): string {
|
|
19
|
+
return `save:${encodeURIComponent(id)}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The prefix every value scoped to one trial shares. */
|
|
23
|
+
export function trialValuesPrefix(trialId: string): string {
|
|
24
|
+
return `value:trial:${encodeURIComponent(trialId)}:`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Where a `usePersistedState` value lives: under its trial, or — with a null
|
|
28
|
+
* trial — under the lab. */
|
|
29
|
+
export function valueRecord(trialId: string | null, name: string): string {
|
|
30
|
+
const encoded = encodeURIComponent(name);
|
|
31
|
+
return trialId === null ? `value:lab:${encoded}` : `${trialValuesPrefix(trialId)}${encoded}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** What a record name addresses, or null for a name no lab writes. */
|
|
35
|
+
export type RecordName =
|
|
36
|
+
| { kind: 'meta' | 'layout' | 'undock' | 'value' }
|
|
37
|
+
| { kind: 'trial' | 'save'; id: string };
|
|
38
|
+
|
|
39
|
+
export function parseRecordName(name: string): RecordName | null {
|
|
40
|
+
const parts = name.split(':');
|
|
41
|
+
try {
|
|
42
|
+
switch (parts[0]) {
|
|
43
|
+
case 'meta':
|
|
44
|
+
case 'layout':
|
|
45
|
+
case 'undock':
|
|
46
|
+
return parts.length === 1 ? { kind: parts[0] } : null;
|
|
47
|
+
case 'trial':
|
|
48
|
+
case 'save':
|
|
49
|
+
return parts.length === 2 && parts[1]
|
|
50
|
+
? { kind: parts[0], id: decodeURIComponent(parts[1]) }
|
|
51
|
+
: null;
|
|
52
|
+
case 'value':
|
|
53
|
+
return (parts[1] === 'lab' && parts.length === 3) ||
|
|
54
|
+
(parts[1] === 'trial' && parts.length === 4)
|
|
55
|
+
? { kind: 'value' }
|
|
56
|
+
: null;
|
|
57
|
+
default:
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The fields of the meta record. */
|
|
66
|
+
export interface LabMeta {
|
|
67
|
+
version: number;
|
|
68
|
+
mode: unknown;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
72
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** A document as the records a lab stores it in, `meta` last — so a write in
|
|
76
|
+
* this order that stops partway leaves no `meta`, and the next open folds the
|
|
77
|
+
* old storage again rather than trusting a partial set. */
|
|
78
|
+
export function recordsOfDocument(doc: LabDocument): [string, unknown][] {
|
|
79
|
+
return [
|
|
80
|
+
...doc.trials.map((t, order): [string, unknown] => [trialRecord(t.id), { ...t, order }]),
|
|
81
|
+
...doc.saves.map((s): [string, unknown] => [saveRecord(s.id), s]),
|
|
82
|
+
[LAYOUT_RECORD, doc.layout],
|
|
83
|
+
[UNDOCK_RECORD, doc.undockedPanels],
|
|
84
|
+
[META_RECORD, { version: doc.version, mode: doc.mode } satisfies LabMeta],
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Records joined back into an unmigrated document, with each trial's stored
|
|
89
|
+
* order. Null when there is no `meta` record — no lab has been stored here in
|
|
90
|
+
* this form. */
|
|
91
|
+
export function documentOfRecords(
|
|
92
|
+
entries: Iterable<[string, unknown]>,
|
|
93
|
+
): { doc: Record<string, unknown>; orders: Map<string, number> } | null {
|
|
94
|
+
let meta: unknown;
|
|
95
|
+
let layout: unknown;
|
|
96
|
+
let undock: unknown;
|
|
97
|
+
const trials: { trial: SerializedTrial; order: number }[] = [];
|
|
98
|
+
const saves: SavedSnapshot[] = [];
|
|
99
|
+
|
|
100
|
+
for (const [name, value] of entries) {
|
|
101
|
+
const parsed = parseRecordName(name);
|
|
102
|
+
if (!parsed) continue;
|
|
103
|
+
switch (parsed.kind) {
|
|
104
|
+
case 'meta':
|
|
105
|
+
meta = value;
|
|
106
|
+
break;
|
|
107
|
+
case 'layout':
|
|
108
|
+
layout = value;
|
|
109
|
+
break;
|
|
110
|
+
case 'undock':
|
|
111
|
+
undock = value;
|
|
112
|
+
break;
|
|
113
|
+
case 'trial':
|
|
114
|
+
if (isObject(value)) {
|
|
115
|
+
const { order, ...rest } = value;
|
|
116
|
+
trials.push({
|
|
117
|
+
trial: { ...rest, id: parsed.id } as SerializedTrial,
|
|
118
|
+
order: typeof order === 'number' && Number.isFinite(order) ? order : Infinity,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
case 'save':
|
|
123
|
+
if (isObject(value)) saves.push({ ...value, id: parsed.id } as SavedSnapshot);
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (!isObject(meta)) return null;
|
|
128
|
+
|
|
129
|
+
trials.sort(compareTrialOrder);
|
|
130
|
+
const orders = new Map<string, number>();
|
|
131
|
+
let next = 0;
|
|
132
|
+
for (const { trial, order } of trials) {
|
|
133
|
+
const at = Number.isFinite(order) ? order : next;
|
|
134
|
+
orders.set(trial.id, at);
|
|
135
|
+
next = Math.max(next, at + 1);
|
|
136
|
+
}
|
|
137
|
+
saves.sort((a, b) => a.savedAt - b.savedAt);
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
doc: {
|
|
141
|
+
version: meta.version,
|
|
142
|
+
mode: meta.mode,
|
|
143
|
+
trials: trials.map((t) => t.trial),
|
|
144
|
+
saves,
|
|
145
|
+
layout,
|
|
146
|
+
undockedPanels: undock,
|
|
147
|
+
},
|
|
148
|
+
orders,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Stored order first; two trials added at once in two tabs can share an
|
|
153
|
+
* order, so the id breaks the tie the same way everywhere. */
|
|
154
|
+
export function compareTrialOrder(
|
|
155
|
+
a: { trial: { id: string }; order: number },
|
|
156
|
+
b: { trial: { id: string }; order: number },
|
|
157
|
+
): number {
|
|
158
|
+
if (a.order !== b.order) return a.order < b.order ? -1 : 1;
|
|
159
|
+
return a.trial.id < b.trial.id ? -1 : a.trial.id > b.trial.id ? 1 : 0;
|
|
160
|
+
}
|