@anvilkit/puck-studio 0.0.1 → 0.1.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.
@@ -0,0 +1,2090 @@
1
+ 'use strict';
2
+
3
+ var lucideReact = require('lucide-react');
4
+ var zustand = require('zustand');
5
+ var React6 = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var scrollArea = require('@base-ui/react/scroll-area');
8
+ var clsx = require('clsx');
9
+ var tailwindMerge = require('tailwind-merge');
10
+ var input = require('@base-ui/react/input');
11
+ var core = require('@puckeditor/core');
12
+ var separator = require('@base-ui/react/separator');
13
+ var tooltip = require('@base-ui/react/tooltip');
14
+ var mergeProps = require('@base-ui/react/merge-props');
15
+ var useRender = require('@base-ui/react/use-render');
16
+ var button = require('@base-ui/react/button');
17
+ var classVarianceAuthority = require('class-variance-authority');
18
+ var select = require('@base-ui/react/select');
19
+ var core$1 = require('@dnd-kit/core');
20
+ var sortable = require('@dnd-kit/sortable');
21
+ var utilities = require('@dnd-kit/utilities');
22
+ var popover = require('@base-ui/react/popover');
23
+ var react = require('motion/react');
24
+ var toggle = require('@base-ui/react/toggle');
25
+ var cmdk = require('cmdk');
26
+
27
+ function _interopNamespace(e) {
28
+ if (e && e.__esModule) return e;
29
+ var n = Object.create(null);
30
+ if (e) {
31
+ Object.keys(e).forEach(function (k) {
32
+ if (k !== 'default') {
33
+ var d = Object.getOwnPropertyDescriptor(e, k);
34
+ Object.defineProperty(n, k, d.get ? d : {
35
+ enumerable: true,
36
+ get: function () { return e[k]; }
37
+ });
38
+ }
39
+ });
40
+ }
41
+ n.default = e;
42
+ return Object.freeze(n);
43
+ }
44
+
45
+ var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
46
+
47
+ // src/core/overrides/layout/EditorDrawer.tsx
48
+ function getStrictContext(name) {
49
+ const Context = React6__namespace.createContext(void 0);
50
+ const Provider = ({
51
+ value,
52
+ children
53
+ }) => /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value, children });
54
+ const useSafeContext = () => {
55
+ const ctx = React6__namespace.useContext(Context);
56
+ if (ctx === void 0) {
57
+ throw new Error(`useContext must be used within ${name ?? "a Provider"}`);
58
+ }
59
+ return ctx;
60
+ };
61
+ return [Provider, useSafeContext];
62
+ }
63
+
64
+ // src/store/ui-context.ts
65
+ var [EditorUiStoreProvider, useEditorUiStoreApi] = getStrictContext("EditorUiStoreProvider");
66
+
67
+ // src/store/i18n-context.ts
68
+ var [EditorI18nStoreProvider, useEditorI18nStoreApi] = getStrictContext("EditorI18nStoreProvider");
69
+
70
+ // src/store/hooks.ts
71
+ function useDrawerSearch() {
72
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.drawerSearch);
73
+ }
74
+ function useSetDrawerSearch() {
75
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.setDrawerSearch);
76
+ }
77
+ function useTheme() {
78
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.theme);
79
+ }
80
+ function useMsg(key) {
81
+ return zustand.useStore(useEditorI18nStoreApi(), (s) => s.messages[key] ?? key);
82
+ }
83
+ function cn(...inputs) {
84
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
85
+ }
86
+ function ScrollArea({
87
+ className,
88
+ children,
89
+ ...props
90
+ }) {
91
+ return /* @__PURE__ */ jsxRuntime.jsxs(
92
+ scrollArea.ScrollArea.Root,
93
+ {
94
+ "data-slot": "scroll-area",
95
+ className: cn("relative", className),
96
+ ...props,
97
+ children: [
98
+ /* @__PURE__ */ jsxRuntime.jsx(
99
+ scrollArea.ScrollArea.Viewport,
100
+ {
101
+ "data-slot": "scroll-area-viewport",
102
+ className: "size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1",
103
+ children
104
+ }
105
+ ),
106
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollBar, {}),
107
+ /* @__PURE__ */ jsxRuntime.jsx(scrollArea.ScrollArea.Corner, {})
108
+ ]
109
+ }
110
+ );
111
+ }
112
+ function ScrollBar({
113
+ className,
114
+ orientation = "vertical",
115
+ ...props
116
+ }) {
117
+ return /* @__PURE__ */ jsxRuntime.jsx(
118
+ scrollArea.ScrollArea.Scrollbar,
119
+ {
120
+ "data-slot": "scroll-area-scrollbar",
121
+ "data-orientation": orientation,
122
+ orientation,
123
+ className: cn(
124
+ "flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent",
125
+ className
126
+ ),
127
+ ...props,
128
+ children: /* @__PURE__ */ jsxRuntime.jsx(
129
+ scrollArea.ScrollArea.Thumb,
130
+ {
131
+ "data-slot": "scroll-area-thumb",
132
+ className: "relative flex-1 rounded-full bg-border"
133
+ }
134
+ )
135
+ }
136
+ );
137
+ }
138
+ function Input({ className, type, ...props }) {
139
+ return /* @__PURE__ */ jsxRuntime.jsx(
140
+ input.Input,
141
+ {
142
+ type,
143
+ "data-slot": "input",
144
+ className: cn(
145
+ "h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-2.5 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
146
+ className
147
+ ),
148
+ ...props
149
+ }
150
+ );
151
+ }
152
+ function EditorDrawer({
153
+ children
154
+ }) {
155
+ const search = useDrawerSearch();
156
+ const setSearch = useSetDrawerSearch();
157
+ const drawerTitle = useMsg("drawer.title");
158
+ const searchPlaceholder = useMsg("drawer.search.placeholder");
159
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
160
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pt-3 pb-1 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: drawerTitle }),
161
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
162
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
163
+ /* @__PURE__ */ jsxRuntime.jsx(
164
+ Input,
165
+ {
166
+ className: "pl-8",
167
+ placeholder: searchPlaceholder,
168
+ value: search,
169
+ onChange: (e) => setSearch(e.target.value)
170
+ }
171
+ )
172
+ ] }) }),
173
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children })
174
+ ] });
175
+ }
176
+ function EditorComponents({
177
+ children
178
+ }) {
179
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-puck-components-grid": true, className: "p-2", children: [
180
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
181
+ [data-puck-components-grid] [data-puck-drawer] {
182
+ display: grid;
183
+ grid-template-columns: repeat(3, minmax(0, 1fr));
184
+ gap: 6px;
185
+ }
186
+ /* flatten item wrapper and draggable wrapper */
187
+ [data-puck-components-grid] [data-puck-drawer] > div,
188
+ [data-puck-components-grid] [data-puck-drawer] > div > div {
189
+ display: contents;
190
+ }
191
+ /* hide the ghost/bg copy */
192
+ [data-puck-components-grid] [data-puck-drawer] > div > div > div:first-child {
193
+ display: none;
194
+ }
195
+ /* flatten the real draggable wrapper */
196
+ [data-puck-components-grid] [data-puck-drawer] > div > div > div:last-child {
197
+ display: contents;
198
+ }
199
+ ` }),
200
+ children
201
+ ] });
202
+ }
203
+ function getPlaceholderUrl(name) {
204
+ return `https://picsum.photos/seed/${encodeURIComponent(name)}/120/80`;
205
+ }
206
+ function DrawerItem({
207
+ children,
208
+ name
209
+ }) {
210
+ const { config } = core.usePuck();
211
+ const componentConfig = config.components?.[name];
212
+ const thumbnail = typeof componentConfig?.metadata?.thumbnail === "string" ? componentConfig.metadata.thumbnail : void 0;
213
+ const src = thumbnail ?? getPlaceholderUrl(name);
214
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col rounded-md border border-border bg-muted/40 cursor-grab select-none transition-colors hover:bg-muted active:cursor-grabbing overflow-hidden", children: [
215
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-16 bg-muted overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
216
+ "img",
217
+ {
218
+ src,
219
+ alt: name,
220
+ className: "w-full h-full object-cover",
221
+ onError: (e) => {
222
+ e.currentTarget.style.display = "none";
223
+ }
224
+ }
225
+ ) }),
226
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5 text-xs font-medium truncate", children: name ?? children })
227
+ ] });
228
+ }
229
+ function Separator({
230
+ className,
231
+ orientation = "horizontal",
232
+ ...props
233
+ }) {
234
+ return /* @__PURE__ */ jsxRuntime.jsx(
235
+ separator.Separator,
236
+ {
237
+ "data-slot": "separator",
238
+ orientation,
239
+ className: cn(
240
+ "shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
241
+ className
242
+ ),
243
+ ...props
244
+ }
245
+ );
246
+ }
247
+ function EditorOutline({
248
+ children
249
+ }) {
250
+ const { selectedItem } = core.usePuck();
251
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col", children: [
252
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wide", children: "Outline" }) }),
253
+ selectedItem && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
254
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-1.5 text-xs text-muted-foreground truncate", children: [
255
+ "Selected:",
256
+ " ",
257
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: typeof selectedItem.type === "string" ? selectedItem.type : String(selectedItem.type) })
258
+ ] }),
259
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, {})
260
+ ] }),
261
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm", children }) })
262
+ ] });
263
+ }
264
+ var CANVAS_CSS = `
265
+ *, *::before, *::after { box-sizing: border-box; }
266
+ :root {
267
+ --background: 0 0% 100%;
268
+ --foreground: 222.2 84% 4.9%;
269
+ --primary: 222.2 47.4% 11.2%;
270
+ --primary-foreground: 210 40% 98%;
271
+ --secondary: 210 40% 96.1%;
272
+ --muted: 210 40% 96.1%;
273
+ --muted-foreground: 215.4 16.3% 46.9%;
274
+ --border: 214.3 31.8% 91.4%;
275
+ --radius: 0.5rem;
276
+ }
277
+ .dark {
278
+ --background: 222.2 84% 4.9%;
279
+ --foreground: 210 40% 98%;
280
+ --primary: 210 40% 98%;
281
+ --primary-foreground: 222.2 47.4% 11.2%;
282
+ --secondary: 217.2 32.6% 17.5%;
283
+ --muted: 217.2 32.6% 17.5%;
284
+ --muted-foreground: 215 20.2% 65.1%;
285
+ --border: 217.2 32.6% 17.5%;
286
+ }
287
+ body { margin: 0; font-family: system-ui, sans-serif; }
288
+ `;
289
+ var CANVAS_STYLE_ID = "__anvilkit_styles__";
290
+ function resolveDocument(target) {
291
+ if (target) return target;
292
+ if (typeof document === "undefined") return void 0;
293
+ return document;
294
+ }
295
+ function useThemeSync({
296
+ document: targetDocument,
297
+ injectCanvasCss = false
298
+ } = {}) {
299
+ const theme = useTheme();
300
+ React6__namespace.useEffect(() => {
301
+ const resolvedDocument = resolveDocument(targetDocument);
302
+ if (!resolvedDocument || !injectCanvasCss) return;
303
+ const existing = resolvedDocument.getElementById(CANVAS_STYLE_ID);
304
+ if (existing) existing.remove();
305
+ const style = resolvedDocument.createElement("style");
306
+ style.id = CANVAS_STYLE_ID;
307
+ style.textContent = CANVAS_CSS;
308
+ resolvedDocument.head.appendChild(style);
309
+ }, [targetDocument, injectCanvasCss]);
310
+ React6__namespace.useEffect(() => {
311
+ const resolvedDocument = resolveDocument(targetDocument);
312
+ if (!resolvedDocument) return;
313
+ resolvedDocument.documentElement.classList.toggle("dark", theme === "dark");
314
+ }, [targetDocument, theme]);
315
+ }
316
+
317
+ // src/features/library-dnd/drop-contract.ts
318
+ var LIBRARY_DRAG_START = "anvilkit:librarydragstart";
319
+ var IMAGE_DROP = "anvilkit:imagedrop";
320
+ var TEXT_DROP = "anvilkit:textdrop";
321
+ function addLibraryDragEventListener(type, listener, target = window) {
322
+ const wrapped = (event) => {
323
+ listener(event);
324
+ };
325
+ target.addEventListener(type, wrapped);
326
+ return () => {
327
+ target.removeEventListener(type, wrapped);
328
+ };
329
+ }
330
+
331
+ // src/features/library-dnd/replace-props.ts
332
+ function isImageUrl(val) {
333
+ return /\.(jpg|jpeg|png|gif|webp|svg|avif)(\?.*)?$/i.test(val) || val.includes("picsum.photos") || val.includes("unsplash.com") || val.includes("images.") || val.startsWith("data:image/");
334
+ }
335
+ function replaceImageInProps(props, newSrc) {
336
+ const result = {};
337
+ for (const key of Object.keys(props)) {
338
+ const val = props[key];
339
+ if (typeof val === "string" && isImageUrl(val)) {
340
+ result[key] = newSrc;
341
+ } else if (Array.isArray(val)) {
342
+ result[key] = val.map(
343
+ (item) => item && typeof item === "object" ? replaceImageInProps(item, newSrc) : item
344
+ );
345
+ } else if (val && typeof val === "object") {
346
+ result[key] = replaceImageInProps(val, newSrc);
347
+ } else {
348
+ result[key] = val;
349
+ }
350
+ }
351
+ return result;
352
+ }
353
+ function replaceTextInProps(props, newText, targetText) {
354
+ for (const key of Object.keys(props)) {
355
+ if (key === "id") continue;
356
+ const val = props[key];
357
+ if (typeof val === "string" && val === targetText && !isImageUrl(val)) {
358
+ return { result: { ...props, [key]: newText }, replaced: true };
359
+ }
360
+ }
361
+ for (const key of Object.keys(props)) {
362
+ if (key === "id") continue;
363
+ const val = props[key];
364
+ if (typeof val === "string" && !isImageUrl(val) && val.length > 0) {
365
+ return { result: { ...props, [key]: newText }, replaced: true };
366
+ }
367
+ }
368
+ return { result: props, replaced: false };
369
+ }
370
+
371
+ // src/core/overrides/canvas/drop-targets.ts
372
+ var TEXT_TAGS = /* @__PURE__ */ new Set([
373
+ "P",
374
+ "H1",
375
+ "H2",
376
+ "H3",
377
+ "H4",
378
+ "H5",
379
+ "H6",
380
+ "SPAN",
381
+ "A",
382
+ "LI",
383
+ "BUTTON",
384
+ "LABEL"
385
+ ]);
386
+ function getIframeCoords(iframeEl, clientX, clientY) {
387
+ const rect = iframeEl.getBoundingClientRect();
388
+ const x = clientX - rect.left;
389
+ const y = clientY - rect.top;
390
+ if (x < 0 || y < 0 || x > rect.width || y > rect.height) {
391
+ return null;
392
+ }
393
+ return { x, y };
394
+ }
395
+ function getComponentElAt(iframeDoc, iframeEl, clientX, clientY) {
396
+ const coords = getIframeCoords(iframeEl, clientX, clientY);
397
+ if (!coords) return null;
398
+ const element = iframeDoc.elementFromPoint(coords.x, coords.y);
399
+ if (!element) return null;
400
+ return element.closest("[data-puck-component]");
401
+ }
402
+ function getImageElInComponent(compEl, iframeEl, clientX, clientY) {
403
+ const images = Array.from(compEl.querySelectorAll("img"));
404
+ if (!images.length) return null;
405
+ if (images.length === 1) return images[0];
406
+ const rect = iframeEl.getBoundingClientRect();
407
+ const x = clientX - rect.left;
408
+ const y = clientY - rect.top;
409
+ let closest = null;
410
+ let minDistance = Infinity;
411
+ for (const image of images) {
412
+ const imageRect = image.getBoundingClientRect();
413
+ const centerX = imageRect.left + imageRect.width / 2;
414
+ const centerY = imageRect.top + imageRect.height / 2;
415
+ const distance = Math.hypot(centerX - x, centerY - y);
416
+ if (distance < minDistance) {
417
+ minDistance = distance;
418
+ closest = image;
419
+ }
420
+ }
421
+ return closest;
422
+ }
423
+ function getTextElInComponent(iframeDoc, iframeEl, compEl, clientX, clientY) {
424
+ const coords = getIframeCoords(iframeEl, clientX, clientY);
425
+ if (!coords) return null;
426
+ const element = iframeDoc.elementFromPoint(coords.x, coords.y);
427
+ if (element && compEl.contains(element)) {
428
+ let current = element;
429
+ while (current && current !== iframeDoc.body) {
430
+ if (TEXT_TAGS.has(current.tagName) && current.textContent?.trim()) {
431
+ return current;
432
+ }
433
+ current = current.parentElement;
434
+ }
435
+ }
436
+ for (const tag of TEXT_TAGS) {
437
+ const candidate = compEl.querySelector(tag.toLowerCase());
438
+ if (candidate?.textContent?.trim()) {
439
+ return candidate;
440
+ }
441
+ }
442
+ return null;
443
+ }
444
+
445
+ // src/core/overrides/canvas/highlight.ts
446
+ function createElementHighlighter() {
447
+ let highlightedEl = null;
448
+ function set(el, color) {
449
+ if (highlightedEl && highlightedEl !== el) {
450
+ highlightedEl.style.outline = "";
451
+ highlightedEl.style.outlineOffset = "";
452
+ }
453
+ if (el) {
454
+ el.style.outline = `2px solid ${color}`;
455
+ el.style.outlineOffset = "2px";
456
+ }
457
+ highlightedEl = el;
458
+ }
459
+ function clear() {
460
+ set(null, "");
461
+ }
462
+ return { set, clear };
463
+ }
464
+
465
+ // src/core/overrides/canvas/useLibraryDropBridge.ts
466
+ function useLibraryDropBridge(iframeDoc) {
467
+ const getPuck = core.useGetPuck();
468
+ React6__namespace.useEffect(() => {
469
+ if (!iframeDoc) return;
470
+ const iframeEl = iframeDoc.defaultView?.frameElement;
471
+ if (!iframeEl) return;
472
+ const iframeDocument = iframeDoc;
473
+ const frameElement = iframeEl;
474
+ let activeLibrary = null;
475
+ const highlighter = createElementHighlighter();
476
+ function dispatchReplace(componentId, updatedProps) {
477
+ const { dispatch, getItemById, getSelectorForId } = getPuck();
478
+ const item = getItemById(componentId);
479
+ const selector = getSelectorForId(componentId);
480
+ if (!item || !selector) return false;
481
+ dispatch({
482
+ type: "replace",
483
+ destinationIndex: selector.index,
484
+ destinationZone: selector.zone,
485
+ data: {
486
+ ...item,
487
+ props: { ...item.props, ...updatedProps }
488
+ }
489
+ });
490
+ return true;
491
+ }
492
+ function onLibraryDragStart(type) {
493
+ activeLibrary = type;
494
+ }
495
+ function onPointerMove(e) {
496
+ if (!activeLibrary) return;
497
+ const compEl = getComponentElAt(iframeDocument, frameElement, e.clientX, e.clientY);
498
+ if (!compEl) {
499
+ highlighter.clear();
500
+ return;
501
+ }
502
+ if (activeLibrary === "image") {
503
+ highlighter.set(
504
+ getImageElInComponent(compEl, frameElement, e.clientX, e.clientY),
505
+ "#6366f1"
506
+ );
507
+ } else {
508
+ highlighter.set(
509
+ getTextElInComponent(iframeDocument, frameElement, compEl, e.clientX, e.clientY),
510
+ "#f59e0b"
511
+ );
512
+ }
513
+ }
514
+ function onPointerUp() {
515
+ activeLibrary = null;
516
+ highlighter.clear();
517
+ }
518
+ function onImageDrop(src, clientX, clientY) {
519
+ highlighter.clear();
520
+ activeLibrary = null;
521
+ if (!src) return;
522
+ const compEl = getComponentElAt(iframeDocument, frameElement, clientX, clientY);
523
+ if (!compEl) return;
524
+ const componentId = compEl.dataset.puckComponent;
525
+ if (!componentId) return;
526
+ const item = getPuck().getItemById(componentId);
527
+ if (!item) return;
528
+ const updatedProps = replaceImageInProps(
529
+ item.props,
530
+ src
531
+ );
532
+ dispatchReplace(componentId, updatedProps);
533
+ }
534
+ function onTextDrop(text, clientX, clientY) {
535
+ highlighter.clear();
536
+ activeLibrary = null;
537
+ if (!text) return;
538
+ const compEl = getComponentElAt(iframeDocument, frameElement, clientX, clientY);
539
+ if (!compEl) return;
540
+ const componentId = compEl.dataset.puckComponent;
541
+ if (!componentId) return;
542
+ const textEl = getTextElInComponent(
543
+ iframeDocument,
544
+ frameElement,
545
+ compEl,
546
+ clientX,
547
+ clientY
548
+ );
549
+ const targetText = textEl?.textContent?.trim() ?? "";
550
+ const item = getPuck().getItemById(componentId);
551
+ if (!item) return;
552
+ const { result: updatedProps, replaced } = replaceTextInProps(
553
+ item.props,
554
+ text,
555
+ targetText
556
+ );
557
+ if (replaced) dispatchReplace(componentId, updatedProps);
558
+ }
559
+ const removeLibraryDragStart = addLibraryDragEventListener(
560
+ LIBRARY_DRAG_START,
561
+ (event) => {
562
+ onLibraryDragStart(event.detail.type);
563
+ }
564
+ );
565
+ window.addEventListener("pointermove", onPointerMove);
566
+ window.addEventListener("pointerup", onPointerUp);
567
+ const removeImageDrop = addLibraryDragEventListener(IMAGE_DROP, (event) => {
568
+ const { src, clientX, clientY } = event.detail;
569
+ onImageDrop(src, clientX, clientY);
570
+ });
571
+ const removeTextDrop = addLibraryDragEventListener(TEXT_DROP, (event) => {
572
+ const { text, clientX, clientY } = event.detail;
573
+ onTextDrop(text, clientX, clientY);
574
+ });
575
+ return () => {
576
+ removeLibraryDragStart();
577
+ window.removeEventListener("pointermove", onPointerMove);
578
+ window.removeEventListener("pointerup", onPointerUp);
579
+ removeImageDrop();
580
+ removeTextDrop();
581
+ highlighter.clear();
582
+ };
583
+ }, [iframeDoc, getPuck]);
584
+ }
585
+ function CanvasIframe({
586
+ children,
587
+ document: iframeDoc
588
+ }) {
589
+ useThemeSync({ document: iframeDoc, injectCanvasCss: true });
590
+ useLibraryDropBridge(iframeDoc);
591
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
592
+ }
593
+ function CanvasPreview({
594
+ children
595
+ }) {
596
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full px-3 py-2 text-sm font-medium text-foreground", children });
597
+ }
598
+ function ComponentOverlay({
599
+ children,
600
+ hover,
601
+ isSelected
602
+ }) {
603
+ return /* @__PURE__ */ jsxRuntime.jsx(
604
+ "div",
605
+ {
606
+ className: [
607
+ "absolute inset-0 rounded-sm pointer-events-none z-10 transition-colors",
608
+ isSelected ? "border-2 border-primary/80" : hover ? "border-2 border-primary/40" : ""
609
+ ].filter(Boolean).join(" "),
610
+ children
611
+ }
612
+ );
613
+ }
614
+ function TooltipProvider({
615
+ delay = 0,
616
+ ...props
617
+ }) {
618
+ return /* @__PURE__ */ jsxRuntime.jsx(
619
+ tooltip.Tooltip.Provider,
620
+ {
621
+ "data-slot": "tooltip-provider",
622
+ delay,
623
+ ...props
624
+ }
625
+ );
626
+ }
627
+ function Tooltip({ ...props }) {
628
+ return /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Root, { "data-slot": "tooltip", ...props });
629
+ }
630
+ function TooltipTrigger({ ...props }) {
631
+ return /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Trigger, { "data-slot": "tooltip-trigger", ...props });
632
+ }
633
+ function TooltipContent({
634
+ className,
635
+ side = "top",
636
+ sideOffset = 4,
637
+ align = "center",
638
+ alignOffset = 0,
639
+ children,
640
+ ...props
641
+ }) {
642
+ return /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
643
+ tooltip.Tooltip.Positioner,
644
+ {
645
+ align,
646
+ alignOffset,
647
+ side,
648
+ sideOffset,
649
+ className: "isolate z-50",
650
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
651
+ tooltip.Tooltip.Popup,
652
+ {
653
+ "data-slot": "tooltip-content",
654
+ className: cn(
655
+ "z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
656
+ className
657
+ ),
658
+ ...props,
659
+ children: [
660
+ children,
661
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" })
662
+ ]
663
+ }
664
+ )
665
+ }
666
+ ) });
667
+ }
668
+ function ActionBar({
669
+ children,
670
+ label,
671
+ parentAction
672
+ }) {
673
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5 rounded-md border bg-background shadow-md px-1 py-0.5", children: [
674
+ label && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
675
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 text-xs font-medium text-muted-foreground truncate max-w-[120px]", children: label }),
676
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5" })
677
+ ] }),
678
+ parentAction && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
679
+ parentAction,
680
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5" })
681
+ ] }),
682
+ children
683
+ ] }) });
684
+ }
685
+ function Label({ className, ...props }) {
686
+ return /* @__PURE__ */ jsxRuntime.jsx(
687
+ "label",
688
+ {
689
+ "data-slot": "label",
690
+ className: cn(
691
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
692
+ className
693
+ ),
694
+ ...props
695
+ }
696
+ );
697
+ }
698
+ function Breadcrumb({ className, ...props }) {
699
+ return /* @__PURE__ */ jsxRuntime.jsx(
700
+ "nav",
701
+ {
702
+ "aria-label": "breadcrumb",
703
+ "data-slot": "breadcrumb",
704
+ className: cn(className),
705
+ ...props
706
+ }
707
+ );
708
+ }
709
+ function BreadcrumbList({ className, ...props }) {
710
+ return /* @__PURE__ */ jsxRuntime.jsx(
711
+ "ol",
712
+ {
713
+ "data-slot": "breadcrumb-list",
714
+ className: cn(
715
+ "flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground sm:gap-2.5",
716
+ className
717
+ ),
718
+ ...props
719
+ }
720
+ );
721
+ }
722
+ function BreadcrumbItem({ className, ...props }) {
723
+ return /* @__PURE__ */ jsxRuntime.jsx(
724
+ "li",
725
+ {
726
+ "data-slot": "breadcrumb-item",
727
+ className: cn("inline-flex items-center gap-1.5", className),
728
+ ...props
729
+ }
730
+ );
731
+ }
732
+ function BreadcrumbLink({
733
+ className,
734
+ render,
735
+ ...props
736
+ }) {
737
+ return useRender.useRender({
738
+ defaultTagName: "a",
739
+ props: mergeProps.mergeProps(
740
+ {
741
+ className: cn("transition-colors hover:text-foreground", className)
742
+ },
743
+ props
744
+ ),
745
+ render,
746
+ state: {
747
+ slot: "breadcrumb-link"
748
+ }
749
+ });
750
+ }
751
+ function BreadcrumbPage({ className, ...props }) {
752
+ return /* @__PURE__ */ jsxRuntime.jsx(
753
+ "span",
754
+ {
755
+ "data-slot": "breadcrumb-page",
756
+ role: "link",
757
+ "aria-disabled": "true",
758
+ "aria-current": "page",
759
+ className: cn("font-normal text-foreground", className),
760
+ ...props
761
+ }
762
+ );
763
+ }
764
+ function BreadcrumbSeparator({
765
+ children,
766
+ className,
767
+ ...props
768
+ }) {
769
+ return /* @__PURE__ */ jsxRuntime.jsx(
770
+ "li",
771
+ {
772
+ "data-slot": "breadcrumb-separator",
773
+ role: "presentation",
774
+ "aria-hidden": "true",
775
+ className: cn("[&>svg]:size-3.5", className),
776
+ ...props,
777
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, {})
778
+ }
779
+ );
780
+ }
781
+ function getComponentTypeLabel(item) {
782
+ if (!item) return "Component";
783
+ return typeof item.type === "string" ? item.type : String(item.type);
784
+ }
785
+ function getComponentId(item) {
786
+ const id = item?.props?.id;
787
+ return typeof id === "string" ? id : null;
788
+ }
789
+ function useBreadcrumbs() {
790
+ const { appState, dispatch, selectedItem, getParentById } = core.usePuck();
791
+ const { itemSelector } = appState.ui;
792
+ const selectRoot = () => dispatch({ type: "setUi", ui: { itemSelector: null } });
793
+ if (!itemSelector || !selectedItem) {
794
+ return [{ label: "Page" }];
795
+ }
796
+ const selectedType = getComponentTypeLabel(selectedItem);
797
+ const parentId = getComponentId(selectedItem);
798
+ const parent = parentId ? getParentById(parentId) : void 0;
799
+ if (!parent) {
800
+ return [{ label: "Page", onSelect: selectRoot }, { label: selectedType }];
801
+ }
802
+ const parentType = getComponentTypeLabel(parent);
803
+ return [
804
+ { label: "Page", onSelect: selectRoot },
805
+ { label: parentType },
806
+ { label: selectedType }
807
+ ];
808
+ }
809
+ function FieldWrapper({
810
+ children
811
+ }) {
812
+ const crumbs = useBreadcrumbs();
813
+ return /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "h-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0", children: [
814
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ jsxRuntime.jsx(Breadcrumb, { children: /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbList, { children: crumbs.map((crumb, i) => {
815
+ const isLast = i === crumbs.length - 1;
816
+ return /* @__PURE__ */ jsxRuntime.jsxs(React6__namespace.Fragment, { children: [
817
+ i > 0 && /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbSeparator, {}),
818
+ /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbItem, { children: isLast ? /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbPage, { children: crumb.label }) : /* @__PURE__ */ jsxRuntime.jsx(
819
+ BreadcrumbLink,
820
+ {
821
+ className: "cursor-pointer",
822
+ onClick: crumb.onSelect,
823
+ children: crumb.label
824
+ }
825
+ ) })
826
+ ] }, i);
827
+ }) }) }) }),
828
+ children
829
+ ] }) });
830
+ }
831
+ function FieldLabel({
832
+ children,
833
+ label,
834
+ icon,
835
+ labelIcon,
836
+ el,
837
+ readOnly,
838
+ className
839
+ }) {
840
+ const El = el ?? "div";
841
+ const labelAdornment = icon ?? labelIcon;
842
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(El, { className: `flex flex-col gap-1.5 ${className ?? ""}`, children: [
843
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
844
+ labelAdornment && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: labelAdornment }),
845
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-medium text-muted-foreground", children: label }),
846
+ label && /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
847
+ /* @__PURE__ */ jsxRuntime.jsx(
848
+ TooltipTrigger,
849
+ {
850
+ "aria-label": label,
851
+ render: /* @__PURE__ */ jsxRuntime.jsx(
852
+ "button",
853
+ {
854
+ type: "button",
855
+ className: "inline-flex cursor-help items-center justify-center text-muted-foreground/60 transition-colors hover:text-muted-foreground"
856
+ }
857
+ ),
858
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: "h-3 w-3 text-muted-foreground/60 cursor-help" })
859
+ }
860
+ ),
861
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "right", children: label })
862
+ ] }),
863
+ readOnly && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-muted-foreground/50", children: "Read only" })
864
+ ] }),
865
+ children
866
+ ] }) });
867
+ }
868
+ var buttonVariants = classVarianceAuthority.cva(
869
+ "group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
870
+ {
871
+ variants: {
872
+ variant: {
873
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
874
+ outline: "border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
875
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
876
+ ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
877
+ destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
878
+ link: "text-primary underline-offset-4 hover:underline"
879
+ },
880
+ size: {
881
+ default: "h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
882
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
883
+ sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
884
+ lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
885
+ icon: "size-9",
886
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
887
+ "icon-sm": "size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
888
+ "icon-lg": "size-10"
889
+ }
890
+ },
891
+ defaultVariants: {
892
+ variant: "default",
893
+ size: "default"
894
+ }
895
+ }
896
+ );
897
+ function Button({
898
+ className,
899
+ variant = "default",
900
+ size = "default",
901
+ ...props
902
+ }) {
903
+ return /* @__PURE__ */ jsxRuntime.jsx(
904
+ button.Button,
905
+ {
906
+ "data-slot": "button",
907
+ className: cn(buttonVariants({ variant, size, className })),
908
+ ...props
909
+ }
910
+ );
911
+ }
912
+ var MOCK_VALUES = {
913
+ default: ["AI-generated content", "Smart suggestion", "Generated text"]
914
+ };
915
+ function getMock(instructions) {
916
+ if (instructions?.toLowerCase().includes("caps")) {
917
+ return "AI GENERATED TITLE";
918
+ }
919
+ const pool = MOCK_VALUES.default;
920
+ return pool[Math.floor(Math.random() * pool.length)];
921
+ }
922
+ function AiButton({ ai, onGenerate }) {
923
+ const [loading, setLoading] = React6__namespace.useState(false);
924
+ const handleClick = () => {
925
+ setLoading(true);
926
+ setTimeout(() => {
927
+ onGenerate(getMock(ai.instructions));
928
+ setLoading(false);
929
+ }, 600);
930
+ };
931
+ return /* @__PURE__ */ jsxRuntime.jsx(
932
+ Button,
933
+ {
934
+ type: "button",
935
+ variant: "outline",
936
+ size: "icon",
937
+ className: "h-8 w-8 shrink-0 text-muted-foreground hover:text-primary",
938
+ onClick: handleClick,
939
+ disabled: loading,
940
+ "aria-label": "Generate with AI",
941
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: `h-3.5 w-3.5 ${loading ? "animate-pulse" : ""}` })
942
+ }
943
+ );
944
+ }
945
+ function TextField({
946
+ field,
947
+ value,
948
+ onChange,
949
+ readOnly,
950
+ placeholder,
951
+ label,
952
+ labelIcon
953
+ }) {
954
+ const [local, setLocal] = React6__namespace.useState(value ?? "");
955
+ const onChangeRef = React6__namespace.useRef(onChange);
956
+ const lastCommittedValueRef = React6__namespace.useRef(value ?? "");
957
+ React6__namespace.useEffect(() => {
958
+ onChangeRef.current = onChange;
959
+ }, [onChange]);
960
+ React6__namespace.useEffect(() => {
961
+ lastCommittedValueRef.current = value ?? "";
962
+ setLocal(value ?? "");
963
+ }, [value]);
964
+ React6__namespace.useEffect(() => {
965
+ const timer = setTimeout(() => {
966
+ if (local !== lastCommittedValueRef.current) {
967
+ onChangeRef.current(local);
968
+ lastCommittedValueRef.current = local;
969
+ }
970
+ }, 200);
971
+ return () => clearTimeout(timer);
972
+ }, [local]);
973
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", labelIcon, readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
974
+ /* @__PURE__ */ jsxRuntime.jsx(
975
+ Input,
976
+ {
977
+ value: local,
978
+ onChange: (e) => setLocal(e.target.value),
979
+ readOnly,
980
+ placeholder,
981
+ className: "h-8 text-sm flex-1"
982
+ }
983
+ ),
984
+ field?.ai && /* @__PURE__ */ jsxRuntime.jsx(
985
+ AiButton,
986
+ {
987
+ ai: field.ai,
988
+ onGenerate: (nextValue) => {
989
+ lastCommittedValueRef.current = nextValue;
990
+ setLocal(nextValue);
991
+ onChangeRef.current(nextValue);
992
+ }
993
+ }
994
+ )
995
+ ] }) });
996
+ }
997
+ function Textarea({ className, ...props }) {
998
+ return /* @__PURE__ */ jsxRuntime.jsx(
999
+ "textarea",
1000
+ {
1001
+ "data-slot": "textarea",
1002
+ className: cn(
1003
+ "flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-2.5 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
1004
+ className
1005
+ ),
1006
+ ...props
1007
+ }
1008
+ );
1009
+ }
1010
+ function TextareaField({ value, onChange, readOnly, placeholder, label }) {
1011
+ const [local, setLocal] = React6__namespace.useState(value ?? "");
1012
+ React6__namespace.useEffect(() => {
1013
+ setLocal(value ?? "");
1014
+ }, [value]);
1015
+ React6__namespace.useEffect(() => {
1016
+ const timer = setTimeout(() => {
1017
+ if (local !== value) onChange(local);
1018
+ }, 200);
1019
+ return () => clearTimeout(timer);
1020
+ }, [local]);
1021
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsx(
1022
+ Textarea,
1023
+ {
1024
+ value: local,
1025
+ onChange: (e) => setLocal(e.target.value),
1026
+ readOnly,
1027
+ placeholder,
1028
+ className: "min-h-[80px] text-sm resize-y"
1029
+ }
1030
+ ) });
1031
+ }
1032
+ function NumberField({ value, onChange, readOnly, min, max, step, label }) {
1033
+ const [local, setLocal] = React6__namespace.useState(String(value ?? ""));
1034
+ React6__namespace.useEffect(() => {
1035
+ setLocal(String(value ?? ""));
1036
+ }, [value]);
1037
+ React6__namespace.useEffect(() => {
1038
+ const parsed = parseFloat(local);
1039
+ if (!isNaN(parsed) && parsed !== value) {
1040
+ const timer = setTimeout(() => onChange(parsed), 200);
1041
+ return () => clearTimeout(timer);
1042
+ }
1043
+ }, [local]);
1044
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsx(
1045
+ Input,
1046
+ {
1047
+ type: "number",
1048
+ value: local,
1049
+ onChange: (e) => setLocal(e.target.value),
1050
+ readOnly,
1051
+ min,
1052
+ max,
1053
+ step,
1054
+ className: "h-8 text-sm"
1055
+ }
1056
+ ) });
1057
+ }
1058
+ var Select = select.Select.Root;
1059
+ function SelectGroup({ className, ...props }) {
1060
+ return /* @__PURE__ */ jsxRuntime.jsx(
1061
+ select.Select.Group,
1062
+ {
1063
+ "data-slot": "select-group",
1064
+ className: cn("scroll-my-1 p-1", className),
1065
+ ...props
1066
+ }
1067
+ );
1068
+ }
1069
+ function SelectValue({ className, ...props }) {
1070
+ return /* @__PURE__ */ jsxRuntime.jsx(
1071
+ select.Select.Value,
1072
+ {
1073
+ "data-slot": "select-value",
1074
+ className: cn("flex flex-1 text-left", className),
1075
+ ...props
1076
+ }
1077
+ );
1078
+ }
1079
+ function SelectTrigger({
1080
+ className,
1081
+ size = "default",
1082
+ children,
1083
+ ...props
1084
+ }) {
1085
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1086
+ select.Select.Trigger,
1087
+ {
1088
+ "data-slot": "select-trigger",
1089
+ "data-size": size,
1090
+ className: cn(
1091
+ "flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1092
+ className
1093
+ ),
1094
+ ...props,
1095
+ children: [
1096
+ children,
1097
+ /* @__PURE__ */ jsxRuntime.jsx(
1098
+ select.Select.Icon,
1099
+ {
1100
+ render: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: "pointer-events-none size-4 text-muted-foreground" })
1101
+ }
1102
+ )
1103
+ ]
1104
+ }
1105
+ );
1106
+ }
1107
+ function SelectContent({
1108
+ className,
1109
+ children,
1110
+ side = "bottom",
1111
+ sideOffset = 4,
1112
+ align = "center",
1113
+ alignOffset = 0,
1114
+ alignItemWithTrigger = true,
1115
+ ...props
1116
+ }) {
1117
+ return /* @__PURE__ */ jsxRuntime.jsx(select.Select.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1118
+ select.Select.Positioner,
1119
+ {
1120
+ side,
1121
+ sideOffset,
1122
+ align,
1123
+ alignOffset,
1124
+ alignItemWithTrigger,
1125
+ className: "isolate z-50",
1126
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1127
+ select.Select.Popup,
1128
+ {
1129
+ "data-slot": "select-content",
1130
+ "data-align-trigger": alignItemWithTrigger,
1131
+ className: cn("relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
1132
+ ...props,
1133
+ children: [
1134
+ /* @__PURE__ */ jsxRuntime.jsx(SelectScrollUpButton, {}),
1135
+ /* @__PURE__ */ jsxRuntime.jsx(select.Select.List, { children }),
1136
+ /* @__PURE__ */ jsxRuntime.jsx(SelectScrollDownButton, {})
1137
+ ]
1138
+ }
1139
+ )
1140
+ }
1141
+ ) });
1142
+ }
1143
+ function SelectItem({
1144
+ className,
1145
+ children,
1146
+ ...props
1147
+ }) {
1148
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1149
+ select.Select.Item,
1150
+ {
1151
+ "data-slot": "select-item",
1152
+ className: cn(
1153
+ "relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
1154
+ className
1155
+ ),
1156
+ ...props,
1157
+ children: [
1158
+ /* @__PURE__ */ jsxRuntime.jsx(select.Select.ItemText, { className: "flex flex-1 shrink-0 gap-2 whitespace-nowrap", children }),
1159
+ /* @__PURE__ */ jsxRuntime.jsx(
1160
+ select.Select.ItemIndicator,
1161
+ {
1162
+ render: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }),
1163
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, { className: "pointer-events-none" })
1164
+ }
1165
+ )
1166
+ ]
1167
+ }
1168
+ );
1169
+ }
1170
+ function SelectScrollUpButton({
1171
+ className,
1172
+ ...props
1173
+ }) {
1174
+ return /* @__PURE__ */ jsxRuntime.jsx(
1175
+ select.Select.ScrollUpArrow,
1176
+ {
1177
+ "data-slot": "select-scroll-up-button",
1178
+ className: cn(
1179
+ "top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
1180
+ className
1181
+ ),
1182
+ ...props,
1183
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1184
+ lucideReact.ChevronUpIcon,
1185
+ {}
1186
+ )
1187
+ }
1188
+ );
1189
+ }
1190
+ function SelectScrollDownButton({
1191
+ className,
1192
+ ...props
1193
+ }) {
1194
+ return /* @__PURE__ */ jsxRuntime.jsx(
1195
+ select.Select.ScrollDownArrow,
1196
+ {
1197
+ "data-slot": "select-scroll-down-button",
1198
+ className: cn(
1199
+ "bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
1200
+ className
1201
+ ),
1202
+ ...props,
1203
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1204
+ lucideReact.ChevronDownIcon,
1205
+ {}
1206
+ )
1207
+ }
1208
+ );
1209
+ }
1210
+ function SelectField({ field, value, onChange, id, readOnly, label }) {
1211
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs(
1212
+ Select,
1213
+ {
1214
+ value: String(value ?? ""),
1215
+ onValueChange: (v) => {
1216
+ if (v === null) return;
1217
+ const match = field.options.find((o) => String(o.value) === v);
1218
+ onChange(match ? match.value : v);
1219
+ },
1220
+ children: [
1221
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id, className: "h-8 text-sm w-full", disabled: readOnly, children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select..." }) }),
1222
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectGroup, { children: field.options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: String(opt.value), children: opt.label }, String(opt.value))) }) })
1223
+ ]
1224
+ }
1225
+ ) });
1226
+ }
1227
+ var buttonGroupVariants = classVarianceAuthority.cva(
1228
+ "flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
1229
+ {
1230
+ variants: {
1231
+ orientation: {
1232
+ horizontal: "*:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-md! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0",
1233
+ vertical: "flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0"
1234
+ }
1235
+ },
1236
+ defaultVariants: {
1237
+ orientation: "horizontal"
1238
+ }
1239
+ }
1240
+ );
1241
+ function ButtonGroup({
1242
+ className,
1243
+ orientation,
1244
+ ...props
1245
+ }) {
1246
+ return /* @__PURE__ */ jsxRuntime.jsx(
1247
+ "div",
1248
+ {
1249
+ role: "group",
1250
+ "data-slot": "button-group",
1251
+ "data-orientation": orientation,
1252
+ className: cn(buttonGroupVariants({ orientation }), className),
1253
+ ...props
1254
+ }
1255
+ );
1256
+ }
1257
+ function RadioField({ field, value, onChange, readOnly, label }) {
1258
+ const options = field.options ?? [];
1259
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, el: "div", children: /* @__PURE__ */ jsxRuntime.jsx(ButtonGroup, { className: "w-full", children: options.map((opt) => {
1260
+ const selected = String(opt.value) === String(value ?? "");
1261
+ return /* @__PURE__ */ jsxRuntime.jsx(
1262
+ Button,
1263
+ {
1264
+ type: "button",
1265
+ variant: selected ? "default" : "outline",
1266
+ size: "sm",
1267
+ className: "flex-1 text-xs",
1268
+ disabled: readOnly,
1269
+ onClick: () => onChange(opt.value),
1270
+ children: opt.label
1271
+ },
1272
+ String(opt.value)
1273
+ );
1274
+ }) }) });
1275
+ }
1276
+ function ItemGroup({ className, ...props }) {
1277
+ return /* @__PURE__ */ jsxRuntime.jsx(
1278
+ "div",
1279
+ {
1280
+ role: "list",
1281
+ "data-slot": "item-group",
1282
+ className: cn(
1283
+ "group/item-group flex w-full flex-col gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2",
1284
+ className
1285
+ ),
1286
+ ...props
1287
+ }
1288
+ );
1289
+ }
1290
+ var itemVariants = classVarianceAuthority.cva(
1291
+ "group/item flex w-full flex-wrap items-center rounded-md border text-sm transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [a]:transition-colors [a]:hover:bg-muted",
1292
+ {
1293
+ variants: {
1294
+ variant: {
1295
+ default: "border-transparent",
1296
+ outline: "border-border",
1297
+ muted: "border-transparent bg-muted/50"
1298
+ },
1299
+ size: {
1300
+ default: "gap-3.5 px-4 py-3.5",
1301
+ sm: "gap-2.5 px-3 py-2.5",
1302
+ xs: "gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0"
1303
+ }
1304
+ },
1305
+ defaultVariants: {
1306
+ variant: "default",
1307
+ size: "default"
1308
+ }
1309
+ }
1310
+ );
1311
+ function Item({
1312
+ className,
1313
+ variant = "default",
1314
+ size = "default",
1315
+ render,
1316
+ ...props
1317
+ }) {
1318
+ return useRender.useRender({
1319
+ defaultTagName: "div",
1320
+ props: mergeProps.mergeProps(
1321
+ {
1322
+ className: cn(itemVariants({ variant, size, className }))
1323
+ },
1324
+ props
1325
+ ),
1326
+ render,
1327
+ state: {
1328
+ slot: "item",
1329
+ variant,
1330
+ size
1331
+ }
1332
+ });
1333
+ }
1334
+ classVarianceAuthority.cva(
1335
+ "flex shrink-0 items-center justify-center gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start [&_svg]:pointer-events-none",
1336
+ {
1337
+ variants: {
1338
+ variant: {
1339
+ default: "bg-transparent",
1340
+ icon: "[&_svg:not([class*='size-'])]:size-4",
1341
+ image: "size-10 overflow-hidden rounded-sm group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 [&_img]:size-full [&_img]:object-cover"
1342
+ }
1343
+ },
1344
+ defaultVariants: {
1345
+ variant: "default"
1346
+ }
1347
+ }
1348
+ );
1349
+ function ItemContent({ className, ...props }) {
1350
+ return /* @__PURE__ */ jsxRuntime.jsx(
1351
+ "div",
1352
+ {
1353
+ "data-slot": "item-content",
1354
+ className: cn(
1355
+ "flex flex-1 flex-col gap-1 group-data-[size=xs]/item:gap-0 [&+[data-slot=item-content]]:flex-none",
1356
+ className
1357
+ ),
1358
+ ...props
1359
+ }
1360
+ );
1361
+ }
1362
+ function ItemTitle({ className, ...props }) {
1363
+ return /* @__PURE__ */ jsxRuntime.jsx(
1364
+ "div",
1365
+ {
1366
+ "data-slot": "item-title",
1367
+ className: cn(
1368
+ "line-clamp-1 flex w-fit items-center gap-2 text-sm leading-snug font-medium underline-offset-4",
1369
+ className
1370
+ ),
1371
+ ...props
1372
+ }
1373
+ );
1374
+ }
1375
+ function ItemActions({ className, ...props }) {
1376
+ return /* @__PURE__ */ jsxRuntime.jsx(
1377
+ "div",
1378
+ {
1379
+ "data-slot": "item-actions",
1380
+ className: cn("flex items-center gap-2", className),
1381
+ ...props
1382
+ }
1383
+ );
1384
+ }
1385
+ function useControlledState(props) {
1386
+ const { value, defaultValue, onChange } = props;
1387
+ const [state, setInternalState] = React6__namespace.useState(
1388
+ value !== void 0 ? value : defaultValue
1389
+ );
1390
+ React6__namespace.useEffect(() => {
1391
+ if (value !== void 0) setInternalState(value);
1392
+ }, [value]);
1393
+ const setState = React6__namespace.useCallback(
1394
+ (next, ...args) => {
1395
+ setInternalState(next);
1396
+ onChange?.(next, ...args);
1397
+ },
1398
+ [onChange]
1399
+ );
1400
+ return [state, setState];
1401
+ }
1402
+ var [PopoverProvider, usePopover] = getStrictContext("PopoverContext");
1403
+ function Popover(props) {
1404
+ const [isOpen, setIsOpen] = useControlledState({
1405
+ value: props?.open,
1406
+ defaultValue: props?.defaultOpen,
1407
+ onChange: props?.onOpenChange
1408
+ });
1409
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverProvider, { value: { isOpen, setIsOpen }, children: /* @__PURE__ */ jsxRuntime.jsx(
1410
+ popover.Popover.Root,
1411
+ {
1412
+ "data-slot": "popover",
1413
+ ...props,
1414
+ onOpenChange: setIsOpen
1415
+ }
1416
+ ) });
1417
+ }
1418
+ function PopoverTrigger(props) {
1419
+ return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { "data-slot": "popover-trigger", ...props });
1420
+ }
1421
+ function PopoverPortal(props) {
1422
+ const { isOpen } = usePopover();
1423
+ return /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxRuntime.jsx(
1424
+ popover.Popover.Portal,
1425
+ {
1426
+ keepMounted: true,
1427
+ "data-slot": "popover-portal",
1428
+ ...props
1429
+ }
1430
+ ) });
1431
+ }
1432
+ function PopoverPositioner(props) {
1433
+ return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Positioner, { "data-slot": "popover-positioner", ...props });
1434
+ }
1435
+ function PopoverPopup({
1436
+ initialFocus,
1437
+ finalFocus,
1438
+ transition = { type: "spring", stiffness: 300, damping: 25 },
1439
+ ...props
1440
+ }) {
1441
+ return /* @__PURE__ */ jsxRuntime.jsx(
1442
+ popover.Popover.Popup,
1443
+ {
1444
+ initialFocus,
1445
+ finalFocus,
1446
+ render: /* @__PURE__ */ jsxRuntime.jsx(
1447
+ react.motion.div,
1448
+ {
1449
+ "data-slot": "popover-popup",
1450
+ initial: { opacity: 0, scale: 0.5 },
1451
+ animate: { opacity: 1, scale: 1 },
1452
+ exit: { opacity: 0, scale: 0.5 },
1453
+ transition,
1454
+ ...props
1455
+ },
1456
+ "popover-popup"
1457
+ )
1458
+ }
1459
+ );
1460
+ }
1461
+ function Popover2(props) {
1462
+ return /* @__PURE__ */ jsxRuntime.jsx(Popover, { ...props });
1463
+ }
1464
+ function PopoverTrigger2(props) {
1465
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { ...props });
1466
+ }
1467
+ function PopoverPanel({
1468
+ className,
1469
+ align = "center",
1470
+ sideOffset = 4,
1471
+ initialFocus,
1472
+ finalFocus,
1473
+ style,
1474
+ children,
1475
+ ...props
1476
+ }) {
1477
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverPortal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1478
+ PopoverPositioner,
1479
+ {
1480
+ align,
1481
+ sideOffset,
1482
+ className: "z-50",
1483
+ ...props,
1484
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1485
+ PopoverPopup,
1486
+ {
1487
+ initialFocus,
1488
+ finalFocus,
1489
+ className: cn(
1490
+ "bg-popover text-popover-foreground w-72 rounded-md border p-4 shadow-md outline-hidden origin-(--transform-origin)",
1491
+ className
1492
+ ),
1493
+ style,
1494
+ children
1495
+ }
1496
+ )
1497
+ }
1498
+ ) });
1499
+ }
1500
+ function getArraySubField(subName, subField) {
1501
+ return { ...subField, label: subField.label ?? subName };
1502
+ }
1503
+ function SortableItem({
1504
+ id,
1505
+ index,
1506
+ item,
1507
+ field,
1508
+ readOnly,
1509
+ atMax,
1510
+ atMin,
1511
+ fieldId,
1512
+ open,
1513
+ onOpenChange,
1514
+ onDuplicate,
1515
+ onRemove,
1516
+ onUpdate,
1517
+ getSummary
1518
+ }) {
1519
+ const {
1520
+ attributes,
1521
+ listeners,
1522
+ setNodeRef,
1523
+ transform,
1524
+ transition,
1525
+ isDragging
1526
+ } = sortable.useSortable({ id });
1527
+ const style = {
1528
+ transform: utilities.CSS.Transform.toString(transform),
1529
+ transition,
1530
+ opacity: isDragging ? 0.5 : 1
1531
+ };
1532
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: setNodeRef, style, children: /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { open, onOpenChange, children: [
1533
+ /* @__PURE__ */ jsxRuntime.jsxs(Item, { variant: "outline", size: "sm", className: "cursor-pointer", children: [
1534
+ /* @__PURE__ */ jsxRuntime.jsx(
1535
+ "button",
1536
+ {
1537
+ type: "button",
1538
+ className: "cursor-grab active:cursor-grabbing touch-none p-0.5 text-muted-foreground/40 hover:text-muted-foreground",
1539
+ ...attributes,
1540
+ ...listeners,
1541
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, { className: "h-3.5 w-3.5 shrink-0" })
1542
+ }
1543
+ ),
1544
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger2, { className: "flex-1 min-w-0 text-left", children: /* @__PURE__ */ jsxRuntime.jsx(ItemContent, { children: /* @__PURE__ */ jsxRuntime.jsx(ItemTitle, { className: "text-xs", children: getSummary(item, index) }) }) }),
1545
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(ItemActions, { children: [
1546
+ /* @__PURE__ */ jsxRuntime.jsx(
1547
+ Button,
1548
+ {
1549
+ variant: "ghost",
1550
+ size: "icon",
1551
+ className: "h-5 w-5",
1552
+ disabled: atMax,
1553
+ onClick: (e) => {
1554
+ e.stopPropagation();
1555
+ onDuplicate(index);
1556
+ },
1557
+ title: "Duplicate",
1558
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3 w-3" })
1559
+ }
1560
+ ),
1561
+ /* @__PURE__ */ jsxRuntime.jsx(
1562
+ Button,
1563
+ {
1564
+ variant: "ghost",
1565
+ size: "icon",
1566
+ className: "h-5 w-5 text-destructive hover:text-destructive",
1567
+ disabled: atMin,
1568
+ onClick: (e) => {
1569
+ e.stopPropagation();
1570
+ onRemove(index);
1571
+ },
1572
+ title: "Delete",
1573
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
1574
+ }
1575
+ )
1576
+ ] })
1577
+ ] }),
1578
+ /* @__PURE__ */ jsxRuntime.jsx(
1579
+ PopoverPanel,
1580
+ {
1581
+ side: "left",
1582
+ sideOffset: 60,
1583
+ align: "start",
1584
+ alignOffset: -14,
1585
+ className: "w-56 p-3 flex flex-col gap-2",
1586
+ children: Object.entries(field.arrayFields).map(([subName, subField]) => /* @__PURE__ */ jsxRuntime.jsx(
1587
+ core.AutoField,
1588
+ {
1589
+ field: getArraySubField(subName, subField),
1590
+ value: item[subName],
1591
+ onChange: (val) => onUpdate(index, subName, val),
1592
+ readOnly,
1593
+ id: `${fieldId}-${index}-${subName}`
1594
+ },
1595
+ subName
1596
+ ))
1597
+ }
1598
+ )
1599
+ ] }) });
1600
+ }
1601
+ function ArrayField({
1602
+ field,
1603
+ value = [],
1604
+ onChange,
1605
+ readOnly,
1606
+ label,
1607
+ id = ""
1608
+ }) {
1609
+ const [openIndex, setOpenIndex] = React6__namespace.useState(null);
1610
+ const stableValue = React6__namespace.useMemo(() => {
1611
+ const needsId = value.some((item) => !item._id);
1612
+ if (!needsId) return value;
1613
+ return value.map(
1614
+ (item) => item._id ? item : { ...item, _id: `${id}-${Math.random().toString(36).slice(2)}` }
1615
+ );
1616
+ }, [value, id]);
1617
+ const itemIds = stableValue.map((item) => item._id);
1618
+ const atMax = field.max !== void 0 && stableValue.length >= field.max;
1619
+ const atMin = field.min !== void 0 && stableValue.length <= field.min;
1620
+ const sensors = core$1.useSensors(core$1.useSensor(core$1.PointerSensor));
1621
+ const handleDragEnd = (event) => {
1622
+ const { active, over } = event;
1623
+ if (!over || active.id === over.id) return;
1624
+ const from = itemIds.indexOf(active.id);
1625
+ const to = itemIds.indexOf(over.id);
1626
+ if (from === -1 || to === -1) return;
1627
+ onChange(sortable.arrayMove(stableValue, from, to));
1628
+ };
1629
+ const defaultItem = () => {
1630
+ if (!field.defaultItemProps) return {};
1631
+ return typeof field.defaultItemProps === "function" ? field.defaultItemProps(value.length) : { ...field.defaultItemProps };
1632
+ };
1633
+ const addItem = () => {
1634
+ if (atMax || readOnly) return;
1635
+ const newIndex = stableValue.length;
1636
+ onChange([...stableValue, defaultItem()]);
1637
+ setOpenIndex(newIndex);
1638
+ };
1639
+ const removeItem = (i) => {
1640
+ if (atMin || readOnly) return;
1641
+ const next = [...stableValue];
1642
+ next.splice(i, 1);
1643
+ onChange(next);
1644
+ };
1645
+ const duplicateItem = (i) => {
1646
+ if (atMax || readOnly) return;
1647
+ const next = [...stableValue];
1648
+ next.splice(i + 1, 0, { ...stableValue[i] });
1649
+ onChange(next);
1650
+ };
1651
+ const updateItem = (i, subName, val) => {
1652
+ onChange(
1653
+ stableValue.map(
1654
+ (item, idx) => idx === i ? { ...item, [subName]: val } : item
1655
+ )
1656
+ );
1657
+ };
1658
+ const getSummary = (item, i) => {
1659
+ if (field.getItemSummary) return field.getItemSummary(item, i);
1660
+ const first = Object.entries(item).find(
1661
+ (entry) => entry[0] !== "_id" && typeof entry[1] === "string" && entry[1].length > 0
1662
+ );
1663
+ return first?.[1] ?? `Item ${i + 1}`;
1664
+ };
1665
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? field.label ?? "", readOnly, el: "div", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
1666
+ /* @__PURE__ */ jsxRuntime.jsx(
1667
+ core$1.DndContext,
1668
+ {
1669
+ sensors,
1670
+ collisionDetection: core$1.closestCenter,
1671
+ onDragEnd: handleDragEnd,
1672
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1673
+ sortable.SortableContext,
1674
+ {
1675
+ items: itemIds,
1676
+ strategy: sortable.verticalListSortingStrategy,
1677
+ children: /* @__PURE__ */ jsxRuntime.jsx(ItemGroup, { children: stableValue.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(
1678
+ SortableItem,
1679
+ {
1680
+ id: itemIds[i],
1681
+ index: i,
1682
+ item,
1683
+ field,
1684
+ readOnly,
1685
+ atMax,
1686
+ atMin,
1687
+ fieldId: id,
1688
+ open: openIndex === i,
1689
+ onOpenChange: (o) => setOpenIndex(o ? i : null),
1690
+ onDuplicate: duplicateItem,
1691
+ onRemove: removeItem,
1692
+ onUpdate: updateItem,
1693
+ getSummary
1694
+ },
1695
+ itemIds[i]
1696
+ )) })
1697
+ }
1698
+ )
1699
+ }
1700
+ ),
1701
+ !readOnly && !atMax && /* @__PURE__ */ jsxRuntime.jsxs(
1702
+ Button,
1703
+ {
1704
+ variant: "outline",
1705
+ size: "sm",
1706
+ onClick: addItem,
1707
+ className: "w-full gap-1.5 mt-0.5",
1708
+ children: [
1709
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
1710
+ "Add item"
1711
+ ]
1712
+ }
1713
+ )
1714
+ ] }) });
1715
+ }
1716
+ function ObjectField({ children, name, readOnly }) {
1717
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: name, el: "div", readOnly, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3 pl-3 border-l-2 border-border/60 ml-1", children }) });
1718
+ }
1719
+ function Card({
1720
+ className,
1721
+ size = "default",
1722
+ ...props
1723
+ }) {
1724
+ return /* @__PURE__ */ jsxRuntime.jsx(
1725
+ "div",
1726
+ {
1727
+ "data-slot": "card",
1728
+ "data-size": size,
1729
+ className: cn(
1730
+ "group/card flex flex-col gap-6 overflow-hidden rounded-xl bg-card py-6 text-sm text-card-foreground shadow-xs ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
1731
+ className
1732
+ ),
1733
+ ...props
1734
+ }
1735
+ );
1736
+ }
1737
+ function CardContent({ className, ...props }) {
1738
+ return /* @__PURE__ */ jsxRuntime.jsx(
1739
+ "div",
1740
+ {
1741
+ "data-slot": "card-content",
1742
+ className: cn("px-6 group-data-[size=sm]/card:px-4", className),
1743
+ ...props
1744
+ }
1745
+ );
1746
+ }
1747
+ function SlotField({ children, label }) {
1748
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", el: "div", children: /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "border-dashed", children: /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "py-3 px-3", children: children ?? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground text-center", children: "Slot content is managed directly on the canvas." }) }) }) });
1749
+ }
1750
+ function CustomField({ children, label }) {
1751
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", el: "div", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-border/60 p-3", children }) });
1752
+ }
1753
+ var toggleVariants = classVarianceAuthority.cva(
1754
+ "group/toggle inline-flex items-center justify-center gap-1 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1755
+ {
1756
+ variants: {
1757
+ variant: {
1758
+ default: "bg-transparent",
1759
+ outline: "border border-input bg-transparent shadow-xs hover:bg-muted"
1760
+ },
1761
+ size: {
1762
+ default: "h-9 min-w-9 px-2",
1763
+ sm: "h-8 min-w-8 px-1.5",
1764
+ lg: "h-10 min-w-10 px-2.5"
1765
+ }
1766
+ },
1767
+ defaultVariants: {
1768
+ variant: "default",
1769
+ size: "default"
1770
+ }
1771
+ }
1772
+ );
1773
+ function Toggle({
1774
+ className,
1775
+ variant = "default",
1776
+ size = "default",
1777
+ ...props
1778
+ }) {
1779
+ return /* @__PURE__ */ jsxRuntime.jsx(
1780
+ toggle.Toggle,
1781
+ {
1782
+ "data-slot": "toggle",
1783
+ className: cn(toggleVariants({ variant, size, className })),
1784
+ ...props
1785
+ }
1786
+ );
1787
+ }
1788
+ function RichtextField({ value, onChange, readOnly, label }) {
1789
+ const ref = React6__namespace.useRef(null);
1790
+ const boldLabel = useMsg("richtext.bold");
1791
+ const italicLabel = useMsg("richtext.italic");
1792
+ const linkLabel = useMsg("richtext.link");
1793
+ const linkPrompt = useMsg("richtext.link.prompt");
1794
+ React6__namespace.useEffect(() => {
1795
+ if (ref.current && ref.current.innerHTML !== value) {
1796
+ ref.current.innerHTML = value ?? "";
1797
+ }
1798
+ }, [value]);
1799
+ const exec = (cmd, val) => {
1800
+ document.execCommand(cmd, false, val);
1801
+ if (ref.current) onChange(ref.current.innerHTML);
1802
+ };
1803
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 rounded-md border border-input overflow-hidden", children: [
1804
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5 border-b px-1 py-0.5 bg-muted/30", children: [
1805
+ /* @__PURE__ */ jsxRuntime.jsx(Toggle, { size: "sm", onPressedChange: () => exec("bold"), "aria-label": boldLabel, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bold, { className: "h-3.5 w-3.5" }) }),
1806
+ /* @__PURE__ */ jsxRuntime.jsx(Toggle, { size: "sm", onPressedChange: () => exec("italic"), "aria-label": italicLabel, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Italic, { className: "h-3.5 w-3.5" }) }),
1807
+ /* @__PURE__ */ jsxRuntime.jsx(
1808
+ Toggle,
1809
+ {
1810
+ size: "sm",
1811
+ onPressedChange: () => {
1812
+ const url = window.prompt(linkPrompt);
1813
+ if (url) exec("createLink", url);
1814
+ },
1815
+ "aria-label": linkLabel,
1816
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link, { className: "h-3.5 w-3.5" })
1817
+ }
1818
+ )
1819
+ ] }),
1820
+ /* @__PURE__ */ jsxRuntime.jsx(
1821
+ "div",
1822
+ {
1823
+ ref,
1824
+ contentEditable: !readOnly,
1825
+ suppressContentEditableWarning: true,
1826
+ onInput: () => {
1827
+ if (ref.current) onChange(ref.current.innerHTML);
1828
+ },
1829
+ className: "min-h-[60px] px-3 py-2 text-sm outline-none"
1830
+ }
1831
+ )
1832
+ ] }) });
1833
+ }
1834
+ function InputGroup({ className, ...props }) {
1835
+ return /* @__PURE__ */ jsxRuntime.jsx(
1836
+ "div",
1837
+ {
1838
+ "data-slot": "input-group",
1839
+ role: "group",
1840
+ className: cn(
1841
+ "group/input-group relative flex h-9 w-full min-w-0 items-center rounded-md border border-input shadow-xs transition-[color,box-shadow] outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5",
1842
+ className
1843
+ ),
1844
+ ...props
1845
+ }
1846
+ );
1847
+ }
1848
+ var inputGroupAddonVariants = classVarianceAuthority.cva(
1849
+ "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
1850
+ {
1851
+ variants: {
1852
+ align: {
1853
+ "inline-start": "order-first pl-2 has-[>button]:-ml-1 has-[>kbd]:ml-[-0.15rem]",
1854
+ "inline-end": "order-last pr-2 has-[>button]:-mr-1 has-[>kbd]:mr-[-0.15rem]",
1855
+ "block-start": "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
1856
+ "block-end": "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"
1857
+ }
1858
+ },
1859
+ defaultVariants: {
1860
+ align: "inline-start"
1861
+ }
1862
+ }
1863
+ );
1864
+ function InputGroupAddon({
1865
+ className,
1866
+ align = "inline-start",
1867
+ ...props
1868
+ }) {
1869
+ return /* @__PURE__ */ jsxRuntime.jsx(
1870
+ "div",
1871
+ {
1872
+ role: "group",
1873
+ "data-slot": "input-group-addon",
1874
+ "data-align": align,
1875
+ className: cn(inputGroupAddonVariants({ align }), className),
1876
+ onClick: (e) => {
1877
+ if (e.target.closest("button")) {
1878
+ return;
1879
+ }
1880
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
1881
+ },
1882
+ ...props
1883
+ }
1884
+ );
1885
+ }
1886
+ classVarianceAuthority.cva(
1887
+ "flex items-center gap-2 text-sm shadow-none",
1888
+ {
1889
+ variants: {
1890
+ size: {
1891
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
1892
+ sm: "",
1893
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
1894
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0"
1895
+ }
1896
+ },
1897
+ defaultVariants: {
1898
+ size: "xs"
1899
+ }
1900
+ }
1901
+ );
1902
+ function Command({
1903
+ className,
1904
+ ...props
1905
+ }) {
1906
+ return /* @__PURE__ */ jsxRuntime.jsx(
1907
+ cmdk.Command,
1908
+ {
1909
+ "data-slot": "command",
1910
+ className: cn(
1911
+ "flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",
1912
+ className
1913
+ ),
1914
+ ...props
1915
+ }
1916
+ );
1917
+ }
1918
+ function CommandInput({
1919
+ className,
1920
+ ...props
1921
+ }) {
1922
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "command-input-wrapper", className: "p-1 pb-0", children: /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { className: "h-8! rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:pl-2!", children: [
1923
+ /* @__PURE__ */ jsxRuntime.jsx(
1924
+ cmdk.Command.Input,
1925
+ {
1926
+ "data-slot": "command-input",
1927
+ className: cn(
1928
+ "w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
1929
+ className
1930
+ ),
1931
+ ...props
1932
+ }
1933
+ ),
1934
+ /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SearchIcon, { className: "size-4 shrink-0 opacity-50" }) })
1935
+ ] }) });
1936
+ }
1937
+ function CommandList({
1938
+ className,
1939
+ ...props
1940
+ }) {
1941
+ return /* @__PURE__ */ jsxRuntime.jsx(
1942
+ cmdk.Command.List,
1943
+ {
1944
+ "data-slot": "command-list",
1945
+ className: cn(
1946
+ "no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none",
1947
+ className
1948
+ ),
1949
+ ...props
1950
+ }
1951
+ );
1952
+ }
1953
+ function CommandEmpty({
1954
+ className,
1955
+ ...props
1956
+ }) {
1957
+ return /* @__PURE__ */ jsxRuntime.jsx(
1958
+ cmdk.Command.Empty,
1959
+ {
1960
+ "data-slot": "command-empty",
1961
+ className: cn("py-6 text-center text-sm", className),
1962
+ ...props
1963
+ }
1964
+ );
1965
+ }
1966
+ function CommandItem({
1967
+ className,
1968
+ children,
1969
+ ...props
1970
+ }) {
1971
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1972
+ cmdk.Command.Item,
1973
+ {
1974
+ "data-slot": "command-item",
1975
+ className: cn(
1976
+ "group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:**:[svg]:text-foreground",
1977
+ className
1978
+ ),
1979
+ ...props,
1980
+ children: [
1981
+ children,
1982
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, { className: "ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" })
1983
+ ]
1984
+ }
1985
+ );
1986
+ }
1987
+ function Skeleton({ className, ...props }) {
1988
+ return /* @__PURE__ */ jsxRuntime.jsx(
1989
+ "div",
1990
+ {
1991
+ "data-slot": "skeleton",
1992
+ className: cn("animate-pulse rounded-md bg-muted", className),
1993
+ ...props
1994
+ }
1995
+ );
1996
+ }
1997
+ function ExternalField({ value, onChange, fetchList, readOnly, label }) {
1998
+ const [query, setQuery] = React6__namespace.useState("");
1999
+ const [results, setResults] = React6__namespace.useState([]);
2000
+ const [loading, setLoading] = React6__namespace.useState(false);
2001
+ React6__namespace.useEffect(() => {
2002
+ if (!fetchList) return;
2003
+ setLoading(true);
2004
+ const timer = setTimeout(async () => {
2005
+ try {
2006
+ const data = await fetchList(query);
2007
+ setResults(data);
2008
+ } catch {
2009
+ setResults([]);
2010
+ } finally {
2011
+ setLoading(false);
2012
+ }
2013
+ }, 300);
2014
+ return () => clearTimeout(timer);
2015
+ }, [query, fetchList]);
2016
+ const selectedLabel = results.find((r) => r.value === value)?.label ?? String(value ?? "");
2017
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs(Command, { className: "rounded-md border border-input", children: [
2018
+ /* @__PURE__ */ jsxRuntime.jsx(
2019
+ CommandInput,
2020
+ {
2021
+ placeholder: "Search...",
2022
+ value: query,
2023
+ onValueChange: setQuery,
2024
+ disabled: readOnly
2025
+ }
2026
+ ),
2027
+ /* @__PURE__ */ jsxRuntime.jsx(CommandList, { children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 p-2", children: [
2028
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-6 w-full" }),
2029
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-6 w-3/4" }),
2030
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-6 w-1/2" })
2031
+ ] }) : results.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty, { children: "No results found." }) : results.map((r, i) => /* @__PURE__ */ jsxRuntime.jsx(
2032
+ CommandItem,
2033
+ {
2034
+ "data-checked": r.value === value,
2035
+ onSelect: () => onChange(r.value),
2036
+ children: r.label
2037
+ },
2038
+ i
2039
+ )) }),
2040
+ value != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t px-3 py-1.5 text-xs text-muted-foreground truncate", children: [
2041
+ "Selected: ",
2042
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: selectedLabel })
2043
+ ] })
2044
+ ] }) });
2045
+ }
2046
+
2047
+ // src/core/overrides/fields/FieldTypesRegistry.ts
2048
+ var fieldTypesRegistry = {
2049
+ text: TextField,
2050
+ textarea: TextareaField,
2051
+ number: NumberField,
2052
+ select: SelectField,
2053
+ radio: RadioField,
2054
+ array: ArrayField,
2055
+ object: ObjectField,
2056
+ slot: SlotField,
2057
+ custom: CustomField,
2058
+ richtext: RichtextField,
2059
+ external: ExternalField
2060
+ };
2061
+ function PuckRoot({ children }) {
2062
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
2063
+ }
2064
+ var puckOverrides = {
2065
+ drawer: EditorDrawer,
2066
+ components: EditorComponents,
2067
+ drawerItem: DrawerItem,
2068
+ componentItem: DrawerItem,
2069
+ outline: EditorOutline,
2070
+ iframe: CanvasIframe,
2071
+ preview: CanvasPreview,
2072
+ componentOverlay: ComponentOverlay,
2073
+ actionBar: ActionBar,
2074
+ fields: FieldWrapper,
2075
+ fieldTypes: fieldTypesRegistry,
2076
+ puck: PuckRoot
2077
+ };
2078
+
2079
+ exports.ActionBar = ActionBar;
2080
+ exports.CanvasIframe = CanvasIframe;
2081
+ exports.CanvasPreview = CanvasPreview;
2082
+ exports.ComponentOverlay = ComponentOverlay;
2083
+ exports.DrawerItem = DrawerItem;
2084
+ exports.EditorComponents = EditorComponents;
2085
+ exports.EditorDrawer = EditorDrawer;
2086
+ exports.EditorOutline = EditorOutline;
2087
+ exports.FieldLabel = FieldLabel;
2088
+ exports.FieldWrapper = FieldWrapper;
2089
+ exports.fieldTypesRegistry = fieldTypesRegistry;
2090
+ exports.puckOverrides = puckOverrides;