@weasel-js/labkit 1.0.2 → 1.0.4

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 (111) hide show
  1. package/dist/_dts/{DrawCommand-CitWPxMY.d.ts → DrawCommand-BkZztJsW.d.ts} +59 -1
  2. package/dist/_dts/{index-C6Yze7sQ.d.ts → index-CFlDPeZh.d.ts} +30 -1
  3. package/dist/_dts/{types-Si4Fw-1F.d.ts → types-x92Kfeme.d.ts} +14 -0
  4. package/dist/_dts/{useExperimentState-CJn2hHzd.d.ts → useExperimentState-D7EQnnwJ.d.ts} +47 -0
  5. package/dist/canvas/index.d.ts +13 -2
  6. package/dist/canvas/index.js +2 -2
  7. package/dist/{chunk-54IQ2DX7.js → chunk-574LJAV4.js} +3 -3
  8. package/dist/chunk-574LJAV4.js.map +1 -0
  9. package/dist/{chunk-VLAHRJOC.js → chunk-5R2ATYPJ.js} +2 -2
  10. package/dist/{chunk-VLAHRJOC.js.map → chunk-5R2ATYPJ.js.map} +1 -1
  11. package/dist/{chunk-R4TACNW7.js → chunk-BAPZPDDA.js} +631 -591
  12. package/dist/chunk-BAPZPDDA.js.map +1 -0
  13. package/dist/{chunk-PWC7AQZM.js → chunk-CPUJ3QXL.js} +2 -2
  14. package/dist/chunk-CPUJ3QXL.js.map +1 -0
  15. package/dist/{chunk-2ZRE7WGQ.js → chunk-DEWXYFEU.js} +6 -6
  16. package/dist/chunk-DEWXYFEU.js.map +1 -0
  17. package/dist/{chunk-3P56ZCCJ.js → chunk-DWV7SFKR.js} +601 -269
  18. package/dist/chunk-DWV7SFKR.js.map +1 -0
  19. package/dist/{chunk-53XSBIUK.js → chunk-KSTEW2AF.js} +18 -2
  20. package/dist/chunk-KSTEW2AF.js.map +1 -0
  21. package/dist/{chunk-HXZHVU4G.js → chunk-PMAU3SEE.js} +3 -3
  22. package/dist/chunk-PMAU3SEE.js.map +1 -0
  23. package/dist/{chunk-7BKDG73Z.js → chunk-RL2LOLNI.js} +2 -2
  24. package/dist/chunk-RL2LOLNI.js.map +1 -0
  25. package/dist/{chunk-2QNYYL3V.js → chunk-SFL7NFKN.js} +2 -2
  26. package/dist/chunk-SFL7NFKN.js.map +1 -0
  27. package/dist/controls/index.d.ts +4 -2
  28. package/dist/controls/index.js +1 -1
  29. package/dist/dragdrop/index.d.ts +2 -2
  30. package/dist/index.d.ts +180 -15
  31. package/dist/index.js +146 -37
  32. package/dist/index.js.map +1 -1
  33. package/dist/layers/index.d.ts +6 -3
  34. package/dist/layers/index.js +1 -1
  35. package/dist/passthrough/weasel-canvas.d.ts +5 -1
  36. package/dist/passthrough/weasel-canvas.js +1 -1
  37. package/dist/passthrough/weasel-ui.d.ts +444 -7
  38. package/dist/passthrough/weasel-ui.js +2 -2
  39. package/dist/primitives/index.d.ts +13 -0
  40. package/dist/primitives/index.js +2 -2
  41. package/dist/state/index.d.ts +16 -3
  42. package/dist/state/index.js +2 -2
  43. package/dist/state/index.js.map +1 -1
  44. package/dist/styles.css +163 -6
  45. package/dist/ui/layers/index.d.ts +5 -0
  46. package/dist/ui/layers/index.js +3 -3
  47. package/dist/undo/index.d.ts +17 -2
  48. package/dist/undo/index.js +1 -1
  49. package/package.json +2 -1
  50. package/src/canvas/CanvasStack.tsx +4 -0
  51. package/src/canvas/CanvasStackContext.ts +3 -0
  52. package/src/canvas/canvasCoords.ts +2 -0
  53. package/src/canvas/useLayerScheduler.ts +2 -0
  54. package/src/controls/ControlPanel.tsx +2 -0
  55. package/src/controls/types.ts +14 -0
  56. package/src/instrument/capabilityDetector.ts +3 -0
  57. package/src/instrument/defineInstrument.ts +2 -0
  58. package/src/instrument/types.ts +29 -0
  59. package/src/instrument/validateConfigSchema.ts +5 -0
  60. package/src/lab/Lab.tsx +17 -2
  61. package/src/lab/LabContext.ts +6 -0
  62. package/src/lab/LabShell.tsx +4 -0
  63. package/src/lab/WorkspaceGrid.less +37 -5
  64. package/src/lab/WorkspaceGrid.stories.tsx +16 -0
  65. package/src/lab/WorkspaceGrid.test.tsx +84 -10
  66. package/src/lab/WorkspaceGrid.tsx +188 -12
  67. package/src/lab/index.ts +0 -2
  68. package/src/layers/LayerList.tsx +3 -0
  69. package/src/primitives/FpsMeter.tsx +1 -0
  70. package/src/primitives/ScaleIndicator.tsx +4 -0
  71. package/src/primitives/Sidebar.tsx +3 -0
  72. package/src/primitives/StatusBar.tsx +3 -0
  73. package/src/primitives/Toolbar.tsx +6 -0
  74. package/src/state/SingletonExperiment.tsx +1 -0
  75. package/src/state/adapters.ts +8 -0
  76. package/src/state/context.tsx +9 -0
  77. package/src/state/helpers.ts +13 -1
  78. package/src/state/store.test.ts +2 -1
  79. package/src/state/store.ts +25 -0
  80. package/src/state/types.ts +20 -0
  81. package/src/state/useExperimentState.ts +3 -0
  82. package/src/test-setup.ts +19 -0
  83. package/src/ui/layers/LayerStack.tsx +5 -0
  84. package/src/ui/properties/CurveField.tsx +4 -1
  85. package/src/ui/properties/EffectCard.tsx +12 -0
  86. package/src/ui/properties/PropertyGroup.tsx +1 -0
  87. package/src/ui/properties/PropertyPanel.tsx +28 -0
  88. package/src/undo/eventBus.ts +4 -0
  89. package/src/undo/undoStack.ts +11 -0
  90. package/src/workspace/DefaultSidebar.tsx +3 -0
  91. package/src/workspace/DefaultStatusBar.tsx +3 -0
  92. package/src/workspace/DefaultToolbar.tsx +3 -0
  93. package/src/workspace/Workspace.stories.tsx +1 -0
  94. package/src/workspace/Workspace.test.tsx +1 -0
  95. package/src/workspace/Workspace.tsx +3 -0
  96. package/src/workspace/WorkspaceChrome.tsx +4 -0
  97. package/src/workspace/index.ts +1 -0
  98. package/src/workspace/slotTypes.ts +9 -0
  99. package/src/workspace/workspaceOps.test.ts +34 -1
  100. package/src/workspace/workspaceOps.ts +24 -0
  101. package/dist/chunk-2QNYYL3V.js.map +0 -1
  102. package/dist/chunk-2ZRE7WGQ.js.map +0 -1
  103. package/dist/chunk-3P56ZCCJ.js.map +0 -1
  104. package/dist/chunk-53XSBIUK.js.map +0 -1
  105. package/dist/chunk-54IQ2DX7.js.map +0 -1
  106. package/dist/chunk-7BKDG73Z.js.map +0 -1
  107. package/dist/chunk-HXZHVU4G.js.map +0 -1
  108. package/dist/chunk-PWC7AQZM.js.map +0 -1
  109. package/dist/chunk-R4TACNW7.js.map +0 -1
  110. package/src/lab/gridDims.test.ts +0 -35
  111. package/src/lab/gridDims.ts +0 -11
package/dist/index.js CHANGED
@@ -1,23 +1,25 @@
1
- export { LayerStack } from './chunk-2ZRE7WGQ.js';
2
- import { p, F } from './chunk-R4TACNW7.js';
3
- import './chunk-3P56ZCCJ.js';
4
- import { Sidebar, StatusBar, Toolbar } from './chunk-HXZHVU4G.js';
5
- export { FpsMeter, ScaleIndicator, Sidebar, StatusBar, Toolbar } from './chunk-HXZHVU4G.js';
6
- import { LabStoreContext, createLabStore, noneAdapter } from './chunk-53XSBIUK.js';
7
- export { LabStoreContext, LabStoreProvider, WorkspaceIdContext, WorkspaceIdProvider, createMemoryAdapter, localStorageAdapter, noneAdapter, sessionStorageAdapter, urlHashAdapter, useExperimentState, useLabStore, useWorkspaceId } from './chunk-53XSBIUK.js';
8
- import { ControlPanel } from './chunk-VLAHRJOC.js';
9
- export { ControlPanel } from './chunk-VLAHRJOC.js';
10
- import { CanvasStack, screenToWorld } from './chunk-54IQ2DX7.js';
11
- export { CanvasStack, screenToWorld, worldToScreen } from './chunk-54IQ2DX7.js';
12
- export { CanvasStackContext } from './chunk-PWC7AQZM.js';
13
- import { LayerList } from './chunk-2QNYYL3V.js';
14
- export { LayerList } from './chunk-2QNYYL3V.js';
15
- import { createEventBus, redo, undo, pushSnapshot } from './chunk-7BKDG73Z.js';
16
- export { clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './chunk-7BKDG73Z.js';
17
- import { createContext, useContext, useMemo, useRef, useState, Children, useEffect, useCallback, useLayoutEffect } from 'react';
1
+ export { LayerStack } from './chunk-DEWXYFEU.js';
2
+ import { p, F } from './chunk-BAPZPDDA.js';
3
+ import './chunk-DWV7SFKR.js';
4
+ import { Sidebar, StatusBar, Toolbar } from './chunk-PMAU3SEE.js';
5
+ export { FpsMeter, ScaleIndicator, Sidebar, StatusBar, Toolbar } from './chunk-PMAU3SEE.js';
6
+ import { LabStoreContext, createLabStore, noneAdapter } from './chunk-KSTEW2AF.js';
7
+ export { LabStoreContext, LabStoreProvider, WorkspaceIdContext, WorkspaceIdProvider, createMemoryAdapter, localStorageAdapter, noneAdapter, sessionStorageAdapter, urlHashAdapter, useExperimentState, useLabStore, useWorkspaceId } from './chunk-KSTEW2AF.js';
8
+ import { ControlPanel } from './chunk-5R2ATYPJ.js';
9
+ export { ControlPanel } from './chunk-5R2ATYPJ.js';
10
+ import { CanvasStack, screenToWorld } from './chunk-574LJAV4.js';
11
+ export { CanvasStack, screenToWorld, worldToScreen } from './chunk-574LJAV4.js';
12
+ export { CanvasStackContext } from './chunk-CPUJ3QXL.js';
13
+ import { LayerList } from './chunk-SFL7NFKN.js';
14
+ export { LayerList } from './chunk-SFL7NFKN.js';
15
+ import { createEventBus, redo, undo, pushSnapshot } from './chunk-RL2LOLNI.js';
16
+ export { clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './chunk-RL2LOLNI.js';
17
+ import { createContext, useContext, useMemo, useRef, useState, Children, useLayoutEffect, useEffect, useCallback } from 'react';
18
18
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
19
19
  import { useStore } from 'zustand/react';
20
20
  import { createPortal } from 'react-dom';
21
+ import { asNodeId, Store, createNode, gridStrategy } from 'windease';
22
+ import { DragHandle, Provider, StrategyRegistryProvider, DragProvider, Container } from 'windease/react';
21
23
 
22
24
  // src/instrument/capabilityDetector.ts
23
25
  function detectCapabilities(instrument) {
@@ -88,15 +90,7 @@ function validateConfigSchema(fields) {
88
90
  return { valid: errors.length === 0, errors };
89
91
  }
90
92
 
91
- // src/lab/gridDims.ts
92
- function gridDims(count) {
93
- if (count <= 1) return { cols: 1, rows: 1 };
94
- const cols = Math.ceil(Math.sqrt(count));
95
- const rows = Math.ceil(count / cols);
96
- return { cols, rows };
97
- }
98
-
99
- // ../theme/dist/chunk-RATE4LL3.js
93
+ // ../theme/dist/chunk-STFENPNX.js
100
94
  var THEME_SOURCES = {
101
95
  "weasel": {
102
96
  "primitives": {
@@ -1390,6 +1384,13 @@ function resetWorkspace(workspaces, id, instruments) {
1390
1384
  };
1391
1385
  return [...workspaces.slice(0, idx), reset, ...workspaces.slice(idx + 1)];
1392
1386
  }
1387
+ function reorderWorkspaces(workspaces, ids) {
1388
+ const byId = new Map(workspaces.map((w) => [w.id, w]));
1389
+ const named = ids.map((id) => byId.get(id)).filter((w) => w !== void 0);
1390
+ const seen = new Set(named.map((w) => w.id));
1391
+ const rest = workspaces.filter((w) => !seen.has(w.id));
1392
+ return [...named, ...rest];
1393
+ }
1393
1394
  function query() {
1394
1395
  if (typeof window === "undefined" || !window.matchMedia) return null;
1395
1396
  return window.matchMedia("(prefers-color-scheme: light)");
@@ -1421,14 +1422,107 @@ function LabShell({ title, children, header, footer, mode = "auto" }) {
1421
1422
  ] });
1422
1423
  return outer ? shell : /* @__PURE__ */ jsx(ThemeProvider, { theme: interstellarTheme, mode: resolved, children: shell });
1423
1424
  }
1424
- function WorkspaceGrid({ children }) {
1425
- const count = Children.count(children);
1426
- const { cols, rows } = gridDims(count);
1427
- const style = {
1428
- "--lk-grid-cols": String(cols),
1429
- "--lk-grid-rows": String(rows)
1430
- };
1431
- return /* @__PURE__ */ jsx("div", { className: "lk-workspace-grid", style, children });
1425
+ var ZONE_ID = asNodeId("lk-workspaces");
1426
+ var STRATEGIES = { grid: gridStrategy };
1427
+ var KIND = "workspace";
1428
+ function extentOf(store, id) {
1429
+ const p2 = store.getNode(id)?.membership?.placement;
1430
+ if (!p2) return null;
1431
+ const out = {};
1432
+ if (p2.size) out.size = p2.size;
1433
+ if (p2.span) out.span = p2.span;
1434
+ return Object.keys(out).length > 0 ? out : null;
1435
+ }
1436
+ function WorkspaceGrid({
1437
+ children,
1438
+ ids,
1439
+ resizable = false,
1440
+ reorderable = false,
1441
+ onReorder,
1442
+ layout,
1443
+ onLayoutChange,
1444
+ gap = 12,
1445
+ padding = 0,
1446
+ viewport
1447
+ }) {
1448
+ const items = Children.toArray(children);
1449
+ const idKey = ids ? ids.join(",") : `#${items.length}`;
1450
+ const nodeIds = useMemo(() => items.map((_, i) => asNodeId(ids?.[i] ?? `lk-ws-${i}`)), [idKey]);
1451
+ const layoutRef = useRef(layout);
1452
+ layoutRef.current = layout;
1453
+ const onLayoutChangeRef = useRef(onLayoutChange);
1454
+ onLayoutChangeRef.current = onLayoutChange;
1455
+ const storeRef = useRef(null);
1456
+ if (storeRef.current === null) {
1457
+ const store2 = new Store();
1458
+ store2.registerNode(
1459
+ createNode({
1460
+ kind: "zone",
1461
+ id: ZONE_ID,
1462
+ container: { strategyId: "grid", config: { resizable, gap, padding } }
1463
+ })
1464
+ );
1465
+ storeRef.current = store2;
1466
+ }
1467
+ const store = storeRef.current;
1468
+ useLayoutEffect(() => {
1469
+ store.updateContainerConfig(ZONE_ID, { resizable, gap, padding });
1470
+ }, [store, resizable, gap, padding]);
1471
+ useLayoutEffect(() => {
1472
+ const present = new Set(store.getContainerView(ZONE_ID)?.childOrder ?? []);
1473
+ const wanted = new Set(nodeIds);
1474
+ for (const id of present) {
1475
+ if (!wanted.has(id)) store.unregisterNode(id);
1476
+ }
1477
+ for (const id of nodeIds) {
1478
+ if (present.has(id)) continue;
1479
+ store.registerNode(createNode({ kind: KIND, id, parentId: ZONE_ID, focus: true }));
1480
+ store.showNode(id);
1481
+ const saved = layoutRef.current?.[id];
1482
+ if (saved) store.patchPlacement(id, saved);
1483
+ }
1484
+ store.setChildOrder(ZONE_ID, [...nodeIds]);
1485
+ }, [store, nodeIds]);
1486
+ useEffect(() => {
1487
+ if (!onLayoutChange) return;
1488
+ return store.events.on("node.placementChanged", () => {
1489
+ const next = {};
1490
+ for (const child of store.getChildren(ZONE_ID)) {
1491
+ const extent = extentOf(store, child.id);
1492
+ if (extent) next[child.id] = extent;
1493
+ }
1494
+ onLayoutChangeRef.current?.(next);
1495
+ });
1496
+ }, [store, onLayoutChange]);
1497
+ const commitOrder = useCallback(
1498
+ (nextIds) => onReorder?.(nextIds.map(String)),
1499
+ [onReorder]
1500
+ );
1501
+ const chrome = useMemo(() => {
1502
+ const byId = new Map(nodeIds.map((id, i) => [id, items[i]]));
1503
+ return {
1504
+ [KIND]: ({ node }) => {
1505
+ const content = byId.get(node.id) ?? null;
1506
+ if (!reorderable) return content;
1507
+ return /* @__PURE__ */ jsxs("div", { className: "lk-workspace-tile", children: [
1508
+ /* @__PURE__ */ jsx(DragHandle, { nodeId: node.id, className: "lk-workspace-tile__grip", children: /* @__PURE__ */ jsx("span", { className: "lk-workspace-tile__grip-dots", "aria-hidden": "true" }) }),
1509
+ /* @__PURE__ */ jsx("div", { className: "lk-workspace-tile__body", children: content })
1510
+ ] });
1511
+ }
1512
+ };
1513
+ }, [nodeIds, items, reorderable]);
1514
+ const grid = /* @__PURE__ */ jsx(
1515
+ Container,
1516
+ {
1517
+ parentId: ZONE_ID,
1518
+ chrome,
1519
+ className: "lk-workspace-grid windease-zone",
1520
+ affordances: resizable,
1521
+ viewport,
1522
+ onChildOrderChange: reorderable ? commitOrder : void 0
1523
+ }
1524
+ );
1525
+ return /* @__PURE__ */ jsx(Provider, { store, children: /* @__PURE__ */ jsx(StrategyRegistryProvider, { strategies: STRATEGIES, children: reorderable ? /* @__PURE__ */ jsx(DragProvider, { children: grid }) : grid }) });
1432
1526
  }
1433
1527
  function buildStore(instruments, defaultInstrument, storage, storageKey, initialMode) {
1434
1528
  const store = createLabStore({ storageKey, storage, initialMode });
@@ -1484,6 +1578,7 @@ function Lab({
1484
1578
  const workspaces = useStore(store, (s) => s.workspaces);
1485
1579
  const savedSnapshots = useStore(store, (s) => s.savedSnapshots);
1486
1580
  const modeValue = useStore(store, (s) => s.mode);
1581
+ const layout = useStore(store, (s) => s.layout);
1487
1582
  const resolvedMode = useResolvedMode(modeValue);
1488
1583
  useEffect(() => {
1489
1584
  if (mode && mode !== store.getState().mode) {
@@ -1512,6 +1607,9 @@ function Lab({
1512
1607
  const next = closeWorkspace(store.getState().workspaces, id);
1513
1608
  replaceWorkspaces(next);
1514
1609
  },
1610
+ reorderWorkspaces: (ids) => {
1611
+ replaceWorkspaces(reorderWorkspaces(store.getState().workspaces, ids));
1612
+ },
1515
1613
  resetWorkspace: (id) => {
1516
1614
  const next = resetWorkspace(store.getState().workspaces, id, instruments);
1517
1615
  const record = next.find((w) => w.id === id);
@@ -1547,7 +1645,18 @@ function Lab({
1547
1645
  mode: resolvedMode,
1548
1646
  className: "lk-lab",
1549
1647
  style: backdropStyle,
1550
- children: /* @__PURE__ */ jsx(LabShell, { title: title ?? "Labkit", mode: modeValue, header: children, children: /* @__PURE__ */ jsx(WorkspaceGrid, { children: workspaces.map((w) => /* @__PURE__ */ jsx(Workspace, { id: w.id }, w.id)) }) })
1648
+ children: /* @__PURE__ */ jsx(LabShell, { title: title ?? "Labkit", mode: modeValue, header: children, children: /* @__PURE__ */ jsx(
1649
+ WorkspaceGrid,
1650
+ {
1651
+ ids: workspaces.map((w) => w.id),
1652
+ resizable: true,
1653
+ reorderable: true,
1654
+ onReorder: (ids) => contextValue.reorderWorkspaces(ids),
1655
+ layout,
1656
+ onLayoutChange: (next) => store.getState().setLayout(next),
1657
+ children: workspaces.map((w) => /* @__PURE__ */ jsx(Workspace, { id: w.id }, w.id))
1658
+ }
1659
+ ) })
1551
1660
  }
1552
1661
  ) }) });
1553
1662
  }
@@ -1610,7 +1719,7 @@ function CurveField({
1610
1719
  F,
1611
1720
  {
1612
1721
  value: points,
1613
- onChange: handleChange,
1722
+ onInput: handleChange,
1614
1723
  domain: "1d",
1615
1724
  constrain: "function",
1616
1725
  xRange: [0, 1],
@@ -2169,6 +2278,6 @@ function ToggleRow({
2169
2278
  }) }) });
2170
2279
  }
2171
2280
 
2172
- export { CheckboxRow, ColorRow, CurveField, DefaultSidebar, DefaultStatusBar, DefaultToolbar, EffectCard, EffectCardList, Lab, LabContext, LabShell, NumberRow, PropertyGroup, PropertyList, PropertyPanel, PropertyRow, SelectRow, SliderRow, Subpanel, TextRow, ToggleRow, Workspace, WorkspaceChrome, WorkspaceGrid, addWorkspace, cloneWorkspace, closeWorkspace, defineInstrument, detectCapabilities, gridDims, interstellarTheme, resetWorkspace, useLabContext, validateConfigSchema };
2281
+ export { CheckboxRow, ColorRow, CurveField, DefaultSidebar, DefaultStatusBar, DefaultToolbar, EffectCard, EffectCardList, Lab, LabContext, LabShell, NumberRow, PropertyGroup, PropertyList, PropertyPanel, PropertyRow, SelectRow, SliderRow, Subpanel, TextRow, ToggleRow, Workspace, WorkspaceChrome, WorkspaceGrid, addWorkspace, cloneWorkspace, closeWorkspace, defineInstrument, detectCapabilities, interstellarTheme, reorderWorkspaces, resetWorkspace, useLabContext, validateConfigSchema };
2173
2282
  //# sourceMappingURL=index.js.map
2174
2283
  //# sourceMappingURL=index.js.map