@floegence/floe-webapp-core 0.40.5 → 0.40.6

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,4 +1,4 @@
1
- import { type JSX } from 'solid-js';
1
+ import { type Component, type JSX } from 'solid-js';
2
2
  import { type WorkbenchEdgeAutoPanFrame } from './workbenchEdgeAutoPan';
3
3
  import type { WorkbenchDockToolId, WorkbenchInteractionMode, WorkbenchViewport, WorkbenchWidgetDefinition, WorkbenchWidgetItem, WorkbenchWidgetType } from './types';
4
4
  export interface WorkbenchFilterBarProps {
@@ -9,17 +9,38 @@ export interface WorkbenchFilterBarProps {
9
9
  /** Solo a single dock component in the supplied mode scope; soloing it again shows the full scope. */
10
10
  onSoloFilter: (id: string, scope: readonly string[]) => void;
11
11
  onSelectMode?: (mode: WorkbenchInteractionMode) => void;
12
+ dockActions?: readonly WorkbenchDockAction[];
12
13
  /**
13
14
  * Called when the user drags a widget pill onto the canvas to create a
14
15
  * new widget of that type. Coordinates are in client space (clientX/Y).
15
16
  */
16
17
  onCreateAt?: (type: WorkbenchWidgetType, clientX: number, clientY: number, context?: WorkbenchDockDropContext) => void;
17
18
  onCreateToolAt?: (tool: WorkbenchDockToolId, clientX: number, clientY: number, context?: WorkbenchDockDropContext) => void;
19
+ /**
20
+ * Handles a plain click on a dock item. Return true when the host consumed
21
+ * the click and the default filter-solo behavior should be skipped.
22
+ */
23
+ onItemClick?: (item: WorkbenchDockItemActivation) => boolean | void;
18
24
  onDragPreviewChange?: (preview: WorkbenchDockDragPreview | null) => void;
19
25
  viewport?: WorkbenchViewport;
20
26
  onViewportCommit?: (viewport: WorkbenchViewport) => void;
21
27
  onViewportInteractionStart?: (kind: 'pan') => void;
22
28
  }
29
+ export type WorkbenchDockAction = Readonly<{
30
+ id: string;
31
+ label: string;
32
+ icon: Component<{
33
+ class?: string;
34
+ }>;
35
+ active?: boolean;
36
+ onActivate: (trigger: HTMLButtonElement) => void;
37
+ }>;
38
+ export type WorkbenchDockItemActivation = Readonly<{
39
+ kind: 'widget' | 'tool';
40
+ id: WorkbenchWidgetType | WorkbenchDockToolId;
41
+ label: string;
42
+ trigger: HTMLButtonElement;
43
+ }>;
23
44
  export type WorkbenchDockDragPreview = Readonly<{
24
45
  kind: 'widget' | 'tool';
25
46
  id: WorkbenchWidgetType | WorkbenchDockToolId;
@@ -1,69 +1,69 @@
1
- import { insert as w, createComponent as g, effect as P, setAttribute as T, memo as me, template as $, Portal as he, setStyleProperty as ke, use as be, delegateEvents as we } from "solid-js/web";
2
- import { createSignal as H, onCleanup as J, createEffect as Q, createMemo as B, Show as K, For as Z } from "solid-js";
3
- import { Motion as F } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.11/node_modules/solid-motionone/dist/index.js";
4
- import { easing as A, duration as X } from "../../utils/animations.js";
5
- import { Plus as _e } from "../icons/index.js";
6
- import { startHotInteraction as Ee } from "../../utils/hotInteraction.js";
7
- import { startPointerSession as Ce } from "../ui/pointerSession.js";
8
- import { WORKBENCH_EDGE_AUTO_PAN_FRAME_SELECTOR as oe, frameFromElement as ie, createWorkbenchEdgeAutoPanController as Se } from "./workbenchEdgeAutoPan.js";
9
- import { DockLayoutDashboard as pe, DockLayers as De, DockRegion as Oe, DockText as Me, DockMessageSquare as Le } from "../icons/DockIcons.js";
10
- var ye = /* @__PURE__ */ $("<button type=button class=workbench-dock__item>"), $e = /* @__PURE__ */ $('<div class=workbench-dock__mode-popover role=menu aria-label="Canvas mode">'), Ie = /* @__PURE__ */ $('<div class=workbench-dock data-floe-canvas-interactive=true><div class=workbench-dock__mode-switcher><button type=button class="workbench-dock__item workbench-dock__mode-trigger"aria-label="Switch canvas mode"aria-haspopup=menu></button></div><span class=workbench-dock__divider aria-hidden=true>'), Pe = /* @__PURE__ */ $("<button type=button class=workbench-dock__mode-option role=menuitemradio><span class=workbench-dock__mode-option-icon></span><span class=workbench-dock__mode-option-copy><span class=workbench-dock__mode-option-label></span><span class=workbench-dock__mode-option-description>"), Te = /* @__PURE__ */ $("<div class=workbench-dock-ghost aria-hidden=true><div class=workbench-dock-ghost__halo></div><div class=workbench-dock-ghost__card><div class=workbench-dock-ghost__icon></div><div class=workbench-dock-ghost__copy><div class=workbench-dock-ghost__title></div><div class=workbench-dock-ghost__hint><span>Drag onto canvas");
11
- const ee = 5, Fe = ".workbench-dock", W = [{
1
+ import { insert as h, createComponent as s, effect as X, setAttribute as L, memo as be, template as T, addEventListener as ee, Portal as _e, setStyleProperty as we, use as Ee, delegateEvents as Ce } from "solid-js/web";
2
+ import { createSignal as K, onCleanup as te, createEffect as ne, createMemo as R, Show as p, For as N } from "solid-js";
3
+ import { Motion as I } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.11/node_modules/solid-motionone/dist/index.js";
4
+ import { easing as $, duration as P } from "../../utils/animations.js";
5
+ import { Plus as Oe } from "../icons/index.js";
6
+ import { startHotInteraction as Se } from "../../utils/hotInteraction.js";
7
+ import { startPointerSession as De } from "../ui/pointerSession.js";
8
+ import { WORKBENCH_EDGE_AUTO_PAN_FRAME_SELECTOR as ae, frameFromElement as ce, createWorkbenchEdgeAutoPanController as Le } from "./workbenchEdgeAutoPan.js";
9
+ import { DockLayoutDashboard as ye, DockLayers as Me, DockRegion as Ie, DockText as $e, DockMessageSquare as Pe } from "../icons/DockIcons.js";
10
+ var Te = /* @__PURE__ */ T("<button type=button class=workbench-dock__item>"), Ae = /* @__PURE__ */ T('<button type=button class="workbench-dock__item workbench-dock__action">'), Fe = /* @__PURE__ */ T('<div class=workbench-dock__mode-popover role=menu aria-label="Canvas mode">'), Xe = /* @__PURE__ */ T('<div class=workbench-dock data-floe-canvas-interactive=true><div class=workbench-dock__mode-switcher><button type=button class="workbench-dock__item workbench-dock__mode-trigger"aria-label="Switch canvas mode"aria-haspopup=menu></button></div><span class=workbench-dock__divider aria-hidden=true>'), xe = /* @__PURE__ */ T("<button type=button class=workbench-dock__mode-option role=menuitemradio><span class=workbench-dock__mode-option-icon></span><span class=workbench-dock__mode-option-copy><span class=workbench-dock__mode-option-label></span><span class=workbench-dock__mode-option-description>"), Ye = /* @__PURE__ */ T("<div class=workbench-dock-ghost aria-hidden=true><div class=workbench-dock-ghost__halo></div><div class=workbench-dock-ghost__card><div class=workbench-dock-ghost__icon></div><div class=workbench-dock-ghost__copy><div class=workbench-dock-ghost__title></div><div class=workbench-dock-ghost__hint><span>Drag onto canvas");
11
+ const oe = 5, Re = ".workbench-dock", V = [{
12
12
  mode: "work",
13
13
  label: "Work Mode",
14
14
  description: "Operate windows and sticky notes",
15
- icon: pe
15
+ icon: ye
16
16
  }, {
17
17
  mode: "background",
18
18
  label: "Composition Mode",
19
19
  description: "Arrange regions and canvas text",
20
- icon: De
21
- }], Ae = [{
20
+ icon: Me
21
+ }], He = [{
22
22
  tool: "sticky-note",
23
23
  label: "Sticky",
24
- icon: Le
25
- }], Xe = [{
24
+ icon: Pe
25
+ }], Be = [{
26
26
  tool: "background-region",
27
27
  label: "Region",
28
- icon: Oe
28
+ icon: Ie
29
29
  }, {
30
30
  tool: "text",
31
31
  label: "Text",
32
- icon: Me
32
+ icon: $e
33
33
  }];
34
- function Ye() {
35
- const e = document.querySelector(oe);
36
- return e instanceof HTMLElement ? ie(e) : null;
34
+ function We() {
35
+ const e = document.querySelector(ae);
36
+ return e instanceof HTMLElement ? ce(e) : null;
37
37
  }
38
- function N(e, c, r) {
39
- return e >= r.left && e <= r.right && c >= r.top && c <= r.bottom;
38
+ function G(e, l, a) {
39
+ return e >= a.left && e <= a.right && l >= a.top && l <= a.bottom;
40
40
  }
41
- function Re(e, c, r) {
42
- return r ? N(e, c, r) : !1;
41
+ function Ke(e, l, a) {
42
+ return a ? G(e, l, a) : !1;
43
43
  }
44
- function te(e, c, r) {
45
- return Math.min(r, Math.max(c, e));
44
+ function ie(e, l, a) {
45
+ return Math.min(a, Math.max(l, e));
46
46
  }
47
- function xe(e, c, r, d, i) {
47
+ function Ne(e, l, a, d, n) {
48
48
  if (!e) return !1;
49
- if (N(c, r, e) || N(d, i, e))
49
+ if (G(l, a, e) || G(d, n, e))
50
50
  return !0;
51
- const a = d - c, _ = i - r;
52
- let f = 0, m = 1;
53
- const u = (h, p) => {
54
- if (h === 0) return p >= 0;
55
- const E = p / h;
56
- return h < 0 ? E > m ? !1 : (E > f && (f = E), !0) : E < f ? !1 : (E < m && (m = E), !0);
51
+ const o = d - l, b = n - a;
52
+ let v = 0, f = 1;
53
+ const u = (k, S) => {
54
+ if (k === 0) return S >= 0;
55
+ const C = S / k;
56
+ return k < 0 ? C > f ? !1 : (C > v && (v = C), !0) : C < v ? !1 : (C < f && (f = C), !0);
57
57
  };
58
- return u(-a, c - e.left) && u(a, e.right - c) && u(-_, r - e.top) && u(_, e.bottom - r);
58
+ return u(-o, l - e.left) && u(o, e.right - l) && u(-b, a - e.top) && u(b, e.bottom - a);
59
59
  }
60
- function ne(e, c) {
60
+ function re(e, l) {
61
61
  if (typeof document.elementFromPoint != "function") return !1;
62
- const r = document.elementFromPoint(e, c);
63
- return r instanceof Element && r.closest(Fe) !== null;
62
+ const a = document.elementFromPoint(e, l);
63
+ return a instanceof Element && a.closest(Re) !== null;
64
64
  }
65
- function He(e) {
66
- const c = () => e.hoverOffset === -1 ? {
65
+ function Ve(e) {
66
+ const l = () => e.hoverOffset === -1 ? {
67
67
  scale: 1.26,
68
68
  y: -6,
69
69
  x: 0
@@ -79,50 +79,50 @@ function He(e) {
79
79
  scale: 1,
80
80
  y: 0,
81
81
  x: 0
82
- }, r = () => e.hoverOffset === -1, d = (i) => {
83
- i.button === 0 && e.onDragBegin(i, e.kind, e.id, e.label, e.icon);
82
+ }, a = () => e.hoverOffset === -1, d = (n) => {
83
+ n.button === 0 && e.onDragBegin(n, e.kind, e.id, e.label, e.icon, n.currentTarget);
84
84
  };
85
85
  return (() => {
86
- var i = ye();
87
- return i.$$pointerdown = d, i.addEventListener("pointerleave", () => e.onLeave()), i.addEventListener("pointerenter", () => e.onEnter()), w(i, g(F.span, {
86
+ var n = Te();
87
+ return n.$$pointerdown = d, n.addEventListener("pointerleave", () => e.onLeave()), n.addEventListener("pointerenter", () => e.onEnter()), h(n, s(I.span, {
88
88
  class: "workbench-dock__tile",
89
89
  get animate() {
90
- return c();
90
+ return l();
91
91
  },
92
92
  get transition() {
93
93
  return {
94
- duration: X.fast,
95
- easing: A.easeOut
94
+ duration: P.fast,
95
+ easing: $.easeOut
96
96
  };
97
97
  },
98
98
  get children() {
99
99
  return (() => {
100
- const a = e.icon;
101
- return g(a, {
100
+ const o = e.icon;
101
+ return s(o, {
102
102
  class: "workbench-dock__icon"
103
103
  });
104
104
  })();
105
105
  }
106
- }), null), w(i, g(F.span, {
106
+ }), null), h(n, s(I.span, {
107
107
  class: "workbench-dock__tooltip",
108
108
  get animate() {
109
109
  return {
110
- opacity: r() ? 1 : 0,
111
- y: r() ? -6 : 0
110
+ opacity: a() ? 1 : 0,
111
+ y: a() ? -6 : 0
112
112
  };
113
113
  },
114
114
  get transition() {
115
115
  return {
116
- duration: X.fast,
117
- easing: A.easeOut
116
+ duration: P.fast,
117
+ easing: $.easeOut
118
118
  };
119
119
  },
120
120
  get children() {
121
121
  return e.label;
122
122
  }
123
- }), null), P((a) => {
124
- var _ = !!e.active, f = !!(e.filterable && !e.visible), m = !!r(), u = !!e.isDragging, h = e.filterable ? `${e.label} — click to solo, drag to canvas to create` : `${e.label} — drag to canvas to create`, p = e.active;
125
- return _ !== a.e && i.classList.toggle("is-active", a.e = _), f !== a.t && i.classList.toggle("is-filter-muted", a.t = f), m !== a.a && i.classList.toggle("is-hovered", a.a = m), u !== a.o && i.classList.toggle("is-source-dragging", a.o = u), h !== a.i && T(i, "aria-label", a.i = h), p !== a.n && T(i, "aria-pressed", a.n = p), a;
123
+ }), null), X((o) => {
124
+ var b = !!e.active, v = !!(e.filterable && !e.visible), f = !!a(), u = !!e.isDragging, k = e.filterable ? `${e.label} — click to solo, drag to canvas to create` : `${e.label} — drag to canvas to create`, S = e.active;
125
+ return b !== o.e && n.classList.toggle("is-active", o.e = b), v !== o.t && n.classList.toggle("is-filter-muted", o.t = v), f !== o.a && n.classList.toggle("is-hovered", o.a = f), u !== o.o && n.classList.toggle("is-source-dragging", o.o = u), k !== o.i && L(n, "aria-label", o.i = k), S !== o.n && L(n, "aria-pressed", o.n = S), o;
126
126
  }, {
127
127
  e: void 0,
128
128
  t: void 0,
@@ -130,77 +130,148 @@ function He(e) {
130
130
  o: void 0,
131
131
  i: void 0,
132
132
  n: void 0
133
- }), i;
133
+ }), n;
134
+ })();
135
+ }
136
+ function pe(e) {
137
+ const l = () => e.hoverOffset === -1, a = () => e.hoverOffset === -1 ? {
138
+ scale: 1.26,
139
+ y: -6,
140
+ x: 0
141
+ } : e.hoverOffset === 1 ? {
142
+ scale: 1.08,
143
+ y: -2,
144
+ x: 5
145
+ } : e.hoverOffset === -2 ? {
146
+ scale: 1.08,
147
+ y: -2,
148
+ x: -5
149
+ } : {
150
+ scale: 1,
151
+ y: 0,
152
+ x: 0
153
+ }, d = e.action.icon;
154
+ return (() => {
155
+ var n = Ae();
156
+ return n.$$click = (o) => e.action.onActivate(o.currentTarget), n.addEventListener("dragstart", (o) => o.preventDefault()), ee(n, "pointerleave", e.onLeave), ee(n, "pointerenter", e.onEnter), L(n, "draggable", !1), h(n, s(I.span, {
157
+ class: "workbench-dock__tile",
158
+ get animate() {
159
+ return a();
160
+ },
161
+ get transition() {
162
+ return {
163
+ duration: P.fast,
164
+ easing: $.easeOut
165
+ };
166
+ },
167
+ get children() {
168
+ return s(d, {
169
+ class: "workbench-dock__icon"
170
+ });
171
+ }
172
+ }), null), h(n, s(I.span, {
173
+ class: "workbench-dock__tooltip",
174
+ get animate() {
175
+ return {
176
+ opacity: l() ? 1 : 0,
177
+ y: l() ? -6 : 0
178
+ };
179
+ },
180
+ get transition() {
181
+ return {
182
+ duration: P.fast,
183
+ easing: $.easeOut
184
+ };
185
+ },
186
+ get children() {
187
+ return e.action.label;
188
+ }
189
+ }), null), X((o) => {
190
+ var b = e.action.id, v = !!e.action.active, f = !!l(), u = e.action.label, k = e.action.active;
191
+ return b !== o.e && L(n, "data-workbench-dock-action", o.e = b), v !== o.t && n.classList.toggle("is-active", o.t = v), f !== o.a && n.classList.toggle("is-hovered", o.a = f), u !== o.o && L(n, "aria-label", o.o = u), k !== o.i && L(n, "aria-pressed", o.i = k), o;
192
+ }, {
193
+ e: void 0,
194
+ t: void 0,
195
+ a: void 0,
196
+ o: void 0,
197
+ i: void 0
198
+ }), n;
134
199
  })();
135
200
  }
136
- function Je(e) {
137
- const [c, r] = H(null), [d, i] = H(null), [a, _] = H(!1);
138
- let f, m, u, h = null;
139
- J(() => {
140
- u?.stop(), m?.stop({
201
+ function nt(e) {
202
+ const [l, a] = K(null), [d, n] = K(null), [o, b] = K(!1);
203
+ let v, f, u, k = null;
204
+ te(() => {
205
+ u?.stop(), f?.stop({
141
206
  reason: "manual_stop",
142
207
  commit: !1
143
- }), m = void 0, d()?.stopInteraction(), e.onDragPreviewChange?.(null);
144
- }), Q(() => {
208
+ }), f = void 0, d()?.stopInteraction(), e.onDragPreviewChange?.(null);
209
+ }), ne(() => {
145
210
  e.onDragPreviewChange?.(d()?.preview ?? null);
146
- }), Q(() => {
147
- if (!a() || typeof window > "u") return;
148
- const t = (s) => {
149
- f && s.target instanceof Node && f.contains(s.target) || _(!1);
150
- }, n = (s) => {
151
- s.key === "Escape" && _(!1);
211
+ }), ne(() => {
212
+ if (!o() || typeof window > "u") return;
213
+ const t = (g) => {
214
+ v && g.target instanceof Node && v.contains(g.target) || b(!1);
215
+ }, i = (g) => {
216
+ g.key === "Escape" && b(!1);
152
217
  };
153
- window.addEventListener("pointerdown", t, !0), window.addEventListener("keydown", n, !0), J(() => {
154
- window.removeEventListener("pointerdown", t, !0), window.removeEventListener("keydown", n, !0);
218
+ window.addEventListener("pointerdown", t, !0), window.addEventListener("keydown", i, !0), te(() => {
219
+ window.removeEventListener("pointerdown", t, !0), window.removeEventListener("keydown", i, !0);
155
220
  });
156
221
  });
157
- const p = (t) => {
158
- const n = c();
159
- return n === null ? 0 : n === t ? -1 : n === t + 1 ? -2 : n === t - 1 ? 1 : 0;
160
- }, E = () => {
161
- u?.stop(), u = void 0, h = null;
162
- }, Y = () => {
163
- !e.viewport || !e.onViewportCommit || (h = e.viewport, u?.stop(), u = Se({
222
+ const S = (t) => {
223
+ const i = l();
224
+ return i === null ? 0 : i === t ? -1 : i === t + 1 ? -2 : i === t - 1 ? 1 : 0;
225
+ }, C = () => {
226
+ u?.stop(), u = void 0, k = null;
227
+ }, H = () => {
228
+ !e.viewport || !e.onViewportCommit || (k = e.viewport, u?.stop(), u = Le({
164
229
  readFrame: () => {
165
- const t = document.querySelector(oe);
166
- return t instanceof HTMLElement ? ie(t) : null;
230
+ const t = document.querySelector(ae);
231
+ return t instanceof HTMLElement ? ce(t) : null;
167
232
  },
168
- readViewport: () => h ?? e.viewport ?? null,
233
+ readViewport: () => k ?? e.viewport ?? null,
169
234
  commitViewport: (t) => {
170
- h = t, e.onViewportCommit?.(t);
235
+ k = t, e.onViewportCommit?.(t);
171
236
  },
172
237
  onPanStart: () => e.onViewportInteractionStart?.("pan"),
173
238
  shouldPan: () => {
174
239
  const t = d();
175
- return !!(t?.moved && t.hasEnteredCanvas && !ne(t.clientX, t.clientY));
240
+ return !!(t?.moved && t.hasEnteredCanvas && !re(t.clientX, t.clientY));
176
241
  }
177
242
  }));
178
- }, re = (t) => {
179
- const n = d();
180
- if (!n) return;
181
- const s = !n.moved;
182
- if (n.stopInteraction(), E(), i(null), m = void 0, s) {
183
- D() !== "background" && e.onSoloFilter(String(n.id), U());
243
+ }, le = (t) => {
244
+ const i = d();
245
+ if (!i) return;
246
+ const g = !i.moved;
247
+ if (i.stopInteraction(), C(), n(null), f = void 0, g) {
248
+ if (e.onItemClick?.({
249
+ kind: i.kind,
250
+ id: i.id,
251
+ label: i.label,
252
+ trigger: i.trigger
253
+ })) return;
254
+ D() !== "background" && e.onSoloFilter(String(i.id), j());
184
255
  return;
185
256
  }
186
- if (t && n.overCanvas) {
187
- const O = n.canvasFrame ? {
188
- dropAllowed: n.overCanvas,
189
- canvasFrame: n.canvasFrame
257
+ if (t && i.overCanvas) {
258
+ const y = i.canvasFrame ? {
259
+ dropAllowed: i.overCanvas,
260
+ canvasFrame: i.canvasFrame
190
261
  } : void 0;
191
- n.kind === "widget" ? e.onCreateAt?.(n.id, n.clientX, n.clientY, O) : e.onCreateToolAt?.(n.id, n.clientX, n.clientY, O);
262
+ i.kind === "widget" ? e.onCreateAt?.(i.id, i.clientX, i.clientY, y) : e.onCreateToolAt?.(i.id, i.clientX, i.clientY, y);
192
263
  }
193
- }, ae = (t, n, s, O, l) => {
194
- t.preventDefault(), m?.stop({
264
+ }, se = (t, i, g, y, x, c) => {
265
+ t.preventDefault(), f?.stop({
195
266
  reason: "manual_stop",
196
267
  commit: !1
197
- }), Y();
198
- const k = Ye();
199
- i({
200
- kind: n,
201
- id: s,
202
- label: O,
203
- icon: l,
268
+ }), H();
269
+ const _ = We();
270
+ n({
271
+ kind: i,
272
+ id: g,
273
+ label: y,
274
+ icon: x,
204
275
  pointerId: t.pointerId,
205
276
  startClientX: t.clientX,
206
277
  startClientY: t.clientY,
@@ -209,53 +280,54 @@ function Je(e) {
209
280
  moved: !1,
210
281
  overCanvas: !1,
211
282
  hasEnteredCanvas: !1,
212
- canvasFrame: k,
283
+ canvasFrame: _,
213
284
  preview: null,
214
- stopInteraction: Ee({
285
+ stopInteraction: Se({
215
286
  kind: "drag",
216
287
  cursor: "grabbing"
217
- })
288
+ }),
289
+ trigger: c
218
290
  });
219
- const S = (o) => {
220
- let y = !1;
221
- i((v) => {
222
- if (!v || v.pointerId !== o.pointerId) return v;
223
- const I = o.clientX - v.startClientX, x = o.clientY - v.startClientY, C = v.moved || Math.abs(I) > ee || Math.abs(x) > ee, M = ne(o.clientX, o.clientY), b = v.canvasFrame, q = C && Re(o.clientX, o.clientY, b), z = q && !M, ge = C && !M && xe(b, v.clientX, v.clientY, o.clientX, o.clientY), j = v.hasEnteredCanvas || q || ge;
224
- y = C && j && !M;
225
- const ve = b ? te(o.clientX, b.left, b.right) : o.clientX, fe = b ? te(o.clientY, b.top, b.bottom) : o.clientY;
291
+ const w = (r) => {
292
+ let F = !1;
293
+ n((m) => {
294
+ if (!m || m.pointerId !== r.pointerId) return m;
295
+ const Y = r.clientX - m.startClientX, W = r.clientY - m.startClientY, O = m.moved || Math.abs(Y) > oe || Math.abs(W) > oe, M = re(r.clientX, r.clientY), E = m.canvasFrame, J = O && Ke(r.clientX, r.clientY, E), Q = J && !M, ke = O && !M && Ne(E, m.clientX, m.clientY, r.clientX, r.clientY), Z = m.hasEnteredCanvas || J || ke;
296
+ F = O && Z && !M;
297
+ const me = E ? ie(r.clientX, E.left, E.right) : r.clientX, he = E ? ie(r.clientY, E.top, E.bottom) : r.clientY;
226
298
  return {
227
- ...v,
228
- clientX: o.clientX,
229
- clientY: o.clientY,
230
- moved: C,
231
- overCanvas: z,
232
- hasEnteredCanvas: j,
233
- preview: C && b ? {
234
- kind: v.kind,
235
- id: v.id,
236
- label: v.label,
237
- clientX: ve,
238
- clientY: fe,
239
- dropAllowed: z,
240
- canvasFrame: b
299
+ ...m,
300
+ clientX: r.clientX,
301
+ clientY: r.clientY,
302
+ moved: O,
303
+ overCanvas: Q,
304
+ hasEnteredCanvas: Z,
305
+ preview: O && E ? {
306
+ kind: m.kind,
307
+ id: m.id,
308
+ label: m.label,
309
+ clientX: me,
310
+ clientY: he,
311
+ dropAllowed: Q,
312
+ canvasFrame: E
241
313
  } : null
242
314
  };
243
- }), y && u?.updatePointer(o.clientX, o.clientY);
315
+ }), F && u?.updatePointer(r.clientX, r.clientY);
244
316
  };
245
- m = Ce({
317
+ f = De({
246
318
  pointerEvent: t,
247
319
  captureEl: t.currentTarget,
248
- onMove: S,
320
+ onMove: w,
249
321
  onEnd: ({
250
- commit: o
251
- }) => re(o)
322
+ commit: r
323
+ }) => le(r)
252
324
  });
253
- }, le = () => d()?.kind === "widget" ? d().id : null, ce = () => d()?.kind === "tool" ? d().id : null, D = () => e.mode === "background" || e.mode === "annotation" ? "background" : "work", V = B(() => W.find((t) => t.mode === D()) ?? W[0]), G = B(() => D() === "background" ? Xe.map((t) => ({
325
+ }, de = () => d()?.kind === "widget" ? d().id : null, ue = () => d()?.kind === "tool" ? d().id : null, D = () => e.mode === "background" || e.mode === "annotation" ? "background" : "work", U = R(() => V.find((t) => t.mode === D()) ?? V[0]), q = R(() => D() === "background" ? Be.map((t) => ({
254
326
  id: t.tool,
255
327
  kind: "tool",
256
328
  label: t.label,
257
329
  icon: t.icon
258
- })) : [...Ae.map((t) => ({
330
+ })) : [...He.map((t) => ({
259
331
  id: t.tool,
260
332
  kind: "tool",
261
333
  label: t.label,
@@ -265,166 +337,181 @@ function Je(e) {
265
337
  kind: "widget",
266
338
  label: t.label,
267
339
  icon: t.icon
268
- }))]), U = B(() => G().map((t) => String(t.id))), R = () => D() !== "background", se = (t) => !R() || e.filters[t] !== !1, de = (t) => {
269
- if (!R())
340
+ }))]), z = R(() => D() === "background" ? [] : [...e.dockActions ?? []]), j = R(() => q().map((t) => String(t.id))), B = () => D() !== "background", ge = (t) => !B() || e.filters[t] !== !1, ve = (t) => {
341
+ if (!B())
270
342
  return !1;
271
- const n = U();
272
- return n.length > 1 && n.every((s) => e.filters[s] !== !1 == (s === t));
273
- }, L = () => c() === 0, ue = () => ({
274
- scale: L() || a() ? 1.26 : 1,
275
- y: L() || a() ? -6 : 0,
276
- x: c() === 1 ? -5 : 0
343
+ const i = j();
344
+ return i.length > 1 && i.every((g) => e.filters[g] !== !1 == (g === t));
345
+ }, A = () => l() === 0, fe = () => ({
346
+ scale: A() || o() ? 1.26 : 1,
347
+ y: A() || o() ? -6 : 0,
348
+ x: l() === 1 ? -5 : 0
277
349
  });
278
350
  return [(() => {
279
- var t = Ie(), n = t.firstChild, s = n.firstChild;
280
- n.nextSibling, t.addEventListener("pointerleave", () => r(null));
281
- var O = f;
282
- return typeof O == "function" ? be(O, t) : f = t, s.$$click = () => _((l) => !l), s.addEventListener("pointerleave", () => r((l) => l === 0 ? null : l)), s.addEventListener("pointerenter", () => r(0)), w(s, g(F.span, {
351
+ var t = Xe(), i = t.firstChild, g = i.firstChild, y = i.nextSibling;
352
+ t.addEventListener("pointerleave", () => a(null));
353
+ var x = v;
354
+ return typeof x == "function" ? Ee(x, t) : v = t, g.$$click = () => b((c) => !c), g.addEventListener("pointerleave", () => a((c) => c === 0 ? null : c)), g.addEventListener("pointerenter", () => a(0)), h(g, s(I.span, {
283
355
  class: "workbench-dock__tile",
284
356
  get animate() {
285
- return ue();
357
+ return fe();
286
358
  },
287
359
  get transition() {
288
360
  return {
289
- duration: X.fast,
290
- easing: A.easeOut
361
+ duration: P.fast,
362
+ easing: $.easeOut
291
363
  };
292
364
  },
293
365
  get children() {
294
366
  return (() => {
295
- const l = V().icon;
296
- return g(l, {
367
+ const c = U().icon;
368
+ return s(c, {
297
369
  class: "workbench-dock__icon"
298
370
  });
299
371
  })();
300
372
  }
301
- }), null), w(s, g(F.span, {
373
+ }), null), h(g, s(I.span, {
302
374
  class: "workbench-dock__tooltip",
303
375
  get animate() {
304
376
  return {
305
- opacity: L() && !a() ? 1 : 0,
306
- y: L() && !a() ? -6 : 0
377
+ opacity: A() && !o() ? 1 : 0,
378
+ y: A() && !o() ? -6 : 0
307
379
  };
308
380
  },
309
381
  get transition() {
310
382
  return {
311
- duration: X.fast,
312
- easing: A.easeOut
383
+ duration: P.fast,
384
+ easing: $.easeOut
313
385
  };
314
386
  },
315
387
  get children() {
316
- return V().label;
388
+ return U().label;
317
389
  }
318
- }), null), w(n, g(K, {
390
+ }), null), h(i, s(p, {
319
391
  get when() {
320
- return a();
392
+ return o();
321
393
  },
322
394
  get children() {
323
- var l = $e();
324
- return w(l, g(Z, {
325
- each: W,
326
- children: (k) => {
327
- const S = k.icon;
395
+ var c = Fe();
396
+ return h(c, s(N, {
397
+ each: V,
398
+ children: (_) => {
399
+ const w = _.icon;
328
400
  return (() => {
329
- var o = Pe(), y = o.firstChild, v = y.nextSibling, I = v.firstChild, x = I.nextSibling;
330
- return o.$$click = () => {
331
- e.onSelectMode?.(k.mode), _(!1);
332
- }, w(y, g(S, {
401
+ var r = xe(), F = r.firstChild, m = F.nextSibling, Y = m.firstChild, W = Y.nextSibling;
402
+ return r.$$click = () => {
403
+ e.onSelectMode?.(_.mode), b(!1);
404
+ }, h(F, s(w, {
333
405
  class: "workbench-dock__mode-icon"
334
- })), w(I, () => k.label), w(x, () => k.description), P((C) => {
335
- var M = D() === k.mode, b = D() === k.mode;
336
- return M !== C.e && o.classList.toggle("is-active", C.e = M), b !== C.t && T(o, "aria-checked", C.t = b), C;
406
+ })), h(Y, () => _.label), h(W, () => _.description), X((O) => {
407
+ var M = D() === _.mode, E = D() === _.mode;
408
+ return M !== O.e && r.classList.toggle("is-active", O.e = M), E !== O.t && L(r, "aria-checked", O.t = E), O;
337
409
  }, {
338
410
  e: void 0,
339
411
  t: void 0
340
- }), o;
412
+ }), r;
341
413
  })();
342
414
  }
343
- })), l;
415
+ })), c;
416
+ }
417
+ }), null), h(t, s(N, {
418
+ get each() {
419
+ return z();
420
+ },
421
+ children: (c, _) => {
422
+ const w = () => _() + 1;
423
+ return s(pe, {
424
+ action: c,
425
+ get hoverOffset() {
426
+ return S(w());
427
+ },
428
+ onEnter: () => a(w()),
429
+ onLeave: () => a((r) => r === w() ? null : r)
430
+ });
344
431
  }
345
- }), null), w(t, g(Z, {
432
+ }), y), h(t, s(N, {
346
433
  get each() {
347
- return G();
434
+ return q();
348
435
  },
349
- children: (l, k) => {
350
- const S = () => k() + 1;
351
- return g(He, {
436
+ children: (c, _) => {
437
+ const w = () => _() + z().length + 1;
438
+ return s(Ve, {
352
439
  get id() {
353
- return String(l.id);
440
+ return String(c.id);
354
441
  },
355
442
  get kind() {
356
- return l.kind;
443
+ return c.kind;
357
444
  },
358
445
  get label() {
359
- return l.label;
446
+ return c.label;
360
447
  },
361
448
  get icon() {
362
- return l.icon;
449
+ return c.icon;
363
450
  },
364
451
  get active() {
365
- return de(String(l.id));
452
+ return ve(String(c.id));
366
453
  },
367
454
  get visible() {
368
- return se(String(l.id));
455
+ return ge(String(c.id));
369
456
  },
370
457
  get filterable() {
371
- return R();
458
+ return B();
372
459
  },
373
460
  get hoverOffset() {
374
- return p(S());
461
+ return S(w());
375
462
  },
376
463
  get isDragging() {
377
- return me(() => l.kind === "widget")() ? le() === l.id : ce() === l.id;
464
+ return be(() => c.kind === "widget")() ? de() === c.id : ue() === c.id;
378
465
  },
379
- onEnter: () => r(S()),
380
- onLeave: () => r((o) => o === S() ? null : o),
381
- onDragBegin: ae
466
+ onEnter: () => a(w()),
467
+ onLeave: () => a((r) => r === w() ? null : r),
468
+ onDragBegin: se
382
469
  });
383
470
  }
384
- }), null), P((l) => {
385
- var k = D() === "background", S = !!(L() || a()), o = a();
386
- return k !== l.e && s.classList.toggle("is-active", l.e = k), S !== l.t && s.classList.toggle("is-hovered", l.t = S), o !== l.a && T(s, "aria-expanded", l.a = o), l;
471
+ }), null), X((c) => {
472
+ var _ = D() === "background", w = !!(A() || o()), r = o();
473
+ return _ !== c.e && g.classList.toggle("is-active", c.e = _), w !== c.t && g.classList.toggle("is-hovered", c.t = w), r !== c.a && L(g, "aria-expanded", c.a = r), c;
387
474
  }, {
388
475
  e: void 0,
389
476
  t: void 0,
390
477
  a: void 0
391
478
  }), t;
392
- })(), g(K, {
479
+ })(), s(p, {
393
480
  get when() {
394
481
  return !!(d()?.moved && !d()?.preview);
395
482
  },
396
483
  get children() {
397
- return g(Be, {
484
+ return s(Ge, {
398
485
  state: d
399
486
  });
400
487
  }
401
488
  })];
402
489
  }
403
- function Be(e) {
404
- const c = () => {
405
- const i = e.state();
406
- return i ? `translate3d(${i.clientX + 14}px, ${i.clientY - 56}px, 0)` : "translate3d(0px, 0px, 0)";
407
- }, r = () => e.state()?.label ?? "", d = () => e.state()?.icon;
408
- return g(he, {
490
+ function Ge(e) {
491
+ const l = () => {
492
+ const n = e.state();
493
+ return n ? `translate3d(${n.clientX + 14}px, ${n.clientY - 56}px, 0)` : "translate3d(0px, 0px, 0)";
494
+ }, a = () => e.state()?.label ?? "", d = () => e.state()?.icon;
495
+ return s(_e, {
409
496
  get children() {
410
- var i = Te(), a = i.firstChild, _ = a.nextSibling, f = _.firstChild, m = f.nextSibling, u = m.firstChild, h = u.nextSibling, p = h.firstChild;
411
- return w(f, g(K, {
497
+ var n = Ye(), o = n.firstChild, b = o.nextSibling, v = b.firstChild, f = v.nextSibling, u = f.firstChild, k = u.nextSibling, S = k.firstChild;
498
+ return h(v, s(p, {
412
499
  get when() {
413
500
  return d();
414
501
  },
415
- children: (E) => {
416
- const Y = E();
417
- return g(Y, {
502
+ children: (C) => {
503
+ const H = C();
504
+ return s(H, {
418
505
  class: "w-4 h-4"
419
506
  });
420
507
  }
421
- })), w(u, r), w(h, g(_e, {
508
+ })), h(u, a), h(k, s(Oe, {
422
509
  class: "w-3 h-3"
423
- }), p), P((E) => ke(i, "transform", c())), i;
510
+ }), S), X((C) => we(n, "transform", l())), n;
424
511
  }
425
512
  });
426
513
  }
427
- we(["pointerdown", "click"]);
514
+ Ce(["pointerdown", "click"]);
428
515
  export {
429
- Je as WorkbenchDock
516
+ nt as WorkbenchDock
430
517
  };
@@ -1,5 +1,6 @@
1
1
  import { type UIFirstSelectionEvent } from '../../utils/uiFirstSelection';
2
2
  import { type WorkbenchContextMenuItem } from './WorkbenchContextMenu';
3
+ import { type WorkbenchDockItemActivation, type WorkbenchDockAction } from './WorkbenchFilterBar';
3
4
  import type { WorkbenchState, WorkbenchAnnotationItem, WorkbenchBackgroundLayer, WorkbenchBackgroundLayerDefaults, WorkbenchBackgroundLayerPatch, WorkbenchContextMenuState, WorkbenchInteractionAdapter, WorkbenchStickyNoteItem, WorkbenchStickyNotePatch, WorkbenchTextAnnotationDefaults, WorkbenchTextAnnotationPatch, WorkbenchWidgetDefinition, WorkbenchWidgetItem, WorkbenchWidgetType } from './types';
4
5
  export interface WorkbenchCreateAtOptions {
5
6
  worldX?: number;
@@ -66,6 +67,8 @@ export interface WorkbenchSurfaceProps {
66
67
  resolveContextMenuItems?: WorkbenchContextMenuItemsResolver;
67
68
  onApiReady?: (api: WorkbenchSurfaceApi | null) => void;
68
69
  onRequestDelete?: (widgetId: string) => void;
70
+ onDockItemClick?: (item: WorkbenchDockItemActivation) => boolean | void;
71
+ dockActions?: readonly WorkbenchDockAction[];
69
72
  onLayoutInteractionStart?: () => void;
70
73
  onLayoutInteractionEnd?: () => void;
71
74
  /** Defer pointer/focus widget activation until the visual selection has painted. */
@@ -1,5 +1,5 @@
1
1
  import { use as j, spread as K, mergeProps as Z, insert as v, createComponent as l, Portal as G, addEventListener as J, template as R, delegateEvents as Q } from "solid-js/web";
2
- import { createSignal as p, createMemo as w, untrack as C, createEffect as k, onCleanup as A, Show as ee } from "solid-js";
2
+ import { createSignal as C, createMemo as w, untrack as h, createEffect as k, onCleanup as A, Show as ee } from "solid-js";
3
3
  import { clientToCanvasWorld as B } from "../ui/canvasGeometry.js";
4
4
  import { createUIFirstSelection as te } from "../../utils/uiFirstSelection.js";
5
5
  import { WorkbenchCanvas as ne } from "./WorkbenchCanvas.js";
@@ -11,8 +11,8 @@ import { installWorkbenchContextMenuDismissListeners as ce } from "./workbenchCo
11
11
  import { createContextMenuPosition as de, WORKBENCH_CONTEXT_MENU_WIDTH_PX as ue, estimateContextMenuHeight as se } from "./workbenchHelpers.js";
12
12
  import { resolveWorkbenchWidgetPlacementPreview as le, resolveWorkbenchToolPlacementPreview as ge } from "./workbenchPlacement.js";
13
13
  import { useWorkbenchModel as we } from "./useWorkbenchModel.js";
14
- import { resolveWorkbenchInteractionAdapter as fe } from "./workbenchInteractionAdapter.js";
15
- var me = /* @__PURE__ */ R("<div class=workbench-menu-backdrop data-floe-workbench-boundary=true>"), ve = /* @__PURE__ */ R("<div><div class=workbench-surface__body data-floe-workbench-canvas-frame=true>");
14
+ import { resolveWorkbenchInteractionAdapter as me } from "./workbenchInteractionAdapter.js";
15
+ var fe = /* @__PURE__ */ R("<div class=workbench-menu-backdrop data-floe-workbench-boundary=true>"), ve = /* @__PURE__ */ R("<div><div class=workbench-surface__body data-floe-workbench-canvas-frame=true>");
16
16
  const ke = "F1";
17
17
  function T(i) {
18
18
  if (i)
@@ -70,17 +70,17 @@ function Re(i) {
70
70
  return;
71
71
  }
72
72
  t.canvas.selectWidget(e), t.canvas.commitFront(e);
73
- }, [s, X] = p(null), [_, q] = p(null), c = w(() => fe(i.interactionAdapter)), [h, g] = p(C(() => c().createInitialInputOwner())), S = w(() => {
73
+ }, [s, X] = C(null), [_, q] = C(null), c = w(() => me(i.interactionAdapter)), [p, g] = C(h(() => c().createInitialInputOwner())), S = w(() => {
74
74
  const e = i.launcherWidgetTypes;
75
75
  return !e || e.length <= 0 ? null : new Set(e);
76
76
  }), Y = w(() => {
77
77
  const e = t.widgetDefinitions(), n = S();
78
78
  return n ? e.filter((o) => n.has(o.type)) : e;
79
79
  }), b = w(() => {
80
- const e = t.contextMenu.state(), n = t.contextMenu.items(), o = S(), r = o ? n.filter((m) => {
81
- if (m.kind !== "action")
80
+ const e = t.contextMenu.state(), n = t.contextMenu.items(), o = S(), r = o ? n.filter((f) => {
81
+ if (f.kind !== "action")
82
82
  return !0;
83
- const L = /^add-(.+)$/.exec(String(m.id ?? ""));
83
+ const L = /^add-(.+)$/.exec(String(f.id ?? ""));
84
84
  return L ? o.has(L[1]) : !0;
85
85
  }) : n;
86
86
  if (!e || !i.resolveContextMenuItems)
@@ -113,8 +113,8 @@ function Re(i) {
113
113
  g(r.createWidgetInputOwner(d, n));
114
114
  return;
115
115
  }
116
- const m = s();
117
- m && e instanceof Node && m.contains(e) && g(r.createCanvasInputOwner(o));
116
+ const f = s();
117
+ f && e instanceof Node && f.contains(e) && g(r.createCanvasInputOwner(o));
118
118
  }, I = (e = "selection_cleared") => {
119
119
  const n = c(), o = s();
120
120
  t.selection.clear(), g(n.createCanvasInputOwner(e)), queueMicrotask(() => {
@@ -133,17 +133,17 @@ function Re(i) {
133
133
  worldX: r > 0 ? (r / 2 - n.x) / n.scale : 240,
134
134
  worldY: a > 0 ? (a / 2 - n.y) / n.scale : 180
135
135
  };
136
- }, f = (e) => {
137
- const n = C(c), o = C(s);
136
+ }, m = (e) => {
137
+ const n = h(c), o = h(s);
138
138
  queueMicrotask(() => {
139
139
  n.focusWidgetElement(o, e), g(n.createWidgetInputOwner(e, "activation"));
140
140
  });
141
141
  }, P = (e) => {
142
142
  const n = t.navigation.fitWidget(e);
143
- f(n.id);
143
+ m(n.id);
144
144
  }, V = (e) => {
145
145
  const n = t.navigation.overviewWidget(e);
146
- f(n.id);
146
+ m(n.id);
147
147
  };
148
148
  k(() => {
149
149
  i.onApiReady?.({
@@ -167,15 +167,15 @@ function Re(i) {
167
167
  clearSelection: () => I("selection_cleared"),
168
168
  focusWidget: (e, n) => {
169
169
  const o = t.navigation.focusWidget(e, n);
170
- return f(o.id), o;
170
+ return m(o.id), o;
171
171
  },
172
172
  fitWidget: (e) => {
173
173
  const n = t.navigation.fitWidget(e);
174
- return f(n.id), n;
174
+ return m(n.id), n;
175
175
  },
176
176
  overviewWidget: (e) => {
177
177
  const n = t.navigation.overviewWidget(e);
178
- return f(n.id), n;
178
+ return m(n.id), n;
179
179
  },
180
180
  findWidgetByType: (e) => t.queries.findWidgetByType(e),
181
181
  findWidgetById: (e) => t.queries.findWidgetById(e),
@@ -211,7 +211,7 @@ function Re(i) {
211
211
  });
212
212
  A(() => e());
213
213
  }), k(() => {
214
- const e = h();
214
+ const e = p();
215
215
  if (e.kind !== "widget") return;
216
216
  t.widgets().some((o) => o.id === e.widgetId) || g(c().createCanvasInputOwner("widget_removed"));
217
217
  }), k(() => {
@@ -236,7 +236,7 @@ function Re(i) {
236
236
  if (!c().shouldBypassGlobalHotkeys({
237
237
  root: s(),
238
238
  target: o.target,
239
- owner: h(),
239
+ owner: p(),
240
240
  interactiveSelector: c().interactiveSelector
241
241
  }))
242
242
  switch (o.key) {
@@ -513,6 +513,12 @@ function Re(i) {
513
513
  onViewportInteractionStart: () => t.canvas.cancelViewportNavigation(),
514
514
  onCreateAt: z,
515
515
  onCreateToolAt: H,
516
+ get onItemClick() {
517
+ return i.onDockItemClick;
518
+ },
519
+ get dockActions() {
520
+ return i.dockActions;
521
+ },
516
522
  onDragPreviewChange: q
517
523
  }), null), v(e, l(ie, {
518
524
  get scaleLabel() {
@@ -536,7 +542,7 @@ function Re(i) {
536
542
  return l(G, {
537
543
  get children() {
538
544
  return [(() => {
539
- var o = me();
545
+ var o = fe();
540
546
  return J(o, "contextmenu", t.contextMenu.retarget, !0), o;
541
547
  })(), l(oe, {
542
548
  get x() {
@@ -1,5 +1,6 @@
1
1
  export { WorkbenchOverlay, type WorkbenchOverlayProps, } from './WorkbenchOverlay';
2
2
  export { WorkbenchSurface, type WorkbenchSurfaceApi, type WorkbenchCreateAtOptions, type WorkbenchCreateWidgetOptions, type WorkbenchContextMenuItemsResolver, type WorkbenchSurfaceProps, } from './WorkbenchSurface';
3
+ export type { WorkbenchDockAction, WorkbenchDockItemActivation } from './WorkbenchFilterBar';
3
4
  export { WorkbenchContextMenu, type WorkbenchContextMenuItem, type WorkbenchContextMenuProps, } from './WorkbenchContextMenu';
4
5
  export { useWorkbenchModel, type UseWorkbenchModelOptions } from './useWorkbenchModel';
5
6
  export { WIDGET_REGISTRY, createWorkbenchFilterState, getWidgetEntry, isValidWorkbenchWidgetType, resolveWorkbenchWidgetDefinitions, type WidgetRegistryEntry, } from './widgets/widgetRegistry';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/floe-webapp-core",
3
- "version": "0.40.5",
3
+ "version": "0.40.6",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",