@floegence/floe-webapp-core 0.36.13 → 0.36.16

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 (39) hide show
  1. package/dist/components/deck/DeckCell.js +46 -38
  2. package/dist/components/file-browser/FileContextMenu.js +8 -6
  3. package/dist/components/ui/Dialog.js +62 -52
  4. package/dist/components/ui/Dropdown.js +50 -48
  5. package/dist/components/ui/FloatingWindow.js +73 -69
  6. package/dist/components/ui/InfiniteCanvas.d.ts +2 -0
  7. package/dist/components/ui/InfiniteCanvas.js +121 -101
  8. package/dist/components/ui/canvasGeometry.d.ts +32 -0
  9. package/dist/components/ui/canvasGeometry.js +33 -0
  10. package/dist/components/ui/dialogSurfaceScope.d.ts +8 -8
  11. package/dist/components/ui/dialogSurfaceScope.js +108 -62
  12. package/dist/components/ui/index.d.ts +2 -0
  13. package/dist/components/ui/surfacePortalScope.d.ts +1 -1
  14. package/dist/components/ui/surfacePortalTypes.d.ts +8 -0
  15. package/dist/components/workbench/WorkbenchCanvas.d.ts +4 -0
  16. package/dist/components/workbench/WorkbenchCanvas.js +52 -26
  17. package/dist/components/workbench/WorkbenchCanvasField.d.ts +2 -0
  18. package/dist/components/workbench/WorkbenchCanvasField.js +18 -6
  19. package/dist/components/workbench/WorkbenchHud.d.ts +9 -0
  20. package/dist/components/workbench/WorkbenchHud.js +24 -10
  21. package/dist/components/workbench/WorkbenchSurface.js +56 -36
  22. package/dist/components/workbench/WorkbenchThemeSelector.d.ts +6 -0
  23. package/dist/components/workbench/WorkbenchThemeSelector.js +77 -0
  24. package/dist/components/workbench/WorkbenchWidget.d.ts +2 -0
  25. package/dist/components/workbench/WorkbenchWidget.js +205 -164
  26. package/dist/components/workbench/index.d.ts +2 -0
  27. package/dist/components/workbench/types.d.ts +2 -0
  28. package/dist/components/workbench/useWorkbenchModel.d.ts +6 -0
  29. package/dist/components/workbench/useWorkbenchModel.js +115 -106
  30. package/dist/components/workbench/workbenchHelpers.js +53 -50
  31. package/dist/components/workbench/workbenchThemes.d.ts +32 -0
  32. package/dist/components/workbench/workbenchThemes.js +82 -0
  33. package/dist/full.js +611 -591
  34. package/dist/styles.css +1 -1
  35. package/dist/ui.js +120 -100
  36. package/dist/workbench-themes.css +1106 -0
  37. package/dist/workbench.css +492 -96
  38. package/dist/workbench.js +35 -27
  39. package/package.json +1 -1
@@ -1,41 +1,41 @@
1
- import { createSignal as V, createMemo as d, onCleanup as xt } from "solid-js";
2
- import { ArrowUp as St, Copy as Ct, Trash as pt } from "../icons/index.js";
3
- import { getTopZIndex as kt, createContextMenuPosition as Ft, createWorkbenchId as bt, createWorkbenchViewportCenteredOnWidget as L, findNearestWidget as It, clampScale as Mt, WORKBENCH_CANVAS_ZOOM_STEP as $, WORKBENCH_MIN_SCALE as Xt, createWorkbenchViewportFitForWidget as yt, WORKBENCH_CONTEXT_MENU_WIDTH_PX as Yt, estimateContextMenuHeight as vt } from "./workbenchHelpers.js";
4
- import { resolveWorkbenchWidgetDefinitions as Ot, getWidgetEntry as j, createWorkbenchFilterState as zt } from "./widgets/widgetRegistry.js";
5
- function qt(c) {
6
- const [W, x] = V(null), [U, D] = V(null), [H, G] = V({ width: 0, height: 0 });
7
- let r = null, S = null;
8
- const l = c.state, w = d(() => l().widgets), u = d(() => l().viewport), J = d(() => l().locked), N = d(() => l().filters), F = d(() => l().selectedWidgetId), b = d(() => kt(w())), Q = d(() => `${Math.round(u().scale * 100)}%`), tt = () => typeof c.widgetDefinitions == "function" ? c.widgetDefinitions() : c.widgetDefinitions, m = d(
9
- () => Ot(tt())
1
+ import { createSignal as N, createMemo as r, onCleanup as Ct } from "solid-js";
2
+ import { ArrowUp as pt, Copy as kt, Trash as Ft } from "../icons/index.js";
3
+ import { getTopZIndex as bt, createContextMenuPosition as It, createWorkbenchId as Mt, createWorkbenchViewportCenteredOnWidget as L, findNearestWidget as Xt, clampScale as vt, WORKBENCH_CANVAS_ZOOM_STEP as $, WORKBENCH_MIN_SCALE as yt, createWorkbenchViewportFitForWidget as Yt, WORKBENCH_CONTEXT_MENU_WIDTH_PX as Ot, estimateContextMenuHeight as zt } from "./workbenchHelpers.js";
4
+ import { resolveWorkbenchWidgetDefinitions as _t, getWidgetEntry as j, createWorkbenchFilterState as Vt } from "./widgets/widgetRegistry.js";
5
+ function Kt(c) {
6
+ const [W, x] = N(null), [U, T] = N(null), [D, G] = N({ width: 0, height: 0 });
7
+ let d = null, S = null;
8
+ const l = c.state, m = r(() => l().widgets), u = r(() => l().viewport), J = r(() => l().locked), H = r(() => l().filters), F = r(() => l().selectedWidgetId), Q = r(() => l().theme), b = r(() => bt(m())), tt = r(() => `${Math.round(u().scale * 100)}%`), et = () => typeof c.widgetDefinitions == "function" ? c.widgetDefinitions() : c.widgetDefinitions, w = r(
9
+ () => _t(et())
10
10
  ), I = (t, e) => {
11
- const n = Number.isFinite(t) && t > 0 ? t : 0, i = Number.isFinite(e) && e > 0 ? e : 0, o = { width: n, height: i }, s = H();
11
+ const n = Number.isFinite(t) && t > 0 ? t : 0, i = Number.isFinite(e) && e > 0 ? e : 0, o = { width: n, height: i }, s = D();
12
12
  return s.width === n && s.height === i ? s : (G(o), o);
13
13
  }, R = () => {
14
14
  S?.disconnect(), S = null;
15
- }, a = () => r ? I(r.clientWidth, r.clientHeight) : I(0, 0), et = (t) => {
16
- if (r === (t ?? null)) {
15
+ }, a = () => d ? I(d.clientWidth, d.clientHeight) : I(0, 0), nt = (t) => {
16
+ if (d === (t ?? null)) {
17
17
  a();
18
18
  return;
19
19
  }
20
- R(), r = t ?? null, a(), !(!r || typeof ResizeObserver > "u") && (S = new ResizeObserver((e) => {
20
+ R(), d = t ?? null, a(), !(!d || typeof ResizeObserver > "u") && (S = new ResizeObserver((e) => {
21
21
  const n = e[0];
22
22
  I(
23
- n?.contentRect.width ?? r?.clientWidth ?? 0,
24
- n?.contentRect.height ?? r?.clientHeight ?? 0
23
+ n?.contentRect.width ?? d?.clientWidth ?? 0,
24
+ n?.contentRect.height ?? d?.clientHeight ?? 0
25
25
  );
26
- }), S.observe(r));
26
+ }), S.observe(d));
27
27
  };
28
- xt(() => {
29
- R(), r = null;
28
+ Ct(() => {
29
+ R(), d = null;
30
30
  });
31
- const nt = (t) => {
31
+ const it = (t) => {
32
32
  x({
33
33
  clientX: t.clientX,
34
34
  clientY: t.clientY,
35
35
  worldX: t.worldX,
36
36
  worldY: t.worldY
37
37
  });
38
- }, it = (t, e) => {
38
+ }, ot = (t, e) => {
39
39
  f(e.id), x({
40
40
  clientX: t.clientX,
41
41
  clientY: t.clientY,
@@ -43,16 +43,16 @@ function qt(c) {
43
43
  worldY: e.y,
44
44
  widgetId: e.id
45
45
  });
46
- }, h = () => x(null), ot = (t) => l().widgets.find((e) => e.id === t) ?? null, M = (t) => l().widgets.find((e) => e.type === t) ?? null, T = d(() => {
46
+ }, h = () => x(null), ct = (t) => l().widgets.find((e) => e.id === t) ?? null, M = (t) => l().widgets.find((e) => e.type === t) ?? null, E = r(() => {
47
47
  const t = W();
48
48
  if (!t) return [];
49
49
  if (t.widgetId) {
50
- const e = w().find((i) => i.id === t.widgetId), n = [];
50
+ const e = m().find((i) => i.id === t.widgetId), n = [];
51
51
  return e && (n.push({
52
52
  id: "bring-to-front",
53
53
  kind: "action",
54
54
  label: "Bring to Front",
55
- icon: St,
55
+ icon: pt,
56
56
  onSelect: () => {
57
57
  f(e.id), h();
58
58
  }
@@ -60,46 +60,46 @@ function qt(c) {
60
60
  id: "duplicate",
61
61
  kind: "action",
62
62
  label: "Duplicate",
63
- icon: Ct,
63
+ icon: kt,
64
64
  onSelect: () => {
65
- E(e.type, e.x + 32, e.y + 32), h();
65
+ B(e.type, e.x + 32, e.y + 32), h();
66
66
  }
67
67
  })), n.push({ id: "separator-delete", kind: "separator" }), n.push({
68
68
  id: "delete",
69
69
  kind: "action",
70
70
  label: "Delete",
71
- icon: pt,
71
+ icon: Ft,
72
72
  destructive: !0,
73
73
  onSelect: () => {
74
- t.widgetId && Y(t.widgetId), h();
74
+ t.widgetId && y(t.widgetId), h();
75
75
  }
76
76
  }), n;
77
77
  }
78
- return m().map((e) => ({
78
+ return w().map((e) => ({
79
79
  id: `add-${e.type}`,
80
80
  kind: "action",
81
81
  label: `Add ${e.label}`,
82
82
  icon: e.icon,
83
83
  onSelect: () => {
84
- y(e.type, t.worldX, t.worldY), h();
84
+ v(e.type, t.worldX, t.worldY), h();
85
85
  }
86
86
  }));
87
- }), ct = d(() => {
87
+ }), st = r(() => {
88
88
  const t = W();
89
89
  if (!t) return;
90
- const e = T(), n = e.filter((o) => o.kind === "action").length, i = e.filter((o) => o.kind === "separator").length;
91
- return Ft({
90
+ const e = E(), n = e.filter((o) => o.kind === "action").length, i = e.filter((o) => o.kind === "separator").length;
91
+ return It({
92
92
  clientX: t.clientX,
93
93
  clientY: t.clientY,
94
- menuWidth: Yt,
95
- menuHeight: vt(n, i)
94
+ menuWidth: Ot,
95
+ menuHeight: zt(n, i)
96
96
  });
97
97
  }), X = (t, e, n) => {
98
- const i = j(t, m()), o = i.singleton ? M(t) : null;
98
+ const i = j(t, w()), o = i.singleton ? M(t) : null;
99
99
  if (o)
100
100
  return p(o, { centerViewport: !0 });
101
101
  const s = i.defaultSize, g = {
102
- id: bt(),
102
+ id: Mt(),
103
103
  type: t,
104
104
  title: i.defaultTitle,
105
105
  x: e,
@@ -114,136 +114,139 @@ function qt(c) {
114
114
  widgets: [...k.widgets, g],
115
115
  selectedWidgetId: g.id
116
116
  })), g;
117
- }, y = (t, e, n) => {
118
- const i = j(t, m()).defaultSize;
117
+ }, v = (t, e, n) => {
118
+ const i = j(t, w()).defaultSize;
119
119
  return X(t, e - i.width / 2, n - i.height / 2);
120
- }, E = (t, e, n) => X(t, e, n), Y = (t) => {
120
+ }, B = (t, e, n) => X(t, e, n), y = (t) => {
121
121
  c.setState((e) => ({
122
122
  ...e,
123
123
  widgets: e.widgets.filter((n) => n.id !== t),
124
124
  selectedWidgetId: e.selectedWidgetId === t ? null : e.selectedWidgetId
125
125
  }));
126
- }, st = (t) => {
127
- D(t);
126
+ }, rt = (t) => {
127
+ T(t);
128
128
  }, f = (t) => {
129
- D(t);
130
- const e = b(), n = w().find((i) => i.id === t);
129
+ T(t);
130
+ const e = b(), n = m().find((i) => i.id === t);
131
131
  n && n.z_index < e && c.setState((i) => ({
132
132
  ...i,
133
133
  widgets: i.widgets.map(
134
134
  (o) => o.id === t ? { ...o, z_index: e + 1 } : o
135
135
  )
136
136
  }));
137
- }, rt = (t, e) => {
137
+ }, dt = (t, e) => {
138
138
  c.setState((n) => ({
139
139
  ...n,
140
140
  widgets: n.widgets.map(
141
141
  (i) => i.id === t ? { ...i, x: e.x, y: e.y } : i
142
142
  )
143
143
  }));
144
- }, dt = (t, e) => {
144
+ }, lt = (t, e) => {
145
145
  c.setState((n) => ({
146
146
  ...n,
147
147
  widgets: n.widgets.map(
148
148
  (i) => i.id === t ? { ...i, width: e.width, height: e.height } : i
149
149
  )
150
150
  }));
151
- }, v = (t) => {
151
+ }, Y = (t) => {
152
152
  c.setState((e) => ({ ...e, viewport: t }));
153
- }, B = (t) => {
154
- const e = u(), n = a(), i = (n.width / 2 - e.x) / e.scale, o = (n.height / 2 - e.y) / e.scale, s = Mt(
153
+ }, q = (t) => {
154
+ const e = u(), n = a(), i = (n.width / 2 - e.x) / e.scale, o = (n.height / 2 - e.y) / e.scale, s = vt(
155
155
  t === "in" ? e.scale * $ : e.scale / $
156
156
  ), g = {
157
157
  x: n.width / 2 - i * s,
158
158
  y: n.height / 2 - o * s,
159
159
  scale: s
160
160
  };
161
- v(g);
162
- }, lt = () => {
161
+ Y(g);
162
+ }, at = () => {
163
163
  c.setState((t) => ({ ...t, locked: !t.locked }));
164
- }, at = (t) => {
164
+ }, gt = (t) => {
165
165
  c.setState((e) => ({
166
166
  ...e,
167
167
  filters: { ...e.filters, [t]: !e.filters[t] }
168
168
  }));
169
- }, gt = (t) => {
169
+ }, ut = (t) => {
170
170
  c.setState((e) => {
171
171
  const n = { ...e.filters };
172
172
  for (const i of Object.keys(n))
173
173
  n[i] = i === t;
174
174
  return { ...e, filters: n };
175
175
  });
176
- }, ut = () => {
177
- const t = zt(m());
176
+ }, ht = () => {
177
+ const t = Vt(w());
178
178
  c.setState((e) => ({
179
179
  ...e,
180
180
  filters: t
181
181
  }));
182
182
  }, C = (t) => {
183
183
  c.setState((e) => ({ ...e, selectedWidgetId: t }));
184
- }, q = () => {
184
+ }, P = () => {
185
185
  c.setState(
186
186
  (t) => t.selectedWidgetId === null ? t : { ...t, selectedWidgetId: null }
187
187
  );
188
- }, ht = () => {
188
+ }, ft = () => {
189
189
  const t = a(), e = u();
190
190
  return {
191
191
  worldX: t.width > 0 ? (t.width / 2 - e.x) / e.scale : 240,
192
192
  worldY: t.height > 0 ? (t.height / 2 - e.y) / e.scale : 180
193
193
  };
194
194
  };
195
- let P = 0;
196
- const O = (t) => {
197
- const e = u(), n = e.x, i = e.y, o = e.scale, s = performance.now(), g = 360, k = ++P, mt = (_) => 1 - Math.pow(1 - _, 3), Z = (_) => {
198
- if (k !== P) return;
199
- const Wt = _ - s, K = Math.min(Math.max(Wt / g, 0), 1), A = mt(K);
200
- v({
195
+ let O = 0;
196
+ const mt = () => {
197
+ O += 1;
198
+ }, z = (t) => {
199
+ const e = u(), n = e.x, i = e.y, o = e.scale, s = performance.now(), g = 360, k = ++O, xt = (V) => 1 - Math.pow(1 - V, 3), Z = (V) => {
200
+ if (k !== O) return;
201
+ const St = V - s, K = Math.min(Math.max(St / g, 0), 1), A = xt(K);
202
+ Y({
201
203
  x: n + (t.x - n) * A,
202
204
  y: i + (t.y - i) * A,
203
205
  scale: o + (t.scale - o) * A
204
206
  }), K < 1 && requestAnimationFrame(Z);
205
207
  };
206
208
  requestAnimationFrame(Z);
207
- }, z = (t) => {
209
+ }, _ = (t) => {
208
210
  const e = a();
209
- e.width === 0 || e.height === 0 || O(L({
211
+ e.width === 0 || e.height === 0 || z(L({
210
212
  widget: t,
211
213
  scale: u().scale,
212
214
  frameWidth: e.width,
213
215
  frameHeight: e.height
214
216
  }));
215
- }, ft = (t) => {
217
+ }, wt = (t) => {
216
218
  const e = a();
217
- e.width === 0 || e.height === 0 || O(yt({
219
+ e.width === 0 || e.height === 0 || z(Yt({
218
220
  widget: t,
219
221
  frameWidth: e.width,
220
222
  frameHeight: e.height
221
223
  }));
222
- }, wt = (t) => {
224
+ }, Wt = (t) => {
223
225
  const e = a();
224
- e.width === 0 || e.height === 0 || O(L({
226
+ e.width === 0 || e.height === 0 || z(L({
225
227
  widget: t,
226
- scale: Xt,
228
+ scale: yt,
227
229
  frameWidth: e.width,
228
230
  frameHeight: e.height
229
231
  }));
230
- }, p = (t, e = {}) => (C(t.id), f(t.id), e.centerViewport !== !1 && z(t), t);
232
+ }, p = (t, e = {}) => (C(t.id), f(t.id), e.centerViewport !== !1 && _(t), t);
231
233
  return {
232
- widgets: w,
234
+ widgets: m,
233
235
  viewport: u,
234
- canvasFrameSize: H,
236
+ canvasFrameSize: D,
235
237
  locked: J,
236
- filters: N,
238
+ filters: H,
237
239
  selectedWidgetId: F,
240
+ theme: Q,
238
241
  topZIndex: b,
239
- scaleLabel: Q,
242
+ scaleLabel: tt,
240
243
  optimisticFrontWidgetId: U,
241
- widgetDefinitions: m,
242
- setCanvasFrameRef: et,
244
+ widgetDefinitions: w,
245
+ setCanvasFrameRef: nt,
243
246
  contextMenu: {
244
247
  state: W,
245
- items: T,
246
- position: ct,
248
+ items: E,
249
+ position: st,
247
250
  close: h,
248
251
  retarget: (t) => {
249
252
  t.preventDefault(), t.stopPropagation(), x({
@@ -255,70 +258,76 @@ function qt(c) {
255
258
  }
256
259
  },
257
260
  canvas: {
258
- openCanvasContextMenu: nt,
259
- openWidgetContextMenu: it,
261
+ openCanvasContextMenu: it,
262
+ openWidgetContextMenu: ot,
260
263
  selectWidget: C,
261
- clearSelection: q,
262
- startOptimisticFront: st,
264
+ clearSelection: P,
265
+ startOptimisticFront: rt,
263
266
  commitFront: f,
264
- commitMove: rt,
265
- commitResize: dt,
266
- commitViewport: v
267
+ commitMove: dt,
268
+ commitResize: lt,
269
+ commitViewport: Y,
270
+ cancelViewportNavigation: mt
267
271
  },
268
272
  hud: {
269
- zoomIn: () => B("in"),
270
- zoomOut: () => B("out")
273
+ zoomIn: () => q("in"),
274
+ zoomOut: () => q("out")
271
275
  },
272
276
  lock: {
273
- toggle: lt
277
+ toggle: at
274
278
  },
275
279
  filter: {
276
- toggle: at,
277
- solo: gt,
278
- showAll: ut
280
+ toggle: gt,
281
+ solo: ut,
282
+ showAll: ht
279
283
  },
280
284
  navigation: {
281
285
  handleArrowNavigation: (t) => {
282
- const e = It(
283
- w(),
286
+ const e = Xt(
287
+ m(),
284
288
  F(),
285
289
  t,
286
- N()
290
+ H()
287
291
  );
288
292
  e && p(e);
289
293
  },
290
- centerOnWidget: z,
294
+ centerOnWidget: _,
291
295
  focusWidget: p,
292
- fitWidget: (t) => (C(t.id), f(t.id), ft(t), t),
293
- overviewWidget: (t) => (C(t.id), f(t.id), wt(t), t)
296
+ fitWidget: (t) => (C(t.id), f(t.id), wt(t), t),
297
+ overviewWidget: (t) => (C(t.id), f(t.id), Wt(t), t)
294
298
  },
295
299
  selection: {
296
- clear: q
300
+ clear: P
297
301
  },
298
302
  widgetActions: {
299
303
  deleteSelected: () => {
300
304
  const t = F();
301
- t && Y(t);
305
+ t && y(t);
302
306
  },
303
- deleteWidget: Y,
307
+ deleteWidget: y,
304
308
  addWidget: X,
305
- addWidgetAtCursor: y,
306
- addWidgetCentered: E,
309
+ addWidgetAtCursor: v,
310
+ addWidgetCentered: B,
307
311
  ensureWidget: (t, e) => {
308
312
  const n = M(t);
309
313
  if (n)
310
314
  return p(n, { centerViewport: e?.centerViewport ?? !0 });
311
- const i = ht(), o = y(
315
+ const i = ft(), o = v(
312
316
  t,
313
317
  e?.worldX ?? i.worldX,
314
318
  e?.worldY ?? i.worldY
315
319
  );
316
- return (e?.centerViewport ?? !0) && o && z(o), o;
320
+ return (e?.centerViewport ?? !0) && o && _(o), o;
317
321
  }
318
322
  },
319
323
  queries: {
320
324
  findWidgetByType: M,
321
- findWidgetById: ot
325
+ findWidgetById: ct
326
+ },
327
+ appearance: {
328
+ setTheme: (t) => {
329
+ l().theme !== t && c.setState((e) => ({ ...e, theme: t }));
330
+ }
322
331
  },
323
332
  handleCloseRequest: () => {
324
333
  if (W()) {
@@ -330,5 +339,5 @@ function qt(c) {
330
339
  };
331
340
  }
332
341
  export {
333
- qt as useWorkbenchModel
342
+ Kt as useWorkbenchModel
334
343
  };
@@ -1,13 +1,14 @@
1
1
  import { DEFAULT_WORKBENCH_VIEWPORT as y } from "./types.js";
2
- import { resolveWorkbenchWidgetDefinitions as _, getWidgetEntry as W, createWorkbenchFilterState as w, isValidWorkbenchWidgetType as k } from "./widgets/widgetRegistry.js";
3
- function D() {
2
+ import { resolveWorkbenchWidgetDefinitions as _, getWidgetEntry as W, createWorkbenchFilterState as w, isValidWorkbenchWidgetType as H } from "./widgets/widgetRegistry.js";
3
+ import { DEFAULT_WORKBENCH_THEME as b, isWorkbenchThemeId as N } from "./workbenchThemes.js";
4
+ function T() {
4
5
  const e = globalThis.crypto;
5
6
  return e && typeof e.randomUUID == "function" ? `wb-${e.randomUUID()}` : `wb-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
6
7
  }
7
- function O(e) {
8
+ function A(e) {
8
9
  return e.renderMode ?? "canvas_scaled";
9
10
  }
10
- function N(e) {
11
+ function E(e) {
11
12
  const t = Number.isFinite(e.viewport.scale) && e.viewport.scale > 0 ? e.viewport.scale : 1;
12
13
  return {
13
14
  widgetId: e.widgetId,
@@ -22,28 +23,28 @@ function N(e) {
22
23
  viewportScale: t
23
24
  };
24
25
  }
25
- function R(e) {
26
+ function P(e) {
26
27
  return {
27
28
  ready: e.ready,
28
- rect: N(e)
29
+ rect: E(e)
29
30
  };
30
31
  }
31
- function H(e) {
32
+ function F(e) {
32
33
  return e ? {
33
34
  x: Number.isFinite(e.x) ? e.x : 0,
34
35
  y: Number.isFinite(e.y) ? e.y : 0,
35
36
  scale: Number.isFinite(e.scale) && e.scale > 0 ? e.scale : 1
36
37
  } : { ...y };
37
38
  }
38
- function F(e, t) {
39
+ function I(e, t) {
39
40
  return w(t, e);
40
41
  }
41
- function T(e, t = {}) {
42
- const r = _(t.widgetDefinitions), d = t.createFallbackState ?? (() => I(r)), n = e;
42
+ function X(e, t = {}) {
43
+ const r = _(t.widgetDefinitions), d = t.createFallbackState ?? (() => z(r)), n = e;
43
44
  if (!n || n.version !== 1 || !Array.isArray(n.widgets))
44
45
  return d();
45
46
  const a = n.widgets.filter(
46
- (i) => !!i && typeof i.id == "string" && k(i.type, r) && typeof i.title == "string"
47
+ (i) => !!i && typeof i.id == "string" && H(i.type, r) && typeof i.title == "string"
47
48
  ).map((i) => {
48
49
  const h = W(i.type, r);
49
50
  return {
@@ -61,13 +62,14 @@ function T(e, t = {}) {
61
62
  return {
62
63
  version: 1,
63
64
  widgets: a,
64
- viewport: H(n.viewport),
65
+ viewport: F(n.viewport),
65
66
  locked: typeof n.locked == "boolean" ? n.locked : !1,
66
- filters: F(n.filters, r),
67
- selectedWidgetId: c
67
+ filters: I(n.filters, r),
68
+ selectedWidgetId: c,
69
+ theme: N(n.theme) ? n.theme : b
68
70
  };
69
71
  }
70
- function I(e) {
72
+ function z(e) {
71
73
  const t = _(e), r = Date.now(), d = [
72
74
  { type: "terminal", title: "dev · terminal", x: 80, y: 80 },
73
75
  { type: "file-browser", title: "project · files", x: 600, y: 80 },
@@ -94,20 +96,21 @@ function I(e) {
94
96
  viewport: { ...y },
95
97
  locked: !1,
96
98
  filters: w(t),
97
- selectedWidgetId: n[0]?.id ?? null
99
+ selectedWidgetId: n[0]?.id ?? null,
100
+ theme: b
98
101
  };
99
102
  }
100
- const P = 1.18, A = 200, u = 0.45, g = 2.2, z = 48;
103
+ const B = 1.18, K = 200, m = 0.45, u = 2.2, p = 48;
101
104
  function v(e) {
102
- const t = b(e.scale, u, g);
105
+ const t = M(e.scale, m, u);
103
106
  return {
104
107
  x: e.frameWidth / 2 - (e.widget.x + e.widget.width / 2) * t,
105
108
  y: e.frameHeight / 2 - (e.widget.y + e.widget.height / 2) * t,
106
109
  scale: t
107
110
  };
108
111
  }
109
- function X(e) {
110
- const t = e.minScale ?? u, r = e.maxScale ?? g, d = e.paddingPx ?? z, n = Math.max(e.frameWidth - d * 2, 1), a = Math.max(e.frameHeight - d * 2, 1), c = b(
112
+ function U(e) {
113
+ const t = e.minScale ?? m, r = e.maxScale ?? u, d = e.paddingPx ?? p, n = Math.max(e.frameWidth - d * 2, 1), a = Math.max(e.frameHeight - d * 2, 1), c = M(
111
114
  Math.min(
112
115
  n / Math.max(e.widget.width, 1),
113
116
  a / Math.max(e.widget.height, 1)
@@ -122,11 +125,11 @@ function X(e) {
122
125
  frameHeight: e.frameHeight
123
126
  });
124
127
  }
125
- function p(e, t) {
128
+ function C(e, t) {
126
129
  return e.z_index !== t.z_index ? e.z_index - t.z_index : e.created_at_unix_ms !== t.created_at_unix_ms ? e.created_at_unix_ms - t.created_at_unix_ms : e.id.localeCompare(t.id);
127
130
  }
128
131
  function V(e) {
129
- const t = [...e].sort(p), r = /* @__PURE__ */ new Map();
132
+ const t = [...e].sort(C), r = /* @__PURE__ */ new Map();
130
133
  for (const [d, n] of t.entries())
131
134
  r.set(n.id, d + 1);
132
135
  return {
@@ -134,22 +137,22 @@ function V(e) {
134
137
  topRenderLayer: Math.max(t.length, 1)
135
138
  };
136
139
  }
137
- function B(e) {
140
+ function L(e) {
138
141
  const t = typeof window < "u" ? window.innerWidth : 1280, r = typeof window < "u" ? window.innerHeight : 800;
139
142
  let d = e.clientX, n = e.clientY;
140
143
  return d + e.menuWidth > t && (d = Math.max(0, t - e.menuWidth - 8)), n + e.menuHeight > r && (n = Math.max(0, r - e.menuHeight - 8)), { left: d, top: n };
141
144
  }
142
- function K(e) {
145
+ function Y(e) {
143
146
  return e.reduce((t, r) => Math.max(t, r.z_index), 1);
144
147
  }
145
- function U(e, t, r, d) {
148
+ function $(e, t, r, d) {
146
149
  const n = e.filter((o) => d[o.type]);
147
150
  if (n.length === 0) return null;
148
151
  if (!t) return n[0] ?? null;
149
152
  const a = n.find((o) => o.id === t);
150
153
  if (!a) return n[0] ?? null;
151
154
  const c = a.x + a.width / 2, i = a.y + a.height / 2;
152
- let h = null, m = 1 / 0;
155
+ let h = null, g = 1 / 0;
153
156
  for (const o of n) {
154
157
  if (o.id === t) continue;
155
158
  const s = o.x + o.width / 2 - c, l = o.y + o.height / 2 - i;
@@ -169,40 +172,40 @@ function U(e, t, r, d) {
169
172
  break;
170
173
  }
171
174
  if (!f) continue;
172
- const M = Math.sqrt(s * s + l * l), S = Math.atan2(
175
+ const S = Math.sqrt(s * s + l * l), k = Math.atan2(
173
176
  Math.abs(r === "up" || r === "down" ? s : l),
174
177
  Math.abs(r === "up" || r === "down" ? l : s)
175
- ), x = M * (1 + S * 1.5);
176
- x < m && (m = x, h = o);
178
+ ), x = S * (1 + k * 1.5);
179
+ x < g && (g = x, h = o);
177
180
  }
178
181
  return h;
179
182
  }
180
- function b(e, t = u, r = g) {
183
+ function M(e, t = m, r = u) {
181
184
  return Math.max(t, Math.min(r, e));
182
185
  }
183
- function L(e, t = 0) {
186
+ function j(e, t = 0) {
184
187
  return 16 + Math.max(1, e) * 32 + Math.max(0, t) * 9;
185
188
  }
186
189
  export {
187
- P as WORKBENCH_CANVAS_ZOOM_STEP,
188
- A as WORKBENCH_CONTEXT_MENU_WIDTH_PX,
189
- g as WORKBENCH_MAX_SCALE,
190
- u as WORKBENCH_MIN_SCALE,
191
- z as WORKBENCH_VIEWPORT_FIT_PADDING_PX,
192
- b as clampScale,
193
- B as createContextMenuPosition,
194
- I as createDefaultWorkbenchState,
195
- D as createWorkbenchId,
196
- N as createWorkbenchProjectedRect,
190
+ B as WORKBENCH_CANVAS_ZOOM_STEP,
191
+ K as WORKBENCH_CONTEXT_MENU_WIDTH_PX,
192
+ u as WORKBENCH_MAX_SCALE,
193
+ m as WORKBENCH_MIN_SCALE,
194
+ p as WORKBENCH_VIEWPORT_FIT_PADDING_PX,
195
+ M as clampScale,
196
+ L as createContextMenuPosition,
197
+ z as createDefaultWorkbenchState,
198
+ T as createWorkbenchId,
199
+ E as createWorkbenchProjectedRect,
197
200
  V as createWorkbenchRenderLayerMap,
198
201
  v as createWorkbenchViewportCenteredOnWidget,
199
- X as createWorkbenchViewportFitForWidget,
200
- R as createWorkbenchWidgetSurfaceMetrics,
201
- L as estimateContextMenuHeight,
202
- U as findNearestWidget,
203
- K as getTopZIndex,
204
- O as resolveWorkbenchWidgetRenderMode,
205
- F as sanitizeFilters,
206
- H as sanitizeViewport,
207
- T as sanitizeWorkbenchState
202
+ U as createWorkbenchViewportFitForWidget,
203
+ P as createWorkbenchWidgetSurfaceMetrics,
204
+ j as estimateContextMenuHeight,
205
+ $ as findNearestWidget,
206
+ Y as getTopZIndex,
207
+ A as resolveWorkbenchWidgetRenderMode,
208
+ I as sanitizeFilters,
209
+ F as sanitizeViewport,
210
+ X as sanitizeWorkbenchState
208
211
  };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Workbench theme catalog.
3
+ *
4
+ * Themes customise the canvas surface, atmosphere, grid, widget chrome,
5
+ * body treatment, dock, typography, and focus accent via `data-workbench-theme`
6
+ * on `.workbench-surface`. Theme-specific CSS overrides live in
7
+ * `workbench-themes.css`.
8
+ *
9
+ * The `default` theme is a no-op: it inherits the app's global theme tokens
10
+ * (`--background`, `--card`, `--border`, `--primary`, ...), so swapping to
11
+ * `default` reproduces the look before this theme system existed.
12
+ */
13
+ export declare const WORKBENCH_THEME_IDS: readonly ["default", "vibrancy", "mica", "midnight", "aurora", "terminal"];
14
+ export type WorkbenchThemeId = (typeof WORKBENCH_THEME_IDS)[number];
15
+ export interface WorkbenchThemePreview {
16
+ /** CSS value applied to the theme swatch's outer frame (represents canvas). */
17
+ canvas: string;
18
+ /** CSS value for the swatch's inner card (represents a widget). */
19
+ widget: string;
20
+ /** Solid CSS color for the selected/active indicator in the preview. */
21
+ accent: string;
22
+ }
23
+ export interface WorkbenchThemeMeta {
24
+ id: WorkbenchThemeId;
25
+ label: string;
26
+ description: string;
27
+ preview: WorkbenchThemePreview;
28
+ }
29
+ export declare const WORKBENCH_THEMES: readonly WorkbenchThemeMeta[];
30
+ export declare const DEFAULT_WORKBENCH_THEME: WorkbenchThemeId;
31
+ export declare function isWorkbenchThemeId(value: unknown): value is WorkbenchThemeId;
32
+ export declare function workbenchThemeMeta(id: WorkbenchThemeId): WorkbenchThemeMeta;