@object-ui/plugin-designer 0.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +154 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +3674 -828
  4. package/dist/index.umd.cjs +2 -2
  5. package/dist/{src → plugin-designer/src}/CollaborationProvider.d.ts +15 -2
  6. package/dist/{src → plugin-designer/src}/DataModelDesigner.d.ts +2 -1
  7. package/dist/{src → plugin-designer/src}/PageDesigner.d.ts +3 -2
  8. package/dist/{src → plugin-designer/src}/ProcessDesigner.d.ts +6 -2
  9. package/dist/{src → plugin-designer/src}/ReportDesigner.d.ts +0 -1
  10. package/dist/plugin-designer/src/ViewDesigner.d.ts +67 -0
  11. package/dist/plugin-designer/src/components/ConfirmDialog.d.ts +30 -0
  12. package/dist/plugin-designer/src/components/Minimap.d.ts +35 -0
  13. package/dist/plugin-designer/src/components/PropertyEditor.d.ts +43 -0
  14. package/dist/plugin-designer/src/components/VersionHistory.d.ts +34 -0
  15. package/dist/plugin-designer/src/components/index.d.ts +15 -0
  16. package/dist/plugin-designer/src/hooks/index.d.ts +17 -0
  17. package/dist/plugin-designer/src/hooks/useCanvasPanZoom.d.ts +40 -0
  18. package/dist/plugin-designer/src/hooks/useClipboard.d.ts +22 -0
  19. package/dist/plugin-designer/src/hooks/useConfirmDialog.d.ts +25 -0
  20. package/dist/plugin-designer/src/hooks/useMultiSelect.d.ts +27 -0
  21. package/dist/plugin-designer/src/hooks/useUndoRedo.d.ts +36 -0
  22. package/dist/plugin-designer/src/index.d.ts +17 -0
  23. package/package.json +11 -11
  24. package/dist/src/CollaborationProvider.d.ts.map +0 -1
  25. package/dist/src/DataModelDesigner.d.ts.map +0 -1
  26. package/dist/src/PageDesigner.d.ts.map +0 -1
  27. package/dist/src/ProcessDesigner.d.ts.map +0 -1
  28. package/dist/src/ReportDesigner.d.ts.map +0 -1
  29. package/dist/src/index.d.ts +0 -7
  30. package/dist/src/index.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,431 +1,1229 @@
1
- import { ComponentRegistry as G } from "@object-ui/core";
2
- import xe, { useState as A, useMemo as Z, useCallback as P, createContext as fe } from "react";
3
- import { Plus as K, Undo2 as be, Redo2 as ge, Eye as ye, GripVertical as ve, Trash2 as L, Layers as we, Database as le, Link2 as je, GitBranch as Ne, Play as Ee, Square as oe, Diamond as ke, FileText as Re, Type as Te, ImageIcon as _e, BarChart3 as Se, Table2 as Ae } from "lucide-react";
4
- import { clsx as M } from "clsx";
5
- import { twMerge as Y } from "tailwind-merge";
6
- var F = { exports: {} }, $ = {};
7
- var ne;
8
- function Pe() {
9
- if (ne) return $;
10
- ne = 1;
11
- var l = /* @__PURE__ */ Symbol.for("react.transitional.element"), u = /* @__PURE__ */ Symbol.for("react.fragment");
12
- function p(w, i, d) {
13
- var x = null;
14
- if (d !== void 0 && (x = "" + d), i.key !== void 0 && (x = "" + i.key), "key" in i) {
15
- d = {};
16
- for (var E in i)
17
- E !== "key" && (d[E] = i[E]);
18
- } else d = i;
19
- return i = d.ref, {
20
- $$typeof: l,
1
+ import { ComponentRegistry as Se } from "@object-ui/core";
2
+ import mt, { useState as K, useRef as ee, useCallback as b, useEffect as fe, createContext as ht, useContext as rt, useMemo as ce } from "react";
3
+ import { AlertTriangle as xt, ChevronRight as He, ChevronDown as Xe, Plus as xe, PanelLeftClose as ft, Undo2 as Ee, Redo2 as De, Copy as Pe, Clipboard as Te, Trash2 as he, Eye as st, Map as nt, Minus as bt, Maximize2 as gt, PanelRightClose as Ke, GripVertical as at, Layers as vt, Database as qe, ZoomOut as ot, ZoomIn as lt, RotateCcw as it, Grid3X3 as yt, Users as wt, Link2 as jt, GitBranch as Nt, Link as Ct, Layout as kt, Play as St, Square as Je, Diamond as Et, PanelRightOpen as Dt, FileText as Pt, Type as Tt, ImageIcon as Rt, BarChart3 as At, Table2 as It, Settings2 as Ft, X as $t, Save as Mt, LayoutGrid as _t, Kanban as zt, Image as Lt, Calendar as Ut, Clock as dt, GanttChart as Gt, Columns3 as Yt, ArrowUp as Vt, ArrowDown as Zt, EyeOff as Ht, History as Xt, User as Kt } from "lucide-react";
4
+ import { clsx as ue } from "clsx";
5
+ import { twMerge as pe } from "tailwind-merge";
6
+ var Me = { exports: {} }, Ne = {};
7
+ var Qe;
8
+ function Wt() {
9
+ if (Qe) return Ne;
10
+ Qe = 1;
11
+ var s = /* @__PURE__ */ Symbol.for("react.transitional.element"), N = /* @__PURE__ */ Symbol.for("react.fragment");
12
+ function E(w, v, R) {
13
+ var y = null;
14
+ if (R !== void 0 && (y = "" + R), v.key !== void 0 && (y = "" + v.key), "key" in v) {
15
+ R = {};
16
+ for (var f in v)
17
+ f !== "key" && (R[f] = v[f]);
18
+ } else R = v;
19
+ return v = R.ref, {
20
+ $$typeof: s,
21
21
  type: w,
22
- key: x,
23
- ref: i !== void 0 ? i : null,
24
- props: d
22
+ key: y,
23
+ ref: v !== void 0 ? v : null,
24
+ props: R
25
25
  };
26
26
  }
27
- return $.Fragment = u, $.jsx = p, $.jsxs = p, $;
27
+ return Ne.Fragment = N, Ne.jsx = E, Ne.jsxs = E, Ne;
28
28
  }
29
- var z = {};
30
- var ie;
31
- function Ce() {
32
- return ie || (ie = 1, process.env.NODE_ENV !== "production" && (function() {
33
- function l(t) {
34
- if (t == null) return null;
35
- if (typeof t == "function")
36
- return t.$$typeof === pe ? null : t.displayName || t.name || null;
37
- if (typeof t == "string") return t;
38
- switch (t) {
39
- case o:
29
+ var Ce = {};
30
+ var Oe;
31
+ function Bt() {
32
+ return Oe || (Oe = 1, process.env.NODE_ENV !== "production" && (function() {
33
+ function s(d) {
34
+ if (d == null) return null;
35
+ if (typeof d == "function")
36
+ return d.$$typeof === J ? null : d.displayName || d.name || null;
37
+ if (typeof d == "string") return d;
38
+ switch (d) {
39
+ case T:
40
40
  return "Fragment";
41
- case c:
41
+ case F:
42
42
  return "Profiler";
43
- case r:
43
+ case A:
44
44
  return "StrictMode";
45
- case h:
45
+ case U:
46
46
  return "Suspense";
47
- case f:
47
+ case H:
48
48
  return "SuspenseList";
49
- case V:
49
+ case oe:
50
50
  return "Activity";
51
51
  }
52
- if (typeof t == "object")
53
- switch (typeof t.tag == "number" && console.error(
52
+ if (typeof d == "object")
53
+ switch (typeof d.tag == "number" && console.error(
54
54
  "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
55
- ), t.$$typeof) {
56
- case S:
55
+ ), d.$$typeof) {
56
+ case x:
57
57
  return "Portal";
58
- case T:
59
- return t.displayName || "Context";
60
- case s:
61
- return (t._context.displayName || "Context") + ".Consumer";
62
- case m:
63
- var a = t.render;
64
- return t = t.displayName, t || (t = a.displayName || a.name || "", t = t !== "" ? "ForwardRef(" + t + ")" : "ForwardRef"), t;
65
- case C:
66
- return a = t.displayName || null, a !== null ? a : l(t.type) || "Memo";
58
+ case $:
59
+ return d.displayName || "Context";
67
60
  case D:
68
- a = t._payload, t = t._init;
61
+ return (d._context.displayName || "Context") + ".Consumer";
62
+ case S:
63
+ var z = d.render;
64
+ return d = d.displayName, d || (d = z.displayName || z.name || "", d = d !== "" ? "ForwardRef(" + d + ")" : "ForwardRef"), d;
65
+ case G:
66
+ return z = d.displayName || null, z !== null ? z : s(d.type) || "Memo";
67
+ case Z:
68
+ z = d._payload, d = d._init;
69
69
  try {
70
- return l(t(a));
70
+ return s(d(z));
71
71
  } catch {
72
72
  }
73
73
  }
74
74
  return null;
75
75
  }
76
- function u(t) {
77
- return "" + t;
76
+ function N(d) {
77
+ return "" + d;
78
78
  }
79
- function p(t) {
79
+ function E(d) {
80
80
  try {
81
- u(t);
82
- var a = !1;
81
+ N(d);
82
+ var z = !1;
83
83
  } catch {
84
- a = !0;
84
+ z = !0;
85
85
  }
86
- if (a) {
87
- a = console;
88
- var y = a.error, j = typeof Symbol == "function" && Symbol.toStringTag && t[Symbol.toStringTag] || t.constructor.name || "Object";
89
- return y.call(
90
- a,
86
+ if (z) {
87
+ z = console;
88
+ var p = z.error, P = typeof Symbol == "function" && Symbol.toStringTag && d[Symbol.toStringTag] || d.constructor.name || "Object";
89
+ return p.call(
90
+ z,
91
91
  "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
92
- j
93
- ), u(t);
92
+ P
93
+ ), N(d);
94
94
  }
95
95
  }
96
- function w(t) {
97
- if (t === o) return "<>";
98
- if (typeof t == "object" && t !== null && t.$$typeof === D)
96
+ function w(d) {
97
+ if (d === T) return "<>";
98
+ if (typeof d == "object" && d !== null && d.$$typeof === Z)
99
99
  return "<...>";
100
100
  try {
101
- var a = l(t);
102
- return a ? "<" + a + ">" : "<...>";
101
+ var z = s(d);
102
+ return z ? "<" + z + ">" : "<...>";
103
103
  } catch {
104
104
  return "<...>";
105
105
  }
106
106
  }
107
- function i() {
108
- var t = U.A;
109
- return t === null ? null : t.getOwner();
107
+ function v() {
108
+ var d = X.A;
109
+ return d === null ? null : d.getOwner();
110
110
  }
111
- function d() {
111
+ function R() {
112
112
  return Error("react-stack-top-frame");
113
113
  }
114
- function x(t) {
115
- if (Q.call(t, "key")) {
116
- var a = Object.getOwnPropertyDescriptor(t, "key").get;
117
- if (a && a.isReactWarning) return !1;
114
+ function y(d) {
115
+ if (te.call(d, "key")) {
116
+ var z = Object.getOwnPropertyDescriptor(d, "key").get;
117
+ if (z && z.isReactWarning) return !1;
118
118
  }
119
- return t.key !== void 0;
119
+ return d.key !== void 0;
120
120
  }
121
- function E(t, a) {
122
- function y() {
123
- ee || (ee = !0, console.error(
121
+ function f(d, z) {
122
+ function p() {
123
+ ae || (ae = !0, console.error(
124
124
  "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
125
- a
125
+ z
126
126
  ));
127
127
  }
128
- y.isReactWarning = !0, Object.defineProperty(t, "key", {
129
- get: y,
128
+ p.isReactWarning = !0, Object.defineProperty(d, "key", {
129
+ get: p,
130
130
  configurable: !0
131
131
  });
132
132
  }
133
- function n() {
134
- var t = l(this.type);
135
- return te[t] || (te[t] = !0, console.error(
133
+ function j() {
134
+ var d = s(this.type);
135
+ return O[d] || (O[d] = !0, console.error(
136
136
  "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
137
- )), t = this.props.ref, t !== void 0 ? t : null;
137
+ )), d = this.props.ref, d !== void 0 ? d : null;
138
138
  }
139
- function _(t, a, y, j, I, q) {
140
- var N = y.ref;
141
- return t = {
142
- $$typeof: v,
143
- type: t,
144
- key: a,
145
- props: y,
146
- _owner: j
147
- }, (N !== void 0 ? N : null) !== null ? Object.defineProperty(t, "ref", {
139
+ function n(d, z, p, P, h, a) {
140
+ var t = p.ref;
141
+ return d = {
142
+ $$typeof: u,
143
+ type: d,
144
+ key: z,
145
+ props: p,
146
+ _owner: P
147
+ }, (t !== void 0 ? t : null) !== null ? Object.defineProperty(d, "ref", {
148
148
  enumerable: !1,
149
- get: n
150
- }) : Object.defineProperty(t, "ref", { enumerable: !1, value: null }), t._store = {}, Object.defineProperty(t._store, "validated", {
149
+ get: j
150
+ }) : Object.defineProperty(d, "ref", { enumerable: !1, value: null }), d._store = {}, Object.defineProperty(d._store, "validated", {
151
151
  configurable: !1,
152
152
  enumerable: !1,
153
153
  writable: !0,
154
154
  value: 0
155
- }), Object.defineProperty(t, "_debugInfo", {
155
+ }), Object.defineProperty(d, "_debugInfo", {
156
156
  configurable: !1,
157
157
  enumerable: !1,
158
158
  writable: !0,
159
159
  value: null
160
- }), Object.defineProperty(t, "_debugStack", {
160
+ }), Object.defineProperty(d, "_debugStack", {
161
161
  configurable: !1,
162
162
  enumerable: !1,
163
163
  writable: !0,
164
- value: I
165
- }), Object.defineProperty(t, "_debugTask", {
164
+ value: h
165
+ }), Object.defineProperty(d, "_debugTask", {
166
166
  configurable: !1,
167
167
  enumerable: !1,
168
168
  writable: !0,
169
- value: q
170
- }), Object.freeze && (Object.freeze(t.props), Object.freeze(t)), t;
169
+ value: a
170
+ }), Object.freeze && (Object.freeze(d.props), Object.freeze(d)), d;
171
171
  }
172
- function b(t, a, y, j, I, q) {
173
- var N = a.children;
174
- if (N !== void 0)
175
- if (j)
176
- if (he(N)) {
177
- for (j = 0; j < N.length; j++)
178
- k(N[j]);
179
- Object.freeze && Object.freeze(N);
172
+ function C(d, z, p, P, h, a) {
173
+ var t = z.children;
174
+ if (t !== void 0)
175
+ if (P)
176
+ if (se(t)) {
177
+ for (P = 0; P < t.length; P++)
178
+ c(t[P]);
179
+ Object.freeze && Object.freeze(t);
180
180
  } else
181
181
  console.error(
182
182
  "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
183
183
  );
184
- else k(N);
185
- if (Q.call(a, "key")) {
186
- N = l(t);
187
- var O = Object.keys(a).filter(function(me) {
188
- return me !== "key";
184
+ else c(t);
185
+ if (te.call(z, "key")) {
186
+ t = s(d);
187
+ var o = Object.keys(z).filter(function(l) {
188
+ return l !== "key";
189
189
  });
190
- j = 0 < O.length ? "{key: someKey, " + O.join(": ..., ") + ": ...}" : "{key: someKey}", ae[N + j] || (O = 0 < O.length ? "{" + O.join(": ..., ") + ": ...}" : "{}", console.error(
190
+ P = 0 < o.length ? "{key: someKey, " + o.join(": ..., ") + ": ...}" : "{key: someKey}", re[t + P] || (o = 0 < o.length ? "{" + o.join(": ..., ") + ": ...}" : "{}", console.error(
191
191
  `A props object containing a "key" prop is being spread into JSX:
192
192
  let props = %s;
193
193
  <%s {...props} />
194
194
  React keys must be passed directly to JSX without using spread:
195
195
  let props = %s;
196
196
  <%s key={someKey} {...props} />`,
197
- j,
198
- N,
199
- O,
200
- N
201
- ), ae[N + j] = !0);
197
+ P,
198
+ t,
199
+ o,
200
+ t
201
+ ), re[t + P] = !0);
202
202
  }
203
- if (N = null, y !== void 0 && (p(y), N = "" + y), x(a) && (p(a.key), N = "" + a.key), "key" in a) {
204
- y = {};
205
- for (var H in a)
206
- H !== "key" && (y[H] = a[H]);
207
- } else y = a;
208
- return N && E(
209
- y,
210
- typeof t == "function" ? t.displayName || t.name || "Unknown" : t
211
- ), _(
203
+ if (t = null, p !== void 0 && (E(p), t = "" + p), y(z) && (E(z.key), t = "" + z.key), "key" in z) {
204
+ p = {};
205
+ for (var r in z)
206
+ r !== "key" && (p[r] = z[r]);
207
+ } else p = z;
208
+ return t && f(
209
+ p,
210
+ typeof d == "function" ? d.displayName || d.name || "Unknown" : d
211
+ ), n(
212
+ d,
212
213
  t,
213
- N,
214
- y,
215
- i(),
216
- I,
217
- q
214
+ p,
215
+ v(),
216
+ h,
217
+ a
218
218
  );
219
219
  }
220
- function k(t) {
221
- g(t) ? t._store && (t._store.validated = 1) : typeof t == "object" && t !== null && t.$$typeof === D && (t._payload.status === "fulfilled" ? g(t._payload.value) && t._payload.value._store && (t._payload.value._store.validated = 1) : t._store && (t._store.validated = 1));
220
+ function c(d) {
221
+ i(d) ? d._store && (d._store.validated = 1) : typeof d == "object" && d !== null && d.$$typeof === Z && (d._payload.status === "fulfilled" ? i(d._payload.value) && d._payload.value._store && (d._payload.value._store.validated = 1) : d._store && (d._store.validated = 1));
222
222
  }
223
- function g(t) {
224
- return typeof t == "object" && t !== null && t.$$typeof === v;
223
+ function i(d) {
224
+ return typeof d == "object" && d !== null && d.$$typeof === u;
225
225
  }
226
- var R = xe, v = /* @__PURE__ */ Symbol.for("react.transitional.element"), S = /* @__PURE__ */ Symbol.for("react.portal"), o = /* @__PURE__ */ Symbol.for("react.fragment"), r = /* @__PURE__ */ Symbol.for("react.strict_mode"), c = /* @__PURE__ */ Symbol.for("react.profiler"), s = /* @__PURE__ */ Symbol.for("react.consumer"), T = /* @__PURE__ */ Symbol.for("react.context"), m = /* @__PURE__ */ Symbol.for("react.forward_ref"), h = /* @__PURE__ */ Symbol.for("react.suspense"), f = /* @__PURE__ */ Symbol.for("react.suspense_list"), C = /* @__PURE__ */ Symbol.for("react.memo"), D = /* @__PURE__ */ Symbol.for("react.lazy"), V = /* @__PURE__ */ Symbol.for("react.activity"), pe = /* @__PURE__ */ Symbol.for("react.client.reference"), U = R.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Q = Object.prototype.hasOwnProperty, he = Array.isArray, W = console.createTask ? console.createTask : function() {
226
+ var k = mt, u = /* @__PURE__ */ Symbol.for("react.transitional.element"), x = /* @__PURE__ */ Symbol.for("react.portal"), T = /* @__PURE__ */ Symbol.for("react.fragment"), A = /* @__PURE__ */ Symbol.for("react.strict_mode"), F = /* @__PURE__ */ Symbol.for("react.profiler"), D = /* @__PURE__ */ Symbol.for("react.consumer"), $ = /* @__PURE__ */ Symbol.for("react.context"), S = /* @__PURE__ */ Symbol.for("react.forward_ref"), U = /* @__PURE__ */ Symbol.for("react.suspense"), H = /* @__PURE__ */ Symbol.for("react.suspense_list"), G = /* @__PURE__ */ Symbol.for("react.memo"), Z = /* @__PURE__ */ Symbol.for("react.lazy"), oe = /* @__PURE__ */ Symbol.for("react.activity"), J = /* @__PURE__ */ Symbol.for("react.client.reference"), X = k.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, te = Object.prototype.hasOwnProperty, se = Array.isArray, ne = console.createTask ? console.createTask : function() {
227
227
  return null;
228
228
  };
229
- R = {
230
- react_stack_bottom_frame: function(t) {
231
- return t();
229
+ k = {
230
+ react_stack_bottom_frame: function(d) {
231
+ return d();
232
232
  }
233
233
  };
234
- var ee, te = {}, re = R.react_stack_bottom_frame.bind(
235
- R,
236
- d
237
- )(), se = W(w(d)), ae = {};
238
- z.Fragment = o, z.jsx = function(t, a, y) {
239
- var j = 1e4 > U.recentlyCreatedOwnerStacks++;
240
- return b(
241
- t,
242
- a,
243
- y,
234
+ var ae, O = {}, le = k.react_stack_bottom_frame.bind(
235
+ k,
236
+ R
237
+ )(), ie = ne(w(R)), re = {};
238
+ Ce.Fragment = T, Ce.jsx = function(d, z, p) {
239
+ var P = 1e4 > X.recentlyCreatedOwnerStacks++;
240
+ return C(
241
+ d,
242
+ z,
243
+ p,
244
244
  !1,
245
- j ? Error("react-stack-top-frame") : re,
246
- j ? W(w(t)) : se
245
+ P ? Error("react-stack-top-frame") : le,
246
+ P ? ne(w(d)) : ie
247
247
  );
248
- }, z.jsxs = function(t, a, y) {
249
- var j = 1e4 > U.recentlyCreatedOwnerStacks++;
250
- return b(
251
- t,
252
- a,
253
- y,
248
+ }, Ce.jsxs = function(d, z, p) {
249
+ var P = 1e4 > X.recentlyCreatedOwnerStacks++;
250
+ return C(
251
+ d,
252
+ z,
253
+ p,
254
254
  !0,
255
- j ? Error("react-stack-top-frame") : re,
256
- j ? W(w(t)) : se
255
+ P ? Error("react-stack-top-frame") : le,
256
+ P ? ne(w(d)) : ie
257
257
  );
258
258
  };
259
- })()), z;
259
+ })()), Ce;
260
260
  }
261
- var de;
262
- function De() {
263
- return de || (de = 1, process.env.NODE_ENV === "production" ? F.exports = Pe() : F.exports = Ce()), F.exports;
261
+ var et;
262
+ function qt() {
263
+ return et || (et = 1, process.env.NODE_ENV === "production" ? Me.exports = Wt() : Me.exports = Bt()), Me.exports;
264
264
  }
265
- var e = De();
266
- function J(...l) {
267
- return Y(M(l));
265
+ var e = qt();
266
+ function Re(s, N = {}) {
267
+ const { maxHistory: E = 50 } = N, [w, v] = K(s), R = ee([]), y = ee([]), f = b((c) => {
268
+ v((i) => (R.current = [...R.current.slice(-(E - 1)), i], y.current = [], c));
269
+ }, [E]), j = b(() => {
270
+ R.current.length !== 0 && v((c) => {
271
+ const i = [...R.current], k = i.pop();
272
+ return R.current = i, y.current = [c, ...y.current], k;
273
+ });
274
+ }, []), n = b(() => {
275
+ y.current.length !== 0 && v((c) => {
276
+ const i = [...y.current], k = i.shift();
277
+ return y.current = i, R.current = [...R.current, c], k;
278
+ });
279
+ }, []), C = b((c) => {
280
+ R.current = [], y.current = [], v(c);
281
+ }, []);
282
+ return {
283
+ current: w,
284
+ canUndo: R.current.length > 0,
285
+ canRedo: y.current.length > 0,
286
+ undoCount: R.current.length,
287
+ redoCount: y.current.length,
288
+ push: f,
289
+ undo: j,
290
+ redo: n,
291
+ reset: C
292
+ };
268
293
  }
269
- function Oe({
270
- canvas: l = { width: 1200, height: 800, gridSize: 8, showGrid: !0, snapToGrid: !0 },
271
- components: u = [],
272
- palette: p = $e,
273
- showComponentTree: w = !0,
274
- undoRedo: i = !0,
275
- readOnly: d = !1,
276
- onChange: x,
277
- className: E
294
+ function Ae() {
295
+ const [s, N] = K(!1), [E, w] = K(""), [v, R] = K(""), y = ee(null), f = b((C, c) => (w(C), R(c), N(!0), new Promise((i) => {
296
+ y.current = i;
297
+ })), []), j = b(() => {
298
+ N(!1), y.current?.(!0), y.current = null;
299
+ }, []), n = b(() => {
300
+ N(!1), y.current?.(!1), y.current = null;
301
+ }, []);
302
+ return { isOpen: s, title: E, message: v, confirm: f, onConfirm: j, onCancel: n };
303
+ }
304
+ function Le() {
305
+ const [s, N] = K(/* @__PURE__ */ new Set()), E = b((f, j = !1) => {
306
+ N((n) => {
307
+ const C = new Set(j ? n : []);
308
+ return n.has(f) && j ? C.delete(f) : C.add(f), C;
309
+ });
310
+ }, []), w = b((f) => {
311
+ N(/* @__PURE__ */ new Set([f]));
312
+ }, []), v = b((f) => {
313
+ N(new Set(f));
314
+ }, []), R = b(() => {
315
+ N(/* @__PURE__ */ new Set());
316
+ }, []), y = b((f) => s.has(f), [s]);
317
+ return {
318
+ selectedIds: s,
319
+ toggle: E,
320
+ selectOne: w,
321
+ selectMany: v,
322
+ clearSelection: R,
323
+ isSelected: y,
324
+ count: s.size
325
+ };
326
+ }
327
+ function Ie() {
328
+ const [s, N] = K(null), E = b((v) => {
329
+ N(structuredClone(v));
330
+ }, []), w = b(() => s ? structuredClone(s) : null, [s]);
331
+ return {
332
+ clipboard: s,
333
+ copy: E,
334
+ paste: w,
335
+ hasContent: s !== null
336
+ };
337
+ }
338
+ function We(s = {}) {
339
+ const { minZoom: N = 0.25, maxZoom: E = 3, zoomStep: w = 0.1, initialZoom: v = 1 } = s, [R, y] = K(v), [f, j] = K({ x: 0, y: 0 }), n = ee(!1), C = ee({ x: 0, y: 0 }), c = b((D) => Math.min(E, Math.max(N, +D.toFixed(2))), [N, E]), i = b(() => y((D) => c(D + w)), [c, w]), k = b(() => y((D) => c(D - w)), [c, w]), u = b(() => {
340
+ y(1), j({ x: 0, y: 0 });
341
+ }, []), x = b((D) => y(c(D)), [c]), T = b((D) => {
342
+ if (D.ctrlKey || D.metaKey) {
343
+ D.preventDefault();
344
+ const $ = D.deltaY > 0 ? -w : w;
345
+ y((S) => c(S + $));
346
+ }
347
+ }, [c, w]), A = b((D) => {
348
+ if (D.button === 1 || D.button === 0 && D.altKey) {
349
+ D.preventDefault(), n.current = !0, C.current = { x: D.clientX, y: D.clientY };
350
+ const $ = (U) => {
351
+ if (!n.current) return;
352
+ const H = U.clientX - C.current.x, G = U.clientY - C.current.y;
353
+ C.current = { x: U.clientX, y: U.clientY }, j((Z) => ({ x: Z.x + H, y: Z.y + G }));
354
+ }, S = () => {
355
+ n.current = !1, document.removeEventListener("mousemove", $), document.removeEventListener("mouseup", S);
356
+ };
357
+ document.addEventListener("mousemove", $), document.addEventListener("mouseup", S);
358
+ }
359
+ }, []), F = {
360
+ transform: `translate(${f.x}px, ${f.y}px) scale(${R})`,
361
+ transformOrigin: "0 0"
362
+ };
363
+ return {
364
+ zoom: R,
365
+ panOffset: f,
366
+ zoomIn: i,
367
+ zoomOut: k,
368
+ resetZoom: u,
369
+ setZoom: x,
370
+ handleWheel: T,
371
+ startPan: A,
372
+ transformStyle: F
373
+ };
374
+ }
375
+ function Jt(...s) {
376
+ return pe(ue(s));
377
+ }
378
+ function Fe({
379
+ isOpen: s,
380
+ title: N,
381
+ message: E,
382
+ confirmLabel: w = "Delete",
383
+ cancelLabel: v = "Cancel",
384
+ destructive: R = !0,
385
+ onConfirm: y,
386
+ onCancel: f
278
387
  }) {
279
- const [n, _] = A(u), [b, k] = A(null), [g, R] = A(l.zoom ?? 1), v = Z(
280
- () => n.find((r) => r.id === b),
281
- [n, b]
282
- ), S = P(
283
- (r, c) => {
284
- if (d) return;
285
- const s = {
286
- id: `comp-${Date.now()}`,
287
- type: r,
288
- label: c,
289
- position: { x: 100, y: 100, width: 200, height: 100 },
290
- props: {}
291
- }, T = [...n, s];
292
- _(T), k(s.id), x?.(T);
293
- },
294
- [n, d, x]
295
- ), o = P(
296
- (r) => {
297
- if (d) return;
298
- const c = n.filter((s) => s.id !== r);
299
- _(c), b === r && k(null), x?.(c);
300
- },
301
- [n, b, d, x]
302
- );
303
- return /* @__PURE__ */ e.jsxs("div", { className: J("flex h-full w-full border rounded-lg overflow-hidden bg-background", E), children: [
304
- !d && /* @__PURE__ */ e.jsxs("div", { className: "w-60 border-r bg-muted/30 flex flex-col", children: [
305
- /* @__PURE__ */ e.jsx("div", { className: "p-3 border-b font-medium text-sm", children: "Components" }),
306
- /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto p-2", children: p.map((r) => /* @__PURE__ */ e.jsxs("div", { className: "mb-3", children: [
307
- /* @__PURE__ */ e.jsx("div", { className: "text-xs font-medium text-muted-foreground px-2 py-1 uppercase", children: r.label }),
308
- r.items.map((c) => /* @__PURE__ */ e.jsxs(
388
+ const j = ee(null);
389
+ return fe(() => {
390
+ const n = j.current;
391
+ n && (s && !n.open ? n.showModal() : !s && n.open && n.close());
392
+ }, [s]), s ? /* @__PURE__ */ e.jsx(
393
+ "dialog",
394
+ {
395
+ ref: j,
396
+ className: "fixed inset-0 z-50 m-auto rounded-lg border bg-background p-0 shadow-lg backdrop:bg-black/50",
397
+ onClose: f,
398
+ "aria-labelledby": "confirm-title",
399
+ "aria-describedby": "confirm-message",
400
+ children: /* @__PURE__ */ e.jsxs("div", { className: "w-80 p-6", children: [
401
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
402
+ R && /* @__PURE__ */ e.jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-destructive/10", children: /* @__PURE__ */ e.jsx(xt, { className: "h-5 w-5 text-destructive" }) }),
403
+ /* @__PURE__ */ e.jsx("h2", { id: "confirm-title", className: "text-lg font-semibold", children: N })
404
+ ] }),
405
+ /* @__PURE__ */ e.jsx("p", { id: "confirm-message", className: "text-sm text-muted-foreground mb-6", children: E }),
406
+ /* @__PURE__ */ e.jsxs("div", { className: "flex justify-end gap-2", children: [
407
+ /* @__PURE__ */ e.jsx(
408
+ "button",
409
+ {
410
+ onClick: f,
411
+ className: "px-4 py-2 text-sm rounded-md border hover:bg-accent",
412
+ children: v
413
+ }
414
+ ),
415
+ /* @__PURE__ */ e.jsx(
416
+ "button",
417
+ {
418
+ onClick: y,
419
+ className: Jt(
420
+ "px-4 py-2 text-sm rounded-md font-medium",
421
+ R ? "bg-destructive text-destructive-foreground hover:bg-destructive/90" : "bg-primary text-primary-foreground hover:bg-primary/90"
422
+ ),
423
+ autoFocus: !0,
424
+ children: w
425
+ }
426
+ )
427
+ ] })
428
+ ] })
429
+ }
430
+ ) : null;
431
+ }
432
+ function Qt(...s) {
433
+ return pe(ue(s));
434
+ }
435
+ function Ue({
436
+ title: s = "Properties",
437
+ fields: N,
438
+ onChange: E,
439
+ className: w
440
+ }) {
441
+ const [v, R] = K(/* @__PURE__ */ new Set()), y = b((j) => {
442
+ R((n) => {
443
+ const C = new Set(n);
444
+ return C.has(j) ? C.delete(j) : C.add(j), C;
445
+ });
446
+ }, []), f = N.reduce((j, n) => {
447
+ const C = n.group ?? "General";
448
+ return j[C] || (j[C] = []), j[C].push(n), j;
449
+ }, {});
450
+ return /* @__PURE__ */ e.jsxs("div", { className: Qt("flex flex-col", w), role: "region", "aria-label": s, children: [
451
+ /* @__PURE__ */ e.jsx("div", { className: "p-3 border-b font-medium text-sm", children: s }),
452
+ /* @__PURE__ */ e.jsxs("div", { className: "flex-1 overflow-y-auto", children: [
453
+ Object.entries(f).map(([j, n]) => /* @__PURE__ */ e.jsxs("div", { className: "border-b last:border-b-0", children: [
454
+ /* @__PURE__ */ e.jsxs(
309
455
  "button",
310
456
  {
311
- onClick: () => S(c.type, c.label),
312
- className: "w-full flex items-center gap-2 px-2 py-1.5 text-sm rounded hover:bg-accent text-left",
457
+ onClick: () => y(j),
458
+ className: "w-full flex items-center gap-1 px-3 py-2 text-xs font-medium text-muted-foreground hover:bg-accent/50",
313
459
  children: [
314
- /* @__PURE__ */ e.jsx(K, { className: "h-3 w-3" }),
315
- c.label
460
+ v.has(j) ? /* @__PURE__ */ e.jsx(He, { className: "h-3 w-3" }) : /* @__PURE__ */ e.jsx(Xe, { className: "h-3 w-3" }),
461
+ j
316
462
  ]
317
- },
318
- c.type
319
- ))
320
- ] }, r.name)) })
463
+ }
464
+ ),
465
+ !v.has(j) && /* @__PURE__ */ e.jsx("div", { className: "px-3 pb-2 space-y-2", children: n.map((C) => /* @__PURE__ */ e.jsx(Ot, { field: C, onChange: E }, C.name)) })
466
+ ] }, j)),
467
+ N.length === 0 && /* @__PURE__ */ e.jsx("div", { className: "p-3 text-xs text-muted-foreground text-center", children: "Select an element to edit its properties" })
468
+ ] })
469
+ ] });
470
+ }
471
+ function Ot({ field: s, onChange: N }) {
472
+ const E = (w) => {
473
+ N(s.name, w);
474
+ };
475
+ return /* @__PURE__ */ e.jsxs("div", { className: "space-y-1", children: [
476
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: s.label }),
477
+ s.type === "text" && /* @__PURE__ */ e.jsx(
478
+ "input",
479
+ {
480
+ type: "text",
481
+ value: String(s.value ?? ""),
482
+ onChange: (w) => E(w.target.value),
483
+ className: "w-full px-2 py-1 text-xs border rounded bg-background"
484
+ }
485
+ ),
486
+ s.type === "number" && /* @__PURE__ */ e.jsx(
487
+ "input",
488
+ {
489
+ type: "number",
490
+ value: Number(s.value ?? 0),
491
+ onChange: (w) => E(Number(w.target.value)),
492
+ className: "w-full px-2 py-1 text-xs border rounded bg-background"
493
+ }
494
+ ),
495
+ s.type === "boolean" && /* @__PURE__ */ e.jsxs("label", { className: "flex items-center gap-2", children: [
496
+ /* @__PURE__ */ e.jsx(
497
+ "input",
498
+ {
499
+ type: "checkbox",
500
+ checked: !!s.value,
501
+ onChange: (w) => E(w.target.checked),
502
+ className: "rounded"
503
+ }
504
+ ),
505
+ /* @__PURE__ */ e.jsx("span", { className: "text-xs", children: s.value ? "Yes" : "No" })
321
506
  ] }),
322
- /* @__PURE__ */ e.jsxs("div", { className: "flex-1 flex flex-col", children: [
323
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 p-2 border-b bg-muted/20", children: [
324
- i && !d && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
325
- /* @__PURE__ */ e.jsx("button", { className: "p-1.5 rounded hover:bg-accent", title: "Undo", children: /* @__PURE__ */ e.jsx(be, { className: "h-4 w-4" }) }),
326
- /* @__PURE__ */ e.jsx("button", { className: "p-1.5 rounded hover:bg-accent", title: "Redo", children: /* @__PURE__ */ e.jsx(ge, { className: "h-4 w-4" }) }),
327
- /* @__PURE__ */ e.jsx("div", { className: "w-px h-5 bg-border mx-1" })
328
- ] }),
329
- /* @__PURE__ */ e.jsx("button", { className: "p-1.5 rounded hover:bg-accent", title: "Preview", children: /* @__PURE__ */ e.jsx(ye, { className: "h-4 w-4" }) }),
330
- /* @__PURE__ */ e.jsx("div", { className: "flex-1" }),
331
- /* @__PURE__ */ e.jsxs("span", { className: "text-xs text-muted-foreground", children: [
332
- Math.round(g * 100),
333
- "%"
334
- ] })
335
- ] }),
336
- /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-auto bg-muted/10 p-4", children: /* @__PURE__ */ e.jsx(
337
- "div",
507
+ s.type === "select" && /* @__PURE__ */ e.jsx(
508
+ "select",
509
+ {
510
+ value: String(s.value ?? ""),
511
+ onChange: (w) => E(w.target.value),
512
+ className: "w-full px-2 py-1 text-xs border rounded bg-background",
513
+ children: s.options?.map((w) => /* @__PURE__ */ e.jsx("option", { value: w.value, children: w.label }, w.value))
514
+ }
515
+ ),
516
+ s.type === "color" && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2", children: [
517
+ /* @__PURE__ */ e.jsx(
518
+ "input",
338
519
  {
339
- className: "relative bg-background border rounded shadow-sm mx-auto",
340
- style: {
341
- width: l.width * g,
342
- height: l.height * g,
343
- backgroundImage: l.showGrid ? "radial-gradient(circle, hsl(var(--border)) 1px, transparent 1px)" : void 0,
344
- backgroundSize: l.showGrid && l.gridSize ? `${l.gridSize * g}px ${l.gridSize * g}px` : void 0
520
+ type: "color",
521
+ value: String(s.value ?? "#000000"),
522
+ onChange: (w) => E(w.target.value),
523
+ className: "h-6 w-6 rounded border cursor-pointer"
524
+ }
525
+ ),
526
+ /* @__PURE__ */ e.jsx("span", { className: "text-xs font-mono", children: String(s.value ?? "#000000") })
527
+ ] }),
528
+ s.type === "textarea" && /* @__PURE__ */ e.jsx(
529
+ "textarea",
530
+ {
531
+ value: String(s.value ?? ""),
532
+ onChange: (w) => E(w.target.value),
533
+ className: "w-full px-2 py-1 text-xs border rounded bg-background resize-y",
534
+ rows: 3
535
+ }
536
+ ),
537
+ s.description && /* @__PURE__ */ e.jsx("p", { className: "text-[0.65rem] text-muted-foreground/70", children: s.description })
538
+ ] });
539
+ }
540
+ function er(...s) {
541
+ return pe(ue(s));
542
+ }
543
+ function Be({
544
+ items: s,
545
+ canvasWidth: N,
546
+ canvasHeight: E,
547
+ position: w = "bottom-right",
548
+ size: v = 150,
549
+ className: R
550
+ }) {
551
+ const y = Math.min(v / N, v / E), f = N * y, j = E * y, n = {
552
+ "top-left": "top-2 left-2",
553
+ "top-right": "top-2 right-2",
554
+ "bottom-left": "bottom-2 left-2",
555
+ "bottom-right": "bottom-2 right-2"
556
+ };
557
+ return /* @__PURE__ */ e.jsx(
558
+ "div",
559
+ {
560
+ className: er(
561
+ "absolute border rounded bg-background/90 shadow-sm overflow-hidden",
562
+ n[w],
563
+ R
564
+ ),
565
+ role: "img",
566
+ "aria-label": "Canvas minimap",
567
+ children: /* @__PURE__ */ e.jsxs("svg", { width: f, height: j, viewBox: `0 0 ${N} ${E}`, children: [
568
+ /* @__PURE__ */ e.jsx("rect", { width: N, height: E, fill: "hsl(var(--muted))", opacity: "0.3" }),
569
+ s.map((C) => /* @__PURE__ */ e.jsx(
570
+ "rect",
571
+ {
572
+ x: C.x,
573
+ y: C.y,
574
+ width: C.width,
575
+ height: C.height,
576
+ fill: C.selected ? "hsl(var(--primary))" : C.color ?? "hsl(var(--foreground) / 0.3)",
577
+ rx: "2"
345
578
  },
346
- children: n.map((r) => /* @__PURE__ */ e.jsxs(
579
+ C.id
580
+ ))
581
+ ] })
582
+ }
583
+ );
584
+ }
585
+ function tr(...s) {
586
+ return pe(ue(s));
587
+ }
588
+ const Ge = ht(null);
589
+ Ge.displayName = "CollaborationContext";
590
+ function vr({
591
+ config: s,
592
+ user: N,
593
+ onOperation: E,
594
+ onPresenceChange: w,
595
+ children: v
596
+ }) {
597
+ const R = ee(null), [y, f] = K([]), [j, n] = K("disconnected"), C = ee(0), c = ee(null);
598
+ fe(() => {
599
+ if (!s.enabled || !N || !s.serverUrl || !(typeof WebSocket < "u")) return;
600
+ function A() {
601
+ let F;
602
+ try {
603
+ if (F = new URL(s.serverUrl), F.protocol !== "ws:" && F.protocol !== "wss:") return;
604
+ } catch {
605
+ return;
606
+ }
607
+ s.roomId && F.searchParams.set("room", s.roomId), F.searchParams.set("userId", N.id), n("connecting");
608
+ const D = new WebSocket(F.toString());
609
+ D.onopen = () => {
610
+ n("connected"), D.send(JSON.stringify({
611
+ type: "join",
612
+ userId: N.id,
613
+ userName: N.name,
614
+ avatar: N.avatar
615
+ }));
616
+ }, D.onmessage = ($) => {
617
+ try {
618
+ const S = JSON.parse($.data);
619
+ if (S.type === "presence") {
620
+ const U = S.users || [];
621
+ f(U.filter((H) => H.userId !== N.id)), w?.(U);
622
+ } else S.type === "operation" && E?.(S.operation);
623
+ } catch {
624
+ }
625
+ }, D.onclose = () => {
626
+ n("disconnected"), R.current = null, s.enabled && (c.current = setTimeout(A, s.autoSaveInterval ?? 3e3));
627
+ }, D.onerror = () => {
628
+ n("error");
629
+ }, R.current = D;
630
+ }
631
+ return A(), () => {
632
+ c.current && clearTimeout(c.current), R.current && (R.current.onclose = null, R.current.close(), R.current = null), n("disconnected");
633
+ };
634
+ }, [s.enabled, s.serverUrl, s.roomId, s.autoSaveInterval, N, E, w]);
635
+ const i = ce(() => !s.enabled || !N ? [] : [{
636
+ userId: N.id,
637
+ userName: N.name,
638
+ avatar: N.avatar,
639
+ color: rr(N.id),
640
+ status: "active",
641
+ lastActivity: (/* @__PURE__ */ new Date()).toISOString()
642
+ }, ...y], [s.enabled, N, y]), k = s.enabled && !!N && (s.serverUrl ? j === "connected" : !0), u = b(
643
+ (T) => {
644
+ if (!s.enabled || !N) return;
645
+ C.current += 1;
646
+ const A = {
647
+ ...T,
648
+ id: `op-${Date.now()}-${C.current}`,
649
+ userId: N.id,
650
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
651
+ version: C.current
652
+ };
653
+ R.current?.readyState === WebSocket.OPEN && R.current.send(JSON.stringify({ type: "operation", operation: A })), E?.(A);
654
+ },
655
+ [s.enabled, N, E]
656
+ ), x = ce(
657
+ () => ({
658
+ users: i,
659
+ isConnected: k,
660
+ sendOperation: u,
661
+ currentUserId: N?.id,
662
+ connectionState: j,
663
+ versionCount: C.current
664
+ }),
665
+ [i, k, u, N?.id, j]
666
+ );
667
+ return /* @__PURE__ */ e.jsx(Ge.Provider, { value: x, children: v });
668
+ }
669
+ function $e() {
670
+ return rt(Ge);
671
+ }
672
+ function yr({ className: s }) {
673
+ const N = rt(Ge);
674
+ if (!N) return null;
675
+ const { connectionState: E, users: w } = N, v = {
676
+ connected: { color: "bg-green-500", label: "Connected" },
677
+ connecting: { color: "bg-yellow-500 animate-pulse", label: "Connecting…" },
678
+ disconnected: { color: "bg-gray-400", label: "Disconnected" },
679
+ error: { color: "bg-red-500", label: "Connection error" }
680
+ }, { color: R, label: y } = v[E] ?? v.disconnected;
681
+ return /* @__PURE__ */ e.jsxs("div", { className: tr("flex items-center gap-2 text-xs", s), role: "status", "aria-live": "polite", "aria-label": `Collaboration: ${y}`, children: [
682
+ /* @__PURE__ */ e.jsx("span", { className: `inline-block h-2 w-2 rounded-full ${R}` }),
683
+ /* @__PURE__ */ e.jsx("span", { children: y }),
684
+ E === "connected" && w.length > 1 && /* @__PURE__ */ e.jsxs("span", { className: "text-muted-foreground", children: [
685
+ "(",
686
+ w.length,
687
+ " users)"
688
+ ] })
689
+ ] });
690
+ }
691
+ function rr(s) {
692
+ const N = [
693
+ "#3b82f6",
694
+ "#ef4444",
695
+ "#22c55e",
696
+ "#f59e0b",
697
+ "#8b5cf6",
698
+ "#ec4899",
699
+ "#06b6d4",
700
+ "#f97316",
701
+ "#14b8a6",
702
+ "#f43f5e",
703
+ "#a855f7",
704
+ "#84cc16",
705
+ "#0ea5e9",
706
+ "#e879f9",
707
+ "#fb923c",
708
+ "#facc15"
709
+ ];
710
+ let E = 0;
711
+ for (let w = 0; w < s.length; w++)
712
+ E = (E << 5) - E + s.charCodeAt(w) | 0;
713
+ return N[Math.abs(E) % N.length];
714
+ }
715
+ function de(...s) {
716
+ return pe(ue(s));
717
+ }
718
+ function sr({
719
+ canvas: s = { width: 1200, height: 800, gridSize: 8, showGrid: !0, snapToGrid: !0 },
720
+ components: N = [],
721
+ palette: E = nr,
722
+ showComponentTree: w = !0,
723
+ undoRedo: v = !0,
724
+ propertyEditor: R = !0,
725
+ readOnly: y = !1,
726
+ showMinimap: f = !1,
727
+ onChange: j,
728
+ className: n
729
+ }) {
730
+ const C = Re(N), c = C.current, i = b(
731
+ (a) => {
732
+ C.push(a), j?.(a);
733
+ },
734
+ [C, j]
735
+ ), k = We({
736
+ initialZoom: s.zoom ?? 1
737
+ }), { zoom: u } = k, x = Le(), T = ce(() => {
738
+ const a = Array.from(x.selectedIds);
739
+ return a.length > 0 ? a[0] : null;
740
+ }, [x.selectedIds]), A = ce(
741
+ () => c.find((a) => a.id === T),
742
+ [c, T]
743
+ ), F = Ie(), D = Ae(), $ = $e(), S = b(
744
+ (a) => {
745
+ $ && $.sendOperation({ ...a, userId: $.currentUserId ?? "" });
746
+ },
747
+ [$]
748
+ ), [U, H] = K(!0), [G, Z] = K(!0), [oe, J] = K(f), X = ee(null), te = ee(null), se = b(
749
+ (a) => !s.snapToGrid || !s.gridSize ? a : Math.round(a / s.gridSize) * s.gridSize,
750
+ [s.snapToGrid, s.gridSize]
751
+ ), ne = b(
752
+ (a, t) => {
753
+ if (y) return;
754
+ const o = E.flatMap((I) => I.items).find((I) => I.type === a), r = o?.defaultSize, l = {
755
+ id: `comp-${Date.now()}`,
756
+ type: a,
757
+ label: t,
758
+ position: {
759
+ x: 100,
760
+ y: 100,
761
+ width: r?.width ?? 200,
762
+ height: r?.height ?? 100
763
+ },
764
+ props: o?.defaultProps ?? {}
765
+ }, g = [...c, l];
766
+ i(g), x.selectOne(l.id), S({ type: "insert", elementId: l.id, data: { component: l } });
767
+ },
768
+ [c, y, E, i, x, S]
769
+ ), ae = b(
770
+ (a) => {
771
+ if (y) return;
772
+ const t = c.filter((o) => o.id !== a);
773
+ i(t), x.isSelected(a) && x.clearSelection(), S({ type: "delete", elementId: a, data: {} });
774
+ },
775
+ [c, y, i, x, S]
776
+ ), O = b(async () => {
777
+ if (y || x.count === 0 || !await D.confirm(
778
+ "Delete components",
779
+ `Are you sure you want to delete ${x.count} component${x.count > 1 ? "s" : ""}?`
780
+ )) return;
781
+ const t = x.selectedIds, o = c.filter((r) => !t.has(r.id));
782
+ i(o), x.clearSelection(), t.forEach((r) => {
783
+ S({ type: "delete", elementId: r, data: {} });
784
+ });
785
+ }, [y, x, D, c, i, S]), le = b(
786
+ (a, t) => {
787
+ if (y || !T) return;
788
+ const o = c.map((r) => r.id !== T ? r : a === "label" ? { ...r, label: String(t) } : a === "x" ? { ...r, position: { ...r.position, x: Number(t) } } : a === "y" ? { ...r, position: { ...r.position, y: Number(t) } } : a === "width" ? { ...r, position: { ...r.position, width: Number(t) } } : a === "height" ? { ...r, position: { ...r.position, height: Number(t) } } : { ...r, props: { ...r.props, [a]: t } });
789
+ i(o), S({ type: "update", elementId: T, data: { [a]: t } });
790
+ },
791
+ [y, T, c, i, S]
792
+ ), ie = b(() => {
793
+ const a = x.selectedIds;
794
+ if (a.size === 0) return;
795
+ const t = c.filter((o) => a.has(o.id));
796
+ F.copy(t);
797
+ }, [x, c, F]), re = b(() => {
798
+ if (y) return;
799
+ const a = F.paste();
800
+ if (!a || a.length === 0) return;
801
+ let t = 0;
802
+ const o = a.map((l) => ({
803
+ ...l,
804
+ id: `comp-${Date.now()}-${++t}-${Math.random().toString(36).slice(2, 7)}`,
805
+ position: { ...l.position, x: l.position.x + 20, y: l.position.y + 20 }
806
+ })), r = [...c, ...o];
807
+ i(r), x.selectMany(o.map((l) => l.id)), o.forEach((l) => {
808
+ S({ type: "insert", elementId: l.id, data: { component: l } });
809
+ });
810
+ }, [y, F, c, i, x, S]), d = b(
811
+ (a, t) => {
812
+ y || (X.current = { id: t.id, startX: a.clientX, startY: a.clientY }, a.dataTransfer.effectAllowed = "move", a.dataTransfer.setData("text/plain", t.id));
813
+ },
814
+ [y]
815
+ ), z = b((a) => {
816
+ a.preventDefault(), a.dataTransfer.dropEffect = "move";
817
+ }, []), p = b(
818
+ (a) => {
819
+ a.preventDefault();
820
+ const t = X.current;
821
+ if (!t || y) return;
822
+ const o = (a.clientX - t.startX) / u, r = (a.clientY - t.startY) / u, l = c.map((g) => g.id !== t.id ? g : {
823
+ ...g,
824
+ position: {
825
+ ...g.position,
826
+ x: se(g.position.x + o),
827
+ y: se(g.position.y + r)
828
+ }
829
+ });
830
+ i(l), S({ type: "move", elementId: t.id, data: {} }), X.current = null;
831
+ },
832
+ [y, u, c, i, se, S]
833
+ ), P = ce(() => A ? [
834
+ { name: "label", label: "Label", type: "text", value: A.label ?? "", group: "General" },
835
+ { name: "x", label: "X", type: "number", value: A.position.x, group: "Position" },
836
+ { name: "y", label: "Y", type: "number", value: A.position.y, group: "Position" },
837
+ { name: "width", label: "Width", type: "number", value: A.position.width, group: "Size" },
838
+ { name: "height", label: "Height", type: "number", value: A.position.height, group: "Size" }
839
+ ] : [], [A]), h = ce(
840
+ () => c.map((a) => ({
841
+ id: a.id,
842
+ x: a.position.x,
843
+ y: a.position.y,
844
+ width: typeof a.position.width == "number" ? a.position.width : 100,
845
+ height: typeof a.position.height == "number" ? a.position.height : 50,
846
+ selected: x.isSelected(a.id)
847
+ })),
848
+ [c, x]
849
+ );
850
+ return fe(() => {
851
+ const a = te.current;
852
+ if (!a) return;
853
+ const t = (o) => {
854
+ const r = ["INPUT", "TEXTAREA", "SELECT"].includes(o.target.tagName), l = o.ctrlKey || o.metaKey;
855
+ if ((o.key === "Delete" || o.key === "Backspace") && x.count > 0 && !r) {
856
+ o.preventDefault(), O();
857
+ return;
858
+ }
859
+ if (o.key === "Escape") {
860
+ x.clearSelection();
861
+ return;
862
+ }
863
+ if (!r) {
864
+ if (l && o.key === "z" && !o.shiftKey && v && !y) {
865
+ o.preventDefault(), C.undo();
866
+ return;
867
+ }
868
+ if (l && (o.key === "z" && o.shiftKey || o.key === "y") && v && !y) {
869
+ o.preventDefault(), C.redo();
870
+ return;
871
+ }
872
+ if (l && o.key === "c") {
873
+ o.preventDefault(), ie();
874
+ return;
875
+ }
876
+ if (l && o.key === "v" && !y) {
877
+ o.preventDefault(), re();
878
+ return;
879
+ }
880
+ if (l && o.key === "a") {
881
+ o.preventDefault(), x.selectMany(c.map((g) => g.id));
882
+ return;
883
+ }
884
+ }
885
+ };
886
+ return a.addEventListener("keydown", t), () => a.removeEventListener("keydown", t);
887
+ }, [
888
+ x,
889
+ O,
890
+ v,
891
+ y,
892
+ C,
893
+ ie,
894
+ re,
895
+ c
896
+ ]), /* @__PURE__ */ e.jsxs(
897
+ "div",
898
+ {
899
+ ref: te,
900
+ tabIndex: 0,
901
+ className: de(
902
+ "flex h-full w-full border rounded-lg overflow-hidden bg-background",
903
+ n
904
+ ),
905
+ children: [
906
+ !y && /* @__PURE__ */ e.jsx(
907
+ "div",
908
+ {
909
+ className: de(
910
+ "border-r bg-muted/30 flex flex-col transition-[width] duration-200",
911
+ U ? "w-60" : "w-0 overflow-hidden"
912
+ ),
913
+ role: "region",
914
+ "aria-label": "Component palette",
915
+ children: U && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
916
+ /* @__PURE__ */ e.jsx("div", { className: "p-3 border-b font-medium text-sm", children: "Components" }),
917
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto p-2", children: E.map((a) => /* @__PURE__ */ e.jsxs("div", { className: "mb-3", children: [
918
+ /* @__PURE__ */ e.jsx("div", { className: "text-xs font-medium text-muted-foreground px-2 py-1 uppercase", children: a.label }),
919
+ a.items.map((t) => /* @__PURE__ */ e.jsxs(
920
+ "button",
921
+ {
922
+ onClick: () => ne(t.type, t.label),
923
+ className: "w-full flex items-center gap-2 px-2 py-1.5 text-sm rounded hover:bg-accent text-left",
924
+ children: [
925
+ /* @__PURE__ */ e.jsx(xe, { className: "h-3 w-3" }),
926
+ t.label
927
+ ]
928
+ },
929
+ t.type
930
+ ))
931
+ ] }, a.name)) })
932
+ ] })
933
+ }
934
+ ),
935
+ /* @__PURE__ */ e.jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
936
+ /* @__PURE__ */ e.jsxs(
347
937
  "div",
348
938
  {
349
- className: J(
350
- "absolute border rounded cursor-move select-none transition-shadow",
351
- b === r.id ? "border-primary ring-2 ring-primary/20 shadow-md" : "border-border hover:border-primary/50"
352
- ),
353
- style: {
354
- left: r.position.x * g,
355
- top: r.position.y * g,
356
- width: typeof r.position.width == "number" ? r.position.width * g : r.position.width,
357
- height: typeof r.position.height == "number" ? r.position.height * g : r.position.height
358
- },
359
- onClick: () => k(r.id),
939
+ className: "flex items-center gap-2 p-2 border-b bg-muted/20",
940
+ role: "toolbar",
941
+ "aria-label": "Designer toolbar",
360
942
  children: [
361
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 px-2 py-1 bg-muted/50 text-xs border-b", children: [
362
- /* @__PURE__ */ e.jsx(ve, { className: "h-3 w-3 text-muted-foreground" }),
363
- /* @__PURE__ */ e.jsx("span", { className: "truncate", children: r.label ?? r.type }),
364
- !d && /* @__PURE__ */ e.jsx(
943
+ !y && /* @__PURE__ */ e.jsx(
944
+ "button",
945
+ {
946
+ className: "p-1.5 rounded hover:bg-accent",
947
+ title: U ? "Collapse palette" : "Expand palette",
948
+ "aria-label": U ? "Collapse palette" : "Expand palette",
949
+ onClick: () => H((a) => !a),
950
+ children: /* @__PURE__ */ e.jsx(ft, { className: de("h-4 w-4", !U && "rotate-180") })
951
+ }
952
+ ),
953
+ v && !y && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
954
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-5 bg-border mx-1" }),
955
+ /* @__PURE__ */ e.jsx(
365
956
  "button",
366
957
  {
367
- onClick: (c) => {
368
- c.stopPropagation(), o(r.id);
369
- },
370
- className: "ml-auto p-0.5 rounded hover:bg-destructive/10",
371
- children: /* @__PURE__ */ e.jsx(L, { className: "h-3 w-3 text-destructive" })
958
+ className: de("p-1.5 rounded hover:bg-accent", !C.canUndo && "opacity-40 pointer-events-none"),
959
+ title: "Undo (Ctrl+Z)",
960
+ "aria-label": "Undo",
961
+ disabled: !C.canUndo,
962
+ onClick: () => C.undo(),
963
+ children: /* @__PURE__ */ e.jsx(Ee, { className: "h-4 w-4" })
964
+ }
965
+ ),
966
+ /* @__PURE__ */ e.jsx(
967
+ "button",
968
+ {
969
+ className: de("p-1.5 rounded hover:bg-accent", !C.canRedo && "opacity-40 pointer-events-none"),
970
+ title: "Redo (Ctrl+Shift+Z)",
971
+ "aria-label": "Redo",
972
+ disabled: !C.canRedo,
973
+ onClick: () => C.redo(),
974
+ children: /* @__PURE__ */ e.jsx(De, { className: "h-4 w-4" })
975
+ }
976
+ ),
977
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-5 bg-border mx-1" })
978
+ ] }),
979
+ !y && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
980
+ /* @__PURE__ */ e.jsx(
981
+ "button",
982
+ {
983
+ className: de("p-1.5 rounded hover:bg-accent", x.count === 0 && "opacity-40 pointer-events-none"),
984
+ title: "Copy (Ctrl+C)",
985
+ "aria-label": "Copy",
986
+ disabled: x.count === 0,
987
+ onClick: ie,
988
+ children: /* @__PURE__ */ e.jsx(Pe, { className: "h-4 w-4" })
989
+ }
990
+ ),
991
+ /* @__PURE__ */ e.jsx(
992
+ "button",
993
+ {
994
+ className: de("p-1.5 rounded hover:bg-accent", !F.hasContent && "opacity-40 pointer-events-none"),
995
+ title: "Paste (Ctrl+V)",
996
+ "aria-label": "Paste",
997
+ disabled: !F.hasContent,
998
+ onClick: re,
999
+ children: /* @__PURE__ */ e.jsx(Te, { className: "h-4 w-4" })
1000
+ }
1001
+ ),
1002
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-5 bg-border mx-1" })
1003
+ ] }),
1004
+ !y && /* @__PURE__ */ e.jsx(
1005
+ "button",
1006
+ {
1007
+ className: de("p-1.5 rounded hover:bg-accent", x.count === 0 && "opacity-40 pointer-events-none"),
1008
+ title: "Delete selected",
1009
+ "aria-label": "Delete selected",
1010
+ disabled: x.count === 0,
1011
+ onClick: O,
1012
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-4 w-4" })
1013
+ }
1014
+ ),
1015
+ /* @__PURE__ */ e.jsx("button", { className: "p-1.5 rounded hover:bg-accent", title: "Preview", "aria-label": "Preview", children: /* @__PURE__ */ e.jsx(st, { className: "h-4 w-4" }) }),
1016
+ /* @__PURE__ */ e.jsx(
1017
+ "button",
1018
+ {
1019
+ className: de("p-1.5 rounded hover:bg-accent", oe && "bg-accent"),
1020
+ title: "Toggle minimap",
1021
+ "aria-label": "Toggle minimap",
1022
+ onClick: () => J((a) => !a),
1023
+ children: /* @__PURE__ */ e.jsx(nt, { className: "h-4 w-4" })
1024
+ }
1025
+ ),
1026
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1" }),
1027
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1", children: [
1028
+ /* @__PURE__ */ e.jsx(
1029
+ "button",
1030
+ {
1031
+ className: "p-1 rounded hover:bg-accent text-xs",
1032
+ "aria-label": "Zoom out",
1033
+ onClick: k.zoomOut,
1034
+ children: /* @__PURE__ */ e.jsx(bt, { className: "h-3 w-3" })
1035
+ }
1036
+ ),
1037
+ /* @__PURE__ */ e.jsxs("span", { className: "text-xs text-muted-foreground w-10 text-center", children: [
1038
+ Math.round(u * 100),
1039
+ "%"
1040
+ ] }),
1041
+ /* @__PURE__ */ e.jsx(
1042
+ "button",
1043
+ {
1044
+ className: "p-1 rounded hover:bg-accent text-xs",
1045
+ "aria-label": "Zoom in",
1046
+ onClick: k.zoomIn,
1047
+ children: /* @__PURE__ */ e.jsx(xe, { className: "h-3 w-3" })
1048
+ }
1049
+ ),
1050
+ /* @__PURE__ */ e.jsx(
1051
+ "button",
1052
+ {
1053
+ className: "p-1 rounded hover:bg-accent text-xs",
1054
+ "aria-label": "Reset zoom",
1055
+ onClick: k.resetZoom,
1056
+ children: /* @__PURE__ */ e.jsx(gt, { className: "h-3 w-3" })
372
1057
  }
373
1058
  )
374
1059
  ] }),
375
- /* @__PURE__ */ e.jsx("div", { className: "p-2 text-xs text-muted-foreground", children: r.type })
1060
+ w && /* @__PURE__ */ e.jsx(
1061
+ "button",
1062
+ {
1063
+ className: "p-1.5 rounded hover:bg-accent",
1064
+ title: G ? "Collapse panel" : "Expand panel",
1065
+ "aria-label": G ? "Collapse panel" : "Expand panel",
1066
+ onClick: () => Z((a) => !a),
1067
+ children: /* @__PURE__ */ e.jsx(Ke, { className: de("h-4 w-4", !G && "rotate-180") })
1068
+ }
1069
+ )
376
1070
  ]
377
- },
378
- r.id
379
- ))
380
- }
381
- ) })
382
- ] }),
383
- w && /* @__PURE__ */ e.jsxs("div", { className: "w-60 border-l bg-muted/30 flex flex-col", children: [
384
- /* @__PURE__ */ e.jsxs("div", { className: "p-3 border-b font-medium text-sm flex items-center gap-2", children: [
385
- /* @__PURE__ */ e.jsx(we, { className: "h-4 w-4" }),
386
- "Component Tree"
387
- ] }),
388
- /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto p-2", children: n.length === 0 ? /* @__PURE__ */ e.jsx("div", { className: "text-xs text-muted-foreground text-center py-4", children: "No components added yet" }) : n.map((r) => /* @__PURE__ */ e.jsx(
389
- "button",
390
- {
391
- onClick: () => k(r.id),
392
- className: J(
393
- "w-full flex items-center gap-2 px-2 py-1.5 text-sm rounded text-left",
394
- b === r.id ? "bg-accent" : "hover:bg-accent/50"
1071
+ }
395
1072
  ),
396
- children: /* @__PURE__ */ e.jsx("span", { className: "truncate", children: r.label ?? r.type })
397
- },
398
- r.id
399
- )) }),
400
- v && /* @__PURE__ */ e.jsxs("div", { className: "border-t p-3", children: [
401
- /* @__PURE__ */ e.jsx("div", { className: "text-xs font-medium mb-2", children: "Properties" }),
402
- /* @__PURE__ */ e.jsxs("div", { className: "text-xs text-muted-foreground space-y-1", children: [
403
- /* @__PURE__ */ e.jsxs("div", { children: [
404
- "Type: ",
405
- v.type
406
- ] }),
407
- /* @__PURE__ */ e.jsxs("div", { children: [
408
- "ID: ",
409
- v.id
410
- ] }),
411
- /* @__PURE__ */ e.jsxs("div", { children: [
412
- "Position: ",
413
- v.position.x,
414
- ", ",
415
- v.position.y
416
- ] }),
417
- /* @__PURE__ */ e.jsxs("div", { children: [
418
- "Size: ",
419
- v.position.width,
420
- " × ",
421
- v.position.height
422
- ] })
423
- ] })
424
- ] })
425
- ] })
426
- ] });
1073
+ /* @__PURE__ */ e.jsx(
1074
+ "div",
1075
+ {
1076
+ className: "flex-1 overflow-auto bg-muted/10 p-4 relative",
1077
+ role: "region",
1078
+ "aria-label": "Design canvas",
1079
+ onWheel: k.handleWheel,
1080
+ onMouseDown: k.startPan,
1081
+ onDragOver: z,
1082
+ onDrop: p,
1083
+ children: /* @__PURE__ */ e.jsxs(
1084
+ "div",
1085
+ {
1086
+ className: "relative bg-background border rounded shadow-sm mx-auto",
1087
+ style: {
1088
+ width: s.width * u,
1089
+ height: s.height * u,
1090
+ transform: `translate(${k.panOffset.x}px, ${k.panOffset.y}px)`,
1091
+ backgroundImage: s.showGrid ? "radial-gradient(circle, hsl(var(--border)) 1px, transparent 1px)" : void 0,
1092
+ backgroundSize: s.showGrid && s.gridSize ? `${s.gridSize * u}px ${s.gridSize * u}px` : void 0
1093
+ },
1094
+ children: [
1095
+ c.map((a) => {
1096
+ const t = x.isSelected(a.id);
1097
+ return /* @__PURE__ */ e.jsxs(
1098
+ "div",
1099
+ {
1100
+ draggable: !y,
1101
+ onDragStart: (o) => d(o, a),
1102
+ className: de(
1103
+ "absolute border rounded cursor-move select-none transition-shadow",
1104
+ t ? "border-primary ring-2 ring-primary/20 shadow-md" : "border-border hover:border-primary/50"
1105
+ ),
1106
+ style: {
1107
+ left: a.position.x * u,
1108
+ top: a.position.y * u,
1109
+ width: typeof a.position.width == "number" ? a.position.width * u : a.position.width,
1110
+ height: typeof a.position.height == "number" ? a.position.height * u : a.position.height
1111
+ },
1112
+ onClick: (o) => x.toggle(a.id, o.shiftKey),
1113
+ children: [
1114
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 px-2 py-1 bg-muted/50 text-xs border-b", children: [
1115
+ /* @__PURE__ */ e.jsx(at, { className: "h-3 w-3 text-muted-foreground" }),
1116
+ /* @__PURE__ */ e.jsx("span", { className: "truncate", children: a.label ?? a.type }),
1117
+ !y && /* @__PURE__ */ e.jsx(
1118
+ "button",
1119
+ {
1120
+ onClick: (o) => {
1121
+ o.stopPropagation(), ae(a.id);
1122
+ },
1123
+ className: "ml-auto p-0.5 rounded hover:bg-destructive/10",
1124
+ "aria-label": `Delete ${a.label ?? a.type}`,
1125
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-3 w-3 text-destructive" })
1126
+ }
1127
+ )
1128
+ ] }),
1129
+ /* @__PURE__ */ e.jsx("div", { className: "p-2 text-xs text-muted-foreground", children: a.type })
1130
+ ]
1131
+ },
1132
+ a.id
1133
+ );
1134
+ }),
1135
+ oe && /* @__PURE__ */ e.jsx(
1136
+ Be,
1137
+ {
1138
+ items: h,
1139
+ canvasWidth: s.width,
1140
+ canvasHeight: s.height
1141
+ }
1142
+ )
1143
+ ]
1144
+ }
1145
+ )
1146
+ }
1147
+ )
1148
+ ] }),
1149
+ w && /* @__PURE__ */ e.jsx(
1150
+ "div",
1151
+ {
1152
+ className: de(
1153
+ "border-l bg-muted/30 flex flex-col transition-[width] duration-200",
1154
+ G ? "w-60" : "w-0 overflow-hidden"
1155
+ ),
1156
+ role: "region",
1157
+ "aria-label": "Component tree",
1158
+ children: G && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
1159
+ /* @__PURE__ */ e.jsxs("div", { className: "p-3 border-b font-medium text-sm flex items-center gap-2", children: [
1160
+ /* @__PURE__ */ e.jsx(vt, { className: "h-4 w-4" }),
1161
+ "Component Tree"
1162
+ ] }),
1163
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto p-2", children: c.length === 0 ? /* @__PURE__ */ e.jsx("div", { className: "text-xs text-muted-foreground text-center py-4", children: "No components added yet. Click a component in the palette to add it to the canvas." }) : c.map((a) => /* @__PURE__ */ e.jsx(
1164
+ "button",
1165
+ {
1166
+ onClick: (t) => x.toggle(a.id, t.shiftKey),
1167
+ className: de(
1168
+ "w-full flex items-center gap-2 px-2 py-1.5 text-sm rounded text-left",
1169
+ x.isSelected(a.id) ? "bg-accent" : "hover:bg-accent/50"
1170
+ ),
1171
+ children: /* @__PURE__ */ e.jsx("span", { className: "truncate", children: a.label ?? a.type })
1172
+ },
1173
+ a.id
1174
+ )) }),
1175
+ R && A ? /* @__PURE__ */ e.jsx("div", { className: "border-t", children: /* @__PURE__ */ e.jsx(
1176
+ Ue,
1177
+ {
1178
+ title: `Properties – ${A.label ?? A.type}`,
1179
+ fields: P,
1180
+ onChange: le
1181
+ }
1182
+ ) }) : A && /* @__PURE__ */ e.jsxs("div", { className: "border-t p-3", children: [
1183
+ /* @__PURE__ */ e.jsx("div", { className: "text-xs font-medium mb-2", children: "Properties" }),
1184
+ /* @__PURE__ */ e.jsxs("div", { className: "text-xs text-muted-foreground space-y-1", children: [
1185
+ /* @__PURE__ */ e.jsxs("div", { children: [
1186
+ "Type: ",
1187
+ A.type
1188
+ ] }),
1189
+ /* @__PURE__ */ e.jsxs("div", { children: [
1190
+ "ID: ",
1191
+ A.id
1192
+ ] }),
1193
+ /* @__PURE__ */ e.jsxs("div", { children: [
1194
+ "Position: ",
1195
+ A.position.x,
1196
+ ",",
1197
+ " ",
1198
+ A.position.y
1199
+ ] }),
1200
+ /* @__PURE__ */ e.jsxs("div", { children: [
1201
+ "Size: ",
1202
+ A.position.width,
1203
+ " ×",
1204
+ " ",
1205
+ A.position.height
1206
+ ] })
1207
+ ] })
1208
+ ] })
1209
+ ] })
1210
+ }
1211
+ ),
1212
+ /* @__PURE__ */ e.jsx(
1213
+ Fe,
1214
+ {
1215
+ isOpen: D.isOpen,
1216
+ title: D.title,
1217
+ message: D.message,
1218
+ onConfirm: D.onConfirm,
1219
+ onCancel: D.onCancel
1220
+ }
1221
+ )
1222
+ ]
1223
+ }
1224
+ );
427
1225
  }
428
- const $e = [
1226
+ const nr = [
429
1227
  {
430
1228
  name: "layout",
431
1229
  label: "Layout",
@@ -459,212 +1257,775 @@ const $e = [
459
1257
  ]
460
1258
  }
461
1259
  ];
462
- function B(...l) {
463
- return Y(M(l));
1260
+ function Ve(...s) {
1261
+ return pe(ue(s));
464
1262
  }
465
- function ze({
466
- entities: l = [],
467
- relationships: u = [],
468
- canvas: p = { width: 1200, height: 800, showGrid: !0 },
1263
+ function ar(s, N = 4, E = 280, w = 250, v = 50, R = 50) {
1264
+ return s.map((y, f) => ({
1265
+ ...y,
1266
+ position: {
1267
+ x: v + f % N * E,
1268
+ y: R + Math.floor(f / N) * w
1269
+ }
1270
+ }));
1271
+ }
1272
+ function or({
1273
+ entities: s = [],
1274
+ relationships: N = [],
1275
+ canvas: E = { width: 1200, height: 800, showGrid: !0 },
469
1276
  showRelationshipLabels: w = !0,
470
- readOnly: i = !1,
471
- onEntitiesChange: d,
472
- onRelationshipsChange: x,
473
- className: E
1277
+ readOnly: v = !1,
1278
+ onEntitiesChange: R,
1279
+ onRelationshipsChange: y,
1280
+ className: f
474
1281
  }) {
475
- const [n, _] = A(l), [b, k] = A(u), [g, R] = A(null), v = P(() => {
476
- if (i) return;
477
- const o = {
1282
+ const j = ee(null), n = Re(
1283
+ { entities: s, relationships: N },
1284
+ { maxHistory: 50 }
1285
+ ), { entities: C, relationships: c } = n.current, i = b(
1286
+ (r) => {
1287
+ n.push(r), R?.(r.entities), y?.(r.relationships);
1288
+ },
1289
+ [n, R, y]
1290
+ ), k = Ae(), u = Le(), x = u.count > 0 ? Array.from(u.selectedIds)[0] : null, T = Ie(), A = We({ minZoom: 0.25, maxZoom: 3, zoomStep: 0.1 }), F = $e(), [D, $] = K(!0), [S, U] = K(!0), [H, G] = K(null), [Z, oe] = K(""), J = ee(null), X = b(() => {
1291
+ if (v) return;
1292
+ const r = n.current, l = {
478
1293
  id: `entity-${Date.now()}`,
479
- name: `new_entity_${n.length + 1}`,
480
- label: `New Entity ${n.length + 1}`,
1294
+ name: `new_entity_${r.entities.length + 1}`,
1295
+ label: `New Entity ${r.entities.length + 1}`,
481
1296
  fields: [
482
1297
  { name: "id", type: "uuid", primaryKey: !0, required: !0 },
483
1298
  { name: "created_at", type: "datetime", required: !0 },
484
1299
  { name: "updated_at", type: "datetime", required: !0 }
485
1300
  ],
486
- position: { x: 50 + n.length % 4 * 280, y: 50 + Math.floor(n.length / 4) * 250 }
487
- }, r = [...n, o];
488
- _(r), R(o.id), d?.(r);
489
- }, [n, i, d]), S = P(
490
- (o) => {
491
- if (i) return;
492
- const r = n.filter((s) => s.id !== o), c = b.filter(
493
- (s) => s.sourceEntity !== o && s.targetEntity !== o
494
- );
495
- _(r), k(c), g === o && R(null), d?.(r), x?.(c);
496
- },
497
- [n, b, g, i, d, x]
498
- );
499
- return /* @__PURE__ */ e.jsx("div", { className: B("flex h-full w-full border rounded-lg overflow-hidden bg-background", E), children: /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col w-full", children: [
500
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 p-2 border-b bg-muted/20", children: [
501
- /* @__PURE__ */ e.jsx(le, { className: "h-4 w-4" }),
502
- /* @__PURE__ */ e.jsx("span", { className: "font-medium text-sm", children: "Data Model Designer" }),
503
- /* @__PURE__ */ e.jsx("div", { className: "flex-1" }),
504
- !i && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
505
- /* @__PURE__ */ e.jsxs(
506
- "button",
507
- {
508
- onClick: v,
509
- className: "flex items-center gap-1 px-2 py-1 text-xs rounded bg-primary text-primary-foreground hover:bg-primary/90",
510
- children: [
511
- /* @__PURE__ */ e.jsx(K, { className: "h-3 w-3" }),
512
- " Add Entity"
513
- ]
514
- }
515
- ),
516
- /* @__PURE__ */ e.jsxs(
517
- "button",
518
- {
519
- className: "flex items-center gap-1 px-2 py-1 text-xs rounded bg-secondary text-secondary-foreground hover:bg-secondary/80",
520
- children: [
521
- /* @__PURE__ */ e.jsx(je, { className: "h-3 w-3" }),
522
- " Add Relationship"
523
- ]
524
- }
1301
+ position: {
1302
+ x: 50 + r.entities.length % 4 * 280,
1303
+ y: 50 + Math.floor(r.entities.length / 4) * 250
1304
+ }
1305
+ }, g = {
1306
+ entities: [...r.entities, l],
1307
+ relationships: r.relationships
1308
+ };
1309
+ i(g), u.selectOne(l.id), F?.sendOperation({ type: "insert", userId: F?.currentUserId ?? "", elementId: l.id, data: { name: l.name, label: l.label } });
1310
+ }, [v, n, i, u, F]), te = b(
1311
+ async (r) => {
1312
+ if (v) return;
1313
+ const l = C.find((Q) => Q.id === r);
1314
+ if (!await k.confirm(
1315
+ "Delete Entity",
1316
+ `Are you sure you want to delete "${l?.label ?? r}"? This action cannot be undone.`
1317
+ )) return;
1318
+ const I = n.current, V = {
1319
+ entities: I.entities.filter((Q) => Q.id !== r),
1320
+ relationships: I.relationships.filter(
1321
+ (Q) => Q.sourceEntity !== r && Q.targetEntity !== r
525
1322
  )
526
- ] })
527
- ] }),
528
- /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-auto bg-muted/10 p-4", children: /* @__PURE__ */ e.jsxs(
529
- "div",
530
- {
531
- className: "relative",
532
- style: {
533
- width: p.width,
534
- minHeight: p.height,
535
- backgroundImage: p.showGrid ? "radial-gradient(circle, hsl(var(--border)) 1px, transparent 1px)" : void 0,
536
- backgroundSize: p.showGrid ? "20px 20px" : void 0
537
- },
538
- children: [
539
- /* @__PURE__ */ e.jsx(
540
- "svg",
541
- {
542
- className: "absolute inset-0 pointer-events-none",
543
- width: p.width,
544
- height: p.height,
545
- children: b.map((o) => {
546
- const r = n.find((s) => s.id === o.sourceEntity), c = n.find((s) => s.id === o.targetEntity);
547
- return !r || !c ? null : /* @__PURE__ */ e.jsxs("g", { children: [
548
- /* @__PURE__ */ e.jsx(
549
- "line",
550
- {
551
- x1: r.position.x + 120,
552
- y1: r.position.y + 50,
553
- x2: c.position.x + 120,
554
- y2: c.position.y + 50,
555
- stroke: "hsl(var(--primary))",
556
- strokeWidth: "2",
557
- strokeDasharray: o.type === "many-to-many" ? "5,5" : void 0
558
- }
559
- ),
560
- w && o.label && /* @__PURE__ */ e.jsx(
561
- "text",
562
- {
563
- x: (r.position.x + c.position.x) / 2 + 120,
564
- y: (r.position.y + c.position.y) / 2 + 50 - 8,
565
- textAnchor: "middle",
566
- className: "text-xs fill-muted-foreground",
567
- children: o.label
568
- }
569
- )
570
- ] }, o.id);
571
- })
572
- }
573
- ),
574
- n.map((o) => /* @__PURE__ */ e.jsxs(
1323
+ };
1324
+ i(V), u.isSelected(r) && u.clearSelection(), F?.sendOperation({ type: "delete", userId: F?.currentUserId ?? "", elementId: r, data: {} });
1325
+ },
1326
+ [v, C, k, n, i, u, F]
1327
+ ), se = b(async () => {
1328
+ if (v || u.count === 0) return;
1329
+ const r = Array.from(u.selectedIds);
1330
+ if (!await k.confirm(
1331
+ "Delete Entities",
1332
+ `Are you sure you want to delete ${r.length} selected entity(s)? This action cannot be undone.`
1333
+ )) return;
1334
+ const g = n.current, I = new Set(r), V = {
1335
+ entities: g.entities.filter((Q) => !I.has(Q.id)),
1336
+ relationships: g.relationships.filter(
1337
+ (Q) => !I.has(Q.sourceEntity) && !I.has(Q.targetEntity)
1338
+ )
1339
+ };
1340
+ i(V), u.clearSelection();
1341
+ }, [v, u, k, n, i]), ne = b(() => {
1342
+ if (v) return;
1343
+ const r = n.current, l = {
1344
+ entities: ar(r.entities),
1345
+ relationships: r.relationships
1346
+ };
1347
+ i(l);
1348
+ }, [v, n, i]), ae = b(() => {
1349
+ const r = C.filter((l) => u.isSelected(l.id));
1350
+ r.length > 0 && T.copy(r);
1351
+ }, [C, u, T]), O = b(() => {
1352
+ if (v) return;
1353
+ const r = T.paste();
1354
+ if (!r || r.length === 0) return;
1355
+ const l = n.current, g = r.map((V, Q) => ({
1356
+ ...V,
1357
+ id: `entity-${Date.now()}-${Q}`,
1358
+ name: `${V.name}_copy`,
1359
+ label: `${V.label} (Copy)`,
1360
+ position: { x: V.position.x + 30, y: V.position.y + 30 }
1361
+ })), I = {
1362
+ entities: [...l.entities, ...g],
1363
+ relationships: l.relationships
1364
+ };
1365
+ i(I), u.selectMany(g.map((V) => V.id));
1366
+ }, [v, T, n, i, u]), le = b(
1367
+ (r) => {
1368
+ if (v) return;
1369
+ const l = n.current, g = {
1370
+ entities: l.entities.map((I) => {
1371
+ if (I.id !== r) return I;
1372
+ const V = {
1373
+ name: `field_${I.fields.length + 1}`,
1374
+ type: "text",
1375
+ required: !1
1376
+ };
1377
+ return { ...I, fields: [...I.fields, V] };
1378
+ }),
1379
+ relationships: l.relationships
1380
+ };
1381
+ i(g);
1382
+ },
1383
+ [v, n, i]
1384
+ ), ie = b(
1385
+ (r, l, g) => {
1386
+ v || (G({ entityId: r, fieldIndex: l }), oe(g));
1387
+ },
1388
+ [v]
1389
+ ), re = b(() => {
1390
+ if (!H) return;
1391
+ const r = Z.trim();
1392
+ if (r === "") {
1393
+ G(null);
1394
+ return;
1395
+ }
1396
+ const l = n.current, g = {
1397
+ entities: l.entities.map((I) => {
1398
+ if (I.id !== H.entityId) return I;
1399
+ const V = I.fields.map(
1400
+ (Q, we) => we === H.fieldIndex ? { ...Q, name: r } : Q
1401
+ );
1402
+ return { ...I, fields: V };
1403
+ }),
1404
+ relationships: l.relationships
1405
+ };
1406
+ i(g), G(null);
1407
+ }, [H, Z, n, i]), d = b(() => {
1408
+ G(null);
1409
+ }, []), z = b(
1410
+ (r, l) => {
1411
+ if (v || !C.find((V) => V.id === l)) return;
1412
+ const I = r.target.getBoundingClientRect();
1413
+ J.current = {
1414
+ entityId: l,
1415
+ offsetX: r.clientX - I.left,
1416
+ offsetY: r.clientY - I.top
1417
+ }, r.dataTransfer.effectAllowed = "move", r.dataTransfer.setData("text/plain", l);
1418
+ },
1419
+ [v, C]
1420
+ ), p = b((r) => {
1421
+ r.preventDefault(), r.dataTransfer.dropEffect = "move";
1422
+ }, []), P = b(
1423
+ (r) => {
1424
+ if (r.preventDefault(), !J.current) return;
1425
+ const l = r.currentTarget.getBoundingClientRect(), g = A.zoom, I = (r.clientX - l.left - A.panOffset.x) / g - J.current.offsetX, V = (r.clientY - l.top - A.panOffset.y) / g - J.current.offsetY, Q = n.current, we = {
1426
+ entities: Q.entities.map(
1427
+ (je) => je.id === J.current.entityId ? { ...je, position: { x: Math.max(0, Math.round(I)), y: Math.max(0, Math.round(V)) } } : je
1428
+ ),
1429
+ relationships: Q.relationships
1430
+ };
1431
+ i(we), J.current = null;
1432
+ },
1433
+ [A.zoom, A.panOffset, n, i]
1434
+ ), h = x ? C.find((r) => r.id === x) : null, a = h ? [
1435
+ { name: "name", label: "Name", type: "text", value: h.name, group: "General" },
1436
+ { name: "label", label: "Label", type: "text", value: h.label, group: "General" },
1437
+ { name: "description", label: "Description", type: "textarea", value: h.description ?? "", group: "General" },
1438
+ { name: "color", label: "Color", type: "color", value: h.color ?? "#3b82f6", group: "Appearance" },
1439
+ { name: "position.x", label: "X Position", type: "number", value: h.position.x, group: "Position" },
1440
+ { name: "position.y", label: "Y Position", type: "number", value: h.position.y, group: "Position" }
1441
+ ] : [], t = b(
1442
+ (r, l) => {
1443
+ if (!x) return;
1444
+ const g = n.current, I = {
1445
+ entities: g.entities.map((V) => V.id !== x ? V : r === "position.x" ? { ...V, position: { ...V.position, x: Number(l) } } : r === "position.y" ? { ...V, position: { ...V.position, y: Number(l) } } : { ...V, [r]: l }),
1446
+ relationships: g.relationships
1447
+ };
1448
+ i(I);
1449
+ },
1450
+ [x, n, i]
1451
+ );
1452
+ fe(() => {
1453
+ const r = j.current;
1454
+ if (!r) return;
1455
+ const l = (g) => {
1456
+ const I = g.target.tagName;
1457
+ if (I === "INPUT" || I === "TEXTAREA" || I === "SELECT") return;
1458
+ const V = g.ctrlKey || g.metaKey;
1459
+ V && g.key === "z" ? (g.preventDefault(), n.undo()) : V && (g.key === "y" || g.shiftKey && g.key === "Z") ? (g.preventDefault(), n.redo()) : V && g.key === "c" ? (g.preventDefault(), ae()) : V && g.key === "v" ? (g.preventDefault(), O()) : (g.key === "Delete" || g.key === "Backspace") && u.count > 0 ? (g.preventDefault(), se()) : g.key === "Escape" && (u.clearSelection(), G(null));
1460
+ };
1461
+ return r.addEventListener("keydown", l), () => r.removeEventListener("keydown", l);
1462
+ }, [n, ae, O, se, u]);
1463
+ const o = C.map((r) => ({
1464
+ id: r.id,
1465
+ x: r.position.x,
1466
+ y: r.position.y,
1467
+ width: 240,
1468
+ height: 40 + r.fields.length * 24,
1469
+ color: r.color,
1470
+ selected: u.isSelected(r.id)
1471
+ }));
1472
+ return /* @__PURE__ */ e.jsxs(
1473
+ "div",
1474
+ {
1475
+ ref: j,
1476
+ tabIndex: 0,
1477
+ className: Ve("flex h-full w-full border rounded-lg overflow-hidden bg-background", f),
1478
+ children: [
1479
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col flex-1 min-w-0", children: [
1480
+ /* @__PURE__ */ e.jsxs("div", { role: "toolbar", "aria-label": "Designer toolbar", className: "flex items-center gap-2 p-2 border-b bg-muted/20 flex-wrap", children: [
1481
+ /* @__PURE__ */ e.jsx(qe, { className: "h-4 w-4" }),
1482
+ /* @__PURE__ */ e.jsx("span", { className: "font-medium text-sm", children: "Data Model Designer" }),
1483
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 ml-2 border-l pl-2", children: [
1484
+ /* @__PURE__ */ e.jsx(
1485
+ "button",
1486
+ {
1487
+ onClick: () => n.undo(),
1488
+ disabled: !n.canUndo,
1489
+ "aria-label": "Undo",
1490
+ title: "Undo (Ctrl+Z)",
1491
+ className: "p-1 rounded hover:bg-accent disabled:opacity-40",
1492
+ children: /* @__PURE__ */ e.jsx(Ee, { className: "h-3.5 w-3.5" })
1493
+ }
1494
+ ),
1495
+ /* @__PURE__ */ e.jsx(
1496
+ "button",
1497
+ {
1498
+ onClick: () => n.redo(),
1499
+ disabled: !n.canRedo,
1500
+ "aria-label": "Redo",
1501
+ title: "Redo (Ctrl+Y)",
1502
+ className: "p-1 rounded hover:bg-accent disabled:opacity-40",
1503
+ children: /* @__PURE__ */ e.jsx(De, { className: "h-3.5 w-3.5" })
1504
+ }
1505
+ )
1506
+ ] }),
1507
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 border-l pl-2", children: [
1508
+ /* @__PURE__ */ e.jsx(
1509
+ "button",
1510
+ {
1511
+ onClick: A.zoomOut,
1512
+ "aria-label": "Zoom Out",
1513
+ title: "Zoom Out",
1514
+ className: "p-1 rounded hover:bg-accent",
1515
+ children: /* @__PURE__ */ e.jsx(ot, { className: "h-3.5 w-3.5" })
1516
+ }
1517
+ ),
1518
+ /* @__PURE__ */ e.jsxs("span", { className: "text-xs tabular-nums w-10 text-center", children: [
1519
+ Math.round(A.zoom * 100),
1520
+ "%"
1521
+ ] }),
1522
+ /* @__PURE__ */ e.jsx(
1523
+ "button",
1524
+ {
1525
+ onClick: A.zoomIn,
1526
+ "aria-label": "Zoom In",
1527
+ title: "Zoom In",
1528
+ className: "p-1 rounded hover:bg-accent",
1529
+ children: /* @__PURE__ */ e.jsx(lt, { className: "h-3.5 w-3.5" })
1530
+ }
1531
+ ),
1532
+ /* @__PURE__ */ e.jsx(
1533
+ "button",
1534
+ {
1535
+ onClick: A.resetZoom,
1536
+ "aria-label": "Reset Zoom",
1537
+ title: "Reset Zoom",
1538
+ className: "p-1 rounded hover:bg-accent",
1539
+ children: /* @__PURE__ */ e.jsx(it, { className: "h-3 w-3" })
1540
+ }
1541
+ )
1542
+ ] }),
1543
+ !v && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 border-l pl-2", children: [
1544
+ /* @__PURE__ */ e.jsx(
1545
+ "button",
1546
+ {
1547
+ onClick: ae,
1548
+ disabled: u.count === 0,
1549
+ "aria-label": "Copy",
1550
+ title: "Copy (Ctrl+C)",
1551
+ className: "p-1 rounded hover:bg-accent disabled:opacity-40",
1552
+ children: /* @__PURE__ */ e.jsx(Pe, { className: "h-3.5 w-3.5" })
1553
+ }
1554
+ ),
1555
+ /* @__PURE__ */ e.jsx(
1556
+ "button",
1557
+ {
1558
+ onClick: O,
1559
+ disabled: !T.hasContent,
1560
+ "aria-label": "Paste",
1561
+ title: "Paste (Ctrl+V)",
1562
+ className: "p-1 rounded hover:bg-accent disabled:opacity-40",
1563
+ children: /* @__PURE__ */ e.jsx(Te, { className: "h-3.5 w-3.5" })
1564
+ }
1565
+ )
1566
+ ] }),
1567
+ !v && /* @__PURE__ */ e.jsxs(
1568
+ "button",
1569
+ {
1570
+ onClick: ne,
1571
+ "aria-label": "Auto Layout",
1572
+ title: "Auto Layout",
1573
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded border hover:bg-accent",
1574
+ children: [
1575
+ /* @__PURE__ */ e.jsx(yt, { className: "h-3 w-3" }),
1576
+ " Auto Layout"
1577
+ ]
1578
+ }
1579
+ ),
1580
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1" }),
1581
+ F?.isConnected && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", role: "status", "aria-label": "Collaboration active", children: [
1582
+ /* @__PURE__ */ e.jsx(wt, { className: "h-3 w-3" }),
1583
+ /* @__PURE__ */ e.jsxs("span", { children: [
1584
+ F.users.length,
1585
+ " user",
1586
+ F.users.length !== 1 ? "s" : ""
1587
+ ] })
1588
+ ] }),
1589
+ u.count > 1 && /* @__PURE__ */ e.jsxs("span", { className: "text-xs text-muted-foreground", children: [
1590
+ u.count,
1591
+ " selected"
1592
+ ] }),
1593
+ !v && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
1594
+ /* @__PURE__ */ e.jsxs(
1595
+ "button",
1596
+ {
1597
+ onClick: X,
1598
+ "aria-label": "Add Entity",
1599
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded bg-primary text-primary-foreground hover:bg-primary/90",
1600
+ children: [
1601
+ /* @__PURE__ */ e.jsx(xe, { className: "h-3 w-3" }),
1602
+ " Add Entity"
1603
+ ]
1604
+ }
1605
+ ),
1606
+ /* @__PURE__ */ e.jsxs(
1607
+ "button",
1608
+ {
1609
+ "aria-label": "Add Relationship",
1610
+ title: "Add Relationship (coming soon)",
1611
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded bg-secondary text-secondary-foreground hover:bg-secondary/80",
1612
+ children: [
1613
+ /* @__PURE__ */ e.jsx(jt, { className: "h-3 w-3" }),
1614
+ " Add Relationship"
1615
+ ]
1616
+ }
1617
+ )
1618
+ ] })
1619
+ ] }),
1620
+ /* @__PURE__ */ e.jsxs(
575
1621
  "div",
576
1622
  {
577
- className: B(
578
- "absolute rounded-lg border-2 bg-background shadow-sm w-60 select-none",
579
- g === o.id ? "border-primary ring-2 ring-primary/20" : "border-border hover:border-primary/50"
580
- ),
581
- style: {
582
- left: o.position.x,
583
- top: o.position.y
584
- },
585
- onClick: () => R(o.id),
1623
+ role: "region",
1624
+ "aria-label": "Canvas",
1625
+ className: "flex-1 overflow-auto bg-muted/10 p-4 relative",
1626
+ onWheel: A.handleWheel,
1627
+ onMouseDown: A.startPan,
1628
+ onDragOver: p,
1629
+ onDrop: P,
586
1630
  children: [
587
1631
  /* @__PURE__ */ e.jsxs(
588
1632
  "div",
589
1633
  {
590
- className: "flex items-center gap-2 px-3 py-2 rounded-t-lg font-medium text-sm",
591
- style: { backgroundColor: o.color ?? "hsl(var(--primary) / 0.1)" },
1634
+ className: "relative",
1635
+ style: {
1636
+ width: E.width,
1637
+ minHeight: E.height,
1638
+ ...A.transformStyle,
1639
+ backgroundImage: E.showGrid ? "radial-gradient(circle, hsl(var(--border)) 1px, transparent 1px)" : void 0,
1640
+ backgroundSize: E.showGrid ? "20px 20px" : void 0
1641
+ },
592
1642
  children: [
593
- /* @__PURE__ */ e.jsx(le, { className: "h-3.5 w-3.5" }),
594
- /* @__PURE__ */ e.jsx("span", { className: "truncate", children: o.label }),
595
- !i && /* @__PURE__ */ e.jsx(
596
- "button",
1643
+ /* @__PURE__ */ e.jsx(
1644
+ "svg",
597
1645
  {
598
- onClick: (r) => {
599
- r.stopPropagation(), S(o.id);
600
- },
601
- className: "ml-auto p-0.5 rounded hover:bg-destructive/20",
602
- children: /* @__PURE__ */ e.jsx(L, { className: "h-3 w-3 text-destructive" })
1646
+ className: "absolute inset-0 pointer-events-none",
1647
+ width: E.width,
1648
+ height: E.height,
1649
+ children: c.map((r) => {
1650
+ const l = C.find((I) => I.id === r.sourceEntity), g = C.find((I) => I.id === r.targetEntity);
1651
+ return !l || !g ? null : /* @__PURE__ */ e.jsxs("g", { children: [
1652
+ /* @__PURE__ */ e.jsx(
1653
+ "line",
1654
+ {
1655
+ x1: l.position.x + 120,
1656
+ y1: l.position.y + 50,
1657
+ x2: g.position.x + 120,
1658
+ y2: g.position.y + 50,
1659
+ stroke: "hsl(var(--primary))",
1660
+ strokeWidth: "2",
1661
+ strokeDasharray: r.type === "many-to-many" ? "5,5" : void 0
1662
+ }
1663
+ ),
1664
+ w && r.label && /* @__PURE__ */ e.jsx(
1665
+ "text",
1666
+ {
1667
+ x: (l.position.x + g.position.x) / 2 + 120,
1668
+ y: (l.position.y + g.position.y) / 2 + 50 - 8,
1669
+ textAnchor: "middle",
1670
+ className: "text-xs fill-muted-foreground",
1671
+ children: r.label
1672
+ }
1673
+ )
1674
+ ] }, r.id);
1675
+ })
603
1676
  }
604
- )
1677
+ ),
1678
+ C.length === 0 && /* @__PURE__ */ e.jsx("div", { className: "absolute inset-0 flex items-center justify-center text-muted-foreground text-sm", children: "No entities in the model. Click 'Add Entity' to create your first entity." }),
1679
+ C.map((r) => /* @__PURE__ */ e.jsxs(
1680
+ "div",
1681
+ {
1682
+ role: "group",
1683
+ "aria-label": r.label,
1684
+ draggable: !v,
1685
+ onDragStart: (l) => z(l, r.id),
1686
+ className: Ve(
1687
+ "absolute rounded-lg border-2 bg-background shadow-sm w-60 select-none cursor-grab active:cursor-grabbing",
1688
+ u.isSelected(r.id) ? "border-primary ring-2 ring-primary/20" : "border-border hover:border-primary/50"
1689
+ ),
1690
+ style: {
1691
+ left: r.position.x,
1692
+ top: r.position.y
1693
+ },
1694
+ onClick: (l) => u.toggle(r.id, l.shiftKey),
1695
+ children: [
1696
+ /* @__PURE__ */ e.jsxs(
1697
+ "div",
1698
+ {
1699
+ className: "flex items-center gap-2 px-3 py-2 rounded-t-lg font-medium text-sm",
1700
+ style: { backgroundColor: r.color ?? "hsl(var(--primary) / 0.1)" },
1701
+ children: [
1702
+ /* @__PURE__ */ e.jsx(qe, { className: "h-3.5 w-3.5" }),
1703
+ /* @__PURE__ */ e.jsx("span", { className: "truncate", children: r.label }),
1704
+ !v && /* @__PURE__ */ e.jsx(
1705
+ "button",
1706
+ {
1707
+ onClick: (l) => {
1708
+ l.stopPropagation(), te(r.id);
1709
+ },
1710
+ "aria-label": `Delete ${r.label}`,
1711
+ className: "ml-auto p-0.5 rounded hover:bg-destructive/20",
1712
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-3 w-3 text-destructive" })
1713
+ }
1714
+ )
1715
+ ]
1716
+ }
1717
+ ),
1718
+ /* @__PURE__ */ e.jsx("div", { className: "px-3 py-1 divide-y", children: r.fields.map((l, g) => /* @__PURE__ */ e.jsxs(
1719
+ "div",
1720
+ {
1721
+ className: "flex items-center gap-2 py-1 text-xs",
1722
+ children: [
1723
+ H && H.entityId === r.id && H.fieldIndex === g ? /* @__PURE__ */ e.jsx(
1724
+ "input",
1725
+ {
1726
+ type: "text",
1727
+ value: Z,
1728
+ onChange: (I) => oe(I.target.value),
1729
+ onBlur: re,
1730
+ onKeyDown: (I) => {
1731
+ I.key === "Enter" && re(), I.key === "Escape" && d();
1732
+ },
1733
+ className: "font-mono text-xs px-1 py-0 border rounded bg-background w-24 focus:outline-none focus:ring-1 focus:ring-primary",
1734
+ autoFocus: !0,
1735
+ onClick: (I) => I.stopPropagation()
1736
+ }
1737
+ ) : /* @__PURE__ */ e.jsxs(
1738
+ "span",
1739
+ {
1740
+ className: Ve(
1741
+ "font-mono cursor-text",
1742
+ l.primaryKey && "font-bold text-primary"
1743
+ ),
1744
+ onClick: (I) => {
1745
+ I.stopPropagation(), ie(r.id, g, l.name);
1746
+ },
1747
+ title: "Click to edit field name",
1748
+ children: [
1749
+ l.primaryKey && /* @__PURE__ */ e.jsx("span", { className: "text-[0.65rem] font-semibold text-primary mr-0.5", children: "PK" }),
1750
+ l.name
1751
+ ]
1752
+ }
1753
+ ),
1754
+ /* @__PURE__ */ e.jsx("span", { className: "text-muted-foreground ml-auto", children: l.type }),
1755
+ l.required && /* @__PURE__ */ e.jsx("span", { className: "text-destructive", children: "*" })
1756
+ ]
1757
+ },
1758
+ `${l.name}-${g}`
1759
+ )) }),
1760
+ !v && /* @__PURE__ */ e.jsx("div", { className: "px-3 py-1 border-t", children: /* @__PURE__ */ e.jsxs(
1761
+ "button",
1762
+ {
1763
+ onClick: (l) => {
1764
+ l.stopPropagation(), le(r.id);
1765
+ },
1766
+ "aria-label": `Add field to ${r.label}`,
1767
+ className: "flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground w-full py-0.5",
1768
+ children: [
1769
+ /* @__PURE__ */ e.jsx(xe, { className: "h-3 w-3" }),
1770
+ " Add Field"
1771
+ ]
1772
+ }
1773
+ ) })
1774
+ ]
1775
+ },
1776
+ r.id
1777
+ ))
605
1778
  ]
606
1779
  }
607
1780
  ),
608
- /* @__PURE__ */ e.jsx("div", { className: "px-3 py-1 divide-y", children: o.fields.map((r) => /* @__PURE__ */ e.jsxs(
609
- "div",
1781
+ S && C.length > 0 && /* @__PURE__ */ e.jsx(
1782
+ Be,
610
1783
  {
611
- className: "flex items-center gap-2 py-1 text-xs",
612
- children: [
613
- /* @__PURE__ */ e.jsxs("span", { className: B("font-mono", r.primaryKey && "font-bold text-primary"), children: [
614
- r.primaryKey ? "🔑 " : "",
615
- r.name
616
- ] }),
617
- /* @__PURE__ */ e.jsx("span", { className: "text-muted-foreground ml-auto", children: r.type }),
618
- r.required && /* @__PURE__ */ e.jsx("span", { className: "text-destructive", children: "*" })
619
- ]
620
- },
621
- r.name
622
- )) })
1784
+ items: o,
1785
+ canvasWidth: E.width,
1786
+ canvasHeight: E.height,
1787
+ position: "bottom-right",
1788
+ size: 150
1789
+ }
1790
+ )
623
1791
  ]
624
- },
625
- o.id
626
- ))
627
- ]
628
- }
629
- ) })
630
- ] }) });
1792
+ }
1793
+ )
1794
+ ] }),
1795
+ /* @__PURE__ */ e.jsxs("div", { className: "w-64 border-l flex flex-col bg-background shrink-0", children: [
1796
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [
1797
+ /* @__PURE__ */ e.jsxs(
1798
+ "button",
1799
+ {
1800
+ onClick: () => $((r) => !r),
1801
+ className: "flex items-center gap-1 px-3 py-2 text-xs font-medium text-muted-foreground hover:bg-accent/50 border-b",
1802
+ "aria-expanded": D,
1803
+ "aria-controls": "property-editor-panel",
1804
+ children: [
1805
+ D ? /* @__PURE__ */ e.jsx(Xe, { className: "h-3 w-3" }) : /* @__PURE__ */ e.jsx(He, { className: "h-3 w-3" }),
1806
+ "Properties"
1807
+ ]
1808
+ }
1809
+ ),
1810
+ D && /* @__PURE__ */ e.jsx("div", { id: "property-editor-panel", className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ e.jsx(
1811
+ Ue,
1812
+ {
1813
+ title: h ? h.label : "Properties",
1814
+ fields: a,
1815
+ onChange: t
1816
+ }
1817
+ ) })
1818
+ ] }),
1819
+ /* @__PURE__ */ e.jsx("div", { className: "border-t", children: /* @__PURE__ */ e.jsxs(
1820
+ "button",
1821
+ {
1822
+ onClick: () => U((r) => !r),
1823
+ className: "flex items-center gap-1 px-3 py-2 text-xs font-medium text-muted-foreground hover:bg-accent/50 w-full",
1824
+ "aria-expanded": S,
1825
+ children: [
1826
+ S ? /* @__PURE__ */ e.jsx(Xe, { className: "h-3 w-3" }) : /* @__PURE__ */ e.jsx(He, { className: "h-3 w-3" }),
1827
+ "Minimap"
1828
+ ]
1829
+ }
1830
+ ) })
1831
+ ] }),
1832
+ /* @__PURE__ */ e.jsx(
1833
+ Fe,
1834
+ {
1835
+ isOpen: k.isOpen,
1836
+ title: k.title,
1837
+ message: k.message,
1838
+ onConfirm: k.onConfirm,
1839
+ onCancel: k.onCancel,
1840
+ destructive: !0
1841
+ }
1842
+ )
1843
+ ]
1844
+ }
1845
+ );
1846
+ }
1847
+ function _e(...s) {
1848
+ return pe(ue(s));
631
1849
  }
632
- function X(...l) {
633
- return Y(M(l));
1850
+ const ye = 120, ke = 50;
1851
+ function lr(s, N) {
1852
+ if (s.length === 0) return s;
1853
+ const E = 200, w = 100, v = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
1854
+ for (const c of s)
1855
+ v.set(c.id, 0), R.set(c.id, []);
1856
+ for (const c of N)
1857
+ v.set(c.target, (v.get(c.target) ?? 0) + 1), R.get(c.source)?.push(c.target);
1858
+ const y = [], f = /* @__PURE__ */ new Set();
1859
+ let j = s.filter((c) => (v.get(c.id) ?? 0) === 0).map((c) => c.id);
1860
+ for (j.length === 0 && (j = [s[0].id]); j.length > 0; ) {
1861
+ y.push(j);
1862
+ for (const i of j) f.add(i);
1863
+ const c = /* @__PURE__ */ new Set();
1864
+ for (const i of j)
1865
+ for (const k of R.get(i) ?? [])
1866
+ f.has(k) || c.add(k);
1867
+ j = Array.from(c);
1868
+ }
1869
+ const n = s.filter((c) => !f.has(c.id)).map((c) => c.id);
1870
+ n.length > 0 && y.push(n);
1871
+ const C = /* @__PURE__ */ new Map();
1872
+ for (let c = 0; c < y.length; c++) {
1873
+ const i = y[c];
1874
+ for (let k = 0; k < i.length; k++)
1875
+ C.set(i[k], {
1876
+ x: 80 + c * E,
1877
+ y: 80 + k * w
1878
+ });
1879
+ }
1880
+ return s.map((c) => ({
1881
+ ...c,
1882
+ position: C.get(c.id) ?? c.position
1883
+ }));
634
1884
  }
635
- function Ie({
636
- processName: l = "New Process",
637
- nodes: u = [],
638
- edges: p = [],
1885
+ function ir({
1886
+ processName: s = "New Process",
1887
+ nodes: N = [],
1888
+ edges: E = [],
639
1889
  lanes: w,
640
- canvas: i = { width: 1400, height: 800, showGrid: !0 },
641
- showToolbar: d = !0,
642
- readOnly: x = !1,
643
- onNodesChange: E,
1890
+ canvas: v = { width: 1400, height: 800, showGrid: !0 },
1891
+ showMinimap: R = !0,
1892
+ showToolbar: y = !0,
1893
+ readOnly: f = !1,
1894
+ onNodesChange: j,
644
1895
  onEdgesChange: n,
645
- className: _
1896
+ className: C
646
1897
  }) {
647
- const [b, k] = A(u), [g, R] = A(p), [v, S] = A(null), o = P(
648
- (s, T) => {
649
- if (x) return;
650
- const m = {
1898
+ const c = Re(
1899
+ { nodes: N, edges: E },
1900
+ { maxHistory: 50 }
1901
+ ), i = c.current.nodes, k = c.current.edges, u = b(
1902
+ (m, Y) => {
1903
+ c.push({ nodes: m, edges: Y }), j?.(m), n?.(Y);
1904
+ },
1905
+ [c, j, n]
1906
+ ), x = Ae(), T = Le(), A = Ie(), F = We({ initialZoom: 1 }), D = $e(), [$, S] = K(null), [U, H] = K(!1), [G, Z] = K(null), [oe, J] = K(null), [X, te] = K(!0), [se, ne] = K(null), [ae, O] = K({ x: 0, y: 0 }), le = ee(null), ie = ee(j), re = ee(n);
1907
+ ie.current = j, re.current = n, fe(() => {
1908
+ ie.current?.(i), re.current?.(k);
1909
+ }, [c.current]);
1910
+ const d = b(
1911
+ (m, Y) => {
1912
+ if (f) return;
1913
+ const L = {
651
1914
  id: `node-${Date.now()}`,
652
- type: s,
653
- label: T,
654
- position: { x: 200 + b.length * 160, y: 200 }
655
- }, h = [...b, m];
656
- k(h), S(m.id), E?.(h);
1915
+ type: m,
1916
+ label: Y,
1917
+ position: { x: 200 + i.length * 160, y: 200 }
1918
+ }, q = [...i, L];
1919
+ u(q, k), S(L.id), T.selectOne(L.id), D?.sendOperation({ type: "insert", elementId: L.id, data: { label: Y }, userId: D.currentUserId ?? "" });
657
1920
  },
658
- [b, x, E]
659
- ), r = P(
660
- (s) => {
661
- if (x) return;
662
- const T = b.filter((h) => h.id !== s), m = g.filter((h) => h.source !== s && h.target !== s);
663
- k(T), R(m), v === s && S(null), E?.(T), n?.(m);
1921
+ [i, k, f, u, T, D]
1922
+ ), z = b(
1923
+ async (m) => {
1924
+ if (f) return;
1925
+ const Y = i.find((W) => W.id === m);
1926
+ if (!await x.confirm(
1927
+ "Delete Node",
1928
+ `Are you sure you want to delete "${Y?.label ?? m}"? This will also remove all connected edges.`
1929
+ )) return;
1930
+ const q = i.filter((W) => W.id !== m), B = k.filter((W) => W.source !== m && W.target !== m);
1931
+ u(q, B), $ === m && S(null), T.clearSelection(), D?.sendOperation({ type: "delete", elementId: m, data: {}, userId: D.currentUserId ?? "" });
664
1932
  },
665
- [b, g, v, x, E, n]
666
- ), c = (s) => {
667
- switch (s) {
1933
+ [i, k, $, f, u, x, T, D]
1934
+ ), p = b(async () => {
1935
+ if (f || T.count === 0 || !await x.confirm(
1936
+ "Delete Selected Nodes",
1937
+ `Are you sure you want to delete ${T.count} selected node(s) and their connected edges?`
1938
+ )) return;
1939
+ const Y = T.selectedIds, L = i.filter((B) => !Y.has(B.id)), q = k.filter((B) => !Y.has(B.source) && !Y.has(B.target));
1940
+ u(L, q), S(null), T.clearSelection();
1941
+ }, [i, k, f, u, x, T]), P = b(() => {
1942
+ const m = T.count > 0 ? T.selectedIds : $ ? /* @__PURE__ */ new Set([$]) : /* @__PURE__ */ new Set();
1943
+ if (m.size === 0) return;
1944
+ const Y = i.filter((L) => m.has(L.id));
1945
+ A.copy(Y);
1946
+ }, [i, $, T, A]), h = b(() => {
1947
+ if (f) return;
1948
+ const m = A.paste();
1949
+ if (!m || m.length === 0) return;
1950
+ const Y = 40, L = m.map((B) => ({
1951
+ ...B,
1952
+ id: `node-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
1953
+ position: { x: B.position.x + Y, y: B.position.y + Y }
1954
+ })), q = [...i, ...L];
1955
+ u(q, k), T.selectMany(L.map((B) => B.id)), S(L[0].id);
1956
+ }, [f, i, k, A, u, T]), a = b(() => {
1957
+ H((m) => m ? (Z(null), !1) : !0);
1958
+ }, []), t = b(
1959
+ (m) => {
1960
+ if (!U) return !1;
1961
+ if (!G)
1962
+ return Z(m), !0;
1963
+ if (G === m) return !0;
1964
+ const Y = {
1965
+ id: `edge-${Date.now()}`,
1966
+ source: G,
1967
+ target: m
1968
+ }, L = [...k, Y];
1969
+ return u(i, L), Z(null), H(!1), D?.sendOperation({ type: "insert", elementId: Y.id, data: { source: G, target: m }, userId: D.currentUserId ?? "" }), !0;
1970
+ },
1971
+ [U, G, i, k, u, D]
1972
+ ), o = b(() => {
1973
+ if (f || i.length === 0) return;
1974
+ const m = lr(i, k);
1975
+ u(m, k);
1976
+ }, [i, k, f, u]), r = b(
1977
+ (m, Y) => {
1978
+ if (f || !i.find((B) => B.id === Y)) return;
1979
+ ne(Y);
1980
+ const q = m.target.getBoundingClientRect();
1981
+ O({
1982
+ x: m.clientX - q.left,
1983
+ y: m.clientY - q.top
1984
+ }), m.dataTransfer.effectAllowed = "move", m.dataTransfer.setData("text/plain", Y);
1985
+ },
1986
+ [f, i]
1987
+ ), l = b(
1988
+ (m) => {
1989
+ if (m.preventDefault(), f || !se) return;
1990
+ const Y = m.currentTarget.getBoundingClientRect(), L = F.zoom, q = (m.clientX - Y.left - F.panOffset.x) / L - ae.x, B = (m.clientY - Y.top - F.panOffset.y) / L - ae.y, W = Math.max(0, Math.round(q / 20) * 20), ge = Math.max(0, Math.round(B / 20) * 20), ve = i.map(
1991
+ (be) => be.id === se ? { ...be, position: { x: W, y: ge } } : be
1992
+ );
1993
+ u(ve, k), ne(null);
1994
+ },
1995
+ [f, se, ae, i, k, F.zoom, F.panOffset, u]
1996
+ ), g = b((m) => {
1997
+ m.preventDefault(), m.dataTransfer.dropEffect = "move";
1998
+ }, []), I = ce(() => i.find((m) => m.id === $) ?? null, [i, $]), V = ce(() => I ? [
1999
+ { name: "label", label: "Name", type: "text", value: I.label, group: "General" },
2000
+ {
2001
+ name: "type",
2002
+ label: "Type",
2003
+ type: "select",
2004
+ value: I.type,
2005
+ options: [
2006
+ { label: "Start Event", value: "start-event" },
2007
+ { label: "End Event", value: "end-event" },
2008
+ { label: "User Task", value: "user-task" },
2009
+ { label: "Service Task", value: "service-task" },
2010
+ { label: "Script Task", value: "script-task" },
2011
+ { label: "Exclusive Gateway", value: "exclusive-gateway" },
2012
+ { label: "Parallel Gateway", value: "parallel-gateway" },
2013
+ { label: "Inclusive Gateway", value: "inclusive-gateway" }
2014
+ ],
2015
+ group: "General"
2016
+ },
2017
+ { name: "description", label: "Description", type: "textarea", value: I.description ?? "", group: "General" }
2018
+ ] : [], [I]), Q = b(
2019
+ (m, Y) => {
2020
+ if (f || !$) return;
2021
+ const L = i.map(
2022
+ (q) => q.id === $ ? { ...q, [m]: Y } : q
2023
+ );
2024
+ u(L, k);
2025
+ },
2026
+ [f, $, i, k, u]
2027
+ ), we = (m) => {
2028
+ switch (m) {
668
2029
  case "start-event":
669
2030
  return "rounded-full bg-green-100 border-green-500 text-green-700";
670
2031
  case "end-event":
@@ -682,423 +2043,1882 @@ function Ie({
682
2043
  default:
683
2044
  return "rounded bg-gray-100 border-gray-500 text-gray-700";
684
2045
  }
685
- };
686
- return /* @__PURE__ */ e.jsxs("div", { className: X("flex flex-col h-full w-full border rounded-lg overflow-hidden bg-background", _), children: [
687
- d && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 p-2 border-b bg-muted/20", children: [
688
- /* @__PURE__ */ e.jsx(Ne, { className: "h-4 w-4" }),
689
- /* @__PURE__ */ e.jsx("span", { className: "font-medium text-sm", children: l }),
690
- /* @__PURE__ */ e.jsx("div", { className: "flex-1" }),
691
- !x && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1", children: [
692
- /* @__PURE__ */ e.jsxs(
693
- "button",
694
- {
695
- onClick: () => o("start-event", "Start"),
696
- className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
697
- title: "Add Start Event",
698
- children: [
699
- /* @__PURE__ */ e.jsx(Ee, { className: "h-3 w-3 text-green-600" }),
700
- " Start"
701
- ]
702
- }
703
- ),
704
- /* @__PURE__ */ e.jsxs(
705
- "button",
706
- {
707
- onClick: () => o("user-task", "User Task"),
708
- className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
709
- title: "Add User Task",
710
- children: [
711
- /* @__PURE__ */ e.jsx(oe, { className: "h-3 w-3 text-blue-600" }),
712
- " Task"
713
- ]
714
- }
715
- ),
716
- /* @__PURE__ */ e.jsxs(
717
- "button",
2046
+ }, je = ce(
2047
+ () => i.map((m) => ({
2048
+ id: m.id,
2049
+ x: m.position.x,
2050
+ y: m.position.y,
2051
+ width: ye,
2052
+ height: ke,
2053
+ selected: T.isSelected(m.id) || m.id === $
2054
+ })),
2055
+ [i, T, $]
2056
+ );
2057
+ fe(() => {
2058
+ const m = le.current;
2059
+ if (!m) return;
2060
+ const Y = (L) => {
2061
+ const q = L.target?.tagName;
2062
+ if (q === "INPUT" || q === "TEXTAREA" || q === "SELECT") return;
2063
+ const B = L.ctrlKey || L.metaKey;
2064
+ if (B && L.key === "z" && !L.shiftKey) {
2065
+ L.preventDefault(), c.undo();
2066
+ return;
2067
+ }
2068
+ if (B && L.key === "y" || B && L.key === "z" && L.shiftKey) {
2069
+ L.preventDefault(), c.redo();
2070
+ return;
2071
+ }
2072
+ if (B && L.key === "c") {
2073
+ L.preventDefault(), P();
2074
+ return;
2075
+ }
2076
+ if (B && L.key === "v") {
2077
+ L.preventDefault(), h();
2078
+ return;
2079
+ }
2080
+ if (L.key === "Delete" || L.key === "Backspace") {
2081
+ T.count > 0 ? (L.preventDefault(), p()) : $ && (L.preventDefault(), z($));
2082
+ return;
2083
+ }
2084
+ if (L.key === "Escape") {
2085
+ U ? (H(!1), Z(null)) : (S(null), T.clearSelection());
2086
+ return;
2087
+ }
2088
+ };
2089
+ return m.addEventListener("keydown", Y), () => m.removeEventListener("keydown", Y);
2090
+ }, [
2091
+ $,
2092
+ U,
2093
+ T,
2094
+ c,
2095
+ P,
2096
+ h,
2097
+ z,
2098
+ p
2099
+ ]);
2100
+ const ct = b(
2101
+ (m) => {
2102
+ m.target === m.currentTarget && (S(null), T.clearSelection(), U && (H(!1), Z(null)));
2103
+ },
2104
+ [U, T]
2105
+ );
2106
+ return /* @__PURE__ */ e.jsxs(
2107
+ "div",
2108
+ {
2109
+ ref: le,
2110
+ tabIndex: 0,
2111
+ className: _e("flex flex-col h-full w-full border rounded-lg overflow-hidden bg-background", C),
2112
+ children: [
2113
+ /* @__PURE__ */ e.jsx(
2114
+ Fe,
718
2115
  {
719
- onClick: () => o("exclusive-gateway", "Decision"),
720
- className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
721
- title: "Add Gateway",
722
- children: [
723
- /* @__PURE__ */ e.jsx(ke, { className: "h-3 w-3 text-yellow-600" }),
724
- " Gateway"
725
- ]
2116
+ isOpen: x.isOpen,
2117
+ title: x.title,
2118
+ message: x.message,
2119
+ onConfirm: x.onConfirm,
2120
+ onCancel: x.onCancel,
2121
+ destructive: !0
726
2122
  }
727
2123
  ),
728
- /* @__PURE__ */ e.jsxs(
729
- "button",
730
- {
731
- onClick: () => o("end-event", "End"),
732
- className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
733
- title: "Add End Event",
734
- children: [
735
- /* @__PURE__ */ e.jsx(oe, { className: "h-3 w-3 text-red-600" }),
736
- " End"
737
- ]
738
- }
739
- )
740
- ] })
741
- ] }),
742
- /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-auto bg-muted/10 p-4", children: /* @__PURE__ */ e.jsxs(
743
- "div",
744
- {
745
- className: "relative",
746
- style: {
747
- width: i.width,
748
- minHeight: i.height,
749
- backgroundImage: i.showGrid ? "radial-gradient(circle, hsl(var(--border)) 1px, transparent 1px)" : void 0,
750
- backgroundSize: i.showGrid ? "20px 20px" : void 0
751
- },
752
- children: [
753
- /* @__PURE__ */ e.jsxs(
754
- "svg",
2124
+ y && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 p-2 border-b bg-muted/20", role: "toolbar", "aria-label": "Process toolbar", children: [
2125
+ /* @__PURE__ */ e.jsx(Nt, { className: "h-4 w-4" }),
2126
+ /* @__PURE__ */ e.jsx("span", { className: "font-medium text-sm", "aria-label": "Process name", children: s }),
2127
+ D?.isConnected && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", role: "status", "aria-label": "Collaboration active", children: [
2128
+ /* @__PURE__ */ e.jsx("span", { className: "inline-block h-2 w-2 rounded-full bg-green-500" }),
2129
+ D.users.length,
2130
+ " user",
2131
+ D.users.length !== 1 ? "s" : ""
2132
+ ] }),
2133
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1" }),
2134
+ !f && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1", children: [
2135
+ /* @__PURE__ */ e.jsx(
2136
+ "button",
2137
+ {
2138
+ onClick: () => c.undo(),
2139
+ disabled: !c.canUndo,
2140
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent disabled:opacity-40",
2141
+ title: "Undo (Ctrl+Z)",
2142
+ "aria-label": "Undo",
2143
+ children: /* @__PURE__ */ e.jsx(Ee, { className: "h-3 w-3" })
2144
+ }
2145
+ ),
2146
+ /* @__PURE__ */ e.jsx(
2147
+ "button",
2148
+ {
2149
+ onClick: () => c.redo(),
2150
+ disabled: !c.canRedo,
2151
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent disabled:opacity-40",
2152
+ title: "Redo (Ctrl+Y)",
2153
+ "aria-label": "Redo",
2154
+ children: /* @__PURE__ */ e.jsx(De, { className: "h-3 w-3" })
2155
+ }
2156
+ ),
2157
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-4 bg-border mx-1" }),
2158
+ /* @__PURE__ */ e.jsx(
2159
+ "button",
2160
+ {
2161
+ onClick: P,
2162
+ disabled: T.count === 0 && !$,
2163
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent disabled:opacity-40",
2164
+ title: "Copy (Ctrl+C)",
2165
+ "aria-label": "Copy",
2166
+ children: /* @__PURE__ */ e.jsx(Pe, { className: "h-3 w-3" })
2167
+ }
2168
+ ),
2169
+ /* @__PURE__ */ e.jsx(
2170
+ "button",
2171
+ {
2172
+ onClick: h,
2173
+ disabled: !A.hasContent,
2174
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent disabled:opacity-40",
2175
+ title: "Paste (Ctrl+V)",
2176
+ "aria-label": "Paste",
2177
+ children: /* @__PURE__ */ e.jsx(Te, { className: "h-3 w-3" })
2178
+ }
2179
+ ),
2180
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-4 bg-border mx-1" }),
2181
+ /* @__PURE__ */ e.jsxs(
2182
+ "button",
2183
+ {
2184
+ onClick: a,
2185
+ className: _e(
2186
+ "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2187
+ U && "bg-primary text-primary-foreground"
2188
+ ),
2189
+ title: "Connect nodes",
2190
+ "aria-label": "Connect nodes",
2191
+ "aria-pressed": U,
2192
+ children: [
2193
+ /* @__PURE__ */ e.jsx(Ct, { className: "h-3 w-3" }),
2194
+ " Connect"
2195
+ ]
2196
+ }
2197
+ ),
2198
+ /* @__PURE__ */ e.jsxs(
2199
+ "button",
2200
+ {
2201
+ onClick: o,
2202
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2203
+ title: "Auto layout",
2204
+ "aria-label": "Auto layout",
2205
+ children: [
2206
+ /* @__PURE__ */ e.jsx(kt, { className: "h-3 w-3" }),
2207
+ " Layout"
2208
+ ]
2209
+ }
2210
+ ),
2211
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-4 bg-border mx-1" }),
2212
+ /* @__PURE__ */ e.jsx(
2213
+ "button",
2214
+ {
2215
+ onClick: F.zoomIn,
2216
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2217
+ title: "Zoom in",
2218
+ "aria-label": "Zoom in",
2219
+ children: /* @__PURE__ */ e.jsx(lt, { className: "h-3 w-3" })
2220
+ }
2221
+ ),
2222
+ /* @__PURE__ */ e.jsxs("span", { className: "text-xs tabular-nums min-w-[3ch] text-center", "aria-label": "Zoom level", children: [
2223
+ Math.round(F.zoom * 100),
2224
+ "%"
2225
+ ] }),
2226
+ /* @__PURE__ */ e.jsx(
2227
+ "button",
2228
+ {
2229
+ onClick: F.zoomOut,
2230
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2231
+ title: "Zoom out",
2232
+ "aria-label": "Zoom out",
2233
+ children: /* @__PURE__ */ e.jsx(ot, { className: "h-3 w-3" })
2234
+ }
2235
+ ),
2236
+ /* @__PURE__ */ e.jsx(
2237
+ "button",
2238
+ {
2239
+ onClick: F.resetZoom,
2240
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2241
+ title: "Reset zoom",
2242
+ "aria-label": "Reset zoom",
2243
+ children: /* @__PURE__ */ e.jsx(it, { className: "h-3 w-3" })
2244
+ }
2245
+ ),
2246
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-4 bg-border mx-1" }),
2247
+ /* @__PURE__ */ e.jsxs(
2248
+ "button",
2249
+ {
2250
+ onClick: () => d("start-event", "Start"),
2251
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2252
+ title: "Add Start Event",
2253
+ "aria-label": "Add Start Event",
2254
+ children: [
2255
+ /* @__PURE__ */ e.jsx(St, { className: "h-3 w-3 text-green-600" }),
2256
+ " Start"
2257
+ ]
2258
+ }
2259
+ ),
2260
+ /* @__PURE__ */ e.jsxs(
2261
+ "button",
2262
+ {
2263
+ onClick: () => d("user-task", "User Task"),
2264
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2265
+ title: "Add User Task",
2266
+ "aria-label": "Add User Task",
2267
+ children: [
2268
+ /* @__PURE__ */ e.jsx(Je, { className: "h-3 w-3 text-blue-600" }),
2269
+ " Task"
2270
+ ]
2271
+ }
2272
+ ),
2273
+ /* @__PURE__ */ e.jsxs(
2274
+ "button",
2275
+ {
2276
+ onClick: () => d("exclusive-gateway", "Decision"),
2277
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2278
+ title: "Add Gateway",
2279
+ "aria-label": "Add Gateway",
2280
+ children: [
2281
+ /* @__PURE__ */ e.jsx(Et, { className: "h-3 w-3 text-yellow-600" }),
2282
+ " Gateway"
2283
+ ]
2284
+ }
2285
+ ),
2286
+ /* @__PURE__ */ e.jsxs(
2287
+ "button",
2288
+ {
2289
+ onClick: () => d("end-event", "End"),
2290
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2291
+ title: "Add End Event",
2292
+ "aria-label": "Add End Event",
2293
+ children: [
2294
+ /* @__PURE__ */ e.jsx(Je, { className: "h-3 w-3 text-red-600" }),
2295
+ " End"
2296
+ ]
2297
+ }
2298
+ ),
2299
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-4 bg-border mx-1" }),
2300
+ /* @__PURE__ */ e.jsx(
2301
+ "button",
2302
+ {
2303
+ onClick: () => te((m) => !m),
2304
+ className: "flex items-center gap-1 px-2 py-1 text-xs rounded hover:bg-accent",
2305
+ title: X ? "Hide properties" : "Show properties",
2306
+ "aria-label": X ? "Hide property panel" : "Show property panel",
2307
+ "aria-expanded": X,
2308
+ children: X ? /* @__PURE__ */ e.jsx(Ke, { className: "h-3 w-3" }) : /* @__PURE__ */ e.jsx(Dt, { className: "h-3 w-3" })
2309
+ }
2310
+ )
2311
+ ] })
2312
+ ] }),
2313
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-1 overflow-hidden", children: [
2314
+ /* @__PURE__ */ e.jsx(
2315
+ "div",
755
2316
  {
756
- className: "absolute inset-0 pointer-events-none",
757
- width: i.width,
758
- height: i.height,
759
- children: [
760
- /* @__PURE__ */ e.jsx("defs", { children: /* @__PURE__ */ e.jsx(
761
- "marker",
762
- {
763
- id: "arrowhead",
764
- markerWidth: "10",
765
- markerHeight: "7",
766
- refX: "10",
767
- refY: "3.5",
768
- orient: "auto",
769
- children: /* @__PURE__ */ e.jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "hsl(var(--foreground))" })
770
- }
771
- ) }),
772
- g.map((s) => {
773
- const T = b.find((h) => h.id === s.source), m = b.find((h) => h.id === s.target);
774
- return !T || !m ? null : /* @__PURE__ */ e.jsx(
775
- "line",
776
- {
777
- x1: T.position.x + 60,
778
- y1: T.position.y + 25,
779
- x2: m.position.x,
780
- y2: m.position.y + 25,
781
- stroke: "hsl(var(--foreground) / 0.5)",
782
- strokeWidth: "2",
783
- markerEnd: "url(#arrowhead)"
784
- },
785
- s.id
786
- );
787
- })
788
- ]
2317
+ className: "flex-1 overflow-auto bg-muted/10 p-4",
2318
+ role: "region",
2319
+ "aria-label": "Process canvas",
2320
+ onWheel: F.handleWheel,
2321
+ onMouseDown: F.startPan,
2322
+ children: /* @__PURE__ */ e.jsxs(
2323
+ "div",
2324
+ {
2325
+ className: "relative",
2326
+ style: {
2327
+ ...F.transformStyle,
2328
+ width: v.width,
2329
+ minHeight: v.height,
2330
+ backgroundImage: v.showGrid ? "radial-gradient(circle, hsl(var(--border)) 1px, transparent 1px)" : void 0,
2331
+ backgroundSize: v.showGrid ? "20px 20px" : void 0
2332
+ },
2333
+ onClick: ct,
2334
+ onDrop: l,
2335
+ onDragOver: g,
2336
+ children: [
2337
+ /* @__PURE__ */ e.jsxs(
2338
+ "svg",
2339
+ {
2340
+ className: "absolute inset-0 pointer-events-none",
2341
+ width: v.width,
2342
+ height: v.height,
2343
+ children: [
2344
+ /* @__PURE__ */ e.jsx("defs", { children: /* @__PURE__ */ e.jsx(
2345
+ "marker",
2346
+ {
2347
+ id: "arrowhead",
2348
+ markerWidth: "10",
2349
+ markerHeight: "7",
2350
+ refX: "10",
2351
+ refY: "3.5",
2352
+ orient: "auto",
2353
+ children: /* @__PURE__ */ e.jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "hsl(var(--foreground))" })
2354
+ }
2355
+ ) }),
2356
+ k.map((m) => {
2357
+ const Y = i.find((Ye) => Ye.id === m.source), L = i.find((Ye) => Ye.id === m.target);
2358
+ if (!Y || !L) return null;
2359
+ Y.position.x + ye / 2;
2360
+ const q = Y.position.y + ke / 2;
2361
+ L.position.x + ye / 2;
2362
+ const B = L.position.y + ke / 2, W = Y.position.x + ye, ge = q, ve = L.position.x, be = B, ut = (W + ve) / 2, pt = `M ${W} ${ge} Q ${ut} ${ge}, ${(W + ve) / 2} ${(ge + be) / 2} T ${ve} ${be}`;
2363
+ return /* @__PURE__ */ e.jsxs("g", { children: [
2364
+ /* @__PURE__ */ e.jsx(
2365
+ "path",
2366
+ {
2367
+ d: pt,
2368
+ fill: "none",
2369
+ stroke: "hsl(var(--foreground) / 0.5)",
2370
+ strokeWidth: "2",
2371
+ markerEnd: "url(#arrowhead)"
2372
+ }
2373
+ ),
2374
+ m.label && /* @__PURE__ */ e.jsx(
2375
+ "text",
2376
+ {
2377
+ x: (W + ve) / 2,
2378
+ y: (ge + be) / 2 - 8,
2379
+ textAnchor: "middle",
2380
+ className: "text-[10px] fill-muted-foreground",
2381
+ children: m.label
2382
+ }
2383
+ )
2384
+ ] }, m.id);
2385
+ })
2386
+ ]
2387
+ }
2388
+ ),
2389
+ i.length === 0 && /* @__PURE__ */ e.jsx("div", { className: "flex items-center justify-center h-full min-h-[200px] text-muted-foreground text-sm", children: "No nodes in the process. Use the toolbar buttons to add start events, tasks, gateways, and end events." }),
2390
+ i.map((m) => {
2391
+ const Y = T.isSelected(m.id) || $ === m.id, L = G === m.id, q = oe === m.id, B = U || q;
2392
+ return /* @__PURE__ */ e.jsxs(
2393
+ "div",
2394
+ {
2395
+ className: "absolute select-none",
2396
+ style: {
2397
+ left: m.position.x,
2398
+ top: m.position.y
2399
+ },
2400
+ role: "group",
2401
+ "aria-label": m.label,
2402
+ draggable: !f && !U,
2403
+ onDragStart: (W) => r(W, m.id),
2404
+ onMouseEnter: () => J(m.id),
2405
+ onMouseLeave: () => J(null),
2406
+ onClick: (W) => {
2407
+ t(m.id) || (W.shiftKey ? T.toggle(m.id, !0) : (S(m.id), T.selectOne(m.id)));
2408
+ },
2409
+ children: [
2410
+ /* @__PURE__ */ e.jsx(
2411
+ "div",
2412
+ {
2413
+ className: _e(
2414
+ "flex items-center justify-center border-2 min-w-[120px] min-h-[50px] px-3 py-2 transition-shadow",
2415
+ we(m.type),
2416
+ Y && "ring-2 ring-primary shadow-md",
2417
+ L && "ring-2 ring-blue-400 shadow-lg",
2418
+ U && !L && "cursor-crosshair"
2419
+ ),
2420
+ children: /* @__PURE__ */ e.jsx("span", { className: _e(
2421
+ "text-xs font-medium",
2422
+ (m.type === "exclusive-gateway" || m.type === "parallel-gateway" || m.type === "inclusive-gateway" || m.type === "event-based-gateway") && "-rotate-45"
2423
+ ), children: m.label })
2424
+ }
2425
+ ),
2426
+ B && !f && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
2427
+ /* @__PURE__ */ e.jsx(
2428
+ "div",
2429
+ {
2430
+ className: "absolute w-3 h-3 rounded-full bg-blue-500 border-2 border-white shadow cursor-crosshair",
2431
+ style: { left: -6, top: ke / 2 - 6 },
2432
+ title: "Input port",
2433
+ onClick: (W) => {
2434
+ W.stopPropagation(), t(m.id);
2435
+ }
2436
+ }
2437
+ ),
2438
+ /* @__PURE__ */ e.jsx(
2439
+ "div",
2440
+ {
2441
+ className: "absolute w-3 h-3 rounded-full bg-blue-500 border-2 border-white shadow cursor-crosshair",
2442
+ style: { right: -6, top: ke / 2 - 6 },
2443
+ title: "Output port",
2444
+ onClick: (W) => {
2445
+ W.stopPropagation(), U ? t(m.id) : (H(!0), Z(m.id));
2446
+ }
2447
+ }
2448
+ ),
2449
+ /* @__PURE__ */ e.jsx(
2450
+ "div",
2451
+ {
2452
+ className: "absolute w-3 h-3 rounded-full bg-blue-400 border-2 border-white shadow cursor-crosshair",
2453
+ style: { left: ye / 2 - 6, top: -6 },
2454
+ title: "Port",
2455
+ onClick: (W) => {
2456
+ W.stopPropagation(), t(m.id);
2457
+ }
2458
+ }
2459
+ ),
2460
+ /* @__PURE__ */ e.jsx(
2461
+ "div",
2462
+ {
2463
+ className: "absolute w-3 h-3 rounded-full bg-blue-400 border-2 border-white shadow cursor-crosshair",
2464
+ style: { left: ye / 2 - 6, bottom: -6 },
2465
+ title: "Port",
2466
+ onClick: (W) => {
2467
+ W.stopPropagation(), t(m.id);
2468
+ }
2469
+ }
2470
+ )
2471
+ ] }),
2472
+ !f && Y && !U && /* @__PURE__ */ e.jsx(
2473
+ "button",
2474
+ {
2475
+ onClick: (W) => {
2476
+ W.stopPropagation(), z(m.id);
2477
+ },
2478
+ className: "absolute -top-2 -right-2 p-0.5 rounded-full bg-destructive text-destructive-foreground shadow",
2479
+ "aria-label": "Delete node",
2480
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-3 w-3" })
2481
+ }
2482
+ )
2483
+ ]
2484
+ },
2485
+ m.id
2486
+ );
2487
+ }),
2488
+ R && i.length > 0 && /* @__PURE__ */ e.jsx(
2489
+ Be,
2490
+ {
2491
+ items: je,
2492
+ canvasWidth: v.width ?? 1400,
2493
+ canvasHeight: v.height ?? 800,
2494
+ position: "bottom-right"
2495
+ }
2496
+ )
2497
+ ]
2498
+ }
2499
+ )
789
2500
  }
790
2501
  ),
791
- b.map((s) => /* @__PURE__ */ e.jsxs(
792
- "div",
2502
+ X && !f && /* @__PURE__ */ e.jsx("div", { className: "w-64 border-l bg-background overflow-y-auto flex-shrink-0", role: "complementary", "aria-label": "Property panel", children: /* @__PURE__ */ e.jsx(
2503
+ Ue,
793
2504
  {
794
- className: "absolute select-none",
795
- style: {
796
- left: s.position.x,
797
- top: s.position.y
798
- },
799
- onClick: () => S(s.id),
800
- children: [
801
- /* @__PURE__ */ e.jsx(
802
- "div",
803
- {
804
- className: X(
805
- "flex items-center justify-center border-2 min-w-[120px] min-h-[50px] px-3 py-2",
806
- c(s.type),
807
- v === s.id && "ring-2 ring-primary shadow-md"
808
- ),
809
- children: /* @__PURE__ */ e.jsx("span", { className: X(
810
- "text-xs font-medium",
811
- (s.type === "exclusive-gateway" || s.type === "parallel-gateway") && "-rotate-45"
812
- ), children: s.label })
813
- }
814
- ),
815
- !x && v === s.id && /* @__PURE__ */ e.jsx(
816
- "button",
817
- {
818
- onClick: (T) => {
819
- T.stopPropagation(), r(s.id);
820
- },
821
- className: "absolute -top-2 -right-2 p-0.5 rounded-full bg-destructive text-destructive-foreground shadow",
822
- children: /* @__PURE__ */ e.jsx(L, { className: "h-3 w-3" })
823
- }
824
- )
825
- ]
826
- },
827
- s.id
828
- ))
829
- ]
830
- }
831
- ) })
832
- ] });
2505
+ title: I ? `Properties: ${I.label}` : "Properties",
2506
+ fields: V,
2507
+ onChange: Q
2508
+ }
2509
+ ) })
2510
+ ] })
2511
+ ]
2512
+ }
2513
+ );
833
2514
  }
834
- function ce(...l) {
835
- return Y(M(l));
2515
+ function me(...s) {
2516
+ return pe(ue(s));
836
2517
  }
837
- const Fe = {
2518
+ const M = {
2519
+ untitledReport: "Untitled Report",
2520
+ reportCanvas: "Report canvas",
2521
+ properties: "Properties",
2522
+ propertiesPanel: "Properties panel",
2523
+ designerToolbar: "Report designer toolbar",
2524
+ selectElementPrompt: "Select an element to edit its properties",
2525
+ addElementsPrompt: "Add elements using the buttons above",
2526
+ addText: "Add Text",
2527
+ addField: "Add Field",
2528
+ addImage: "Add Image",
2529
+ addChart: "Add Chart",
2530
+ addTable: "Add Table",
2531
+ undo: "Undo",
2532
+ undoShortcut: "Undo (Ctrl+Z)",
2533
+ redo: "Redo",
2534
+ redoShortcut: "Redo (Ctrl+Shift+Z)",
2535
+ copy: "Copy",
2536
+ copyShortcut: "Copy (Ctrl+C)",
2537
+ paste: "Paste",
2538
+ pasteShortcut: "Paste (Ctrl+V)",
2539
+ deleteSelected: "Delete selected",
2540
+ deleteElement: "Delete element",
2541
+ deleteElementsTitle: "Delete elements",
2542
+ deleteElementMessage: (s) => `Are you sure you want to delete ${s} element${s > 1 ? "s" : ""}?`,
2543
+ collapsePanel: "Collapse panel",
2544
+ expandPanel: "Expand panel",
2545
+ collaborationConnected: "Connected",
2546
+ sectionHeader: "Report Header",
2547
+ sectionPageHeader: "Page Header",
2548
+ sectionGroupHeader: "Group Header",
2549
+ sectionDetail: "Detail",
2550
+ sectionGroupFooter: "Group Footer",
2551
+ sectionPageFooter: "Page Footer",
2552
+ sectionFooter: "Report Footer",
2553
+ elementText: "Text",
2554
+ elementImage: "🖼 Image",
2555
+ elementChart: "📊 Chart",
2556
+ elementTable: "📋 Table",
2557
+ propLabel: "Label",
2558
+ propX: "X",
2559
+ propY: "Y",
2560
+ propWidth: "Width",
2561
+ propHeight: "Height",
2562
+ propText: "Text",
2563
+ propField: "Field",
2564
+ groupPosition: "Position",
2565
+ groupSize: "Size",
2566
+ groupContent: "Content",
2567
+ groupGeneral: "General"
2568
+ }, dr = {
838
2569
  A4: { width: 595, height: 842 },
839
2570
  A3: { width: 842, height: 1191 },
840
2571
  Letter: { width: 612, height: 792 },
841
2572
  Legal: { width: 612, height: 1008 },
842
2573
  Tabloid: { width: 792, height: 1224 }
843
- };
844
- function Ge({
845
- reportName: l = "Untitled Report",
846
- objectName: u,
847
- pageSize: p = "A4",
2574
+ }, cr = [
2575
+ { type: "header", height: 80, elements: [] },
2576
+ { type: "detail", height: 400, elements: [], repeat: !0 },
2577
+ { type: "footer", height: 60, elements: [] }
2578
+ ];
2579
+ function ur({
2580
+ reportName: s = M.untitledReport,
2581
+ objectName: N,
2582
+ pageSize: E = "A4",
848
2583
  orientation: w = "portrait",
849
- margins: i = { top: 40, right: 40, bottom: 40, left: 40 },
850
- sections: d = [],
851
- showToolbar: x = !0,
852
- showPropertyPanel: E = !0,
853
- readOnly: n = !1,
854
- onSectionsChange: _,
855
- className: b
2584
+ margins: v = { top: 40, right: 40, bottom: 40, left: 40 },
2585
+ sections: R = [],
2586
+ showToolbar: y = !0,
2587
+ showPropertyPanel: f = !0,
2588
+ readOnly: j = !1,
2589
+ onSectionsChange: n,
2590
+ className: C
856
2591
  }) {
857
- const [k, g] = A(
858
- d.length > 0 ? d : [
859
- { type: "header", height: 80, elements: [] },
860
- { type: "detail", height: 400, elements: [], repeat: !0 },
861
- { type: "footer", height: 60, elements: [] }
862
- ]
863
- ), [R, v] = A(null), S = Fe[p], o = w === "landscape" ? S.height : S.width, r = w === "landscape" ? S.width : S.height, c = P(
864
- (m, h) => {
865
- if (n) return;
866
- const f = {
867
- id: `elem-${Date.now()}`,
868
- type: h,
869
- position: { x: i.left, y: 10, width: 200, height: 30 },
870
- properties: {
871
- text: h === "text" ? "New Text" : void 0,
872
- field: h === "field" ? "field_name" : void 0
873
- }
874
- }, C = k.map(
875
- (D, V) => V === m ? { ...D, elements: [...D.elements, f] } : D
876
- );
877
- g(C), v(f.id), _?.(C);
2592
+ const c = Re(
2593
+ R.length > 0 ? R : cr
2594
+ ), i = c.current, k = b(
2595
+ (p) => {
2596
+ c.push(p), n?.(p);
878
2597
  },
879
- [k, i.left, n, _]
880
- ), s = P(
881
- (m) => {
882
- if (n) return;
883
- const h = k.map((f) => ({
884
- ...f,
885
- elements: f.elements.filter((C) => C.id !== m)
886
- }));
887
- g(h), R === m && v(null), _?.(h);
2598
+ [c, n]
2599
+ ), u = Le(), x = ce(() => {
2600
+ const p = Array.from(u.selectedIds);
2601
+ return p.length > 0 ? p[0] : null;
2602
+ }, [u.selectedIds]), T = Ie(), A = Ae(), F = $e(), D = b(
2603
+ (p) => {
2604
+ F && F.sendOperation({ ...p, userId: F.currentUserId ?? "" });
888
2605
  },
889
- [k, R, n, _]
890
- ), T = (m) => {
891
- switch (m) {
2606
+ [F]
2607
+ ), [$, S] = K(!0), U = ee(null), H = ee(null), G = dr[E], Z = w === "landscape" ? G.height : G.width, oe = w === "landscape" ? G.width : G.height, J = (p) => {
2608
+ switch (p) {
892
2609
  case "header":
893
- return "Report Header";
2610
+ return M.sectionHeader;
894
2611
  case "page-header":
895
- return "Page Header";
2612
+ return M.sectionPageHeader;
896
2613
  case "group-header":
897
- return "Group Header";
2614
+ return M.sectionGroupHeader;
898
2615
  case "detail":
899
- return "Detail";
2616
+ return M.sectionDetail;
900
2617
  case "group-footer":
901
- return "Group Footer";
2618
+ return M.sectionGroupFooter;
902
2619
  case "page-footer":
903
- return "Page Footer";
2620
+ return M.sectionPageFooter;
904
2621
  case "footer":
905
- return "Report Footer";
2622
+ return M.sectionFooter;
906
2623
  default:
907
- return m;
2624
+ return p;
908
2625
  }
909
- };
910
- return /* @__PURE__ */ e.jsxs("div", { className: ce("flex h-full w-full border rounded-lg overflow-hidden bg-background", b), children: [
911
- /* @__PURE__ */ e.jsxs("div", { className: "flex-1 flex flex-col", children: [
912
- x && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 p-2 border-b bg-muted/20", children: [
913
- /* @__PURE__ */ e.jsx(Re, { className: "h-4 w-4" }),
914
- /* @__PURE__ */ e.jsx("span", { className: "font-medium text-sm", children: l }),
915
- u && /* @__PURE__ */ e.jsxs("span", { className: "text-xs text-muted-foreground", children: [
2626
+ }, X = ce(
2627
+ () => x ? i.flatMap((p) => p.elements).find((p) => p.id === x) : null,
2628
+ [x, i]
2629
+ ), te = b(
2630
+ (p, P) => {
2631
+ if (j) return;
2632
+ const h = {
2633
+ id: `elem-${Date.now()}`,
2634
+ type: P,
2635
+ position: { x: v.left, y: 10, width: 200, height: 30 },
2636
+ properties: {
2637
+ text: P === "text" ? "New Text" : void 0,
2638
+ field: P === "field" ? "field_name" : void 0
2639
+ }
2640
+ }, a = i.map(
2641
+ (t, o) => o === p ? { ...t, elements: [...t.elements, h] } : t
2642
+ );
2643
+ k(a), u.selectOne(h.id), D({ type: "insert", elementId: h.id, data: { element: h } });
2644
+ },
2645
+ [i, v.left, j, k, u, D]
2646
+ ), se = b(
2647
+ (p) => {
2648
+ if (j) return;
2649
+ const P = i.map((h) => ({
2650
+ ...h,
2651
+ elements: h.elements.filter((a) => a.id !== p)
2652
+ }));
2653
+ k(P), u.isSelected(p) && u.clearSelection(), D({ type: "delete", elementId: p, data: {} });
2654
+ },
2655
+ [i, j, k, u, D]
2656
+ ), ne = b(async () => {
2657
+ if (j || u.count === 0 || !await A.confirm(
2658
+ M.deleteElementsTitle,
2659
+ M.deleteElementMessage(u.count)
2660
+ )) return;
2661
+ const P = u.selectedIds, h = i.map((a) => ({
2662
+ ...a,
2663
+ elements: a.elements.filter((t) => !P.has(t.id))
2664
+ }));
2665
+ k(h), u.clearSelection(), P.forEach((a) => {
2666
+ D({ type: "delete", elementId: a, data: {} });
2667
+ });
2668
+ }, [j, u, A, i, k, D]), ae = b(
2669
+ (p, P) => {
2670
+ if (j || !x) return;
2671
+ const h = i.map((a) => ({
2672
+ ...a,
2673
+ elements: a.elements.map((t) => t.id !== x ? t : p === "x" ? { ...t, position: { ...t.position, x: Number(P) } } : p === "y" ? { ...t, position: { ...t.position, y: Number(P) } } : p === "width" ? { ...t, position: { ...t.position, width: Number(P) } } : p === "height" ? { ...t, position: { ...t.position, height: Number(P) } } : { ...t, properties: { ...t.properties, [p]: P } })
2674
+ }));
2675
+ k(h), D({ type: "update", elementId: x, data: { [p]: P } });
2676
+ },
2677
+ [j, x, i, k, D]
2678
+ ), O = b(() => {
2679
+ const p = u.selectedIds;
2680
+ if (p.size === 0) return;
2681
+ const h = i.flatMap((a) => a.elements).filter((a) => p.has(a.id));
2682
+ T.copy(h);
2683
+ }, [u, i, T]), le = b(() => {
2684
+ if (j) return;
2685
+ const p = T.paste();
2686
+ if (!p || p.length === 0) return;
2687
+ let P = 0;
2688
+ const h = p.map((r) => ({
2689
+ ...r,
2690
+ id: `elem-${Date.now()}-${++P}-${Math.random().toString(36).slice(2, 7)}`,
2691
+ position: { ...r.position, x: r.position.x + 20, y: r.position.y + 20 }
2692
+ })), a = i.findIndex((r) => r.type === "detail"), t = a >= 0 ? a : 0, o = i.map(
2693
+ (r, l) => l === t ? { ...r, elements: [...r.elements, ...h] } : r
2694
+ );
2695
+ k(o), u.selectMany(h.map((r) => r.id)), h.forEach((r) => {
2696
+ D({ type: "insert", elementId: r.id, data: { element: r } });
2697
+ });
2698
+ }, [j, T, i, k, u, D]), ie = b(
2699
+ (p, P, h) => {
2700
+ j || (U.current = { id: P.id, sectionIndex: h, startX: p.clientX, startY: p.clientY }, p.dataTransfer.effectAllowed = "move", p.dataTransfer.setData("text/plain", P.id));
2701
+ },
2702
+ [j]
2703
+ ), re = b((p) => {
2704
+ p.preventDefault(), p.dataTransfer.dropEffect = "move";
2705
+ }, []), d = b(
2706
+ (p, P) => {
2707
+ p.preventDefault();
2708
+ const h = U.current;
2709
+ if (!h || j) return;
2710
+ const a = p.clientX - h.startX, t = p.clientY - h.startY;
2711
+ if (h.sectionIndex === P) {
2712
+ const o = i.map((r, l) => l !== P ? r : {
2713
+ ...r,
2714
+ elements: r.elements.map((g) => g.id !== h.id ? g : {
2715
+ ...g,
2716
+ position: {
2717
+ ...g.position,
2718
+ x: Math.max(0, g.position.x + a),
2719
+ y: Math.max(0, (typeof g.position.y == "number" ? g.position.y : 0) + t)
2720
+ }
2721
+ })
2722
+ });
2723
+ k(o);
2724
+ } else {
2725
+ let o = null;
2726
+ const r = i.map((l, g) => {
2727
+ if (g !== h.sectionIndex) return l;
2728
+ const I = l.elements.find((V) => V.id === h.id);
2729
+ return I && (o = {
2730
+ ...I,
2731
+ position: {
2732
+ ...I.position,
2733
+ x: Math.max(0, I.position.x + a),
2734
+ y: Math.max(0, 10)
2735
+ }
2736
+ }), {
2737
+ ...l,
2738
+ elements: l.elements.filter((V) => V.id !== h.id)
2739
+ };
2740
+ });
2741
+ if (o) {
2742
+ const l = r.map((g, I) => I !== P ? g : { ...g, elements: [...g.elements, o] });
2743
+ k(l);
2744
+ }
2745
+ }
2746
+ D({ type: "move", elementId: h.id, data: {} }), U.current = null;
2747
+ },
2748
+ [j, i, k, D]
2749
+ ), z = ce(() => {
2750
+ if (!X) return [];
2751
+ const p = [
2752
+ { name: "x", label: M.propX, type: "number", value: X.position.x, group: M.groupPosition },
2753
+ { name: "y", label: M.propY, type: "number", value: X.position.y, group: M.groupPosition },
2754
+ { name: "width", label: M.propWidth, type: "number", value: X.position.width, group: M.groupSize },
2755
+ { name: "height", label: M.propHeight, type: "number", value: X.position.height, group: M.groupSize }
2756
+ ];
2757
+ return X.type === "text" && p.push({
2758
+ name: "text",
2759
+ label: M.propText,
2760
+ type: "text",
2761
+ value: X.properties.text ?? "",
2762
+ group: M.groupContent
2763
+ }), X.type === "field" && p.push({
2764
+ name: "field",
2765
+ label: M.propField,
2766
+ type: "text",
2767
+ value: X.properties.field ?? "",
2768
+ group: M.groupContent
2769
+ }), p;
2770
+ }, [X]);
2771
+ return fe(() => {
2772
+ const p = H.current;
2773
+ if (!p) return;
2774
+ const P = (h) => {
2775
+ const a = ["INPUT", "TEXTAREA", "SELECT"].includes(h.target.tagName), t = h.ctrlKey || h.metaKey;
2776
+ if ((h.key === "Delete" || h.key === "Backspace") && u.count > 0 && !a) {
2777
+ h.preventDefault(), ne();
2778
+ return;
2779
+ }
2780
+ if (h.key === "Escape") {
2781
+ u.clearSelection();
2782
+ return;
2783
+ }
2784
+ if (!a) {
2785
+ if (t && h.key === "z" && !h.shiftKey && !j) {
2786
+ h.preventDefault(), c.undo();
2787
+ return;
2788
+ }
2789
+ if (t && (h.key === "z" && h.shiftKey || h.key === "y") && !j) {
2790
+ h.preventDefault(), c.redo();
2791
+ return;
2792
+ }
2793
+ if (t && h.key === "c") {
2794
+ h.preventDefault(), O();
2795
+ return;
2796
+ }
2797
+ if (t && h.key === "v" && !j) {
2798
+ h.preventDefault(), le();
2799
+ return;
2800
+ }
2801
+ if (t && h.key === "a") {
2802
+ h.preventDefault();
2803
+ const o = i.flatMap((r) => r.elements).map((r) => r.id);
2804
+ u.selectMany(o);
2805
+ return;
2806
+ }
2807
+ }
2808
+ };
2809
+ return p.addEventListener("keydown", P), () => p.removeEventListener("keydown", P);
2810
+ }, [u, ne, j, c, O, le, i]), /* @__PURE__ */ e.jsxs("div", { ref: H, tabIndex: 0, className: me("flex h-full w-full border rounded-lg overflow-hidden bg-background", C), children: [
2811
+ /* @__PURE__ */ e.jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [
2812
+ y && /* @__PURE__ */ e.jsxs("div", { role: "toolbar", "aria-label": M.designerToolbar, className: "flex items-center gap-2 p-2 border-b bg-muted/20", children: [
2813
+ /* @__PURE__ */ e.jsx(Pt, { className: "h-4 w-4" }),
2814
+ /* @__PURE__ */ e.jsx("span", { className: "font-medium text-sm", children: s }),
2815
+ N && /* @__PURE__ */ e.jsxs("span", { className: "text-xs text-muted-foreground", children: [
916
2816
  "(",
917
- u,
2817
+ N,
918
2818
  ")"
919
2819
  ] }),
2820
+ !j && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
2821
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-5 bg-border mx-1" }),
2822
+ /* @__PURE__ */ e.jsx(
2823
+ "button",
2824
+ {
2825
+ className: me("p-1.5 rounded hover:bg-accent", !c.canUndo && "opacity-40 pointer-events-none"),
2826
+ title: M.undoShortcut,
2827
+ "aria-label": M.undo,
2828
+ disabled: !c.canUndo,
2829
+ onClick: () => c.undo(),
2830
+ children: /* @__PURE__ */ e.jsx(Ee, { className: "h-4 w-4" })
2831
+ }
2832
+ ),
2833
+ /* @__PURE__ */ e.jsx(
2834
+ "button",
2835
+ {
2836
+ className: me("p-1.5 rounded hover:bg-accent", !c.canRedo && "opacity-40 pointer-events-none"),
2837
+ title: M.redoShortcut,
2838
+ "aria-label": M.redo,
2839
+ disabled: !c.canRedo,
2840
+ onClick: () => c.redo(),
2841
+ children: /* @__PURE__ */ e.jsx(De, { className: "h-4 w-4" })
2842
+ }
2843
+ ),
2844
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-5 bg-border mx-1" })
2845
+ ] }),
2846
+ !j && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
2847
+ /* @__PURE__ */ e.jsx(
2848
+ "button",
2849
+ {
2850
+ className: me("p-1.5 rounded hover:bg-accent", u.count === 0 && "opacity-40 pointer-events-none"),
2851
+ title: M.copyShortcut,
2852
+ "aria-label": M.copy,
2853
+ disabled: u.count === 0,
2854
+ onClick: O,
2855
+ children: /* @__PURE__ */ e.jsx(Pe, { className: "h-4 w-4" })
2856
+ }
2857
+ ),
2858
+ /* @__PURE__ */ e.jsx(
2859
+ "button",
2860
+ {
2861
+ className: me("p-1.5 rounded hover:bg-accent", !T.hasContent && "opacity-40 pointer-events-none"),
2862
+ title: M.pasteShortcut,
2863
+ "aria-label": M.paste,
2864
+ disabled: !T.hasContent,
2865
+ onClick: le,
2866
+ children: /* @__PURE__ */ e.jsx(Te, { className: "h-4 w-4" })
2867
+ }
2868
+ ),
2869
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-5 bg-border mx-1" })
2870
+ ] }),
2871
+ !j && /* @__PURE__ */ e.jsx(
2872
+ "button",
2873
+ {
2874
+ className: me("p-1.5 rounded hover:bg-accent", u.count === 0 && "opacity-40 pointer-events-none"),
2875
+ title: M.deleteSelected,
2876
+ "aria-label": M.deleteSelected,
2877
+ disabled: u.count === 0,
2878
+ onClick: ne,
2879
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-4 w-4" })
2880
+ }
2881
+ ),
920
2882
  /* @__PURE__ */ e.jsx("div", { className: "flex-1" }),
2883
+ F?.isConnected && /* @__PURE__ */ e.jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
2884
+ /* @__PURE__ */ e.jsx("span", { className: "inline-block h-2 w-2 rounded-full bg-green-500" }),
2885
+ M.collaborationConnected,
2886
+ F.users.length > 1 && ` (${F.users.length})`
2887
+ ] }),
921
2888
  /* @__PURE__ */ e.jsxs("span", { className: "text-xs text-muted-foreground", children: [
922
- p,
2889
+ E,
923
2890
  " ",
924
2891
  w
925
- ] })
2892
+ ] }),
2893
+ f && /* @__PURE__ */ e.jsx(
2894
+ "button",
2895
+ {
2896
+ className: "p-1.5 rounded hover:bg-accent",
2897
+ title: $ ? M.collapsePanel : M.expandPanel,
2898
+ "aria-label": $ ? M.collapsePanel : M.expandPanel,
2899
+ onClick: () => S((p) => !p),
2900
+ children: /* @__PURE__ */ e.jsx(Ke, { className: me("h-4 w-4", !$ && "rotate-180") })
2901
+ }
2902
+ )
926
2903
  ] }),
927
- /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-auto bg-muted/10 p-4 flex justify-center", children: /* @__PURE__ */ e.jsx(
2904
+ /* @__PURE__ */ e.jsx("div", { role: "region", "aria-label": M.reportCanvas, className: "flex-1 overflow-auto bg-muted/10 p-4 flex justify-center", children: /* @__PURE__ */ e.jsx(
928
2905
  "div",
929
2906
  {
930
2907
  className: "bg-white shadow-lg border",
931
2908
  style: {
932
- width: o,
933
- minHeight: r
2909
+ width: Z,
2910
+ minHeight: oe
934
2911
  },
935
- children: k.map((m, h) => /* @__PURE__ */ e.jsxs(
2912
+ children: i.map((p, P) => /* @__PURE__ */ e.jsxs(
936
2913
  "div",
937
2914
  {
938
2915
  className: "relative border-b border-dashed border-gray-300",
939
- style: { minHeight: m.height },
2916
+ style: { minHeight: p.height },
2917
+ onDragOver: re,
2918
+ onDrop: (h) => d(h, P),
940
2919
  children: [
941
2920
  /* @__PURE__ */ e.jsxs("div", { className: "absolute left-0 top-0 px-2 py-0.5 bg-muted text-xs text-muted-foreground border-r border-b rounded-br", children: [
942
- T(m.type),
943
- m.repeat && " ↻"
2921
+ J(p.type),
2922
+ p.repeat && " ↻"
944
2923
  ] }),
945
- !n && /* @__PURE__ */ e.jsxs("div", { className: "absolute right-1 top-0 flex items-center gap-0.5", children: [
2924
+ !j && /* @__PURE__ */ e.jsxs("div", { className: "absolute right-1 top-0 flex items-center gap-0.5", children: [
946
2925
  /* @__PURE__ */ e.jsx(
947
2926
  "button",
948
2927
  {
949
- onClick: () => c(h, "text"),
2928
+ onClick: () => te(P, "text"),
950
2929
  className: "p-0.5 rounded hover:bg-accent",
951
- title: "Add Text",
952
- children: /* @__PURE__ */ e.jsx(Te, { className: "h-3 w-3" })
2930
+ title: M.addText,
2931
+ "aria-label": M.addText,
2932
+ children: /* @__PURE__ */ e.jsx(Tt, { className: "h-3 w-3" })
953
2933
  }
954
2934
  ),
955
2935
  /* @__PURE__ */ e.jsx(
956
2936
  "button",
957
2937
  {
958
- onClick: () => c(h, "field"),
2938
+ onClick: () => te(P, "field"),
959
2939
  className: "p-0.5 rounded hover:bg-accent",
960
- title: "Add Field",
961
- children: /* @__PURE__ */ e.jsx(K, { className: "h-3 w-3" })
2940
+ title: M.addField,
2941
+ "aria-label": M.addField,
2942
+ children: /* @__PURE__ */ e.jsx(xe, { className: "h-3 w-3" })
962
2943
  }
963
2944
  ),
964
2945
  /* @__PURE__ */ e.jsx(
965
2946
  "button",
966
2947
  {
967
- onClick: () => c(h, "image"),
2948
+ onClick: () => te(P, "image"),
968
2949
  className: "p-0.5 rounded hover:bg-accent",
969
- title: "Add Image",
970
- children: /* @__PURE__ */ e.jsx(_e, { className: "h-3 w-3" })
2950
+ title: M.addImage,
2951
+ "aria-label": M.addImage,
2952
+ children: /* @__PURE__ */ e.jsx(Rt, { className: "h-3 w-3" })
971
2953
  }
972
2954
  ),
973
2955
  /* @__PURE__ */ e.jsx(
974
2956
  "button",
975
2957
  {
976
- onClick: () => c(h, "chart"),
2958
+ onClick: () => te(P, "chart"),
977
2959
  className: "p-0.5 rounded hover:bg-accent",
978
- title: "Add Chart",
979
- children: /* @__PURE__ */ e.jsx(Se, { className: "h-3 w-3" })
2960
+ title: M.addChart,
2961
+ "aria-label": M.addChart,
2962
+ children: /* @__PURE__ */ e.jsx(At, { className: "h-3 w-3" })
980
2963
  }
981
2964
  ),
982
2965
  /* @__PURE__ */ e.jsx(
983
2966
  "button",
984
2967
  {
985
- onClick: () => c(h, "table"),
2968
+ onClick: () => te(P, "table"),
986
2969
  className: "p-0.5 rounded hover:bg-accent",
987
- title: "Add Table",
988
- children: /* @__PURE__ */ e.jsx(Ae, { className: "h-3 w-3" })
2970
+ title: M.addTable,
2971
+ "aria-label": M.addTable,
2972
+ children: /* @__PURE__ */ e.jsx(It, { className: "h-3 w-3" })
989
2973
  }
990
2974
  )
991
2975
  ] }),
992
- /* @__PURE__ */ e.jsx("div", { className: "relative", style: { minHeight: m.height, paddingTop: 24 }, children: m.elements.map((f) => /* @__PURE__ */ e.jsxs(
993
- "div",
994
- {
995
- className: ce(
996
- "absolute border rounded px-2 py-1 text-xs cursor-pointer",
997
- R === f.id ? "border-primary ring-1 ring-primary/30 bg-primary/5" : "border-dashed border-gray-400 hover:border-primary/50"
998
- ),
999
- style: {
1000
- left: f.position.x,
1001
- top: (typeof f.position.y == "number" ? f.position.y : 0) + 24,
1002
- width: f.position.width,
1003
- height: f.position.height
1004
- },
1005
- onClick: () => v(f.id),
1006
- children: [
1007
- /* @__PURE__ */ e.jsxs("span", { className: "text-muted-foreground", children: [
1008
- f.type === "text" && (f.properties.text ?? "Text"),
1009
- f.type === "field" && `{${f.properties.field ?? "field"}}`,
1010
- f.type === "image" && "🖼 Image",
1011
- f.type === "chart" && "📊 Chart",
1012
- f.type === "table" && "📋 Table"
1013
- ] }),
1014
- !n && R === f.id && /* @__PURE__ */ e.jsx(
1015
- "button",
1016
- {
1017
- onClick: (C) => {
1018
- C.stopPropagation(), s(f.id);
1019
- },
1020
- className: "absolute -top-2 -right-2 p-0.5 rounded-full bg-destructive text-destructive-foreground shadow",
1021
- children: /* @__PURE__ */ e.jsx(L, { className: "h-2.5 w-2.5" })
1022
- }
1023
- )
1024
- ]
1025
- },
1026
- f.id
1027
- )) })
2976
+ /* @__PURE__ */ e.jsxs("div", { className: "relative", style: { minHeight: p.height, paddingTop: 24 }, children: [
2977
+ p.elements.length === 0 && /* @__PURE__ */ e.jsx("div", { className: "text-xs text-muted-foreground text-center pt-4", children: M.addElementsPrompt }),
2978
+ p.elements.map((h) => {
2979
+ const a = u.isSelected(h.id);
2980
+ return /* @__PURE__ */ e.jsxs(
2981
+ "div",
2982
+ {
2983
+ draggable: !j,
2984
+ onDragStart: (t) => ie(t, h, P),
2985
+ className: me(
2986
+ "absolute border rounded px-2 py-1 text-xs cursor-pointer",
2987
+ a ? "border-primary ring-1 ring-primary/30 bg-primary/5" : "border-dashed border-gray-400 hover:border-primary/50"
2988
+ ),
2989
+ style: {
2990
+ left: h.position.x,
2991
+ top: (typeof h.position.y == "number" ? h.position.y : 0) + 24,
2992
+ width: h.position.width,
2993
+ height: h.position.height
2994
+ },
2995
+ onClick: (t) => u.toggle(h.id, t.shiftKey),
2996
+ children: [
2997
+ /* @__PURE__ */ e.jsxs("span", { className: "text-muted-foreground", children: [
2998
+ h.type === "text" && (h.properties.text ?? M.elementText),
2999
+ h.type === "field" && `{${h.properties.field ?? "field"}}`,
3000
+ h.type === "image" && M.elementImage,
3001
+ h.type === "chart" && M.elementChart,
3002
+ h.type === "table" && M.elementTable
3003
+ ] }),
3004
+ !j && a && /* @__PURE__ */ e.jsx(
3005
+ "button",
3006
+ {
3007
+ onClick: (t) => {
3008
+ t.stopPropagation(), se(h.id);
3009
+ },
3010
+ className: "absolute -top-2 -right-2 p-0.5 rounded-full bg-destructive text-destructive-foreground shadow",
3011
+ "aria-label": M.deleteElement,
3012
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-2.5 w-2.5" })
3013
+ }
3014
+ )
3015
+ ]
3016
+ },
3017
+ h.id
3018
+ );
3019
+ })
3020
+ ] })
1028
3021
  ]
1029
3022
  },
1030
- `${m.type}-${h}`
3023
+ `${p.type}-${P}`
1031
3024
  ))
1032
3025
  }
1033
3026
  ) })
1034
3027
  ] }),
1035
- E && /* @__PURE__ */ e.jsxs("div", { className: "w-56 border-l bg-muted/30 flex flex-col", children: [
1036
- /* @__PURE__ */ e.jsx("div", { className: "p-3 border-b font-medium text-sm", children: "Properties" }),
1037
- /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto p-3", children: R ? /* @__PURE__ */ e.jsx("div", { className: "space-y-2 text-xs", children: /* @__PURE__ */ e.jsxs("div", { className: "text-muted-foreground", children: [
1038
- "Element ID: ",
1039
- R
1040
- ] }) }) : /* @__PURE__ */ e.jsx("div", { className: "text-xs text-muted-foreground text-center py-4", children: "Select an element to view properties" }) })
1041
- ] })
3028
+ f && /* @__PURE__ */ e.jsx(
3029
+ "div",
3030
+ {
3031
+ role: "region",
3032
+ "aria-label": M.propertiesPanel,
3033
+ className: me(
3034
+ "border-l bg-muted/30 flex flex-col transition-[width] duration-200",
3035
+ $ ? "w-56" : "w-0 overflow-hidden"
3036
+ ),
3037
+ children: $ && (x && X ? /* @__PURE__ */ e.jsx(
3038
+ Ue,
3039
+ {
3040
+ title: `${M.properties} – ${X.type}`,
3041
+ fields: z,
3042
+ onChange: ae
3043
+ }
3044
+ ) : /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
3045
+ /* @__PURE__ */ e.jsx("div", { className: "p-3 border-b font-medium text-sm", children: M.properties }),
3046
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto p-3", children: /* @__PURE__ */ e.jsx("div", { className: "text-xs text-muted-foreground text-center py-4", children: M.selectElementPrompt }) })
3047
+ ] }))
3048
+ }
3049
+ ),
3050
+ /* @__PURE__ */ e.jsx(
3051
+ Fe,
3052
+ {
3053
+ isOpen: A.isOpen,
3054
+ title: A.title,
3055
+ message: A.message,
3056
+ onConfirm: A.onConfirm,
3057
+ onCancel: A.onCancel
3058
+ }
3059
+ )
1042
3060
  ] });
1043
3061
  }
1044
- const ue = fe(null);
1045
- ue.displayName = "CollaborationContext";
1046
- function qe({
1047
- config: l,
1048
- user: u,
1049
- onOperation: p,
1050
- children: w
3062
+ function ze(...s) {
3063
+ return pe(ue(s));
3064
+ }
3065
+ const _ = {
3066
+ title: "View Designer",
3067
+ saveView: "Save View",
3068
+ cancel: "Cancel",
3069
+ availableFields: "Available Fields",
3070
+ allFieldsAdded: "All fields added",
3071
+ noColumnsTitle: "No columns added yet. Select fields from the palette to add columns.",
3072
+ columnsCount: (s) => `Columns (${s})`,
3073
+ viewType: "View Type",
3074
+ viewName: "View Name",
3075
+ viewNamePlaceholder: "Enter view name...",
3076
+ columnProperties: "Column Properties",
3077
+ selectColumnPrompt: "Select a column to edit its properties",
3078
+ labelField: "Label",
3079
+ widthField: "Width",
3080
+ widthPlaceholder: "auto",
3081
+ fieldLabel: "Field:",
3082
+ addFilter: "Add Filter",
3083
+ addSort: "Add Sort",
3084
+ valuePlaceholder: "Value",
3085
+ asc: "Asc",
3086
+ desc: "Desc",
3087
+ selectField: "Select field...",
3088
+ moveUp: "Move up",
3089
+ moveDown: "Move down",
3090
+ moveColumnUp: "Move column up",
3091
+ moveColumnDown: "Move column down",
3092
+ hideColumn: "Hide column",
3093
+ showColumn: "Show column",
3094
+ toggleVisibility: "Toggle column visibility",
3095
+ removeColumn: "Remove column",
3096
+ copyColumn: "Copy column",
3097
+ pasteColumn: "Paste column",
3098
+ deleteColumnTitle: "Delete Column",
3099
+ deleteColumnMessage: (s) => `Are you sure you want to delete the column "${s}"? This action cannot be undone.`,
3100
+ undo: "Undo (Ctrl+Z)",
3101
+ redo: "Redo (Ctrl+Y)",
3102
+ gridOptionsHint: "Grid view uses the columns configured above.",
3103
+ groupByField: "Group By Field",
3104
+ startDateField: "Start Date Field",
3105
+ titleField: "Title Field",
3106
+ latitudeField: "Latitude Field",
3107
+ longitudeField: "Longitude Field",
3108
+ imageField: "Image Field",
3109
+ dateField: "Date Field"
3110
+ }, tt = [
3111
+ { type: "grid", label: "Grid", icon: _t },
3112
+ { type: "kanban", label: "Kanban", icon: zt },
3113
+ { type: "gallery", label: "Gallery", icon: Lt },
3114
+ { type: "calendar", label: "Calendar", icon: Ut },
3115
+ { type: "timeline", label: "Timeline", icon: dt },
3116
+ { type: "gantt", label: "Gantt", icon: Gt },
3117
+ { type: "map", label: "Map", icon: nt }
3118
+ ], pr = [
3119
+ { value: "equals", label: "=" },
3120
+ { value: "contains", label: "Contains" },
3121
+ { value: "startsWith", label: "Starts with" },
3122
+ { value: "gt", label: ">" },
3123
+ { value: "lt", label: "<" },
3124
+ { value: "gte", label: ">=" },
3125
+ { value: "lte", label: "<=" },
3126
+ { value: "ne", label: "!=" }
3127
+ ];
3128
+ function mr({
3129
+ objectName: s,
3130
+ viewId: N,
3131
+ viewLabel: E = "",
3132
+ viewType: w = "grid",
3133
+ columns: v = [],
3134
+ filters: R = [],
3135
+ sort: y = [],
3136
+ availableFields: f = [],
3137
+ options: j = {},
3138
+ readOnly: n = !1,
3139
+ onSave: C,
3140
+ onCancel: c,
3141
+ className: i
1051
3142
  }) {
1052
- const i = Z(() => !l.enabled || !u ? [] : [{
1053
- userId: u.id,
1054
- userName: u.name,
1055
- avatar: u.avatar,
1056
- color: Le(u.id),
1057
- status: "active",
1058
- lastActivity: (/* @__PURE__ */ new Date()).toISOString()
1059
- }], [l.enabled, u]), d = l.enabled && !!u, x = P(
1060
- (n) => {
1061
- if (!d || !u) return;
1062
- const _ = {
1063
- ...n,
1064
- id: `op-${Date.now()}`,
1065
- userId: u.id,
1066
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1067
- version: Date.now()
3143
+ const k = ee(null), u = Re({
3144
+ columns: v,
3145
+ filters: R,
3146
+ sort: y,
3147
+ viewType: w,
3148
+ viewLabel: E,
3149
+ options: j
3150
+ }), { columns: x, filters: T, sort: A, viewType: F, viewLabel: D, options: $ } = u.current, S = b(
3151
+ (t) => {
3152
+ u.push({ ...u.current, ...t });
3153
+ },
3154
+ [u]
3155
+ ), U = Ie(), H = Ae(), G = $e(), [Z, oe] = K(null), [J, X] = K("columns"), te = ce(() => {
3156
+ const t = new Set(x.map((o) => o.field));
3157
+ return f.filter((o) => !t.has(o.name));
3158
+ }, [f, x]), se = b(
3159
+ (t) => {
3160
+ if (n) return;
3161
+ const o = f.find((l) => l.name === t), r = {
3162
+ field: t,
3163
+ label: o?.label ?? t,
3164
+ visible: !0,
3165
+ order: x.length
1068
3166
  };
1069
- p?.(_);
3167
+ S({ columns: [...x, r] }), G?.sendOperation({ type: "insert", userId: G.currentUserId ?? "", elementId: t, data: { column: r } });
1070
3168
  },
1071
- [d, u, p]
1072
- ), E = Z(
1073
- () => ({
1074
- users: i,
1075
- isConnected: d,
1076
- sendOperation: x,
1077
- currentUserId: u?.id
1078
- }),
1079
- [i, d, x, u?.id]
3169
+ [f, x, n, S, G]
3170
+ ), ne = b(
3171
+ async (t) => {
3172
+ if (n) return;
3173
+ const o = x[t];
3174
+ !o || !await H.confirm(
3175
+ _.deleteColumnTitle,
3176
+ _.deleteColumnMessage(o.label || o.field)
3177
+ ) || (S({ columns: x.filter((l, g) => g !== t) }), Z === t && oe(null), G?.sendOperation({ type: "delete", userId: G.currentUserId ?? "", elementId: o.field, data: {} }));
3178
+ },
3179
+ [n, x, H, S, Z, G]
3180
+ ), ae = b(
3181
+ (t) => {
3182
+ n || S({
3183
+ columns: x.map((o, r) => r === t ? { ...o, visible: !o.visible } : o)
3184
+ });
3185
+ },
3186
+ [n, x, S]
3187
+ ), O = b(
3188
+ (t, o) => {
3189
+ if (n) return;
3190
+ const r = o === "up" ? t - 1 : t + 1;
3191
+ if (r < 0 || r >= x.length) return;
3192
+ const l = [...x], g = l[t];
3193
+ l[t] = l[r], l[r] = g, S({ columns: l }), oe(r);
3194
+ },
3195
+ [n, x, S]
3196
+ ), le = b(() => {
3197
+ n || f.length === 0 || S({
3198
+ filters: [...T, { field: f[0].name, operator: "equals", value: "" }]
3199
+ });
3200
+ }, [n, f, T, S]), ie = b(
3201
+ (t) => {
3202
+ n || S({ filters: T.filter((o, r) => r !== t) });
3203
+ },
3204
+ [n, T, S]
3205
+ ), re = b(
3206
+ (t, o) => {
3207
+ n || S({
3208
+ filters: T.map((r, l) => l === t ? { ...r, ...o } : r)
3209
+ });
3210
+ },
3211
+ [n, T, S]
3212
+ ), d = b(() => {
3213
+ n || f.length === 0 || S({
3214
+ sort: [...A, { field: f[0].name, direction: "asc" }]
3215
+ });
3216
+ }, [n, f, A, S]), z = b(
3217
+ (t) => {
3218
+ n || S({ sort: A.filter((o, r) => r !== t) });
3219
+ },
3220
+ [n, A, S]
3221
+ ), p = b(
3222
+ (t, o) => {
3223
+ n || S({
3224
+ sort: A.map((r, l) => l === t ? { ...r, ...o } : r)
3225
+ });
3226
+ },
3227
+ [n, A, S]
3228
+ ), P = b(() => {
3229
+ Z === null || !x[Z] || U.copy(x[Z]);
3230
+ }, [Z, x, U]), h = b(() => {
3231
+ if (n) return;
3232
+ const t = U.paste();
3233
+ if (!t) return;
3234
+ const o = {
3235
+ ...t,
3236
+ field: `${t.field}_copy`,
3237
+ label: `${t.label || t.field} (Copy)`,
3238
+ order: x.length
3239
+ };
3240
+ S({ columns: [...x, o] });
3241
+ }, [n, U, x, S]), a = b(() => {
3242
+ C?.({
3243
+ viewId: N,
3244
+ viewLabel: D || `${s} View`,
3245
+ viewType: F,
3246
+ columns: x,
3247
+ filters: T,
3248
+ sort: A,
3249
+ options: $
3250
+ });
3251
+ }, [C, N, D, s, F, x, T, A, $]);
3252
+ return fe(() => {
3253
+ const t = k.current;
3254
+ if (!t) return;
3255
+ const o = (r) => {
3256
+ const l = ["INPUT", "TEXTAREA", "SELECT"].includes(r.target.tagName), g = r.ctrlKey || r.metaKey;
3257
+ if (!l) {
3258
+ if (g && r.key === "z" && !r.shiftKey && !n) {
3259
+ r.preventDefault(), u.undo();
3260
+ return;
3261
+ }
3262
+ if (g && (r.key === "z" && r.shiftKey || r.key === "y") && !n) {
3263
+ r.preventDefault(), u.redo();
3264
+ return;
3265
+ }
3266
+ if (g && r.key === "c") {
3267
+ r.preventDefault(), P();
3268
+ return;
3269
+ }
3270
+ if (g && r.key === "v" && !n) {
3271
+ r.preventDefault(), h();
3272
+ return;
3273
+ }
3274
+ }
3275
+ };
3276
+ return t.addEventListener("keydown", o), () => t.removeEventListener("keydown", o);
3277
+ }, [n, u, P, h]), /* @__PURE__ */ e.jsxs(
3278
+ "div",
3279
+ {
3280
+ ref: k,
3281
+ tabIndex: -1,
3282
+ className: ze("flex flex-col h-full w-full border rounded-lg overflow-hidden bg-background", i),
3283
+ children: [
3284
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 p-2 border-b bg-muted/20 shrink-0", role: "toolbar", children: [
3285
+ /* @__PURE__ */ e.jsx(Ft, { className: "h-4 w-4 text-muted-foreground" }),
3286
+ /* @__PURE__ */ e.jsx("span", { className: "font-medium text-sm", children: _.title }),
3287
+ /* @__PURE__ */ e.jsxs("span", { className: "text-xs text-muted-foreground", children: [
3288
+ "— ",
3289
+ s
3290
+ ] }),
3291
+ G?.isConnected && G.users.length > 1 && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 ml-2", role: "status", "aria-label": "Active collaborators", children: [
3292
+ G.users.slice(0, 3).map((t) => /* @__PURE__ */ e.jsx(
3293
+ "div",
3294
+ {
3295
+ className: "h-5 w-5 rounded-full text-[10px] font-bold flex items-center justify-center text-white",
3296
+ style: { backgroundColor: t.color },
3297
+ title: t.userName,
3298
+ children: t.userName.charAt(0).toUpperCase()
3299
+ },
3300
+ t.userId
3301
+ )),
3302
+ G.users.length > 3 && /* @__PURE__ */ e.jsxs("span", { className: "text-xs text-muted-foreground", children: [
3303
+ "+",
3304
+ G.users.length - 3
3305
+ ] })
3306
+ ] }),
3307
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1" }),
3308
+ !n && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
3309
+ /* @__PURE__ */ e.jsx(
3310
+ "button",
3311
+ {
3312
+ onClick: u.undo,
3313
+ disabled: !u.canUndo,
3314
+ className: "p-1.5 rounded hover:bg-accent disabled:opacity-30",
3315
+ title: _.undo,
3316
+ "aria-label": _.undo,
3317
+ "data-testid": "view-designer-undo",
3318
+ children: /* @__PURE__ */ e.jsx(Ee, { className: "h-3.5 w-3.5" })
3319
+ }
3320
+ ),
3321
+ /* @__PURE__ */ e.jsx(
3322
+ "button",
3323
+ {
3324
+ onClick: u.redo,
3325
+ disabled: !u.canRedo,
3326
+ className: "p-1.5 rounded hover:bg-accent disabled:opacity-30",
3327
+ title: _.redo,
3328
+ "aria-label": _.redo,
3329
+ "data-testid": "view-designer-redo",
3330
+ children: /* @__PURE__ */ e.jsx(De, { className: "h-3.5 w-3.5" })
3331
+ }
3332
+ ),
3333
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-4 bg-border mx-1" })
3334
+ ] }),
3335
+ !n && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
3336
+ /* @__PURE__ */ e.jsx(
3337
+ "button",
3338
+ {
3339
+ onClick: P,
3340
+ disabled: Z === null,
3341
+ className: "p-1.5 rounded hover:bg-accent disabled:opacity-30",
3342
+ title: _.copyColumn,
3343
+ "aria-label": _.copyColumn,
3344
+ "data-testid": "view-designer-copy",
3345
+ children: /* @__PURE__ */ e.jsx(Pe, { className: "h-3.5 w-3.5" })
3346
+ }
3347
+ ),
3348
+ /* @__PURE__ */ e.jsx(
3349
+ "button",
3350
+ {
3351
+ onClick: h,
3352
+ disabled: !U.hasContent,
3353
+ className: "p-1.5 rounded hover:bg-accent disabled:opacity-30",
3354
+ title: _.pasteColumn,
3355
+ "aria-label": _.pasteColumn,
3356
+ "data-testid": "view-designer-paste",
3357
+ children: /* @__PURE__ */ e.jsx(Te, { className: "h-3.5 w-3.5" })
3358
+ }
3359
+ ),
3360
+ /* @__PURE__ */ e.jsx("div", { className: "w-px h-4 bg-border mx-1" })
3361
+ ] }),
3362
+ !n && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
3363
+ c && /* @__PURE__ */ e.jsxs(
3364
+ "button",
3365
+ {
3366
+ onClick: c,
3367
+ className: "flex items-center gap-1 px-3 py-1.5 text-xs rounded border border-border hover:bg-accent",
3368
+ "data-testid": "view-designer-cancel",
3369
+ children: [
3370
+ /* @__PURE__ */ e.jsx($t, { className: "h-3 w-3" }),
3371
+ " ",
3372
+ _.cancel
3373
+ ]
3374
+ }
3375
+ ),
3376
+ /* @__PURE__ */ e.jsxs(
3377
+ "button",
3378
+ {
3379
+ onClick: a,
3380
+ className: "flex items-center gap-1 px-3 py-1.5 text-xs rounded bg-primary text-primary-foreground hover:bg-primary/90",
3381
+ "data-testid": "view-designer-save",
3382
+ children: [
3383
+ /* @__PURE__ */ e.jsx(Mt, { className: "h-3 w-3" }),
3384
+ " ",
3385
+ _.saveView
3386
+ ]
3387
+ }
3388
+ )
3389
+ ] })
3390
+ ] }),
3391
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-1 overflow-hidden", children: [
3392
+ !n && /* @__PURE__ */ e.jsxs("div", { className: "w-56 border-r bg-muted/30 flex flex-col shrink-0", children: [
3393
+ /* @__PURE__ */ e.jsx("div", { className: "p-3 border-b font-medium text-sm", children: _.availableFields }),
3394
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto p-2", children: te.length === 0 ? /* @__PURE__ */ e.jsx("div", { className: "text-xs text-muted-foreground text-center py-4", children: _.allFieldsAdded }) : te.map((t) => /* @__PURE__ */ e.jsxs(
3395
+ "button",
3396
+ {
3397
+ onClick: () => se(t.name),
3398
+ className: "w-full flex items-center gap-2 px-2 py-1.5 text-sm rounded hover:bg-accent text-left",
3399
+ "data-testid": `field-${t.name}`,
3400
+ children: [
3401
+ /* @__PURE__ */ e.jsx(xe, { className: "h-3 w-3 text-muted-foreground" }),
3402
+ /* @__PURE__ */ e.jsx("span", { className: "truncate", children: t.label || t.name }),
3403
+ /* @__PURE__ */ e.jsx("span", { className: "ml-auto text-xs text-muted-foreground", children: t.type })
3404
+ ]
3405
+ },
3406
+ t.name
3407
+ )) })
3408
+ ] }),
3409
+ /* @__PURE__ */ e.jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
3410
+ /* @__PURE__ */ e.jsxs("div", { className: "p-3 border-b space-y-3 shrink-0 bg-muted/10", children: [
3411
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col gap-2", children: [
3412
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs font-semibold text-foreground", children: _.viewType }),
3413
+ /* @__PURE__ */ e.jsx("div", { className: "flex gap-2 flex-wrap", children: tt.map(({ type: t, label: o, icon: r }) => /* @__PURE__ */ e.jsxs(
3414
+ "button",
3415
+ {
3416
+ onClick: () => !n && S({ viewType: t }),
3417
+ className: ze(
3418
+ "flex items-center gap-2 px-3 py-2 text-sm rounded-md border-2 transition-all font-medium",
3419
+ F === t ? "border-primary bg-primary text-primary-foreground shadow-sm" : "border-border bg-background hover:border-primary/50 hover:bg-accent"
3420
+ ),
3421
+ "data-testid": `view-type-${t}`,
3422
+ children: [
3423
+ /* @__PURE__ */ e.jsx(r, { className: "h-4 w-4" }),
3424
+ o
3425
+ ]
3426
+ },
3427
+ t
3428
+ )) })
3429
+ ] }),
3430
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col gap-2", children: [
3431
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs font-semibold text-foreground", children: _.viewName }),
3432
+ /* @__PURE__ */ e.jsx(
3433
+ "input",
3434
+ {
3435
+ type: "text",
3436
+ value: D,
3437
+ onChange: (t) => !n && S({ viewLabel: t.target.value }),
3438
+ placeholder: _.viewNamePlaceholder,
3439
+ className: "px-3 py-2 text-sm border-2 rounded-md bg-background focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary",
3440
+ readOnly: n,
3441
+ "data-testid": "view-label-input"
3442
+ }
3443
+ )
3444
+ ] })
3445
+ ] }),
3446
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-auto p-3", children: x.length === 0 ? /* @__PURE__ */ e.jsx("div", { className: "flex items-center justify-center h-full text-sm text-muted-foreground", children: /* @__PURE__ */ e.jsxs("div", { className: "text-center", children: [
3447
+ /* @__PURE__ */ e.jsx(Yt, { className: "h-8 w-8 mx-auto mb-2 opacity-50" }),
3448
+ /* @__PURE__ */ e.jsx("p", { children: _.noColumnsTitle })
3449
+ ] }) }) : /* @__PURE__ */ e.jsxs("div", { className: "space-y-1", children: [
3450
+ /* @__PURE__ */ e.jsx("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: _.columnsCount(x.length) }),
3451
+ x.map((t, o) => /* @__PURE__ */ e.jsxs(
3452
+ "div",
3453
+ {
3454
+ className: ze(
3455
+ "flex items-center gap-2 px-3 py-2 rounded border transition-colors cursor-pointer",
3456
+ Z === o ? "border-primary bg-primary/5 ring-1 ring-primary/20" : "border-border hover:border-primary/50",
3457
+ !t.visible && "opacity-50"
3458
+ ),
3459
+ onClick: () => oe(o),
3460
+ "data-testid": `column-${t.field}`,
3461
+ children: [
3462
+ /* @__PURE__ */ e.jsx(at, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }),
3463
+ /* @__PURE__ */ e.jsx("span", { className: "text-sm font-medium truncate flex-1", children: t.label || t.field }),
3464
+ /* @__PURE__ */ e.jsx("span", { className: "text-xs text-muted-foreground", children: t.field }),
3465
+ !n && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [
3466
+ /* @__PURE__ */ e.jsx(
3467
+ "button",
3468
+ {
3469
+ onClick: (r) => {
3470
+ r.stopPropagation(), O(o, "up");
3471
+ },
3472
+ disabled: o === 0,
3473
+ className: "p-0.5 rounded hover:bg-accent disabled:opacity-30",
3474
+ title: _.moveUp,
3475
+ "aria-label": _.moveColumnUp,
3476
+ children: /* @__PURE__ */ e.jsx(Vt, { className: "h-3 w-3" })
3477
+ }
3478
+ ),
3479
+ /* @__PURE__ */ e.jsx(
3480
+ "button",
3481
+ {
3482
+ onClick: (r) => {
3483
+ r.stopPropagation(), O(o, "down");
3484
+ },
3485
+ disabled: o === x.length - 1,
3486
+ className: "p-0.5 rounded hover:bg-accent disabled:opacity-30",
3487
+ title: _.moveDown,
3488
+ "aria-label": _.moveColumnDown,
3489
+ children: /* @__PURE__ */ e.jsx(Zt, { className: "h-3 w-3" })
3490
+ }
3491
+ ),
3492
+ /* @__PURE__ */ e.jsx(
3493
+ "button",
3494
+ {
3495
+ onClick: (r) => {
3496
+ r.stopPropagation(), ae(o);
3497
+ },
3498
+ className: "p-0.5 rounded hover:bg-accent",
3499
+ title: t.visible !== !1 ? _.hideColumn : _.showColumn,
3500
+ "aria-label": _.toggleVisibility,
3501
+ children: t.visible !== !1 ? /* @__PURE__ */ e.jsx(st, { className: "h-3 w-3" }) : /* @__PURE__ */ e.jsx(Ht, { className: "h-3 w-3" })
3502
+ }
3503
+ ),
3504
+ /* @__PURE__ */ e.jsx(
3505
+ "button",
3506
+ {
3507
+ onClick: (r) => {
3508
+ r.stopPropagation(), ne(o);
3509
+ },
3510
+ className: "p-0.5 rounded hover:bg-destructive/10",
3511
+ title: _.removeColumn,
3512
+ "aria-label": _.removeColumn,
3513
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-3 w-3 text-destructive" })
3514
+ }
3515
+ )
3516
+ ] })
3517
+ ]
3518
+ },
3519
+ `${t.field}-${o}`
3520
+ ))
3521
+ ] }) })
3522
+ ] }),
3523
+ /* @__PURE__ */ e.jsxs("div", { className: "w-64 border-l bg-muted/30 flex flex-col shrink-0", children: [
3524
+ /* @__PURE__ */ e.jsx("div", { className: "flex border-b shrink-0", role: "tablist", children: ["columns", "filters", "sort", "options"].map((t) => /* @__PURE__ */ e.jsx(
3525
+ "button",
3526
+ {
3527
+ onClick: () => X(t),
3528
+ role: "tab",
3529
+ "aria-selected": J === t,
3530
+ className: ze(
3531
+ "flex-1 px-2 py-2 text-xs font-medium capitalize transition-colors",
3532
+ J === t ? "border-b-2 border-primary text-primary" : "text-muted-foreground hover:text-foreground"
3533
+ ),
3534
+ children: t
3535
+ },
3536
+ t
3537
+ )) }),
3538
+ /* @__PURE__ */ e.jsxs("div", { className: "flex-1 overflow-y-auto p-3", children: [
3539
+ J === "columns" && /* @__PURE__ */ e.jsx("div", { children: Z !== null && x[Z] ? /* @__PURE__ */ e.jsxs("div", { className: "space-y-3", children: [
3540
+ /* @__PURE__ */ e.jsx("div", { className: "text-xs font-medium", children: _.columnProperties }),
3541
+ /* @__PURE__ */ e.jsxs("div", { children: [
3542
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.labelField }),
3543
+ /* @__PURE__ */ e.jsx(
3544
+ "input",
3545
+ {
3546
+ type: "text",
3547
+ value: x[Z].label ?? "",
3548
+ onChange: (t) => {
3549
+ if (n) return;
3550
+ const o = Z;
3551
+ S({
3552
+ columns: x.map((r, l) => l === o ? { ...r, label: t.target.value } : r)
3553
+ });
3554
+ },
3555
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3556
+ readOnly: n,
3557
+ "data-testid": "column-label-input"
3558
+ }
3559
+ )
3560
+ ] }),
3561
+ /* @__PURE__ */ e.jsxs("div", { children: [
3562
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.widthField }),
3563
+ /* @__PURE__ */ e.jsx(
3564
+ "input",
3565
+ {
3566
+ type: "text",
3567
+ value: x[Z].width ?? "",
3568
+ onChange: (t) => {
3569
+ if (n) return;
3570
+ const o = Z, r = t.target.value;
3571
+ S({
3572
+ columns: x.map(
3573
+ (l, g) => g === o ? { ...l, width: /^\d+$/.test(r) ? Number(r) : r } : l
3574
+ )
3575
+ });
3576
+ },
3577
+ placeholder: _.widthPlaceholder,
3578
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3579
+ readOnly: n,
3580
+ "data-testid": "column-width-input"
3581
+ }
3582
+ )
3583
+ ] }),
3584
+ /* @__PURE__ */ e.jsxs("div", { className: "text-xs text-muted-foreground", children: [
3585
+ _.fieldLabel,
3586
+ " ",
3587
+ /* @__PURE__ */ e.jsx("span", { className: "font-mono", children: x[Z].field })
3588
+ ] })
3589
+ ] }) : /* @__PURE__ */ e.jsx("div", { className: "text-xs text-muted-foreground text-center py-4", children: _.selectColumnPrompt }) }),
3590
+ J === "filters" && /* @__PURE__ */ e.jsxs("div", { className: "space-y-2", children: [
3591
+ T.map((t, o) => /* @__PURE__ */ e.jsxs("div", { className: "space-y-1 p-2 border rounded bg-background", "data-testid": `filter-${o}`, children: [
3592
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1", children: [
3593
+ /* @__PURE__ */ e.jsx(
3594
+ "select",
3595
+ {
3596
+ value: t.field,
3597
+ onChange: (r) => re(o, { field: r.target.value }),
3598
+ className: "flex-1 px-1 py-0.5 text-xs border rounded bg-background",
3599
+ disabled: n,
3600
+ children: f.map((r) => /* @__PURE__ */ e.jsx("option", { value: r.name, children: r.label || r.name }, r.name))
3601
+ }
3602
+ ),
3603
+ !n && /* @__PURE__ */ e.jsx(
3604
+ "button",
3605
+ {
3606
+ onClick: () => ie(o),
3607
+ className: "p-0.5 rounded hover:bg-destructive/10",
3608
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-3 w-3 text-destructive" })
3609
+ }
3610
+ )
3611
+ ] }),
3612
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1", children: [
3613
+ /* @__PURE__ */ e.jsx(
3614
+ "select",
3615
+ {
3616
+ value: t.operator,
3617
+ onChange: (r) => re(o, { operator: r.target.value }),
3618
+ className: "w-24 px-1 py-0.5 text-xs border rounded bg-background",
3619
+ disabled: n,
3620
+ children: pr.map((r) => /* @__PURE__ */ e.jsx("option", { value: r.value, children: r.label }, r.value))
3621
+ }
3622
+ ),
3623
+ /* @__PURE__ */ e.jsx(
3624
+ "input",
3625
+ {
3626
+ type: "text",
3627
+ value: t.value ?? "",
3628
+ onChange: (r) => re(o, { value: r.target.value }),
3629
+ placeholder: _.valuePlaceholder,
3630
+ className: "flex-1 px-1 py-0.5 text-xs border rounded bg-background",
3631
+ readOnly: n
3632
+ }
3633
+ )
3634
+ ] })
3635
+ ] }, o)),
3636
+ !n && /* @__PURE__ */ e.jsxs(
3637
+ "button",
3638
+ {
3639
+ onClick: le,
3640
+ className: "w-full flex items-center justify-center gap-1 px-2 py-1.5 text-xs rounded border border-dashed border-border hover:bg-accent",
3641
+ "data-testid": "add-filter",
3642
+ "aria-label": _.addFilter,
3643
+ children: [
3644
+ /* @__PURE__ */ e.jsx(xe, { className: "h-3 w-3" }),
3645
+ " ",
3646
+ _.addFilter
3647
+ ]
3648
+ }
3649
+ )
3650
+ ] }),
3651
+ J === "sort" && /* @__PURE__ */ e.jsxs("div", { className: "space-y-2", children: [
3652
+ A.map((t, o) => /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1 p-2 border rounded bg-background", "data-testid": `sort-${o}`, children: [
3653
+ /* @__PURE__ */ e.jsx(
3654
+ "select",
3655
+ {
3656
+ value: t.field,
3657
+ onChange: (r) => p(o, { field: r.target.value }),
3658
+ className: "flex-1 px-1 py-0.5 text-xs border rounded bg-background",
3659
+ disabled: n,
3660
+ children: f.map((r) => /* @__PURE__ */ e.jsx("option", { value: r.name, children: r.label || r.name }, r.name))
3661
+ }
3662
+ ),
3663
+ /* @__PURE__ */ e.jsxs(
3664
+ "select",
3665
+ {
3666
+ value: t.direction,
3667
+ onChange: (r) => p(o, { direction: r.target.value }),
3668
+ className: "w-16 px-1 py-0.5 text-xs border rounded bg-background",
3669
+ disabled: n,
3670
+ children: [
3671
+ /* @__PURE__ */ e.jsx("option", { value: "asc", children: _.asc }),
3672
+ /* @__PURE__ */ e.jsx("option", { value: "desc", children: _.desc })
3673
+ ]
3674
+ }
3675
+ ),
3676
+ !n && /* @__PURE__ */ e.jsx(
3677
+ "button",
3678
+ {
3679
+ onClick: () => z(o),
3680
+ className: "p-0.5 rounded hover:bg-destructive/10",
3681
+ children: /* @__PURE__ */ e.jsx(he, { className: "h-3 w-3 text-destructive" })
3682
+ }
3683
+ )
3684
+ ] }, o)),
3685
+ !n && /* @__PURE__ */ e.jsxs(
3686
+ "button",
3687
+ {
3688
+ onClick: d,
3689
+ className: "w-full flex items-center justify-center gap-1 px-2 py-1.5 text-xs rounded border border-dashed border-border hover:bg-accent",
3690
+ "data-testid": "add-sort",
3691
+ "aria-label": _.addSort,
3692
+ children: [
3693
+ /* @__PURE__ */ e.jsx(xe, { className: "h-3 w-3" }),
3694
+ " ",
3695
+ _.addSort
3696
+ ]
3697
+ }
3698
+ )
3699
+ ] }),
3700
+ J === "options" && /* @__PURE__ */ e.jsxs("div", { className: "space-y-3", children: [
3701
+ /* @__PURE__ */ e.jsxs("div", { className: "text-xs font-medium", children: [
3702
+ tt.find((t) => t.type === F)?.label ?? F,
3703
+ " Options"
3704
+ ] }),
3705
+ F === "kanban" && /* @__PURE__ */ e.jsxs("div", { children: [
3706
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.groupByField }),
3707
+ /* @__PURE__ */ e.jsxs(
3708
+ "select",
3709
+ {
3710
+ value: $.groupBy ?? "",
3711
+ onChange: (t) => !n && S({ options: { ...$, groupBy: t.target.value } }),
3712
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3713
+ disabled: n,
3714
+ "data-testid": "kanban-group-by",
3715
+ children: [
3716
+ /* @__PURE__ */ e.jsx("option", { value: "", children: _.selectField }),
3717
+ f.map((t) => /* @__PURE__ */ e.jsx("option", { value: t.name, children: t.label || t.name }, t.name))
3718
+ ]
3719
+ }
3720
+ )
3721
+ ] }),
3722
+ F === "calendar" && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
3723
+ /* @__PURE__ */ e.jsxs("div", { children: [
3724
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.startDateField }),
3725
+ /* @__PURE__ */ e.jsxs(
3726
+ "select",
3727
+ {
3728
+ value: $.startDateField ?? "",
3729
+ onChange: (t) => !n && S({ options: { ...$, startDateField: t.target.value } }),
3730
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3731
+ disabled: n,
3732
+ "data-testid": "calendar-start-date",
3733
+ children: [
3734
+ /* @__PURE__ */ e.jsx("option", { value: "", children: _.selectField }),
3735
+ f.map((t) => /* @__PURE__ */ e.jsx("option", { value: t.name, children: t.label || t.name }, t.name))
3736
+ ]
3737
+ }
3738
+ )
3739
+ ] }),
3740
+ /* @__PURE__ */ e.jsxs("div", { children: [
3741
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.titleField }),
3742
+ /* @__PURE__ */ e.jsxs(
3743
+ "select",
3744
+ {
3745
+ value: $.titleField ?? "",
3746
+ onChange: (t) => !n && S({ options: { ...$, titleField: t.target.value } }),
3747
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3748
+ disabled: n,
3749
+ "data-testid": "calendar-title-field",
3750
+ children: [
3751
+ /* @__PURE__ */ e.jsx("option", { value: "", children: _.selectField }),
3752
+ f.map((t) => /* @__PURE__ */ e.jsx("option", { value: t.name, children: t.label || t.name }, t.name))
3753
+ ]
3754
+ }
3755
+ )
3756
+ ] })
3757
+ ] }),
3758
+ F === "map" && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
3759
+ /* @__PURE__ */ e.jsxs("div", { children: [
3760
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.latitudeField }),
3761
+ /* @__PURE__ */ e.jsxs(
3762
+ "select",
3763
+ {
3764
+ value: $.latitudeField ?? "",
3765
+ onChange: (t) => !n && S({ options: { ...$, latitudeField: t.target.value } }),
3766
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3767
+ disabled: n,
3768
+ children: [
3769
+ /* @__PURE__ */ e.jsx("option", { value: "", children: _.selectField }),
3770
+ f.map((t) => /* @__PURE__ */ e.jsx("option", { value: t.name, children: t.label || t.name }, t.name))
3771
+ ]
3772
+ }
3773
+ )
3774
+ ] }),
3775
+ /* @__PURE__ */ e.jsxs("div", { children: [
3776
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.longitudeField }),
3777
+ /* @__PURE__ */ e.jsxs(
3778
+ "select",
3779
+ {
3780
+ value: $.longitudeField ?? "",
3781
+ onChange: (t) => !n && S({ options: { ...$, longitudeField: t.target.value } }),
3782
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3783
+ disabled: n,
3784
+ children: [
3785
+ /* @__PURE__ */ e.jsx("option", { value: "", children: _.selectField }),
3786
+ f.map((t) => /* @__PURE__ */ e.jsx("option", { value: t.name, children: t.label || t.name }, t.name))
3787
+ ]
3788
+ }
3789
+ )
3790
+ ] })
3791
+ ] }),
3792
+ F === "gallery" && /* @__PURE__ */ e.jsxs("div", { children: [
3793
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.imageField }),
3794
+ /* @__PURE__ */ e.jsxs(
3795
+ "select",
3796
+ {
3797
+ value: $.imageField ?? "",
3798
+ onChange: (t) => !n && S({ options: { ...$, imageField: t.target.value } }),
3799
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3800
+ disabled: n,
3801
+ children: [
3802
+ /* @__PURE__ */ e.jsx("option", { value: "", children: _.selectField }),
3803
+ f.map((t) => /* @__PURE__ */ e.jsx("option", { value: t.name, children: t.label || t.name }, t.name))
3804
+ ]
3805
+ }
3806
+ )
3807
+ ] }),
3808
+ (F === "timeline" || F === "gantt") && /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
3809
+ /* @__PURE__ */ e.jsxs("div", { children: [
3810
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.dateField }),
3811
+ /* @__PURE__ */ e.jsxs(
3812
+ "select",
3813
+ {
3814
+ value: $.dateField ?? $.startDateField ?? "",
3815
+ onChange: (t) => !n && S({ options: { ...$, dateField: t.target.value, startDateField: t.target.value } }),
3816
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3817
+ disabled: n,
3818
+ children: [
3819
+ /* @__PURE__ */ e.jsx("option", { value: "", children: _.selectField }),
3820
+ f.map((t) => /* @__PURE__ */ e.jsx("option", { value: t.name, children: t.label || t.name }, t.name))
3821
+ ]
3822
+ }
3823
+ )
3824
+ ] }),
3825
+ /* @__PURE__ */ e.jsxs("div", { children: [
3826
+ /* @__PURE__ */ e.jsx("label", { className: "text-xs text-muted-foreground", children: _.titleField }),
3827
+ /* @__PURE__ */ e.jsxs(
3828
+ "select",
3829
+ {
3830
+ value: $.titleField ?? "",
3831
+ onChange: (t) => !n && S({ options: { ...$, titleField: t.target.value } }),
3832
+ className: "w-full px-2 py-1 text-sm border rounded bg-background mt-1",
3833
+ disabled: n,
3834
+ children: [
3835
+ /* @__PURE__ */ e.jsx("option", { value: "", children: _.selectField }),
3836
+ f.map((t) => /* @__PURE__ */ e.jsx("option", { value: t.name, children: t.label || t.name }, t.name))
3837
+ ]
3838
+ }
3839
+ )
3840
+ ] })
3841
+ ] }),
3842
+ F === "grid" && /* @__PURE__ */ e.jsx("div", { className: "text-xs text-muted-foreground text-center py-2", children: _.gridOptionsHint })
3843
+ ] })
3844
+ ] })
3845
+ ] })
3846
+ ] }),
3847
+ /* @__PURE__ */ e.jsx(
3848
+ Fe,
3849
+ {
3850
+ isOpen: H.isOpen,
3851
+ title: H.title,
3852
+ message: H.message,
3853
+ onConfirm: H.onConfirm,
3854
+ onCancel: H.onCancel
3855
+ }
3856
+ )
3857
+ ]
3858
+ }
1080
3859
  );
1081
- return /* @__PURE__ */ e.jsx(ue.Provider, { value: E, children: w });
1082
3860
  }
1083
- function Le(l) {
1084
- const u = [
1085
- "#3b82f6",
1086
- "#ef4444",
1087
- "#22c55e",
1088
- "#f59e0b",
1089
- "#8b5cf6",
1090
- "#ec4899",
1091
- "#06b6d4",
1092
- "#f97316"
1093
- ];
1094
- let p = 0;
1095
- for (let w = 0; w < l.length; w++)
1096
- p = (p << 5) - p + l.charCodeAt(w) | 0;
1097
- return u[Math.abs(p) % u.length];
3861
+ function Ze(...s) {
3862
+ return pe(ue(s));
3863
+ }
3864
+ function wr({
3865
+ versions: s,
3866
+ onRestore: N,
3867
+ className: E
3868
+ }) {
3869
+ return /* @__PURE__ */ e.jsxs("div", { className: Ze("flex flex-col", E), role: "region", "aria-label": "Version history", children: [
3870
+ /* @__PURE__ */ e.jsxs("div", { className: "p-3 border-b font-medium text-sm flex items-center gap-2", children: [
3871
+ /* @__PURE__ */ e.jsx(Xt, { className: "h-4 w-4" }),
3872
+ "Version History"
3873
+ ] }),
3874
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto", children: s.length === 0 ? /* @__PURE__ */ e.jsx("div", { className: "p-3 text-xs text-muted-foreground text-center", children: "No version history available" }) : /* @__PURE__ */ e.jsxs("div", { className: "relative", children: [
3875
+ /* @__PURE__ */ e.jsx("div", { className: "absolute left-5 top-0 bottom-0 w-px bg-border" }),
3876
+ s.map((w) => /* @__PURE__ */ e.jsxs(
3877
+ "div",
3878
+ {
3879
+ className: Ze(
3880
+ "relative flex items-start gap-3 px-3 py-2 hover:bg-accent/50",
3881
+ w.isCurrent && "bg-accent/30"
3882
+ ),
3883
+ children: [
3884
+ /* @__PURE__ */ e.jsx("div", { className: Ze(
3885
+ "relative z-10 mt-1 h-2.5 w-2.5 rounded-full border-2 bg-background",
3886
+ w.isCurrent ? "border-primary" : "border-muted-foreground"
3887
+ ) }),
3888
+ /* @__PURE__ */ e.jsxs("div", { className: "flex-1 min-w-0", children: [
3889
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
3890
+ /* @__PURE__ */ e.jsxs("span", { className: "font-medium", children: [
3891
+ "v",
3892
+ w.version
3893
+ ] }),
3894
+ w.isCurrent && /* @__PURE__ */ e.jsx("span", { className: "px-1 py-0.5 rounded bg-primary/10 text-primary text-[0.6rem]", children: "Current" })
3895
+ ] }),
3896
+ /* @__PURE__ */ e.jsx("p", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: w.description }),
3897
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 mt-1 text-[0.65rem] text-muted-foreground/70", children: [
3898
+ /* @__PURE__ */ e.jsx(Kt, { className: "h-2.5 w-2.5" }),
3899
+ /* @__PURE__ */ e.jsx("span", { children: w.userName }),
3900
+ /* @__PURE__ */ e.jsx(dt, { className: "h-2.5 w-2.5 ml-1" }),
3901
+ /* @__PURE__ */ e.jsx("span", { children: new Date(w.timestamp).toLocaleString() })
3902
+ ] }),
3903
+ !w.isCurrent && N && /* @__PURE__ */ e.jsx(
3904
+ "button",
3905
+ {
3906
+ onClick: () => N(w.version),
3907
+ className: "mt-1 text-[0.65rem] text-primary hover:underline",
3908
+ children: "Restore this version"
3909
+ }
3910
+ )
3911
+ ] })
3912
+ ]
3913
+ },
3914
+ w.version
3915
+ ))
3916
+ ] }) })
3917
+ ] });
1098
3918
  }
1099
- G.register(
3919
+ Se.register(
1100
3920
  "page-designer",
1101
- Oe,
3921
+ sr,
1102
3922
  {
1103
3923
  label: "Page Designer",
1104
3924
  category: "Designer",
@@ -1111,9 +3931,9 @@ G.register(
1111
3931
  ]
1112
3932
  }
1113
3933
  );
1114
- G.register(
3934
+ Se.register(
1115
3935
  "data-model-designer",
1116
- ze,
3936
+ or,
1117
3937
  {
1118
3938
  label: "Data Model Designer",
1119
3939
  category: "Designer",
@@ -1125,9 +3945,9 @@ G.register(
1125
3945
  ]
1126
3946
  }
1127
3947
  );
1128
- G.register(
3948
+ Se.register(
1129
3949
  "process-designer",
1130
- Ie,
3950
+ ir,
1131
3951
  {
1132
3952
  label: "Process Designer (BPMN)",
1133
3953
  category: "Designer",
@@ -1141,9 +3961,9 @@ G.register(
1141
3961
  ]
1142
3962
  }
1143
3963
  );
1144
- G.register(
3964
+ Se.register(
1145
3965
  "report-designer",
1146
- Ge,
3966
+ ur,
1147
3967
  {
1148
3968
  label: "Report Designer",
1149
3969
  category: "Designer",
@@ -1157,10 +3977,36 @@ G.register(
1157
3977
  ]
1158
3978
  }
1159
3979
  );
3980
+ Se.register(
3981
+ "view-designer",
3982
+ mr,
3983
+ {
3984
+ label: "View Designer",
3985
+ category: "Designer",
3986
+ inputs: [
3987
+ { name: "objectName", type: "string", label: "Object Name" },
3988
+ { name: "viewId", type: "string", label: "View ID" },
3989
+ { name: "viewLabel", type: "string", label: "View Label" },
3990
+ { name: "viewType", type: "string", label: "View Type", defaultValue: "grid" },
3991
+ { name: "readOnly", type: "boolean", label: "Read Only", defaultValue: !1 }
3992
+ ]
3993
+ }
3994
+ );
1160
3995
  export {
1161
- qe as CollaborationProvider,
1162
- ze as DataModelDesigner,
1163
- Oe as PageDesigner,
1164
- Ie as ProcessDesigner,
1165
- Ge as ReportDesigner
3996
+ vr as CollaborationProvider,
3997
+ Fe as ConfirmDialog,
3998
+ yr as ConnectionStatusIndicator,
3999
+ or as DataModelDesigner,
4000
+ Be as Minimap,
4001
+ sr as PageDesigner,
4002
+ ir as ProcessDesigner,
4003
+ Ue as PropertyEditor,
4004
+ ur as ReportDesigner,
4005
+ wr as VersionHistory,
4006
+ mr as ViewDesigner,
4007
+ We as useCanvasPanZoom,
4008
+ Ie as useClipboard,
4009
+ Ae as useConfirmDialog,
4010
+ Le as useMultiSelect,
4011
+ Re as useUndoRedo
1166
4012
  };