@anvilkit/puck-studio 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,4093 @@
1
+ 'use strict';
2
+
3
+ var core = require('@puckeditor/core');
4
+ var lucideReact = require('lucide-react');
5
+ var button = require('@base-ui/react/button');
6
+ var classVarianceAuthority = require('class-variance-authority');
7
+ var clsx = require('clsx');
8
+ var tailwindMerge = require('tailwind-merge');
9
+ var jsxRuntime = require('react/jsx-runtime');
10
+ var separator = require('@base-ui/react/separator');
11
+ var zustand = require('zustand');
12
+ var React18 = require('react');
13
+ var TooltipPrimitive = require('@radix-ui/react-tooltip');
14
+ var menu = require('@base-ui/react/menu');
15
+ var scrollArea = require('@base-ui/react/scroll-area');
16
+ var input = require('@base-ui/react/input');
17
+ var mergeProps = require('@base-ui/react/merge-props');
18
+ var useRender = require('@base-ui/react/use-render');
19
+ var select = require('@base-ui/react/select');
20
+ var core$1 = require('@dnd-kit/core');
21
+ var sortable = require('@dnd-kit/sortable');
22
+ var utilities = require('@dnd-kit/utilities');
23
+ var popover = require('@base-ui-components/react/popover');
24
+ var react = require('motion/react');
25
+ var toggle = require('@base-ui/react/toggle');
26
+ var cmdk = require('cmdk');
27
+ require('@base-ui/react/dialog');
28
+ var pluginAi = require('@puckeditor/plugin-ai');
29
+ require('@puckeditor/plugin-ai/styles.css');
30
+ require('@puckeditor/core/puck.css');
31
+ var tabs = require('@base-ui-components/react/tabs');
32
+ var motion9 = require('motion/react-client');
33
+ var react$1 = require('@floating-ui/react');
34
+ var avatar = require('@base-ui/react/avatar');
35
+ var middleware = require('zustand/middleware');
36
+
37
+ function _interopNamespace(e) {
38
+ if (e && e.__esModule) return e;
39
+ var n = Object.create(null);
40
+ if (e) {
41
+ Object.keys(e).forEach(function (k) {
42
+ if (k !== 'default') {
43
+ var d = Object.getOwnPropertyDescriptor(e, k);
44
+ Object.defineProperty(n, k, d.get ? d : {
45
+ enumerable: true,
46
+ get: function () { return e[k]; }
47
+ });
48
+ }
49
+ });
50
+ }
51
+ n.default = e;
52
+ return Object.freeze(n);
53
+ }
54
+
55
+ var React18__namespace = /*#__PURE__*/_interopNamespace(React18);
56
+ var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
57
+ var motion9__namespace = /*#__PURE__*/_interopNamespace(motion9);
58
+
59
+ // src/components/overrides/layout/EditorHeader.tsx
60
+ function cn(...inputs) {
61
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
62
+ }
63
+ var buttonVariants = classVarianceAuthority.cva(
64
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg 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",
65
+ {
66
+ variants: {
67
+ variant: {
68
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
69
+ outline: "border-border bg-background 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",
70
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
71
+ ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
72
+ 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",
73
+ link: "text-primary underline-offset-4 hover:underline"
74
+ },
75
+ size: {
76
+ default: "h-8 gap-1.5 px-2.5",
77
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs [&_svg:not([class*='size-'])]:size-3",
78
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] [&_svg:not([class*='size-'])]:size-3.5",
79
+ lg: "h-9 gap-1.5 px-2.5",
80
+ icon: "size-8",
81
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] [&_svg:not([class*='size-'])]:size-3",
82
+ "icon-sm": "size-7 rounded-[min(var(--radius-md),12px)]",
83
+ "icon-lg": "size-9"
84
+ }
85
+ },
86
+ defaultVariants: {
87
+ variant: "default",
88
+ size: "default"
89
+ }
90
+ }
91
+ );
92
+ function Button({
93
+ className,
94
+ variant = "default",
95
+ size = "default",
96
+ ...props
97
+ }) {
98
+ return /* @__PURE__ */ jsxRuntime.jsx(
99
+ button.Button,
100
+ {
101
+ "data-slot": "button",
102
+ className: cn(buttonVariants({ variant, size, className })),
103
+ ...props
104
+ }
105
+ );
106
+ }
107
+ function Separator({
108
+ className,
109
+ orientation = "horizontal",
110
+ ...props
111
+ }) {
112
+ return /* @__PURE__ */ jsxRuntime.jsx(
113
+ separator.Separator,
114
+ {
115
+ "data-slot": "separator",
116
+ orientation,
117
+ className: cn(
118
+ "shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
119
+ className
120
+ ),
121
+ ...props
122
+ }
123
+ );
124
+ }
125
+ function getStrictContext(name) {
126
+ const Context = React18__namespace.createContext(void 0);
127
+ const Provider2 = ({
128
+ value,
129
+ children
130
+ }) => /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value, children });
131
+ const useSafeContext = () => {
132
+ const ctx = React18__namespace.useContext(Context);
133
+ if (ctx === void 0) {
134
+ throw new Error(`useContext must be used within ${name ?? "a Provider"}`);
135
+ }
136
+ return ctx;
137
+ };
138
+ return [Provider2, useSafeContext];
139
+ }
140
+
141
+ // src/store/ui-context.ts
142
+ var [EditorUiStoreProvider, useEditorUiStoreApi] = getStrictContext("EditorUiStoreProvider");
143
+
144
+ // src/store/i18n-context.ts
145
+ var [EditorI18nStoreProvider, useEditorI18nStoreApi] = getStrictContext("EditorI18nStoreProvider");
146
+
147
+ // src/store/hooks.ts
148
+ function useActiveTab() {
149
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.activeTab);
150
+ }
151
+ function useSetActiveTab() {
152
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.setActiveTab);
153
+ }
154
+ function useDrawerSearch() {
155
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.drawerSearch);
156
+ }
157
+ function useSetDrawerSearch() {
158
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.setDrawerSearch);
159
+ }
160
+ function useTheme() {
161
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.theme);
162
+ }
163
+ function useToggleTheme() {
164
+ return zustand.useStore(useEditorUiStoreApi(), (s) => s.toggleTheme);
165
+ }
166
+ function useMsg(key) {
167
+ return zustand.useStore(useEditorI18nStoreApi(), (s) => s.messages[key] ?? key);
168
+ }
169
+ var TooltipProvider = TooltipPrimitive__namespace.Provider;
170
+ var Tooltip = TooltipPrimitive__namespace.Root;
171
+ var TooltipTrigger = TooltipPrimitive__namespace.Trigger;
172
+ var TooltipContent = React18__namespace.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
173
+ TooltipPrimitive__namespace.Content,
174
+ {
175
+ ref,
176
+ sideOffset,
177
+ className: cn(
178
+ "z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-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 origin-[--radix-tooltip-content-transform-origin]",
179
+ className
180
+ ),
181
+ ...props
182
+ }
183
+ ) }));
184
+ TooltipContent.displayName = TooltipPrimitive__namespace.Content.displayName;
185
+ function DropdownMenu({ ...props }) {
186
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
187
+ }
188
+ function DropdownMenuTrigger({ ...props }) {
189
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
190
+ }
191
+ function DropdownMenuContent({
192
+ align = "start",
193
+ alignOffset = 0,
194
+ side = "bottom",
195
+ sideOffset = 4,
196
+ className,
197
+ ...props
198
+ }) {
199
+ return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
200
+ menu.Menu.Positioner,
201
+ {
202
+ className: "isolate z-50 outline-none",
203
+ align,
204
+ alignOffset,
205
+ side,
206
+ sideOffset,
207
+ children: /* @__PURE__ */ jsxRuntime.jsx(
208
+ menu.Menu.Popup,
209
+ {
210
+ "data-slot": "dropdown-menu-content",
211
+ className: cn(
212
+ "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden",
213
+ className
214
+ ),
215
+ ...props
216
+ }
217
+ )
218
+ }
219
+ ) });
220
+ }
221
+ function DropdownMenuItem({
222
+ className,
223
+ inset,
224
+ variant = "default",
225
+ ...props
226
+ }) {
227
+ return /* @__PURE__ */ jsxRuntime.jsx(
228
+ menu.Menu.Item,
229
+ {
230
+ "data-slot": "dropdown-menu-item",
231
+ "data-inset": inset,
232
+ "data-variant": variant,
233
+ className: cn(
234
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
235
+ className
236
+ ),
237
+ ...props
238
+ }
239
+ );
240
+ }
241
+ function EditorHeader({
242
+ actions,
243
+ children
244
+ }) {
245
+ const { history, appState } = core.usePuck();
246
+ const undo = useMsg("header.undo");
247
+ const undoTooltip = useMsg("header.undo.tooltip");
248
+ const redo = useMsg("header.redo");
249
+ const redoTooltip = useMsg("header.redo.tooltip");
250
+ const exportLabel = useMsg("header.export");
251
+ const exportJson = useMsg("header.export.json");
252
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex h-12 items-center justify-between border-b bg-background px-4 gap-2", children: [
253
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-4 w-4" }) }),
254
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: appState?.data?.root?.props?.title || "" }),
255
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
256
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
257
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
258
+ Button,
259
+ {
260
+ variant: "ghost",
261
+ size: "icon",
262
+ disabled: !history.hasPast,
263
+ onClick: () => history.back(),
264
+ "aria-label": undo,
265
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo2, { className: "h-4 w-4" })
266
+ }
267
+ ) }),
268
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: undoTooltip })
269
+ ] }),
270
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
271
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
272
+ Button,
273
+ {
274
+ variant: "ghost",
275
+ size: "icon",
276
+ disabled: !history.hasFuture,
277
+ onClick: () => history.forward(),
278
+ "aria-label": redo,
279
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Redo2, { className: "h-4 w-4" })
280
+ }
281
+ ) }),
282
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: redoTooltip })
283
+ ] }),
284
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
285
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
286
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
287
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { "aria-label": exportLabel, className: "inline-flex items-center justify-center rounded-md h-9 w-9 hover:bg-accent hover:text-accent-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { className: "h-4 w-4" }) }) }),
288
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: exportLabel })
289
+ ] }),
290
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuItem, { children: exportJson }) })
291
+ ] }),
292
+ actions
293
+ ] })
294
+ ] }) });
295
+ }
296
+ function EditorHeaderActions({
297
+ children
298
+ }) {
299
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children }) });
300
+ }
301
+ function ScrollArea({
302
+ className,
303
+ children,
304
+ ...props
305
+ }) {
306
+ return /* @__PURE__ */ jsxRuntime.jsxs(
307
+ scrollArea.ScrollArea.Root,
308
+ {
309
+ "data-slot": "scroll-area",
310
+ className: cn("relative", className),
311
+ ...props,
312
+ children: [
313
+ /* @__PURE__ */ jsxRuntime.jsx(
314
+ scrollArea.ScrollArea.Viewport,
315
+ {
316
+ "data-slot": "scroll-area-viewport",
317
+ className: "size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1",
318
+ children
319
+ }
320
+ ),
321
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollBar, {}),
322
+ /* @__PURE__ */ jsxRuntime.jsx(scrollArea.ScrollArea.Corner, {})
323
+ ]
324
+ }
325
+ );
326
+ }
327
+ function ScrollBar({
328
+ className,
329
+ orientation = "vertical",
330
+ ...props
331
+ }) {
332
+ return /* @__PURE__ */ jsxRuntime.jsx(
333
+ scrollArea.ScrollArea.Scrollbar,
334
+ {
335
+ "data-slot": "scroll-area-scrollbar",
336
+ "data-orientation": orientation,
337
+ orientation,
338
+ className: cn(
339
+ "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",
340
+ className
341
+ ),
342
+ ...props,
343
+ children: /* @__PURE__ */ jsxRuntime.jsx(
344
+ scrollArea.ScrollArea.Thumb,
345
+ {
346
+ "data-slot": "scroll-area-thumb",
347
+ className: "relative flex-1 rounded-full bg-border"
348
+ }
349
+ )
350
+ }
351
+ );
352
+ }
353
+ function Input({ className, type, ...props }) {
354
+ return /* @__PURE__ */ jsxRuntime.jsx(
355
+ input.Input,
356
+ {
357
+ type,
358
+ "data-slot": "input",
359
+ className: cn(
360
+ "h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 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:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
361
+ className
362
+ ),
363
+ ...props
364
+ }
365
+ );
366
+ }
367
+ function EditorDrawer({
368
+ children
369
+ }) {
370
+ const search = useDrawerSearch();
371
+ const setSearch = useSetDrawerSearch();
372
+ const drawerTitle = useMsg("drawer.title");
373
+ const searchPlaceholder = useMsg("drawer.search.placeholder");
374
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
375
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pt-3 pb-1 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: drawerTitle }),
376
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
377
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
378
+ /* @__PURE__ */ jsxRuntime.jsx(
379
+ Input,
380
+ {
381
+ className: "pl-8",
382
+ placeholder: searchPlaceholder,
383
+ value: search,
384
+ onChange: (e) => setSearch(e.target.value)
385
+ }
386
+ )
387
+ ] }) }),
388
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children })
389
+ ] });
390
+ }
391
+ function EditorComponents({
392
+ children
393
+ }) {
394
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-puck-components-grid": true, className: "p-2", children: [
395
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
396
+ [data-puck-components-grid] [data-puck-drawer] {
397
+ display: grid;
398
+ grid-template-columns: repeat(3, minmax(0, 1fr));
399
+ gap: 6px;
400
+ }
401
+ /* flatten item wrapper and draggable wrapper */
402
+ [data-puck-components-grid] [data-puck-drawer] > div,
403
+ [data-puck-components-grid] [data-puck-drawer] > div > div {
404
+ display: contents;
405
+ }
406
+ /* hide the ghost/bg copy */
407
+ [data-puck-components-grid] [data-puck-drawer] > div > div > div:first-child {
408
+ display: none;
409
+ }
410
+ /* flatten the real draggable wrapper */
411
+ [data-puck-components-grid] [data-puck-drawer] > div > div > div:last-child {
412
+ display: contents;
413
+ }
414
+ ` }),
415
+ children
416
+ ] });
417
+ }
418
+ function getPlaceholderUrl(name) {
419
+ return `https://picsum.photos/seed/${encodeURIComponent(name)}/120/80`;
420
+ }
421
+ function DrawerItem({
422
+ children,
423
+ name
424
+ }) {
425
+ const { appState } = core.usePuck();
426
+ const componentConfig = appState.config?.components?.[name];
427
+ const thumbnail = componentConfig?.metadata?.thumbnail;
428
+ const src = thumbnail ?? getPlaceholderUrl(name);
429
+ 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: [
430
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-16 bg-muted overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
431
+ "img",
432
+ {
433
+ src,
434
+ alt: name,
435
+ className: "w-full h-full object-cover",
436
+ onError: (e) => {
437
+ e.currentTarget.style.display = "none";
438
+ }
439
+ }
440
+ ) }),
441
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1.5 text-xs font-medium truncate", children: name ?? children })
442
+ ] });
443
+ }
444
+ function EditorOutline({
445
+ children
446
+ }) {
447
+ const { selectedItem } = core.usePuck();
448
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col", children: [
449
+ /* @__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" }) }),
450
+ selectedItem && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
451
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-1.5 text-xs text-muted-foreground truncate", children: [
452
+ "Selected:",
453
+ " ",
454
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: selectedItem.type ?? "Component" })
455
+ ] }),
456
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, {})
457
+ ] }),
458
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm", children }) })
459
+ ] });
460
+ }
461
+ var CANVAS_CSS = `
462
+ *, *::before, *::after { box-sizing: border-box; }
463
+ :root {
464
+ --background: 0 0% 100%;
465
+ --foreground: 222.2 84% 4.9%;
466
+ --primary: 222.2 47.4% 11.2%;
467
+ --primary-foreground: 210 40% 98%;
468
+ --secondary: 210 40% 96.1%;
469
+ --muted: 210 40% 96.1%;
470
+ --muted-foreground: 215.4 16.3% 46.9%;
471
+ --border: 214.3 31.8% 91.4%;
472
+ --radius: 0.5rem;
473
+ }
474
+ .dark {
475
+ --background: 222.2 84% 4.9%;
476
+ --foreground: 210 40% 98%;
477
+ --primary: 210 40% 98%;
478
+ --primary-foreground: 222.2 47.4% 11.2%;
479
+ --secondary: 217.2 32.6% 17.5%;
480
+ --muted: 217.2 32.6% 17.5%;
481
+ --muted-foreground: 215 20.2% 65.1%;
482
+ --border: 217.2 32.6% 17.5%;
483
+ }
484
+ body { margin: 0; font-family: system-ui, sans-serif; }
485
+ `;
486
+ function isImageUrl(val) {
487
+ 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/");
488
+ }
489
+ function replaceImageInProps(props, newSrc) {
490
+ const result = {};
491
+ for (const key of Object.keys(props)) {
492
+ const val = props[key];
493
+ if (typeof val === "string" && isImageUrl(val)) {
494
+ result[key] = newSrc;
495
+ } else if (Array.isArray(val)) {
496
+ result[key] = val.map(
497
+ (item) => item && typeof item === "object" ? replaceImageInProps(item, newSrc) : item
498
+ );
499
+ } else if (val && typeof val === "object") {
500
+ result[key] = replaceImageInProps(val, newSrc);
501
+ } else {
502
+ result[key] = val;
503
+ }
504
+ }
505
+ return result;
506
+ }
507
+ function replaceTextInProps(props, newText, targetText) {
508
+ for (const key of Object.keys(props)) {
509
+ if (key === "id") continue;
510
+ const val = props[key];
511
+ if (typeof val === "string" && val === targetText && !isImageUrl(val)) {
512
+ return { result: { ...props, [key]: newText }, replaced: true };
513
+ }
514
+ }
515
+ for (const key of Object.keys(props)) {
516
+ if (key === "id") continue;
517
+ const val = props[key];
518
+ if (typeof val === "string" && !isImageUrl(val) && val.length > 0) {
519
+ return { result: { ...props, [key]: newText }, replaced: true };
520
+ }
521
+ }
522
+ return { result: props, replaced: false };
523
+ }
524
+ function CanvasIframe({
525
+ children,
526
+ document: iframeDoc
527
+ }) {
528
+ const getPuck = core.useGetPuck();
529
+ const theme = useTheme();
530
+ React18__namespace.useEffect(() => {
531
+ if (!iframeDoc) return;
532
+ const existing = iframeDoc.getElementById("__anvilkit_styles__");
533
+ if (existing) existing.remove();
534
+ const style = iframeDoc.createElement("style");
535
+ style.id = "__anvilkit_styles__";
536
+ style.textContent = CANVAS_CSS;
537
+ iframeDoc.head.appendChild(style);
538
+ }, [iframeDoc]);
539
+ React18__namespace.useEffect(() => {
540
+ if (!iframeDoc) return;
541
+ iframeDoc.documentElement.classList.toggle("dark", theme === "dark");
542
+ }, [iframeDoc, theme]);
543
+ React18__namespace.useEffect(() => {
544
+ if (!iframeDoc) return;
545
+ const iframeEl = iframeDoc.defaultView?.frameElement;
546
+ if (!iframeEl) return;
547
+ let highlightedEl = null;
548
+ function iframeCoords(clientX, clientY) {
549
+ const rect = iframeEl.getBoundingClientRect();
550
+ const x = clientX - rect.left;
551
+ const y = clientY - rect.top;
552
+ if (x < 0 || y < 0 || x > rect.width || y > rect.height) return null;
553
+ return { x, y };
554
+ }
555
+ function getComponentElAt(clientX, clientY) {
556
+ const coords = iframeCoords(clientX, clientY);
557
+ if (!coords) return null;
558
+ const el = iframeDoc.elementFromPoint(coords.x, coords.y);
559
+ if (!el) return null;
560
+ const comp = el.closest("[data-puck-component]");
561
+ return comp;
562
+ }
563
+ function getImgInComponent(compEl, clientX, clientY) {
564
+ const imgs = Array.from(compEl.querySelectorAll("img"));
565
+ if (!imgs.length) return null;
566
+ if (imgs.length === 1) return imgs[0];
567
+ const rect = iframeEl.getBoundingClientRect();
568
+ const x = clientX - rect.left;
569
+ const y = clientY - rect.top;
570
+ let closest = null;
571
+ let minDist = Infinity;
572
+ for (const img of imgs) {
573
+ const r = img.getBoundingClientRect();
574
+ const cx = r.left + r.width / 2;
575
+ const cy = r.top + r.height / 2;
576
+ const dist = Math.hypot(cx - x, cy - y);
577
+ if (dist < minDist) {
578
+ minDist = dist;
579
+ closest = img;
580
+ }
581
+ }
582
+ return closest;
583
+ }
584
+ const TEXT_TAGS = /* @__PURE__ */ new Set(["P", "H1", "H2", "H3", "H4", "H5", "H6", "SPAN", "A", "LI", "BUTTON", "LABEL"]);
585
+ function getTextElInComponent(compEl, clientX, clientY) {
586
+ const coords = iframeCoords(clientX, clientY);
587
+ if (!coords) return null;
588
+ const el = iframeDoc.elementFromPoint(coords.x, coords.y);
589
+ if (el && compEl.contains(el)) {
590
+ let cur = el;
591
+ while (cur && cur !== iframeDoc.body) {
592
+ if (TEXT_TAGS.has(cur.tagName) && cur.textContent?.trim()) return cur;
593
+ cur = cur.parentElement;
594
+ }
595
+ }
596
+ for (const tag of TEXT_TAGS) {
597
+ const found = compEl.querySelector(tag.toLowerCase());
598
+ if (found?.textContent?.trim()) return found;
599
+ }
600
+ return null;
601
+ }
602
+ function setHighlight(el, color) {
603
+ if (highlightedEl && highlightedEl !== el) {
604
+ highlightedEl.style.outline = "";
605
+ highlightedEl.style.outlineOffset = "";
606
+ }
607
+ if (el) {
608
+ el.style.outline = `2px solid ${color}`;
609
+ el.style.outlineOffset = "2px";
610
+ }
611
+ highlightedEl = el;
612
+ }
613
+ function clearHighlight() {
614
+ setHighlight(null, "");
615
+ }
616
+ let activeLibrary = null;
617
+ function onLibraryDragStart(e) {
618
+ activeLibrary = e.detail.type;
619
+ }
620
+ function onPointerMove(e) {
621
+ if (!activeLibrary) return;
622
+ const compEl = getComponentElAt(e.clientX, e.clientY);
623
+ if (!compEl) {
624
+ clearHighlight();
625
+ return;
626
+ }
627
+ if (activeLibrary === "image") {
628
+ const img = getImgInComponent(compEl, e.clientX, e.clientY);
629
+ setHighlight(img, "#6366f1");
630
+ } else {
631
+ const textEl = getTextElInComponent(compEl, e.clientX, e.clientY);
632
+ setHighlight(textEl, "#f59e0b");
633
+ }
634
+ }
635
+ function onPointerUp() {
636
+ activeLibrary = null;
637
+ clearHighlight();
638
+ }
639
+ function dispatchReplace(componentId, updatedProps) {
640
+ const { dispatch, getItemById, getSelectorForId } = getPuck();
641
+ const item = getItemById(componentId);
642
+ const selector = getSelectorForId(componentId);
643
+ if (!item || !selector) return false;
644
+ dispatch({
645
+ type: "replace",
646
+ destinationIndex: selector.index,
647
+ destinationZone: selector.zone,
648
+ data: { ...item, props: { ...item.props, ...updatedProps } }
649
+ });
650
+ return true;
651
+ }
652
+ function onImageDrop(e) {
653
+ const { src, clientX, clientY } = e.detail;
654
+ clearHighlight();
655
+ activeLibrary = null;
656
+ if (!src) return;
657
+ const compEl = getComponentElAt(clientX, clientY);
658
+ if (!compEl) return;
659
+ const componentId = compEl.getAttribute("data-puck-component");
660
+ const { getItemById } = getPuck();
661
+ const item = getItemById(componentId);
662
+ if (!item) return;
663
+ const updatedProps = replaceImageInProps(item.props, src);
664
+ dispatchReplace(componentId, updatedProps);
665
+ }
666
+ function onTextDrop(e) {
667
+ const { text, clientX, clientY } = e.detail;
668
+ clearHighlight();
669
+ activeLibrary = null;
670
+ if (!text) return;
671
+ const compEl = getComponentElAt(clientX, clientY);
672
+ if (!compEl) return;
673
+ const componentId = compEl.getAttribute("data-puck-component");
674
+ const textEl = getTextElInComponent(compEl, clientX, clientY);
675
+ const targetText = textEl?.textContent?.trim() ?? "";
676
+ const { getItemById } = getPuck();
677
+ const item = getItemById(componentId);
678
+ if (!item) return;
679
+ const { result: updatedProps, replaced } = replaceTextInProps(
680
+ item.props,
681
+ text,
682
+ targetText
683
+ );
684
+ if (replaced) dispatchReplace(componentId, updatedProps);
685
+ }
686
+ window.addEventListener("anvilkit:librarydragstart", onLibraryDragStart);
687
+ window.addEventListener("pointermove", onPointerMove);
688
+ window.addEventListener("pointerup", onPointerUp);
689
+ window.addEventListener("anvilkit:imagedrop", onImageDrop);
690
+ window.addEventListener("anvilkit:textdrop", onTextDrop);
691
+ return () => {
692
+ window.removeEventListener("anvilkit:librarydragstart", onLibraryDragStart);
693
+ window.removeEventListener("pointermove", onPointerMove);
694
+ window.removeEventListener("pointerup", onPointerUp);
695
+ window.removeEventListener("anvilkit:imagedrop", onImageDrop);
696
+ window.removeEventListener("anvilkit:textdrop", onTextDrop);
697
+ };
698
+ }, [iframeDoc, getPuck]);
699
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
700
+ }
701
+ function CanvasPreview({
702
+ children
703
+ }) {
704
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full px-3 py-2 text-sm font-medium text-foreground", children });
705
+ }
706
+ function ComponentOverlay({
707
+ children,
708
+ hover,
709
+ isSelected
710
+ }) {
711
+ return /* @__PURE__ */ jsxRuntime.jsx(
712
+ "div",
713
+ {
714
+ className: [
715
+ "absolute inset-0 rounded-sm pointer-events-none z-10 transition-colors",
716
+ isSelected ? "border-2 border-primary/80" : hover ? "border-2 border-primary/40" : ""
717
+ ].filter(Boolean).join(" "),
718
+ children
719
+ }
720
+ );
721
+ }
722
+ function ActionBar({
723
+ children,
724
+ label,
725
+ parentAction
726
+ }) {
727
+ 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: [
728
+ label && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
729
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 text-xs font-medium text-muted-foreground truncate max-w-[120px]", children: label }),
730
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5" })
731
+ ] }),
732
+ parentAction && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
733
+ parentAction,
734
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5" })
735
+ ] }),
736
+ children
737
+ ] }) });
738
+ }
739
+ function cn2(...inputs) {
740
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
741
+ }
742
+ function Label({ className, ...props }) {
743
+ return /* @__PURE__ */ jsxRuntime.jsx(
744
+ "label",
745
+ {
746
+ "data-slot": "label",
747
+ className: cn2(
748
+ "gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed",
749
+ className
750
+ ),
751
+ ...props
752
+ }
753
+ );
754
+ }
755
+ function Breadcrumb({ className, ...props }) {
756
+ return /* @__PURE__ */ jsxRuntime.jsx(
757
+ "nav",
758
+ {
759
+ "aria-label": "breadcrumb",
760
+ "data-slot": "breadcrumb",
761
+ className: cn2(className),
762
+ ...props
763
+ }
764
+ );
765
+ }
766
+ function BreadcrumbList({ className, ...props }) {
767
+ return /* @__PURE__ */ jsxRuntime.jsx(
768
+ "ol",
769
+ {
770
+ "data-slot": "breadcrumb-list",
771
+ className: cn2(
772
+ "text-muted-foreground gap-1.5 text-sm flex flex-wrap items-center wrap-break-word",
773
+ className
774
+ ),
775
+ ...props
776
+ }
777
+ );
778
+ }
779
+ function BreadcrumbItem({ className, ...props }) {
780
+ return /* @__PURE__ */ jsxRuntime.jsx(
781
+ "li",
782
+ {
783
+ "data-slot": "breadcrumb-item",
784
+ className: cn2("gap-1 inline-flex items-center", className),
785
+ ...props
786
+ }
787
+ );
788
+ }
789
+ function BreadcrumbLink({
790
+ className,
791
+ render,
792
+ ...props
793
+ }) {
794
+ return useRender.useRender({
795
+ defaultTagName: "a",
796
+ props: mergeProps.mergeProps(
797
+ {
798
+ className: cn2("hover:text-foreground transition-colors", className)
799
+ },
800
+ props
801
+ ),
802
+ render,
803
+ state: {
804
+ slot: "breadcrumb-link"
805
+ }
806
+ });
807
+ }
808
+ function BreadcrumbPage({ className, ...props }) {
809
+ return /* @__PURE__ */ jsxRuntime.jsx(
810
+ "span",
811
+ {
812
+ "data-slot": "breadcrumb-page",
813
+ role: "link",
814
+ "aria-disabled": "true",
815
+ "aria-current": "page",
816
+ className: cn2("text-foreground font-normal", className),
817
+ ...props
818
+ }
819
+ );
820
+ }
821
+ function BreadcrumbSeparator({
822
+ children,
823
+ className,
824
+ ...props
825
+ }) {
826
+ return /* @__PURE__ */ jsxRuntime.jsx(
827
+ "li",
828
+ {
829
+ "data-slot": "breadcrumb-separator",
830
+ role: "presentation",
831
+ "aria-hidden": "true",
832
+ className: cn2("[&>svg]:size-3.5", className),
833
+ ...props,
834
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "cn-rtl-flip" })
835
+ }
836
+ );
837
+ }
838
+ function useBreadcrumbs() {
839
+ const { appState, dispatch, selectedItem, getParentById, getSelectorForId } = core.usePuck();
840
+ const { itemSelector } = appState.ui;
841
+ const selectRoot = () => dispatch({ type: "setUi", ui: { itemSelector: null } });
842
+ if (!itemSelector || !selectedItem) {
843
+ return [{ label: "Page" }];
844
+ }
845
+ const selectedType = selectedItem.type ?? "Component";
846
+ const parent = getParentById(selectedItem.props?.id ?? "");
847
+ if (!parent) {
848
+ return [{ label: "Page", onSelect: selectRoot }, { label: selectedType }];
849
+ }
850
+ parent.type ?? "Component";
851
+ let parentSelector = void 0;
852
+ try {
853
+ parentSelector = getSelectorForId(parent.props?.id ?? "");
854
+ } catch {
855
+ parentSelector = void 0;
856
+ }
857
+ return [{ label: "Page", onSelect: selectRoot }, { label: selectedType }];
858
+ }
859
+ function FieldWrapper({
860
+ children
861
+ }) {
862
+ const crumbs = useBreadcrumbs();
863
+ return /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "h-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0", children: [
864
+ /* @__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) => {
865
+ const isLast = i === crumbs.length - 1;
866
+ return /* @__PURE__ */ jsxRuntime.jsxs(React18__namespace.Fragment, { children: [
867
+ i > 0 && /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbSeparator, {}),
868
+ /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbItem, { children: isLast ? /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbPage, { children: crumb.label }) : /* @__PURE__ */ jsxRuntime.jsx(
869
+ BreadcrumbLink,
870
+ {
871
+ className: "cursor-pointer",
872
+ onClick: crumb.onSelect,
873
+ children: crumb.label
874
+ }
875
+ ) })
876
+ ] }, i);
877
+ }) }) }) }),
878
+ children
879
+ ] }) });
880
+ }
881
+ function FieldLabel({
882
+ children,
883
+ label,
884
+ labelIcon,
885
+ el,
886
+ type: _type,
887
+ readOnly,
888
+ className
889
+ }) {
890
+ console.log("Lable type", labelIcon);
891
+ const El = el ?? "div";
892
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(El, { className: `flex flex-col gap-1.5 ${className ?? ""}`, children: [
893
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
894
+ labelIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: labelIcon }),
895
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-xs font-medium text-muted-foreground", children: label }),
896
+ label && /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
897
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: "h-3 w-3 text-muted-foreground/60 cursor-help" }) }),
898
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "right", children: label })
899
+ ] }),
900
+ readOnly && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-muted-foreground/50", children: "Read only" })
901
+ ] }),
902
+ children
903
+ ] }) });
904
+ }
905
+ var MOCK_VALUES = {
906
+ default: ["AI-generated content", "Smart suggestion", "Generated text"]
907
+ };
908
+ function getMock(instructions) {
909
+ if (instructions?.toLowerCase().includes("caps")) {
910
+ return "AI GENERATED TITLE";
911
+ }
912
+ const pool = MOCK_VALUES.default;
913
+ return pool[Math.floor(Math.random() * pool.length)];
914
+ }
915
+ function AiButton({ ai, onGenerate }) {
916
+ const [loading, setLoading] = React18__namespace.useState(false);
917
+ const handleClick = () => {
918
+ setLoading(true);
919
+ setTimeout(() => {
920
+ onGenerate(getMock(ai.instructions));
921
+ setLoading(false);
922
+ }, 600);
923
+ };
924
+ return /* @__PURE__ */ jsxRuntime.jsx(
925
+ Button,
926
+ {
927
+ type: "button",
928
+ variant: "outline",
929
+ size: "icon",
930
+ className: "h-8 w-8 shrink-0 text-muted-foreground hover:text-primary",
931
+ onClick: handleClick,
932
+ disabled: loading,
933
+ "aria-label": "Generate with AI",
934
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: `h-3.5 w-3.5 ${loading ? "animate-pulse" : ""}` })
935
+ }
936
+ );
937
+ }
938
+ function TextField({
939
+ field,
940
+ value,
941
+ onChange,
942
+ readOnly,
943
+ placeholder,
944
+ label,
945
+ labelIcon
946
+ }) {
947
+ const [local, setLocal] = React18__namespace.useState(value ?? "");
948
+ React18__namespace.useEffect(() => {
949
+ setLocal(value ?? "");
950
+ }, [value]);
951
+ React18__namespace.useEffect(() => {
952
+ const timer = setTimeout(() => {
953
+ if (local !== value) onChange(local);
954
+ }, 200);
955
+ return () => clearTimeout(timer);
956
+ }, [local]);
957
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", labelIcon, readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
958
+ /* @__PURE__ */ jsxRuntime.jsx(
959
+ Input,
960
+ {
961
+ value: local,
962
+ onChange: (e) => setLocal(e.target.value),
963
+ readOnly,
964
+ placeholder,
965
+ className: "h-8 text-sm flex-1"
966
+ }
967
+ ),
968
+ field?.ai && /* @__PURE__ */ jsxRuntime.jsx(AiButton, { ai: field.ai, onGenerate: (v) => {
969
+ setLocal(v);
970
+ onChange(v);
971
+ } })
972
+ ] }) });
973
+ }
974
+ function Textarea({ className, ...props }) {
975
+ return /* @__PURE__ */ jsxRuntime.jsx(
976
+ "textarea",
977
+ {
978
+ "data-slot": "textarea",
979
+ className: cn(
980
+ "flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
981
+ className
982
+ ),
983
+ ...props
984
+ }
985
+ );
986
+ }
987
+ function TextareaField({ value, onChange, readOnly, placeholder, label }) {
988
+ const [local, setLocal] = React18__namespace.useState(value ?? "");
989
+ React18__namespace.useEffect(() => {
990
+ setLocal(value ?? "");
991
+ }, [value]);
992
+ React18__namespace.useEffect(() => {
993
+ const timer = setTimeout(() => {
994
+ if (local !== value) onChange(local);
995
+ }, 200);
996
+ return () => clearTimeout(timer);
997
+ }, [local]);
998
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsx(
999
+ Textarea,
1000
+ {
1001
+ value: local,
1002
+ onChange: (e) => setLocal(e.target.value),
1003
+ readOnly,
1004
+ placeholder,
1005
+ className: "min-h-[80px] text-sm resize-y"
1006
+ }
1007
+ ) });
1008
+ }
1009
+ function NumberField({ value, onChange, readOnly, min, max, step, label }) {
1010
+ const [local, setLocal] = React18__namespace.useState(String(value ?? ""));
1011
+ React18__namespace.useEffect(() => {
1012
+ setLocal(String(value ?? ""));
1013
+ }, [value]);
1014
+ React18__namespace.useEffect(() => {
1015
+ const parsed = parseFloat(local);
1016
+ if (!isNaN(parsed) && parsed !== value) {
1017
+ const timer = setTimeout(() => onChange(parsed), 200);
1018
+ return () => clearTimeout(timer);
1019
+ }
1020
+ }, [local]);
1021
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsx(
1022
+ Input,
1023
+ {
1024
+ type: "number",
1025
+ value: local,
1026
+ onChange: (e) => setLocal(e.target.value),
1027
+ readOnly,
1028
+ min,
1029
+ max,
1030
+ step,
1031
+ className: "h-8 text-sm"
1032
+ }
1033
+ ) });
1034
+ }
1035
+ var Select = select.Select.Root;
1036
+ function SelectGroup({ className, ...props }) {
1037
+ return /* @__PURE__ */ jsxRuntime.jsx(
1038
+ select.Select.Group,
1039
+ {
1040
+ "data-slot": "select-group",
1041
+ className: cn("scroll-my-1 p-1", className),
1042
+ ...props
1043
+ }
1044
+ );
1045
+ }
1046
+ function SelectValue({ className, ...props }) {
1047
+ return /* @__PURE__ */ jsxRuntime.jsx(
1048
+ select.Select.Value,
1049
+ {
1050
+ "data-slot": "select-value",
1051
+ className: cn("flex flex-1 text-left", className),
1052
+ ...props
1053
+ }
1054
+ );
1055
+ }
1056
+ function SelectTrigger({
1057
+ className,
1058
+ size = "default",
1059
+ children,
1060
+ ...props
1061
+ }) {
1062
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1063
+ select.Select.Trigger,
1064
+ {
1065
+ "data-slot": "select-trigger",
1066
+ "data-size": size,
1067
+ className: cn(
1068
+ "border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-lg border bg-transparent py-2 pr-2 pl-2.5 text-sm transition-colors select-none focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*='size-'])]:size-4 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
1069
+ className
1070
+ ),
1071
+ ...props,
1072
+ children: [
1073
+ children,
1074
+ /* @__PURE__ */ jsxRuntime.jsx(
1075
+ select.Select.Icon,
1076
+ {
1077
+ render: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: "text-muted-foreground size-4 pointer-events-none" })
1078
+ }
1079
+ )
1080
+ ]
1081
+ }
1082
+ );
1083
+ }
1084
+ function SelectContent({
1085
+ className,
1086
+ children,
1087
+ side = "bottom",
1088
+ sideOffset = 4,
1089
+ align = "center",
1090
+ alignOffset = 0,
1091
+ alignItemWithTrigger = true,
1092
+ ...props
1093
+ }) {
1094
+ return /* @__PURE__ */ jsxRuntime.jsx(select.Select.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1095
+ select.Select.Positioner,
1096
+ {
1097
+ side,
1098
+ sideOffset,
1099
+ align,
1100
+ alignOffset,
1101
+ alignItemWithTrigger,
1102
+ className: "isolate z-50",
1103
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1104
+ select.Select.Popup,
1105
+ {
1106
+ "data-slot": "select-content",
1107
+ "data-align-trigger": alignItemWithTrigger,
1108
+ className: cn(
1109
+ "bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-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 ring-foreground/10 min-w-36 rounded-lg shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 relative isolate z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none",
1110
+ className
1111
+ ),
1112
+ ...props,
1113
+ children: [
1114
+ /* @__PURE__ */ jsxRuntime.jsx(SelectScrollUpButton, {}),
1115
+ /* @__PURE__ */ jsxRuntime.jsx(select.Select.List, { children }),
1116
+ /* @__PURE__ */ jsxRuntime.jsx(SelectScrollDownButton, {})
1117
+ ]
1118
+ }
1119
+ )
1120
+ }
1121
+ ) });
1122
+ }
1123
+ function SelectItem({
1124
+ className,
1125
+ children,
1126
+ ...props
1127
+ }) {
1128
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1129
+ select.Select.Item,
1130
+ {
1131
+ "data-slot": "select-item",
1132
+ className: cn(
1133
+ "focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
1134
+ className
1135
+ ),
1136
+ ...props,
1137
+ children: [
1138
+ /* @__PURE__ */ jsxRuntime.jsx(select.Select.ItemText, { className: "flex flex-1 gap-2 shrink-0 whitespace-nowrap", children }),
1139
+ /* @__PURE__ */ jsxRuntime.jsx(
1140
+ select.Select.ItemIndicator,
1141
+ {
1142
+ render: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, { className: "pointer-events-none" }) })
1143
+ }
1144
+ )
1145
+ ]
1146
+ }
1147
+ );
1148
+ }
1149
+ function SelectScrollUpButton({
1150
+ className,
1151
+ ...props
1152
+ }) {
1153
+ return /* @__PURE__ */ jsxRuntime.jsx(
1154
+ select.Select.ScrollUpArrow,
1155
+ {
1156
+ "data-slot": "select-scroll-up-button",
1157
+ className: cn(
1158
+ "bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4 top-0 w-full",
1159
+ className
1160
+ ),
1161
+ ...props,
1162
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUpIcon, {})
1163
+ }
1164
+ );
1165
+ }
1166
+ function SelectScrollDownButton({
1167
+ className,
1168
+ ...props
1169
+ }) {
1170
+ return /* @__PURE__ */ jsxRuntime.jsx(
1171
+ select.Select.ScrollDownArrow,
1172
+ {
1173
+ "data-slot": "select-scroll-down-button",
1174
+ className: cn(
1175
+ "bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4 bottom-0 w-full",
1176
+ className
1177
+ ),
1178
+ ...props,
1179
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, {})
1180
+ }
1181
+ );
1182
+ }
1183
+ function SelectField({ field, value, onChange, id, readOnly, label }) {
1184
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs(
1185
+ Select,
1186
+ {
1187
+ value: String(value ?? ""),
1188
+ onValueChange: (v) => {
1189
+ if (v === null) return;
1190
+ const match = field.options.find((o) => String(o.value) === v);
1191
+ onChange(match ? match.value : v);
1192
+ },
1193
+ children: [
1194
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id, className: "h-8 text-sm w-full", disabled: readOnly, children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select..." }) }),
1195
+ /* @__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))) }) })
1196
+ ]
1197
+ }
1198
+ ) });
1199
+ }
1200
+ var buttonGroupVariants = classVarianceAuthority.cva(
1201
+ "has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-lg flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
1202
+ {
1203
+ variants: {
1204
+ orientation: {
1205
+ horizontal: "[&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-lg! *:data-slot:rounded-r-none [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0",
1206
+ vertical: "[&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-lg! flex-col *:data-slot:rounded-b-none [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0"
1207
+ }
1208
+ },
1209
+ defaultVariants: {
1210
+ orientation: "horizontal"
1211
+ }
1212
+ }
1213
+ );
1214
+ function ButtonGroup({
1215
+ className,
1216
+ orientation,
1217
+ ...props
1218
+ }) {
1219
+ return /* @__PURE__ */ jsxRuntime.jsx(
1220
+ "div",
1221
+ {
1222
+ role: "group",
1223
+ "data-slot": "button-group",
1224
+ "data-orientation": orientation,
1225
+ className: cn2(buttonGroupVariants({ orientation }), className),
1226
+ ...props
1227
+ }
1228
+ );
1229
+ }
1230
+ function RadioField({ field, value, onChange, readOnly, label }) {
1231
+ const options = field.options ?? [];
1232
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, el: "div", children: /* @__PURE__ */ jsxRuntime.jsx(ButtonGroup, { className: "w-full", children: options.map((opt) => {
1233
+ const selected = String(opt.value) === String(value ?? "");
1234
+ return /* @__PURE__ */ jsxRuntime.jsx(
1235
+ Button,
1236
+ {
1237
+ type: "button",
1238
+ variant: selected ? "default" : "outline",
1239
+ size: "sm",
1240
+ className: "flex-1 text-xs",
1241
+ disabled: readOnly,
1242
+ onClick: () => onChange(opt.value),
1243
+ children: opt.label
1244
+ },
1245
+ String(opt.value)
1246
+ );
1247
+ }) }) });
1248
+ }
1249
+ function ItemGroup({ className, ...props }) {
1250
+ return /* @__PURE__ */ jsxRuntime.jsx(
1251
+ "div",
1252
+ {
1253
+ role: "list",
1254
+ "data-slot": "item-group",
1255
+ className: cn2(
1256
+ "gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2 group/item-group flex w-full flex-col",
1257
+ className
1258
+ ),
1259
+ ...props
1260
+ }
1261
+ );
1262
+ }
1263
+ var itemVariants = classVarianceAuthority.cva(
1264
+ "[a]:hover:bg-muted rounded-lg border text-sm group/item flex w-full flex-wrap items-center transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [a]:transition-colors",
1265
+ {
1266
+ variants: {
1267
+ variant: {
1268
+ default: "border-transparent",
1269
+ outline: "border-border",
1270
+ muted: "bg-muted/50 border-transparent"
1271
+ },
1272
+ size: {
1273
+ default: "gap-2.5 px-3 py-2.5",
1274
+ sm: "gap-2.5 px-3 py-2.5",
1275
+ xs: "gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0"
1276
+ }
1277
+ },
1278
+ defaultVariants: {
1279
+ variant: "default",
1280
+ size: "default"
1281
+ }
1282
+ }
1283
+ );
1284
+ function Item({
1285
+ className,
1286
+ variant = "default",
1287
+ size = "default",
1288
+ render,
1289
+ ...props
1290
+ }) {
1291
+ return useRender.useRender({
1292
+ defaultTagName: "div",
1293
+ props: mergeProps.mergeProps(
1294
+ {
1295
+ className: cn2(itemVariants({ variant, size, className }))
1296
+ },
1297
+ props
1298
+ ),
1299
+ render,
1300
+ state: {
1301
+ slot: "item",
1302
+ variant,
1303
+ size
1304
+ }
1305
+ });
1306
+ }
1307
+ classVarianceAuthority.cva(
1308
+ "gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start flex shrink-0 items-center justify-center [&_svg]:pointer-events-none",
1309
+ {
1310
+ variants: {
1311
+ variant: {
1312
+ default: "bg-transparent",
1313
+ icon: "[&_svg:not([class*='size-'])]:size-4",
1314
+ 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"
1315
+ }
1316
+ },
1317
+ defaultVariants: {
1318
+ variant: "default"
1319
+ }
1320
+ }
1321
+ );
1322
+ function ItemContent({ className, ...props }) {
1323
+ return /* @__PURE__ */ jsxRuntime.jsx(
1324
+ "div",
1325
+ {
1326
+ "data-slot": "item-content",
1327
+ className: cn2(
1328
+ "gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none",
1329
+ className
1330
+ ),
1331
+ ...props
1332
+ }
1333
+ );
1334
+ }
1335
+ function ItemTitle({ className, ...props }) {
1336
+ return /* @__PURE__ */ jsxRuntime.jsx(
1337
+ "div",
1338
+ {
1339
+ "data-slot": "item-title",
1340
+ className: cn2(
1341
+ "gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center",
1342
+ className
1343
+ ),
1344
+ ...props
1345
+ }
1346
+ );
1347
+ }
1348
+ function ItemActions({ className, ...props }) {
1349
+ return /* @__PURE__ */ jsxRuntime.jsx(
1350
+ "div",
1351
+ {
1352
+ "data-slot": "item-actions",
1353
+ className: cn2("gap-2 flex items-center", className),
1354
+ ...props
1355
+ }
1356
+ );
1357
+ }
1358
+ function useControlledState(props) {
1359
+ const { value, defaultValue, onChange } = props;
1360
+ const [state, setInternalState] = React18__namespace.useState(
1361
+ value !== void 0 ? value : defaultValue
1362
+ );
1363
+ React18__namespace.useEffect(() => {
1364
+ if (value !== void 0) setInternalState(value);
1365
+ }, [value]);
1366
+ const setState = React18__namespace.useCallback(
1367
+ (next, ...args) => {
1368
+ setInternalState(next);
1369
+ onChange?.(next, ...args);
1370
+ },
1371
+ [onChange]
1372
+ );
1373
+ return [state, setState];
1374
+ }
1375
+ var [PopoverProvider, usePopover] = getStrictContext("PopoverContext");
1376
+ function Popover(props) {
1377
+ const [isOpen, setIsOpen] = useControlledState({
1378
+ value: props?.open,
1379
+ defaultValue: props?.defaultOpen,
1380
+ onChange: props?.onOpenChange
1381
+ });
1382
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverProvider, { value: { isOpen, setIsOpen }, children: /* @__PURE__ */ jsxRuntime.jsx(
1383
+ popover.Popover.Root,
1384
+ {
1385
+ "data-slot": "popover",
1386
+ ...props,
1387
+ onOpenChange: setIsOpen
1388
+ }
1389
+ ) });
1390
+ }
1391
+ function PopoverTrigger(props) {
1392
+ return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { "data-slot": "popover-trigger", ...props });
1393
+ }
1394
+ function PopoverPortal(props) {
1395
+ const { isOpen } = usePopover();
1396
+ return /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxRuntime.jsx(
1397
+ popover.Popover.Portal,
1398
+ {
1399
+ keepMounted: true,
1400
+ "data-slot": "popover-portal",
1401
+ ...props
1402
+ }
1403
+ ) });
1404
+ }
1405
+ function PopoverPositioner(props) {
1406
+ return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Positioner, { "data-slot": "popover-positioner", ...props });
1407
+ }
1408
+ function PopoverPopup({
1409
+ initialFocus,
1410
+ finalFocus,
1411
+ transition = { type: "spring", stiffness: 300, damping: 25 },
1412
+ ...props
1413
+ }) {
1414
+ return /* @__PURE__ */ jsxRuntime.jsx(
1415
+ popover.Popover.Popup,
1416
+ {
1417
+ initialFocus,
1418
+ finalFocus,
1419
+ render: /* @__PURE__ */ jsxRuntime.jsx(
1420
+ react.motion.div,
1421
+ {
1422
+ "data-slot": "popover-popup",
1423
+ initial: { opacity: 0, scale: 0.5 },
1424
+ animate: { opacity: 1, scale: 1 },
1425
+ exit: { opacity: 0, scale: 0.5 },
1426
+ transition,
1427
+ ...props
1428
+ },
1429
+ "popover-popup"
1430
+ )
1431
+ }
1432
+ );
1433
+ }
1434
+ function PopoverTitle(props) {
1435
+ return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Title, { "data-slot": "popover-title", ...props });
1436
+ }
1437
+ function Popover2(props) {
1438
+ return /* @__PURE__ */ jsxRuntime.jsx(Popover, { ...props });
1439
+ }
1440
+ function PopoverTrigger2(props) {
1441
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { ...props });
1442
+ }
1443
+ function PopoverPanel({
1444
+ className,
1445
+ align = "center",
1446
+ sideOffset = 4,
1447
+ initialFocus,
1448
+ finalFocus,
1449
+ style,
1450
+ children,
1451
+ ...props
1452
+ }) {
1453
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverPortal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1454
+ PopoverPositioner,
1455
+ {
1456
+ align,
1457
+ sideOffset,
1458
+ className: "z-50",
1459
+ ...props,
1460
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1461
+ PopoverPopup,
1462
+ {
1463
+ initialFocus,
1464
+ finalFocus,
1465
+ className: cn(
1466
+ "bg-popover text-popover-foreground w-72 rounded-md border p-4 shadow-md outline-hidden origin-(--transform-origin)",
1467
+ className
1468
+ ),
1469
+ style,
1470
+ children
1471
+ }
1472
+ )
1473
+ }
1474
+ ) });
1475
+ }
1476
+ function PopoverTitle2(props) {
1477
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverTitle, { ...props });
1478
+ }
1479
+ function SortableItem({
1480
+ id,
1481
+ index,
1482
+ item,
1483
+ field,
1484
+ readOnly,
1485
+ atMax,
1486
+ atMin,
1487
+ fieldId,
1488
+ open,
1489
+ onOpenChange,
1490
+ onDuplicate,
1491
+ onRemove,
1492
+ onUpdate,
1493
+ getSummary
1494
+ }) {
1495
+ const {
1496
+ attributes,
1497
+ listeners,
1498
+ setNodeRef,
1499
+ transform,
1500
+ transition,
1501
+ isDragging
1502
+ } = sortable.useSortable({ id });
1503
+ const style = {
1504
+ transform: utilities.CSS.Transform.toString(transform),
1505
+ transition,
1506
+ opacity: isDragging ? 0.5 : 1
1507
+ };
1508
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: setNodeRef, style, children: /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { open, onOpenChange, children: [
1509
+ /* @__PURE__ */ jsxRuntime.jsxs(Item, { variant: "outline", size: "sm", className: "cursor-pointer", children: [
1510
+ /* @__PURE__ */ jsxRuntime.jsx(
1511
+ "button",
1512
+ {
1513
+ type: "button",
1514
+ className: "cursor-grab active:cursor-grabbing touch-none p-0.5 text-muted-foreground/40 hover:text-muted-foreground",
1515
+ ...attributes,
1516
+ ...listeners,
1517
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, { className: "h-3.5 w-3.5 shrink-0" })
1518
+ }
1519
+ ),
1520
+ /* @__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) }) }) }),
1521
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(ItemActions, { children: [
1522
+ /* @__PURE__ */ jsxRuntime.jsx(
1523
+ Button,
1524
+ {
1525
+ variant: "ghost",
1526
+ size: "icon",
1527
+ className: "h-5 w-5",
1528
+ disabled: atMax,
1529
+ onClick: (e) => {
1530
+ e.stopPropagation();
1531
+ onDuplicate(index);
1532
+ },
1533
+ title: "Duplicate",
1534
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3 w-3" })
1535
+ }
1536
+ ),
1537
+ /* @__PURE__ */ jsxRuntime.jsx(
1538
+ Button,
1539
+ {
1540
+ variant: "ghost",
1541
+ size: "icon",
1542
+ className: "h-5 w-5 text-destructive hover:text-destructive",
1543
+ disabled: atMin,
1544
+ onClick: (e) => {
1545
+ e.stopPropagation();
1546
+ onRemove(index);
1547
+ },
1548
+ title: "Delete",
1549
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
1550
+ }
1551
+ )
1552
+ ] })
1553
+ ] }),
1554
+ /* @__PURE__ */ jsxRuntime.jsx(
1555
+ PopoverPanel,
1556
+ {
1557
+ side: "left",
1558
+ sideOffset: 60,
1559
+ align: "start",
1560
+ alignOffset: -14,
1561
+ className: "w-56 p-3 flex flex-col gap-2",
1562
+ children: Object.entries(field.arrayFields).map(([subName, subField]) => /* @__PURE__ */ jsxRuntime.jsx(
1563
+ core.AutoField,
1564
+ {
1565
+ field: { ...subField, label: subField.label ?? subName },
1566
+ value: item[subName],
1567
+ onChange: (val) => onUpdate(index, subName, val),
1568
+ readOnly,
1569
+ id: `${fieldId}-${index}-${subName}`
1570
+ },
1571
+ subName
1572
+ ))
1573
+ }
1574
+ )
1575
+ ] }) });
1576
+ }
1577
+ function ArrayField({
1578
+ field,
1579
+ value = [],
1580
+ onChange,
1581
+ readOnly,
1582
+ label,
1583
+ id = ""
1584
+ }) {
1585
+ const atMax = field.max !== void 0 && value.length >= field.max;
1586
+ const atMin = field.min !== void 0 && value.length <= field.min;
1587
+ const [openIndex, setOpenIndex] = React18__namespace.useState(null);
1588
+ const itemIds = React18__namespace.useMemo(
1589
+ () => value.map((_, i) => `${id}-item-${i}`),
1590
+ [value.length, id]
1591
+ );
1592
+ const sensors = core$1.useSensors(core$1.useSensor(core$1.PointerSensor));
1593
+ const handleDragEnd = (event) => {
1594
+ const { active, over } = event;
1595
+ if (!over || active.id === over.id) return;
1596
+ const from = itemIds.indexOf(active.id);
1597
+ const to = itemIds.indexOf(over.id);
1598
+ if (from === -1 || to === -1) return;
1599
+ onChange(sortable.arrayMove(value, from, to));
1600
+ };
1601
+ const defaultItem = () => {
1602
+ if (!field.defaultItemProps) return {};
1603
+ return typeof field.defaultItemProps === "function" ? field.defaultItemProps(value.length) : { ...field.defaultItemProps };
1604
+ };
1605
+ const addItem = () => {
1606
+ if (atMax || readOnly) return;
1607
+ const newIndex = value.length;
1608
+ onChange([...value, defaultItem()]);
1609
+ setOpenIndex(newIndex);
1610
+ };
1611
+ const removeItem = (i) => {
1612
+ if (atMin || readOnly) return;
1613
+ const next = [...value];
1614
+ next.splice(i, 1);
1615
+ onChange(next);
1616
+ };
1617
+ const duplicateItem = (i) => {
1618
+ if (atMax || readOnly) return;
1619
+ const next = [...value];
1620
+ next.splice(i + 1, 0, { ...value[i] });
1621
+ onChange(next);
1622
+ };
1623
+ const updateItem = (i, subName, val) => {
1624
+ onChange(
1625
+ value.map(
1626
+ (item, idx) => idx === i ? { ...item, [subName]: val } : item
1627
+ )
1628
+ );
1629
+ };
1630
+ const getSummary = (item, i) => {
1631
+ if (field.getItemSummary) return field.getItemSummary(item, i);
1632
+ const first = Object.values(item).find((v) => typeof v === "string" && v);
1633
+ return first || `Item ${i + 1}`;
1634
+ };
1635
+ 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: [
1636
+ /* @__PURE__ */ jsxRuntime.jsx(
1637
+ core$1.DndContext,
1638
+ {
1639
+ sensors,
1640
+ collisionDetection: core$1.closestCenter,
1641
+ onDragEnd: handleDragEnd,
1642
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1643
+ sortable.SortableContext,
1644
+ {
1645
+ items: itemIds,
1646
+ strategy: sortable.verticalListSortingStrategy,
1647
+ children: /* @__PURE__ */ jsxRuntime.jsx(ItemGroup, { children: value.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(
1648
+ SortableItem,
1649
+ {
1650
+ id: itemIds[i],
1651
+ index: i,
1652
+ item,
1653
+ field,
1654
+ readOnly,
1655
+ atMax,
1656
+ atMin,
1657
+ fieldId: id,
1658
+ open: openIndex === i,
1659
+ onOpenChange: (o) => setOpenIndex(o ? i : null),
1660
+ onDuplicate: duplicateItem,
1661
+ onRemove: removeItem,
1662
+ onUpdate: updateItem,
1663
+ getSummary
1664
+ },
1665
+ itemIds[i]
1666
+ )) })
1667
+ }
1668
+ )
1669
+ }
1670
+ ),
1671
+ !readOnly && !atMax && /* @__PURE__ */ jsxRuntime.jsxs(
1672
+ Button,
1673
+ {
1674
+ variant: "outline",
1675
+ size: "sm",
1676
+ onClick: addItem,
1677
+ className: "w-full gap-1.5 mt-0.5",
1678
+ children: [
1679
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
1680
+ "Add item"
1681
+ ]
1682
+ }
1683
+ )
1684
+ ] }) });
1685
+ }
1686
+ function ObjectField({ children, name, readOnly }) {
1687
+ 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 }) });
1688
+ }
1689
+ function Card({
1690
+ className,
1691
+ size = "default",
1692
+ ...props
1693
+ }) {
1694
+ return /* @__PURE__ */ jsxRuntime.jsx(
1695
+ "div",
1696
+ {
1697
+ "data-slot": "card",
1698
+ "data-size": size,
1699
+ className: cn(
1700
+ "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
1701
+ className
1702
+ ),
1703
+ ...props
1704
+ }
1705
+ );
1706
+ }
1707
+ function CardContent({ className, ...props }) {
1708
+ return /* @__PURE__ */ jsxRuntime.jsx(
1709
+ "div",
1710
+ {
1711
+ "data-slot": "card-content",
1712
+ className: cn("px-4 group-data-[size=sm]/card:px-3", className),
1713
+ ...props
1714
+ }
1715
+ );
1716
+ }
1717
+ function SlotField({ children, label }) {
1718
+ 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." }) }) }) });
1719
+ }
1720
+ function CustomField({ children, label }) {
1721
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", el: "div", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-border/60 p-3", children }) });
1722
+ }
1723
+ var toggleVariants = classVarianceAuthority.cva(
1724
+ "group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all 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 data-[state=on]:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1725
+ {
1726
+ variants: {
1727
+ variant: {
1728
+ default: "bg-transparent",
1729
+ outline: "border border-input bg-transparent hover:bg-muted"
1730
+ },
1731
+ size: {
1732
+ default: "h-8 min-w-8 px-2",
1733
+ sm: "h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-1.5 text-[0.8rem]",
1734
+ lg: "h-9 min-w-9 px-2.5"
1735
+ }
1736
+ },
1737
+ defaultVariants: {
1738
+ variant: "default",
1739
+ size: "default"
1740
+ }
1741
+ }
1742
+ );
1743
+ function Toggle({
1744
+ className,
1745
+ variant = "default",
1746
+ size = "default",
1747
+ ...props
1748
+ }) {
1749
+ return /* @__PURE__ */ jsxRuntime.jsx(
1750
+ toggle.Toggle,
1751
+ {
1752
+ "data-slot": "toggle",
1753
+ className: cn(toggleVariants({ variant, size, className })),
1754
+ ...props
1755
+ }
1756
+ );
1757
+ }
1758
+ function RichtextField({ value, onChange, readOnly, label }) {
1759
+ const ref = React18__namespace.useRef(null);
1760
+ const boldLabel = useMsg("richtext.bold");
1761
+ const italicLabel = useMsg("richtext.italic");
1762
+ const linkLabel = useMsg("richtext.link");
1763
+ const linkPrompt = useMsg("richtext.link.prompt");
1764
+ React18__namespace.useEffect(() => {
1765
+ if (ref.current && ref.current.innerHTML !== value) {
1766
+ ref.current.innerHTML = value ?? "";
1767
+ }
1768
+ }, [value]);
1769
+ const exec = (cmd, val) => {
1770
+ document.execCommand(cmd, false, val);
1771
+ if (ref.current) onChange(ref.current.innerHTML);
1772
+ };
1773
+ 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: [
1774
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5 border-b px-1 py-0.5 bg-muted/30", children: [
1775
+ /* @__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" }) }),
1776
+ /* @__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" }) }),
1777
+ /* @__PURE__ */ jsxRuntime.jsx(
1778
+ Toggle,
1779
+ {
1780
+ size: "sm",
1781
+ onPressedChange: () => {
1782
+ const url = window.prompt(linkPrompt);
1783
+ if (url) exec("createLink", url);
1784
+ },
1785
+ "aria-label": linkLabel,
1786
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link, { className: "h-3.5 w-3.5" })
1787
+ }
1788
+ )
1789
+ ] }),
1790
+ /* @__PURE__ */ jsxRuntime.jsx(
1791
+ "div",
1792
+ {
1793
+ ref,
1794
+ contentEditable: !readOnly,
1795
+ suppressContentEditableWarning: true,
1796
+ onInput: () => {
1797
+ if (ref.current) onChange(ref.current.innerHTML);
1798
+ },
1799
+ className: "min-h-[60px] px-3 py-2 text-sm outline-none"
1800
+ }
1801
+ )
1802
+ ] }) });
1803
+ }
1804
+ function InputGroup({ className, ...props }) {
1805
+ return /* @__PURE__ */ jsxRuntime.jsx(
1806
+ "div",
1807
+ {
1808
+ "data-slot": "input-group",
1809
+ role: "group",
1810
+ className: cn(
1811
+ "group/input-group border-input dark:bg-input/30 shadow-xs relative flex w-full items-center rounded-md border outline-none transition-[color,box-shadow]",
1812
+ "h-9 has-[>textarea]:h-auto",
1813
+ // Variants based on alignment.
1814
+ "has-[>[data-align=inline-start]]:[&>input]:pl-2",
1815
+ "has-[>[data-align=inline-end]]:[&>input]:pr-2",
1816
+ "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
1817
+ "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
1818
+ // Focus state.
1819
+ "has-[[data-slot=input-group-control]:focus-visible]:ring-ring has-[[data-slot=input-group-control]:focus-visible]:ring-1",
1820
+ // Error state.
1821
+ "has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
1822
+ className
1823
+ ),
1824
+ ...props
1825
+ }
1826
+ );
1827
+ }
1828
+ var inputGroupAddonVariants = classVarianceAuthority.cva(
1829
+ "text-muted-foreground flex h-auto cursor-text select-none items-center justify-center gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
1830
+ {
1831
+ variants: {
1832
+ align: {
1833
+ "inline-start": "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
1834
+ "inline-end": "order-last pr-3 has-[>button]:mr-[-0.4rem] has-[>kbd]:mr-[-0.35rem]",
1835
+ "block-start": "[.border-b]:pb-3 order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5",
1836
+ "block-end": "[.border-t]:pt-3 order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5"
1837
+ }
1838
+ },
1839
+ defaultVariants: {
1840
+ align: "inline-start"
1841
+ }
1842
+ }
1843
+ );
1844
+ function InputGroupAddon({
1845
+ className,
1846
+ align = "inline-start",
1847
+ ...props
1848
+ }) {
1849
+ return /* @__PURE__ */ jsxRuntime.jsx(
1850
+ "div",
1851
+ {
1852
+ role: "group",
1853
+ "data-slot": "input-group-addon",
1854
+ "data-align": align,
1855
+ className: cn(inputGroupAddonVariants({ align }), className),
1856
+ onClick: (e) => {
1857
+ if (e.target.closest("button")) {
1858
+ return;
1859
+ }
1860
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
1861
+ },
1862
+ ...props
1863
+ }
1864
+ );
1865
+ }
1866
+ classVarianceAuthority.cva(
1867
+ "flex items-center gap-2 text-sm shadow-none",
1868
+ {
1869
+ variants: {
1870
+ size: {
1871
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5",
1872
+ sm: "h-8 gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5",
1873
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
1874
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0"
1875
+ }
1876
+ },
1877
+ defaultVariants: {
1878
+ size: "xs"
1879
+ }
1880
+ }
1881
+ );
1882
+ function Command({
1883
+ className,
1884
+ ...props
1885
+ }) {
1886
+ return /* @__PURE__ */ jsxRuntime.jsx(
1887
+ cmdk.Command,
1888
+ {
1889
+ "data-slot": "command",
1890
+ className: cn(
1891
+ "flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",
1892
+ className
1893
+ ),
1894
+ ...props
1895
+ }
1896
+ );
1897
+ }
1898
+ function CommandInput({
1899
+ className,
1900
+ ...props
1901
+ }) {
1902
+ 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: [
1903
+ /* @__PURE__ */ jsxRuntime.jsx(
1904
+ cmdk.Command.Input,
1905
+ {
1906
+ "data-slot": "command-input",
1907
+ className: cn(
1908
+ "w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
1909
+ className
1910
+ ),
1911
+ ...props
1912
+ }
1913
+ ),
1914
+ /* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SearchIcon, { className: "size-4 shrink-0 opacity-50" }) })
1915
+ ] }) });
1916
+ }
1917
+ function CommandList({
1918
+ className,
1919
+ ...props
1920
+ }) {
1921
+ return /* @__PURE__ */ jsxRuntime.jsx(
1922
+ cmdk.Command.List,
1923
+ {
1924
+ "data-slot": "command-list",
1925
+ className: cn(
1926
+ "no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none",
1927
+ className
1928
+ ),
1929
+ ...props
1930
+ }
1931
+ );
1932
+ }
1933
+ function CommandEmpty({
1934
+ className,
1935
+ ...props
1936
+ }) {
1937
+ return /* @__PURE__ */ jsxRuntime.jsx(
1938
+ cmdk.Command.Empty,
1939
+ {
1940
+ "data-slot": "command-empty",
1941
+ className: cn("py-6 text-center text-sm", className),
1942
+ ...props
1943
+ }
1944
+ );
1945
+ }
1946
+ function CommandItem({
1947
+ className,
1948
+ children,
1949
+ ...props
1950
+ }) {
1951
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1952
+ cmdk.Command.Item,
1953
+ {
1954
+ "data-slot": "command-item",
1955
+ className: cn(
1956
+ "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",
1957
+ className
1958
+ ),
1959
+ ...props,
1960
+ children: [
1961
+ children,
1962
+ /* @__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" })
1963
+ ]
1964
+ }
1965
+ );
1966
+ }
1967
+ function Skeleton({ className, ...props }) {
1968
+ return /* @__PURE__ */ jsxRuntime.jsx(
1969
+ "div",
1970
+ {
1971
+ "data-slot": "skeleton",
1972
+ className: cn("animate-pulse rounded-md bg-muted", className),
1973
+ ...props
1974
+ }
1975
+ );
1976
+ }
1977
+ function ExternalField({ value, onChange, fetchList, readOnly, label }) {
1978
+ const [query, setQuery] = React18__namespace.useState("");
1979
+ const [results, setResults] = React18__namespace.useState([]);
1980
+ const [loading, setLoading] = React18__namespace.useState(false);
1981
+ React18__namespace.useEffect(() => {
1982
+ if (!fetchList) return;
1983
+ setLoading(true);
1984
+ const timer = setTimeout(async () => {
1985
+ try {
1986
+ const data = await fetchList(query);
1987
+ setResults(data);
1988
+ } catch {
1989
+ setResults([]);
1990
+ } finally {
1991
+ setLoading(false);
1992
+ }
1993
+ }, 300);
1994
+ return () => clearTimeout(timer);
1995
+ }, [query, fetchList]);
1996
+ const selectedLabel = results.find((r) => r.value === value)?.label ?? String(value ?? "");
1997
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldLabel, { label: label ?? "", readOnly, children: /* @__PURE__ */ jsxRuntime.jsxs(Command, { className: "rounded-md border border-input", children: [
1998
+ /* @__PURE__ */ jsxRuntime.jsx(
1999
+ CommandInput,
2000
+ {
2001
+ placeholder: "Search...",
2002
+ value: query,
2003
+ onValueChange: setQuery,
2004
+ disabled: readOnly
2005
+ }
2006
+ ),
2007
+ /* @__PURE__ */ jsxRuntime.jsx(CommandList, { children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 p-2", children: [
2008
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-6 w-full" }),
2009
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-6 w-3/4" }),
2010
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-6 w-1/2" })
2011
+ ] }) : results.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(CommandEmpty, { children: "No results found." }) : results.map((r, i) => /* @__PURE__ */ jsxRuntime.jsx(
2012
+ CommandItem,
2013
+ {
2014
+ "data-checked": r.value === value,
2015
+ onSelect: () => onChange(r.value),
2016
+ children: r.label
2017
+ },
2018
+ i
2019
+ )) }),
2020
+ value != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t px-3 py-1.5 text-xs text-muted-foreground truncate", children: [
2021
+ "Selected: ",
2022
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: selectedLabel })
2023
+ ] })
2024
+ ] }) });
2025
+ }
2026
+
2027
+ // src/components/overrides/fields/FieldTypesRegistry.ts
2028
+ var fieldTypesRegistry = {
2029
+ text: TextField,
2030
+ textarea: TextareaField,
2031
+ number: NumberField,
2032
+ select: SelectField,
2033
+ radio: RadioField,
2034
+ array: ArrayField,
2035
+ object: ObjectField,
2036
+ slot: SlotField,
2037
+ custom: CustomField,
2038
+ richtext: RichtextField,
2039
+ external: ExternalField
2040
+ };
2041
+ function PuckRoot({ children }) {
2042
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
2043
+ }
2044
+ var puckOverrides = {
2045
+ header: EditorHeader,
2046
+ headerActions: EditorHeaderActions,
2047
+ drawer: EditorDrawer,
2048
+ components: EditorComponents,
2049
+ drawerItem: DrawerItem,
2050
+ componentItem: DrawerItem,
2051
+ outline: EditorOutline,
2052
+ iframe: CanvasIframe,
2053
+ preview: CanvasPreview,
2054
+ componentOverlay: ComponentOverlay,
2055
+ actionBar: ActionBar,
2056
+ fields: FieldWrapper,
2057
+ fieldTypes: fieldTypesRegistry,
2058
+ puck: PuckRoot
2059
+ };
2060
+ var DEFAULT_BOUNDS_OFFSET = {
2061
+ top: 0,
2062
+ left: 0,
2063
+ width: 0,
2064
+ height: 0
2065
+ };
2066
+ var HighlightContext = React18__namespace.createContext(void 0);
2067
+ function useHighlight() {
2068
+ const context = React18__namespace.useContext(HighlightContext);
2069
+ if (!context) {
2070
+ throw new Error("useHighlight must be used within a HighlightProvider");
2071
+ }
2072
+ return context;
2073
+ }
2074
+ function Highlight({
2075
+ ref,
2076
+ ...props
2077
+ }) {
2078
+ const {
2079
+ as: Component = "div",
2080
+ children,
2081
+ value,
2082
+ defaultValue,
2083
+ onValueChange,
2084
+ className,
2085
+ style,
2086
+ transition = { type: "spring", stiffness: 350, damping: 35 },
2087
+ hover = false,
2088
+ click = true,
2089
+ enabled = true,
2090
+ controlledItems,
2091
+ disabled = false,
2092
+ exitDelay = 200,
2093
+ mode = "children"
2094
+ } = props;
2095
+ const localRef = React18__namespace.useRef(null);
2096
+ React18__namespace.useImperativeHandle(ref, () => localRef.current);
2097
+ const propsBoundsOffset = props?.boundsOffset;
2098
+ const boundsOffset = propsBoundsOffset ?? DEFAULT_BOUNDS_OFFSET;
2099
+ const boundsOffsetTop = boundsOffset.top ?? 0;
2100
+ const boundsOffsetLeft = boundsOffset.left ?? 0;
2101
+ const boundsOffsetWidth = boundsOffset.width ?? 0;
2102
+ const boundsOffsetHeight = boundsOffset.height ?? 0;
2103
+ const boundsOffsetRef = React18__namespace.useRef({
2104
+ top: boundsOffsetTop,
2105
+ left: boundsOffsetLeft,
2106
+ width: boundsOffsetWidth,
2107
+ height: boundsOffsetHeight
2108
+ });
2109
+ React18__namespace.useEffect(() => {
2110
+ boundsOffsetRef.current = {
2111
+ top: boundsOffsetTop,
2112
+ left: boundsOffsetLeft,
2113
+ width: boundsOffsetWidth,
2114
+ height: boundsOffsetHeight
2115
+ };
2116
+ }, [
2117
+ boundsOffsetTop,
2118
+ boundsOffsetLeft,
2119
+ boundsOffsetWidth,
2120
+ boundsOffsetHeight
2121
+ ]);
2122
+ const [activeValue, setActiveValue] = React18__namespace.useState(
2123
+ value ?? defaultValue ?? null
2124
+ );
2125
+ const [boundsState, setBoundsState] = React18__namespace.useState(null);
2126
+ const [activeClassNameState, setActiveClassNameState] = React18__namespace.useState("");
2127
+ const safeSetActiveValue = (id2) => {
2128
+ setActiveValue((prev) => {
2129
+ if (prev !== id2) {
2130
+ onValueChange?.(id2);
2131
+ return id2;
2132
+ }
2133
+ return prev;
2134
+ });
2135
+ };
2136
+ const safeSetBoundsRef = React18__namespace.useRef(void 0);
2137
+ React18__namespace.useEffect(() => {
2138
+ safeSetBoundsRef.current = (bounds) => {
2139
+ if (!localRef.current) return;
2140
+ const containerRect = localRef.current.getBoundingClientRect();
2141
+ const offset = boundsOffsetRef.current;
2142
+ const newBounds = {
2143
+ top: bounds.top - containerRect.top + offset.top,
2144
+ left: bounds.left - containerRect.left + offset.left,
2145
+ width: bounds.width + offset.width,
2146
+ height: bounds.height + offset.height
2147
+ };
2148
+ setBoundsState((prev) => {
2149
+ if (prev && prev.top === newBounds.top && prev.left === newBounds.left && prev.width === newBounds.width && prev.height === newBounds.height) {
2150
+ return prev;
2151
+ }
2152
+ return newBounds;
2153
+ });
2154
+ };
2155
+ });
2156
+ const safeSetBounds = (bounds) => {
2157
+ safeSetBoundsRef.current?.(bounds);
2158
+ };
2159
+ const clearBounds = React18__namespace.useCallback(() => {
2160
+ setBoundsState((prev) => prev === null ? prev : null);
2161
+ }, []);
2162
+ React18__namespace.useEffect(() => {
2163
+ if (value !== void 0) setActiveValue(value);
2164
+ else if (defaultValue !== void 0) setActiveValue(defaultValue);
2165
+ }, [value, defaultValue]);
2166
+ const id = React18__namespace.useId();
2167
+ React18__namespace.useEffect(() => {
2168
+ if (mode !== "parent") return;
2169
+ const container = localRef.current;
2170
+ if (!container) return;
2171
+ const onScroll = () => {
2172
+ if (!activeValue) return;
2173
+ const activeEl = container.querySelector(
2174
+ `[data-value="${activeValue}"][data-highlight="true"]`
2175
+ );
2176
+ if (activeEl)
2177
+ safeSetBoundsRef.current?.(activeEl.getBoundingClientRect());
2178
+ };
2179
+ container.addEventListener("scroll", onScroll, { passive: true });
2180
+ return () => container.removeEventListener("scroll", onScroll);
2181
+ }, [mode, activeValue]);
2182
+ const render = (children2) => {
2183
+ if (mode === "parent") {
2184
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2185
+ Component,
2186
+ {
2187
+ ref: localRef,
2188
+ "data-slot": "motion-highlight-container",
2189
+ style: { position: "relative", zIndex: 1 },
2190
+ className: props?.containerClassName,
2191
+ children: [
2192
+ /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { initial: false, mode: "wait", children: boundsState && /* @__PURE__ */ jsxRuntime.jsx(
2193
+ react.motion.div,
2194
+ {
2195
+ "data-slot": "motion-highlight",
2196
+ animate: {
2197
+ top: boundsState.top,
2198
+ left: boundsState.left,
2199
+ width: boundsState.width,
2200
+ height: boundsState.height,
2201
+ opacity: 1
2202
+ },
2203
+ initial: {
2204
+ top: boundsState.top,
2205
+ left: boundsState.left,
2206
+ width: boundsState.width,
2207
+ height: boundsState.height,
2208
+ opacity: 0
2209
+ },
2210
+ exit: {
2211
+ opacity: 0,
2212
+ transition: {
2213
+ ...transition,
2214
+ delay: (transition?.delay ?? 0) + (exitDelay ?? 0) / 1e3
2215
+ }
2216
+ },
2217
+ transition,
2218
+ style: { position: "absolute", zIndex: 0, ...style },
2219
+ className: cn(className, activeClassNameState)
2220
+ }
2221
+ ) }),
2222
+ children2
2223
+ ]
2224
+ }
2225
+ );
2226
+ }
2227
+ return children2;
2228
+ };
2229
+ return /* @__PURE__ */ jsxRuntime.jsx(
2230
+ HighlightContext.Provider,
2231
+ {
2232
+ value: {
2233
+ mode,
2234
+ activeValue,
2235
+ setActiveValue: safeSetActiveValue,
2236
+ id,
2237
+ hover,
2238
+ click,
2239
+ className,
2240
+ style,
2241
+ transition,
2242
+ disabled,
2243
+ enabled,
2244
+ exitDelay,
2245
+ setBounds: safeSetBounds,
2246
+ clearBounds,
2247
+ activeClassName: activeClassNameState,
2248
+ setActiveClassName: setActiveClassNameState,
2249
+ forceUpdateBounds: props?.forceUpdateBounds
2250
+ },
2251
+ children: enabled ? controlledItems ? render(children) : render(
2252
+ React18__namespace.Children.map(children, (child, index) => /* @__PURE__ */ jsxRuntime.jsx(HighlightItem, { className: props?.itemsClassName, children: child }, index))
2253
+ ) : children
2254
+ }
2255
+ );
2256
+ }
2257
+ function getNonOverridingDataAttributes(element, dataAttributes) {
2258
+ return Object.keys(dataAttributes).reduce(
2259
+ (acc, key) => {
2260
+ if (element.props[key] === void 0) {
2261
+ acc[key] = dataAttributes[key];
2262
+ }
2263
+ return acc;
2264
+ },
2265
+ {}
2266
+ );
2267
+ }
2268
+ function HighlightItem({
2269
+ ref,
2270
+ as,
2271
+ children,
2272
+ id,
2273
+ value,
2274
+ className,
2275
+ style,
2276
+ transition,
2277
+ disabled = false,
2278
+ activeClassName,
2279
+ exitDelay,
2280
+ asChild = false,
2281
+ forceUpdateBounds,
2282
+ ...props
2283
+ }) {
2284
+ const itemId = React18__namespace.useId();
2285
+ const {
2286
+ activeValue,
2287
+ setActiveValue,
2288
+ mode,
2289
+ setBounds,
2290
+ clearBounds,
2291
+ hover,
2292
+ click,
2293
+ enabled,
2294
+ className: contextClassName,
2295
+ style: contextStyle,
2296
+ transition: contextTransition,
2297
+ id: contextId,
2298
+ disabled: contextDisabled,
2299
+ exitDelay: contextExitDelay,
2300
+ forceUpdateBounds: contextForceUpdateBounds,
2301
+ setActiveClassName
2302
+ } = useHighlight();
2303
+ const Component = as ?? "div";
2304
+ const element = children;
2305
+ const childValue = id ?? value ?? element.props?.["data-value"] ?? element.props?.id ?? itemId;
2306
+ const isActive = activeValue === childValue;
2307
+ const isDisabled = disabled === void 0 ? contextDisabled : disabled;
2308
+ const itemTransition = transition ?? contextTransition;
2309
+ const localRef = React18__namespace.useRef(null);
2310
+ React18__namespace.useImperativeHandle(ref, () => localRef.current);
2311
+ const refCallback = React18__namespace.useCallback((node) => {
2312
+ localRef.current = node;
2313
+ }, []);
2314
+ React18__namespace.useEffect(() => {
2315
+ if (mode !== "parent") return;
2316
+ let rafId;
2317
+ let previousBounds = null;
2318
+ const shouldUpdateBounds = forceUpdateBounds === true || contextForceUpdateBounds && forceUpdateBounds !== false;
2319
+ const updateBounds = () => {
2320
+ if (!localRef.current) return;
2321
+ const bounds = localRef.current.getBoundingClientRect();
2322
+ if (shouldUpdateBounds) {
2323
+ if (previousBounds && previousBounds.top === bounds.top && previousBounds.left === bounds.left && previousBounds.width === bounds.width && previousBounds.height === bounds.height) {
2324
+ rafId = requestAnimationFrame(updateBounds);
2325
+ return;
2326
+ }
2327
+ previousBounds = bounds;
2328
+ rafId = requestAnimationFrame(updateBounds);
2329
+ }
2330
+ setBounds(bounds);
2331
+ };
2332
+ if (isActive) {
2333
+ updateBounds();
2334
+ setActiveClassName(activeClassName ?? "");
2335
+ } else if (!activeValue) clearBounds();
2336
+ if (shouldUpdateBounds) return () => cancelAnimationFrame(rafId);
2337
+ }, [
2338
+ mode,
2339
+ isActive,
2340
+ activeValue,
2341
+ setBounds,
2342
+ clearBounds,
2343
+ activeClassName,
2344
+ setActiveClassName,
2345
+ forceUpdateBounds,
2346
+ contextForceUpdateBounds
2347
+ ]);
2348
+ if (!React18__namespace.isValidElement(children)) return children;
2349
+ const dataAttributes = {
2350
+ "data-active": isActive ? "true" : "false",
2351
+ "aria-selected": isActive,
2352
+ "data-disabled": isDisabled,
2353
+ "data-value": childValue,
2354
+ "data-highlight": true
2355
+ };
2356
+ const commonHandlers = hover ? {
2357
+ onMouseEnter: (e) => {
2358
+ setActiveValue(childValue);
2359
+ element.props.onMouseEnter?.(e);
2360
+ },
2361
+ onMouseLeave: (e) => {
2362
+ setActiveValue(null);
2363
+ element.props.onMouseLeave?.(e);
2364
+ }
2365
+ } : click ? {
2366
+ onClick: (e) => {
2367
+ setActiveValue(childValue);
2368
+ element.props.onClick?.(e);
2369
+ }
2370
+ } : {};
2371
+ if (asChild) {
2372
+ if (mode === "children") {
2373
+ return React18__namespace.cloneElement(
2374
+ element,
2375
+ {
2376
+ key: childValue,
2377
+ ref: refCallback,
2378
+ className: cn("relative", element.props.className),
2379
+ ...getNonOverridingDataAttributes(element, {
2380
+ ...dataAttributes,
2381
+ "data-slot": "motion-highlight-item-container"
2382
+ }),
2383
+ ...commonHandlers,
2384
+ ...props
2385
+ },
2386
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2387
+ /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { initial: false, mode: "wait", children: isActive && !isDisabled && /* @__PURE__ */ jsxRuntime.jsx(
2388
+ react.motion.div,
2389
+ {
2390
+ layoutId: `transition-background-${contextId}`,
2391
+ "data-slot": "motion-highlight",
2392
+ style: {
2393
+ position: "absolute",
2394
+ zIndex: 0,
2395
+ ...contextStyle,
2396
+ ...style
2397
+ },
2398
+ className: cn(contextClassName, activeClassName),
2399
+ transition: itemTransition,
2400
+ initial: { opacity: 0 },
2401
+ animate: { opacity: 1 },
2402
+ exit: {
2403
+ opacity: 0,
2404
+ transition: {
2405
+ ...itemTransition,
2406
+ delay: (itemTransition?.delay ?? 0) + (exitDelay ?? contextExitDelay ?? 0) / 1e3
2407
+ }
2408
+ },
2409
+ ...dataAttributes
2410
+ }
2411
+ ) }),
2412
+ /* @__PURE__ */ jsxRuntime.jsx(
2413
+ Component,
2414
+ {
2415
+ "data-slot": "motion-highlight-item",
2416
+ style: { position: "relative", zIndex: 1 },
2417
+ className,
2418
+ ...dataAttributes,
2419
+ children
2420
+ }
2421
+ )
2422
+ ] })
2423
+ );
2424
+ }
2425
+ return React18__namespace.cloneElement(element, {
2426
+ ref: refCallback,
2427
+ ...getNonOverridingDataAttributes(element, {
2428
+ ...dataAttributes,
2429
+ "data-slot": "motion-highlight-item"
2430
+ }),
2431
+ ...commonHandlers
2432
+ });
2433
+ }
2434
+ return enabled ? /* @__PURE__ */ jsxRuntime.jsxs(
2435
+ Component,
2436
+ {
2437
+ ref: localRef,
2438
+ "data-slot": "motion-highlight-item-container",
2439
+ className: cn(mode === "children" && "relative", className),
2440
+ ...dataAttributes,
2441
+ ...props,
2442
+ ...commonHandlers,
2443
+ children: [
2444
+ mode === "children" && /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { initial: false, mode: "wait", children: isActive && !isDisabled && /* @__PURE__ */ jsxRuntime.jsx(
2445
+ react.motion.div,
2446
+ {
2447
+ layoutId: `transition-background-${contextId}`,
2448
+ "data-slot": "motion-highlight",
2449
+ style: {
2450
+ position: "absolute",
2451
+ zIndex: 0,
2452
+ ...contextStyle,
2453
+ ...style
2454
+ },
2455
+ className: cn(contextClassName, activeClassName),
2456
+ transition: itemTransition,
2457
+ initial: { opacity: 0 },
2458
+ animate: { opacity: 1 },
2459
+ exit: {
2460
+ opacity: 0,
2461
+ transition: {
2462
+ ...itemTransition,
2463
+ delay: (itemTransition?.delay ?? 0) + (exitDelay ?? contextExitDelay ?? 0) / 1e3
2464
+ }
2465
+ },
2466
+ ...dataAttributes
2467
+ }
2468
+ ) }),
2469
+ React18__namespace.cloneElement(element, {
2470
+ style: { position: "relative", zIndex: 1 },
2471
+ className: element.props.className,
2472
+ ...getNonOverridingDataAttributes(element, {
2473
+ ...dataAttributes,
2474
+ "data-slot": "motion-highlight-item"
2475
+ })
2476
+ })
2477
+ ]
2478
+ },
2479
+ childValue
2480
+ ) : children;
2481
+ }
2482
+ function mergeRefs(...refs) {
2483
+ return (node) => {
2484
+ refs.forEach((ref) => {
2485
+ if (!ref) return;
2486
+ if (typeof ref === "function") {
2487
+ ref(node);
2488
+ } else {
2489
+ ref.current = node;
2490
+ }
2491
+ });
2492
+ };
2493
+ }
2494
+ function mergeProps4(childProps, slotProps) {
2495
+ const merged = { ...childProps, ...slotProps };
2496
+ if (childProps.className || slotProps.className) {
2497
+ merged.className = cn(
2498
+ childProps.className,
2499
+ slotProps.className
2500
+ );
2501
+ }
2502
+ if (childProps.style || slotProps.style) {
2503
+ merged.style = {
2504
+ ...childProps.style,
2505
+ ...slotProps.style
2506
+ };
2507
+ }
2508
+ return merged;
2509
+ }
2510
+ function Slot({
2511
+ children,
2512
+ ref,
2513
+ ...props
2514
+ }) {
2515
+ const isAlreadyMotion = typeof children.type === "object" && children.type !== null && react.isMotionComponent(children.type);
2516
+ const Base = React18__namespace.useMemo(
2517
+ () => isAlreadyMotion ? children.type : react.motion.create(children.type),
2518
+ [isAlreadyMotion, children.type]
2519
+ );
2520
+ if (!React18__namespace.isValidElement(children)) return null;
2521
+ const { ref: childRef, ...childProps } = children.props;
2522
+ const mergedProps = mergeProps4(childProps, props);
2523
+ return /* @__PURE__ */ jsxRuntime.jsx(Base, { ...mergedProps, ref: mergeRefs(childRef, ref) });
2524
+ }
2525
+ var [TabsProvider, useTabs] = getStrictContext("TabsContext");
2526
+ function Tabs(props) {
2527
+ const [value, setValue] = useControlledState({
2528
+ value: props.value,
2529
+ defaultValue: props.defaultValue,
2530
+ onChange: props.onValueChange
2531
+ });
2532
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsProvider, { value: { value, setValue }, children: /* @__PURE__ */ jsxRuntime.jsx(
2533
+ tabs.Tabs.Root,
2534
+ {
2535
+ "data-slot": "tabs",
2536
+ ...props,
2537
+ onValueChange: setValue
2538
+ }
2539
+ ) });
2540
+ }
2541
+ function TabsHighlight({
2542
+ transition = { type: "spring", stiffness: 200, damping: 25 },
2543
+ ...props
2544
+ }) {
2545
+ const { value } = useTabs();
2546
+ return /* @__PURE__ */ jsxRuntime.jsx(
2547
+ Highlight,
2548
+ {
2549
+ "data-slot": "tabs-highlight",
2550
+ controlledItems: true,
2551
+ value,
2552
+ transition,
2553
+ click: false,
2554
+ ...props
2555
+ }
2556
+ );
2557
+ }
2558
+ function TabsList(props) {
2559
+ return /* @__PURE__ */ jsxRuntime.jsx(tabs.Tabs.List, { "data-slot": "tabs-list", ...props });
2560
+ }
2561
+ function TabsHighlightItem(props) {
2562
+ return /* @__PURE__ */ jsxRuntime.jsx(HighlightItem, { "data-slot": "tabs-highlight-item", ...props });
2563
+ }
2564
+ function TabsTab(props) {
2565
+ return /* @__PURE__ */ jsxRuntime.jsx(tabs.Tabs.Tab, { "data-slot": "tabs-tab", ...props });
2566
+ }
2567
+ function Tabs2({ className, ...props }) {
2568
+ return /* @__PURE__ */ jsxRuntime.jsx(
2569
+ Tabs,
2570
+ {
2571
+ className: cn("flex flex-col gap-2", className),
2572
+ ...props
2573
+ }
2574
+ );
2575
+ }
2576
+ function TabsList2({ className, ...props }) {
2577
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsHighlight, { className: "absolute z-0 inset-0 border border-transparent rounded-md bg-background dark:border-input dark:bg-input/30 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx(
2578
+ TabsList,
2579
+ {
2580
+ className: cn(
2581
+ "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
2582
+ className
2583
+ ),
2584
+ ...props
2585
+ }
2586
+ ) });
2587
+ }
2588
+ function TabsTab2({ className, ...props }) {
2589
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsHighlightItem, { value: props.value, className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
2590
+ TabsTab,
2591
+ {
2592
+ className: cn(
2593
+ "data-[selected]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md w-full px-2 py-1 text-sm font-medium whitespace-nowrap transition-colors duration-500 ease-in-out focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
2594
+ className
2595
+ ),
2596
+ ...props
2597
+ }
2598
+ ) });
2599
+ }
2600
+ function Aside() {
2601
+ const activeTab = useActiveTab();
2602
+ const setActiveTab = useSetActiveTab();
2603
+ const tabs = [
2604
+ { value: "insert", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }), label: useMsg("aside.insert") },
2605
+ { value: "layer", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Layers2, { className: "h-4 w-4" }), label: useMsg("aside.layer") },
2606
+ { value: "image", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "h-4 w-4" }), label: useMsg("aside.image") },
2607
+ { value: "text", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Type, { className: "h-4 w-4" }), label: useMsg("aside.text") },
2608
+ { value: "copilot", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bot, { className: "h-4 w-4" }), label: useMsg("aside.copilot") }
2609
+ ];
2610
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-18 h-full py-4 border-r border-neutral-200 dark:border-neutral-800/80", children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(Tabs2, { value: activeTab, onValueChange: setActiveTab, className: "w-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(TabsList2, { className: "flex-col h-auto bg-transparent gap-2", children: tabs.map(({ value, icon, label }) => /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
2611
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: /* @__PURE__ */ jsxRuntime.jsx(TabsTab2, { value, className: "p-2", children: icon }) }) }),
2612
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "right", children: label })
2613
+ ] }, value)) }) }) }) });
2614
+ }
2615
+ function AnimatedAsana({
2616
+ trigger = false,
2617
+ useTrigger = true,
2618
+ // Enable hover trigger by default
2619
+ animationDuration = 400,
2620
+ // Default animation duration
2621
+ springConfig = {
2622
+ stiffness: 180,
2623
+ damping: 15,
2624
+ mass: 1
2625
+ },
2626
+ priority = false,
2627
+ // Default non-priority
2628
+ ...props
2629
+ }) {
2630
+ const [isHovered, setIsHovered] = React18.useState(false);
2631
+ const [animationPhase, setAnimationPhase] = React18.useState("three-circles");
2632
+ const animationTimerRef = React18.useRef(null);
2633
+ const animationStartedRef = React18.useRef(false);
2634
+ const effectiveTrigger = React18.useMemo(
2635
+ () => trigger || useTrigger && isHovered,
2636
+ [trigger, useTrigger, isHovered]
2637
+ );
2638
+ const springTransition = React18.useMemo(
2639
+ () => ({
2640
+ type: "spring",
2641
+ stiffness: springConfig.stiffness,
2642
+ damping: springConfig.damping,
2643
+ mass: springConfig.mass
2644
+ }),
2645
+ [springConfig.stiffness, springConfig.damping, springConfig.mass]
2646
+ );
2647
+ const handleMouseEnter = React18.useCallback(() => {
2648
+ if (useTrigger) {
2649
+ setIsHovered(true);
2650
+ }
2651
+ }, [useTrigger]);
2652
+ const handleMouseLeave = React18.useCallback(() => {
2653
+ if (useTrigger) {
2654
+ setIsHovered(false);
2655
+ }
2656
+ }, [useTrigger]);
2657
+ React18.useEffect(() => {
2658
+ if (animationTimerRef.current) {
2659
+ clearTimeout(animationTimerRef.current);
2660
+ animationTimerRef.current = null;
2661
+ }
2662
+ if (effectiveTrigger) {
2663
+ animationStartedRef.current = true;
2664
+ setAnimationPhase("one-circle");
2665
+ animationTimerRef.current = setTimeout(() => {
2666
+ setAnimationPhase("three-circles");
2667
+ animationTimerRef.current = null;
2668
+ }, animationDuration);
2669
+ } else if (animationStartedRef.current) {
2670
+ setAnimationPhase("three-circles");
2671
+ animationStartedRef.current = false;
2672
+ }
2673
+ return () => {
2674
+ if (animationTimerRef.current) {
2675
+ clearTimeout(animationTimerRef.current);
2676
+ animationTimerRef.current = null;
2677
+ }
2678
+ };
2679
+ }, [effectiveTrigger, animationDuration]);
2680
+ const centerCircleAnimation = React18.useMemo(
2681
+ () => ({
2682
+ opacity: animationPhase === "one-circle" ? 1 : 0,
2683
+ scale: animationPhase === "one-circle" ? 1 : 0
2684
+ }),
2685
+ [animationPhase]
2686
+ );
2687
+ const topCircleAnimation = React18.useMemo(
2688
+ () => ({
2689
+ opacity: animationPhase === "three-circles" ? 1 : 0,
2690
+ y: animationPhase === "three-circles" ? 0 : 4.5,
2691
+ scale: animationPhase === "three-circles" ? 1 : 0
2692
+ }),
2693
+ [animationPhase]
2694
+ );
2695
+ const leftBottomCircleAnimation = React18.useMemo(
2696
+ () => ({
2697
+ opacity: animationPhase === "three-circles" ? 1 : 0,
2698
+ x: animationPhase === "three-circles" ? 0 : 5,
2699
+ y: animationPhase === "three-circles" ? 0 : -4.5,
2700
+ scale: animationPhase === "three-circles" ? 1 : 0
2701
+ }),
2702
+ [animationPhase]
2703
+ );
2704
+ const rightBottomCircleAnimation = React18.useMemo(
2705
+ () => ({
2706
+ opacity: animationPhase === "three-circles" ? 1 : 0,
2707
+ x: animationPhase === "three-circles" ? 0 : -5,
2708
+ y: animationPhase === "three-circles" ? 0 : -4.5,
2709
+ scale: animationPhase === "three-circles" ? 1 : 0
2710
+ }),
2711
+ [animationPhase]
2712
+ );
2713
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2714
+ "svg",
2715
+ {
2716
+ width: "1em",
2717
+ height: "1em",
2718
+ strokeWidth: "1.5",
2719
+ viewBox: "0 0 24 24",
2720
+ fill: "none",
2721
+ xmlns: "http://www.w3.org/2000/svg",
2722
+ color: "currentColor",
2723
+ onMouseEnter: handleMouseEnter,
2724
+ onMouseLeave: handleMouseLeave,
2725
+ role: "img",
2726
+ "aria-label": "Asana logo",
2727
+ style: { touchAction: "none" },
2728
+ "data-testid": "asana-icon",
2729
+ ...props,
2730
+ children: [
2731
+ /* @__PURE__ */ jsxRuntime.jsx(
2732
+ react.motion.circle,
2733
+ {
2734
+ cx: 12,
2735
+ cy: 12,
2736
+ r: 6,
2737
+ stroke: "currentColor",
2738
+ strokeWidth: "1.5",
2739
+ strokeLinecap: "round",
2740
+ strokeLinejoin: "round",
2741
+ fill: "none",
2742
+ initial: { opacity: 0, scale: 0 },
2743
+ animate: centerCircleAnimation,
2744
+ transition: {
2745
+ opacity: { duration: 0.2 },
2746
+ scale: { ...springTransition, duration: 0.3 }
2747
+ }
2748
+ }
2749
+ ),
2750
+ /* @__PURE__ */ jsxRuntime.jsx(
2751
+ react.motion.path,
2752
+ {
2753
+ d: "M12 11.5C14.2091 11.5 16 9.70914 16 7.5C16 5.29086 14.2091 3.5 12 3.5C9.79086 3.5 8 5.29086 8 7.5C8 9.70914 9.79086 11.5 12 11.5Z",
2754
+ stroke: "currentColor",
2755
+ strokeWidth: "1.5",
2756
+ strokeLinecap: "round",
2757
+ strokeLinejoin: "round",
2758
+ fill: "none",
2759
+ initial: { opacity: 1, y: 0, scale: 1 },
2760
+ animate: topCircleAnimation,
2761
+ transition: {
2762
+ ...springTransition,
2763
+ delay: animationPhase === "three-circles" ? 0.1 : 0
2764
+ }
2765
+ }
2766
+ ),
2767
+ /* @__PURE__ */ jsxRuntime.jsx(
2768
+ react.motion.path,
2769
+ {
2770
+ d: "M7 20.5C9.20914 20.5 11 18.7091 11 16.5C11 14.2909 9.20914 12.5 7 12.5C4.79086 12.5 3 14.2909 3 16.5C3 18.7091 4.79086 20.5 7 20.5Z",
2771
+ stroke: "currentColor",
2772
+ strokeWidth: "1.5",
2773
+ strokeLinecap: "round",
2774
+ strokeLinejoin: "round",
2775
+ fill: "none",
2776
+ initial: { opacity: 1, x: 0, y: 0, scale: 1 },
2777
+ animate: leftBottomCircleAnimation,
2778
+ transition: {
2779
+ ...springTransition,
2780
+ delay: animationPhase === "three-circles" ? 0.15 : 0.05
2781
+ }
2782
+ }
2783
+ ),
2784
+ /* @__PURE__ */ jsxRuntime.jsx(
2785
+ react.motion.path,
2786
+ {
2787
+ d: "M17 20.5C19.2091 20.5 21 18.7091 21 16.5C21 14.2909 19.2091 12.5 17 12.5C14.7909 12.5 13 14.2909 13 16.5C13 18.7091 14.7909 20.5 17 20.5Z",
2788
+ stroke: "currentColor",
2789
+ strokeWidth: "1.5",
2790
+ strokeLinecap: "round",
2791
+ strokeLinejoin: "round",
2792
+ fill: "none",
2793
+ initial: { opacity: 1, x: 0, y: 0, scale: 1 },
2794
+ animate: rightBottomCircleAnimation,
2795
+ transition: {
2796
+ ...springTransition,
2797
+ delay: animationPhase === "three-circles" ? 0.2 : 0.1
2798
+ }
2799
+ }
2800
+ )
2801
+ ]
2802
+ }
2803
+ );
2804
+ }
2805
+ React18__namespace.default.memo(function TriggerableAsana2(props) {
2806
+ return /* @__PURE__ */ jsxRuntime.jsx(AnimatedAsana, { useTrigger: true, ...props });
2807
+ });
2808
+ React18__namespace.default.memo(function ControlledAsana2(props) {
2809
+ return /* @__PURE__ */ jsxRuntime.jsx(AnimatedAsana, { useTrigger: false, ...props });
2810
+ });
2811
+ var [GlobalTooltipProvider, useGlobalTooltip] = getStrictContext("GlobalTooltipProvider");
2812
+ var [LocalTooltipProvider, useTooltip] = getStrictContext(
2813
+ "LocalTooltipProvider"
2814
+ );
2815
+ function getResolvedSide(placement) {
2816
+ if (placement.includes("-")) {
2817
+ return placement.split("-")[0];
2818
+ }
2819
+ return placement;
2820
+ }
2821
+ function initialFromSide(side) {
2822
+ if (side === "top") return { y: 15 };
2823
+ if (side === "bottom") return { y: -15 };
2824
+ if (side === "left") return { x: 15 };
2825
+ return { x: -15 };
2826
+ }
2827
+ function TooltipProvider2({
2828
+ children,
2829
+ id,
2830
+ openDelay = 700,
2831
+ closeDelay = 300,
2832
+ transition = { type: "spring", stiffness: 300, damping: 35 }
2833
+ }) {
2834
+ const globalId = React18__namespace.useId();
2835
+ const [currentTooltip, setCurrentTooltip] = React18__namespace.useState(null);
2836
+ const timeoutRef = React18__namespace.useRef(null);
2837
+ const lastCloseTimeRef = React18__namespace.useRef(0);
2838
+ const referenceElRef = React18__namespace.useRef(null);
2839
+ const showTooltip = React18__namespace.useCallback(
2840
+ (data) => {
2841
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
2842
+ if (currentTooltip !== null) {
2843
+ setCurrentTooltip(data);
2844
+ return;
2845
+ }
2846
+ const now = Date.now();
2847
+ const delay = now - lastCloseTimeRef.current < closeDelay ? 0 : openDelay;
2848
+ timeoutRef.current = window.setTimeout(
2849
+ () => setCurrentTooltip(data),
2850
+ delay
2851
+ );
2852
+ },
2853
+ [openDelay, closeDelay, currentTooltip]
2854
+ );
2855
+ const hideTooltip = React18__namespace.useCallback(() => {
2856
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
2857
+ timeoutRef.current = window.setTimeout(() => {
2858
+ setCurrentTooltip(null);
2859
+ lastCloseTimeRef.current = Date.now();
2860
+ }, closeDelay);
2861
+ }, [closeDelay]);
2862
+ const hideImmediate = React18__namespace.useCallback(() => {
2863
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
2864
+ setCurrentTooltip(null);
2865
+ lastCloseTimeRef.current = Date.now();
2866
+ }, []);
2867
+ const setReferenceEl = React18__namespace.useCallback((el) => {
2868
+ referenceElRef.current = el;
2869
+ }, []);
2870
+ React18__namespace.useEffect(() => {
2871
+ const onKeyDown = (e) => {
2872
+ if (e.key === "Escape") hideImmediate();
2873
+ };
2874
+ window.addEventListener("keydown", onKeyDown, true);
2875
+ window.addEventListener("scroll", hideImmediate, true);
2876
+ window.addEventListener("resize", hideImmediate, true);
2877
+ return () => {
2878
+ window.removeEventListener("keydown", onKeyDown, true);
2879
+ window.removeEventListener("scroll", hideImmediate, true);
2880
+ window.removeEventListener("resize", hideImmediate, true);
2881
+ };
2882
+ }, [hideImmediate]);
2883
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2884
+ GlobalTooltipProvider,
2885
+ {
2886
+ value: {
2887
+ showTooltip,
2888
+ hideTooltip,
2889
+ hideImmediate,
2890
+ currentTooltip,
2891
+ transition,
2892
+ globalId: id ?? globalId,
2893
+ setReferenceEl,
2894
+ referenceElRef
2895
+ },
2896
+ children: [
2897
+ /* @__PURE__ */ jsxRuntime.jsx(react.LayoutGroup, { children }),
2898
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipOverlay, {})
2899
+ ]
2900
+ }
2901
+ );
2902
+ }
2903
+ var [RenderedTooltipProvider, useRenderedTooltip] = getStrictContext("RenderedTooltipContext");
2904
+ var [FloatingProvider, useFloatingContext] = getStrictContext("FloatingContext");
2905
+ var MotionTooltipArrow = react.motion.create(react$1.FloatingArrow);
2906
+ function TooltipArrow({
2907
+ ref,
2908
+ withTransition = true,
2909
+ ...props
2910
+ }) {
2911
+ const { side, align, open } = useRenderedTooltip();
2912
+ const { context, arrowRef } = useFloatingContext();
2913
+ const { transition, globalId } = useGlobalTooltip();
2914
+ React18__namespace.useImperativeHandle(ref, () => arrowRef.current);
2915
+ const deg = { top: 0, right: 90, bottom: 180, left: -90 }[side];
2916
+ return /* @__PURE__ */ jsxRuntime.jsx(
2917
+ MotionTooltipArrow,
2918
+ {
2919
+ ref: arrowRef,
2920
+ context,
2921
+ "data-state": open ? "open" : "closed",
2922
+ "data-side": side,
2923
+ "data-align": align,
2924
+ "data-slot": "tooltip-arrow",
2925
+ style: { rotate: deg },
2926
+ layoutId: withTransition ? `tooltip-arrow-${globalId}` : void 0,
2927
+ transition: withTransition ? transition : void 0,
2928
+ ...props
2929
+ }
2930
+ );
2931
+ }
2932
+ function TooltipPortal(props) {
2933
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.FloatingPortal, { ...props });
2934
+ }
2935
+ function TooltipOverlay() {
2936
+ const { currentTooltip, transition, globalId, referenceElRef } = useGlobalTooltip();
2937
+ const [rendered, setRendered] = React18__namespace.useState({ data: null, open: false });
2938
+ const arrowRef = React18__namespace.useRef(null);
2939
+ const side = rendered.data?.side ?? "top";
2940
+ const align = rendered.data?.align ?? "center";
2941
+ const { refs, x, y, strategy, context, update } = react$1.useFloating({
2942
+ placement: align === "center" ? side : `${side}-${align}`,
2943
+ whileElementsMounted: react$1.autoUpdate,
2944
+ middleware: [
2945
+ react$1.offset({
2946
+ mainAxis: rendered.data?.sideOffset ?? 0,
2947
+ crossAxis: rendered.data?.alignOffset ?? 0
2948
+ }),
2949
+ react$1.flip(),
2950
+ react$1.shift({ padding: 8 }),
2951
+ react$1.arrow({ element: arrowRef })
2952
+ ]
2953
+ });
2954
+ React18__namespace.useEffect(() => {
2955
+ if (currentTooltip) {
2956
+ setRendered({ data: currentTooltip, open: true });
2957
+ } else {
2958
+ setRendered((p) => p.data ? { ...p, open: false } : p);
2959
+ }
2960
+ }, [currentTooltip]);
2961
+ React18__namespace.useLayoutEffect(() => {
2962
+ if (referenceElRef.current) {
2963
+ refs.setReference(referenceElRef.current);
2964
+ update();
2965
+ }
2966
+ }, [referenceElRef, refs, update, rendered.data]);
2967
+ const ready = x != null && y != null;
2968
+ const Component = rendered.data?.contentAsChild ? Slot : react.motion.div;
2969
+ const resolvedSide = getResolvedSide(context.placement);
2970
+ return /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { mode: "wait", children: rendered.data && ready && /* @__PURE__ */ jsxRuntime.jsx(TooltipPortal, { children: /* @__PURE__ */ jsxRuntime.jsx(
2971
+ "div",
2972
+ {
2973
+ ref: refs.setFloating,
2974
+ "data-slot": "tooltip-overlay",
2975
+ "data-side": resolvedSide,
2976
+ "data-align": rendered.data.align,
2977
+ "data-state": rendered.open ? "open" : "closed",
2978
+ style: {
2979
+ position: strategy,
2980
+ top: 0,
2981
+ left: 0,
2982
+ zIndex: 50,
2983
+ transform: `translate3d(${x}px, ${y}px, 0)`
2984
+ },
2985
+ children: /* @__PURE__ */ jsxRuntime.jsx(FloatingProvider, { value: { context, arrowRef }, children: /* @__PURE__ */ jsxRuntime.jsx(
2986
+ RenderedTooltipProvider,
2987
+ {
2988
+ value: {
2989
+ side: resolvedSide,
2990
+ align: rendered.data.align,
2991
+ open: rendered.open
2992
+ },
2993
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2994
+ Component,
2995
+ {
2996
+ "data-slot": "tooltip-content",
2997
+ "data-side": resolvedSide,
2998
+ "data-align": rendered.data.align,
2999
+ "data-state": rendered.open ? "open" : "closed",
3000
+ layoutId: `tooltip-content-${globalId}`,
3001
+ initial: {
3002
+ opacity: 0,
3003
+ scale: 0,
3004
+ ...initialFromSide(rendered.data.side)
3005
+ },
3006
+ animate: rendered.open ? { opacity: 1, scale: 1, x: 0, y: 0 } : {
3007
+ opacity: 0,
3008
+ scale: 0,
3009
+ ...initialFromSide(rendered.data.side)
3010
+ },
3011
+ exit: {
3012
+ opacity: 0,
3013
+ scale: 0,
3014
+ ...initialFromSide(rendered.data.side)
3015
+ },
3016
+ onAnimationComplete: () => {
3017
+ if (!rendered.open)
3018
+ setRendered({ data: null, open: false });
3019
+ },
3020
+ transition,
3021
+ ...rendered.data.contentProps,
3022
+ style: {
3023
+ position: "relative",
3024
+ ...rendered.data.contentProps?.style || {}
3025
+ }
3026
+ }
3027
+ )
3028
+ }
3029
+ ) })
3030
+ }
3031
+ ) }) });
3032
+ }
3033
+ function Tooltip2({
3034
+ children,
3035
+ side = "top",
3036
+ sideOffset = 0,
3037
+ align = "center",
3038
+ alignOffset = 0
3039
+ }) {
3040
+ const id = React18__namespace.useId();
3041
+ const [props, setProps] = React18__namespace.useState({});
3042
+ const [asChild, setAsChild] = React18__namespace.useState(false);
3043
+ return /* @__PURE__ */ jsxRuntime.jsx(
3044
+ LocalTooltipProvider,
3045
+ {
3046
+ value: {
3047
+ props,
3048
+ setProps,
3049
+ asChild,
3050
+ setAsChild,
3051
+ side,
3052
+ sideOffset,
3053
+ align,
3054
+ alignOffset,
3055
+ id
3056
+ },
3057
+ children
3058
+ }
3059
+ );
3060
+ }
3061
+ function shallowEqualWithoutChildren(a, b) {
3062
+ if (a === b) return true;
3063
+ if (!a || !b) return false;
3064
+ const keysA = Object.keys(a).filter((k) => k !== "children");
3065
+ const keysB = Object.keys(b).filter((k) => k !== "children");
3066
+ if (keysA.length !== keysB.length) return false;
3067
+ for (const k of keysA) {
3068
+ if (a[k] !== b[k]) return false;
3069
+ }
3070
+ return true;
3071
+ }
3072
+ function TooltipContent2({ asChild = false, ...props }) {
3073
+ const { setProps, setAsChild } = useTooltip();
3074
+ const lastPropsRef = React18__namespace.useRef(
3075
+ void 0
3076
+ );
3077
+ React18__namespace.useEffect(() => {
3078
+ if (!shallowEqualWithoutChildren(lastPropsRef.current, props)) {
3079
+ lastPropsRef.current = props;
3080
+ setProps(props);
3081
+ }
3082
+ }, [props, setProps]);
3083
+ React18__namespace.useEffect(() => {
3084
+ setAsChild(asChild);
3085
+ }, [asChild, setAsChild]);
3086
+ return null;
3087
+ }
3088
+ function TooltipTrigger2({
3089
+ ref,
3090
+ onMouseEnter,
3091
+ onMouseLeave,
3092
+ onFocus,
3093
+ onBlur,
3094
+ onPointerDown,
3095
+ asChild = false,
3096
+ ...props
3097
+ }) {
3098
+ const {
3099
+ props: contentProps,
3100
+ asChild: contentAsChild,
3101
+ side,
3102
+ sideOffset,
3103
+ align,
3104
+ alignOffset,
3105
+ id
3106
+ } = useTooltip();
3107
+ const {
3108
+ showTooltip,
3109
+ hideTooltip,
3110
+ hideImmediate,
3111
+ currentTooltip,
3112
+ setReferenceEl
3113
+ } = useGlobalTooltip();
3114
+ const triggerRef = React18__namespace.useRef(null);
3115
+ React18__namespace.useImperativeHandle(ref, () => triggerRef.current);
3116
+ const suppressNextFocusRef = React18__namespace.useRef(false);
3117
+ const handleOpen = React18__namespace.useCallback(() => {
3118
+ if (!triggerRef.current) return;
3119
+ setReferenceEl(triggerRef.current);
3120
+ const rect = triggerRef.current.getBoundingClientRect();
3121
+ showTooltip({
3122
+ contentProps,
3123
+ contentAsChild,
3124
+ rect,
3125
+ side,
3126
+ sideOffset,
3127
+ align,
3128
+ alignOffset,
3129
+ id
3130
+ });
3131
+ }, [
3132
+ showTooltip,
3133
+ setReferenceEl,
3134
+ contentProps,
3135
+ contentAsChild,
3136
+ side,
3137
+ sideOffset,
3138
+ align,
3139
+ alignOffset,
3140
+ id
3141
+ ]);
3142
+ const handlePointerDown = React18__namespace.useCallback(
3143
+ (e) => {
3144
+ onPointerDown?.(e);
3145
+ if (currentTooltip?.id === id) {
3146
+ suppressNextFocusRef.current = true;
3147
+ hideImmediate();
3148
+ Promise.resolve().then(() => {
3149
+ suppressNextFocusRef.current = false;
3150
+ });
3151
+ }
3152
+ },
3153
+ [onPointerDown, currentTooltip?.id, id, hideImmediate]
3154
+ );
3155
+ const handleMouseEnter = React18__namespace.useCallback(
3156
+ (e) => {
3157
+ onMouseEnter?.(e);
3158
+ handleOpen();
3159
+ },
3160
+ [handleOpen, onMouseEnter]
3161
+ );
3162
+ const handleMouseLeave = React18__namespace.useCallback(
3163
+ (e) => {
3164
+ onMouseLeave?.(e);
3165
+ hideTooltip();
3166
+ },
3167
+ [hideTooltip, onMouseLeave]
3168
+ );
3169
+ const handleFocus = React18__namespace.useCallback(
3170
+ (e) => {
3171
+ onFocus?.(e);
3172
+ if (suppressNextFocusRef.current) return;
3173
+ handleOpen();
3174
+ },
3175
+ [handleOpen, onFocus]
3176
+ );
3177
+ const handleBlur = React18__namespace.useCallback(
3178
+ (e) => {
3179
+ onBlur?.(e);
3180
+ hideTooltip();
3181
+ },
3182
+ [hideTooltip, onBlur]
3183
+ );
3184
+ const Component = asChild ? Slot : react.motion.div;
3185
+ return /* @__PURE__ */ jsxRuntime.jsx(
3186
+ Component,
3187
+ {
3188
+ ref: triggerRef,
3189
+ onPointerDown: handlePointerDown,
3190
+ onMouseEnter: handleMouseEnter,
3191
+ onMouseLeave: handleMouseLeave,
3192
+ onFocus: handleFocus,
3193
+ onBlur: handleBlur,
3194
+ "data-slot": "tooltip-trigger",
3195
+ "data-side": side,
3196
+ "data-align": align,
3197
+ "data-state": currentTooltip?.id === id ? "open" : "closed",
3198
+ ...props
3199
+ }
3200
+ );
3201
+ }
3202
+ function AvatarContainer({
3203
+ zIndex,
3204
+ translate,
3205
+ side,
3206
+ sideOffset,
3207
+ align,
3208
+ alignOffset,
3209
+ ...props
3210
+ }) {
3211
+ return /* @__PURE__ */ jsxRuntime.jsx(
3212
+ Tooltip2,
3213
+ {
3214
+ side,
3215
+ sideOffset,
3216
+ align,
3217
+ alignOffset,
3218
+ children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3219
+ react.motion.div,
3220
+ {
3221
+ "data-slot": "avatar-container",
3222
+ initial: "initial",
3223
+ whileHover: "hover",
3224
+ whileTap: "hover",
3225
+ style: { position: "relative", zIndex },
3226
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3227
+ react.motion.div,
3228
+ {
3229
+ variants: {
3230
+ initial: { y: 0 },
3231
+ hover: { y: translate }
3232
+ },
3233
+ ...props
3234
+ }
3235
+ )
3236
+ }
3237
+ ) })
3238
+ }
3239
+ );
3240
+ }
3241
+ function AvatarGroup({
3242
+ ref,
3243
+ children,
3244
+ id,
3245
+ transition = { type: "spring", stiffness: 300, damping: 17 },
3246
+ invertOverlap = false,
3247
+ translate = "-30%",
3248
+ openDelay = 0,
3249
+ closeDelay = 0,
3250
+ side = "top",
3251
+ sideOffset = 25,
3252
+ align = "center",
3253
+ alignOffset = 0,
3254
+ tooltipTransition = { type: "spring", stiffness: 300, damping: 35 },
3255
+ style,
3256
+ ...props
3257
+ }) {
3258
+ return /* @__PURE__ */ jsxRuntime.jsx(
3259
+ TooltipProvider2,
3260
+ {
3261
+ id,
3262
+ openDelay,
3263
+ closeDelay,
3264
+ transition: tooltipTransition,
3265
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3266
+ "div",
3267
+ {
3268
+ ref,
3269
+ "data-slot": "avatar-group",
3270
+ style: {
3271
+ display: "flex",
3272
+ alignItems: "center",
3273
+ ...style
3274
+ },
3275
+ ...props,
3276
+ children: children?.map((child, index) => /* @__PURE__ */ jsxRuntime.jsx(
3277
+ AvatarContainer,
3278
+ {
3279
+ zIndex: invertOverlap ? React18__namespace.Children.count(children) - index : index,
3280
+ transition,
3281
+ translate,
3282
+ side,
3283
+ sideOffset,
3284
+ align,
3285
+ alignOffset,
3286
+ children: child
3287
+ },
3288
+ index
3289
+ ))
3290
+ }
3291
+ )
3292
+ }
3293
+ );
3294
+ }
3295
+ function AvatarGroupTooltip(props) {
3296
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipContent2, { ...props });
3297
+ }
3298
+ function AvatarGroupTooltipArrow(props) {
3299
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipArrow, { ...props });
3300
+ }
3301
+ function AvatarGroup2({
3302
+ className,
3303
+ invertOverlap = true,
3304
+ ...props
3305
+ }) {
3306
+ return /* @__PURE__ */ jsxRuntime.jsx(
3307
+ AvatarGroup,
3308
+ {
3309
+ className: cn("h-12 -space-x-3", className),
3310
+ invertOverlap,
3311
+ ...props
3312
+ }
3313
+ );
3314
+ }
3315
+ function AvatarGroupTooltip2({
3316
+ className,
3317
+ children,
3318
+ layout = "preserve-aspect",
3319
+ ...props
3320
+ }) {
3321
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3322
+ AvatarGroupTooltip,
3323
+ {
3324
+ className: cn(
3325
+ "bg-primary text-primary-foreground z-50 w-fit rounded-md px-3 py-1.5 text-xs text-balance",
3326
+ className
3327
+ ),
3328
+ ...props,
3329
+ children: [
3330
+ /* @__PURE__ */ jsxRuntime.jsx(motion9__namespace.div, { layout, className: "overflow-hidden", children }),
3331
+ /* @__PURE__ */ jsxRuntime.jsx(
3332
+ AvatarGroupTooltipArrow,
3333
+ {
3334
+ className: "fill-primary size-3 data-[side='bottom']:translate-y-[1px] data-[side='right']:translate-x-[1px] data-[side='left']:translate-x-[-1px] data-[side='top']:translate-y-[-1px]",
3335
+ tipRadius: 2
3336
+ }
3337
+ )
3338
+ ]
3339
+ }
3340
+ );
3341
+ }
3342
+ function Avatar({
3343
+ className,
3344
+ size = "default",
3345
+ ...props
3346
+ }) {
3347
+ return /* @__PURE__ */ jsxRuntime.jsx(
3348
+ avatar.Avatar.Root,
3349
+ {
3350
+ "data-slot": "avatar",
3351
+ "data-size": size,
3352
+ className: cn(
3353
+ "size-8 rounded-full after:rounded-full data-[size=lg]:size-10 data-[size=sm]:size-6 group/avatar relative flex shrink-0 select-none after:absolute after:inset-0 after:border after:border-border after:mix-blend-darken dark:after:mix-blend-lighten",
3354
+ className
3355
+ ),
3356
+ ...props
3357
+ }
3358
+ );
3359
+ }
3360
+ function AvatarImage({ className, ...props }) {
3361
+ return /* @__PURE__ */ jsxRuntime.jsx(
3362
+ avatar.Avatar.Image,
3363
+ {
3364
+ "data-slot": "avatar-image",
3365
+ className: cn(
3366
+ "rounded-full aspect-square size-full object-cover",
3367
+ className
3368
+ ),
3369
+ ...props
3370
+ }
3371
+ );
3372
+ }
3373
+ function AvatarFallback({
3374
+ className,
3375
+ ...props
3376
+ }) {
3377
+ return /* @__PURE__ */ jsxRuntime.jsx(
3378
+ avatar.Avatar.Fallback,
3379
+ {
3380
+ "data-slot": "avatar-fallback",
3381
+ className: cn(
3382
+ "bg-muted text-muted-foreground rounded-full flex size-full items-center justify-center text-sm group-data-[size=sm]/avatar:text-xs",
3383
+ className
3384
+ ),
3385
+ ...props
3386
+ }
3387
+ );
3388
+ }
3389
+ var AVATARS = [
3390
+ {
3391
+ src: "https://pbs.twimg.com/profile_images/1534700564810018816/anAuSfkp_400x400.jpg",
3392
+ fallback: "JH",
3393
+ tooltip: "Jhey"
3394
+ },
3395
+ {
3396
+ src: "https://pbs.twimg.com/profile_images/1927474594102784000/Al0g-I6o_400x400.jpg",
3397
+ fallback: "DH",
3398
+ tooltip: "David Haz"
3399
+ }
3400
+ ];
3401
+ var Collaborators = () => {
3402
+ return /* @__PURE__ */ jsxRuntime.jsx(AvatarGroup2, { children: AVATARS.map((avatar, index) => /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-8 border-3 border-background", children: [
3403
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatar.src }),
3404
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: avatar.fallback }),
3405
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarGroupTooltip2, { children: avatar.tooltip })
3406
+ ] }, index)) });
3407
+ };
3408
+ var Share = () => {
3409
+ const [access, setAccess] = React18__namespace.useState("private");
3410
+ const [copied, setCopied] = React18__namespace.useState(false);
3411
+ const shareUrl = typeof window !== "undefined" ? window.location.href : "";
3412
+ const shareButton = useMsg("share.button");
3413
+ const shareTitle = useMsg("share.title");
3414
+ const peopleWithAccess = useMsg("share.people-with-access");
3415
+ const generalAccess = useMsg("share.general-access");
3416
+ const copyLabel = useMsg("share.copy");
3417
+ const copiedLabel = useMsg("share.copied");
3418
+ const ACCESS_OPTIONS = [
3419
+ {
3420
+ value: "private",
3421
+ label: useMsg("share.access.private.label"),
3422
+ description: useMsg("share.access.private.description"),
3423
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Lock, { className: "w-4 h-4" })
3424
+ },
3425
+ {
3426
+ value: "anyone-view",
3427
+ label: useMsg("share.access.anyone-view.label"),
3428
+ description: useMsg("share.access.anyone-view.description"),
3429
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Globe, { className: "w-4 h-4" })
3430
+ },
3431
+ {
3432
+ value: "anyone-edit",
3433
+ label: useMsg("share.access.anyone-edit.label"),
3434
+ description: useMsg("share.access.anyone-edit.description"),
3435
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Users, { className: "w-4 h-4" })
3436
+ }
3437
+ ];
3438
+ const handleCopy = () => {
3439
+ navigator.clipboard.writeText(shareUrl).then(() => {
3440
+ setCopied(true);
3441
+ setTimeout(() => setCopied(false), 2e3);
3442
+ });
3443
+ };
3444
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { children: [
3445
+ /* @__PURE__ */ jsxRuntime.jsxs(PopoverTrigger2, { render: /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", variant: "outline" }), children: [
3446
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, { className: "h-4 w-4" }),
3447
+ shareButton
3448
+ ] }),
3449
+ /* @__PURE__ */ jsxRuntime.jsxs(PopoverPanel, { side: "bottom", align: "end", className: "w-80 flex flex-col gap-3", children: [
3450
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTitle2, { className: "text-base font-medium", children: shareTitle }),
3451
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
3452
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: peopleWithAccess }),
3453
+ /* @__PURE__ */ jsxRuntime.jsx(Collaborators, {})
3454
+ ] }),
3455
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, {}),
3456
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
3457
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: generalAccess }),
3458
+ ACCESS_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
3459
+ "button",
3460
+ {
3461
+ onClick: () => setAccess(opt.value),
3462
+ className: "flex items-center gap-3 rounded-lg px-3 py-2 text-left transition-colors hover:bg-muted",
3463
+ children: [
3464
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: opt.icon }),
3465
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
3466
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-none", children: opt.label }),
3467
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: opt.description })
3468
+ ] }),
3469
+ access === opt.value && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-primary shrink-0" })
3470
+ ]
3471
+ },
3472
+ opt.value
3473
+ ))
3474
+ ] }),
3475
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, {}),
3476
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
3477
+ /* @__PURE__ */ jsxRuntime.jsx(Input, { readOnly: true, value: shareUrl, className: "flex-1 text-xs" }),
3478
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: handleCopy, className: "shrink-0", children: [
3479
+ copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, { className: "h-4 w-4" }),
3480
+ copied ? copiedLabel : copyLabel
3481
+ ] })
3482
+ ] })
3483
+ ] })
3484
+ ] });
3485
+ };
3486
+ var AVATARS2 = [
3487
+ {
3488
+ src: "https://pbs.twimg.com/profile_images/1534700564810018816/anAuSfkp_400x400.jpg",
3489
+ fallback: "JH",
3490
+ name: "Jhey",
3491
+ role: "Editor (you)"
3492
+ },
3493
+ {
3494
+ src: "https://pbs.twimg.com/profile_images/1927474594102784000/Al0g-I6o_400x400.jpg",
3495
+ fallback: "DH",
3496
+ name: "David Haz",
3497
+ role: "Editor"
3498
+ }
3499
+ ];
3500
+ var [currentUser, ...others] = AVATARS2;
3501
+ var CollaboratorsPopover = () => {
3502
+ const collaboratorsTitle = useMsg("collaborators.title");
3503
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover2, { children: [
3504
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger2, { render: /* @__PURE__ */ jsxRuntime.jsx("div", {}), nativeButton: false, children: /* @__PURE__ */ jsxRuntime.jsx("button", { className: "rounded-full ring-2 ring-background focus:outline-none focus-visible:ring-primary", children: /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-6", children: [
3505
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: currentUser.src }),
3506
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: currentUser.fallback })
3507
+ ] }) }) }),
3508
+ /* @__PURE__ */ jsxRuntime.jsxs(PopoverPanel, { side: "bottom", align: "end", className: "w-64 flex flex-col gap-3", children: [
3509
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTitle2, { className: "text-sm font-medium", children: collaboratorsTitle }),
3510
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: [currentUser, ...others].map((user) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
3511
+ /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-8 shrink-0", children: [
3512
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: user.src }),
3513
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: user.fallback })
3514
+ ] }),
3515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
3516
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-none truncate", children: user.name }),
3517
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: user.role })
3518
+ ] })
3519
+ ] }, user.fallback)) })
3520
+ ] })
3521
+ ] });
3522
+ };
3523
+ var Header = () => {
3524
+ const { history, appState } = core.usePuck();
3525
+ const publish = useMsg("header.publish");
3526
+ const undo = useMsg("header.undo");
3527
+ const undoTooltip = useMsg("header.undo.tooltip");
3528
+ const redo = useMsg("header.redo");
3529
+ const redoTooltip = useMsg("header.redo.tooltip");
3530
+ const exportLabel = useMsg("header.export");
3531
+ const exportJson = useMsg("header.export.json");
3532
+ const theme = useTheme();
3533
+ const toggleTheme = useToggleTheme();
3534
+ const themeLightLabel = useMsg("header.theme.light");
3535
+ const themeDarkLabel = useMsg("header.theme.dark");
3536
+ const themeLabel = theme === "dark" ? themeLightLabel : themeDarkLabel;
3537
+ React18__namespace.useEffect(() => {
3538
+ document.documentElement.classList.toggle("dark", theme === "dark");
3539
+ }, []);
3540
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex overflow-hidden transition-all duration-300 backdrop-blur-xl w-full border-b border-neutral-200 dark:border-neutral-800 items-center h-[54px] py-0", children: [
3541
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-18 flex items-center justify-center h-full border-r border-neutral-200 dark:border-neutral-800/80", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-10 h-10 bg-primary rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx(AnimatedAsana, { className: "text-white text-2xl" }) }) }),
3542
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-1 w-full px-2", children: [
3543
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-4 w-4" }) }),
3544
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none text-sm font-medium", children: appState?.data?.root?.props?.title || "" }),
3545
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2 h-full ml-auto", children: [
3546
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
3547
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3548
+ Button,
3549
+ {
3550
+ variant: "ghost",
3551
+ size: "icon",
3552
+ disabled: !history.hasPast,
3553
+ onClick: () => history.back(),
3554
+ "aria-label": undo,
3555
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo2, { className: "h-4 w-4" })
3556
+ }
3557
+ ) }),
3558
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: undoTooltip })
3559
+ ] }),
3560
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
3561
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3562
+ Button,
3563
+ {
3564
+ variant: "ghost",
3565
+ size: "icon",
3566
+ disabled: !history.hasFuture,
3567
+ onClick: () => history.forward(),
3568
+ "aria-label": redo,
3569
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Redo2, { className: "h-4 w-4" })
3570
+ }
3571
+ ) }),
3572
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: redoTooltip })
3573
+ ] }),
3574
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
3575
+ /* @__PURE__ */ jsxRuntime.jsx(CollaboratorsPopover, {}),
3576
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
3577
+ /* @__PURE__ */ jsxRuntime.jsx(Share, {}),
3578
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
3579
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
3580
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
3581
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { render: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", "aria-label": exportLabel }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { className: "h-4 w-4" }) }) }),
3582
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: exportLabel })
3583
+ ] }),
3584
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsxRuntime.jsxs(
3585
+ DropdownMenuItem,
3586
+ {
3587
+ onClick: () => {
3588
+ const json = JSON.stringify(appState.data, null, 2);
3589
+ const blob = new Blob([json], { type: "application/json" });
3590
+ const url = URL.createObjectURL(blob);
3591
+ const a = document.createElement("a");
3592
+ a.href = url;
3593
+ a.download = `${appState.data.root?.props?.title || "page"}.json`;
3594
+ a.click();
3595
+ URL.revokeObjectURL(url);
3596
+ },
3597
+ children: [
3598
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileDown, { className: "h-4 w-4" }),
3599
+ " ",
3600
+ exportJson
3601
+ ]
3602
+ }
3603
+ ) })
3604
+ ] }),
3605
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
3606
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
3607
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: toggleTheme, "aria-label": themeLabel, children: theme === "dark" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sun, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Moon, { className: "h-4 w-4" }) }) }),
3608
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: themeLabel })
3609
+ ] }),
3610
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
3611
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
3612
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { size: "sm", "aria-label": publish, children: [
3613
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-4 w-4" }),
3614
+ publish
3615
+ ] }) }),
3616
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: publish })
3617
+ ] })
3618
+ ] })
3619
+ ] })
3620
+ ] }) });
3621
+ };
3622
+ var DEFAULT_SEEDS = [
3623
+ "forest",
3624
+ "ocean",
3625
+ "mountain",
3626
+ "city",
3627
+ "food",
3628
+ "travel",
3629
+ "abstract",
3630
+ "people",
3631
+ "architecture",
3632
+ "animals",
3633
+ "technology",
3634
+ "minimal"
3635
+ ];
3636
+ function picsumUrl(seed, w = 960, h = 960) {
3637
+ return `https://picsum.photos/seed/${encodeURIComponent(seed)}/${w}/${h}`;
3638
+ }
3639
+ function getDefaultImages(seeds) {
3640
+ return seeds.map((seed, i) => ({
3641
+ src: picsumUrl(seed),
3642
+ alt: seed,
3643
+ id: `${seed}-${i}`
3644
+ }));
3645
+ }
3646
+ function getSearchImages(query) {
3647
+ return Array.from({ length: 12 }, (_, i) => ({
3648
+ src: picsumUrl(`${query}-${i}`),
3649
+ alt: `${query} ${i + 1}`,
3650
+ id: `${query}-${i}`
3651
+ }));
3652
+ }
3653
+ var ghostEl = null;
3654
+ function createGhost(src) {
3655
+ const el = document.createElement("div");
3656
+ el.style.cssText = `
3657
+ position: fixed; top: -9999px; left: -9999px; z-index: 99999;
3658
+ width: 80px; height: 60px; border-radius: 6px; overflow: hidden;
3659
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3); pointer-events: none;
3660
+ `;
3661
+ const img = document.createElement("img");
3662
+ img.src = src;
3663
+ img.style.cssText = "width:100%;height:100%;object-fit:cover;";
3664
+ el.appendChild(img);
3665
+ document.body.appendChild(el);
3666
+ return el;
3667
+ }
3668
+ function moveGhost(x, y) {
3669
+ if (!ghostEl) return;
3670
+ ghostEl.style.left = `${x + 12}px`;
3671
+ ghostEl.style.top = `${y + 12}px`;
3672
+ }
3673
+ function removeGhost() {
3674
+ ghostEl?.remove();
3675
+ ghostEl = null;
3676
+ }
3677
+ function ImageLibrary({
3678
+ seeds,
3679
+ items: customImages
3680
+ } = {}) {
3681
+ const effectiveSeeds = seeds ?? DEFAULT_SEEDS;
3682
+ const [query, setQuery] = React18__namespace.useState("");
3683
+ const [committed, setCommitted] = React18__namespace.useState("");
3684
+ const [items, setItems] = React18__namespace.useState(
3685
+ () => customImages ?? getDefaultImages(effectiveSeeds)
3686
+ );
3687
+ const libraryTitle = useMsg("image-library.title");
3688
+ const searchPlaceholder = useMsg("image-library.search.placeholder");
3689
+ React18__namespace.useEffect(() => {
3690
+ const t = setTimeout(() => setCommitted(query.trim()), 400);
3691
+ return () => clearTimeout(t);
3692
+ }, [query]);
3693
+ React18__namespace.useEffect(() => {
3694
+ if (customImages) return;
3695
+ setItems(
3696
+ committed ? getSearchImages(committed) : getDefaultImages(effectiveSeeds)
3697
+ );
3698
+ }, [committed, customImages, effectiveSeeds]);
3699
+ function handlePointerDown(e, src) {
3700
+ e.stopPropagation();
3701
+ e.currentTarget.setPointerCapture(e.pointerId);
3702
+ ghostEl = createGhost(src);
3703
+ moveGhost(e.clientX, e.clientY);
3704
+ window.dispatchEvent(
3705
+ new CustomEvent("anvilkit:librarydragstart", {
3706
+ detail: { type: "image" }
3707
+ })
3708
+ );
3709
+ function onMove(ev) {
3710
+ moveGhost(ev.clientX, ev.clientY);
3711
+ }
3712
+ function onUp(ev) {
3713
+ removeGhost();
3714
+ window.removeEventListener("pointermove", onMove);
3715
+ window.removeEventListener("pointerup", onUp);
3716
+ window.dispatchEvent(
3717
+ new CustomEvent("anvilkit:imagedrop", {
3718
+ detail: { src, clientX: ev.clientX, clientY: ev.clientY }
3719
+ })
3720
+ );
3721
+ }
3722
+ window.addEventListener("pointermove", onMove);
3723
+ window.addEventListener("pointerup", onUp);
3724
+ }
3725
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
3726
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pt-3 pb-1 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: libraryTitle }),
3727
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
3728
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
3729
+ /* @__PURE__ */ jsxRuntime.jsx(
3730
+ Input,
3731
+ {
3732
+ className: "pl-8",
3733
+ placeholder: searchPlaceholder,
3734
+ value: query,
3735
+ onChange: (e) => setQuery(e.target.value)
3736
+ }
3737
+ )
3738
+ ] }) }),
3739
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 grid grid-cols-2 gap-2", children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(
3740
+ "div",
3741
+ {
3742
+ onPointerDown: (e) => handlePointerDown(e, item.src),
3743
+ className: "rounded-md overflow-hidden border border-border bg-muted/40 cursor-grab select-none hover:ring-2 hover:ring-primary/50 active:cursor-grabbing transition-all",
3744
+ children: [
3745
+ /* @__PURE__ */ jsxRuntime.jsx(
3746
+ "img",
3747
+ {
3748
+ src: item.src,
3749
+ alt: item.alt,
3750
+ className: "w-full h-20 object-cover pointer-events-none",
3751
+ loading: "lazy"
3752
+ }
3753
+ ),
3754
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1.5 py-1 text-xs text-muted-foreground truncate capitalize", children: item.alt })
3755
+ ]
3756
+ },
3757
+ `${item.src}-${i}`
3758
+ )) }) })
3759
+ ] });
3760
+ }
3761
+ var ghostEl2 = null;
3762
+ function createGhost2(text) {
3763
+ const el = document.createElement("div");
3764
+ el.style.cssText = `
3765
+ position: fixed; top: -9999px; left: -9999px; z-index: 99999;
3766
+ max-width: 200px; padding: 6px 10px; border-radius: 6px;
3767
+ background: #1e1e2e; color: #fff; font-size: 12px; line-height: 1.4;
3768
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3); pointer-events: none;
3769
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
3770
+ `;
3771
+ el.textContent = text.length > 40 ? text.slice(0, 40) + "\u2026" : text;
3772
+ document.body.appendChild(el);
3773
+ return el;
3774
+ }
3775
+ function moveGhost2(x, y) {
3776
+ if (!ghostEl2) return;
3777
+ ghostEl2.style.left = `${x + 12}px`;
3778
+ ghostEl2.style.top = `${y + 12}px`;
3779
+ }
3780
+ function removeGhost2() {
3781
+ ghostEl2?.remove();
3782
+ ghostEl2 = null;
3783
+ }
3784
+ var DEFAULT_SNIPPETS = [
3785
+ // Headlines
3786
+ {
3787
+ category: "Headlines",
3788
+ label: "Bold statement",
3789
+ text: "The Future Starts Here"
3790
+ },
3791
+ {
3792
+ category: "Headlines",
3793
+ label: "Question hook",
3794
+ text: "Ready to Transform Your Business?"
3795
+ },
3796
+ {
3797
+ category: "Headlines",
3798
+ label: "Value prop",
3799
+ text: "Simple, Powerful, Built for Teams"
3800
+ },
3801
+ {
3802
+ category: "Headlines",
3803
+ label: "Action-led",
3804
+ text: "Ship Faster. Break Less. Sleep Better."
3805
+ },
3806
+ // Subheadings
3807
+ {
3808
+ category: "Subheadings",
3809
+ label: "Feature intro",
3810
+ text: "Everything you need, nothing you don't."
3811
+ },
3812
+ {
3813
+ category: "Subheadings",
3814
+ label: "Social proof",
3815
+ text: "Trusted by over 10,000 teams worldwide."
3816
+ },
3817
+ {
3818
+ category: "Subheadings",
3819
+ label: "CTA support",
3820
+ text: "Get started in minutes \u2014 no credit card required."
3821
+ },
3822
+ // Body
3823
+ {
3824
+ category: "Body",
3825
+ label: "Product description",
3826
+ text: "Our platform helps teams collaborate in real time, ship products faster, and stay aligned across every stage of the process."
3827
+ },
3828
+ {
3829
+ category: "Body",
3830
+ label: "Feature benefit",
3831
+ text: "With built-in analytics and smart automation, you can focus on what matters most \u2014 building great products."
3832
+ },
3833
+ {
3834
+ category: "Body",
3835
+ label: "About us",
3836
+ text: "We're a small team on a big mission: to make software development feel effortless for everyone."
3837
+ },
3838
+ // CTAs
3839
+ { category: "CTAs", label: "Primary", text: "Get Started Free" },
3840
+ { category: "CTAs", label: "Secondary", text: "Learn More" },
3841
+ { category: "CTAs", label: "Soft sell", text: "See How It Works" },
3842
+ { category: "CTAs", label: "Urgency", text: "Start Your Free Trial Today" }
3843
+ ];
3844
+ function CopyLibrary({
3845
+ items
3846
+ } = {}) {
3847
+ const activeSnippets = items ?? DEFAULT_SNIPPETS;
3848
+ const categories = Array.from(new Set(activeSnippets.map((s) => s.category)));
3849
+ const [query, setQuery] = React18__namespace.useState("");
3850
+ const libraryTitle = useMsg("copy-library.title");
3851
+ const searchPlaceholder = useMsg("copy-library.search.placeholder");
3852
+ const filtered = query.trim() ? activeSnippets.filter(
3853
+ (s) => s.text.toLowerCase().includes(query.toLowerCase()) || s.label.toLowerCase().includes(query.toLowerCase()) || s.category.toLowerCase().includes(query.toLowerCase())
3854
+ ) : activeSnippets;
3855
+ function handlePointerDown(e, text) {
3856
+ e.stopPropagation();
3857
+ e.currentTarget.setPointerCapture(e.pointerId);
3858
+ ghostEl2 = createGhost2(text);
3859
+ moveGhost2(e.clientX, e.clientY);
3860
+ window.dispatchEvent(
3861
+ new CustomEvent("anvilkit:librarydragstart", {
3862
+ detail: { type: "text" }
3863
+ })
3864
+ );
3865
+ function onMove(ev) {
3866
+ moveGhost2(ev.clientX, ev.clientY);
3867
+ }
3868
+ function onUp(ev) {
3869
+ removeGhost2();
3870
+ window.removeEventListener("pointermove", onMove);
3871
+ window.removeEventListener("pointerup", onUp);
3872
+ window.dispatchEvent(
3873
+ new CustomEvent("anvilkit:textdrop", {
3874
+ detail: { text, clientX: ev.clientX, clientY: ev.clientY }
3875
+ })
3876
+ );
3877
+ }
3878
+ window.addEventListener("pointermove", onMove);
3879
+ window.addEventListener("pointerup", onUp);
3880
+ }
3881
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
3882
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pt-3 pb-1 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: libraryTitle }),
3883
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
3884
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
3885
+ /* @__PURE__ */ jsxRuntime.jsx(
3886
+ Input,
3887
+ {
3888
+ className: "pl-8",
3889
+ placeholder: searchPlaceholder,
3890
+ value: query,
3891
+ onChange: (e) => setQuery(e.target.value)
3892
+ }
3893
+ )
3894
+ ] }) }),
3895
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 flex flex-col gap-4", children: (query.trim() ? [null] : categories).map((cat) => {
3896
+ const items2 = cat ? filtered.filter((s) => s.category === cat) : filtered;
3897
+ if (!items2.length) return null;
3898
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3899
+ cat && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-1 pb-1 text-xs font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-1", children: [
3900
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Type, { className: "h-3 w-3" }),
3901
+ cat
3902
+ ] }),
3903
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: items2.map((snippet, i) => /* @__PURE__ */ jsxRuntime.jsxs(
3904
+ "div",
3905
+ {
3906
+ onPointerDown: (e) => handlePointerDown(e, snippet.text),
3907
+ className: "rounded-md border border-border bg-muted/40 px-2.5 py-2 cursor-grab select-none hover:bg-muted hover:ring-1 hover:ring-primary/40 active:cursor-grabbing transition-all",
3908
+ children: [
3909
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-foreground/70 mb-0.5", children: snippet.label }),
3910
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-foreground leading-snug line-clamp-2", children: snippet.text })
3911
+ ]
3912
+ },
3913
+ i
3914
+ )) })
3915
+ ] }, cat ?? "results");
3916
+ }) }) })
3917
+ ] });
3918
+ }
3919
+ var EditorLayout = ({
3920
+ aiPanel,
3921
+ images,
3922
+ copywritings
3923
+ }) => {
3924
+ const activeTab = useActiveTab();
3925
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-sm:hidden overflow-hidden h-screen", children: [
3926
+ /* @__PURE__ */ jsxRuntime.jsx(Header, {}),
3927
+ /* @__PURE__ */ jsxRuntime.jsxs(react.motion.div, { className: "relative w-full flex border-r border-neutral-200 dark:border-neutral-800/80 bg-white/60 dark:bg-neutral-950/80 backdrop-blur-md ml-0 h-[calc(100vh-54px)]", children: [
3928
+ /* @__PURE__ */ jsxRuntime.jsx(Aside, {}),
3929
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-full flex flex-col overflow-x-hidden overflow-y-auto border-r border-neutral-200 dark:border-neutral-800/80 w-[240px]", children: [
3930
+ activeTab === "insert" && /* @__PURE__ */ jsxRuntime.jsx(core.Puck.Components, {}),
3931
+ activeTab === "layer" && /* @__PURE__ */ jsxRuntime.jsx(core.Puck.Outline, {}),
3932
+ activeTab === "image" && /* @__PURE__ */ jsxRuntime.jsx(ImageLibrary, { ...images }),
3933
+ activeTab === "text" && /* @__PURE__ */ jsxRuntime.jsx(CopyLibrary, { ...copywritings }),
3934
+ activeTab === "copilot" && aiPanel
3935
+ ] }),
3936
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(core.Puck.Preview, {}) }),
3937
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-l border-neutral-200 dark:border-neutral-800/80 w-[240px]", children: /* @__PURE__ */ jsxRuntime.jsx(core.Puck.Fields, {}) })
3938
+ ] })
3939
+ ] });
3940
+ };
3941
+ function createEditorUiStore(storeId) {
3942
+ return zustand.createStore()(
3943
+ middleware.persist(
3944
+ (set) => ({
3945
+ drawerSearch: "",
3946
+ setDrawerSearch: (q) => set({ drawerSearch: q }),
3947
+ drawerCollapsed: {},
3948
+ toggleDrawerGroup: (group) => set((s) => ({
3949
+ drawerCollapsed: { ...s.drawerCollapsed, [group]: !s.drawerCollapsed[group] }
3950
+ })),
3951
+ activeTab: "insert",
3952
+ setActiveTab: (tab) => set({ activeTab: tab }),
3953
+ outlineExpanded: {},
3954
+ toggleOutlineItem: (id) => set((s) => ({
3955
+ outlineExpanded: { ...s.outlineExpanded, [id]: !s.outlineExpanded[id] }
3956
+ })),
3957
+ theme: "light",
3958
+ toggleTheme: () => set((s) => {
3959
+ const next = s.theme === "light" ? "dark" : "light";
3960
+ document.documentElement.classList.toggle("dark", next === "dark");
3961
+ return { theme: next };
3962
+ })
3963
+ }),
3964
+ {
3965
+ name: `anvilkit-ui-${storeId}`,
3966
+ partialize: (s) => ({
3967
+ activeTab: s.activeTab,
3968
+ drawerCollapsed: s.drawerCollapsed,
3969
+ outlineExpanded: s.outlineExpanded,
3970
+ theme: s.theme
3971
+ // drawerSearch intentionally excluded — transient input
3972
+ })
3973
+ }
3974
+ )
3975
+ );
3976
+ }
3977
+ function createEditorI18nStore(initial) {
3978
+ return zustand.createStore()(
3979
+ middleware.persist(
3980
+ (set) => ({
3981
+ locale: initial.locale,
3982
+ messages: initial.messages,
3983
+ setLocale: (locale, messages) => set({ locale, messages })
3984
+ }),
3985
+ {
3986
+ name: "anvilkit-i18n",
3987
+ // Only persist locale — messages are re-loaded from props on mount
3988
+ partialize: (s) => ({ locale: s.locale })
3989
+ }
3990
+ )
3991
+ );
3992
+ }
3993
+
3994
+ // src/i18n/zh.ts
3995
+ var defaultMessages = {
3996
+ "header.publish": "\u53D1\u5E03",
3997
+ "header.undo": "\u64A4\u9500",
3998
+ "header.undo.tooltip": "\u64A4\u9500 (Ctrl+Z)",
3999
+ "header.redo": "\u91CD\u505A",
4000
+ "header.redo.tooltip": "\u91CD\u505A (Ctrl+Y)",
4001
+ "header.export": "\u5BFC\u51FA",
4002
+ "header.export.json": "\u5BFC\u51FA JSON",
4003
+ "drawer.title": "\u7EC4\u4EF6\u5E93",
4004
+ "drawer.search.placeholder": "\u641C\u7D22\u7EC4\u4EF6...",
4005
+ "aside.insert": "\u63D2\u5165",
4006
+ "aside.layer": "\u56FE\u5C42",
4007
+ "aside.image": "\u56FE\u7247",
4008
+ "aside.text": "\u6587\u672C",
4009
+ "aside.copilot": "AI \u52A9\u624B",
4010
+ "image-library.title": "\u56FE\u7247\u5E93",
4011
+ "image-library.search.placeholder": "\u641C\u7D22\u56FE\u7247...",
4012
+ "copy-library.title": "\u6587\u6848\u5E93",
4013
+ "copy-library.search.placeholder": "\u641C\u7D22\u6587\u6848...",
4014
+ "share.button": "\u5206\u4EAB",
4015
+ "share.title": "\u5206\u4EAB",
4016
+ "share.people-with-access": "\u6709\u6743\u9650\u7684\u4EBA",
4017
+ "share.general-access": "\u901A\u7528\u8BBF\u95EE",
4018
+ "share.copy": "\u590D\u5236",
4019
+ "share.copied": "\u5DF2\u590D\u5236",
4020
+ "share.access.private.label": "\u79C1\u5BC6",
4021
+ "share.access.private.description": "\u4EC5\u53D7\u9080\u4EBA\u5458\u53EF\u8BBF\u95EE",
4022
+ "share.access.anyone-view.label": "\u4EFB\u4F55\u6709\u94FE\u63A5\u7684\u4EBA\u53EF\u67E5\u770B",
4023
+ "share.access.anyone-view.description": "\u4EFB\u4F55\u6709\u94FE\u63A5\u7684\u4EBA\u5747\u53EF\u67E5\u770B",
4024
+ "share.access.anyone-edit.label": "\u4EFB\u4F55\u6709\u94FE\u63A5\u7684\u4EBA\u53EF\u7F16\u8F91",
4025
+ "share.access.anyone-edit.description": "\u4EFB\u4F55\u6709\u94FE\u63A5\u7684\u4EBA\u5747\u53EF\u7F16\u8F91",
4026
+ "collaborators.title": "\u534F\u4F5C\u8005",
4027
+ "collaborators.role.editor": "\u7F16\u8F91\u8005",
4028
+ "collaborators.role.editor-you": "\u7F16\u8F91\u8005\uFF08\u4F60\uFF09",
4029
+ "richtext.bold": "\u52A0\u7C97",
4030
+ "richtext.italic": "\u659C\u4F53",
4031
+ "richtext.link": "\u94FE\u63A5",
4032
+ "richtext.link.prompt": "URL\uFF1A",
4033
+ "header.theme.light": "\u6D45\u8272\u6A21\u5F0F",
4034
+ "header.theme.dark": "\u6DF1\u8272\u6A21\u5F0F"
4035
+ };
4036
+ function Studio({
4037
+ config,
4038
+ data,
4039
+ onPublish,
4040
+ onChange,
4041
+ overrideExtensions,
4042
+ aiHost,
4043
+ className,
4044
+ images,
4045
+ copywritings,
4046
+ storeId,
4047
+ locale,
4048
+ messages
4049
+ }) {
4050
+ const uiStore2 = React18__namespace.useRef(createEditorUiStore(storeId ?? "default")).current;
4051
+ const i18nStore = React18__namespace.useRef(
4052
+ createEditorI18nStore({
4053
+ locale: locale ?? "zh",
4054
+ messages: messages ?? defaultMessages
4055
+ })
4056
+ ).current;
4057
+ const aiPlugin = React18__namespace.useMemo(
4058
+ () => pluginAi.createAiPlugin({ host: aiHost }),
4059
+ [aiHost]
4060
+ );
4061
+ const mergedOverrides = React18__namespace.useMemo(
4062
+ () => ({ ...aiPlugin.overrides, ...puckOverrides, ...overrideExtensions }),
4063
+ [aiPlugin.overrides, overrideExtensions]
4064
+ );
4065
+ return /* @__PURE__ */ jsxRuntime.jsx(EditorUiStoreProvider, { value: uiStore2, children: /* @__PURE__ */ jsxRuntime.jsx(EditorI18nStoreProvider, { value: i18nStore, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx(
4066
+ core.Puck,
4067
+ {
4068
+ config,
4069
+ data,
4070
+ onPublish,
4071
+ onChange,
4072
+ overrides: mergedOverrides,
4073
+ plugins: [aiPlugin],
4074
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4075
+ EditorLayout,
4076
+ {
4077
+ aiPanel: aiPlugin.render(),
4078
+ images,
4079
+ copywritings
4080
+ }
4081
+ )
4082
+ }
4083
+ ) }) }) });
4084
+ }
4085
+
4086
+ // src/store/index.ts
4087
+ var uiStore = createEditorUiStore("default");
4088
+
4089
+ exports.Studio = Studio;
4090
+ exports.createEditorI18nStore = createEditorI18nStore;
4091
+ exports.createEditorUiStore = createEditorUiStore;
4092
+ exports.puckOverrides = puckOverrides;
4093
+ exports.uiStore = uiStore;