@floegence/floe-webapp-core 0.36.11 → 0.36.12

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.
@@ -1,44 +1,49 @@
1
- import { insert as a, createComponent as d, addEventListener as b, effect as v, className as f, setStyleProperty as m, template as l, delegateEvents as h } from "solid-js/web";
2
- import { For as x } from "solid-js";
3
- import { cn as k } from "../../utils/cn.js";
4
- var _ = /* @__PURE__ */ l("<div role=menu class=workbench-context-menu data-floe-workbench-boundary=true>"), p = /* @__PURE__ */ l("<div role=separator aria-orientation=horizontal class=workbench-context-menu__separator>"), w = /* @__PURE__ */ l("<button type=button role=menuitem><span class=workbench-context-menu__label>");
5
- function $(n) {
6
- return n.kind === "action";
1
+ import { spread as d, mergeProps as v, insert as a, createComponent as s, addEventListener as f, effect as b, className as _, template as c, delegateEvents as p } from "solid-js/web";
2
+ import { For as h } from "solid-js";
3
+ import { cn as x } from "../../utils/cn.js";
4
+ import { WORKBENCH_CONTEXT_MENU_ATTR as k } from "./workbenchContextMenuDismiss.js";
5
+ var w = /* @__PURE__ */ c("<div role=menu class=workbench-context-menu data-floe-workbench-boundary=true>"), C = /* @__PURE__ */ c("<div role=separator aria-orientation=horizontal class=workbench-context-menu__separator>"), $ = /* @__PURE__ */ c("<button type=button role=menuitem><span class=workbench-context-menu__label>");
6
+ function E(r) {
7
+ return r.kind === "action";
7
8
  }
8
- function E(n) {
9
+ function M(r) {
9
10
  return (() => {
10
- var r = _();
11
- return r.$$contextmenu = (e) => e.preventDefault(), a(r, d(x, {
11
+ var o = w();
12
+ return d(o, v({
13
+ [k]: "true"
14
+ }, {
15
+ get style() {
16
+ return {
17
+ left: `${r.x}px`,
18
+ top: `${r.y}px`
19
+ };
20
+ },
21
+ onContextMenu: (e) => e.preventDefault()
22
+ }), !1, !0), a(o, s(h, {
12
23
  get each() {
13
- return n.items;
24
+ return r.items;
14
25
  },
15
26
  children: (e) => {
16
- if (!$(e))
17
- return p();
18
- const c = e.icon;
27
+ if (!E(e))
28
+ return C();
29
+ const m = e.icon;
19
30
  return (() => {
20
- var t = w(), i = t.firstChild;
21
- return b(t, "click", e.onSelect, !0), a(t, d(c, {
31
+ var t = $(), l = t.firstChild;
32
+ return f(t, "click", e.onSelect, !0), a(t, s(m, {
22
33
  class: "h-3.5 w-3.5"
23
- }), i), a(i, () => e.label), v((o) => {
24
- var u = k("workbench-context-menu__item", e.destructive && "is-destructive"), s = e.disabled;
25
- return u !== o.e && f(t, o.e = u), s !== o.t && (t.disabled = o.t = s), o;
34
+ }), l), a(l, () => e.label), b((n) => {
35
+ var i = x("workbench-context-menu__item", e.destructive && "is-destructive"), u = e.disabled;
36
+ return i !== n.e && _(t, n.e = i), u !== n.t && (t.disabled = n.t = u), n;
26
37
  }, {
27
38
  e: void 0,
28
39
  t: void 0
29
40
  }), t;
30
41
  })();
31
42
  }
32
- })), v((e) => {
33
- var c = `${n.x}px`, t = `${n.y}px`;
34
- return c !== e.e && m(r, "left", e.e = c), t !== e.t && m(r, "top", e.t = t), e;
35
- }, {
36
- e: void 0,
37
- t: void 0
38
- }), r;
43
+ })), o;
39
44
  })();
40
45
  }
41
- h(["contextmenu", "click"]);
46
+ p(["click"]);
42
47
  export {
43
- E as WorkbenchContextMenu
48
+ M as WorkbenchContextMenu
44
49
  };
@@ -5,9 +5,12 @@ export interface WorkbenchSurfaceApi {
5
5
  worldX?: number;
6
6
  worldY?: number;
7
7
  }) => WorkbenchWidgetItem | null;
8
+ clearSelection: () => void;
8
9
  focusWidget: (widget: WorkbenchWidgetItem, options?: {
9
10
  centerViewport?: boolean;
10
11
  }) => WorkbenchWidgetItem;
12
+ fitWidget: (widget: WorkbenchWidgetItem) => WorkbenchWidgetItem;
13
+ overviewWidget: (widget: WorkbenchWidgetItem) => WorkbenchWidgetItem;
11
14
  findWidgetByType: (type: WorkbenchWidgetType) => WorkbenchWidgetItem | null;
12
15
  }
13
16
  export interface WorkbenchSurfaceProps {
@@ -1,42 +1,53 @@
1
- import { insert as c, createComponent as a, Portal as k, addEventListener as s, effect as p, className as b, template as m, delegateEvents as C } from "solid-js/web";
2
- import { createEffect as d, onCleanup as g, Show as W } from "solid-js";
3
- import { isTypingElement as A } from "../../utils/dom.js";
4
- import { WorkbenchCanvas as y } from "./WorkbenchCanvas.js";
1
+ import { insert as c, createComponent as a, Portal as h, addEventListener as p, effect as k, className as W, template as g, delegateEvents as b } from "solid-js/web";
2
+ import { createEffect as s, onCleanup as u, Show as C } from "solid-js";
3
+ import { isTypingElement as y } from "../../utils/dom.js";
4
+ import { WorkbenchCanvas as A } from "./WorkbenchCanvas.js";
5
5
  import { WorkbenchContextMenu as D } from "./WorkbenchContextMenu.js";
6
6
  import { WorkbenchFilterBar as x } from "./WorkbenchFilterBar.js";
7
7
  import { WorkbenchHud as S } from "./WorkbenchHud.js";
8
- import { WorkbenchLockButton as F } from "./WorkbenchLockButton.js";
9
- import { useWorkbenchModel as M } from "./useWorkbenchModel.js";
10
- var L = /* @__PURE__ */ m("<div class=workbench-menu-backdrop data-floe-workbench-boundary=true>"), R = /* @__PURE__ */ m("<div><div class=workbench-surface__body data-floe-workbench-canvas-frame=true>");
11
- const E = "F1";
12
- function U(i) {
13
- const e = M({
8
+ import { WorkbenchLockButton as M } from "./WorkbenchLockButton.js";
9
+ import { installWorkbenchContextMenuDismissListeners as F } from "./workbenchContextMenuDismiss.js";
10
+ import { useWorkbenchModel as L } from "./useWorkbenchModel.js";
11
+ var R = /* @__PURE__ */ g("<div class=workbench-menu-backdrop data-floe-workbench-boundary=true>"), E = /* @__PURE__ */ g("<div><div class=workbench-surface__body data-floe-workbench-canvas-frame=true>");
12
+ const _ = "F1";
13
+ function P(i) {
14
+ const e = L({
14
15
  state: () => i.state(),
15
16
  setState: (t) => i.setState(t),
16
17
  widgetDefinitions: () => i.widgetDefinitions,
17
18
  onClose: () => {
18
19
  }
19
20
  });
20
- d(() => {
21
+ s(() => {
21
22
  i.onApiReady?.({
22
23
  ensureWidget: (t, r) => e.widgetActions.ensureWidget(t, r) ?? null,
24
+ clearSelection: () => e.selection.clear(),
23
25
  focusWidget: (t, r) => e.navigation.focusWidget(t, r),
26
+ fitWidget: (t) => e.navigation.fitWidget(t),
27
+ overviewWidget: (t) => e.navigation.overviewWidget(t),
24
28
  findWidgetByType: (t) => e.queries.findWidgetByType(t)
25
- }), g(() => {
29
+ }), u(() => {
26
30
  i.onApiReady?.(null);
27
31
  });
28
32
  });
29
- const u = () => i.lockShortcut === void 0 ? E : i.lockShortcut;
30
- d(() => {
33
+ const d = () => i.lockShortcut === void 0 ? _ : i.lockShortcut;
34
+ s(() => {
35
+ if (typeof window > "u" || !e.contextMenu.state()) return;
36
+ const t = F({
37
+ ownerWindow: window,
38
+ onDismiss: e.contextMenu.close
39
+ });
40
+ u(() => t());
41
+ }), s(() => {
31
42
  if (i.enableKeyboard === !1 || typeof document > "u") return;
32
- const t = u(), r = (n) => {
43
+ const t = d(), r = (n) => {
33
44
  if (n.defaultPrevented || n.isComposing) return;
34
45
  if (t !== null && n.key === t) {
35
46
  n.preventDefault(), e.lock.toggle();
36
47
  return;
37
48
  }
38
49
  const o = n.target;
39
- if (!(o instanceof Element && A(o)))
50
+ if (!(o instanceof Element && y(o)))
40
51
  switch (n.key) {
41
52
  case "ArrowUp":
42
53
  n.preventDefault(), e.navigation.handleArrowNavigation("up");
@@ -56,26 +67,26 @@ function U(i) {
56
67
  break;
57
68
  }
58
69
  };
59
- document.addEventListener("keydown", r, !0), g(() => document.removeEventListener("keydown", r, !0));
70
+ document.addEventListener("keydown", r, !0), u(() => document.removeEventListener("keydown", r, !0));
60
71
  });
61
- const f = (t, r) => {
72
+ const m = (t, r) => {
62
73
  const n = document.querySelector('[data-floe-workbench-canvas-frame="true"]');
63
74
  if (!n) return null;
64
75
  const o = n.getBoundingClientRect();
65
76
  if (t < o.left || t > o.right || r < o.top || r > o.bottom)
66
77
  return null;
67
- const v = t - o.left, h = r - o.top, l = e.viewport();
78
+ const w = t - o.left, v = r - o.top, l = e.viewport();
68
79
  return {
69
- worldX: (v - l.x) / l.scale,
70
- worldY: (h - l.y) / l.scale
80
+ worldX: (w - l.x) / l.scale,
81
+ worldY: (v - l.y) / l.scale
71
82
  };
72
- }, w = (t, r, n) => {
73
- const o = f(r, n);
83
+ }, f = (t, r, n) => {
84
+ const o = m(r, n);
74
85
  o && e.widgetActions.addWidgetAtCursor(t, o.worldX, o.worldY);
75
86
  };
76
87
  return (() => {
77
- var t = R(), r = t.firstChild;
78
- return c(r, a(y, {
88
+ var t = E(), r = t.firstChild;
89
+ return c(r, a(A, {
79
90
  get widgetDefinitions() {
80
91
  return e.widgetDefinitions();
81
92
  },
@@ -130,7 +141,7 @@ function U(i) {
130
141
  get onRequestDelete() {
131
142
  return e.widgetActions.deleteWidget;
132
143
  }
133
- })), c(t, a(F, {
144
+ })), c(t, a(M, {
134
145
  get locked() {
135
146
  return e.locked();
136
147
  },
@@ -138,7 +149,7 @@ function U(i) {
138
149
  return e.lock.toggle;
139
150
  },
140
151
  get shortcutLabel() {
141
- return u() ?? void 0;
152
+ return d() ?? void 0;
142
153
  }
143
154
  }), null), c(t, a(x, {
144
155
  get widgetDefinitions() {
@@ -156,7 +167,7 @@ function U(i) {
156
167
  get onShowAll() {
157
168
  return e.filter.showAll;
158
169
  },
159
- onCreateAt: w
170
+ onCreateAt: f
160
171
  }), null), c(t, a(S, {
161
172
  get scaleLabel() {
162
173
  return e.scaleLabel();
@@ -167,16 +178,16 @@ function U(i) {
167
178
  get onZoomIn() {
168
179
  return e.hud.zoomIn;
169
180
  }
170
- }), null), c(t, a(W, {
181
+ }), null), c(t, a(C, {
171
182
  get when() {
172
183
  return e.contextMenu.state();
173
184
  },
174
185
  get children() {
175
- return a(k, {
186
+ return a(h, {
176
187
  get children() {
177
188
  return [(() => {
178
- var n = L();
179
- return s(n, "contextmenu", e.contextMenu.retarget, !0), s(n, "click", e.contextMenu.close, !0), n;
189
+ var n = R();
190
+ return p(n, "contextmenu", e.contextMenu.retarget, !0), n;
180
191
  })(), a(D, {
181
192
  get x() {
182
193
  return e.contextMenu.position()?.left ?? 0;
@@ -191,10 +202,10 @@ function U(i) {
191
202
  }
192
203
  });
193
204
  }
194
- }), null), p(() => b(t, `workbench-surface${i.class ? ` ${i.class}` : ""}`)), t;
205
+ }), null), k(() => W(t, `workbench-surface${i.class ? ` ${i.class}` : ""}`)), t;
195
206
  })();
196
207
  }
197
- C(["click", "contextmenu"]);
208
+ b(["contextmenu"]);
198
209
  export {
199
- U as WorkbenchSurface
210
+ P as WorkbenchSurface
200
211
  };
@@ -4,4 +4,4 @@ export { WorkbenchContextMenu, type WorkbenchContextMenuItem, type WorkbenchCont
4
4
  export { useWorkbenchModel, type UseWorkbenchModelOptions } from './useWorkbenchModel';
5
5
  export { WIDGET_REGISTRY, createWorkbenchFilterState, getWidgetEntry, isValidWorkbenchWidgetType, resolveWorkbenchWidgetDefinitions, type WidgetRegistryEntry, } from './widgets/widgetRegistry';
6
6
  export * from './types';
7
- export { sanitizeWorkbenchState, createDefaultWorkbenchState, createWorkbenchId, createWorkbenchProjectedRect, createWorkbenchRenderLayerMap, createWorkbenchWidgetSurfaceMetrics, resolveWorkbenchWidgetRenderMode, type WorkbenchRenderLayerMap, } from './workbenchHelpers';
7
+ export { sanitizeWorkbenchState, createDefaultWorkbenchState, createWorkbenchId, createWorkbenchProjectedRect, createWorkbenchRenderLayerMap, createWorkbenchViewportCenteredOnWidget, createWorkbenchViewportFitForWidget, createWorkbenchWidgetSurfaceMetrics, resolveWorkbenchWidgetRenderMode, type WorkbenchRenderLayerMap, } from './workbenchHelpers';
@@ -36,6 +36,7 @@ export declare function useWorkbenchModel(options: UseWorkbenchModelOptions): {
36
36
  openCanvasContextMenu: (event: InfiniteCanvasContextMenuEvent) => void;
37
37
  openWidgetContextMenu: (event: MouseEvent, item: WorkbenchWidgetItem) => void;
38
38
  selectWidget: (widgetId: string) => void;
39
+ clearSelection: () => void;
39
40
  startOptimisticFront: (widgetId: string) => void;
40
41
  commitFront: (widgetId: string) => void;
41
42
  commitMove: (widgetId: string, position: {
@@ -66,6 +67,11 @@ export declare function useWorkbenchModel(options: UseWorkbenchModelOptions): {
66
67
  focusWidget: (widget: WorkbenchWidgetItem, options?: {
67
68
  centerViewport?: boolean;
68
69
  }) => WorkbenchWidgetItem<WorkbenchWidgetType>;
70
+ fitWidget: (widget: WorkbenchWidgetItem) => WorkbenchWidgetItem<WorkbenchWidgetType>;
71
+ overviewWidget: (widget: WorkbenchWidgetItem) => WorkbenchWidgetItem<WorkbenchWidgetType>;
72
+ };
73
+ selection: {
74
+ clear: () => void;
69
75
  };
70
76
  widgetActions: {
71
77
  deleteSelected: () => void;
@@ -1,230 +1,252 @@
1
- import { createSignal as _, createMemo as d, onCleanup as mt } from "solid-js";
2
- import { ArrowUp as Wt, Copy as xt, Trash as St } from "../icons/index.js";
3
- import { getTopZIndex as Ct, createContextMenuPosition as pt, createWorkbenchId as kt, findNearestWidget as Ft, clampScale as Xt, WORKBENCH_CANVAS_ZOOM_STEP as Z, WORKBENCH_CONTEXT_MENU_WIDTH_PX as bt, estimateContextMenuHeight as Mt } from "./workbenchHelpers.js";
4
- import { resolveWorkbenchWidgetDefinitions as Yt, getWidgetEntry as $, createWorkbenchFilterState as yt } from "./widgets/widgetRegistry.js";
5
- function Nt(s) {
6
- const [m, W] = _(null), [j, A] = _(null), [D, K] = _({ width: 0, height: 0 });
7
- let r = null, x = null;
8
- const a = s.state, h = d(() => a().widgets), u = d(() => a().viewport), L = d(() => a().locked), T = d(() => a().filters), k = d(() => a().selectedWidgetId), F = d(() => Ct(h())), U = d(() => `${Math.round(u().scale * 100)}%`), G = () => typeof s.widgetDefinitions == "function" ? s.widgetDefinitions() : s.widgetDefinitions, f = d(
9
- () => Yt(G())
10
- ), X = (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 }, c = D();
12
- return c.width === n && c.height === i ? c : (K(o), o);
13
- }, N = () => {
14
- x?.disconnect(), x = null;
15
- }, w = () => r ? X(r.clientWidth, r.clientHeight) : X(0, 0), J = (t) => {
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())
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();
12
+ return s.width === n && s.height === i ? s : (G(o), o);
13
+ }, R = () => {
14
+ S?.disconnect(), S = null;
15
+ }, a = () => r ? I(r.clientWidth, r.clientHeight) : I(0, 0), et = (t) => {
16
16
  if (r === (t ?? null)) {
17
- w();
17
+ a();
18
18
  return;
19
19
  }
20
- N(), r = t ?? null, w(), !(!r || typeof ResizeObserver > "u") && (x = new ResizeObserver((e) => {
20
+ R(), r = t ?? null, a(), !(!r || typeof ResizeObserver > "u") && (S = new ResizeObserver((e) => {
21
21
  const n = e[0];
22
- X(
22
+ I(
23
23
  n?.contentRect.width ?? r?.clientWidth ?? 0,
24
24
  n?.contentRect.height ?? r?.clientHeight ?? 0
25
25
  );
26
- }), x.observe(r));
26
+ }), S.observe(r));
27
27
  };
28
- mt(() => {
29
- N(), r = null;
28
+ xt(() => {
29
+ R(), r = null;
30
30
  });
31
- const Q = (t) => {
32
- W({
31
+ const nt = (t) => {
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
- }, tt = (t, e) => {
39
- S(e.id), W({
38
+ }, it = (t, e) => {
39
+ f(e.id), x({
40
40
  clientX: t.clientX,
41
41
  clientY: t.clientY,
42
42
  worldX: e.x,
43
43
  worldY: e.y,
44
44
  widgetId: e.id
45
45
  });
46
- }, g = () => W(null), et = (t) => a().widgets.find((e) => e.id === t) ?? null, b = (t) => a().widgets.find((e) => e.type === t) ?? null, R = d(() => {
47
- const t = m();
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(() => {
47
+ const t = W();
48
48
  if (!t) return [];
49
49
  if (t.widgetId) {
50
- const e = h().find((i) => i.id === t.widgetId), n = [];
50
+ const e = w().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: Wt,
55
+ icon: St,
56
56
  onSelect: () => {
57
- S(e.id), g();
57
+ f(e.id), h();
58
58
  }
59
59
  }), n.push({
60
60
  id: "duplicate",
61
61
  kind: "action",
62
62
  label: "Duplicate",
63
- icon: xt,
63
+ icon: Ct,
64
64
  onSelect: () => {
65
- V(e.type, e.x + 32, e.y + 32), g();
65
+ E(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: St,
71
+ icon: pt,
72
72
  destructive: !0,
73
73
  onSelect: () => {
74
- t.widgetId && y(t.widgetId), g();
74
+ t.widgetId && Y(t.widgetId), h();
75
75
  }
76
76
  }), n;
77
77
  }
78
- return f().map((e) => ({
78
+ return m().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), g();
84
+ y(e.type, t.worldX, t.worldY), h();
85
85
  }
86
86
  }));
87
- }), nt = d(() => {
88
- const t = m();
87
+ }), ct = d(() => {
88
+ const t = W();
89
89
  if (!t) return;
90
- const e = R(), n = e.filter((o) => o.kind === "action").length, i = e.filter((o) => o.kind === "separator").length;
91
- return pt({
90
+ const e = T(), n = e.filter((o) => o.kind === "action").length, i = e.filter((o) => o.kind === "separator").length;
91
+ return Ft({
92
92
  clientX: t.clientX,
93
93
  clientY: t.clientY,
94
- menuWidth: bt,
95
- menuHeight: Mt(n, i)
94
+ menuWidth: Yt,
95
+ menuHeight: vt(n, i)
96
96
  });
97
- }), M = (t, e, n) => {
98
- const i = $(t, f()), o = i.singleton ? b(t) : null;
97
+ }), X = (t, e, n) => {
98
+ const i = j(t, m()), o = i.singleton ? M(t) : null;
99
99
  if (o)
100
- return C(o, { centerViewport: !0 });
101
- const c = i.defaultSize, l = {
102
- id: kt(),
100
+ return p(o, { centerViewport: !0 });
101
+ const s = i.defaultSize, g = {
102
+ id: bt(),
103
103
  type: t,
104
104
  title: i.defaultTitle,
105
105
  x: e,
106
106
  y: n,
107
- width: c.width,
108
- height: c.height,
109
- z_index: F() + 1,
107
+ width: s.width,
108
+ height: s.height,
109
+ z_index: b() + 1,
110
110
  created_at_unix_ms: Date.now()
111
111
  };
112
- return s.setState((p) => ({
113
- ...p,
114
- widgets: [...p.widgets, l],
115
- selectedWidgetId: l.id
116
- })), l;
117
- }, Y = (t, e, n) => {
118
- const i = $(t, f()).defaultSize;
119
- return M(t, e - i.width / 2, n - i.height / 2);
120
- }, V = (t, e, n) => M(t, e, n), y = (t) => {
121
- s.setState((e) => ({
112
+ return c.setState((k) => ({
113
+ ...k,
114
+ widgets: [...k.widgets, g],
115
+ selectedWidgetId: g.id
116
+ })), g;
117
+ }, y = (t, e, n) => {
118
+ const i = j(t, m()).defaultSize;
119
+ return X(t, e - i.width / 2, n - i.height / 2);
120
+ }, E = (t, e, n) => X(t, e, n), Y = (t) => {
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
- }, it = (t) => {
127
- A(t);
128
- }, S = (t) => {
129
- A(t);
130
- const e = F(), n = h().find((i) => i.id === t);
131
- n && n.z_index < e && s.setState((i) => ({
126
+ }, st = (t) => {
127
+ D(t);
128
+ }, f = (t) => {
129
+ D(t);
130
+ const e = b(), n = w().find((i) => i.id === t);
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
- }, ot = (t, e) => {
138
- s.setState((n) => ({
137
+ }, rt = (t, e) => {
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
- }, st = (t, e) => {
145
- s.setState((n) => ({
144
+ }, dt = (t, e) => {
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
- }, I = (t) => {
152
- s.setState((e) => ({ ...e, viewport: t }));
153
- }, H = (t) => {
154
- const e = u(), n = w(), i = (n.width / 2 - e.x) / e.scale, o = (n.height / 2 - e.y) / e.scale, c = Xt(
155
- t === "in" ? e.scale * Z : e.scale / Z
156
- ), l = {
157
- x: n.width / 2 - i * c,
158
- y: n.height / 2 - o * c,
159
- scale: c
151
+ }, v = (t) => {
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(
155
+ t === "in" ? e.scale * $ : e.scale / $
156
+ ), g = {
157
+ x: n.width / 2 - i * s,
158
+ y: n.height / 2 - o * s,
159
+ scale: s
160
160
  };
161
- I(l);
162
- }, ct = () => {
163
- s.setState((t) => ({ ...t, locked: !t.locked }));
164
- }, rt = (t) => {
165
- s.setState((e) => ({
161
+ v(g);
162
+ }, lt = () => {
163
+ c.setState((t) => ({ ...t, locked: !t.locked }));
164
+ }, at = (t) => {
165
+ c.setState((e) => ({
166
166
  ...e,
167
167
  filters: { ...e.filters, [t]: !e.filters[t] }
168
168
  }));
169
- }, dt = (t) => {
170
- s.setState((e) => {
169
+ }, gt = (t) => {
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
- }, lt = () => {
177
- const t = yt(f());
178
- s.setState((e) => ({
176
+ }, ut = () => {
177
+ const t = zt(m());
178
+ c.setState((e) => ({
179
179
  ...e,
180
180
  filters: t
181
181
  }));
182
- }, E = (t) => {
183
- s.setState((e) => ({ ...e, selectedWidgetId: t }));
184
- }, at = () => {
185
- const t = w(), e = u();
182
+ }, C = (t) => {
183
+ c.setState((e) => ({ ...e, selectedWidgetId: t }));
184
+ }, q = () => {
185
+ c.setState(
186
+ (t) => t.selectedWidgetId === null ? t : { ...t, selectedWidgetId: null }
187
+ );
188
+ }, ht = () => {
189
+ const t = a(), e = u();
186
190
  return {
187
191
  worldX: t.width > 0 ? (t.width / 2 - e.x) / e.scale : 240,
188
192
  worldY: t.height > 0 ? (t.height / 2 - e.y) / e.scale : 180
189
193
  };
190
194
  };
191
- let q = 0;
192
- const ut = (t, e, n) => {
193
- const i = u(), o = i.x, c = i.y, l = i.scale, p = performance.now(), gt = 360, ht = ++q, ft = (v) => 1 - Math.pow(1 - v, 3), B = (v) => {
194
- if (ht !== q) return;
195
- const wt = v - p, P = Math.min(Math.max(wt / gt, 0), 1), O = ft(P);
196
- I({
197
- x: o + (t - o) * O,
198
- y: c + (e - c) * O,
199
- scale: l + (n - l) * O
200
- }), P < 1 && requestAnimationFrame(B);
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({
201
+ x: n + (t.x - n) * A,
202
+ y: i + (t.y - i) * A,
203
+ scale: o + (t.scale - o) * A
204
+ }), K < 1 && requestAnimationFrame(Z);
201
205
  };
202
- requestAnimationFrame(B);
206
+ requestAnimationFrame(Z);
203
207
  }, z = (t) => {
204
- const e = w();
205
- if (e.width === 0 || e.height === 0) return;
206
- const n = u(), i = e.width / 2 - (t.x + t.width / 2) * n.scale, o = e.height / 2 - (t.y + t.height / 2) * n.scale;
207
- ut(i, o, n.scale);
208
- }, C = (t, e = {}) => (E(t.id), S(t.id), e.centerViewport !== !1 && z(t), t);
208
+ const e = a();
209
+ e.width === 0 || e.height === 0 || O(L({
210
+ widget: t,
211
+ scale: u().scale,
212
+ frameWidth: e.width,
213
+ frameHeight: e.height
214
+ }));
215
+ }, ft = (t) => {
216
+ const e = a();
217
+ e.width === 0 || e.height === 0 || O(yt({
218
+ widget: t,
219
+ frameWidth: e.width,
220
+ frameHeight: e.height
221
+ }));
222
+ }, wt = (t) => {
223
+ const e = a();
224
+ e.width === 0 || e.height === 0 || O(L({
225
+ widget: t,
226
+ scale: Xt,
227
+ frameWidth: e.width,
228
+ frameHeight: e.height
229
+ }));
230
+ }, p = (t, e = {}) => (C(t.id), f(t.id), e.centerViewport !== !1 && z(t), t);
209
231
  return {
210
- widgets: h,
232
+ widgets: w,
211
233
  viewport: u,
212
- canvasFrameSize: D,
213
- locked: L,
214
- filters: T,
215
- selectedWidgetId: k,
216
- topZIndex: F,
217
- scaleLabel: U,
218
- optimisticFrontWidgetId: j,
219
- widgetDefinitions: f,
220
- setCanvasFrameRef: J,
234
+ canvasFrameSize: H,
235
+ locked: J,
236
+ filters: N,
237
+ selectedWidgetId: F,
238
+ topZIndex: b,
239
+ scaleLabel: Q,
240
+ optimisticFrontWidgetId: U,
241
+ widgetDefinitions: m,
242
+ setCanvasFrameRef: et,
221
243
  contextMenu: {
222
- state: m,
223
- items: R,
224
- position: nt,
225
- close: g,
244
+ state: W,
245
+ items: T,
246
+ position: ct,
247
+ close: h,
226
248
  retarget: (t) => {
227
- t.preventDefault(), t.stopPropagation(), W({
249
+ t.preventDefault(), t.stopPropagation(), x({
228
250
  clientX: t.clientX,
229
251
  clientY: t.clientY,
230
252
  worldX: 0,
@@ -233,54 +255,60 @@ function Nt(s) {
233
255
  }
234
256
  },
235
257
  canvas: {
236
- openCanvasContextMenu: Q,
237
- openWidgetContextMenu: tt,
238
- selectWidget: E,
239
- startOptimisticFront: it,
240
- commitFront: S,
241
- commitMove: ot,
242
- commitResize: st,
243
- commitViewport: I
258
+ openCanvasContextMenu: nt,
259
+ openWidgetContextMenu: it,
260
+ selectWidget: C,
261
+ clearSelection: q,
262
+ startOptimisticFront: st,
263
+ commitFront: f,
264
+ commitMove: rt,
265
+ commitResize: dt,
266
+ commitViewport: v
244
267
  },
245
268
  hud: {
246
- zoomIn: () => H("in"),
247
- zoomOut: () => H("out")
269
+ zoomIn: () => B("in"),
270
+ zoomOut: () => B("out")
248
271
  },
249
272
  lock: {
250
- toggle: ct
273
+ toggle: lt
251
274
  },
252
275
  filter: {
253
- toggle: rt,
254
- solo: dt,
255
- showAll: lt
276
+ toggle: at,
277
+ solo: gt,
278
+ showAll: ut
256
279
  },
257
280
  navigation: {
258
281
  handleArrowNavigation: (t) => {
259
- const e = Ft(
260
- h(),
261
- k(),
282
+ const e = It(
283
+ w(),
284
+ F(),
262
285
  t,
263
- T()
286
+ N()
264
287
  );
265
- e && C(e);
288
+ e && p(e);
266
289
  },
267
290
  centerOnWidget: z,
268
- focusWidget: C
291
+ 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)
294
+ },
295
+ selection: {
296
+ clear: q
269
297
  },
270
298
  widgetActions: {
271
299
  deleteSelected: () => {
272
- const t = k();
273
- t && y(t);
300
+ const t = F();
301
+ t && Y(t);
274
302
  },
275
- deleteWidget: y,
276
- addWidget: M,
277
- addWidgetAtCursor: Y,
278
- addWidgetCentered: V,
303
+ deleteWidget: Y,
304
+ addWidget: X,
305
+ addWidgetAtCursor: y,
306
+ addWidgetCentered: E,
279
307
  ensureWidget: (t, e) => {
280
- const n = b(t);
308
+ const n = M(t);
281
309
  if (n)
282
- return C(n, { centerViewport: e?.centerViewport ?? !0 });
283
- const i = at(), o = Y(
310
+ return p(n, { centerViewport: e?.centerViewport ?? !0 });
311
+ const i = ht(), o = y(
284
312
  t,
285
313
  e?.worldX ?? i.worldX,
286
314
  e?.worldY ?? i.worldY
@@ -289,18 +317,18 @@ function Nt(s) {
289
317
  }
290
318
  },
291
319
  queries: {
292
- findWidgetByType: b,
293
- findWidgetById: et
320
+ findWidgetByType: M,
321
+ findWidgetById: ot
294
322
  },
295
323
  handleCloseRequest: () => {
296
- if (m()) {
297
- g();
324
+ if (W()) {
325
+ h();
298
326
  return;
299
327
  }
300
- s.onClose();
328
+ c.onClose();
301
329
  }
302
330
  };
303
331
  }
304
332
  export {
305
- Nt as useWorkbenchModel
333
+ qt as useWorkbenchModel
306
334
  };
@@ -0,0 +1,5 @@
1
+ export declare const WORKBENCH_CONTEXT_MENU_ATTR = "data-floe-workbench-context-menu";
2
+ export declare function installWorkbenchContextMenuDismissListeners(options: {
3
+ ownerWindow: Window;
4
+ onDismiss: () => void;
5
+ }): () => void;
@@ -0,0 +1,29 @@
1
+ const i = "data-floe-workbench-context-menu";
2
+ function s(e) {
3
+ return !e || typeof e != "object" ? !1 : e.dataset?.floeWorkbenchContextMenu === "true";
4
+ }
5
+ function d(e) {
6
+ if (typeof e.composedPath == "function") {
7
+ for (const t of e.composedPath())
8
+ if (s(t))
9
+ return !0;
10
+ }
11
+ const n = e.target;
12
+ return typeof Element < "u" && n instanceof Element ? n.closest(`[${i}="true"]`) !== null : !1;
13
+ }
14
+ function c(e) {
15
+ const n = (o) => {
16
+ d(o) || e.onDismiss();
17
+ }, t = (o) => {
18
+ o.key === "Escape" && e.onDismiss();
19
+ }, r = () => {
20
+ e.onDismiss();
21
+ };
22
+ return e.ownerWindow.addEventListener("pointerdown", n, !0), e.ownerWindow.addEventListener("keydown", t, !0), e.ownerWindow.addEventListener("resize", r), e.ownerWindow.addEventListener("scroll", r, !0), () => {
23
+ e.ownerWindow.removeEventListener("pointerdown", n, !0), e.ownerWindow.removeEventListener("keydown", t, !0), e.ownerWindow.removeEventListener("resize", r), e.ownerWindow.removeEventListener("scroll", r, !0);
24
+ };
25
+ }
26
+ export {
27
+ i as WORKBENCH_CONTEXT_MENU_ATTR,
28
+ c as installWorkbenchContextMenuDismissListeners
29
+ };
@@ -23,6 +23,23 @@ export declare function sanitizeWorkbenchState(input: unknown, options?: Sanitiz
23
23
  export declare function createDefaultWorkbenchState(widgetDefinitions?: readonly WorkbenchWidgetDefinition[]): WorkbenchState;
24
24
  export declare const WORKBENCH_CANVAS_ZOOM_STEP = 1.18;
25
25
  export declare const WORKBENCH_CONTEXT_MENU_WIDTH_PX = 200;
26
+ export declare const WORKBENCH_MIN_SCALE = 0.45;
27
+ export declare const WORKBENCH_MAX_SCALE = 2.2;
28
+ export declare const WORKBENCH_VIEWPORT_FIT_PADDING_PX = 48;
29
+ export declare function createWorkbenchViewportCenteredOnWidget(options: {
30
+ widget: WorkbenchWidgetItem;
31
+ scale: number;
32
+ frameWidth: number;
33
+ frameHeight: number;
34
+ }): WorkbenchViewport;
35
+ export declare function createWorkbenchViewportFitForWidget(options: {
36
+ widget: WorkbenchWidgetItem;
37
+ frameWidth: number;
38
+ frameHeight: number;
39
+ minScale?: number;
40
+ maxScale?: number;
41
+ paddingPx?: number;
42
+ }): WorkbenchViewport;
26
43
  export interface WorkbenchRenderLayerMap {
27
44
  byWidgetId: ReadonlyMap<string, number>;
28
45
  topRenderLayer: number;
@@ -1,13 +1,13 @@
1
- import { DEFAULT_WORKBENCH_VIEWPORT as g } from "./types.js";
2
- import { resolveWorkbenchWidgetDefinitions as m, getWidgetEntry as x, createWorkbenchFilterState as _, isValidWorkbenchWidgetType as w } from "./widgets/widgetRegistry.js";
3
- function v() {
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() {
4
4
  const e = globalThis.crypto;
5
5
  return e && typeof e.randomUUID == "function" ? `wb-${e.randomUUID()}` : `wb-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
6
6
  }
7
- function I(e) {
7
+ function O(e) {
8
8
  return e.renderMode ?? "canvas_scaled";
9
9
  }
10
- function p(e) {
10
+ function N(e) {
11
11
  const t = Number.isFinite(e.viewport.scale) && e.viewport.scale > 0 ? e.viewport.scale : 1;
12
12
  return {
13
13
  widgetId: e.widgetId,
@@ -22,30 +22,30 @@ function p(e) {
22
22
  viewportScale: t
23
23
  };
24
24
  }
25
- function H(e) {
25
+ function R(e) {
26
26
  return {
27
27
  ready: e.ready,
28
- rect: p(e)
28
+ rect: N(e)
29
29
  };
30
30
  }
31
- function M(e) {
31
+ function H(e) {
32
32
  return e ? {
33
33
  x: Number.isFinite(e.x) ? e.x : 0,
34
34
  y: Number.isFinite(e.y) ? e.y : 0,
35
35
  scale: Number.isFinite(e.scale) && e.scale > 0 ? e.scale : 1
36
- } : { ...g };
36
+ } : { ...y };
37
37
  }
38
- function k(e, t) {
39
- return _(t, e);
38
+ function F(e, t) {
39
+ return w(t, e);
40
40
  }
41
- function D(e, t = {}) {
42
- const r = m(t.widgetDefinitions), d = t.createFallbackState ?? (() => S(r)), n = e;
41
+ function T(e, t = {}) {
42
+ const r = _(t.widgetDefinitions), d = t.createFallbackState ?? (() => I(r)), n = e;
43
43
  if (!n || n.version !== 1 || !Array.isArray(n.widgets))
44
44
  return d();
45
- const o = n.widgets.filter(
46
- (i) => !!i && typeof i.id == "string" && w(i.type, r) && typeof i.title == "string"
45
+ const a = n.widgets.filter(
46
+ (i) => !!i && typeof i.id == "string" && k(i.type, r) && typeof i.title == "string"
47
47
  ).map((i) => {
48
- const h = x(i.type, r);
48
+ const h = W(i.type, r);
49
49
  return {
50
50
  id: i.id,
51
51
  type: i.type,
@@ -57,52 +57,76 @@ function D(e, t = {}) {
57
57
  z_index: Number.isFinite(i.z_index) && i.z_index >= 0 ? i.z_index : 1,
58
58
  created_at_unix_ms: Number.isFinite(i.created_at_unix_ms) ? i.created_at_unix_ms : Date.now()
59
59
  };
60
- }), a = typeof n.selectedWidgetId == "string" && o.some((i) => i.id === n.selectedWidgetId) ? n.selectedWidgetId : null;
60
+ }), c = typeof n.selectedWidgetId == "string" && a.some((i) => i.id === n.selectedWidgetId) ? n.selectedWidgetId : null;
61
61
  return {
62
62
  version: 1,
63
- widgets: o,
64
- viewport: M(n.viewport),
63
+ widgets: a,
64
+ viewport: H(n.viewport),
65
65
  locked: typeof n.locked == "boolean" ? n.locked : !1,
66
- filters: k(n.filters, r),
67
- selectedWidgetId: a
66
+ filters: F(n.filters, r),
67
+ selectedWidgetId: c
68
68
  };
69
69
  }
70
- function S(e) {
71
- const t = m(e), r = Date.now(), d = [
70
+ function I(e) {
71
+ const t = _(e), r = Date.now(), d = [
72
72
  { type: "terminal", title: "dev · terminal", x: 80, y: 80 },
73
73
  { type: "file-browser", title: "project · files", x: 600, y: 80 },
74
74
  { type: "system-monitor", title: "host · system monitor", x: 80, y: 420 },
75
75
  { type: "log-viewer", title: "services · logs", x: 540, y: 500 },
76
76
  { type: "code-editor", title: "Counter.tsx", x: 1e3, y: 180 }
77
- ], n = d.filter((o) => t.some((a) => a.type === o.type)).map((o, a) => {
78
- const i = x(o.type, t);
77
+ ], n = d.filter((a) => t.some((c) => c.type === a.type)).map((a, c) => {
78
+ const i = W(a.type, t);
79
79
  return {
80
- id: `wb-seed-${a + 1}`,
81
- type: o.type,
82
- title: o.title,
83
- x: o.x,
84
- y: o.y,
80
+ id: `wb-seed-${c + 1}`,
81
+ type: a.type,
82
+ title: a.title,
83
+ x: a.x,
84
+ y: a.y,
85
85
  width: i.defaultSize.width,
86
86
  height: i.defaultSize.height,
87
- z_index: a + 1,
88
- created_at_unix_ms: r - (d.length - a) * 6e5
87
+ z_index: c + 1,
88
+ created_at_unix_ms: r - (d.length - c) * 6e5
89
89
  };
90
90
  });
91
91
  return {
92
92
  version: 1,
93
93
  widgets: n,
94
- viewport: { ...g },
94
+ viewport: { ...y },
95
95
  locked: !1,
96
- filters: _(t),
96
+ filters: w(t),
97
97
  selectedWidgetId: n[0]?.id ?? null
98
98
  };
99
99
  }
100
- const C = 1.18, E = 200;
101
- function z(e, t) {
100
+ const P = 1.18, A = 200, u = 0.45, g = 2.2, z = 48;
101
+ function v(e) {
102
+ const t = b(e.scale, u, g);
103
+ return {
104
+ x: e.frameWidth / 2 - (e.widget.x + e.widget.width / 2) * t,
105
+ y: e.frameHeight / 2 - (e.widget.y + e.widget.height / 2) * t,
106
+ scale: t
107
+ };
108
+ }
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(
111
+ Math.min(
112
+ n / Math.max(e.widget.width, 1),
113
+ a / Math.max(e.widget.height, 1)
114
+ ),
115
+ t,
116
+ r
117
+ );
118
+ return v({
119
+ widget: e.widget,
120
+ scale: c,
121
+ frameWidth: e.frameWidth,
122
+ frameHeight: e.frameHeight
123
+ });
124
+ }
125
+ function p(e, t) {
102
126
  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);
103
127
  }
104
- function R(e) {
105
- const t = [...e].sort(z), r = /* @__PURE__ */ new Map();
128
+ function V(e) {
129
+ const t = [...e].sort(p), r = /* @__PURE__ */ new Map();
106
130
  for (const [d, n] of t.entries())
107
131
  r.set(n.id, d + 1);
108
132
  return {
@@ -110,70 +134,75 @@ function R(e) {
110
134
  topRenderLayer: Math.max(t.length, 1)
111
135
  };
112
136
  }
113
- function T(e) {
137
+ function B(e) {
114
138
  const t = typeof window < "u" ? window.innerWidth : 1280, r = typeof window < "u" ? window.innerHeight : 800;
115
139
  let d = e.clientX, n = e.clientY;
116
140
  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 };
117
141
  }
118
- function O(e) {
142
+ function K(e) {
119
143
  return e.reduce((t, r) => Math.max(t, r.z_index), 1);
120
144
  }
121
- function X(e, t, r, d) {
122
- const n = e.filter((c) => d[c.type]);
145
+ function U(e, t, r, d) {
146
+ const n = e.filter((o) => d[o.type]);
123
147
  if (n.length === 0) return null;
124
148
  if (!t) return n[0] ?? null;
125
- const o = n.find((c) => c.id === t);
126
- if (!o) return n[0] ?? null;
127
- const a = o.x + o.width / 2, i = o.y + o.height / 2;
128
- let h = null, f = 1 / 0;
129
- for (const c of n) {
130
- if (c.id === t) continue;
131
- const s = c.x + c.width / 2 - a, l = c.y + c.height / 2 - i;
132
- let u = !1;
149
+ const a = n.find((o) => o.id === t);
150
+ if (!a) return n[0] ?? null;
151
+ const c = a.x + a.width / 2, i = a.y + a.height / 2;
152
+ let h = null, m = 1 / 0;
153
+ for (const o of n) {
154
+ if (o.id === t) continue;
155
+ const s = o.x + o.width / 2 - c, l = o.y + o.height / 2 - i;
156
+ let f = !1;
133
157
  switch (r) {
134
158
  case "up":
135
- u = l < -10;
159
+ f = l < -10;
136
160
  break;
137
161
  case "down":
138
- u = l > 10;
162
+ f = l > 10;
139
163
  break;
140
164
  case "left":
141
- u = s < -10;
165
+ f = s < -10;
142
166
  break;
143
167
  case "right":
144
- u = s > 10;
168
+ f = s > 10;
145
169
  break;
146
170
  }
147
- if (!u) continue;
148
- const b = Math.sqrt(s * s + l * l), W = Math.atan2(
171
+ if (!f) continue;
172
+ const M = Math.sqrt(s * s + l * l), S = Math.atan2(
149
173
  Math.abs(r === "up" || r === "down" ? s : l),
150
174
  Math.abs(r === "up" || r === "down" ? l : s)
151
- ), y = b * (1 + W * 1.5);
152
- y < f && (f = y, h = c);
175
+ ), x = M * (1 + S * 1.5);
176
+ x < m && (m = x, h = o);
153
177
  }
154
178
  return h;
155
179
  }
156
- function U(e, t = 0.45, r = 2.2) {
180
+ function b(e, t = u, r = g) {
157
181
  return Math.max(t, Math.min(r, e));
158
182
  }
159
- function A(e, t = 0) {
183
+ function L(e, t = 0) {
160
184
  return 16 + Math.max(1, e) * 32 + Math.max(0, t) * 9;
161
185
  }
162
186
  export {
163
- C as WORKBENCH_CANVAS_ZOOM_STEP,
164
- E as WORKBENCH_CONTEXT_MENU_WIDTH_PX,
165
- U as clampScale,
166
- T as createContextMenuPosition,
167
- S as createDefaultWorkbenchState,
168
- v as createWorkbenchId,
169
- p as createWorkbenchProjectedRect,
170
- R as createWorkbenchRenderLayerMap,
171
- H as createWorkbenchWidgetSurfaceMetrics,
172
- A as estimateContextMenuHeight,
173
- X as findNearestWidget,
174
- O as getTopZIndex,
175
- I as resolveWorkbenchWidgetRenderMode,
176
- k as sanitizeFilters,
177
- M as sanitizeViewport,
178
- D as sanitizeWorkbenchState
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,
197
+ V as createWorkbenchRenderLayerMap,
198
+ 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
179
208
  };
package/dist/workbench.js CHANGED
@@ -1,27 +1,29 @@
1
- import { DEFAULT_WORKBENCH_VIEWPORT as o, WORKBENCH_WIDGET_TYPES as t } from "./components/workbench/types.js";
2
- import { WIDGET_REGISTRY as W, createWorkbenchFilterState as n, getWidgetEntry as a, isValidWorkbenchWidgetType as b, resolveWorkbenchWidgetDefinitions as h } from "./components/workbench/widgets/widgetRegistry.js";
1
+ import { DEFAULT_WORKBENCH_VIEWPORT as t, WORKBENCH_WIDGET_TYPES as o } from "./components/workbench/types.js";
2
+ import { WIDGET_REGISTRY as W, createWorkbenchFilterState as n, getWidgetEntry as a, isValidWorkbenchWidgetType as i, resolveWorkbenchWidgetDefinitions as b } from "./components/workbench/widgets/widgetRegistry.js";
3
3
  import { WorkbenchContextMenu as k } from "./components/workbench/WorkbenchContextMenu.js";
4
4
  import { WorkbenchOverlay as f } from "./components/workbench/WorkbenchOverlay.js";
5
5
  import { WorkbenchSurface as E } from "./components/workbench/WorkbenchSurface.js";
6
- import { createDefaultWorkbenchState as R, createWorkbenchId as l, createWorkbenchProjectedRect as m, createWorkbenchRenderLayerMap as s, createWorkbenchWidgetSurfaceMetrics as S, resolveWorkbenchWidgetRenderMode as T, sanitizeWorkbenchState as g } from "./components/workbench/workbenchHelpers.js";
7
- import { useWorkbenchModel as D } from "./components/workbench/useWorkbenchModel.js";
6
+ import { createDefaultWorkbenchState as x, createWorkbenchId as R, createWorkbenchProjectedRect as l, createWorkbenchRenderLayerMap as m, createWorkbenchViewportCenteredOnWidget as s, createWorkbenchViewportFitForWidget as S, createWorkbenchWidgetSurfaceMetrics as T, resolveWorkbenchWidgetRenderMode as u, sanitizeWorkbenchState as D } from "./components/workbench/workbenchHelpers.js";
7
+ import { useWorkbenchModel as M } from "./components/workbench/useWorkbenchModel.js";
8
8
  export {
9
- o as DEFAULT_WORKBENCH_VIEWPORT,
9
+ t as DEFAULT_WORKBENCH_VIEWPORT,
10
10
  W as WIDGET_REGISTRY,
11
- t as WORKBENCH_WIDGET_TYPES,
11
+ o as WORKBENCH_WIDGET_TYPES,
12
12
  k as WorkbenchContextMenu,
13
13
  f as WorkbenchOverlay,
14
14
  E as WorkbenchSurface,
15
- R as createDefaultWorkbenchState,
15
+ x as createDefaultWorkbenchState,
16
16
  n as createWorkbenchFilterState,
17
- l as createWorkbenchId,
18
- m as createWorkbenchProjectedRect,
19
- s as createWorkbenchRenderLayerMap,
20
- S as createWorkbenchWidgetSurfaceMetrics,
17
+ R as createWorkbenchId,
18
+ l as createWorkbenchProjectedRect,
19
+ m as createWorkbenchRenderLayerMap,
20
+ s as createWorkbenchViewportCenteredOnWidget,
21
+ S as createWorkbenchViewportFitForWidget,
22
+ T as createWorkbenchWidgetSurfaceMetrics,
21
23
  a as getWidgetEntry,
22
- b as isValidWorkbenchWidgetType,
23
- h as resolveWorkbenchWidgetDefinitions,
24
- T as resolveWorkbenchWidgetRenderMode,
25
- g as sanitizeWorkbenchState,
26
- D as useWorkbenchModel
24
+ i as isValidWorkbenchWidgetType,
25
+ b as resolveWorkbenchWidgetDefinitions,
26
+ u as resolveWorkbenchWidgetRenderMode,
27
+ D as sanitizeWorkbenchState,
28
+ M as useWorkbenchModel
27
29
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/floe-webapp-core",
3
- "version": "0.36.11",
3
+ "version": "0.36.12",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",