@objectifthunes/whiteboard 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,15 +1,11 @@
1
- // src/WhiteboardShell.tsx
2
- import { useRef as useRef2, useCallback, useEffect as useEffect2 } from "react";
3
-
4
- // src/ZoomBar.tsx
5
- import { useEffect } from "react";
6
-
7
- // src/icons.tsx
8
- import { jsx, jsxs } from "react/jsx-runtime";
9
- var defaults = (size = 14) => ({
1
+ import { jsx as n, jsxs as d, Fragment as re } from "react/jsx-runtime";
2
+ import { useEffect as X, useRef as S, useCallback as H, memo as Te, useId as Re, useState as Se, useLayoutEffect as We, Component as De, useMemo as ye, forwardRef as me, createElement as T } from "react";
3
+ import { create as Xe } from "zustand";
4
+ import { createPortal as Ye } from "react-dom";
5
+ const Y = (e = 14) => ({
10
6
  xmlns: "http://www.w3.org/2000/svg",
11
- width: size,
12
- height: size,
7
+ width: e,
8
+ height: e,
13
9
  viewBox: "0 0 24 24",
14
10
  fill: "none",
15
11
  stroke: "currentColor",
@@ -17,419 +13,308 @@ var defaults = (size = 14) => ({
17
13
  strokeLinecap: "round",
18
14
  strokeLinejoin: "round"
19
15
  });
20
- function Minus({ size, ...props }) {
21
- return /* @__PURE__ */ jsx("svg", { ...defaults(size), ...props, children: /* @__PURE__ */ jsx("path", { d: "M5 12h14" }) });
16
+ function Fe({ size: e, ...t }) {
17
+ return /* @__PURE__ */ n("svg", { ...Y(e), ...t, children: /* @__PURE__ */ n("path", { d: "M5 12h14" }) });
22
18
  }
23
- function Plus({ size, ...props }) {
24
- return /* @__PURE__ */ jsxs("svg", { ...defaults(size), ...props, children: [
25
- /* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
26
- /* @__PURE__ */ jsx("path", { d: "M12 5v14" })
19
+ function Ge({ size: e, ...t }) {
20
+ return /* @__PURE__ */ d("svg", { ...Y(e), ...t, children: [
21
+ /* @__PURE__ */ n("path", { d: "M5 12h14" }),
22
+ /* @__PURE__ */ n("path", { d: "M12 5v14" })
27
23
  ] });
28
24
  }
29
- function ScanSearch({ size, ...props }) {
30
- return /* @__PURE__ */ jsxs("svg", { ...defaults(size), ...props, children: [
31
- /* @__PURE__ */ jsx("path", { d: "M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425z", fill: "none", stroke: "none" }),
32
- /* @__PURE__ */ jsx("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }),
33
- /* @__PURE__ */ jsx("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }),
34
- /* @__PURE__ */ jsx("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }),
35
- /* @__PURE__ */ jsx("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" }),
36
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" }),
37
- /* @__PURE__ */ jsx("path", { d: "m16 16-1.9-1.9" })
25
+ function Ie({ size: e, ...t }) {
26
+ return /* @__PURE__ */ d("svg", { ...Y(e), ...t, children: [
27
+ /* @__PURE__ */ n("path", { d: "M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425z", fill: "none", stroke: "none" }),
28
+ /* @__PURE__ */ n("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }),
29
+ /* @__PURE__ */ n("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }),
30
+ /* @__PURE__ */ n("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }),
31
+ /* @__PURE__ */ n("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" }),
32
+ /* @__PURE__ */ n("circle", { cx: "12", cy: "12", r: "3" }),
33
+ /* @__PURE__ */ n("path", { d: "m16 16-1.9-1.9" })
38
34
  ] });
39
35
  }
40
- function RotateCcw({ size, ...props }) {
41
- return /* @__PURE__ */ jsxs("svg", { ...defaults(size), ...props, children: [
42
- /* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
43
- /* @__PURE__ */ jsx("path", { d: "M3 3v5h5" })
36
+ function Le({ size: e, ...t }) {
37
+ return /* @__PURE__ */ d("svg", { ...Y(e), ...t, children: [
38
+ /* @__PURE__ */ n("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
39
+ /* @__PURE__ */ n("path", { d: "M3 3v5h5" })
44
40
  ] });
45
41
  }
46
- function Grid3x3({ size, ...props }) {
47
- return /* @__PURE__ */ jsxs("svg", { ...defaults(size), ...props, children: [
48
- /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }),
49
- /* @__PURE__ */ jsx("path", { d: "M3 9h18" }),
50
- /* @__PURE__ */ jsx("path", { d: "M3 15h18" }),
51
- /* @__PURE__ */ jsx("path", { d: "M9 3v18" }),
52
- /* @__PURE__ */ jsx("path", { d: "M15 3v18" })
42
+ function Ee({ size: e, ...t }) {
43
+ return /* @__PURE__ */ d("svg", { ...Y(e), ...t, children: [
44
+ /* @__PURE__ */ n("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }),
45
+ /* @__PURE__ */ n("path", { d: "M3 9h18" }),
46
+ /* @__PURE__ */ n("path", { d: "M3 15h18" }),
47
+ /* @__PURE__ */ n("path", { d: "M9 3v18" }),
48
+ /* @__PURE__ */ n("path", { d: "M15 3v18" })
53
49
  ] });
54
50
  }
55
- function Maximize2({ size, ...props }) {
56
- return /* @__PURE__ */ jsxs("svg", { ...defaults(size), ...props, children: [
57
- /* @__PURE__ */ jsx("polyline", { points: "15 3 21 3 21 9" }),
58
- /* @__PURE__ */ jsx("polyline", { points: "9 21 3 21 3 15" }),
59
- /* @__PURE__ */ jsx("line", { x1: "21", x2: "14", y1: "3", y2: "10" }),
60
- /* @__PURE__ */ jsx("line", { x1: "3", x2: "10", y1: "21", y2: "14" })
51
+ function Ae({ size: e, ...t }) {
52
+ return /* @__PURE__ */ d("svg", { ...Y(e), ...t, children: [
53
+ /* @__PURE__ */ n("polyline", { points: "15 3 21 3 21 9" }),
54
+ /* @__PURE__ */ n("polyline", { points: "9 21 3 21 3 15" }),
55
+ /* @__PURE__ */ n("line", { x1: "21", x2: "14", y1: "3", y2: "10" }),
56
+ /* @__PURE__ */ n("line", { x1: "3", x2: "10", y1: "21", y2: "14" })
61
57
  ] });
62
58
  }
63
- function Loader2({ size, ...props }) {
64
- return /* @__PURE__ */ jsx("svg", { ...defaults(size), ...props, children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
59
+ function fe({ size: e, ...t }) {
60
+ return /* @__PURE__ */ n("svg", { ...Y(e), ...t, children: /* @__PURE__ */ n("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
65
61
  }
66
- function AlertTriangle({ size, ...props }) {
67
- return /* @__PURE__ */ jsxs("svg", { ...defaults(size), ...props, children: [
68
- /* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
69
- /* @__PURE__ */ jsx("path", { d: "M12 9v4" }),
70
- /* @__PURE__ */ jsx("path", { d: "M12 17h.01" })
62
+ function Oe({ size: e, ...t }) {
63
+ return /* @__PURE__ */ d("svg", { ...Y(e), ...t, children: [
64
+ /* @__PURE__ */ n("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
65
+ /* @__PURE__ */ n("path", { d: "M12 9v4" }),
66
+ /* @__PURE__ */ n("path", { d: "M12 17h.01" })
71
67
  ] });
72
68
  }
73
- function Check({ size, ...props }) {
74
- return /* @__PURE__ */ jsx("svg", { ...defaults(size), ...props, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
69
+ function He({ size: e, ...t }) {
70
+ return /* @__PURE__ */ n("svg", { ...Y(e), ...t, children: /* @__PURE__ */ n("path", { d: "M20 6 9 17l-5-5" }) });
75
71
  }
76
- function X({ size, ...props }) {
77
- return /* @__PURE__ */ jsxs("svg", { ...defaults(size), ...props, children: [
78
- /* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
79
- /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
72
+ function Me({ size: e, ...t }) {
73
+ return /* @__PURE__ */ d("svg", { ...Y(e), ...t, children: [
74
+ /* @__PURE__ */ n("path", { d: "M18 6 6 18" }),
75
+ /* @__PURE__ */ n("path", { d: "m6 6 12 12" })
80
76
  ] });
81
77
  }
82
- function Moon({ size, ...props }) {
83
- return /* @__PURE__ */ jsx("svg", { ...defaults(size), ...props, children: /* @__PURE__ */ jsx("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" }) });
84
- }
85
- function Sun({ size, ...props }) {
86
- return /* @__PURE__ */ jsxs("svg", { ...defaults(size), ...props, children: [
87
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "4" }),
88
- /* @__PURE__ */ jsx("path", { d: "M12 2v2" }),
89
- /* @__PURE__ */ jsx("path", { d: "M12 20v2" }),
90
- /* @__PURE__ */ jsx("path", { d: "m4.93 4.93 1.41 1.41" }),
91
- /* @__PURE__ */ jsx("path", { d: "m17.66 17.66 1.41 1.41" }),
92
- /* @__PURE__ */ jsx("path", { d: "M2 12h2" }),
93
- /* @__PURE__ */ jsx("path", { d: "M20 12h2" }),
94
- /* @__PURE__ */ jsx("path", { d: "m6.34 17.66-1.41 1.41" }),
95
- /* @__PURE__ */ jsx("path", { d: "m19.07 4.93-1.41 1.41" })
78
+ function Be({ size: e, ...t }) {
79
+ return /* @__PURE__ */ n("svg", { ...Y(e), ...t, children: /* @__PURE__ */ n("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" }) });
80
+ }
81
+ function $e({ size: e, ...t }) {
82
+ return /* @__PURE__ */ d("svg", { ...Y(e), ...t, children: [
83
+ /* @__PURE__ */ n("circle", { cx: "12", cy: "12", r: "4" }),
84
+ /* @__PURE__ */ n("path", { d: "M12 2v2" }),
85
+ /* @__PURE__ */ n("path", { d: "M12 20v2" }),
86
+ /* @__PURE__ */ n("path", { d: "m4.93 4.93 1.41 1.41" }),
87
+ /* @__PURE__ */ n("path", { d: "m17.66 17.66 1.41 1.41" }),
88
+ /* @__PURE__ */ n("path", { d: "M2 12h2" }),
89
+ /* @__PURE__ */ n("path", { d: "M20 12h2" }),
90
+ /* @__PURE__ */ n("path", { d: "m6.34 17.66-1.41 1.41" }),
91
+ /* @__PURE__ */ n("path", { d: "m19.07 4.93-1.41 1.41" })
96
92
  ] });
97
93
  }
98
-
99
- // src/store.ts
100
- import { create } from "zustand";
101
-
102
- // src/grid.ts
103
- var WHITEBOARD_GRID = 20;
104
- function snapToWhiteboardGrid(value) {
105
- return Math.round(value / WHITEBOARD_GRID) * WHITEBOARD_GRID;
106
- }
107
-
108
- // src/store.ts
109
- function computeWhiteboardFit(panels, viewportSize, padding = 60) {
110
- if (panels.size === 0) return null;
111
- let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
112
- for (const r of panels.values()) {
113
- minX = Math.min(minX, r.x);
114
- minY = Math.min(minY, r.y);
115
- maxX = Math.max(maxX, r.x + r.width);
116
- maxY = Math.max(maxY, r.y + r.height);
117
- }
118
- const contentW = maxX - minX + padding * 2;
119
- const contentH = maxY - minY + padding * 2;
120
- const vpW = viewportSize.width || window.innerWidth;
121
- const vpH = viewportSize.height || window.innerHeight;
122
- const fitScale = Math.min(vpW / contentW, vpH / contentH, 1.5);
123
- const centerX = (minX + maxX) / 2;
124
- const centerY = (minY + maxY) / 2;
94
+ const he = 20;
95
+ function ue(e) {
96
+ return Math.round(e / he) * he;
97
+ }
98
+ function Ne(e, t, r = 60) {
99
+ if (e.size === 0) return null;
100
+ let s = 1 / 0, a = 1 / 0, u = -1 / 0, w = -1 / 0;
101
+ for (const v of e.values())
102
+ s = Math.min(s, v.x), a = Math.min(a, v.y), u = Math.max(u, v.x + v.width), w = Math.max(w, v.y + v.height);
103
+ const f = u - s + r * 2, m = w - a + r * 2, g = t.width || window.innerWidth, h = t.height || window.innerHeight, M = Math.min(g / f, h / m, 1.5), k = (s + u) / 2, _ = (a + w) / 2;
125
104
  return {
126
- scale: Math.min(3, Math.max(0.2, fitScale)),
105
+ scale: Math.min(3, Math.max(0.2, M)),
127
106
  offset: {
128
- x: vpW / 2 - centerX * fitScale,
129
- y: vpH / 2 - centerY * fitScale
107
+ x: g / 2 - k * M,
108
+ y: h / 2 - _ * M
130
109
  }
131
110
  };
132
111
  }
133
- function computeWhiteboardRectFocus(rect, viewportSize, padding = 40, maxScale = 1.5) {
134
- const vpW = viewportSize.width || window.innerWidth;
135
- const vpH = viewportSize.height || window.innerHeight;
136
- const safeWidth = Math.max(1, rect.width);
137
- const safeHeight = Math.max(1, rect.height);
138
- const fitScale = Math.min(
139
- (vpW - padding * 2) / safeWidth,
140
- (vpH - padding * 2) / safeHeight,
141
- maxScale
142
- );
143
- const nextScale = Math.min(3, Math.max(0.2, fitScale));
112
+ function Ve(e, t, r = 40, s = 1.5) {
113
+ const a = t.width || window.innerWidth, u = t.height || window.innerHeight, w = Math.max(1, e.width), f = Math.max(1, e.height), m = Math.min(
114
+ (a - r * 2) / w,
115
+ (u - r * 2) / f,
116
+ s
117
+ ), g = Math.min(3, Math.max(0.2, m));
144
118
  return {
145
- scale: nextScale,
119
+ scale: g,
146
120
  offset: {
147
- x: vpW / 2 - (rect.x + safeWidth / 2) * nextScale,
148
- y: vpH / 2 - (rect.y + safeHeight / 2) * nextScale
121
+ x: a / 2 - (e.x + w / 2) * g,
122
+ y: u / 2 - (e.y + f / 2) * g
149
123
  }
150
124
  };
151
125
  }
152
- var useWhiteboardStore = create((set, get) => ({
126
+ const p = Xe((e, t) => ({
153
127
  offset: { x: 0, y: 0 },
154
128
  scale: 1,
155
129
  viewportSize: { width: 0, height: 0 },
156
- snapToGrid: false,
157
- snapGridSize: WHITEBOARD_GRID,
130
+ snapToGrid: !1,
131
+ snapGridSize: he,
158
132
  panels: /* @__PURE__ */ new Map(),
159
133
  resetFns: /* @__PURE__ */ new Map(),
160
134
  registryVersion: 0,
161
- setOffset: (v) => set((s) => ({ offset: typeof v === "function" ? v(s.offset) : v })),
162
- setScale: (v) => set((s) => ({ scale: typeof v === "function" ? v(s.scale) : v })),
163
- setViewportSize: (v) => set({ viewportSize: v }),
164
- setSnapToGrid: (v) => set((s) => ({ snapToGrid: typeof v === "function" ? v(s.snapToGrid) : v })),
165
- register: (id, rect) => {
166
- get().panels.set(id, rect);
167
- set((s) => ({ registryVersion: s.registryVersion + 1 }));
135
+ setOffset: (r) => e((s) => ({ offset: typeof r == "function" ? r(s.offset) : r })),
136
+ setScale: (r) => e((s) => ({ scale: typeof r == "function" ? r(s.scale) : r })),
137
+ setViewportSize: (r) => e({ viewportSize: r }),
138
+ setSnapToGrid: (r) => e((s) => ({ snapToGrid: typeof r == "function" ? r(s.snapToGrid) : r })),
139
+ register: (r, s) => {
140
+ t().panels.set(r, s), e((a) => ({ registryVersion: a.registryVersion + 1 }));
168
141
  },
169
- unregister: (id) => {
170
- get().panels.delete(id);
171
- set((s) => ({ registryVersion: s.registryVersion + 1 }));
142
+ unregister: (r) => {
143
+ t().panels.delete(r), e((s) => ({ registryVersion: s.registryVersion + 1 }));
172
144
  },
173
- registerReset: (id, fn) => {
174
- get().resetFns.set(id, fn);
145
+ registerReset: (r, s) => {
146
+ t().resetFns.set(r, s);
175
147
  },
176
- unregisterReset: (id) => {
177
- get().resetFns.delete(id);
148
+ unregisterReset: (r) => {
149
+ t().resetFns.delete(r);
178
150
  },
179
151
  fitToContent: () => {
180
- const { panels, viewportSize } = get();
181
- const fit = computeWhiteboardFit(panels, viewportSize);
182
- if (fit) set({ scale: fit.scale, offset: fit.offset });
152
+ const { panels: r, viewportSize: s } = t(), a = Ne(r, s);
153
+ a && e({ scale: a.scale, offset: a.offset });
183
154
  },
184
- focusPanel: (rect, options) => {
185
- const { viewportSize } = get();
186
- const fit = computeWhiteboardRectFocus(
187
- rect,
188
- viewportSize,
189
- options?.padding ?? 40,
190
- options?.maxScale ?? 1.5
155
+ focusPanel: (r, s) => {
156
+ const { viewportSize: a } = t(), u = Ve(
157
+ r,
158
+ a,
159
+ (s == null ? void 0 : s.padding) ?? 40,
160
+ (s == null ? void 0 : s.maxScale) ?? 1.5
191
161
  );
192
- set({ scale: fit.scale, offset: fit.offset });
162
+ e({ scale: u.scale, offset: u.offset });
193
163
  },
194
164
  resetWidgets: () => {
195
- for (const fn of get().resetFns.values()) fn();
196
- const attempt = (tries = 0) => {
197
- const { panels, viewportSize } = get();
198
- const fit = computeWhiteboardFit(panels, viewportSize);
199
- if (fit) {
200
- set({ scale: fit.scale, offset: fit.offset });
165
+ for (const s of t().resetFns.values()) s();
166
+ const r = (s = 0) => {
167
+ const { panels: a, viewportSize: u } = t(), w = Ne(a, u);
168
+ if (w) {
169
+ e({ scale: w.scale, offset: w.offset });
201
170
  return;
202
171
  }
203
- if (tries < 6) requestAnimationFrame(() => attempt(tries + 1));
172
+ s < 6 && requestAnimationFrame(() => r(s + 1));
204
173
  };
205
- requestAnimationFrame(() => requestAnimationFrame(() => attempt()));
174
+ requestAnimationFrame(() => requestAnimationFrame(() => r()));
206
175
  },
207
- resetSession: () => set({
176
+ resetSession: () => e({
208
177
  offset: { x: 0, y: 0 },
209
178
  scale: 1,
210
179
  viewportSize: { width: 0, height: 0 },
211
- snapToGrid: false,
180
+ snapToGrid: !1,
212
181
  registryVersion: 0,
213
182
  panels: /* @__PURE__ */ new Map(),
214
183
  resetFns: /* @__PURE__ */ new Map()
215
184
  })
216
185
  }));
217
-
218
- // src/ZoomBar.tsx
219
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
220
- function ZoomBar({ extraActions }) {
221
- const scale = useWhiteboardStore((s) => s.scale);
222
- const viewportSize = useWhiteboardStore((s) => s.viewportSize);
223
- const snapToGrid = useWhiteboardStore((s) => s.snapToGrid);
224
- const setScale = useWhiteboardStore((s) => s.setScale);
225
- const setOffset = useWhiteboardStore((s) => s.setOffset);
226
- const setSnapToGrid = useWhiteboardStore((s) => s.setSnapToGrid);
227
- const fitToContent = useWhiteboardStore((s) => s.fitToContent);
228
- const resetWidgets = useWhiteboardStore((s) => s.resetWidgets);
229
- useEffect(() => {
230
- if (!snapToGrid) return;
231
- window.dispatchEvent(new Event("whiteboard-snap-now"));
232
- }, [snapToGrid]);
233
- const zoomTo = (nextScale) => {
234
- const clamped = Math.min(3, Math.max(0.2, nextScale));
235
- const ratio = clamped / scale;
236
- const cx = (viewportSize.width || window.innerWidth) / 2;
237
- const cy = (viewportSize.height || window.innerHeight) / 2;
238
- setOffset((prev) => ({
239
- x: cx - (cx - prev.x) * ratio,
240
- y: cy - (cy - prev.y) * ratio
241
- }));
242
- setScale(clamped);
186
+ function je({ extraActions: e }) {
187
+ const t = p((h) => h.scale), r = p((h) => h.viewportSize), s = p((h) => h.snapToGrid), a = p((h) => h.setScale), u = p((h) => h.setOffset), w = p((h) => h.setSnapToGrid), f = p((h) => h.fitToContent), m = p((h) => h.resetWidgets);
188
+ X(() => {
189
+ s && window.dispatchEvent(new Event("whiteboard-snap-now"));
190
+ }, [s]);
191
+ const g = (h) => {
192
+ const M = Math.min(3, Math.max(0.2, h)), k = M / t, _ = (r.width || window.innerWidth) / 2, v = (r.height || window.innerHeight) / 2;
193
+ u((P) => ({
194
+ x: _ - (_ - P.x) * k,
195
+ y: v - (v - P.y) * k
196
+ })), a(M);
243
197
  };
244
- return /* @__PURE__ */ jsxs2(
198
+ return /* @__PURE__ */ d(
245
199
  "div",
246
200
  {
247
201
  className: "zoom-bar",
248
- onPointerDown: (e) => e.stopPropagation(),
249
- onWheel: (e) => e.stopPropagation(),
202
+ onPointerDown: (h) => h.stopPropagation(),
203
+ onWheel: (h) => h.stopPropagation(),
250
204
  children: [
251
- /* @__PURE__ */ jsx2("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__icon", onClick: () => zoomTo(scale * 0.8), title: "Zoom out", "aria-label": "Zoom out", children: /* @__PURE__ */ jsx2(Minus, { size: 14 }) }),
252
- /* @__PURE__ */ jsxs2("span", { className: "zoom-bar__value", children: [
253
- Math.round(scale * 100),
205
+ /* @__PURE__ */ n("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__icon", onClick: () => g(t * 0.8), title: "Zoom out", "aria-label": "Zoom out", children: /* @__PURE__ */ n(Fe, { size: 14 }) }),
206
+ /* @__PURE__ */ d("span", { className: "zoom-bar__value", children: [
207
+ Math.round(t * 100),
254
208
  "%"
255
209
  ] }),
256
- /* @__PURE__ */ jsx2("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__icon", onClick: () => zoomTo(scale * 1.2), title: "Zoom in", "aria-label": "Zoom in", children: /* @__PURE__ */ jsx2(Plus, { size: 14 }) }),
257
- /* @__PURE__ */ jsx2("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__action", onClick: fitToContent, title: "Fit camera to all panels", "aria-label": "Fit camera to all panels", children: /* @__PURE__ */ jsx2(ScanSearch, { size: 14 }) }),
258
- /* @__PURE__ */ jsx2("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__action", onClick: resetWidgets, title: "Reset panel positions", "aria-label": "Reset panel positions", children: /* @__PURE__ */ jsx2(RotateCcw, { size: 14 }) }),
259
- /* @__PURE__ */ jsx2(
210
+ /* @__PURE__ */ n("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__icon", onClick: () => g(t * 1.2), title: "Zoom in", "aria-label": "Zoom in", children: /* @__PURE__ */ n(Ge, { size: 14 }) }),
211
+ /* @__PURE__ */ n("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__action", onClick: f, title: "Fit camera to all panels", "aria-label": "Fit camera to all panels", children: /* @__PURE__ */ n(Ie, { size: 14 }) }),
212
+ /* @__PURE__ */ n("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__action", onClick: m, title: "Reset panel positions", "aria-label": "Reset panel positions", children: /* @__PURE__ */ n(Le, { size: 14 }) }),
213
+ /* @__PURE__ */ n(
260
214
  "button",
261
215
  {
262
216
  type: "button",
263
- className: `wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__action${snapToGrid ? " is-active" : ""}`,
264
- onClick: () => setSnapToGrid((prev) => !prev),
265
- title: snapToGrid ? "Disable snap to grid" : "Enable snap to grid",
266
- "aria-label": snapToGrid ? "Disable snap to grid" : "Enable snap to grid",
267
- children: /* @__PURE__ */ jsx2(Grid3x3, { size: 14 })
217
+ className: `wb-btn wb-btn--secondary wb-btn--icon-only zoom-bar__action${s ? " is-active" : ""}`,
218
+ onClick: () => w((h) => !h),
219
+ title: s ? "Disable snap to grid" : "Enable snap to grid",
220
+ "aria-label": s ? "Disable snap to grid" : "Enable snap to grid",
221
+ children: /* @__PURE__ */ n(Ee, { size: 14 })
268
222
  }
269
223
  ),
270
- extraActions
224
+ e
271
225
  ]
272
226
  }
273
227
  );
274
228
  }
275
-
276
- // src/Minimap.tsx
277
- import { useRef } from "react";
278
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
279
- var MAP_W = 200;
280
- var MAP_H = 150;
281
- var PADDING = 40;
282
- var MIN_WORLD_SIZE = 1;
283
- function Minimap({ loading = false }) {
284
- useWhiteboardStore((s) => s.registryVersion);
285
- const offset = useWhiteboardStore((s) => s.offset);
286
- const scale = useWhiteboardStore((s) => s.scale);
287
- const viewportSize = useWhiteboardStore((s) => s.viewportSize);
288
- const panels = useWhiteboardStore((s) => s.panels);
289
- const setOffset = useWhiteboardStore((s) => s.setOffset);
290
- const setScale = useWhiteboardStore((s) => s.setScale);
291
- const focusPanel = useWhiteboardStore((s) => s.focusPanel);
292
- const containerRef = useRef(null);
293
- const dragging = useRef(false);
294
- const lastPanelTapRef = useRef(null);
295
- const rectEntries = Array.from(panels.entries());
296
- const visibleRectEntries = rectEntries.filter(([, rect]) => Number.isFinite(rect.width) && Number.isFinite(rect.height));
297
- const rects = visibleRectEntries.map(([, rect]) => rect);
298
- if (loading || rects.length === 0) {
299
- return /* @__PURE__ */ jsx3("div", { className: "minimap minimap--loading", style: { width: MAP_W, height: MAP_H }, children: /* @__PURE__ */ jsx3("div", { className: "minimap__loading", children: /* @__PURE__ */ jsx3(Loader2, { size: 14, className: "icon-spin" }) }) });
300
- }
301
- const viewportWidth = viewportSize.width || window.innerWidth;
302
- const viewportHeight = viewportSize.height || window.innerHeight;
303
- const vpW = viewportWidth / scale;
304
- const vpH = viewportHeight / scale;
305
- const vpX = -offset.x / scale;
306
- const vpY = -offset.y / scale;
307
- let minX = Infinity;
308
- let minY = Infinity;
309
- let maxX = -Infinity;
310
- let maxY = -Infinity;
311
- for (const r of rects) {
312
- minX = Math.min(minX, r.x);
313
- minY = Math.min(minY, r.y);
314
- maxX = Math.max(maxX, r.x + r.width);
315
- maxY = Math.max(maxY, r.y + r.height);
316
- }
317
- minX -= PADDING;
318
- minY -= PADDING;
319
- maxX += PADDING;
320
- maxY += PADDING;
321
- const worldW = Math.max(MIN_WORLD_SIZE, maxX - minX);
322
- const worldH = Math.max(MIN_WORLD_SIZE, maxY - minY);
323
- const mapScale = Math.min(MAP_W / worldW, MAP_H / worldH);
324
- const contentW = worldW * mapScale;
325
- const contentH = worldH * mapScale;
326
- const mapOffsetX = (MAP_W - contentW) / 2;
327
- const mapOffsetY = (MAP_H - contentH) / 2;
328
- const toMapX = (wx) => mapOffsetX + (wx - minX) * mapScale;
329
- const toMapY = (wy) => mapOffsetY + (wy - minY) * mapScale;
330
- const clientToWorld = (clientX, clientY) => {
331
- if (!containerRef.current) return;
332
- const mapRect = containerRef.current.getBoundingClientRect();
333
- const localX = Math.min(MAP_W, Math.max(0, clientX - mapRect.left));
334
- const localY = Math.min(MAP_H, Math.max(0, clientY - mapRect.top));
335
- const boundedX = Math.min(contentW + mapOffsetX, Math.max(mapOffsetX, localX));
336
- const boundedY = Math.min(contentH + mapOffsetY, Math.max(mapOffsetY, localY));
337
- const worldX = (boundedX - mapOffsetX) / mapScale + minX;
338
- const worldY = (boundedY - mapOffsetY) / mapScale + minY;
339
- return { worldX, worldY };
340
- };
341
- const centerToWorld = (worldX, worldY, targetScale) => {
342
- const clampedScale = Math.min(3, Math.max(0.2, targetScale));
343
- setScale(clampedScale);
344
- setOffset({
345
- x: viewportWidth / 2 - worldX * clampedScale,
346
- y: viewportHeight / 2 - worldY * clampedScale
229
+ const ee = 200, te = 150, de = 40, xe = 1;
230
+ function Ue({ loading: e = !1 }) {
231
+ p((o) => o.registryVersion);
232
+ const t = p((o) => o.offset), r = p((o) => o.scale), s = p((o) => o.viewportSize), a = p((o) => o.panels), u = p((o) => o.setOffset), w = p((o) => o.setScale), f = p((o) => o.focusPanel), m = S(null), g = S(!1), h = S(null), k = Array.from(a.entries()).filter(([, o]) => Number.isFinite(o.width) && Number.isFinite(o.height)), _ = k.map(([, o]) => o);
233
+ if (e || _.length === 0)
234
+ return /* @__PURE__ */ n("div", { className: "minimap minimap--loading", style: { width: ee, height: te }, children: /* @__PURE__ */ n("div", { className: "minimap__loading", children: /* @__PURE__ */ n(fe, { size: 14, className: "icon-spin" }) }) });
235
+ const v = s.width || window.innerWidth, P = s.height || window.innerHeight, L = v / r, B = P / r, $ = -t.x / r, V = -t.y / r;
236
+ let F = 1 / 0, c = 1 / 0, R = -1 / 0, W = -1 / 0;
237
+ for (const o of _)
238
+ F = Math.min(F, o.x), c = Math.min(c, o.y), R = Math.max(R, o.x + o.width), W = Math.max(W, o.y + o.height);
239
+ F -= de, c -= de, R += de, W += de;
240
+ const C = Math.max(xe, R - F), O = Math.max(xe, W - c), z = Math.min(ee / C, te / O), E = C * z, U = O * z, Z = (ee - E) / 2, D = (te - U) / 2, q = (o) => Z + (o - F) * z, j = (o) => D + (o - c) * z, Q = (o, y) => {
241
+ if (!m.current) return;
242
+ const x = m.current.getBoundingClientRect(), G = Math.min(ee, Math.max(0, o - x.left)), A = Math.min(te, Math.max(0, y - x.top)), ae = Math.min(E + Z, Math.max(Z, G)), oe = Math.min(U + D, Math.max(D, A)), ie = (ae - Z) / z + F, ce = (oe - D) / z + c;
243
+ return { worldX: ie, worldY: ce };
244
+ }, K = (o, y, x) => {
245
+ const G = Math.min(3, Math.max(0.2, x));
246
+ w(G), u({
247
+ x: v / 2 - o * G,
248
+ y: P / 2 - y * G
347
249
  });
250
+ }, se = (o, y) => {
251
+ const x = Q(o, y);
252
+ x && K(x.worldX, x.worldY, r);
253
+ }, be = (o) => {
254
+ o.stopPropagation(), o.preventDefault(), g.current = !0, o.currentTarget.setPointerCapture(o.pointerId), se(o.clientX, o.clientY);
255
+ }, i = (o) => {
256
+ g.current && se(o.clientX, o.clientY);
257
+ }, b = () => {
258
+ g.current = !1;
348
259
  };
349
- const panTo = (clientX, clientY) => {
350
- const world = clientToWorld(clientX, clientY);
351
- if (!world) return;
352
- centerToWorld(world.worldX, world.worldY, scale);
353
- };
354
- const onDown = (e) => {
355
- e.stopPropagation();
356
- e.preventDefault();
357
- dragging.current = true;
358
- e.currentTarget.setPointerCapture(e.pointerId);
359
- panTo(e.clientX, e.clientY);
360
- };
361
- const onMove = (e) => {
362
- if (!dragging.current) return;
363
- panTo(e.clientX, e.clientY);
364
- };
365
- const onUp = () => {
366
- dragging.current = false;
367
- };
368
- const onWheel = (e) => {
369
- e.preventDefault();
370
- e.stopPropagation();
371
- const world = clientToWorld(e.clientX, e.clientY);
372
- if (!world) return;
373
- const factor = e.deltaY > 0 ? 0.9 : 1.1;
374
- centerToWorld(world.worldX, world.worldY, scale * factor);
375
- };
376
- return /* @__PURE__ */ jsxs3(
260
+ return /* @__PURE__ */ d(
377
261
  "div",
378
262
  {
379
- ref: containerRef,
380
- onPointerDown: onDown,
381
- onPointerMove: onMove,
382
- onPointerUp: onUp,
383
- onPointerCancel: onUp,
384
- onWheel,
263
+ ref: m,
264
+ onPointerDown: be,
265
+ onPointerMove: i,
266
+ onPointerUp: b,
267
+ onPointerCancel: b,
268
+ onWheel: (o) => {
269
+ o.preventDefault(), o.stopPropagation();
270
+ const y = Q(o.clientX, o.clientY);
271
+ if (!y) return;
272
+ const x = o.deltaY > 0 ? 0.9 : 1.1;
273
+ K(y.worldX, y.worldY, r * x);
274
+ },
385
275
  className: "minimap",
386
276
  style: {
387
- width: MAP_W,
388
- height: MAP_H
277
+ width: ee,
278
+ height: te
389
279
  },
390
280
  children: [
391
- visibleRectEntries.map(([id, r]) => /* @__PURE__ */ jsx3(
281
+ k.map(([o, y]) => /* @__PURE__ */ n(
392
282
  "div",
393
283
  {
394
284
  className: "minimap__panel",
395
- onPointerDown: (event) => {
396
- event.stopPropagation();
285
+ onPointerDown: (x) => {
286
+ x.stopPropagation();
397
287
  },
398
- onPointerUp: (event) => {
399
- event.stopPropagation();
400
- const now = Date.now();
401
- const last = lastPanelTapRef.current;
402
- if (last && last.id === id && now - last.time < 300) {
403
- event.preventDefault();
404
- focusPanel(r, { padding: r.focusPadding, maxScale: r.focusMaxScale });
405
- lastPanelTapRef.current = null;
288
+ onPointerUp: (x) => {
289
+ x.stopPropagation();
290
+ const G = Date.now(), A = h.current;
291
+ if (A && A.id === o && G - A.time < 300) {
292
+ x.preventDefault(), f(y, { padding: y.focusPadding, maxScale: y.focusMaxScale }), h.current = null;
406
293
  return;
407
294
  }
408
- lastPanelTapRef.current = { id, time: now };
295
+ h.current = { id: o, time: G };
409
296
  },
410
- onDoubleClick: (event) => {
411
- event.preventDefault();
412
- event.stopPropagation();
413
- focusPanel(r, { padding: r.focusPadding, maxScale: r.focusMaxScale });
297
+ onDoubleClick: (x) => {
298
+ x.preventDefault(), x.stopPropagation(), f(y, { padding: y.focusPadding, maxScale: y.focusMaxScale });
414
299
  },
415
300
  style: {
416
- left: toMapX(r.x),
417
- top: toMapY(r.y),
418
- width: Math.max(1, r.width * mapScale),
419
- height: Math.max(1, r.height * mapScale)
301
+ left: q(y.x),
302
+ top: j(y.y),
303
+ width: Math.max(1, y.width * z),
304
+ height: Math.max(1, y.height * z)
420
305
  }
421
306
  },
422
- id
307
+ o
423
308
  )),
424
- /* @__PURE__ */ jsx3(
309
+ /* @__PURE__ */ n(
425
310
  "div",
426
311
  {
427
312
  className: "minimap__viewport",
428
313
  style: {
429
- left: toMapX(vpX),
430
- top: toMapY(vpY),
431
- width: vpW * mapScale,
432
- height: vpH * mapScale
314
+ left: q($),
315
+ top: j(V),
316
+ width: L * z,
317
+ height: B * z
433
318
  }
434
319
  }
435
320
  )
@@ -437,384 +322,261 @@ function Minimap({ loading = false }) {
437
322
  }
438
323
  );
439
324
  }
440
-
441
- // src/WhiteboardShell.tsx
442
- import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
443
- function WhiteboardShell({ children, showMinimap = true, minimapLoading = false, extraActions }) {
444
- const offset = useWhiteboardStore((s) => s.offset);
445
- const scale = useWhiteboardStore((s) => s.scale);
446
- const registryVersion = useWhiteboardStore((s) => s.registryVersion);
447
- const viewportSize = useWhiteboardStore((s) => s.viewportSize);
448
- const setOffset = useWhiteboardStore((s) => s.setOffset);
449
- const setScale = useWhiteboardStore((s) => s.setScale);
450
- const setViewportSize = useWhiteboardStore((s) => s.setViewportSize);
451
- const shellRef = useRef2(null);
452
- const panning = useRef2(false);
453
- const last = useRef2({ x: 0, y: 0 });
454
- const activePointerId = useRef2(null);
455
- const scaleRef = useRef2(scale);
456
- const hasFitted = useRef2(false);
457
- useEffect2(() => {
458
- return () => {
459
- useWhiteboardStore.getState().resetSession();
460
- };
461
- }, []);
462
- useEffect2(() => {
463
- scaleRef.current = scale;
464
- }, [scale]);
465
- useEffect2(() => {
466
- const shell = shellRef.current;
467
- if (!shell) return;
468
- const updateViewport = () => {
469
- const rect = shell.getBoundingClientRect();
470
- setViewportSize({
471
- width: Math.max(0, rect.width),
472
- height: Math.max(0, rect.height)
325
+ function xt({ children: e, showMinimap: t = !0, minimapLoading: r = !1, extraActions: s }) {
326
+ const a = p((c) => c.offset), u = p((c) => c.scale), w = p((c) => c.registryVersion), f = p((c) => c.viewportSize), m = p((c) => c.setOffset), g = p((c) => c.setScale), h = p((c) => c.setViewportSize), M = S(null), k = S(!1), _ = S({ x: 0, y: 0 }), v = S(null), P = S(u), L = S(!1);
327
+ X(() => () => {
328
+ p.getState().resetSession();
329
+ }, []), X(() => {
330
+ P.current = u;
331
+ }, [u]), X(() => {
332
+ const c = M.current;
333
+ if (!c) return;
334
+ const R = () => {
335
+ const C = c.getBoundingClientRect();
336
+ h({
337
+ width: Math.max(0, C.width),
338
+ height: Math.max(0, C.height)
473
339
  });
474
340
  };
475
- updateViewport();
476
- if (typeof ResizeObserver === "undefined") return;
477
- const observer = new ResizeObserver(updateViewport);
478
- observer.observe(shell);
479
- return () => observer.disconnect();
480
- }, [setViewportSize]);
481
- useEffect2(() => {
482
- if (hasFitted.current) return;
483
- const { panels } = useWhiteboardStore.getState();
484
- if (panels.size === 0 || viewportSize.width <= 0 || viewportSize.height <= 0) return;
485
- hasFitted.current = true;
486
- requestAnimationFrame(() => {
487
- useWhiteboardStore.getState().fitToContent();
488
- });
489
- }, [registryVersion, viewportSize]);
490
- const onDown = useCallback((e) => {
491
- if (e.target !== e.currentTarget) return;
492
- if (e.button === 0 || e.button === 1) {
493
- panning.current = true;
494
- activePointerId.current = e.pointerId;
495
- last.current = { x: e.clientX, y: e.clientY };
496
- e.currentTarget.setPointerCapture(e.pointerId);
497
- e.preventDefault();
498
- }
499
- }, []);
500
- const onMove = useCallback((e) => {
501
- if (!panning.current || activePointerId.current !== e.pointerId) return;
502
- const dx = e.movementX ?? e.clientX - last.current.x;
503
- const dy = e.movementY ?? e.clientY - last.current.y;
504
- setOffset((p) => ({ x: p.x + dx, y: p.y + dy }));
505
- last.current = { x: e.clientX, y: e.clientY };
506
- }, [setOffset]);
507
- const stopPan = useCallback((e) => {
508
- if (activePointerId.current !== null) {
341
+ if (R(), typeof ResizeObserver > "u") return;
342
+ const W = new ResizeObserver(R);
343
+ return W.observe(c), () => W.disconnect();
344
+ }, [h]), X(() => {
345
+ if (L.current) return;
346
+ const { panels: c } = p.getState();
347
+ c.size === 0 || f.width <= 0 || f.height <= 0 || (L.current = !0, requestAnimationFrame(() => {
348
+ p.getState().fitToContent();
349
+ }));
350
+ }, [w, f]);
351
+ const B = H((c) => {
352
+ c.target === c.currentTarget && (c.button === 0 || c.button === 1) && (k.current = !0, v.current = c.pointerId, _.current = { x: c.clientX, y: c.clientY }, c.currentTarget.setPointerCapture(c.pointerId), c.preventDefault());
353
+ }, []), $ = H((c) => {
354
+ if (!k.current || v.current !== c.pointerId) return;
355
+ const R = c.movementX ?? c.clientX - _.current.x, W = c.movementY ?? c.clientY - _.current.y;
356
+ m((C) => ({ x: C.x + R, y: C.y + W })), _.current = { x: c.clientX, y: c.clientY };
357
+ }, [m]), V = H((c) => {
358
+ if (v.current !== null)
509
359
  try {
510
- e.currentTarget.releasePointerCapture(activePointerId.current);
360
+ c.currentTarget.releasePointerCapture(v.current);
511
361
  } catch {
512
362
  }
513
- }
514
- panning.current = false;
515
- activePointerId.current = null;
516
- }, []);
517
- const onWheel = useCallback((e) => {
518
- const s = scaleRef.current;
519
- const rect = e.currentTarget.getBoundingClientRect();
520
- const anchor = { x: e.clientX - rect.left, y: e.clientY - rect.top };
521
- const nextScale = Math.min(3, Math.max(0.2, s * (e.deltaY > 0 ? 0.9 : 1.1)));
522
- const ratio = nextScale / s;
523
- setOffset((prev) => ({
524
- x: anchor.x - (anchor.x - prev.x) * ratio,
525
- y: anchor.y - (anchor.y - prev.y) * ratio
526
- }));
527
- setScale(nextScale);
528
- }, [setOffset, setScale]);
529
- return /* @__PURE__ */ jsxs4(Fragment, { children: [
530
- /* @__PURE__ */ jsx4(
363
+ k.current = !1, v.current = null;
364
+ }, []), F = H((c) => {
365
+ const R = P.current, W = c.currentTarget.getBoundingClientRect(), C = { x: c.clientX - W.left, y: c.clientY - W.top }, O = Math.min(3, Math.max(0.2, R * (c.deltaY > 0 ? 0.9 : 1.1))), z = O / R;
366
+ m((E) => ({
367
+ x: C.x - (C.x - E.x) * z,
368
+ y: C.y - (C.y - E.y) * z
369
+ })), g(O);
370
+ }, [m, g]);
371
+ return /* @__PURE__ */ d(re, { children: [
372
+ /* @__PURE__ */ n(
531
373
  "div",
532
374
  {
533
- ref: shellRef,
534
- onPointerDown: onDown,
535
- onPointerMove: onMove,
536
- onPointerUp: stopPan,
537
- onPointerCancel: stopPan,
538
- onWheel,
539
- onContextMenu: (e) => e.preventDefault(),
375
+ ref: M,
376
+ onPointerDown: B,
377
+ onPointerMove: $,
378
+ onPointerUp: V,
379
+ onPointerCancel: V,
380
+ onWheel: F,
381
+ onContextMenu: (c) => c.preventDefault(),
540
382
  className: "whiteboard-shell",
541
- children: /* @__PURE__ */ jsxs4(
383
+ children: /* @__PURE__ */ d(
542
384
  "div",
543
385
  {
544
386
  className: "whiteboard-canvas",
545
- style: { transform: `translate(${offset.x}px, ${offset.y}px) scale(${scale})` },
387
+ style: { transform: `translate(${a.x}px, ${a.y}px) scale(${u})` },
546
388
  children: [
547
- /* @__PURE__ */ jsx4("div", { className: "whiteboard-grid", "aria-hidden": true }),
548
- children
389
+ /* @__PURE__ */ n("div", { className: "whiteboard-grid", "aria-hidden": !0 }),
390
+ e
549
391
  ]
550
392
  }
551
393
  )
552
394
  }
553
395
  ),
554
- /* @__PURE__ */ jsx4(ZoomBar, { extraActions }),
555
- showMinimap ? /* @__PURE__ */ jsx4(Minimap, { loading: minimapLoading }) : null
396
+ /* @__PURE__ */ n(je, { extraActions: s }),
397
+ t ? /* @__PURE__ */ n(Ue, { loading: r }) : null
556
398
  ] });
557
399
  }
558
-
559
- // src/FloatingPanel.tsx
560
- import { useRef as useRef3, useId, useState, useCallback as useCallback2, useEffect as useEffect3, useLayoutEffect, memo } from "react";
561
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
562
- var FloatingPanel = memo(function FloatingPanel2({
563
- title,
564
- defaultPosition,
565
- width = 300,
566
- className,
567
- trackRect: trackRectRef,
568
- focusable,
569
- focusPadding = 40,
570
- focusMaxScale = 1.5,
571
- headerActions,
572
- children
400
+ const St = Te(function({
401
+ title: t,
402
+ defaultPosition: r,
403
+ width: s = 300,
404
+ className: a,
405
+ trackRect: u,
406
+ focusable: w,
407
+ focusPadding: f = 40,
408
+ focusMaxScale: m = 1.5,
409
+ headerActions: g,
410
+ children: h
573
411
  }) {
574
- const panelId = useId();
575
- const [pos, setPos] = useState(defaultPosition);
576
- const dragging = useRef3(false);
577
- const posRef = useRef3(pos);
578
- const elRef = useRef3(null);
579
- const lastRegisteredRectRef = useRef3(null);
580
- const scale = useWhiteboardStore((s) => s.scale);
581
- const snapToGrid = useWhiteboardStore((s) => s.snapToGrid);
582
- const snapGridSize = useWhiteboardStore((s) => s.snapGridSize);
583
- const register = useWhiteboardStore((s) => s.register);
584
- const unregister = useWhiteboardStore((s) => s.unregister);
585
- const registerReset = useWhiteboardStore((s) => s.registerReset);
586
- const unregisterReset = useWhiteboardStore((s) => s.unregisterReset);
587
- const focusPanel = useWhiteboardStore((s) => s.focusPanel);
588
- const scaleRef = useRef3(scale);
589
- const snapToGridRef = useRef3(false);
590
- const snapGridSizeRef = useRef3(20);
591
- const defaultPosRef = useRef3(defaultPosition);
592
- const cleanupRef = useRef3(null);
593
- const lastTapRef = useRef3(null);
594
- useEffect3(() => {
595
- scaleRef.current = scale;
596
- }, [scale]);
597
- useEffect3(() => {
598
- snapToGridRef.current = snapToGrid;
599
- snapGridSizeRef.current = snapGridSize;
600
- }, [snapToGrid, snapGridSize]);
601
- useEffect3(() => {
602
- const onSnapNow = () => {
603
- const snapSize = snapGridSizeRef.current;
604
- setPos((current) => {
605
- const next = {
606
- x: Math.round(current.x / snapSize) * snapSize,
607
- y: Math.round(current.y / snapSize) * snapSize
412
+ const M = Re(), [k, _] = Se(r), v = S(!1), P = S(k), L = S(null), B = S(null), $ = p((i) => i.scale), V = p((i) => i.snapToGrid), F = p((i) => i.snapGridSize), c = p((i) => i.register), R = p((i) => i.unregister), W = p((i) => i.registerReset), C = p((i) => i.unregisterReset), O = p((i) => i.focusPanel), z = S($), E = S(!1), U = S(20), Z = S(r), D = S(null), q = S(null);
413
+ X(() => {
414
+ z.current = $;
415
+ }, [$]), X(() => {
416
+ E.current = V, U.current = F;
417
+ }, [V, F]), X(() => {
418
+ const i = () => {
419
+ const b = U.current;
420
+ _((N) => {
421
+ const o = {
422
+ x: Math.round(N.x / b) * b,
423
+ y: Math.round(N.y / b) * b
608
424
  };
609
- return next.x === current.x && next.y === current.y ? current : next;
425
+ return o.x === N.x && o.y === N.y ? N : o;
610
426
  });
611
427
  };
612
- window.addEventListener("whiteboard-snap-now", onSnapNow);
613
- return () => window.removeEventListener("whiteboard-snap-now", onSnapNow);
614
- }, []);
615
- useEffect3(() => {
616
- posRef.current = pos;
617
- }, [pos]);
618
- const registerRect = useCallback2(() => {
619
- const el = elRef.current;
620
- if (!el) return;
621
- const nextRect = {
622
- x: posRef.current.x,
623
- y: posRef.current.y,
624
- width: el.offsetWidth,
625
- height: el.offsetHeight,
626
- focusPadding,
627
- focusMaxScale
628
- };
629
- const prev = lastRegisteredRectRef.current;
630
- if (prev && prev.x === nextRect.x && prev.y === nextRect.y && prev.width === nextRect.width && prev.height === nextRect.height && prev.focusPadding === nextRect.focusPadding && prev.focusMaxScale === nextRect.focusMaxScale) {
631
- return;
632
- }
633
- lastRegisteredRectRef.current = nextRect;
634
- register(panelId, nextRect);
635
- if (trackRectRef) {
636
- trackRectRef.current = nextRect;
637
- }
638
- }, [focusMaxScale, focusPadding, panelId, register, trackRectRef]);
639
- const getCurrentRect = useCallback2(() => {
640
- const el = elRef.current;
641
- if (!el) return null;
642
- return {
643
- x: posRef.current.x,
644
- y: posRef.current.y,
645
- width: el.offsetWidth,
646
- height: el.offsetHeight,
647
- focusPadding,
648
- focusMaxScale
649
- };
650
- }, [focusMaxScale, focusPadding]);
651
- const handleFocus = useCallback2(() => {
652
- const rect = getCurrentRect();
653
- if (!rect) return;
654
- focusPanel(rect, { padding: focusPadding, maxScale: focusMaxScale });
655
- }, [focusPanel, focusPadding, focusMaxScale, getCurrentRect]);
656
- useEffect3(() => {
657
- registerReset(panelId, () => setPos(defaultPosRef.current));
658
- return () => {
659
- cleanupRef.current?.();
660
- unregister(panelId);
661
- unregisterReset(panelId);
662
- lastRegisteredRectRef.current = null;
663
- };
664
- }, [panelId, registerReset, unregister, unregisterReset]);
665
- useLayoutEffect(() => {
666
- registerRect();
667
- }, [pos.x, pos.y, width, registerRect]);
668
- useEffect3(() => {
669
- const el = elRef.current;
670
- if (!el) return;
671
- if (typeof ResizeObserver === "undefined") return;
672
- const obs = new ResizeObserver(() => {
673
- registerRect();
428
+ return window.addEventListener("whiteboard-snap-now", i), () => window.removeEventListener("whiteboard-snap-now", i);
429
+ }, []), X(() => {
430
+ P.current = k;
431
+ }, [k]);
432
+ const j = H(() => {
433
+ const i = L.current;
434
+ if (!i) return;
435
+ const b = {
436
+ x: P.current.x,
437
+ y: P.current.y,
438
+ width: i.offsetWidth,
439
+ height: i.offsetHeight,
440
+ focusPadding: f,
441
+ focusMaxScale: m
442
+ }, N = B.current;
443
+ N && N.x === b.x && N.y === b.y && N.width === b.width && N.height === b.height && N.focusPadding === b.focusPadding && N.focusMaxScale === b.focusMaxScale || (B.current = b, c(M, b), u && (u.current = b));
444
+ }, [m, f, M, c, u]), Q = H(() => {
445
+ const i = L.current;
446
+ return i ? {
447
+ x: P.current.x,
448
+ y: P.current.y,
449
+ width: i.offsetWidth,
450
+ height: i.offsetHeight,
451
+ focusPadding: f,
452
+ focusMaxScale: m
453
+ } : null;
454
+ }, [m, f]), K = H(() => {
455
+ const i = Q();
456
+ i && O(i, { padding: f, maxScale: m });
457
+ }, [O, f, m, Q]);
458
+ X(() => (W(M, () => _(Z.current)), () => {
459
+ var i;
460
+ (i = D.current) == null || i.call(D), R(M), C(M), B.current = null;
461
+ }), [M, W, R, C]), We(() => {
462
+ j();
463
+ }, [k.x, k.y, s, j]), X(() => {
464
+ const i = L.current;
465
+ if (!i || typeof ResizeObserver > "u") return;
466
+ const b = new ResizeObserver(() => {
467
+ j();
674
468
  });
675
- obs.observe(el);
676
- return () => obs.disconnect();
677
- }, [registerRect]);
678
- const onDown = useCallback2((e) => {
679
- if (e.button !== 0) return;
680
- dragging.current = true;
681
- const startX = e.clientX;
682
- const startY = e.clientY;
683
- const startPosX = posRef.current.x;
684
- const startPosY = posRef.current.y;
685
- const startScale = scaleRef.current;
686
- e.preventDefault();
687
- e.stopPropagation();
688
- e.target.setPointerCapture(e.pointerId);
689
- const move = (ev) => {
690
- if (!dragging.current) return;
691
- const rawX = startPosX + (ev.clientX - startX) / startScale;
692
- const rawY = startPosY + (ev.clientY - startY) / startScale;
693
- const snapSize = snapGridSizeRef.current;
694
- const nextX = snapToGridRef.current ? Math.round(rawX / snapSize) * snapSize : rawX;
695
- const nextY = snapToGridRef.current ? Math.round(rawY / snapSize) * snapSize : rawY;
696
- setPos({
697
- x: nextX,
698
- y: nextY
469
+ return b.observe(i), () => b.disconnect();
470
+ }, [j]);
471
+ const se = H((i) => {
472
+ var ae;
473
+ if (i.button !== 0) return;
474
+ v.current = !0;
475
+ const b = i.clientX, N = i.clientY, o = P.current.x, y = P.current.y, x = z.current;
476
+ i.preventDefault(), i.stopPropagation(), i.target.setPointerCapture(i.pointerId);
477
+ const G = (oe) => {
478
+ if (!v.current) return;
479
+ const ie = o + (oe.clientX - b) / x, ce = y + (oe.clientY - N) / x, le = U.current, Ce = E.current ? Math.round(ie / le) * le : ie, ze = E.current ? Math.round(ce / le) * le : ce;
480
+ _({
481
+ x: Ce,
482
+ y: ze
699
483
  });
484
+ }, A = () => {
485
+ v.current = !1, window.removeEventListener("pointermove", G), window.removeEventListener("pointerup", A), D.current = null;
700
486
  };
701
- const up = () => {
702
- dragging.current = false;
703
- window.removeEventListener("pointermove", move);
704
- window.removeEventListener("pointerup", up);
705
- cleanupRef.current = null;
706
- };
707
- cleanupRef.current?.();
708
- window.addEventListener("pointermove", move);
709
- window.addEventListener("pointerup", up);
710
- cleanupRef.current = up;
711
- }, []);
712
- const panelClassName = className ? `floating-panel ${className}` : "floating-panel";
713
- return /* @__PURE__ */ jsxs5(
487
+ (ae = D.current) == null || ae.call(D), window.addEventListener("pointermove", G), window.addEventListener("pointerup", A), D.current = A;
488
+ }, []), be = a ? `floating-panel ${a}` : "floating-panel";
489
+ return /* @__PURE__ */ d(
714
490
  "div",
715
491
  {
716
- ref: elRef,
717
- className: panelClassName,
718
- style: { left: pos.x, top: pos.y, width },
719
- onPointerDown: (e) => e.stopPropagation(),
720
- onPointerUp: (e) => {
721
- if (dragging.current) return;
722
- const now = Date.now();
723
- const last = lastTapRef.current;
724
- if (last && now - last.time < 300) {
725
- const dx = e.clientX - last.x;
726
- const dy = e.clientY - last.y;
727
- if (dx * dx + dy * dy < 100) {
728
- e.stopPropagation();
729
- handleFocus();
730
- lastTapRef.current = null;
492
+ ref: L,
493
+ className: be,
494
+ style: { left: k.x, top: k.y, width: s },
495
+ onPointerDown: (i) => i.stopPropagation(),
496
+ onPointerUp: (i) => {
497
+ if (v.current) return;
498
+ const b = Date.now(), N = q.current;
499
+ if (N && b - N.time < 300) {
500
+ const o = i.clientX - N.x, y = i.clientY - N.y;
501
+ if (o * o + y * y < 100) {
502
+ i.stopPropagation(), K(), q.current = null;
731
503
  return;
732
504
  }
733
505
  }
734
- lastTapRef.current = { time: now, x: e.clientX, y: e.clientY };
506
+ q.current = { time: b, x: i.clientX, y: i.clientY };
735
507
  },
736
- onWheel: (e) => e.stopPropagation(),
737
- onDoubleClick: (e) => {
738
- e.stopPropagation();
739
- handleFocus();
508
+ onWheel: (i) => i.stopPropagation(),
509
+ onDoubleClick: (i) => {
510
+ i.stopPropagation(), K();
740
511
  },
741
512
  children: [
742
- /* @__PURE__ */ jsxs5("div", { onPointerDown: onDown, className: "floating-panel__header", children: [
743
- /* @__PURE__ */ jsx5("strong", { className: "floating-panel__title", children: title }),
744
- headerActions,
745
- focusable && /* @__PURE__ */ jsx5(
513
+ /* @__PURE__ */ d("div", { onPointerDown: se, className: "floating-panel__header", children: [
514
+ /* @__PURE__ */ n("strong", { className: "floating-panel__title", children: t }),
515
+ g,
516
+ w && /* @__PURE__ */ n(
746
517
  "button",
747
518
  {
748
519
  type: "button",
749
520
  className: "wb-btn wb-btn--secondary wb-btn--icon-only floating-panel__focus",
750
- onClick: handleFocus,
751
- onPointerDown: (e) => e.stopPropagation(),
521
+ onClick: K,
522
+ onPointerDown: (i) => i.stopPropagation(),
752
523
  title: "Focus on this panel",
753
524
  "aria-label": "Focus on this panel",
754
- children: /* @__PURE__ */ jsx5(Maximize2, { size: 14 })
525
+ children: /* @__PURE__ */ n(Ae, { size: 14 })
755
526
  }
756
527
  )
757
528
  ] }),
758
- /* @__PURE__ */ jsx5("div", { className: "floating-panel__body", children })
529
+ /* @__PURE__ */ n("div", { className: "floating-panel__body", children: h })
759
530
  ]
760
531
  }
761
532
  );
762
533
  });
763
- function usePanelRect(initial) {
764
- const ref = useRef3({ ...initial, width: 0, height: 0 });
765
- return ref;
766
- }
767
- function belowPanel(rect, gap = WHITEBOARD_GRID) {
768
- return { x: rect.x, y: rect.y + rect.height + gap };
769
- }
770
-
771
- // src/ConfirmDialog.tsx
772
- import { useEffect as useEffect4 } from "react";
773
- import { createPortal } from "react-dom";
774
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
775
- function ConfirmDialog({
776
- open,
777
- title,
778
- message,
779
- onConfirm,
780
- onCancel,
781
- confirmLabel = "Confirm",
782
- loading,
783
- error
534
+ function Mt(e) {
535
+ return S({ ...e, width: 0, height: 0 });
536
+ }
537
+ function kt(e, t = he) {
538
+ return { x: e.x, y: e.y + e.height + t };
539
+ }
540
+ function _t({
541
+ open: e,
542
+ title: t,
543
+ message: r,
544
+ onConfirm: s,
545
+ onCancel: a,
546
+ confirmLabel: u = "Confirm",
547
+ loading: w,
548
+ error: f
784
549
  }) {
785
- useEffect4(() => {
786
- if (!open) return;
787
- const onKey = (e) => {
788
- if (e.key === "Escape") onCancel();
550
+ return X(() => {
551
+ if (!e) return;
552
+ const m = (g) => {
553
+ g.key === "Escape" && a();
789
554
  };
790
- window.addEventListener("keydown", onKey);
791
- return () => window.removeEventListener("keydown", onKey);
792
- }, [open, onCancel]);
793
- if (!open || typeof document === "undefined") return null;
794
- return createPortal(
795
- /* @__PURE__ */ jsx6("div", { className: "confirm-modal-overlay", onMouseDown: onCancel, children: /* @__PURE__ */ jsxs6(
555
+ return window.addEventListener("keydown", m), () => window.removeEventListener("keydown", m);
556
+ }, [e, a]), !e || typeof document > "u" ? null : Ye(
557
+ /* @__PURE__ */ n("div", { className: "confirm-modal-overlay", onMouseDown: a, children: /* @__PURE__ */ d(
796
558
  "div",
797
559
  {
798
560
  className: "confirm-modal",
799
561
  role: "dialog",
800
562
  "aria-modal": "true",
801
- "aria-label": title,
802
- onMouseDown: (e) => e.stopPropagation(),
563
+ "aria-label": t,
564
+ onMouseDown: (m) => m.stopPropagation(),
803
565
  children: [
804
- /* @__PURE__ */ jsxs6("div", { className: "confirm-modal__header", children: [
805
- /* @__PURE__ */ jsxs6("span", { className: "confirm-modal__title", children: [
806
- /* @__PURE__ */ jsx6(AlertTriangle, { size: 16 }),
807
- title
566
+ /* @__PURE__ */ d("div", { className: "confirm-modal__header", children: [
567
+ /* @__PURE__ */ d("span", { className: "confirm-modal__title", children: [
568
+ /* @__PURE__ */ n(Oe, { size: 16 }),
569
+ t
808
570
  ] }),
809
- /* @__PURE__ */ jsx6("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only", onClick: onCancel, "aria-label": "Close dialog", children: /* @__PURE__ */ jsx6(X, { size: 14 }) })
571
+ /* @__PURE__ */ n("button", { type: "button", className: "wb-btn wb-btn--secondary wb-btn--icon-only", onClick: a, "aria-label": "Close dialog", children: /* @__PURE__ */ n(Me, { size: 14 }) })
810
572
  ] }),
811
- /* @__PURE__ */ jsx6("p", { className: "confirm-modal__message", children: message }),
812
- error && /* @__PURE__ */ jsx6("div", { className: "wb-alert wb-alert--error", children: error }),
813
- /* @__PURE__ */ jsxs6("div", { className: "wb-btn-row", children: [
814
- /* @__PURE__ */ jsx6("button", { type: "button", className: "wb-btn wb-btn--secondary", onClick: onCancel, children: "Cancel" }),
815
- /* @__PURE__ */ jsx6("button", { type: "button", className: "wb-btn wb-btn--danger", onClick: onConfirm, disabled: loading, children: loading ? "Deleting..." : /* @__PURE__ */ jsxs6(Fragment2, { children: [
816
- /* @__PURE__ */ jsx6(Check, { size: 14 }),
817
- confirmLabel
573
+ /* @__PURE__ */ n("p", { className: "confirm-modal__message", children: r }),
574
+ f && /* @__PURE__ */ n("div", { className: "wb-alert wb-alert--error", children: f }),
575
+ /* @__PURE__ */ d("div", { className: "wb-btn-row", children: [
576
+ /* @__PURE__ */ n("button", { type: "button", className: "wb-btn wb-btn--secondary", onClick: a, children: "Cancel" }),
577
+ /* @__PURE__ */ n("button", { type: "button", className: "wb-btn wb-btn--danger", onClick: s, disabled: w, children: w ? "Deleting..." : /* @__PURE__ */ d(re, { children: [
578
+ /* @__PURE__ */ n(He, { size: 14 }),
579
+ u
818
580
  ] }) })
819
581
  ] })
820
582
  ]
@@ -823,725 +585,582 @@ function ConfirmDialog({
823
585
  document.body
824
586
  );
825
587
  }
826
-
827
- // src/PanelErrorBoundary.tsx
828
- import { Component } from "react";
829
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
830
- var PanelErrorBoundary = class extends Component {
588
+ class Pt extends De {
831
589
  constructor() {
832
- super(...arguments);
833
- this.state = { error: null };
590
+ super(...arguments), this.state = { error: null };
834
591
  }
835
- static getDerivedStateFromError(error) {
836
- return { error };
592
+ static getDerivedStateFromError(t) {
593
+ return { error: t };
837
594
  }
838
595
  render() {
839
- if (this.state.error) {
840
- return /* @__PURE__ */ jsxs7("div", { className: "wb-stack wb-stack--sm", children: [
841
- /* @__PURE__ */ jsx7("div", { className: "wb-alert wb-alert--error", children: this.props.fallbackMessage ?? "This panel crashed." }),
842
- /* @__PURE__ */ jsx7(
843
- "button",
844
- {
845
- type: "button",
846
- className: "wb-btn wb-btn--secondary",
847
- onClick: () => this.setState({ error: null }),
848
- children: "Retry"
849
- }
850
- )
851
- ] });
852
- }
853
- return this.props.children;
596
+ return this.state.error ? /* @__PURE__ */ d("div", { className: "wb-stack wb-stack--sm", children: [
597
+ /* @__PURE__ */ n("div", { className: "wb-alert wb-alert--error", children: this.props.fallbackMessage ?? "This panel crashed." }),
598
+ /* @__PURE__ */ n(
599
+ "button",
600
+ {
601
+ type: "button",
602
+ className: "wb-btn wb-btn--secondary",
603
+ onClick: () => this.setState({ error: null }),
604
+ children: "Retry"
605
+ }
606
+ )
607
+ ] }) : this.props.children;
854
608
  }
855
- };
856
-
857
- // src/useWhiteboardLayout.ts
858
- import { useMemo } from "react";
859
- function useWhiteboardLayout({
860
- widths,
861
- startX = 20,
862
- y = 40,
863
- gap = 20
609
+ }
610
+ function Ct({
611
+ widths: e,
612
+ startX: t = 20,
613
+ y: r = 40,
614
+ gap: s = 20
864
615
  }) {
865
- const panelWidth = useMemo(() => {
866
- const normalized = {};
867
- for (const [key, value] of Object.entries(widths)) {
868
- normalized[key] = snapToWhiteboardGrid(value);
869
- }
870
- return normalized;
871
- }, [widths]);
872
- const layout = useMemo(
616
+ const a = ye(() => {
617
+ const f = {};
618
+ for (const [m, g] of Object.entries(e))
619
+ f[m] = ue(g);
620
+ return f;
621
+ }, [e]), u = ye(
873
622
  () => ({
874
- startX: snapToWhiteboardGrid(startX),
875
- y: snapToWhiteboardGrid(y),
876
- gap: snapToWhiteboardGrid(gap)
623
+ startX: ue(t),
624
+ y: ue(r),
625
+ gap: ue(s)
877
626
  }),
878
- [startX, y, gap]
879
- );
880
- const positions = useMemo(() => {
881
- const next = {};
882
- let x = layout.startX;
883
- for (const [key, width] of Object.entries(panelWidth)) {
884
- ;
885
- next[key] = { x, y: layout.y };
886
- x += width + layout.gap;
887
- }
888
- return next;
889
- }, [layout.gap, layout.startX, layout.y, panelWidth]);
890
- return { layout, panelWidth, positions };
891
- }
892
-
893
- // src/cn.ts
894
- function cn(...args) {
895
- return args.filter(Boolean).join(" ");
896
- }
897
-
898
- // src/Alert.tsx
899
- import { jsx as jsx8 } from "react/jsx-runtime";
900
- var toneClasses = {
627
+ [t, r, s]
628
+ ), w = ye(() => {
629
+ const f = {};
630
+ let m = u.startX;
631
+ for (const [g, h] of Object.entries(a))
632
+ f[g] = { x: m, y: u.y }, m += h + u.gap;
633
+ return f;
634
+ }, [u.gap, u.startX, u.y, a]);
635
+ return { layout: u, panelWidth: a, positions: w };
636
+ }
637
+ function l(...e) {
638
+ return e.filter(Boolean).join(" ");
639
+ }
640
+ const Ze = {
901
641
  error: "status-error",
902
642
  muted: "text-sm text-muted",
903
643
  info: "ui-alert ui-alert--info",
904
644
  success: "ui-alert ui-alert--success"
905
645
  };
906
- function Alert({ tone = "info", className, ...props }) {
907
- return /* @__PURE__ */ jsx8("p", { className: cn(toneClasses[tone], className), ...props });
908
- }
909
-
910
- // src/Button.tsx
911
- import { forwardRef } from "react";
912
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
913
- var variantClasses = {
646
+ function zt({ tone: e = "info", className: t, ...r }) {
647
+ return /* @__PURE__ */ n("p", { className: l(Ze[e], t), ...r });
648
+ }
649
+ const qe = {
914
650
  primary: "",
915
651
  secondary: "secondary-btn",
916
652
  danger: "danger-btn"
917
- };
918
- var Button = forwardRef(function Button2({
919
- variant = "primary",
920
- fullWidth = false,
921
- iconOnly = false,
922
- loading = false,
923
- disabled,
924
- className,
925
- children,
926
- loadingText,
927
- ...props
928
- }, ref) {
929
- return /* @__PURE__ */ jsx9(
653
+ }, Ke = me(function({
654
+ variant: t = "primary",
655
+ fullWidth: r = !1,
656
+ iconOnly: s = !1,
657
+ loading: a = !1,
658
+ disabled: u,
659
+ className: w,
660
+ children: f,
661
+ loadingText: m,
662
+ ...g
663
+ }, h) {
664
+ return /* @__PURE__ */ n(
930
665
  "button",
931
666
  {
932
- ref,
933
- className: cn(variantClasses[variant], fullWidth && "full-width-btn", iconOnly && "icon-only-btn", className),
934
- disabled: disabled || loading,
935
- ...props,
936
- children: loading ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
937
- /* @__PURE__ */ jsx9(Loader2, { size: 14, className: "icon-spin" }),
938
- loadingText || children
939
- ] }) : children
667
+ ref: h,
668
+ className: l(qe[t], r && "full-width-btn", s && "icon-only-btn", w),
669
+ disabled: u || a,
670
+ ...g,
671
+ children: a ? /* @__PURE__ */ d(re, { children: [
672
+ /* @__PURE__ */ n(fe, { size: 14, className: "icon-spin" }),
673
+ m || f
674
+ ] }) : f
940
675
  }
941
676
  );
942
677
  });
943
-
944
- // src/ButtonRow.tsx
945
- import { createElement } from "react";
946
- function ButtonRow({ as = "div", className, ...props }) {
947
- return createElement(as, {
948
- className: cn("button-row", className),
949
- ...props
678
+ function Je({ as: e = "div", className: t, ...r }) {
679
+ return T(e, {
680
+ className: l("button-row", t),
681
+ ...r
950
682
  });
951
683
  }
952
-
953
- // src/Chip.tsx
954
- import { jsx as jsx10 } from "react/jsx-runtime";
955
- function Chip({ className, ...props }) {
956
- return /* @__PURE__ */ jsx10("span", { className: cn("chip", className), ...props });
957
- }
958
-
959
- // src/ChoiceCard.tsx
960
- import { jsx as jsx11 } from "react/jsx-runtime";
961
- function ChoiceCard({ active = false, className, ...props }) {
962
- return /* @__PURE__ */ jsx11(
684
+ function Tt({ className: e, ...t }) {
685
+ return /* @__PURE__ */ n("span", { className: l("chip", e), ...t });
686
+ }
687
+ function Qe({ active: e = !1, className: t, ...r }) {
688
+ return /* @__PURE__ */ n(
963
689
  "button",
964
690
  {
965
691
  type: "button",
966
- className: cn("choice-card", className),
967
- "data-active": active,
968
- ...props
692
+ className: l("choice-card", t),
693
+ "data-active": e,
694
+ ...r
969
695
  }
970
696
  );
971
697
  }
972
-
973
- // src/List.tsx
974
- import { createElement as createElement2 } from "react";
975
- function List({ as = "ul", reset = true, className, ...props }) {
976
- return createElement2(as, {
977
- className: cn(reset && "list-reset", className),
978
- ...props
698
+ function pe({ as: e = "ul", reset: t = !0, className: r, ...s }) {
699
+ return T(e, {
700
+ className: l(t && "list-reset", r),
701
+ ...s
979
702
  });
980
703
  }
981
-
982
- // src/Skeleton.tsx
983
- import { createElement as createElement3 } from "react";
984
- import { jsx as jsx12 } from "react/jsx-runtime";
985
- var radiusClasses = {
704
+ const et = {
986
705
  sm: "",
987
706
  md: "skeleton--md",
988
707
  pill: "skeleton--pill"
989
708
  };
990
- function Skeleton({ as = "div", radius = "sm", className, ...props }) {
991
- return createElement3(as, {
992
- className: cn("skeleton", radiusClasses[radius], className),
993
- "aria-hidden": true,
994
- ...props
709
+ function I({ as: e = "div", radius: t = "sm", className: r, ...s }) {
710
+ return T(e, {
711
+ className: l("skeleton", et[t], r),
712
+ "aria-hidden": !0,
713
+ ...s
995
714
  });
996
715
  }
997
- function InputSkeleton(props) {
998
- const { className, ...rest } = props;
999
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-input", className), ...rest });
1000
- }
1001
- function ButtonSkeleton(props) {
1002
- const { className, ...rest } = props;
1003
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-btn", className), ...rest });
1004
- }
1005
- function IconButtonSkeleton(props) {
1006
- const { className, ...rest } = props;
1007
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-icon-btn", className), ...rest });
1008
- }
1009
- function SelectSkeleton(props) {
1010
- const { className, ...rest } = props;
1011
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-select", className), ...rest });
1012
- }
1013
- function TextareaSkeleton(props) {
1014
- const { className, ...rest } = props;
1015
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-textarea", className), ...rest });
1016
- }
1017
- function ThumbSkeleton(props) {
1018
- const { className, ...rest } = props;
1019
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-thumb", className), ...rest });
1020
- }
1021
- function ChipSkeleton(props) {
1022
- const { className, ...rest } = props;
1023
- return /* @__PURE__ */ jsx12(Skeleton, { radius: "pill", className: cn("skeleton-chip", className), ...rest });
1024
- }
1025
- function TitleSkeleton(props) {
1026
- const { className, ...rest } = props;
1027
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-title", className), ...rest });
1028
- }
1029
- function LineSkeleton({ short = false, className, ...props }) {
1030
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-line", short && "skeleton-line--short", className), ...props });
1031
- }
1032
- function AvatarSkeleton(props) {
1033
- const { className, ...rest } = props;
1034
- return /* @__PURE__ */ jsx12(Skeleton, { radius: "pill", className: cn("skeleton-avatar", className), ...rest });
1035
- }
1036
- function CanvasSkeleton(props) {
1037
- const { className, ...rest } = props;
1038
- return /* @__PURE__ */ jsx12(Skeleton, { className: cn("skeleton-canvas", className), ...rest });
1039
- }
1040
-
1041
- // src/ChoiceGroup.tsx
1042
- import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1043
- function ChoiceGroup({
1044
- options,
1045
- value,
1046
- onChange,
1047
- className
716
+ function tt(e) {
717
+ const { className: t, ...r } = e;
718
+ return /* @__PURE__ */ n(I, { className: l("skeleton-input", t), ...r });
719
+ }
720
+ function ve(e) {
721
+ const { className: t, ...r } = e;
722
+ return /* @__PURE__ */ n(I, { className: l("skeleton-btn", t), ...r });
723
+ }
724
+ function Rt(e) {
725
+ const { className: t, ...r } = e;
726
+ return /* @__PURE__ */ n(I, { className: l("skeleton-icon-btn", t), ...r });
727
+ }
728
+ function nt(e) {
729
+ const { className: t, ...r } = e;
730
+ return /* @__PURE__ */ n(I, { className: l("skeleton-select", t), ...r });
731
+ }
732
+ function Wt(e) {
733
+ const { className: t, ...r } = e;
734
+ return /* @__PURE__ */ n(I, { className: l("skeleton-textarea", t), ...r });
735
+ }
736
+ function ke(e) {
737
+ const { className: t, ...r } = e;
738
+ return /* @__PURE__ */ n(I, { className: l("skeleton-thumb", t), ...r });
739
+ }
740
+ function ne(e) {
741
+ const { className: t, ...r } = e;
742
+ return /* @__PURE__ */ n(I, { radius: "pill", className: l("skeleton-chip", t), ...r });
743
+ }
744
+ function we(e) {
745
+ const { className: t, ...r } = e;
746
+ return /* @__PURE__ */ n(I, { className: l("skeleton-title", t), ...r });
747
+ }
748
+ function ge({ short: e = !1, className: t, ...r }) {
749
+ return /* @__PURE__ */ n(I, { className: l("skeleton-line", e && "skeleton-line--short", t), ...r });
750
+ }
751
+ function rt(e) {
752
+ const { className: t, ...r } = e;
753
+ return /* @__PURE__ */ n(I, { radius: "pill", className: l("skeleton-avatar", t), ...r });
754
+ }
755
+ function Dt(e) {
756
+ const { className: t, ...r } = e;
757
+ return /* @__PURE__ */ n(I, { className: l("skeleton-canvas", t), ...r });
758
+ }
759
+ function Xt({
760
+ options: e,
761
+ value: t,
762
+ onChange: r,
763
+ className: s
1048
764
  }) {
1049
- return /* @__PURE__ */ jsx13(List, { className: cn("choice-list", className), children: options.map((option) => /* @__PURE__ */ jsx13("li", { children: /* @__PURE__ */ jsx13(
1050
- ChoiceCard,
765
+ return /* @__PURE__ */ n(pe, { className: l("choice-list", s), children: e.map((a) => /* @__PURE__ */ n("li", { children: /* @__PURE__ */ n(
766
+ Qe,
1051
767
  {
1052
- active: value === option.value,
1053
- onClick: () => onChange(option.value),
1054
- disabled: option.disabled,
1055
- "data-has-description": option.description ? "true" : "false",
1056
- children: option.description ? /* @__PURE__ */ jsxs9("span", { className: "choice-card__row", children: [
1057
- /* @__PURE__ */ jsx13("span", { className: "choice-card__label", children: option.label }),
1058
- /* @__PURE__ */ jsx13("span", { className: "choice-card__description", children: option.description })
1059
- ] }) : /* @__PURE__ */ jsx13("span", { className: "choice-card__label", children: option.label })
768
+ active: t === a.value,
769
+ onClick: () => r(a.value),
770
+ disabled: a.disabled,
771
+ "data-has-description": a.description ? "true" : "false",
772
+ children: a.description ? /* @__PURE__ */ d("span", { className: "choice-card__row", children: [
773
+ /* @__PURE__ */ n("span", { className: "choice-card__label", children: a.label }),
774
+ /* @__PURE__ */ n("span", { className: "choice-card__description", children: a.description })
775
+ ] }) : /* @__PURE__ */ n("span", { className: "choice-card__label", children: a.label })
1060
776
  }
1061
- ) }, option.value)) });
1062
- }
1063
- function ChoiceGroupSkeleton({ count = 4, className, withDescription = false }) {
1064
- return /* @__PURE__ */ jsx13(List, { className: cn("choice-list", className), "aria-hidden": true, children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ jsx13("li", { children: /* @__PURE__ */ jsxs9("div", { className: "choice-card", children: [
1065
- /* @__PURE__ */ jsx13(TitleSkeleton, { className: cn("skeleton-title--sm", !withDescription && "skeleton-choice-label") }),
1066
- withDescription ? /* @__PURE__ */ jsx13(LineSkeleton, { short: true }) : null
1067
- ] }) }, `choice-skeleton-${i}`)) });
1068
- }
1069
-
1070
- // src/CoordGrid.tsx
1071
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1072
- function CoordGrid({ className, ...props }) {
1073
- return /* @__PURE__ */ jsx14("div", { className: cn("coord-grid", className), ...props });
1074
- }
1075
- function CoordInput({ axis, className, ...props }) {
1076
- return /* @__PURE__ */ jsxs10("label", { className: cn("coord-input", className), children: [
1077
- axis,
777
+ ) }, a.value)) });
778
+ }
779
+ function Yt({ count: e = 4, className: t, withDescription: r = !1 }) {
780
+ return /* @__PURE__ */ n(pe, { className: l("choice-list", t), "aria-hidden": !0, children: Array.from({ length: e }).map((s, a) => /* @__PURE__ */ n("li", { children: /* @__PURE__ */ d("div", { className: "choice-card", children: [
781
+ /* @__PURE__ */ n(we, { className: l("skeleton-title--sm", !r && "skeleton-choice-label") }),
782
+ r ? /* @__PURE__ */ n(ge, { short: !0 }) : null
783
+ ] }) }, `choice-skeleton-${a}`)) });
784
+ }
785
+ function Ft({ className: e, ...t }) {
786
+ return /* @__PURE__ */ n("div", { className: l("coord-grid", e), ...t });
787
+ }
788
+ function Gt({ axis: e, className: t, ...r }) {
789
+ return /* @__PURE__ */ d("label", { className: l("coord-input", t), children: [
790
+ e,
1078
791
  " ",
1079
- /* @__PURE__ */ jsx14("input", { type: "number", step: "0.01", ...props })
792
+ /* @__PURE__ */ n("input", { type: "number", step: "0.01", ...r })
1080
793
  ] });
1081
794
  }
1082
-
1083
- // src/Stack.tsx
1084
- import { createElement as createElement4 } from "react";
1085
- function Stack({
1086
- as,
1087
- size = "md",
1088
- className,
1089
- ...props
795
+ function J({
796
+ as: e,
797
+ size: t = "md",
798
+ className: r,
799
+ ...s
1090
800
  }) {
1091
- return createElement4(as ?? "div", {
1092
- className: cn(size === "sm" ? "panel-stack-sm" : "panel-stack", className),
1093
- ...props
801
+ return T(e ?? "div", {
802
+ className: l(t === "sm" ? "panel-stack-sm" : "panel-stack", r),
803
+ ...s
1094
804
  });
1095
805
  }
1096
-
1097
- // src/Typography.tsx
1098
- import { createElement as createElement5 } from "react";
1099
- var mutedSizeClasses = {
806
+ const st = {
1100
807
  xs: "text-xs",
1101
808
  sm: "text-sm",
1102
809
  md: ""
1103
810
  };
1104
- function AssetTitle({ as = "p", clamp = false, className, ...props }) {
1105
- return createElement5(as, {
1106
- className: cn("asset-title", clamp && "asset-title--clamp", className),
1107
- ...props
811
+ function at({ as: e = "p", clamp: t = !1, className: r, ...s }) {
812
+ return T(e, {
813
+ className: l("asset-title", t && "asset-title--clamp", r),
814
+ ...s
1108
815
  });
1109
816
  }
1110
- function StoryTitle({ as = "h3", className, ...props }) {
1111
- return createElement5(as, {
1112
- className: cn("story-title", className),
1113
- ...props
817
+ function It({ as: e = "h3", className: t, ...r }) {
818
+ return T(e, {
819
+ className: l("story-title", t),
820
+ ...r
1114
821
  });
1115
822
  }
1116
- function MutedText({ as = "p", size = "sm", className, ...props }) {
1117
- return createElement5(as, {
1118
- className: cn(mutedSizeClasses[size], "text-muted", className),
1119
- ...props
823
+ function _e({ as: e = "p", size: t = "sm", className: r, ...s }) {
824
+ return T(e, {
825
+ className: l(st[t], "text-muted", r),
826
+ ...s
1120
827
  });
1121
828
  }
1122
- function PageTitle({ as = "h1", className, ...props }) {
1123
- return createElement5(as, {
1124
- className: cn("page-title", className),
1125
- ...props
829
+ function Lt({ as: e = "h1", className: t, ...r }) {
830
+ return T(e, {
831
+ className: l("page-title", t),
832
+ ...r
1126
833
  });
1127
834
  }
1128
- function SectionTitle({ as = "span", className, ...props }) {
1129
- return createElement5(as, {
1130
- className: cn("widget-section__title", className),
1131
- ...props
835
+ function ot({ as: e = "span", className: t, ...r }) {
836
+ return T(e, {
837
+ className: l("widget-section__title", t),
838
+ ...r
1132
839
  });
1133
840
  }
1134
- function SectionDescription({ as = "p", className, ...props }) {
1135
- return createElement5(as, {
1136
- className: cn("widget-section__description", className),
1137
- ...props
841
+ function it({ as: e = "p", className: t, ...r }) {
842
+ return T(e, {
843
+ className: l("widget-section__description", t),
844
+ ...r
1138
845
  });
1139
846
  }
1140
-
1141
- // src/EmptyState.tsx
1142
- import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1143
- function EmptyState({ title, description, action }) {
1144
- return /* @__PURE__ */ jsxs11(Stack, { size: "sm", children: [
1145
- /* @__PURE__ */ jsx15(AssetTitle, { children: title }),
1146
- description ? /* @__PURE__ */ jsx15(MutedText, { children: description }) : null,
1147
- action
847
+ function Et({ title: e, description: t, action: r }) {
848
+ return /* @__PURE__ */ d(J, { size: "sm", children: [
849
+ /* @__PURE__ */ n(at, { children: e }),
850
+ t ? /* @__PURE__ */ n(_e, { children: t }) : null,
851
+ r
1148
852
  ] });
1149
853
  }
1150
-
1151
- // src/Field.tsx
1152
- import { createElement as createElement6 } from "react";
1153
-
1154
- // src/Label.tsx
1155
- import { jsx as jsx16 } from "react/jsx-runtime";
1156
- function Label({ className, ...props }) {
1157
- return /* @__PURE__ */ jsx16("label", { className: cn("widget-label", className), ...props });
1158
- }
1159
-
1160
- // src/Field.tsx
1161
- import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
1162
- function Field({
1163
- as,
1164
- label,
1165
- htmlFor,
1166
- hint,
1167
- error,
1168
- layout = "stack",
1169
- className,
1170
- children,
1171
- ...props
854
+ function ct({ className: e, ...t }) {
855
+ return /* @__PURE__ */ n("label", { className: l("widget-label", e), ...t });
856
+ }
857
+ function At({
858
+ as: e,
859
+ label: t,
860
+ htmlFor: r,
861
+ hint: s,
862
+ error: a,
863
+ layout: u = "stack",
864
+ className: w,
865
+ children: f,
866
+ ...m
1172
867
  }) {
1173
- return createElement6(
1174
- as ?? "div",
868
+ return T(
869
+ e ?? "div",
1175
870
  {
1176
- className: cn(layout === "control" ? "widget-control" : "panel-stack-sm", className),
1177
- ...props
871
+ className: l(u === "control" ? "widget-control" : "panel-stack-sm", w),
872
+ ...m
1178
873
  },
1179
- /* @__PURE__ */ jsxs12(Fragment4, { children: [
1180
- label ? /* @__PURE__ */ jsx17(Label, { htmlFor, children: label }) : null,
1181
- children,
1182
- hint ? /* @__PURE__ */ jsx17(MutedText, { size: "xs", children: hint }) : null,
1183
- error ? /* @__PURE__ */ jsx17("p", { className: "field-error", children: error }) : null
874
+ /* @__PURE__ */ d(re, { children: [
875
+ t ? /* @__PURE__ */ n(ct, { htmlFor: r, children: t }) : null,
876
+ f,
877
+ s ? /* @__PURE__ */ n(_e, { size: "xs", children: s }) : null,
878
+ a ? /* @__PURE__ */ n("p", { className: "field-error", children: a }) : null
1184
879
  ] })
1185
880
  );
1186
881
  }
1187
-
1188
- // src/GeneratingOverlay.tsx
1189
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
1190
- function GeneratingOverlay({ isGenerating, children, message }) {
1191
- return /* @__PURE__ */ jsxs13("div", { className: "generating-overlay-wrap", children: [
1192
- children,
1193
- isGenerating && /* @__PURE__ */ jsxs13("div", { className: "generating-overlay", "aria-live": "polite", children: [
1194
- /* @__PURE__ */ jsx18(Loader2, { size: 20, className: "icon-spin" }),
1195
- /* @__PURE__ */ jsx18("span", { children: message ?? "Generating, please wait\u2026" })
882
+ function Ot({ isGenerating: e, children: t, message: r }) {
883
+ return /* @__PURE__ */ d("div", { className: "generating-overlay-wrap", children: [
884
+ t,
885
+ e && /* @__PURE__ */ d("div", { className: "generating-overlay", "aria-live": "polite", children: [
886
+ /* @__PURE__ */ n(fe, { size: 20, className: "icon-spin" }),
887
+ /* @__PURE__ */ n("span", { children: r ?? "Generating, please wait…" })
1196
888
  ] })
1197
889
  ] });
1198
890
  }
1199
-
1200
- // src/IconText.tsx
1201
- import { createElement as createElement7 } from "react";
1202
- import { Fragment as Fragment5, jsxs as jsxs14 } from "react/jsx-runtime";
1203
- function IconText({ as = "span", icon, className, children, ...props }) {
1204
- return createElement7(
1205
- as,
891
+ function Ht({ as: e = "span", icon: t, className: r, children: s, ...a }) {
892
+ return T(
893
+ e,
1206
894
  {
1207
- className: cn("inline-row", className),
1208
- ...props
895
+ className: l("inline-row", r),
896
+ ...a
1209
897
  },
1210
- /* @__PURE__ */ jsxs14(Fragment5, { children: [
1211
- icon,
1212
- children
898
+ /* @__PURE__ */ d(re, { children: [
899
+ t,
900
+ s
1213
901
  ] })
1214
902
  );
1215
903
  }
1216
-
1217
- // src/ImageThumb.tsx
1218
- import { useState as useState2 } from "react";
1219
- import { jsx as jsx19 } from "react/jsx-runtime";
1220
- function ImageThumb({
1221
- src,
1222
- alt,
1223
- placeholder = "No image",
1224
- size = "md",
1225
- fit = "contain",
1226
- onImageError,
1227
- className,
1228
- ...props
904
+ function Bt({
905
+ src: e,
906
+ alt: t,
907
+ placeholder: r = "No image",
908
+ size: s = "md",
909
+ fit: a = "contain",
910
+ onImageError: u,
911
+ className: w,
912
+ ...f
1229
913
  }) {
1230
- const [failedSrc, setFailedSrc] = useState2(null);
1231
- const failed = Boolean(src && failedSrc === src);
1232
- const classes = cn("image-thumb", `image-thumb--${size}`, `image-thumb--fit-${fit}`, className);
1233
- return /* @__PURE__ */ jsx19("div", { className: classes, ...props, children: src && !failed ? /* @__PURE__ */ jsx19(
914
+ const [m, g] = Se(null), h = !!(e && m === e), M = l("image-thumb", `image-thumb--${s}`, `image-thumb--fit-${a}`, w);
915
+ return /* @__PURE__ */ n("div", { className: M, ...f, children: e && !h ? /* @__PURE__ */ n(
1234
916
  "img",
1235
917
  {
1236
- src,
1237
- alt,
918
+ src: e,
919
+ alt: t,
1238
920
  className: "image-thumb__img",
1239
- style: { objectFit: fit, objectPosition: "center" },
921
+ style: { objectFit: a, objectPosition: "center" },
1240
922
  onError: () => {
1241
- setFailedSrc(src);
1242
- onImageError?.();
923
+ g(e), u == null || u();
1243
924
  }
1244
925
  }
1245
- ) : /* @__PURE__ */ jsx19("span", { className: "image-thumb__placeholder", children: placeholder }) });
1246
- }
1247
-
1248
- // src/Inline.tsx
1249
- import { createElement as createElement8 } from "react";
1250
- function Inline({
1251
- as,
1252
- justify = "start",
1253
- className,
1254
- ...props
926
+ ) : /* @__PURE__ */ n("span", { className: "image-thumb__placeholder", children: r }) });
927
+ }
928
+ function lt({
929
+ as: e,
930
+ justify: t = "start",
931
+ className: r,
932
+ ...s
1255
933
  }) {
1256
- return createElement8(as ?? "div", {
1257
- className: cn(justify === "between" ? "space-between" : "inline-row", className),
1258
- ...props
934
+ return T(e ?? "div", {
935
+ className: l(t === "between" ? "space-between" : t === "end" ? "space-end" : "inline-row", r),
936
+ ...s
1259
937
  });
1260
938
  }
1261
-
1262
- // src/Input.tsx
1263
- import { forwardRef as forwardRef2 } from "react";
1264
- import { jsx as jsx20 } from "react/jsx-runtime";
1265
- var Input = forwardRef2(function Input2({ className, ...props }, ref) {
1266
- return /* @__PURE__ */ jsx20("input", { ref, className: cn(className), ...props });
939
+ const $t = me(function({ className: t, ...r }, s) {
940
+ return /* @__PURE__ */ n("input", { ref: s, className: l(t), ...r });
1267
941
  });
1268
-
1269
- // src/ItemCard.tsx
1270
- import { createElement as createElement9 } from "react";
1271
- function ItemCard({ as = "div", className, ...props }) {
1272
- return createElement9(as, {
1273
- className: cn("item-card", className),
1274
- ...props
942
+ function Pe({ as: e = "div", className: t, ...r }) {
943
+ return T(e, {
944
+ className: l("item-card", t),
945
+ ...r
1275
946
  });
1276
947
  }
1277
-
1278
- // src/ItemList.tsx
1279
- import { createElement as createElement10 } from "react";
1280
- function ItemList({ as = "div", className, ...props }) {
1281
- return createElement10(as, {
1282
- className: cn("item-list", className),
1283
- ...props
948
+ function ut({ as: e = "div", className: t, ...r }) {
949
+ return T(e, {
950
+ className: l("item-list", t),
951
+ ...r
1284
952
  });
1285
953
  }
1286
-
1287
- // src/LoadingState.tsx
1288
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1289
- function LoadingState({ label = "Loading...", className }) {
1290
- return /* @__PURE__ */ jsxs15("span", { className: cn("status-inline", className), children: [
1291
- /* @__PURE__ */ jsx21(Loader2, { size: 14, className: "icon-spin" }),
1292
- label
954
+ function Vt({ label: e = "Loading...", className: t }) {
955
+ return /* @__PURE__ */ d("span", { className: l("status-inline", t), children: [
956
+ /* @__PURE__ */ n(fe, { size: 14, className: "icon-spin" }),
957
+ e
1293
958
  ] });
1294
959
  }
1295
-
1296
- // src/PageLayout.tsx
1297
- import { jsx as jsx22 } from "react/jsx-runtime";
1298
- function PageShell({ children }) {
1299
- return /* @__PURE__ */ jsx22("main", { className: "page-shell", children });
1300
- }
1301
- function PageCard({ children }) {
1302
- return /* @__PURE__ */ jsx22("div", { className: "page-card", children });
1303
- }
1304
-
1305
- // src/PanelCloseButton.tsx
1306
- import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1307
- function PanelCloseButton({ onClick, label = "Close" }) {
1308
- return /* @__PURE__ */ jsxs16(Button, { variant: "secondary", className: "panel-close-btn", onClick, children: [
1309
- /* @__PURE__ */ jsx23(X, { size: 14 }),
1310
- label
960
+ function jt({ children: e, className: t, ...r }) {
961
+ return /* @__PURE__ */ n("main", { className: l("page-shell", t), ...r, children: e });
962
+ }
963
+ function Ut({ children: e, className: t, ...r }) {
964
+ return /* @__PURE__ */ n("div", { className: l("page-card", t), ...r, children: e });
965
+ }
966
+ function Zt({ onClick: e, label: t = "Close" }) {
967
+ return /* @__PURE__ */ d(Ke, { variant: "secondary", className: "panel-close-btn", onClick: e, children: [
968
+ /* @__PURE__ */ n(Me, { size: 14 }),
969
+ t
1311
970
  ] });
1312
971
  }
1313
-
1314
- // src/PanelSection.tsx
1315
- import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1316
- function PanelSection({ heading, description, actions, className, children, ...props }) {
1317
- return /* @__PURE__ */ jsxs17("section", { className: cn("widget-section", className), ...props, children: [
1318
- heading || actions ? /* @__PURE__ */ jsxs17("header", { className: actions ? "title-row" : void 0, children: [
1319
- heading ? /* @__PURE__ */ jsx24(SectionTitle, { children: heading }) : null,
1320
- actions
972
+ function qt({ heading: e, description: t, actions: r, className: s, children: a, ...u }) {
973
+ return /* @__PURE__ */ d("section", { className: l("widget-section", s), ...u, children: [
974
+ e || r ? /* @__PURE__ */ d("header", { className: r ? "title-row" : void 0, children: [
975
+ e ? /* @__PURE__ */ n(ot, { children: e }) : null,
976
+ r
1321
977
  ] }) : null,
1322
- description ? /* @__PURE__ */ jsx24(SectionDescription, { children: description }) : null,
1323
- children
978
+ t ? /* @__PURE__ */ n(it, { children: t }) : null,
979
+ a
1324
980
  ] });
1325
981
  }
1326
-
1327
- // src/PanelTitle.tsx
1328
- import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1329
- function PanelTitle({ icon: Icon, label }) {
1330
- return /* @__PURE__ */ jsxs18("span", { className: "panel-title-with-icon", children: [
1331
- /* @__PURE__ */ jsx25(Icon, { size: 13, className: "panel-title-icon" }),
1332
- /* @__PURE__ */ jsx25("span", { children: label })
982
+ function Kt({ icon: e, label: t }) {
983
+ return /* @__PURE__ */ d("span", { className: "panel-title-with-icon", children: [
984
+ /* @__PURE__ */ n(e, { size: 13, className: "panel-title-icon" }),
985
+ /* @__PURE__ */ n("span", { children: t })
1333
986
  ] });
1334
987
  }
1335
-
1336
- // src/PickerCard.tsx
1337
- import { createElement as createElement11 } from "react";
1338
- function PickerCard({ as = "button", className, ...props }) {
1339
- return createElement11(as, {
1340
- className: cn("picker-card", className),
1341
- ...props
988
+ function dt({ as: e = "button", className: t, ...r }) {
989
+ return T(e, {
990
+ className: l("picker-card", t),
991
+ ...r
1342
992
  });
1343
993
  }
1344
-
1345
- // src/PickerGrid.tsx
1346
- import { jsx as jsx26 } from "react/jsx-runtime";
1347
- var variantClasses2 = {
994
+ const ht = {
1348
995
  elements: "picker-grid--elements",
1349
996
  characters: "picker-grid--characters",
1350
997
  library: "picker-grid--library"
1351
998
  };
1352
- function PickerGrid({ variant, className, ...props }) {
1353
- return /* @__PURE__ */ jsx26(List, { className: cn("picker-grid", variantClasses2[variant], className), ...props });
999
+ function Jt({ variant: e, className: t, ...r }) {
1000
+ return /* @__PURE__ */ n(pe, { className: l("picker-grid", ht[e], t), ...r });
1354
1001
  }
1355
-
1356
- // src/Pill.tsx
1357
- import { jsx as jsx27 } from "react/jsx-runtime";
1358
- var toneClasses2 = {
1002
+ const mt = {
1359
1003
  default: "",
1360
1004
  success: "success",
1361
1005
  warning: "warning",
1362
1006
  danger: "danger"
1363
1007
  };
1364
- function Pill({ tone = "default", className, ...props }) {
1365
- return /* @__PURE__ */ jsx27("span", { className: cn("pill", toneClasses2[tone], className), ...props });
1366
- }
1367
-
1368
- // src/Select.tsx
1369
- import { forwardRef as forwardRef3 } from "react";
1370
- import { jsx as jsx28 } from "react/jsx-runtime";
1371
- var Select = forwardRef3(function Select2({ className, ...props }, ref) {
1372
- return /* @__PURE__ */ jsx28("select", { ref, className: cn(className), ...props });
1373
- });
1374
-
1375
- // src/SplitLayout.tsx
1376
- import { jsx as jsx29 } from "react/jsx-runtime";
1377
- var variantClasses3 = {
1008
+ function Qt({ tone: e = "default", className: t, ...r }) {
1009
+ return /* @__PURE__ */ n("span", { className: l("pill", mt[e], t), ...r });
1010
+ }
1011
+ const en = me(function({ className: t, ...r }, s) {
1012
+ return /* @__PURE__ */ n("select", { ref: s, className: l(t), ...r });
1013
+ }), ft = {
1378
1014
  element: "split-layout--element",
1379
1015
  character: "split-layout--character",
1380
1016
  user: "split-layout--user"
1381
1017
  };
1382
- function SplitLayout({ variant, className, ...props }) {
1383
- return /* @__PURE__ */ jsx29("div", { className: cn("split-layout", variantClasses3[variant], className), ...props });
1384
- }
1385
-
1386
- // src/TagRow.tsx
1387
- import { jsx as jsx30 } from "react/jsx-runtime";
1388
- function TagRow({ className, ...props }) {
1389
- return /* @__PURE__ */ jsx30("div", { className: cn("tag-row", className), ...props });
1390
- }
1391
-
1392
- // src/Textarea.tsx
1393
- import { forwardRef as forwardRef4 } from "react";
1394
- import { jsx as jsx31 } from "react/jsx-runtime";
1395
- var Textarea = forwardRef4(function Textarea2({ className, ...props }, ref) {
1396
- return /* @__PURE__ */ jsx31("textarea", { ref, className: cn(className), ...props });
1018
+ function pt({ variant: e, className: t, ...r }) {
1019
+ return /* @__PURE__ */ n("div", { className: l("split-layout", ft[e], t), ...r });
1020
+ }
1021
+ function wt({ className: e, ...t }) {
1022
+ return /* @__PURE__ */ n("div", { className: l("tag-row", e), ...t });
1023
+ }
1024
+ const tn = me(function({ className: t, ...r }, s) {
1025
+ return /* @__PURE__ */ n("textarea", { ref: s, className: l(t), ...r });
1397
1026
  });
1398
-
1399
- // src/ThemeToggle.tsx
1400
- import { jsx as jsx32 } from "react/jsx-runtime";
1401
- function ThemeToggle({ className, theme = "light", onToggle, lightIcon, darkIcon }) {
1402
- return /* @__PURE__ */ jsx32("button", { className, onClick: onToggle, title: `Switch to ${theme === "light" ? "dark" : "light"} mode`, "aria-label": "Toggle theme", children: theme === "light" ? darkIcon ?? /* @__PURE__ */ jsx32(Moon, {}) : lightIcon ?? /* @__PURE__ */ jsx32(Sun, {}) });
1403
- }
1404
-
1405
- // src/TitleRow.tsx
1406
- import { jsx as jsx33 } from "react/jsx-runtime";
1407
- function TitleRow({ className, ...props }) {
1408
- return /* @__PURE__ */ jsx33("div", { className: cn("title-row", className), ...props });
1409
- }
1410
-
1411
- // src/WidgetSkeletons.tsx
1412
- import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
1413
- function PanelFormSkeleton({ inputs = 1, showButton = true, className, ...props }) {
1414
- return /* @__PURE__ */ jsxs19(Stack, { className, ...props, children: [
1415
- Array.from({ length: inputs }).map((_, i) => /* @__PURE__ */ jsx34(InputSkeleton, {}, `panel-form-input-${i}`)),
1416
- showButton && /* @__PURE__ */ jsx34(ButtonSkeleton, {})
1027
+ function nn({ className: e, theme: t = "light", onToggle: r, lightIcon: s, darkIcon: a }) {
1028
+ return /* @__PURE__ */ n("button", { className: e, onClick: r, title: `Switch to ${t === "light" ? "dark" : "light"} mode`, "aria-label": "Toggle theme", children: t === "light" ? a ?? /* @__PURE__ */ n(Be, {}) : s ?? /* @__PURE__ */ n($e, {}) });
1029
+ }
1030
+ function rn({ className: e, ...t }) {
1031
+ return /* @__PURE__ */ n("div", { className: l("title-row", e), ...t });
1032
+ }
1033
+ function sn({ inputs: e = 1, showButton: t = !0, className: r, ...s }) {
1034
+ return /* @__PURE__ */ d(J, { className: r, ...s, children: [
1035
+ Array.from({ length: e }).map((a, u) => /* @__PURE__ */ n(tt, {}, `panel-form-input-${u}`)),
1036
+ t && /* @__PURE__ */ n(ve, {})
1417
1037
  ] });
1418
1038
  }
1419
- function StoryCardSkeleton() {
1420
- return /* @__PURE__ */ jsxs19("article", { className: "story-card", children: [
1421
- /* @__PURE__ */ jsx34("div", { className: "story-cover", children: /* @__PURE__ */ jsx34("div", { className: "story-cover__placeholder story-cover__placeholder--skeleton" }) }),
1422
- /* @__PURE__ */ jsx34("div", { className: "story-card__overlay story-card__overlay--skeleton", children: /* @__PURE__ */ jsxs19("div", { className: "story-card__overlay-text", children: [
1423
- /* @__PURE__ */ jsxs19(Inline, { as: "header", children: [
1424
- /* @__PURE__ */ jsx34(ChipSkeleton, {}),
1425
- /* @__PURE__ */ jsx34(ChipSkeleton, {})
1039
+ function an() {
1040
+ return /* @__PURE__ */ d("article", { className: "story-card", children: [
1041
+ /* @__PURE__ */ n("div", { className: "story-cover", children: /* @__PURE__ */ n("div", { className: "story-cover__placeholder story-cover__placeholder--skeleton" }) }),
1042
+ /* @__PURE__ */ n("div", { className: "story-card__overlay story-card__overlay--skeleton", children: /* @__PURE__ */ d("div", { className: "story-card__overlay-text", children: [
1043
+ /* @__PURE__ */ d(lt, { as: "header", children: [
1044
+ /* @__PURE__ */ n(ne, {}),
1045
+ /* @__PURE__ */ n(ne, {})
1426
1046
  ] }),
1427
- /* @__PURE__ */ jsx34(TitleSkeleton, {}),
1428
- /* @__PURE__ */ jsx34(LineSkeleton, { short: true })
1047
+ /* @__PURE__ */ n(we, {}),
1048
+ /* @__PURE__ */ n(ge, { short: !0 })
1429
1049
  ] }) })
1430
1050
  ] });
1431
1051
  }
1432
- function UserCardSkeleton() {
1433
- return /* @__PURE__ */ jsx34(ItemCard, { as: "li", children: /* @__PURE__ */ jsxs19(SplitLayout, { variant: "user", children: [
1434
- /* @__PURE__ */ jsx34(AvatarSkeleton, {}),
1435
- /* @__PURE__ */ jsxs19(Stack, { size: "sm", children: [
1436
- /* @__PURE__ */ jsx34(TitleSkeleton, {}),
1437
- /* @__PURE__ */ jsx34(LineSkeleton, { short: true })
1052
+ function gt() {
1053
+ return /* @__PURE__ */ n(Pe, { as: "li", children: /* @__PURE__ */ d(pt, { variant: "user", children: [
1054
+ /* @__PURE__ */ n(rt, {}),
1055
+ /* @__PURE__ */ d(J, { size: "sm", children: [
1056
+ /* @__PURE__ */ n(we, {}),
1057
+ /* @__PURE__ */ n(ge, { short: !0 })
1438
1058
  ] }),
1439
- /* @__PURE__ */ jsxs19(Stack, { size: "sm", children: [
1440
- /* @__PURE__ */ jsx34(ChipSkeleton, {}),
1441
- /* @__PURE__ */ jsx34(SelectSkeleton, {})
1059
+ /* @__PURE__ */ d(J, { size: "sm", children: [
1060
+ /* @__PURE__ */ n(ne, {}),
1061
+ /* @__PURE__ */ n(nt, {})
1442
1062
  ] })
1443
1063
  ] }) });
1444
1064
  }
1445
- function UserListSkeleton({ count = 3 }) {
1446
- return /* @__PURE__ */ jsx34(ItemList, { as: "ul", children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ jsx34(UserCardSkeleton, {}, `user-skeleton-${i}`)) });
1447
- }
1448
- function AssetCardSkeleton() {
1449
- return /* @__PURE__ */ jsxs19(ItemCard, { as: "li", children: [
1450
- /* @__PURE__ */ jsxs19(Stack, { size: "sm", children: [
1451
- /* @__PURE__ */ jsx34(ThumbSkeleton, { className: "asset-thumb" }),
1452
- /* @__PURE__ */ jsx34(TitleSkeleton, {}),
1453
- /* @__PURE__ */ jsxs19(TagRow, { children: [
1454
- /* @__PURE__ */ jsx34(ChipSkeleton, {}),
1455
- /* @__PURE__ */ jsx34(ChipSkeleton, {})
1065
+ function on({ count: e = 3 }) {
1066
+ return /* @__PURE__ */ n(ut, { as: "ul", children: Array.from({ length: e }).map((t, r) => /* @__PURE__ */ n(gt, {}, `user-skeleton-${r}`)) });
1067
+ }
1068
+ function cn() {
1069
+ return /* @__PURE__ */ d(Pe, { as: "li", children: [
1070
+ /* @__PURE__ */ d(J, { size: "sm", children: [
1071
+ /* @__PURE__ */ n(ke, { className: "asset-thumb" }),
1072
+ /* @__PURE__ */ n(we, {}),
1073
+ /* @__PURE__ */ d(wt, { children: [
1074
+ /* @__PURE__ */ n(ne, {}),
1075
+ /* @__PURE__ */ n(ne, {})
1456
1076
  ] })
1457
1077
  ] }),
1458
- /* @__PURE__ */ jsxs19(ButtonRow, { children: [
1459
- /* @__PURE__ */ jsx34(ButtonSkeleton, {}),
1460
- /* @__PURE__ */ jsx34(ButtonSkeleton, {})
1078
+ /* @__PURE__ */ d(Je, { children: [
1079
+ /* @__PURE__ */ n(ve, {}),
1080
+ /* @__PURE__ */ n(ve, {})
1461
1081
  ] })
1462
1082
  ] });
1463
1083
  }
1464
- function PickerGridSkeleton({ count = 8, gridClass }) {
1465
- return /* @__PURE__ */ jsx34(List, { className: cn("picker-grid", gridClass), children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ jsx34("li", { children: /* @__PURE__ */ jsx34(PickerCard, { as: "div", className: "picker-card--skeleton", children: /* @__PURE__ */ jsxs19(Stack, { size: "sm", children: [
1466
- /* @__PURE__ */ jsx34(ThumbSkeleton, { className: "asset-thumb" }),
1467
- /* @__PURE__ */ jsx34(LineSkeleton, { short: true })
1468
- ] }) }) }, `picker-skeleton-${i}`)) });
1084
+ function ln({ count: e = 8, gridClass: t }) {
1085
+ return /* @__PURE__ */ n(pe, { className: l("picker-grid", t), children: Array.from({ length: e }).map((r, s) => /* @__PURE__ */ n("li", { children: /* @__PURE__ */ n(dt, { as: "div", className: "picker-card--skeleton", children: /* @__PURE__ */ d(J, { size: "sm", children: [
1086
+ /* @__PURE__ */ n(ke, { className: "asset-thumb" }),
1087
+ /* @__PURE__ */ n(ge, { short: !0 })
1088
+ ] }) }) }, `picker-skeleton-${s}`)) });
1469
1089
  }
1470
1090
  export {
1471
- Alert,
1472
- AssetCardSkeleton,
1473
- AssetTitle,
1474
- AvatarSkeleton,
1475
- Button,
1476
- ButtonRow,
1477
- ButtonSkeleton,
1478
- CanvasSkeleton,
1479
- Chip,
1480
- ChipSkeleton,
1481
- ChoiceCard,
1482
- ChoiceGroup,
1483
- ChoiceGroupSkeleton,
1484
- ConfirmDialog,
1485
- CoordGrid,
1486
- CoordInput,
1487
- EmptyState,
1488
- Field,
1489
- FloatingPanel,
1490
- GeneratingOverlay,
1491
- IconButtonSkeleton,
1492
- IconText,
1493
- ImageThumb,
1494
- Inline,
1495
- Input,
1496
- InputSkeleton,
1497
- ItemCard,
1498
- ItemList,
1499
- Label,
1500
- LineSkeleton,
1501
- List,
1502
- LoadingState,
1503
- Minimap,
1504
- MutedText,
1505
- PageCard,
1506
- PageShell,
1507
- PageTitle,
1508
- PanelCloseButton,
1509
- PanelErrorBoundary,
1510
- PanelFormSkeleton,
1511
- PanelSection,
1512
- PanelTitle,
1513
- PickerCard,
1514
- PickerGrid,
1515
- PickerGridSkeleton,
1516
- Pill,
1517
- SectionDescription,
1518
- SectionTitle,
1519
- Select,
1520
- SelectSkeleton,
1521
- Skeleton,
1522
- SplitLayout,
1523
- Stack,
1524
- StoryCardSkeleton,
1525
- StoryTitle,
1526
- TagRow,
1527
- Textarea,
1528
- TextareaSkeleton,
1529
- ThemeToggle,
1530
- ThumbSkeleton,
1531
- TitleRow,
1532
- TitleSkeleton,
1533
- UserCardSkeleton,
1534
- UserListSkeleton,
1535
- WHITEBOARD_GRID,
1536
- WhiteboardShell,
1537
- ZoomBar,
1538
- belowPanel,
1539
- cn,
1540
- computeWhiteboardFit,
1541
- computeWhiteboardRectFocus,
1542
- snapToWhiteboardGrid,
1543
- usePanelRect,
1544
- useWhiteboardLayout,
1545
- useWhiteboardStore
1091
+ zt as Alert,
1092
+ cn as AssetCardSkeleton,
1093
+ at as AssetTitle,
1094
+ rt as AvatarSkeleton,
1095
+ Ke as Button,
1096
+ Je as ButtonRow,
1097
+ ve as ButtonSkeleton,
1098
+ Dt as CanvasSkeleton,
1099
+ Tt as Chip,
1100
+ ne as ChipSkeleton,
1101
+ Qe as ChoiceCard,
1102
+ Xt as ChoiceGroup,
1103
+ Yt as ChoiceGroupSkeleton,
1104
+ _t as ConfirmDialog,
1105
+ Ft as CoordGrid,
1106
+ Gt as CoordInput,
1107
+ Et as EmptyState,
1108
+ At as Field,
1109
+ St as FloatingPanel,
1110
+ Ot as GeneratingOverlay,
1111
+ Rt as IconButtonSkeleton,
1112
+ Ht as IconText,
1113
+ Bt as ImageThumb,
1114
+ lt as Inline,
1115
+ $t as Input,
1116
+ tt as InputSkeleton,
1117
+ Pe as ItemCard,
1118
+ ut as ItemList,
1119
+ ct as Label,
1120
+ ge as LineSkeleton,
1121
+ pe as List,
1122
+ Vt as LoadingState,
1123
+ Ue as Minimap,
1124
+ _e as MutedText,
1125
+ Ut as PageCard,
1126
+ jt as PageShell,
1127
+ Lt as PageTitle,
1128
+ Zt as PanelCloseButton,
1129
+ Pt as PanelErrorBoundary,
1130
+ sn as PanelFormSkeleton,
1131
+ qt as PanelSection,
1132
+ Kt as PanelTitle,
1133
+ dt as PickerCard,
1134
+ Jt as PickerGrid,
1135
+ ln as PickerGridSkeleton,
1136
+ Qt as Pill,
1137
+ it as SectionDescription,
1138
+ ot as SectionTitle,
1139
+ en as Select,
1140
+ nt as SelectSkeleton,
1141
+ I as Skeleton,
1142
+ pt as SplitLayout,
1143
+ J as Stack,
1144
+ an as StoryCardSkeleton,
1145
+ It as StoryTitle,
1146
+ wt as TagRow,
1147
+ tn as Textarea,
1148
+ Wt as TextareaSkeleton,
1149
+ nn as ThemeToggle,
1150
+ ke as ThumbSkeleton,
1151
+ rn as TitleRow,
1152
+ we as TitleSkeleton,
1153
+ gt as UserCardSkeleton,
1154
+ on as UserListSkeleton,
1155
+ he as WHITEBOARD_GRID,
1156
+ xt as WhiteboardShell,
1157
+ je as ZoomBar,
1158
+ kt as belowPanel,
1159
+ l as cn,
1160
+ Ne as computeWhiteboardFit,
1161
+ Ve as computeWhiteboardRectFocus,
1162
+ ue as snapToWhiteboardGrid,
1163
+ Mt as usePanelRect,
1164
+ Ct as useWhiteboardLayout,
1165
+ p as useWhiteboardStore
1546
1166
  };
1547
- //# sourceMappingURL=index.js.map