@weasel-js/labkit 1.0.4 → 1.1.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 +6 -6
- package/dist/_dts/{index-CFlDPeZh.d.ts → index-iAP6XbH3.d.ts} +17 -7
- package/dist/_dts/{useExperimentState-D7EQnnwJ.d.ts → useTrialState-DYe2vUwN.d.ts} +60 -36
- package/dist/canvas/index.d.ts +1 -1
- package/dist/chunk-3TYUJR7Z.js +488 -0
- package/dist/chunk-3TYUJR7Z.js.map +1 -0
- package/dist/{chunk-BAPZPDDA.js → chunk-C6GJKPUI.js} +365 -340
- package/dist/chunk-C6GJKPUI.js.map +1 -0
- package/dist/{chunk-DWV7SFKR.js → chunk-DJLDIRFN.js} +28 -12
- package/dist/chunk-DJLDIRFN.js.map +1 -0
- package/dist/{chunk-DEWXYFEU.js → chunk-NRKWVTVT.js} +3 -3
- package/dist/{chunk-DEWXYFEU.js.map → chunk-NRKWVTVT.js.map} +1 -1
- package/dist/dragdrop/index.d.ts +1 -1
- package/dist/index.d.ts +149 -149
- package/dist/index.js +164 -159
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +2 -2
- package/dist/passthrough/weasel-canvas.js +1 -1
- package/dist/passthrough/weasel-ui.d.ts +9 -2
- package/dist/passthrough/weasel-ui.js +2 -2
- package/dist/state/index.d.ts +12 -12
- package/dist/state/index.js +5 -5
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +21 -13
- package/dist/ui/layers/index.js +3 -3
- package/dist/undo/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/canvas/AGENTS.md +6 -2
- package/src/dragdrop/dragDrop.test.tsx +4 -7
- package/src/index.test.ts +52 -0
- package/src/index.ts +11 -7
- package/src/instrument/SineWave.smoke.test.tsx +1 -1
- package/src/instrument/capabilityDetector.ts +1 -1
- package/src/instrument/types.ts +18 -6
- package/src/lab/Lab.less +16 -0
- package/src/lab/Lab.stories.tsx +5 -5
- package/src/lab/Lab.test.tsx +25 -25
- package/src/lab/Lab.tsx +50 -50
- package/src/lab/LabContext.ts +12 -12
- package/src/lab/LabShell.tsx +1 -1
- package/src/lab/{WorkspaceGrid.less → Workspace.less} +2 -2
- package/src/lab/{WorkspaceGrid.stories.tsx → Workspace.stories.tsx} +13 -13
- package/src/lab/{WorkspaceGrid.test.tsx → Workspace.test.tsx} +24 -24
- package/src/lab/{WorkspaceGrid.tsx → Workspace.tsx} +18 -18
- package/src/lab/index.ts +2 -2
- package/src/layers/AGENTS.md +3 -3
- package/src/primitives/Toolbar.stories.tsx +2 -2
- package/src/state/SingletonExperiment.test.tsx +8 -8
- package/src/state/SingletonExperiment.tsx +9 -9
- package/src/state/context.tsx +12 -12
- package/src/state/document.test.ts +369 -0
- package/src/state/document.ts +194 -0
- package/src/state/helpers.test.ts +74 -46
- package/src/state/helpers.ts +21 -29
- package/src/state/index.ts +16 -8
- package/src/state/store.test.ts +440 -41
- package/src/state/store.ts +159 -102
- package/src/state/types.ts +29 -12
- package/src/state/{useExperimentState.test.tsx → useTrialState.test.tsx} +18 -18
- package/src/state/useTrialState.ts +29 -0
- package/src/styles.less +2 -2
- package/src/theme/base.less +1 -1
- package/src/{workspace → trial}/DefaultSidebar.tsx +3 -3
- package/src/{workspace → trial}/DefaultStatusBar.tsx +5 -4
- package/src/{workspace → trial}/DefaultToolbar.tsx +9 -8
- package/src/trial/Trial.canvas.test.tsx +80 -0
- package/src/{workspace/Workspace.less → trial/Trial.less} +1 -1
- package/src/{workspace/Workspace.stories.tsx → trial/Trial.stories.tsx} +13 -18
- package/src/{workspace/Workspace.test.tsx → trial/Trial.test.tsx} +26 -26
- package/src/{workspace/Workspace.tsx → trial/Trial.tsx} +48 -43
- package/src/{workspace/WorkspaceChrome.tsx → trial/TrialChrome.tsx} +42 -42
- package/src/{workspace → trial}/index.ts +13 -13
- package/src/{workspace → trial}/slotTypes.ts +16 -16
- package/src/{workspace/workspaceOps.test.ts → trial/trialOps.test.ts} +38 -44
- package/src/trial/trialOps.ts +99 -0
- package/src/ui/format.test.ts +33 -0
- package/src/ui/format.ts +11 -0
- package/src/ui/properties/CurveField.tsx +6 -6
- package/src/ui/properties/SpeechBalloonPanels.stories.tsx +3 -3
- package/dist/chunk-BAPZPDDA.js.map +0 -1
- package/dist/chunk-DWV7SFKR.js.map +0 -1
- package/dist/chunk-KSTEW2AF.js +0 -367
- package/dist/chunk-KSTEW2AF.js.map +0 -1
- package/src/state/useExperimentState.ts +0 -31
- package/src/workspace/workspaceOps.ts +0 -102
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { LayerStack } from './chunk-
|
|
2
|
-
import { p, F } from './chunk-
|
|
3
|
-
import './chunk-
|
|
1
|
+
export { LayerStack } from './chunk-NRKWVTVT.js';
|
|
2
|
+
import { p, F } from './chunk-C6GJKPUI.js';
|
|
3
|
+
import './chunk-DJLDIRFN.js';
|
|
4
4
|
import { Sidebar, StatusBar, Toolbar } from './chunk-PMAU3SEE.js';
|
|
5
5
|
export { FpsMeter, ScaleIndicator, Sidebar, StatusBar, Toolbar } from './chunk-PMAU3SEE.js';
|
|
6
|
-
import { LabStoreContext, createLabStore, noneAdapter } from './chunk-
|
|
7
|
-
export { LabStoreContext, LabStoreProvider,
|
|
6
|
+
import { LabStoreContext, createLabStore, noneAdapter } from './chunk-3TYUJR7Z.js';
|
|
7
|
+
export { CURRENT_DOCUMENT_VERSION, LabStoreContext, LabStoreProvider, TrialIdContext, TrialIdProvider, createMemoryAdapter, labDocumentKey, localStorageAdapter, noneAdapter, quarantineKey, sessionStorageAdapter, urlHashAdapter, useLabStore, useTrialId, useTrialState } from './chunk-3TYUJR7Z.js';
|
|
8
8
|
import { ControlPanel } from './chunk-5R2ATYPJ.js';
|
|
9
9
|
export { ControlPanel } from './chunk-5R2ATYPJ.js';
|
|
10
10
|
import { CanvasStack, screenToWorld } from './chunk-574LJAV4.js';
|
|
@@ -90,7 +90,7 @@ function validateConfigSchema(fields) {
|
|
|
90
90
|
return { valid: errors.length === 0, errors };
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
// ../theme/dist/chunk-
|
|
93
|
+
// ../theme/dist/chunk-E3FOFGMD.js
|
|
94
94
|
var THEME_SOURCES = {
|
|
95
95
|
"weasel": {
|
|
96
96
|
"primitives": {
|
|
@@ -630,19 +630,20 @@ function resolveTheme(theme, mode) {
|
|
|
630
630
|
return out;
|
|
631
631
|
}
|
|
632
632
|
var STYLE_ID = "wzl-themes";
|
|
633
|
-
var emitted = /* @__PURE__ */ new
|
|
633
|
+
var emitted = /* @__PURE__ */ new Map();
|
|
634
634
|
var sheet = null;
|
|
635
635
|
var styleEl = null;
|
|
636
636
|
function canAdopt() {
|
|
637
637
|
return typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype && Array.isArray(document.adoptedStyleSheets);
|
|
638
638
|
}
|
|
639
|
-
function
|
|
639
|
+
function flushRules() {
|
|
640
|
+
const css = [...emitted.values()].join("\n");
|
|
640
641
|
if (canAdopt()) {
|
|
641
642
|
if (!sheet) {
|
|
642
643
|
sheet = new CSSStyleSheet();
|
|
643
644
|
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
|
|
644
645
|
}
|
|
645
|
-
sheet.
|
|
646
|
+
sheet.replaceSync(css);
|
|
646
647
|
return;
|
|
647
648
|
}
|
|
648
649
|
if (!styleEl) {
|
|
@@ -650,17 +651,17 @@ function appendRule(css) {
|
|
|
650
651
|
styleEl.id = STYLE_ID;
|
|
651
652
|
document.head.appendChild(styleEl);
|
|
652
653
|
}
|
|
653
|
-
styleEl.textContent
|
|
654
|
-
`;
|
|
654
|
+
styleEl.textContent = css;
|
|
655
655
|
}
|
|
656
656
|
function applyTheme(el, theme, mode) {
|
|
657
657
|
if (typeof document === "undefined") return;
|
|
658
658
|
const key = `${theme.name}::${mode}`;
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
emitted.
|
|
659
|
+
const resolved = resolveTheme(theme, mode);
|
|
660
|
+
const body = Object.entries(resolved).map(([name, value]) => `${name}: ${value};`).join(" ");
|
|
661
|
+
const rule = `[data-wzl-theme='${theme.name}'][data-wzl-mode='${mode}'] { ${body} }`;
|
|
662
|
+
if (emitted.get(key) !== rule) {
|
|
663
|
+
emitted.set(key, rule);
|
|
664
|
+
flushRules();
|
|
664
665
|
}
|
|
665
666
|
el.setAttribute("data-wzl-theme", theme.name);
|
|
666
667
|
el.setAttribute("data-wzl-mode", mode);
|
|
@@ -949,13 +950,27 @@ function DefaultSidebar({ ctx }) {
|
|
|
949
950
|
}
|
|
950
951
|
) });
|
|
951
952
|
}
|
|
953
|
+
|
|
954
|
+
// src/ui/format.ts
|
|
955
|
+
var MINUS = "\u2212";
|
|
956
|
+
function formatNumber(n, fractionDigits) {
|
|
957
|
+
if (!Number.isFinite(n)) return String(n);
|
|
958
|
+
const s = fractionDigits == null ? String(n) : n.toFixed(fractionDigits);
|
|
959
|
+
return s.startsWith("-") ? MINUS + s.slice(1) : s;
|
|
960
|
+
}
|
|
961
|
+
function parseSignedNumber(s) {
|
|
962
|
+
return Number(s.replace(MINUS, "-"));
|
|
963
|
+
}
|
|
964
|
+
function formatZoom(zoom) {
|
|
965
|
+
if (!Number.isFinite(zoom)) return String(zoom);
|
|
966
|
+
if (zoom <= 2) return `${formatNumber(Math.round(zoom * 100))}%`;
|
|
967
|
+
if (zoom >= 100) return `${Math.round(zoom).toLocaleString("en-US")}x`;
|
|
968
|
+
return `${formatNumber(Math.round(zoom * 10) / 10)}x`;
|
|
969
|
+
}
|
|
952
970
|
function DefaultStatusBar({ ctx }) {
|
|
953
971
|
return /* @__PURE__ */ jsxs(StatusBar, { children: [
|
|
954
972
|
/* @__PURE__ */ jsx(StatusBar.Section, { children: ctx.instrumentName }),
|
|
955
|
-
/* @__PURE__ */
|
|
956
|
-
Math.round(ctx.zoom * 100),
|
|
957
|
-
"%"
|
|
958
|
-
] })
|
|
973
|
+
/* @__PURE__ */ jsx(StatusBar.Section, { children: formatZoom(ctx.zoom) })
|
|
959
974
|
] });
|
|
960
975
|
}
|
|
961
976
|
function DefaultToolbar({ ctx }) {
|
|
@@ -975,10 +990,7 @@ function DefaultToolbar({ ctx }) {
|
|
|
975
990
|
] }),
|
|
976
991
|
ctx.hasCanvas && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
977
992
|
/* @__PURE__ */ jsx(Toolbar.Button, { onClick: ctx.zoomOut, title: "Zoom out", children: "\u2212" }),
|
|
978
|
-
/* @__PURE__ */
|
|
979
|
-
Math.round(ctx.zoom * 100),
|
|
980
|
-
"%"
|
|
981
|
-
] }),
|
|
993
|
+
/* @__PURE__ */ jsx("span", { className: "lk-toolbar__zoom-label", children: formatZoom(ctx.zoom) }),
|
|
982
994
|
/* @__PURE__ */ jsx(Toolbar.Button, { onClick: ctx.zoomIn, title: "Zoom in", children: "+" }),
|
|
983
995
|
/* @__PURE__ */ jsx(Toolbar.Button, { onClick: ctx.resetZoom, title: "Reset zoom", children: "1:1" }),
|
|
984
996
|
/* @__PURE__ */ jsx(Toolbar.Spacer, {})
|
|
@@ -1004,24 +1016,24 @@ function DefaultToolbar({ ctx }) {
|
|
|
1004
1016
|
}
|
|
1005
1017
|
),
|
|
1006
1018
|
/* @__PURE__ */ jsx(Toolbar.Spacer, {}),
|
|
1007
|
-
/* @__PURE__ */ jsx(Toolbar.Button, { onClick: ctx.clone, title: "Clone
|
|
1008
|
-
/* @__PURE__ */ jsx(Toolbar.Button, { onClick: ctx.reset, title: "Reset
|
|
1019
|
+
/* @__PURE__ */ jsx(Toolbar.Button, { onClick: ctx.clone, title: "Clone trial", children: "Clone" }),
|
|
1020
|
+
/* @__PURE__ */ jsx(Toolbar.Button, { onClick: ctx.reset, title: "Reset trial", children: "Reset" }),
|
|
1009
1021
|
/* @__PURE__ */ jsx(
|
|
1010
1022
|
Toolbar.Button,
|
|
1011
1023
|
{
|
|
1012
1024
|
onClick: ctx.close,
|
|
1013
|
-
disabled: ctx.
|
|
1014
|
-
title: ctx.
|
|
1025
|
+
disabled: ctx.isLastTrial,
|
|
1026
|
+
title: ctx.isLastTrial ? "Cannot close the last trial" : "Close trial",
|
|
1015
1027
|
children: "Close"
|
|
1016
1028
|
}
|
|
1017
1029
|
)
|
|
1018
1030
|
] });
|
|
1019
1031
|
}
|
|
1020
|
-
function
|
|
1021
|
-
|
|
1032
|
+
function TrialChrome({
|
|
1033
|
+
trialId,
|
|
1022
1034
|
record,
|
|
1023
1035
|
instrument,
|
|
1024
|
-
|
|
1036
|
+
isLastTrial,
|
|
1025
1037
|
toolbar,
|
|
1026
1038
|
sidebar,
|
|
1027
1039
|
statusBar,
|
|
@@ -1031,16 +1043,16 @@ function WorkspaceChrome({
|
|
|
1031
1043
|
}) {
|
|
1032
1044
|
const lab = useLabContext();
|
|
1033
1045
|
const storeCtx = useContext(LabStoreContext);
|
|
1034
|
-
if (!storeCtx) throw new Error("[labkit]
|
|
1035
|
-
const
|
|
1036
|
-
const
|
|
1037
|
-
const
|
|
1046
|
+
if (!storeCtx) throw new Error("[labkit] TrialChrome requires <LabStoreProvider>");
|
|
1047
|
+
const updateTrialView = useStore(storeCtx.store, (s) => s.updateTrialView);
|
|
1048
|
+
const updateTrialConfig = useStore(storeCtx.store, (s) => s.updateTrialConfig);
|
|
1049
|
+
const updateTrialState = useStore(storeCtx.store, (s) => s.updateTrialState);
|
|
1038
1050
|
const toolbarCtx = useMemo(() => {
|
|
1039
1051
|
const setZoom = (z) => {
|
|
1040
|
-
|
|
1052
|
+
updateTrialView(trialId, { ...record.view, zoom: z });
|
|
1041
1053
|
};
|
|
1042
1054
|
return {
|
|
1043
|
-
|
|
1055
|
+
trialId,
|
|
1044
1056
|
instrumentName: record.instrumentName,
|
|
1045
1057
|
hasUndo: instrument.undo != null,
|
|
1046
1058
|
canUndo: undoBindings?.canUndo ?? false,
|
|
@@ -1055,18 +1067,18 @@ function WorkspaceChrome({
|
|
|
1055
1067
|
zoomOut: () => setZoom(record.view.zoom * 0.8),
|
|
1056
1068
|
resetZoom: () => setZoom(1),
|
|
1057
1069
|
hasCanvas: instrument.canvas != null,
|
|
1058
|
-
savedSnapshots: lab.savedSnapshots.filter((s) => s.
|
|
1059
|
-
saveSnapshot: (name) => lab.saveSnapshot(
|
|
1060
|
-
loadSnapshot: (snapshotId) => lab.loadSnapshot(
|
|
1061
|
-
clone: () => lab.
|
|
1062
|
-
reset: () => lab.
|
|
1063
|
-
close: () => lab.
|
|
1064
|
-
|
|
1070
|
+
savedSnapshots: lab.savedSnapshots.filter((s) => s.trialId === trialId),
|
|
1071
|
+
saveSnapshot: (name) => lab.saveSnapshot(trialId, name),
|
|
1072
|
+
loadSnapshot: (snapshotId) => lab.loadSnapshot(trialId, snapshotId),
|
|
1073
|
+
clone: () => lab.cloneTrial(trialId),
|
|
1074
|
+
reset: () => lab.resetTrial(trialId),
|
|
1075
|
+
close: () => lab.closeTrial(trialId),
|
|
1076
|
+
isLastTrial
|
|
1065
1077
|
};
|
|
1066
|
-
}, [
|
|
1078
|
+
}, [trialId, record, instrument, lab, isLastTrial, updateTrialView, undoBindings]);
|
|
1067
1079
|
const sidebarCtx = useMemo(
|
|
1068
1080
|
() => ({
|
|
1069
|
-
|
|
1081
|
+
trialId,
|
|
1070
1082
|
instrumentName: record.instrumentName,
|
|
1071
1083
|
configFields: instrument.configSchema?.() ?? [],
|
|
1072
1084
|
config: record.config,
|
|
@@ -1077,18 +1089,18 @@ function WorkspaceChrome({
|
|
|
1077
1089
|
`[labkit] setConfig: unknown key "${key}" for instrument "${record.instrumentName}"`
|
|
1078
1090
|
);
|
|
1079
1091
|
}
|
|
1080
|
-
|
|
1092
|
+
updateTrialConfig(trialId, key, value);
|
|
1081
1093
|
if (instrument.onConfigChange) {
|
|
1082
1094
|
const nextConfig = { ...prevConfig, [key]: value };
|
|
1083
1095
|
const nextState = instrument.onConfigChange(nextConfig, prevConfig, record.state);
|
|
1084
|
-
|
|
1096
|
+
updateTrialState(trialId, nextState);
|
|
1085
1097
|
}
|
|
1086
1098
|
}
|
|
1087
1099
|
}),
|
|
1088
|
-
[
|
|
1100
|
+
[trialId, record, instrument, updateTrialConfig, updateTrialState]
|
|
1089
1101
|
);
|
|
1090
1102
|
const statusCtx = {
|
|
1091
|
-
|
|
1103
|
+
trialId,
|
|
1092
1104
|
instrumentName: record.instrumentName,
|
|
1093
1105
|
zoom: record.view.zoom
|
|
1094
1106
|
};
|
|
@@ -1107,57 +1119,57 @@ function WorkspaceChrome({
|
|
|
1107
1119
|
return /* @__PURE__ */ jsxs(
|
|
1108
1120
|
"section",
|
|
1109
1121
|
{
|
|
1110
|
-
className: "lk-
|
|
1111
|
-
"aria-label": `
|
|
1122
|
+
className: "lk-trial",
|
|
1123
|
+
"aria-label": `Trial ${record.instrumentName}`,
|
|
1112
1124
|
onKeyDown: handleKeyDown,
|
|
1113
1125
|
children: [
|
|
1114
|
-
/* @__PURE__ */ jsx("div", { className: "lk-
|
|
1115
|
-
/* @__PURE__ */ jsxs("div", { className: "lk-
|
|
1116
|
-
/* @__PURE__ */ jsxs("div", { className: "lk-
|
|
1126
|
+
/* @__PURE__ */ jsx("div", { className: "lk-trial__toolbar", children: toolbar ? toolbar(toolbarCtx) : /* @__PURE__ */ jsx(DefaultToolbar, { ctx: toolbarCtx }) }),
|
|
1127
|
+
/* @__PURE__ */ jsxs("div", { className: "lk-trial__body", children: [
|
|
1128
|
+
/* @__PURE__ */ jsxs("div", { className: "lk-trial__sidebar", children: [
|
|
1117
1129
|
sidebar ? sidebar(sidebarCtx) : /* @__PURE__ */ jsx(DefaultSidebar, { ctx: sidebarCtx }),
|
|
1118
1130
|
sidebarExtras
|
|
1119
1131
|
] }),
|
|
1120
|
-
/* @__PURE__ */ jsx("div", { className: "lk-
|
|
1132
|
+
/* @__PURE__ */ jsx("div", { className: "lk-trial__content", children })
|
|
1121
1133
|
] }),
|
|
1122
|
-
/* @__PURE__ */ jsx("div", { className: "lk-
|
|
1134
|
+
/* @__PURE__ */ jsx("div", { className: "lk-trial__status", children: statusBar ? statusBar(statusCtx) : /* @__PURE__ */ jsx(DefaultStatusBar, { ctx: statusCtx }) })
|
|
1123
1135
|
]
|
|
1124
1136
|
}
|
|
1125
1137
|
);
|
|
1126
1138
|
}
|
|
1127
|
-
function
|
|
1139
|
+
function Trial({ id }) {
|
|
1128
1140
|
const lab = useLabContext();
|
|
1129
1141
|
const storeCtx = useContext(LabStoreContext);
|
|
1130
|
-
if (!storeCtx) throw new Error("[labkit] <
|
|
1131
|
-
const record = useStore(storeCtx.store, (s) => s.
|
|
1142
|
+
if (!storeCtx) throw new Error("[labkit] <Trial> requires <LabStoreProvider>");
|
|
1143
|
+
const record = useStore(storeCtx.store, (s) => s.trials.find((w) => w.id === id));
|
|
1132
1144
|
if (!record) {
|
|
1133
|
-
return /* @__PURE__ */ jsxs("div", { className: "lk-
|
|
1134
|
-
"
|
|
1145
|
+
return /* @__PURE__ */ jsxs("div", { className: "lk-trial lk-trial--unknown", children: [
|
|
1146
|
+
"Trial not found: ",
|
|
1135
1147
|
id
|
|
1136
1148
|
] });
|
|
1137
1149
|
}
|
|
1138
1150
|
const instrument = lab.instruments.find((i) => i.name === record.instrumentName);
|
|
1139
1151
|
if (!instrument) {
|
|
1140
|
-
return /* @__PURE__ */ jsxs("div", { className: "lk-
|
|
1152
|
+
return /* @__PURE__ */ jsxs("div", { className: "lk-trial lk-trial--unknown", children: [
|
|
1141
1153
|
"Unknown instrument: ",
|
|
1142
1154
|
record.instrumentName
|
|
1143
1155
|
] });
|
|
1144
1156
|
}
|
|
1145
1157
|
return /* @__PURE__ */ jsx(
|
|
1146
|
-
|
|
1158
|
+
TrialRuntime,
|
|
1147
1159
|
{
|
|
1148
1160
|
record,
|
|
1149
1161
|
instrument,
|
|
1150
1162
|
store: storeCtx.store,
|
|
1151
|
-
isLast: lab.
|
|
1163
|
+
isLast: lab.trials.length <= 1
|
|
1152
1164
|
}
|
|
1153
1165
|
);
|
|
1154
1166
|
}
|
|
1155
|
-
function
|
|
1167
|
+
function TrialRuntime({ record, instrument, store, isLast }) {
|
|
1156
1168
|
const canvasContainerRef = useRef(null);
|
|
1157
|
-
const
|
|
1158
|
-
const
|
|
1159
|
-
const
|
|
1160
|
-
const
|
|
1169
|
+
const updateTrialState = useStore(store, (s) => s.updateTrialState);
|
|
1170
|
+
const updateTrialConfig = useStore(store, (s) => s.updateTrialConfig);
|
|
1171
|
+
const updateTrialView = useStore(store, (s) => s.updateTrialView);
|
|
1172
|
+
const updateTrialUndoStack = useStore(store, (s) => s.updateTrialUndoStack);
|
|
1161
1173
|
const busRef = useRef(null);
|
|
1162
1174
|
if (busRef.current === null) busRef.current = createEventBus();
|
|
1163
1175
|
const bus = busRef.current;
|
|
@@ -1168,32 +1180,32 @@ function WorkspaceRuntime({ record, instrument, store, isLast }) {
|
|
|
1168
1180
|
const maxDepth = undoCap?.maxDepth ?? 50;
|
|
1169
1181
|
const snapshotIfNeeded = (event) => {
|
|
1170
1182
|
if (!undoCap || !undoEvents.has(event)) return;
|
|
1171
|
-
const current = store.getState().
|
|
1183
|
+
const current = store.getState().trials.find((w) => w.id === record.id);
|
|
1172
1184
|
if (!current) return;
|
|
1173
1185
|
const snap = structuredClone(current.state);
|
|
1174
|
-
|
|
1186
|
+
updateTrialUndoStack(record.id, (prev) => pushSnapshot(prev, snap, maxDepth));
|
|
1175
1187
|
};
|
|
1176
|
-
const setView = (v) =>
|
|
1188
|
+
const setView = (v) => updateTrialView(record.id, v);
|
|
1177
1189
|
const renderCtx = {
|
|
1178
1190
|
state: record.state,
|
|
1179
1191
|
config: record.config,
|
|
1180
1192
|
setState: (next) => {
|
|
1181
1193
|
snapshotIfNeeded("state.change");
|
|
1182
|
-
|
|
1194
|
+
updateTrialState(record.id, next);
|
|
1183
1195
|
bus.emit("state.change");
|
|
1184
1196
|
},
|
|
1185
1197
|
setConfig: (key, value) => {
|
|
1186
1198
|
const evt = `config.change:${String(key)}`;
|
|
1187
1199
|
snapshotIfNeeded("config.change");
|
|
1188
1200
|
snapshotIfNeeded(evt);
|
|
1189
|
-
|
|
1201
|
+
updateTrialConfig(record.id, key, value);
|
|
1190
1202
|
bus.emit("config.change");
|
|
1191
1203
|
bus.emit(evt);
|
|
1192
1204
|
},
|
|
1193
|
-
|
|
1205
|
+
trial: {
|
|
1194
1206
|
id: record.id,
|
|
1195
1207
|
zoom: record.view.zoom,
|
|
1196
|
-
setZoom: (z) =>
|
|
1208
|
+
setZoom: (z) => updateTrialView(record.id, { ...record.view, zoom: z })
|
|
1197
1209
|
},
|
|
1198
1210
|
emit: (event) => {
|
|
1199
1211
|
snapshotIfNeeded(event);
|
|
@@ -1206,14 +1218,14 @@ function WorkspaceRuntime({ record, instrument, store, isLast }) {
|
|
|
1206
1218
|
undo: () => {
|
|
1207
1219
|
const result = undo(record.undoStack, structuredClone(record.state));
|
|
1208
1220
|
if (!result) return;
|
|
1209
|
-
|
|
1210
|
-
|
|
1221
|
+
updateTrialState(record.id, result.snapshot);
|
|
1222
|
+
updateTrialUndoStack(record.id, result.stack);
|
|
1211
1223
|
},
|
|
1212
1224
|
redo: () => {
|
|
1213
1225
|
const result = redo(record.undoStack, structuredClone(record.state));
|
|
1214
1226
|
if (!result) return;
|
|
1215
|
-
|
|
1216
|
-
|
|
1227
|
+
updateTrialState(record.id, result.snapshot);
|
|
1228
|
+
updateTrialUndoStack(record.id, result.stack);
|
|
1217
1229
|
}
|
|
1218
1230
|
} : void 0;
|
|
1219
1231
|
const canvasLayers = useMemo(() => {
|
|
@@ -1223,7 +1235,11 @@ function WorkspaceRuntime({ record, instrument, store, isLast }) {
|
|
|
1223
1235
|
return ordered.map((layer) => ({
|
|
1224
1236
|
id: layer.id,
|
|
1225
1237
|
visible: layerVisibility[layer.id] !== false,
|
|
1226
|
-
render: (ctx, view) =>
|
|
1238
|
+
render: (ctx, view) => {
|
|
1239
|
+
ctx.translate(view.pan.x, view.pan.y);
|
|
1240
|
+
ctx.scale(view.zoom, view.zoom);
|
|
1241
|
+
layer.draw(ctx, { state: record.state, config: record.config, zoom: view.zoom });
|
|
1242
|
+
}
|
|
1227
1243
|
}));
|
|
1228
1244
|
}, [instrument.canvas, record.state, record.config, layerVisibility, layerOrder]);
|
|
1229
1245
|
const layerDescriptors = useMemo(() => {
|
|
@@ -1238,7 +1254,7 @@ function WorkspaceRuntime({ record, instrument, store, isLast }) {
|
|
|
1238
1254
|
config: record.config,
|
|
1239
1255
|
setState: (next) => {
|
|
1240
1256
|
snapshotIfNeeded("canvas.itemAdded");
|
|
1241
|
-
|
|
1257
|
+
updateTrialState(record.id, next);
|
|
1242
1258
|
},
|
|
1243
1259
|
emit: (evt) => {
|
|
1244
1260
|
snapshotIfNeeded(evt);
|
|
@@ -1280,10 +1296,10 @@ function WorkspaceRuntime({ record, instrument, store, isLast }) {
|
|
|
1280
1296
|
"div",
|
|
1281
1297
|
{
|
|
1282
1298
|
ref: canvasContainerRef,
|
|
1283
|
-
className: "lk-
|
|
1299
|
+
className: "lk-trial__canvas-host",
|
|
1284
1300
|
style: { width: "100%", height: "100%", position: "relative" },
|
|
1285
1301
|
children: [
|
|
1286
|
-
/* @__PURE__ */ jsx(CanvasStack, { layers: layersWithFeedback, view: record.view, onViewChange: setView }),
|
|
1302
|
+
/* @__PURE__ */ jsx(CanvasStack, { layers: layersWithFeedback, view: record.view, onViewChange: setView, children: instrument.render(renderCtx) }),
|
|
1287
1303
|
/* @__PURE__ */ jsx(DragOverlay, { drag: dragDropResult.drag })
|
|
1288
1304
|
]
|
|
1289
1305
|
}
|
|
@@ -1308,12 +1324,12 @@ function WorkspaceRuntime({ record, instrument, store, isLast }) {
|
|
|
1308
1324
|
}
|
|
1309
1325
|
) : null;
|
|
1310
1326
|
return /* @__PURE__ */ jsx(
|
|
1311
|
-
|
|
1327
|
+
TrialChrome,
|
|
1312
1328
|
{
|
|
1313
|
-
|
|
1329
|
+
trialId: record.id,
|
|
1314
1330
|
record,
|
|
1315
1331
|
instrument,
|
|
1316
|
-
|
|
1332
|
+
isLastTrial: isLast,
|
|
1317
1333
|
undoBindings,
|
|
1318
1334
|
sidebarExtras: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1319
1335
|
paletteNode,
|
|
@@ -1324,7 +1340,7 @@ function WorkspaceRuntime({ record, instrument, store, isLast }) {
|
|
|
1324
1340
|
);
|
|
1325
1341
|
}
|
|
1326
1342
|
|
|
1327
|
-
// src/
|
|
1343
|
+
// src/trial/trialOps.ts
|
|
1328
1344
|
var DEFAULT_VIEW = { zoom: 1, pan: { x: 0, y: 0 } };
|
|
1329
1345
|
function findInstrument(instruments, name) {
|
|
1330
1346
|
const found = instruments.find((i) => i.name === name);
|
|
@@ -1336,7 +1352,7 @@ function findInstrument(instruments, name) {
|
|
|
1336
1352
|
function initialView(instrument) {
|
|
1337
1353
|
return instrument.canvas?.initialView ? structuredClone(instrument.canvas.initialView) : { ...DEFAULT_VIEW, pan: { ...DEFAULT_VIEW.pan } };
|
|
1338
1354
|
}
|
|
1339
|
-
function
|
|
1355
|
+
function addTrial(trials, instruments, instrumentName) {
|
|
1340
1356
|
const instrument = findInstrument(instruments, instrumentName);
|
|
1341
1357
|
const config = instrument.defaultConfig();
|
|
1342
1358
|
const state = instrument.initialState(config);
|
|
@@ -1348,12 +1364,12 @@ function addWorkspace(workspaces, instruments, instrumentName) {
|
|
|
1348
1364
|
view: initialView(instrument),
|
|
1349
1365
|
undoStack: { past: [], future: [] }
|
|
1350
1366
|
};
|
|
1351
|
-
return [...
|
|
1367
|
+
return [...trials, record];
|
|
1352
1368
|
}
|
|
1353
|
-
function
|
|
1354
|
-
const sourceIdx =
|
|
1355
|
-
const source =
|
|
1356
|
-
if (!source) return
|
|
1369
|
+
function cloneTrial(trials, id) {
|
|
1370
|
+
const sourceIdx = trials.findIndex((w) => w.id === id);
|
|
1371
|
+
const source = trials[sourceIdx];
|
|
1372
|
+
if (!source) return trials;
|
|
1357
1373
|
const clone = {
|
|
1358
1374
|
...source,
|
|
1359
1375
|
id: crypto.randomUUID(),
|
|
@@ -1362,17 +1378,17 @@ function cloneWorkspace(workspaces, id) {
|
|
|
1362
1378
|
view: structuredClone(source.view),
|
|
1363
1379
|
undoStack: { past: [], future: [] }
|
|
1364
1380
|
};
|
|
1365
|
-
return [...
|
|
1381
|
+
return [...trials.slice(0, sourceIdx + 1), clone, ...trials.slice(sourceIdx + 1)];
|
|
1366
1382
|
}
|
|
1367
|
-
function
|
|
1368
|
-
if (
|
|
1369
|
-
const next =
|
|
1370
|
-
return next.length ===
|
|
1383
|
+
function closeTrial(trials, id) {
|
|
1384
|
+
if (trials.length <= 1) return trials;
|
|
1385
|
+
const next = trials.filter((w) => w.id !== id);
|
|
1386
|
+
return next.length === trials.length ? trials : next;
|
|
1371
1387
|
}
|
|
1372
|
-
function
|
|
1373
|
-
const idx =
|
|
1374
|
-
const current =
|
|
1375
|
-
if (!current) return
|
|
1388
|
+
function resetTrial(trials, id, instruments) {
|
|
1389
|
+
const idx = trials.findIndex((w) => w.id === id);
|
|
1390
|
+
const current = trials[idx];
|
|
1391
|
+
if (!current) return trials;
|
|
1376
1392
|
const instrument = findInstrument(instruments, current.instrumentName);
|
|
1377
1393
|
const config = instrument.defaultConfig();
|
|
1378
1394
|
const state = instrument.initialState(config);
|
|
@@ -1382,13 +1398,13 @@ function resetWorkspace(workspaces, id, instruments) {
|
|
|
1382
1398
|
state,
|
|
1383
1399
|
view: initialView(instrument)
|
|
1384
1400
|
};
|
|
1385
|
-
return [...
|
|
1401
|
+
return [...trials.slice(0, idx), reset, ...trials.slice(idx + 1)];
|
|
1386
1402
|
}
|
|
1387
|
-
function
|
|
1388
|
-
const byId = new Map(
|
|
1403
|
+
function reorderTrials(trials, ids) {
|
|
1404
|
+
const byId = new Map(trials.map((w) => [w.id, w]));
|
|
1389
1405
|
const named = ids.map((id) => byId.get(id)).filter((w) => w !== void 0);
|
|
1390
1406
|
const seen = new Set(named.map((w) => w.id));
|
|
1391
|
-
const rest =
|
|
1407
|
+
const rest = trials.filter((w) => !seen.has(w.id));
|
|
1392
1408
|
return [...named, ...rest];
|
|
1393
1409
|
}
|
|
1394
1410
|
function query() {
|
|
@@ -1422,9 +1438,9 @@ function LabShell({ title, children, header, footer, mode = "auto" }) {
|
|
|
1422
1438
|
] });
|
|
1423
1439
|
return outer ? shell : /* @__PURE__ */ jsx(ThemeProvider, { theme: interstellarTheme, mode: resolved, children: shell });
|
|
1424
1440
|
}
|
|
1425
|
-
var ZONE_ID = asNodeId("lk-
|
|
1441
|
+
var ZONE_ID = asNodeId("lk-workspace");
|
|
1426
1442
|
var STRATEGIES = { grid: gridStrategy };
|
|
1427
|
-
var KIND = "
|
|
1443
|
+
var KIND = "trial";
|
|
1428
1444
|
function extentOf(store, id) {
|
|
1429
1445
|
const p2 = store.getNode(id)?.membership?.placement;
|
|
1430
1446
|
if (!p2) return null;
|
|
@@ -1433,7 +1449,7 @@ function extentOf(store, id) {
|
|
|
1433
1449
|
if (p2.span) out.span = p2.span;
|
|
1434
1450
|
return Object.keys(out).length > 0 ? out : null;
|
|
1435
1451
|
}
|
|
1436
|
-
function
|
|
1452
|
+
function Workspace({
|
|
1437
1453
|
children,
|
|
1438
1454
|
ids,
|
|
1439
1455
|
resizable = false,
|
|
@@ -1504,9 +1520,9 @@ function WorkspaceGrid({
|
|
|
1504
1520
|
[KIND]: ({ node }) => {
|
|
1505
1521
|
const content = byId.get(node.id) ?? null;
|
|
1506
1522
|
if (!reorderable) return content;
|
|
1507
|
-
return /* @__PURE__ */ jsxs("div", { className: "lk-
|
|
1508
|
-
/* @__PURE__ */ jsx(DragHandle, { nodeId: node.id, className: "lk-
|
|
1509
|
-
/* @__PURE__ */ jsx("div", { className: "lk-
|
|
1523
|
+
return /* @__PURE__ */ jsxs("div", { className: "lk-trial-tile", children: [
|
|
1524
|
+
/* @__PURE__ */ jsx(DragHandle, { nodeId: node.id, className: "lk-trial-tile__grip", children: /* @__PURE__ */ jsx("span", { className: "lk-trial-tile__grip-dots", "aria-hidden": "true" }) }),
|
|
1525
|
+
/* @__PURE__ */ jsx("div", { className: "lk-trial-tile__body", children: content })
|
|
1510
1526
|
] });
|
|
1511
1527
|
}
|
|
1512
1528
|
};
|
|
@@ -1516,7 +1532,7 @@ function WorkspaceGrid({
|
|
|
1516
1532
|
{
|
|
1517
1533
|
parentId: ZONE_ID,
|
|
1518
1534
|
chrome,
|
|
1519
|
-
className: "lk-workspace
|
|
1535
|
+
className: "lk-workspace windease-zone",
|
|
1520
1536
|
affordances: resizable,
|
|
1521
1537
|
viewport,
|
|
1522
1538
|
onChildOrderChange: reorderable ? commitOrder : void 0
|
|
@@ -1526,12 +1542,12 @@ function WorkspaceGrid({
|
|
|
1526
1542
|
}
|
|
1527
1543
|
function buildStore(instruments, defaultInstrument, storage, storageKey, initialMode) {
|
|
1528
1544
|
const store = createLabStore({ storageKey, storage, initialMode });
|
|
1529
|
-
if (store.getState().
|
|
1530
|
-
const seeded =
|
|
1545
|
+
if (store.getState().trials.length === 0) {
|
|
1546
|
+
const seeded = addTrial([], instruments, defaultInstrument);
|
|
1531
1547
|
const record = seeded[0];
|
|
1532
1548
|
if (record) {
|
|
1533
1549
|
const { undoStack: _undoStack, ...rest } = record;
|
|
1534
|
-
store.getState().
|
|
1550
|
+
store.getState().addTrial(rest);
|
|
1535
1551
|
}
|
|
1536
1552
|
}
|
|
1537
1553
|
return store;
|
|
@@ -1575,7 +1591,7 @@ function Lab({
|
|
|
1575
1591
|
);
|
|
1576
1592
|
}
|
|
1577
1593
|
const store = storeRef.current;
|
|
1578
|
-
const
|
|
1594
|
+
const trials = useStore(store, (s) => s.trials);
|
|
1579
1595
|
const savedSnapshots = useStore(store, (s) => s.savedSnapshots);
|
|
1580
1596
|
const modeValue = useStore(store, (s) => s.mode);
|
|
1581
1597
|
const layout = useStore(store, (s) => s.layout);
|
|
@@ -1586,47 +1602,47 @@ function Lab({
|
|
|
1586
1602
|
}
|
|
1587
1603
|
}, [mode, store]);
|
|
1588
1604
|
const contextValue = useMemo(() => {
|
|
1589
|
-
const
|
|
1590
|
-
const currentById = new Map(store.getState().
|
|
1605
|
+
const replaceTrials = (next) => {
|
|
1606
|
+
const currentById = new Map(store.getState().trials.map((w) => [w.id, w]));
|
|
1591
1607
|
const merged = next.map((w) => currentById.get(w.id) ?? w);
|
|
1592
|
-
store.setState({
|
|
1608
|
+
store.setState({ trials: merged });
|
|
1593
1609
|
store.getState().setMode(store.getState().mode);
|
|
1594
1610
|
};
|
|
1595
1611
|
return {
|
|
1596
1612
|
instruments,
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
const next =
|
|
1600
|
-
|
|
1613
|
+
trials,
|
|
1614
|
+
addTrial: (instrumentName) => {
|
|
1615
|
+
const next = addTrial(store.getState().trials, instruments, instrumentName);
|
|
1616
|
+
replaceTrials(next);
|
|
1601
1617
|
},
|
|
1602
|
-
|
|
1603
|
-
const next =
|
|
1604
|
-
|
|
1618
|
+
cloneTrial: (id) => {
|
|
1619
|
+
const next = cloneTrial(store.getState().trials, id);
|
|
1620
|
+
replaceTrials(next);
|
|
1605
1621
|
},
|
|
1606
|
-
|
|
1607
|
-
const next =
|
|
1608
|
-
|
|
1622
|
+
closeTrial: (id) => {
|
|
1623
|
+
const next = closeTrial(store.getState().trials, id);
|
|
1624
|
+
replaceTrials(next);
|
|
1609
1625
|
},
|
|
1610
|
-
|
|
1611
|
-
|
|
1626
|
+
reorderTrials: (ids) => {
|
|
1627
|
+
replaceTrials(reorderTrials(store.getState().trials, ids));
|
|
1612
1628
|
},
|
|
1613
|
-
|
|
1614
|
-
const next =
|
|
1629
|
+
resetTrial: (id) => {
|
|
1630
|
+
const next = resetTrial(store.getState().trials, id, instruments);
|
|
1615
1631
|
const record = next.find((w) => w.id === id);
|
|
1616
1632
|
if (!record) return;
|
|
1617
1633
|
store.setState((s) => ({
|
|
1618
|
-
|
|
1634
|
+
trials: s.trials.map(
|
|
1619
1635
|
(w) => w.id === id ? { ...w, config: record.config, state: record.state, view: record.view } : w
|
|
1620
1636
|
)
|
|
1621
1637
|
}));
|
|
1622
|
-
store.getState().
|
|
1638
|
+
store.getState().updateTrialView(id, record.view);
|
|
1623
1639
|
},
|
|
1624
1640
|
savedSnapshots,
|
|
1625
|
-
saveSnapshot: (
|
|
1626
|
-
store.getState().saveSnapshot(
|
|
1641
|
+
saveSnapshot: (trialId, name) => {
|
|
1642
|
+
store.getState().saveSnapshot(trialId, name ?? `Save ${(/* @__PURE__ */ new Date()).toLocaleString()}`);
|
|
1627
1643
|
},
|
|
1628
|
-
loadSnapshot: (
|
|
1629
|
-
store.getState().loadSnapshot(snapshotId,
|
|
1644
|
+
loadSnapshot: (trialId, snapshotId) => {
|
|
1645
|
+
store.getState().loadSnapshot(snapshotId, trialId);
|
|
1630
1646
|
},
|
|
1631
1647
|
deleteSnapshot: (snapshotId) => {
|
|
1632
1648
|
store.getState().deleteSnapshot(snapshotId);
|
|
@@ -1636,7 +1652,7 @@ function Lab({
|
|
|
1636
1652
|
store.getState().setMode(m);
|
|
1637
1653
|
}
|
|
1638
1654
|
};
|
|
1639
|
-
}, [instruments,
|
|
1655
|
+
}, [instruments, trials, savedSnapshots, modeValue, store]);
|
|
1640
1656
|
const backdropStyle = resolvedMode === "dark" && nebula && nebula.length > 0 ? { ["--wzl-backdrop"]: buildNebula(nebula) } : void 0;
|
|
1641
1657
|
return /* @__PURE__ */ jsx(LabStoreContext.Provider, { value: { store }, children: /* @__PURE__ */ jsx(LabContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
1642
1658
|
ThemeProvider,
|
|
@@ -1646,15 +1662,15 @@ function Lab({
|
|
|
1646
1662
|
className: "lk-lab",
|
|
1647
1663
|
style: backdropStyle,
|
|
1648
1664
|
children: /* @__PURE__ */ jsx(LabShell, { title: title ?? "Labkit", mode: modeValue, header: children, children: /* @__PURE__ */ jsx(
|
|
1649
|
-
|
|
1665
|
+
Workspace,
|
|
1650
1666
|
{
|
|
1651
|
-
ids:
|
|
1667
|
+
ids: trials.map((w) => w.id),
|
|
1652
1668
|
resizable: true,
|
|
1653
1669
|
reorderable: true,
|
|
1654
|
-
onReorder: (ids) => contextValue.
|
|
1670
|
+
onReorder: (ids) => contextValue.reorderTrials(ids),
|
|
1655
1671
|
layout,
|
|
1656
1672
|
onLayoutChange: (next) => store.getState().setLayout(next),
|
|
1657
|
-
children:
|
|
1673
|
+
children: trials.map((w) => /* @__PURE__ */ jsx(Trial, { id: w.id }, w.id))
|
|
1658
1674
|
}
|
|
1659
1675
|
) })
|
|
1660
1676
|
}
|
|
@@ -2024,17 +2040,6 @@ function PropertyGroup({
|
|
|
2024
2040
|
/* @__PURE__ */ jsx("div", { className: "lk-property-group__body", children })
|
|
2025
2041
|
] });
|
|
2026
2042
|
}
|
|
2027
|
-
|
|
2028
|
-
// src/ui/format.ts
|
|
2029
|
-
var MINUS = "\u2212";
|
|
2030
|
-
function formatNumber(n, fractionDigits) {
|
|
2031
|
-
if (!Number.isFinite(n)) return String(n);
|
|
2032
|
-
const s = fractionDigits == null ? String(n) : n.toFixed(fractionDigits);
|
|
2033
|
-
return s.startsWith("-") ? MINUS + s.slice(1) : s;
|
|
2034
|
-
}
|
|
2035
|
-
function parseSignedNumber(s) {
|
|
2036
|
-
return Number(s.replace(MINUS, "-"));
|
|
2037
|
-
}
|
|
2038
2043
|
function PropertyPanel({ title, children, className }) {
|
|
2039
2044
|
const cls = className ? `lk-property-panel ${className}` : "lk-property-panel";
|
|
2040
2045
|
return /* @__PURE__ */ jsxs("div", { className: cls, children: [
|
|
@@ -2278,6 +2283,6 @@ function ToggleRow({
|
|
|
2278
2283
|
}) }) });
|
|
2279
2284
|
}
|
|
2280
2285
|
|
|
2281
|
-
export { CheckboxRow, ColorRow, CurveField, DefaultSidebar, DefaultStatusBar, DefaultToolbar, EffectCard, EffectCardList, Lab, LabContext, LabShell, NumberRow, PropertyGroup, PropertyList, PropertyPanel, PropertyRow, SelectRow, SliderRow, Subpanel, TextRow, ToggleRow,
|
|
2286
|
+
export { CheckboxRow, ColorRow, CurveField, DefaultSidebar, DefaultStatusBar, DefaultToolbar, EffectCard, EffectCardList, Lab, LabContext, LabShell, NumberRow, PropertyGroup, PropertyList, PropertyPanel, PropertyRow, SelectRow, SliderRow, Subpanel, TextRow, ToggleRow, Trial, TrialChrome, Workspace, addTrial, cloneTrial, closeTrial, defineInstrument, detectCapabilities, interstellarTheme, reorderTrials, resetTrial, useLabContext, validateConfigSchema };
|
|
2282
2287
|
//# sourceMappingURL=index.js.map
|
|
2283
2288
|
//# sourceMappingURL=index.js.map
|