@anvilkit/puck-studio 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +195 -176
- package/dist/index.cjs +945 -803
- package/dist/index.d.cts +110 -46
- package/dist/index.d.ts +110 -46
- package/dist/index.js +928 -789
- package/dist/legacy.cjs +54 -0
- package/dist/legacy.js +52 -0
- package/dist/overrides.cjs +2090 -0
- package/dist/overrides.d.cts +212 -0
- package/dist/overrides.d.ts +212 -0
- package/dist/overrides.js +2057 -0
- package/dist/styles.css +88 -0
- package/package.json +109 -65
package/dist/index.js
CHANGED
|
@@ -1,118 +1,50 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ArrowLeft, Undo2, Redo2, Download, Search, Plus, Bold, Italic, Link, ChevronRightIcon, Info, Sparkles, ChevronDownIcon, CheckIcon, GripVertical, Copy, Trash2, SearchIcon, ChevronUpIcon, FileDown, Sun, Moon, Send, Layers2, Image, Type, Bot, Lock, Globe, Users, Link2, Check } from 'lucide-react';
|
|
3
|
-
import { Button as Button$1 } from '@base-ui/react/button';
|
|
4
|
-
import { cva } from 'class-variance-authority';
|
|
5
|
-
import { clsx } from 'clsx';
|
|
6
|
-
import { twMerge } from 'tailwind-merge';
|
|
7
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
-
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
1
|
+
import { Search, Plus, Bold, Italic, Link, ChevronRightIcon, Info, Sparkles, ChevronDownIcon, CheckIcon, GripVertical, Copy, Trash2, SearchIcon, ChevronUpIcon, ArrowLeft, Undo2, Redo2, Download, FileDown, Sun, Moon, Send, Layers2, Image, Type, Bot, Lock, Globe, Users, Link2, Check } from 'lucide-react';
|
|
9
2
|
import { createStore, useStore } from 'zustand';
|
|
10
|
-
import * as
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import { Menu } from '@base-ui/react/menu';
|
|
3
|
+
import * as React17 from 'react';
|
|
4
|
+
import React17__default, { useState, useRef, useMemo, useCallback, useEffect } from 'react';
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
14
6
|
import { ScrollArea as ScrollArea$1 } from '@base-ui/react/scroll-area';
|
|
7
|
+
import { clsx } from 'clsx';
|
|
8
|
+
import { twMerge } from 'tailwind-merge';
|
|
15
9
|
import { Input as Input$1 } from '@base-ui/react/input';
|
|
10
|
+
import { usePuck, Puck, useGetPuck, AutoField } from '@puckeditor/core';
|
|
11
|
+
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
12
|
+
import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
|
|
16
13
|
import { mergeProps } from '@base-ui/react/merge-props';
|
|
17
14
|
import { useRender } from '@base-ui/react/use-render';
|
|
15
|
+
import { Button as Button$1 } from '@base-ui/react/button';
|
|
16
|
+
import { cva } from 'class-variance-authority';
|
|
18
17
|
import { Select as Select$1 } from '@base-ui/react/select';
|
|
19
18
|
import { useSensors, useSensor, PointerSensor, DndContext, closestCenter } from '@dnd-kit/core';
|
|
20
19
|
import { SortableContext, verticalListSortingStrategy, arrayMove, useSortable } from '@dnd-kit/sortable';
|
|
21
20
|
import { CSS } from '@dnd-kit/utilities';
|
|
22
|
-
import { Popover as Popover$1 } from '@base-ui
|
|
21
|
+
import { Popover as Popover$1 } from '@base-ui/react/popover';
|
|
23
22
|
import { motion, AnimatePresence, LayoutGroup, isMotionComponent } from 'motion/react';
|
|
24
23
|
import { Toggle as Toggle$1 } from '@base-ui/react/toggle';
|
|
25
24
|
import { Command as Command$1 } from 'cmdk';
|
|
26
|
-
import '@base-ui/react/dialog';
|
|
27
|
-
import { createAiPlugin } from '@puckeditor/plugin-ai';
|
|
28
|
-
import '@puckeditor/plugin-ai/styles.css';
|
|
29
25
|
import '@puckeditor/core/puck.css';
|
|
30
|
-
import { Tabs as Tabs$1 } from '@base-ui
|
|
31
|
-
import
|
|
26
|
+
import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
|
|
27
|
+
import { persist } from 'zustand/middleware';
|
|
28
|
+
import * as motion8 from 'motion/react-client';
|
|
32
29
|
import { FloatingArrow, useFloating, autoUpdate, offset, flip, shift, arrow, FloatingPortal } from '@floating-ui/react';
|
|
33
30
|
import { Avatar as Avatar$1 } from '@base-ui/react/avatar';
|
|
34
|
-
import {
|
|
31
|
+
import { Menu } from '@base-ui/react/menu';
|
|
35
32
|
|
|
36
|
-
// src/
|
|
37
|
-
function cn(...inputs) {
|
|
38
|
-
return twMerge(clsx(inputs));
|
|
39
|
-
}
|
|
40
|
-
var buttonVariants = cva(
|
|
41
|
-
"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",
|
|
42
|
-
{
|
|
43
|
-
variants: {
|
|
44
|
-
variant: {
|
|
45
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
46
|
-
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",
|
|
47
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
48
|
-
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
49
|
-
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",
|
|
50
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
51
|
-
},
|
|
52
|
-
size: {
|
|
53
|
-
default: "h-8 gap-1.5 px-2.5",
|
|
54
|
-
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs [&_svg:not([class*='size-'])]:size-3",
|
|
55
|
-
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] [&_svg:not([class*='size-'])]:size-3.5",
|
|
56
|
-
lg: "h-9 gap-1.5 px-2.5",
|
|
57
|
-
icon: "size-8",
|
|
58
|
-
"icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] [&_svg:not([class*='size-'])]:size-3",
|
|
59
|
-
"icon-sm": "size-7 rounded-[min(var(--radius-md),12px)]",
|
|
60
|
-
"icon-lg": "size-9"
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
defaultVariants: {
|
|
64
|
-
variant: "default",
|
|
65
|
-
size: "default"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
);
|
|
69
|
-
function Button({
|
|
70
|
-
className,
|
|
71
|
-
variant = "default",
|
|
72
|
-
size = "default",
|
|
73
|
-
...props
|
|
74
|
-
}) {
|
|
75
|
-
return /* @__PURE__ */ jsx(
|
|
76
|
-
Button$1,
|
|
77
|
-
{
|
|
78
|
-
"data-slot": "button",
|
|
79
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
80
|
-
...props
|
|
81
|
-
}
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
function Separator({
|
|
85
|
-
className,
|
|
86
|
-
orientation = "horizontal",
|
|
87
|
-
...props
|
|
88
|
-
}) {
|
|
89
|
-
return /* @__PURE__ */ jsx(
|
|
90
|
-
Separator$1,
|
|
91
|
-
{
|
|
92
|
-
"data-slot": "separator",
|
|
93
|
-
orientation,
|
|
94
|
-
className: cn(
|
|
95
|
-
"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
|
|
96
|
-
className
|
|
97
|
-
),
|
|
98
|
-
...props
|
|
99
|
-
}
|
|
100
|
-
);
|
|
101
|
-
}
|
|
33
|
+
// src/core/overrides/layout/EditorDrawer.tsx
|
|
102
34
|
function getStrictContext(name) {
|
|
103
|
-
const Context =
|
|
104
|
-
const
|
|
35
|
+
const Context = React17.createContext(void 0);
|
|
36
|
+
const Provider = ({
|
|
105
37
|
value,
|
|
106
38
|
children
|
|
107
39
|
}) => /* @__PURE__ */ jsx(Context.Provider, { value, children });
|
|
108
40
|
const useSafeContext = () => {
|
|
109
|
-
const ctx =
|
|
41
|
+
const ctx = React17.useContext(Context);
|
|
110
42
|
if (ctx === void 0) {
|
|
111
43
|
throw new Error(`useContext must be used within ${name ?? "a Provider"}`);
|
|
112
44
|
}
|
|
113
45
|
return ctx;
|
|
114
46
|
};
|
|
115
|
-
return [
|
|
47
|
+
return [Provider, useSafeContext];
|
|
116
48
|
}
|
|
117
49
|
|
|
118
50
|
// src/store/ui-context.ts
|
|
@@ -143,137 +75,8 @@ function useToggleTheme() {
|
|
|
143
75
|
function useMsg(key) {
|
|
144
76
|
return useStore(useEditorI18nStoreApi(), (s) => s.messages[key] ?? key);
|
|
145
77
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
149
|
-
var TooltipContent = React18.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
150
|
-
TooltipPrimitive.Content,
|
|
151
|
-
{
|
|
152
|
-
ref,
|
|
153
|
-
sideOffset,
|
|
154
|
-
className: cn(
|
|
155
|
-
"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]",
|
|
156
|
-
className
|
|
157
|
-
),
|
|
158
|
-
...props
|
|
159
|
-
}
|
|
160
|
-
) }));
|
|
161
|
-
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
162
|
-
function DropdownMenu({ ...props }) {
|
|
163
|
-
return /* @__PURE__ */ jsx(Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
164
|
-
}
|
|
165
|
-
function DropdownMenuTrigger({ ...props }) {
|
|
166
|
-
return /* @__PURE__ */ jsx(Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
167
|
-
}
|
|
168
|
-
function DropdownMenuContent({
|
|
169
|
-
align = "start",
|
|
170
|
-
alignOffset = 0,
|
|
171
|
-
side = "bottom",
|
|
172
|
-
sideOffset = 4,
|
|
173
|
-
className,
|
|
174
|
-
...props
|
|
175
|
-
}) {
|
|
176
|
-
return /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
|
|
177
|
-
Menu.Positioner,
|
|
178
|
-
{
|
|
179
|
-
className: "isolate z-50 outline-none",
|
|
180
|
-
align,
|
|
181
|
-
alignOffset,
|
|
182
|
-
side,
|
|
183
|
-
sideOffset,
|
|
184
|
-
children: /* @__PURE__ */ jsx(
|
|
185
|
-
Menu.Popup,
|
|
186
|
-
{
|
|
187
|
-
"data-slot": "dropdown-menu-content",
|
|
188
|
-
className: cn(
|
|
189
|
-
"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",
|
|
190
|
-
className
|
|
191
|
-
),
|
|
192
|
-
...props
|
|
193
|
-
}
|
|
194
|
-
)
|
|
195
|
-
}
|
|
196
|
-
) });
|
|
197
|
-
}
|
|
198
|
-
function DropdownMenuItem({
|
|
199
|
-
className,
|
|
200
|
-
inset,
|
|
201
|
-
variant = "default",
|
|
202
|
-
...props
|
|
203
|
-
}) {
|
|
204
|
-
return /* @__PURE__ */ jsx(
|
|
205
|
-
Menu.Item,
|
|
206
|
-
{
|
|
207
|
-
"data-slot": "dropdown-menu-item",
|
|
208
|
-
"data-inset": inset,
|
|
209
|
-
"data-variant": variant,
|
|
210
|
-
className: cn(
|
|
211
|
-
"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",
|
|
212
|
-
className
|
|
213
|
-
),
|
|
214
|
-
...props
|
|
215
|
-
}
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
function EditorHeader({
|
|
219
|
-
actions,
|
|
220
|
-
children
|
|
221
|
-
}) {
|
|
222
|
-
const { history, appState } = usePuck();
|
|
223
|
-
const undo = useMsg("header.undo");
|
|
224
|
-
const undoTooltip = useMsg("header.undo.tooltip");
|
|
225
|
-
const redo = useMsg("header.redo");
|
|
226
|
-
const redoTooltip = useMsg("header.redo.tooltip");
|
|
227
|
-
const exportLabel = useMsg("header.export");
|
|
228
|
-
const exportJson = useMsg("header.export.json");
|
|
229
|
-
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs("header", { className: "flex h-12 items-center justify-between border-b bg-background px-4 gap-2", children: [
|
|
230
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" }) }),
|
|
231
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: appState?.data?.root?.props?.title || "" }),
|
|
232
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
233
|
-
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
234
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
235
|
-
Button,
|
|
236
|
-
{
|
|
237
|
-
variant: "ghost",
|
|
238
|
-
size: "icon",
|
|
239
|
-
disabled: !history.hasPast,
|
|
240
|
-
onClick: () => history.back(),
|
|
241
|
-
"aria-label": undo,
|
|
242
|
-
children: /* @__PURE__ */ jsx(Undo2, { className: "h-4 w-4" })
|
|
243
|
-
}
|
|
244
|
-
) }),
|
|
245
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: undoTooltip })
|
|
246
|
-
] }),
|
|
247
|
-
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
248
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
249
|
-
Button,
|
|
250
|
-
{
|
|
251
|
-
variant: "ghost",
|
|
252
|
-
size: "icon",
|
|
253
|
-
disabled: !history.hasFuture,
|
|
254
|
-
onClick: () => history.forward(),
|
|
255
|
-
"aria-label": redo,
|
|
256
|
-
children: /* @__PURE__ */ jsx(Redo2, { className: "h-4 w-4" })
|
|
257
|
-
}
|
|
258
|
-
) }),
|
|
259
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: redoTooltip })
|
|
260
|
-
] }),
|
|
261
|
-
/* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
|
|
262
|
-
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
263
|
-
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
264
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ 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__ */ jsx(Download, { className: "h-4 w-4" }) }) }),
|
|
265
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: exportLabel })
|
|
266
|
-
] }),
|
|
267
|
-
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsx(DropdownMenuItem, { children: exportJson }) })
|
|
268
|
-
] }),
|
|
269
|
-
actions
|
|
270
|
-
] })
|
|
271
|
-
] }) });
|
|
272
|
-
}
|
|
273
|
-
function EditorHeaderActions({
|
|
274
|
-
children
|
|
275
|
-
}) {
|
|
276
|
-
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children }) });
|
|
78
|
+
function cn(...inputs) {
|
|
79
|
+
return twMerge(clsx(inputs));
|
|
277
80
|
}
|
|
278
81
|
function ScrollArea({
|
|
279
82
|
className,
|
|
@@ -334,7 +137,7 @@ function Input({ className, type, ...props }) {
|
|
|
334
137
|
type,
|
|
335
138
|
"data-slot": "input",
|
|
336
139
|
className: cn(
|
|
337
|
-
"h-
|
|
140
|
+
"h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-2.5 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
338
141
|
className
|
|
339
142
|
),
|
|
340
143
|
...props
|
|
@@ -399,9 +202,9 @@ function DrawerItem({
|
|
|
399
202
|
children,
|
|
400
203
|
name
|
|
401
204
|
}) {
|
|
402
|
-
const {
|
|
403
|
-
const componentConfig =
|
|
404
|
-
const thumbnail = componentConfig?.metadata?.thumbnail;
|
|
205
|
+
const { config } = usePuck();
|
|
206
|
+
const componentConfig = config.components?.[name];
|
|
207
|
+
const thumbnail = typeof componentConfig?.metadata?.thumbnail === "string" ? componentConfig.metadata.thumbnail : void 0;
|
|
405
208
|
const src = thumbnail ?? getPlaceholderUrl(name);
|
|
406
209
|
return /* @__PURE__ */ 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: [
|
|
407
210
|
/* @__PURE__ */ jsx("div", { className: "w-full h-16 bg-muted overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
@@ -418,6 +221,24 @@ function DrawerItem({
|
|
|
418
221
|
/* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs font-medium truncate", children: name ?? children })
|
|
419
222
|
] });
|
|
420
223
|
}
|
|
224
|
+
function Separator({
|
|
225
|
+
className,
|
|
226
|
+
orientation = "horizontal",
|
|
227
|
+
...props
|
|
228
|
+
}) {
|
|
229
|
+
return /* @__PURE__ */ jsx(
|
|
230
|
+
Separator$1,
|
|
231
|
+
{
|
|
232
|
+
"data-slot": "separator",
|
|
233
|
+
orientation,
|
|
234
|
+
className: cn(
|
|
235
|
+
"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
|
|
236
|
+
className
|
|
237
|
+
),
|
|
238
|
+
...props
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
}
|
|
421
242
|
function EditorOutline({
|
|
422
243
|
children
|
|
423
244
|
}) {
|
|
@@ -428,7 +249,7 @@ function EditorOutline({
|
|
|
428
249
|
/* @__PURE__ */ jsxs("div", { className: "px-3 py-1.5 text-xs text-muted-foreground truncate", children: [
|
|
429
250
|
"Selected:",
|
|
430
251
|
" ",
|
|
431
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: selectedItem.type
|
|
252
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: typeof selectedItem.type === "string" ? selectedItem.type : String(selectedItem.type) })
|
|
432
253
|
] }),
|
|
433
254
|
/* @__PURE__ */ jsx(Separator, {})
|
|
434
255
|
] }),
|
|
@@ -460,6 +281,61 @@ var CANVAS_CSS = `
|
|
|
460
281
|
}
|
|
461
282
|
body { margin: 0; font-family: system-ui, sans-serif; }
|
|
462
283
|
`;
|
|
284
|
+
var CANVAS_STYLE_ID = "__anvilkit_styles__";
|
|
285
|
+
function resolveDocument(target) {
|
|
286
|
+
if (target) return target;
|
|
287
|
+
if (typeof document === "undefined") return void 0;
|
|
288
|
+
return document;
|
|
289
|
+
}
|
|
290
|
+
function useThemeSync({
|
|
291
|
+
document: targetDocument,
|
|
292
|
+
injectCanvasCss = false
|
|
293
|
+
} = {}) {
|
|
294
|
+
const theme = useTheme();
|
|
295
|
+
React17.useEffect(() => {
|
|
296
|
+
const resolvedDocument = resolveDocument(targetDocument);
|
|
297
|
+
if (!resolvedDocument || !injectCanvasCss) return;
|
|
298
|
+
const existing = resolvedDocument.getElementById(CANVAS_STYLE_ID);
|
|
299
|
+
if (existing) existing.remove();
|
|
300
|
+
const style = resolvedDocument.createElement("style");
|
|
301
|
+
style.id = CANVAS_STYLE_ID;
|
|
302
|
+
style.textContent = CANVAS_CSS;
|
|
303
|
+
resolvedDocument.head.appendChild(style);
|
|
304
|
+
}, [targetDocument, injectCanvasCss]);
|
|
305
|
+
React17.useEffect(() => {
|
|
306
|
+
const resolvedDocument = resolveDocument(targetDocument);
|
|
307
|
+
if (!resolvedDocument) return;
|
|
308
|
+
resolvedDocument.documentElement.classList.toggle("dark", theme === "dark");
|
|
309
|
+
}, [targetDocument, theme]);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// src/features/library-dnd/drop-contract.ts
|
|
313
|
+
var LIBRARY_DRAG_START = "anvilkit:librarydragstart";
|
|
314
|
+
var IMAGE_DROP = "anvilkit:imagedrop";
|
|
315
|
+
var TEXT_DROP = "anvilkit:textdrop";
|
|
316
|
+
function createLibraryDragEvent(type, detail) {
|
|
317
|
+
return new CustomEvent(type, { detail });
|
|
318
|
+
}
|
|
319
|
+
function addLibraryDragEventListener(type, listener, target = window) {
|
|
320
|
+
const wrapped = (event) => {
|
|
321
|
+
listener(event);
|
|
322
|
+
};
|
|
323
|
+
target.addEventListener(type, wrapped);
|
|
324
|
+
return () => {
|
|
325
|
+
target.removeEventListener(type, wrapped);
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function dispatchLibraryDragStart(type) {
|
|
329
|
+
window.dispatchEvent(createLibraryDragEvent(LIBRARY_DRAG_START, { type }));
|
|
330
|
+
}
|
|
331
|
+
function dispatchImageDrop(detail) {
|
|
332
|
+
window.dispatchEvent(createLibraryDragEvent(IMAGE_DROP, detail));
|
|
333
|
+
}
|
|
334
|
+
function dispatchTextDrop(detail) {
|
|
335
|
+
window.dispatchEvent(createLibraryDragEvent(TEXT_DROP, detail));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/features/library-dnd/replace-props.ts
|
|
463
339
|
function isImageUrl(val) {
|
|
464
340
|
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/");
|
|
465
341
|
}
|
|
@@ -498,160 +374,187 @@ function replaceTextInProps(props, newText, targetText) {
|
|
|
498
374
|
}
|
|
499
375
|
return { result: props, replaced: false };
|
|
500
376
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
377
|
+
|
|
378
|
+
// src/core/overrides/canvas/drop-targets.ts
|
|
379
|
+
var TEXT_TAGS = /* @__PURE__ */ new Set([
|
|
380
|
+
"P",
|
|
381
|
+
"H1",
|
|
382
|
+
"H2",
|
|
383
|
+
"H3",
|
|
384
|
+
"H4",
|
|
385
|
+
"H5",
|
|
386
|
+
"H6",
|
|
387
|
+
"SPAN",
|
|
388
|
+
"A",
|
|
389
|
+
"LI",
|
|
390
|
+
"BUTTON",
|
|
391
|
+
"LABEL"
|
|
392
|
+
]);
|
|
393
|
+
function getIframeCoords(iframeEl, clientX, clientY) {
|
|
394
|
+
const rect = iframeEl.getBoundingClientRect();
|
|
395
|
+
const x = clientX - rect.left;
|
|
396
|
+
const y = clientY - rect.top;
|
|
397
|
+
if (x < 0 || y < 0 || x > rect.width || y > rect.height) {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
return { x, y };
|
|
401
|
+
}
|
|
402
|
+
function getComponentElAt(iframeDoc, iframeEl, clientX, clientY) {
|
|
403
|
+
const coords = getIframeCoords(iframeEl, clientX, clientY);
|
|
404
|
+
if (!coords) return null;
|
|
405
|
+
const element = iframeDoc.elementFromPoint(coords.x, coords.y);
|
|
406
|
+
if (!element) return null;
|
|
407
|
+
return element.closest("[data-puck-component]");
|
|
408
|
+
}
|
|
409
|
+
function getImageElInComponent(compEl, iframeEl, clientX, clientY) {
|
|
410
|
+
const images = Array.from(compEl.querySelectorAll("img"));
|
|
411
|
+
if (!images.length) return null;
|
|
412
|
+
if (images.length === 1) return images[0];
|
|
413
|
+
const rect = iframeEl.getBoundingClientRect();
|
|
414
|
+
const x = clientX - rect.left;
|
|
415
|
+
const y = clientY - rect.top;
|
|
416
|
+
let closest = null;
|
|
417
|
+
let minDistance = Infinity;
|
|
418
|
+
for (const image of images) {
|
|
419
|
+
const imageRect = image.getBoundingClientRect();
|
|
420
|
+
const centerX = imageRect.left + imageRect.width / 2;
|
|
421
|
+
const centerY = imageRect.top + imageRect.height / 2;
|
|
422
|
+
const distance = Math.hypot(centerX - x, centerY - y);
|
|
423
|
+
if (distance < minDistance) {
|
|
424
|
+
minDistance = distance;
|
|
425
|
+
closest = image;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return closest;
|
|
429
|
+
}
|
|
430
|
+
function getTextElInComponent(iframeDoc, iframeEl, compEl, clientX, clientY) {
|
|
431
|
+
const coords = getIframeCoords(iframeEl, clientX, clientY);
|
|
432
|
+
if (!coords) return null;
|
|
433
|
+
const element = iframeDoc.elementFromPoint(coords.x, coords.y);
|
|
434
|
+
if (element && compEl.contains(element)) {
|
|
435
|
+
let current = element;
|
|
436
|
+
while (current && current !== iframeDoc.body) {
|
|
437
|
+
if (TEXT_TAGS.has(current.tagName) && current.textContent?.trim()) {
|
|
438
|
+
return current;
|
|
439
|
+
}
|
|
440
|
+
current = current.parentElement;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
for (const tag of TEXT_TAGS) {
|
|
444
|
+
const candidate = compEl.querySelector(tag.toLowerCase());
|
|
445
|
+
if (candidate?.textContent?.trim()) {
|
|
446
|
+
return candidate;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// src/core/overrides/canvas/highlight.ts
|
|
453
|
+
function createElementHighlighter() {
|
|
454
|
+
let highlightedEl = null;
|
|
455
|
+
function set(el, color) {
|
|
456
|
+
if (highlightedEl && highlightedEl !== el) {
|
|
457
|
+
highlightedEl.style.outline = "";
|
|
458
|
+
highlightedEl.style.outlineOffset = "";
|
|
459
|
+
}
|
|
460
|
+
if (el) {
|
|
461
|
+
el.style.outline = `2px solid ${color}`;
|
|
462
|
+
el.style.outlineOffset = "2px";
|
|
463
|
+
}
|
|
464
|
+
highlightedEl = el;
|
|
465
|
+
}
|
|
466
|
+
function clear() {
|
|
467
|
+
set(null, "");
|
|
468
|
+
}
|
|
469
|
+
return { set, clear };
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// src/core/overrides/canvas/useLibraryDropBridge.ts
|
|
473
|
+
function useLibraryDropBridge(iframeDoc) {
|
|
505
474
|
const getPuck = useGetPuck();
|
|
506
|
-
|
|
507
|
-
React18.useEffect(() => {
|
|
508
|
-
if (!iframeDoc) return;
|
|
509
|
-
const existing = iframeDoc.getElementById("__anvilkit_styles__");
|
|
510
|
-
if (existing) existing.remove();
|
|
511
|
-
const style = iframeDoc.createElement("style");
|
|
512
|
-
style.id = "__anvilkit_styles__";
|
|
513
|
-
style.textContent = CANVAS_CSS;
|
|
514
|
-
iframeDoc.head.appendChild(style);
|
|
515
|
-
}, [iframeDoc]);
|
|
516
|
-
React18.useEffect(() => {
|
|
517
|
-
if (!iframeDoc) return;
|
|
518
|
-
iframeDoc.documentElement.classList.toggle("dark", theme === "dark");
|
|
519
|
-
}, [iframeDoc, theme]);
|
|
520
|
-
React18.useEffect(() => {
|
|
475
|
+
React17.useEffect(() => {
|
|
521
476
|
if (!iframeDoc) return;
|
|
522
477
|
const iframeEl = iframeDoc.defaultView?.frameElement;
|
|
523
478
|
if (!iframeEl) return;
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
function getImgInComponent(compEl, clientX, clientY) {
|
|
541
|
-
const imgs = Array.from(compEl.querySelectorAll("img"));
|
|
542
|
-
if (!imgs.length) return null;
|
|
543
|
-
if (imgs.length === 1) return imgs[0];
|
|
544
|
-
const rect = iframeEl.getBoundingClientRect();
|
|
545
|
-
const x = clientX - rect.left;
|
|
546
|
-
const y = clientY - rect.top;
|
|
547
|
-
let closest = null;
|
|
548
|
-
let minDist = Infinity;
|
|
549
|
-
for (const img of imgs) {
|
|
550
|
-
const r = img.getBoundingClientRect();
|
|
551
|
-
const cx = r.left + r.width / 2;
|
|
552
|
-
const cy = r.top + r.height / 2;
|
|
553
|
-
const dist = Math.hypot(cx - x, cy - y);
|
|
554
|
-
if (dist < minDist) {
|
|
555
|
-
minDist = dist;
|
|
556
|
-
closest = img;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
return closest;
|
|
560
|
-
}
|
|
561
|
-
const TEXT_TAGS = /* @__PURE__ */ new Set(["P", "H1", "H2", "H3", "H4", "H5", "H6", "SPAN", "A", "LI", "BUTTON", "LABEL"]);
|
|
562
|
-
function getTextElInComponent(compEl, clientX, clientY) {
|
|
563
|
-
const coords = iframeCoords(clientX, clientY);
|
|
564
|
-
if (!coords) return null;
|
|
565
|
-
const el = iframeDoc.elementFromPoint(coords.x, coords.y);
|
|
566
|
-
if (el && compEl.contains(el)) {
|
|
567
|
-
let cur = el;
|
|
568
|
-
while (cur && cur !== iframeDoc.body) {
|
|
569
|
-
if (TEXT_TAGS.has(cur.tagName) && cur.textContent?.trim()) return cur;
|
|
570
|
-
cur = cur.parentElement;
|
|
479
|
+
const iframeDocument = iframeDoc;
|
|
480
|
+
const frameElement = iframeEl;
|
|
481
|
+
let activeLibrary = null;
|
|
482
|
+
const highlighter = createElementHighlighter();
|
|
483
|
+
function dispatchReplace(componentId, updatedProps) {
|
|
484
|
+
const { dispatch, getItemById, getSelectorForId } = getPuck();
|
|
485
|
+
const item = getItemById(componentId);
|
|
486
|
+
const selector = getSelectorForId(componentId);
|
|
487
|
+
if (!item || !selector) return false;
|
|
488
|
+
dispatch({
|
|
489
|
+
type: "replace",
|
|
490
|
+
destinationIndex: selector.index,
|
|
491
|
+
destinationZone: selector.zone,
|
|
492
|
+
data: {
|
|
493
|
+
...item,
|
|
494
|
+
props: { ...item.props, ...updatedProps }
|
|
571
495
|
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
const found = compEl.querySelector(tag.toLowerCase());
|
|
575
|
-
if (found?.textContent?.trim()) return found;
|
|
576
|
-
}
|
|
577
|
-
return null;
|
|
578
|
-
}
|
|
579
|
-
function setHighlight(el, color) {
|
|
580
|
-
if (highlightedEl && highlightedEl !== el) {
|
|
581
|
-
highlightedEl.style.outline = "";
|
|
582
|
-
highlightedEl.style.outlineOffset = "";
|
|
583
|
-
}
|
|
584
|
-
if (el) {
|
|
585
|
-
el.style.outline = `2px solid ${color}`;
|
|
586
|
-
el.style.outlineOffset = "2px";
|
|
587
|
-
}
|
|
588
|
-
highlightedEl = el;
|
|
589
|
-
}
|
|
590
|
-
function clearHighlight() {
|
|
591
|
-
setHighlight(null, "");
|
|
496
|
+
});
|
|
497
|
+
return true;
|
|
592
498
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
activeLibrary = e.detail.type;
|
|
499
|
+
function onLibraryDragStart(type) {
|
|
500
|
+
activeLibrary = type;
|
|
596
501
|
}
|
|
597
502
|
function onPointerMove(e) {
|
|
598
503
|
if (!activeLibrary) return;
|
|
599
|
-
const compEl = getComponentElAt(e.clientX, e.clientY);
|
|
504
|
+
const compEl = getComponentElAt(iframeDocument, frameElement, e.clientX, e.clientY);
|
|
600
505
|
if (!compEl) {
|
|
601
|
-
|
|
506
|
+
highlighter.clear();
|
|
602
507
|
return;
|
|
603
508
|
}
|
|
604
509
|
if (activeLibrary === "image") {
|
|
605
|
-
|
|
606
|
-
|
|
510
|
+
highlighter.set(
|
|
511
|
+
getImageElInComponent(compEl, frameElement, e.clientX, e.clientY),
|
|
512
|
+
"#6366f1"
|
|
513
|
+
);
|
|
607
514
|
} else {
|
|
608
|
-
|
|
609
|
-
|
|
515
|
+
highlighter.set(
|
|
516
|
+
getTextElInComponent(iframeDocument, frameElement, compEl, e.clientX, e.clientY),
|
|
517
|
+
"#f59e0b"
|
|
518
|
+
);
|
|
610
519
|
}
|
|
611
520
|
}
|
|
612
521
|
function onPointerUp() {
|
|
613
522
|
activeLibrary = null;
|
|
614
|
-
|
|
615
|
-
}
|
|
616
|
-
function dispatchReplace(componentId, updatedProps) {
|
|
617
|
-
const { dispatch, getItemById, getSelectorForId } = getPuck();
|
|
618
|
-
const item = getItemById(componentId);
|
|
619
|
-
const selector = getSelectorForId(componentId);
|
|
620
|
-
if (!item || !selector) return false;
|
|
621
|
-
dispatch({
|
|
622
|
-
type: "replace",
|
|
623
|
-
destinationIndex: selector.index,
|
|
624
|
-
destinationZone: selector.zone,
|
|
625
|
-
data: { ...item, props: { ...item.props, ...updatedProps } }
|
|
626
|
-
});
|
|
627
|
-
return true;
|
|
523
|
+
highlighter.clear();
|
|
628
524
|
}
|
|
629
|
-
function onImageDrop(
|
|
630
|
-
|
|
631
|
-
clearHighlight();
|
|
525
|
+
function onImageDrop(src, clientX, clientY) {
|
|
526
|
+
highlighter.clear();
|
|
632
527
|
activeLibrary = null;
|
|
633
528
|
if (!src) return;
|
|
634
|
-
const compEl = getComponentElAt(clientX, clientY);
|
|
529
|
+
const compEl = getComponentElAt(iframeDocument, frameElement, clientX, clientY);
|
|
635
530
|
if (!compEl) return;
|
|
636
|
-
const componentId = compEl.
|
|
637
|
-
|
|
638
|
-
const item = getItemById(componentId);
|
|
531
|
+
const componentId = compEl.dataset.puckComponent;
|
|
532
|
+
if (!componentId) return;
|
|
533
|
+
const item = getPuck().getItemById(componentId);
|
|
639
534
|
if (!item) return;
|
|
640
|
-
const updatedProps = replaceImageInProps(
|
|
535
|
+
const updatedProps = replaceImageInProps(
|
|
536
|
+
item.props,
|
|
537
|
+
src
|
|
538
|
+
);
|
|
641
539
|
dispatchReplace(componentId, updatedProps);
|
|
642
540
|
}
|
|
643
|
-
function onTextDrop(
|
|
644
|
-
|
|
645
|
-
clearHighlight();
|
|
541
|
+
function onTextDrop(text, clientX, clientY) {
|
|
542
|
+
highlighter.clear();
|
|
646
543
|
activeLibrary = null;
|
|
647
544
|
if (!text) return;
|
|
648
|
-
const compEl = getComponentElAt(clientX, clientY);
|
|
545
|
+
const compEl = getComponentElAt(iframeDocument, frameElement, clientX, clientY);
|
|
649
546
|
if (!compEl) return;
|
|
650
|
-
const componentId = compEl.
|
|
651
|
-
|
|
547
|
+
const componentId = compEl.dataset.puckComponent;
|
|
548
|
+
if (!componentId) return;
|
|
549
|
+
const textEl = getTextElInComponent(
|
|
550
|
+
iframeDocument,
|
|
551
|
+
frameElement,
|
|
552
|
+
compEl,
|
|
553
|
+
clientX,
|
|
554
|
+
clientY
|
|
555
|
+
);
|
|
652
556
|
const targetText = textEl?.textContent?.trim() ?? "";
|
|
653
|
-
const
|
|
654
|
-
const item = getItemById(componentId);
|
|
557
|
+
const item = getPuck().getItemById(componentId);
|
|
655
558
|
if (!item) return;
|
|
656
559
|
const { result: updatedProps, replaced } = replaceTextInProps(
|
|
657
560
|
item.props,
|
|
@@ -660,19 +563,38 @@ function CanvasIframe({
|
|
|
660
563
|
);
|
|
661
564
|
if (replaced) dispatchReplace(componentId, updatedProps);
|
|
662
565
|
}
|
|
663
|
-
|
|
566
|
+
const removeLibraryDragStart = addLibraryDragEventListener(
|
|
567
|
+
LIBRARY_DRAG_START,
|
|
568
|
+
(event) => {
|
|
569
|
+
onLibraryDragStart(event.detail.type);
|
|
570
|
+
}
|
|
571
|
+
);
|
|
664
572
|
window.addEventListener("pointermove", onPointerMove);
|
|
665
573
|
window.addEventListener("pointerup", onPointerUp);
|
|
666
|
-
|
|
667
|
-
|
|
574
|
+
const removeImageDrop = addLibraryDragEventListener(IMAGE_DROP, (event) => {
|
|
575
|
+
const { src, clientX, clientY } = event.detail;
|
|
576
|
+
onImageDrop(src, clientX, clientY);
|
|
577
|
+
});
|
|
578
|
+
const removeTextDrop = addLibraryDragEventListener(TEXT_DROP, (event) => {
|
|
579
|
+
const { text, clientX, clientY } = event.detail;
|
|
580
|
+
onTextDrop(text, clientX, clientY);
|
|
581
|
+
});
|
|
668
582
|
return () => {
|
|
669
|
-
|
|
583
|
+
removeLibraryDragStart();
|
|
670
584
|
window.removeEventListener("pointermove", onPointerMove);
|
|
671
585
|
window.removeEventListener("pointerup", onPointerUp);
|
|
672
|
-
|
|
673
|
-
|
|
586
|
+
removeImageDrop();
|
|
587
|
+
removeTextDrop();
|
|
588
|
+
highlighter.clear();
|
|
674
589
|
};
|
|
675
590
|
}, [iframeDoc, getPuck]);
|
|
591
|
+
}
|
|
592
|
+
function CanvasIframe({
|
|
593
|
+
children,
|
|
594
|
+
document: iframeDoc
|
|
595
|
+
}) {
|
|
596
|
+
useThemeSync({ document: iframeDoc, injectCanvasCss: true });
|
|
597
|
+
useLibraryDropBridge(iframeDoc);
|
|
676
598
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
677
599
|
}
|
|
678
600
|
function CanvasPreview({
|
|
@@ -696,6 +618,60 @@ function ComponentOverlay({
|
|
|
696
618
|
}
|
|
697
619
|
);
|
|
698
620
|
}
|
|
621
|
+
function TooltipProvider({
|
|
622
|
+
delay = 0,
|
|
623
|
+
...props
|
|
624
|
+
}) {
|
|
625
|
+
return /* @__PURE__ */ jsx(
|
|
626
|
+
Tooltip$1.Provider,
|
|
627
|
+
{
|
|
628
|
+
"data-slot": "tooltip-provider",
|
|
629
|
+
delay,
|
|
630
|
+
...props
|
|
631
|
+
}
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
function Tooltip({ ...props }) {
|
|
635
|
+
return /* @__PURE__ */ jsx(Tooltip$1.Root, { "data-slot": "tooltip", ...props });
|
|
636
|
+
}
|
|
637
|
+
function TooltipTrigger({ ...props }) {
|
|
638
|
+
return /* @__PURE__ */ jsx(Tooltip$1.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
639
|
+
}
|
|
640
|
+
function TooltipContent({
|
|
641
|
+
className,
|
|
642
|
+
side = "top",
|
|
643
|
+
sideOffset = 4,
|
|
644
|
+
align = "center",
|
|
645
|
+
alignOffset = 0,
|
|
646
|
+
children,
|
|
647
|
+
...props
|
|
648
|
+
}) {
|
|
649
|
+
return /* @__PURE__ */ jsx(Tooltip$1.Portal, { children: /* @__PURE__ */ jsx(
|
|
650
|
+
Tooltip$1.Positioner,
|
|
651
|
+
{
|
|
652
|
+
align,
|
|
653
|
+
alignOffset,
|
|
654
|
+
side,
|
|
655
|
+
sideOffset,
|
|
656
|
+
className: "isolate z-50",
|
|
657
|
+
children: /* @__PURE__ */ jsxs(
|
|
658
|
+
Tooltip$1.Popup,
|
|
659
|
+
{
|
|
660
|
+
"data-slot": "tooltip-content",
|
|
661
|
+
className: cn(
|
|
662
|
+
"z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
663
|
+
className
|
|
664
|
+
),
|
|
665
|
+
...props,
|
|
666
|
+
children: [
|
|
667
|
+
children,
|
|
668
|
+
/* @__PURE__ */ jsx(Tooltip$1.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" })
|
|
669
|
+
]
|
|
670
|
+
}
|
|
671
|
+
)
|
|
672
|
+
}
|
|
673
|
+
) });
|
|
674
|
+
}
|
|
699
675
|
function ActionBar({
|
|
700
676
|
children,
|
|
701
677
|
label,
|
|
@@ -713,16 +689,13 @@ function ActionBar({
|
|
|
713
689
|
children
|
|
714
690
|
] }) });
|
|
715
691
|
}
|
|
716
|
-
function cn2(...inputs) {
|
|
717
|
-
return twMerge(clsx(inputs));
|
|
718
|
-
}
|
|
719
692
|
function Label({ className, ...props }) {
|
|
720
693
|
return /* @__PURE__ */ jsx(
|
|
721
694
|
"label",
|
|
722
695
|
{
|
|
723
696
|
"data-slot": "label",
|
|
724
|
-
className:
|
|
725
|
-
"gap-2 text-sm leading-none font-medium group-data-[disabled=true]:
|
|
697
|
+
className: cn(
|
|
698
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
726
699
|
className
|
|
727
700
|
),
|
|
728
701
|
...props
|
|
@@ -735,7 +708,7 @@ function Breadcrumb({ className, ...props }) {
|
|
|
735
708
|
{
|
|
736
709
|
"aria-label": "breadcrumb",
|
|
737
710
|
"data-slot": "breadcrumb",
|
|
738
|
-
className:
|
|
711
|
+
className: cn(className),
|
|
739
712
|
...props
|
|
740
713
|
}
|
|
741
714
|
);
|
|
@@ -745,8 +718,8 @@ function BreadcrumbList({ className, ...props }) {
|
|
|
745
718
|
"ol",
|
|
746
719
|
{
|
|
747
720
|
"data-slot": "breadcrumb-list",
|
|
748
|
-
className:
|
|
749
|
-
"
|
|
721
|
+
className: cn(
|
|
722
|
+
"flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground sm:gap-2.5",
|
|
750
723
|
className
|
|
751
724
|
),
|
|
752
725
|
...props
|
|
@@ -758,7 +731,7 @@ function BreadcrumbItem({ className, ...props }) {
|
|
|
758
731
|
"li",
|
|
759
732
|
{
|
|
760
733
|
"data-slot": "breadcrumb-item",
|
|
761
|
-
className:
|
|
734
|
+
className: cn("inline-flex items-center gap-1.5", className),
|
|
762
735
|
...props
|
|
763
736
|
}
|
|
764
737
|
);
|
|
@@ -772,7 +745,7 @@ function BreadcrumbLink({
|
|
|
772
745
|
defaultTagName: "a",
|
|
773
746
|
props: mergeProps(
|
|
774
747
|
{
|
|
775
|
-
className:
|
|
748
|
+
className: cn("transition-colors hover:text-foreground", className)
|
|
776
749
|
},
|
|
777
750
|
props
|
|
778
751
|
),
|
|
@@ -790,7 +763,7 @@ function BreadcrumbPage({ className, ...props }) {
|
|
|
790
763
|
role: "link",
|
|
791
764
|
"aria-disabled": "true",
|
|
792
765
|
"aria-current": "page",
|
|
793
|
-
className:
|
|
766
|
+
className: cn("font-normal text-foreground", className),
|
|
794
767
|
...props
|
|
795
768
|
}
|
|
796
769
|
);
|
|
@@ -806,32 +779,39 @@ function BreadcrumbSeparator({
|
|
|
806
779
|
"data-slot": "breadcrumb-separator",
|
|
807
780
|
role: "presentation",
|
|
808
781
|
"aria-hidden": "true",
|
|
809
|
-
className:
|
|
782
|
+
className: cn("[&>svg]:size-3.5", className),
|
|
810
783
|
...props,
|
|
811
|
-
children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon, {
|
|
784
|
+
children: children ?? /* @__PURE__ */ jsx(ChevronRightIcon, {})
|
|
812
785
|
}
|
|
813
786
|
);
|
|
814
787
|
}
|
|
788
|
+
function getComponentTypeLabel(item) {
|
|
789
|
+
if (!item) return "Component";
|
|
790
|
+
return typeof item.type === "string" ? item.type : String(item.type);
|
|
791
|
+
}
|
|
792
|
+
function getComponentId(item) {
|
|
793
|
+
const id = item?.props?.id;
|
|
794
|
+
return typeof id === "string" ? id : null;
|
|
795
|
+
}
|
|
815
796
|
function useBreadcrumbs() {
|
|
816
|
-
const { appState, dispatch, selectedItem, getParentById
|
|
797
|
+
const { appState, dispatch, selectedItem, getParentById } = usePuck();
|
|
817
798
|
const { itemSelector } = appState.ui;
|
|
818
799
|
const selectRoot = () => dispatch({ type: "setUi", ui: { itemSelector: null } });
|
|
819
800
|
if (!itemSelector || !selectedItem) {
|
|
820
801
|
return [{ label: "Page" }];
|
|
821
802
|
}
|
|
822
|
-
const selectedType = selectedItem
|
|
823
|
-
const
|
|
803
|
+
const selectedType = getComponentTypeLabel(selectedItem);
|
|
804
|
+
const parentId = getComponentId(selectedItem);
|
|
805
|
+
const parent = parentId ? getParentById(parentId) : void 0;
|
|
824
806
|
if (!parent) {
|
|
825
807
|
return [{ label: "Page", onSelect: selectRoot }, { label: selectedType }];
|
|
826
808
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
}
|
|
834
|
-
return [{ label: "Page", onSelect: selectRoot }, { label: selectedType }];
|
|
809
|
+
const parentType = getComponentTypeLabel(parent);
|
|
810
|
+
return [
|
|
811
|
+
{ label: "Page", onSelect: selectRoot },
|
|
812
|
+
{ label: parentType },
|
|
813
|
+
{ label: selectedType }
|
|
814
|
+
];
|
|
835
815
|
}
|
|
836
816
|
function FieldWrapper({
|
|
837
817
|
children
|
|
@@ -840,7 +820,7 @@ function FieldWrapper({
|
|
|
840
820
|
return /* @__PURE__ */ jsx(ScrollArea, { className: "h-full", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0", children: [
|
|
841
821
|
/* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsx(BreadcrumbList, { children: crumbs.map((crumb, i) => {
|
|
842
822
|
const isLast = i === crumbs.length - 1;
|
|
843
|
-
return /* @__PURE__ */ jsxs(
|
|
823
|
+
return /* @__PURE__ */ jsxs(React17.Fragment, { children: [
|
|
844
824
|
i > 0 && /* @__PURE__ */ jsx(BreadcrumbSeparator, {}),
|
|
845
825
|
/* @__PURE__ */ jsx(BreadcrumbItem, { children: isLast ? /* @__PURE__ */ jsx(BreadcrumbPage, { children: crumb.label }) : /* @__PURE__ */ jsx(
|
|
846
826
|
BreadcrumbLink,
|
|
@@ -858,20 +838,33 @@ function FieldWrapper({
|
|
|
858
838
|
function FieldLabel({
|
|
859
839
|
children,
|
|
860
840
|
label,
|
|
841
|
+
icon,
|
|
861
842
|
labelIcon,
|
|
862
843
|
el,
|
|
863
|
-
type: _type,
|
|
864
844
|
readOnly,
|
|
865
845
|
className
|
|
866
846
|
}) {
|
|
867
|
-
console.log("Lable type", labelIcon);
|
|
868
847
|
const El = el ?? "div";
|
|
848
|
+
const labelAdornment = icon ?? labelIcon;
|
|
869
849
|
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(El, { className: `flex flex-col gap-1.5 ${className ?? ""}`, children: [
|
|
870
850
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
871
|
-
|
|
851
|
+
labelAdornment && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: labelAdornment }),
|
|
872
852
|
/* @__PURE__ */ jsx(Label, { className: "text-xs font-medium text-muted-foreground", children: label }),
|
|
873
853
|
label && /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
874
|
-
/* @__PURE__ */ jsx(
|
|
854
|
+
/* @__PURE__ */ jsx(
|
|
855
|
+
TooltipTrigger,
|
|
856
|
+
{
|
|
857
|
+
"aria-label": label,
|
|
858
|
+
render: /* @__PURE__ */ jsx(
|
|
859
|
+
"button",
|
|
860
|
+
{
|
|
861
|
+
type: "button",
|
|
862
|
+
className: "inline-flex cursor-help items-center justify-center text-muted-foreground/60 transition-colors hover:text-muted-foreground"
|
|
863
|
+
}
|
|
864
|
+
),
|
|
865
|
+
children: /* @__PURE__ */ jsx(Info, { className: "h-3 w-3 text-muted-foreground/60 cursor-help" })
|
|
866
|
+
}
|
|
867
|
+
),
|
|
875
868
|
/* @__PURE__ */ jsx(TooltipContent, { side: "right", children: label })
|
|
876
869
|
] }),
|
|
877
870
|
readOnly && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs text-muted-foreground/50", children: "Read only" })
|
|
@@ -879,6 +872,50 @@ function FieldLabel({
|
|
|
879
872
|
children
|
|
880
873
|
] }) });
|
|
881
874
|
}
|
|
875
|
+
var buttonVariants = cva(
|
|
876
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
877
|
+
{
|
|
878
|
+
variants: {
|
|
879
|
+
variant: {
|
|
880
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
881
|
+
outline: "border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
882
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
883
|
+
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
884
|
+
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",
|
|
885
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
886
|
+
},
|
|
887
|
+
size: {
|
|
888
|
+
default: "h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
889
|
+
xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
890
|
+
sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
|
|
891
|
+
lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
892
|
+
icon: "size-9",
|
|
893
|
+
"icon-xs": "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
894
|
+
"icon-sm": "size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
|
|
895
|
+
"icon-lg": "size-10"
|
|
896
|
+
}
|
|
897
|
+
},
|
|
898
|
+
defaultVariants: {
|
|
899
|
+
variant: "default",
|
|
900
|
+
size: "default"
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
);
|
|
904
|
+
function Button({
|
|
905
|
+
className,
|
|
906
|
+
variant = "default",
|
|
907
|
+
size = "default",
|
|
908
|
+
...props
|
|
909
|
+
}) {
|
|
910
|
+
return /* @__PURE__ */ jsx(
|
|
911
|
+
Button$1,
|
|
912
|
+
{
|
|
913
|
+
"data-slot": "button",
|
|
914
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
915
|
+
...props
|
|
916
|
+
}
|
|
917
|
+
);
|
|
918
|
+
}
|
|
882
919
|
var MOCK_VALUES = {
|
|
883
920
|
default: ["AI-generated content", "Smart suggestion", "Generated text"]
|
|
884
921
|
};
|
|
@@ -890,7 +927,7 @@ function getMock(instructions) {
|
|
|
890
927
|
return pool[Math.floor(Math.random() * pool.length)];
|
|
891
928
|
}
|
|
892
929
|
function AiButton({ ai, onGenerate }) {
|
|
893
|
-
const [loading, setLoading] =
|
|
930
|
+
const [loading, setLoading] = React17.useState(false);
|
|
894
931
|
const handleClick = () => {
|
|
895
932
|
setLoading(true);
|
|
896
933
|
setTimeout(() => {
|
|
@@ -921,13 +958,22 @@ function TextField({
|
|
|
921
958
|
label,
|
|
922
959
|
labelIcon
|
|
923
960
|
}) {
|
|
924
|
-
const [local, setLocal] =
|
|
925
|
-
|
|
961
|
+
const [local, setLocal] = React17.useState(value ?? "");
|
|
962
|
+
const onChangeRef = React17.useRef(onChange);
|
|
963
|
+
const lastCommittedValueRef = React17.useRef(value ?? "");
|
|
964
|
+
React17.useEffect(() => {
|
|
965
|
+
onChangeRef.current = onChange;
|
|
966
|
+
}, [onChange]);
|
|
967
|
+
React17.useEffect(() => {
|
|
968
|
+
lastCommittedValueRef.current = value ?? "";
|
|
926
969
|
setLocal(value ?? "");
|
|
927
970
|
}, [value]);
|
|
928
|
-
|
|
971
|
+
React17.useEffect(() => {
|
|
929
972
|
const timer = setTimeout(() => {
|
|
930
|
-
if (local !==
|
|
973
|
+
if (local !== lastCommittedValueRef.current) {
|
|
974
|
+
onChangeRef.current(local);
|
|
975
|
+
lastCommittedValueRef.current = local;
|
|
976
|
+
}
|
|
931
977
|
}, 200);
|
|
932
978
|
return () => clearTimeout(timer);
|
|
933
979
|
}, [local]);
|
|
@@ -942,10 +988,17 @@ function TextField({
|
|
|
942
988
|
className: "h-8 text-sm flex-1"
|
|
943
989
|
}
|
|
944
990
|
),
|
|
945
|
-
field?.ai && /* @__PURE__ */ jsx(
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
991
|
+
field?.ai && /* @__PURE__ */ jsx(
|
|
992
|
+
AiButton,
|
|
993
|
+
{
|
|
994
|
+
ai: field.ai,
|
|
995
|
+
onGenerate: (nextValue) => {
|
|
996
|
+
lastCommittedValueRef.current = nextValue;
|
|
997
|
+
setLocal(nextValue);
|
|
998
|
+
onChangeRef.current(nextValue);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
)
|
|
949
1002
|
] }) });
|
|
950
1003
|
}
|
|
951
1004
|
function Textarea({ className, ...props }) {
|
|
@@ -954,7 +1007,7 @@ function Textarea({ className, ...props }) {
|
|
|
954
1007
|
{
|
|
955
1008
|
"data-slot": "textarea",
|
|
956
1009
|
className: cn(
|
|
957
|
-
"flex field-sizing-content min-h-16 w-full rounded-
|
|
1010
|
+
"flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-2.5 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
958
1011
|
className
|
|
959
1012
|
),
|
|
960
1013
|
...props
|
|
@@ -962,11 +1015,11 @@ function Textarea({ className, ...props }) {
|
|
|
962
1015
|
);
|
|
963
1016
|
}
|
|
964
1017
|
function TextareaField({ value, onChange, readOnly, placeholder, label }) {
|
|
965
|
-
const [local, setLocal] =
|
|
966
|
-
|
|
1018
|
+
const [local, setLocal] = React17.useState(value ?? "");
|
|
1019
|
+
React17.useEffect(() => {
|
|
967
1020
|
setLocal(value ?? "");
|
|
968
1021
|
}, [value]);
|
|
969
|
-
|
|
1022
|
+
React17.useEffect(() => {
|
|
970
1023
|
const timer = setTimeout(() => {
|
|
971
1024
|
if (local !== value) onChange(local);
|
|
972
1025
|
}, 200);
|
|
@@ -984,11 +1037,11 @@ function TextareaField({ value, onChange, readOnly, placeholder, label }) {
|
|
|
984
1037
|
) });
|
|
985
1038
|
}
|
|
986
1039
|
function NumberField({ value, onChange, readOnly, min, max, step, label }) {
|
|
987
|
-
const [local, setLocal] =
|
|
988
|
-
|
|
1040
|
+
const [local, setLocal] = React17.useState(String(value ?? ""));
|
|
1041
|
+
React17.useEffect(() => {
|
|
989
1042
|
setLocal(String(value ?? ""));
|
|
990
1043
|
}, [value]);
|
|
991
|
-
|
|
1044
|
+
React17.useEffect(() => {
|
|
992
1045
|
const parsed = parseFloat(local);
|
|
993
1046
|
if (!isNaN(parsed) && parsed !== value) {
|
|
994
1047
|
const timer = setTimeout(() => onChange(parsed), 200);
|
|
@@ -1042,7 +1095,7 @@ function SelectTrigger({
|
|
|
1042
1095
|
"data-slot": "select-trigger",
|
|
1043
1096
|
"data-size": size,
|
|
1044
1097
|
className: cn(
|
|
1045
|
-
"
|
|
1098
|
+
"flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1046
1099
|
className
|
|
1047
1100
|
),
|
|
1048
1101
|
...props,
|
|
@@ -1051,7 +1104,7 @@ function SelectTrigger({
|
|
|
1051
1104
|
/* @__PURE__ */ jsx(
|
|
1052
1105
|
Select$1.Icon,
|
|
1053
1106
|
{
|
|
1054
|
-
render: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "
|
|
1107
|
+
render: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "pointer-events-none size-4 text-muted-foreground" })
|
|
1055
1108
|
}
|
|
1056
1109
|
)
|
|
1057
1110
|
]
|
|
@@ -1082,10 +1135,7 @@ function SelectContent({
|
|
|
1082
1135
|
{
|
|
1083
1136
|
"data-slot": "select-content",
|
|
1084
1137
|
"data-align-trigger": alignItemWithTrigger,
|
|
1085
|
-
className: cn(
|
|
1086
|
-
"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",
|
|
1087
|
-
className
|
|
1088
|
-
),
|
|
1138
|
+
className: cn("relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
|
|
1089
1139
|
...props,
|
|
1090
1140
|
children: [
|
|
1091
1141
|
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
@@ -1107,16 +1157,17 @@ function SelectItem({
|
|
|
1107
1157
|
{
|
|
1108
1158
|
"data-slot": "select-item",
|
|
1109
1159
|
className: cn(
|
|
1110
|
-
"focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground
|
|
1160
|
+
"relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
1111
1161
|
className
|
|
1112
1162
|
),
|
|
1113
1163
|
...props,
|
|
1114
1164
|
children: [
|
|
1115
|
-
/* @__PURE__ */ jsx(Select$1.ItemText, { className: "flex flex-1 gap-2
|
|
1165
|
+
/* @__PURE__ */ jsx(Select$1.ItemText, { className: "flex flex-1 shrink-0 gap-2 whitespace-nowrap", children }),
|
|
1116
1166
|
/* @__PURE__ */ jsx(
|
|
1117
1167
|
Select$1.ItemIndicator,
|
|
1118
1168
|
{
|
|
1119
|
-
render: /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center"
|
|
1169
|
+
render: /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }),
|
|
1170
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { className: "pointer-events-none" })
|
|
1120
1171
|
}
|
|
1121
1172
|
)
|
|
1122
1173
|
]
|
|
@@ -1132,11 +1183,14 @@ function SelectScrollUpButton({
|
|
|
1132
1183
|
{
|
|
1133
1184
|
"data-slot": "select-scroll-up-button",
|
|
1134
1185
|
className: cn(
|
|
1135
|
-
"
|
|
1186
|
+
"top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
|
|
1136
1187
|
className
|
|
1137
1188
|
),
|
|
1138
1189
|
...props,
|
|
1139
|
-
children: /* @__PURE__ */ jsx(
|
|
1190
|
+
children: /* @__PURE__ */ jsx(
|
|
1191
|
+
ChevronUpIcon,
|
|
1192
|
+
{}
|
|
1193
|
+
)
|
|
1140
1194
|
}
|
|
1141
1195
|
);
|
|
1142
1196
|
}
|
|
@@ -1149,11 +1203,14 @@ function SelectScrollDownButton({
|
|
|
1149
1203
|
{
|
|
1150
1204
|
"data-slot": "select-scroll-down-button",
|
|
1151
1205
|
className: cn(
|
|
1152
|
-
"
|
|
1206
|
+
"bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
|
|
1153
1207
|
className
|
|
1154
1208
|
),
|
|
1155
1209
|
...props,
|
|
1156
|
-
children: /* @__PURE__ */ jsx(
|
|
1210
|
+
children: /* @__PURE__ */ jsx(
|
|
1211
|
+
ChevronDownIcon,
|
|
1212
|
+
{}
|
|
1213
|
+
)
|
|
1157
1214
|
}
|
|
1158
1215
|
);
|
|
1159
1216
|
}
|
|
@@ -1175,12 +1232,12 @@ function SelectField({ field, value, onChange, id, readOnly, label }) {
|
|
|
1175
1232
|
) });
|
|
1176
1233
|
}
|
|
1177
1234
|
var buttonGroupVariants = cva(
|
|
1178
|
-
"has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-
|
|
1235
|
+
"flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
|
|
1179
1236
|
{
|
|
1180
1237
|
variants: {
|
|
1181
1238
|
orientation: {
|
|
1182
|
-
horizontal: "[&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-
|
|
1183
|
-
vertical: "[&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-
|
|
1239
|
+
horizontal: "*:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-md! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0",
|
|
1240
|
+
vertical: "flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0"
|
|
1184
1241
|
}
|
|
1185
1242
|
},
|
|
1186
1243
|
defaultVariants: {
|
|
@@ -1199,7 +1256,7 @@ function ButtonGroup({
|
|
|
1199
1256
|
role: "group",
|
|
1200
1257
|
"data-slot": "button-group",
|
|
1201
1258
|
"data-orientation": orientation,
|
|
1202
|
-
className:
|
|
1259
|
+
className: cn(buttonGroupVariants({ orientation }), className),
|
|
1203
1260
|
...props
|
|
1204
1261
|
}
|
|
1205
1262
|
);
|
|
@@ -1229,8 +1286,8 @@ function ItemGroup({ className, ...props }) {
|
|
|
1229
1286
|
{
|
|
1230
1287
|
role: "list",
|
|
1231
1288
|
"data-slot": "item-group",
|
|
1232
|
-
className:
|
|
1233
|
-
"gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2
|
|
1289
|
+
className: cn(
|
|
1290
|
+
"group/item-group flex w-full flex-col gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2",
|
|
1234
1291
|
className
|
|
1235
1292
|
),
|
|
1236
1293
|
...props
|
|
@@ -1238,16 +1295,16 @@ function ItemGroup({ className, ...props }) {
|
|
|
1238
1295
|
);
|
|
1239
1296
|
}
|
|
1240
1297
|
var itemVariants = cva(
|
|
1241
|
-
"
|
|
1298
|
+
"group/item flex w-full flex-wrap items-center rounded-md border text-sm transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [a]:transition-colors [a]:hover:bg-muted",
|
|
1242
1299
|
{
|
|
1243
1300
|
variants: {
|
|
1244
1301
|
variant: {
|
|
1245
1302
|
default: "border-transparent",
|
|
1246
1303
|
outline: "border-border",
|
|
1247
|
-
muted: "bg-muted/50
|
|
1304
|
+
muted: "border-transparent bg-muted/50"
|
|
1248
1305
|
},
|
|
1249
1306
|
size: {
|
|
1250
|
-
default: "gap-
|
|
1307
|
+
default: "gap-3.5 px-4 py-3.5",
|
|
1251
1308
|
sm: "gap-2.5 px-3 py-2.5",
|
|
1252
1309
|
xs: "gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0"
|
|
1253
1310
|
}
|
|
@@ -1269,7 +1326,7 @@ function Item({
|
|
|
1269
1326
|
defaultTagName: "div",
|
|
1270
1327
|
props: mergeProps(
|
|
1271
1328
|
{
|
|
1272
|
-
className:
|
|
1329
|
+
className: cn(itemVariants({ variant, size, className }))
|
|
1273
1330
|
},
|
|
1274
1331
|
props
|
|
1275
1332
|
),
|
|
@@ -1282,7 +1339,7 @@ function Item({
|
|
|
1282
1339
|
});
|
|
1283
1340
|
}
|
|
1284
1341
|
cva(
|
|
1285
|
-
"gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start
|
|
1342
|
+
"flex shrink-0 items-center justify-center gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start [&_svg]:pointer-events-none",
|
|
1286
1343
|
{
|
|
1287
1344
|
variants: {
|
|
1288
1345
|
variant: {
|
|
@@ -1301,8 +1358,8 @@ function ItemContent({ className, ...props }) {
|
|
|
1301
1358
|
"div",
|
|
1302
1359
|
{
|
|
1303
1360
|
"data-slot": "item-content",
|
|
1304
|
-
className:
|
|
1305
|
-
"gap-1 group-data-[size=xs]/item:gap-0
|
|
1361
|
+
className: cn(
|
|
1362
|
+
"flex flex-1 flex-col gap-1 group-data-[size=xs]/item:gap-0 [&+[data-slot=item-content]]:flex-none",
|
|
1306
1363
|
className
|
|
1307
1364
|
),
|
|
1308
1365
|
...props
|
|
@@ -1314,8 +1371,8 @@ function ItemTitle({ className, ...props }) {
|
|
|
1314
1371
|
"div",
|
|
1315
1372
|
{
|
|
1316
1373
|
"data-slot": "item-title",
|
|
1317
|
-
className:
|
|
1318
|
-
"gap-2 text-sm leading-snug font-medium underline-offset-4
|
|
1374
|
+
className: cn(
|
|
1375
|
+
"line-clamp-1 flex w-fit items-center gap-2 text-sm leading-snug font-medium underline-offset-4",
|
|
1319
1376
|
className
|
|
1320
1377
|
),
|
|
1321
1378
|
...props
|
|
@@ -1327,20 +1384,20 @@ function ItemActions({ className, ...props }) {
|
|
|
1327
1384
|
"div",
|
|
1328
1385
|
{
|
|
1329
1386
|
"data-slot": "item-actions",
|
|
1330
|
-
className:
|
|
1387
|
+
className: cn("flex items-center gap-2", className),
|
|
1331
1388
|
...props
|
|
1332
1389
|
}
|
|
1333
1390
|
);
|
|
1334
1391
|
}
|
|
1335
1392
|
function useControlledState(props) {
|
|
1336
1393
|
const { value, defaultValue, onChange } = props;
|
|
1337
|
-
const [state, setInternalState] =
|
|
1394
|
+
const [state, setInternalState] = React17.useState(
|
|
1338
1395
|
value !== void 0 ? value : defaultValue
|
|
1339
1396
|
);
|
|
1340
|
-
|
|
1397
|
+
React17.useEffect(() => {
|
|
1341
1398
|
if (value !== void 0) setInternalState(value);
|
|
1342
1399
|
}, [value]);
|
|
1343
|
-
const setState =
|
|
1400
|
+
const setState = React17.useCallback(
|
|
1344
1401
|
(next, ...args) => {
|
|
1345
1402
|
setInternalState(next);
|
|
1346
1403
|
onChange?.(next, ...args);
|
|
@@ -1453,6 +1510,9 @@ function PopoverPanel({
|
|
|
1453
1510
|
function PopoverTitle2(props) {
|
|
1454
1511
|
return /* @__PURE__ */ jsx(PopoverTitle, { ...props });
|
|
1455
1512
|
}
|
|
1513
|
+
function getArraySubField(subName, subField) {
|
|
1514
|
+
return { ...subField, label: subField.label ?? subName };
|
|
1515
|
+
}
|
|
1456
1516
|
function SortableItem({
|
|
1457
1517
|
id,
|
|
1458
1518
|
index,
|
|
@@ -1539,7 +1599,7 @@ function SortableItem({
|
|
|
1539
1599
|
children: Object.entries(field.arrayFields).map(([subName, subField]) => /* @__PURE__ */ jsx(
|
|
1540
1600
|
AutoField,
|
|
1541
1601
|
{
|
|
1542
|
-
field:
|
|
1602
|
+
field: getArraySubField(subName, subField),
|
|
1543
1603
|
value: item[subName],
|
|
1544
1604
|
onChange: (val) => onUpdate(index, subName, val),
|
|
1545
1605
|
readOnly,
|
|
@@ -1559,13 +1619,17 @@ function ArrayField({
|
|
|
1559
1619
|
label,
|
|
1560
1620
|
id = ""
|
|
1561
1621
|
}) {
|
|
1562
|
-
const
|
|
1563
|
-
const
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1622
|
+
const [openIndex, setOpenIndex] = React17.useState(null);
|
|
1623
|
+
const stableValue = React17.useMemo(() => {
|
|
1624
|
+
const needsId = value.some((item) => !item._id);
|
|
1625
|
+
if (!needsId) return value;
|
|
1626
|
+
return value.map(
|
|
1627
|
+
(item) => item._id ? item : { ...item, _id: `${id}-${Math.random().toString(36).slice(2)}` }
|
|
1628
|
+
);
|
|
1629
|
+
}, [value, id]);
|
|
1630
|
+
const itemIds = stableValue.map((item) => item._id);
|
|
1631
|
+
const atMax = field.max !== void 0 && stableValue.length >= field.max;
|
|
1632
|
+
const atMin = field.min !== void 0 && stableValue.length <= field.min;
|
|
1569
1633
|
const sensors = useSensors(useSensor(PointerSensor));
|
|
1570
1634
|
const handleDragEnd = (event) => {
|
|
1571
1635
|
const { active, over } = event;
|
|
@@ -1573,7 +1637,7 @@ function ArrayField({
|
|
|
1573
1637
|
const from = itemIds.indexOf(active.id);
|
|
1574
1638
|
const to = itemIds.indexOf(over.id);
|
|
1575
1639
|
if (from === -1 || to === -1) return;
|
|
1576
|
-
onChange(arrayMove(
|
|
1640
|
+
onChange(arrayMove(stableValue, from, to));
|
|
1577
1641
|
};
|
|
1578
1642
|
const defaultItem = () => {
|
|
1579
1643
|
if (!field.defaultItemProps) return {};
|
|
@@ -1581,33 +1645,35 @@ function ArrayField({
|
|
|
1581
1645
|
};
|
|
1582
1646
|
const addItem = () => {
|
|
1583
1647
|
if (atMax || readOnly) return;
|
|
1584
|
-
const newIndex =
|
|
1585
|
-
onChange([...
|
|
1648
|
+
const newIndex = stableValue.length;
|
|
1649
|
+
onChange([...stableValue, defaultItem()]);
|
|
1586
1650
|
setOpenIndex(newIndex);
|
|
1587
1651
|
};
|
|
1588
1652
|
const removeItem = (i) => {
|
|
1589
1653
|
if (atMin || readOnly) return;
|
|
1590
|
-
const next = [...
|
|
1654
|
+
const next = [...stableValue];
|
|
1591
1655
|
next.splice(i, 1);
|
|
1592
1656
|
onChange(next);
|
|
1593
1657
|
};
|
|
1594
1658
|
const duplicateItem = (i) => {
|
|
1595
1659
|
if (atMax || readOnly) return;
|
|
1596
|
-
const next = [...
|
|
1597
|
-
next.splice(i + 1, 0, { ...
|
|
1660
|
+
const next = [...stableValue];
|
|
1661
|
+
next.splice(i + 1, 0, { ...stableValue[i] });
|
|
1598
1662
|
onChange(next);
|
|
1599
1663
|
};
|
|
1600
1664
|
const updateItem = (i, subName, val) => {
|
|
1601
1665
|
onChange(
|
|
1602
|
-
|
|
1666
|
+
stableValue.map(
|
|
1603
1667
|
(item, idx) => idx === i ? { ...item, [subName]: val } : item
|
|
1604
1668
|
)
|
|
1605
1669
|
);
|
|
1606
1670
|
};
|
|
1607
1671
|
const getSummary = (item, i) => {
|
|
1608
1672
|
if (field.getItemSummary) return field.getItemSummary(item, i);
|
|
1609
|
-
const first = Object.
|
|
1610
|
-
|
|
1673
|
+
const first = Object.entries(item).find(
|
|
1674
|
+
(entry) => entry[0] !== "_id" && typeof entry[1] === "string" && entry[1].length > 0
|
|
1675
|
+
);
|
|
1676
|
+
return first?.[1] ?? `Item ${i + 1}`;
|
|
1611
1677
|
};
|
|
1612
1678
|
return /* @__PURE__ */ jsx(FieldLabel, { label: label ?? field.label ?? "", readOnly, el: "div", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
1613
1679
|
/* @__PURE__ */ jsx(
|
|
@@ -1621,7 +1687,7 @@ function ArrayField({
|
|
|
1621
1687
|
{
|
|
1622
1688
|
items: itemIds,
|
|
1623
1689
|
strategy: verticalListSortingStrategy,
|
|
1624
|
-
children: /* @__PURE__ */ jsx(ItemGroup, { children:
|
|
1690
|
+
children: /* @__PURE__ */ jsx(ItemGroup, { children: stableValue.map((item, i) => /* @__PURE__ */ jsx(
|
|
1625
1691
|
SortableItem,
|
|
1626
1692
|
{
|
|
1627
1693
|
id: itemIds[i],
|
|
@@ -1674,7 +1740,7 @@ function Card({
|
|
|
1674
1740
|
"data-slot": "card",
|
|
1675
1741
|
"data-size": size,
|
|
1676
1742
|
className: cn(
|
|
1677
|
-
"group/card flex flex-col gap-
|
|
1743
|
+
"group/card flex flex-col gap-6 overflow-hidden rounded-xl bg-card py-6 text-sm text-card-foreground shadow-xs ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
|
|
1678
1744
|
className
|
|
1679
1745
|
),
|
|
1680
1746
|
...props
|
|
@@ -1686,7 +1752,7 @@ function CardContent({ className, ...props }) {
|
|
|
1686
1752
|
"div",
|
|
1687
1753
|
{
|
|
1688
1754
|
"data-slot": "card-content",
|
|
1689
|
-
className: cn("px-
|
|
1755
|
+
className: cn("px-6 group-data-[size=sm]/card:px-4", className),
|
|
1690
1756
|
...props
|
|
1691
1757
|
}
|
|
1692
1758
|
);
|
|
@@ -1698,17 +1764,17 @@ function CustomField({ children, label }) {
|
|
|
1698
1764
|
return /* @__PURE__ */ jsx(FieldLabel, { label: label ?? "", el: "div", children: /* @__PURE__ */ jsx("div", { className: "rounded-md border border-border/60 p-3", children }) });
|
|
1699
1765
|
}
|
|
1700
1766
|
var toggleVariants = cva(
|
|
1701
|
-
"group/toggle inline-flex items-center justify-center gap-1 rounded-
|
|
1767
|
+
"group/toggle inline-flex items-center justify-center gap-1 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1702
1768
|
{
|
|
1703
1769
|
variants: {
|
|
1704
1770
|
variant: {
|
|
1705
1771
|
default: "bg-transparent",
|
|
1706
|
-
outline: "border border-input bg-transparent hover:bg-muted"
|
|
1772
|
+
outline: "border border-input bg-transparent shadow-xs hover:bg-muted"
|
|
1707
1773
|
},
|
|
1708
1774
|
size: {
|
|
1709
|
-
default: "h-
|
|
1710
|
-
sm: "h-
|
|
1711
|
-
lg: "h-
|
|
1775
|
+
default: "h-9 min-w-9 px-2",
|
|
1776
|
+
sm: "h-8 min-w-8 px-1.5",
|
|
1777
|
+
lg: "h-10 min-w-10 px-2.5"
|
|
1712
1778
|
}
|
|
1713
1779
|
},
|
|
1714
1780
|
defaultVariants: {
|
|
@@ -1733,12 +1799,12 @@ function Toggle({
|
|
|
1733
1799
|
);
|
|
1734
1800
|
}
|
|
1735
1801
|
function RichtextField({ value, onChange, readOnly, label }) {
|
|
1736
|
-
const ref =
|
|
1802
|
+
const ref = React17.useRef(null);
|
|
1737
1803
|
const boldLabel = useMsg("richtext.bold");
|
|
1738
1804
|
const italicLabel = useMsg("richtext.italic");
|
|
1739
1805
|
const linkLabel = useMsg("richtext.link");
|
|
1740
1806
|
const linkPrompt = useMsg("richtext.link.prompt");
|
|
1741
|
-
|
|
1807
|
+
React17.useEffect(() => {
|
|
1742
1808
|
if (ref.current && ref.current.innerHTML !== value) {
|
|
1743
1809
|
ref.current.innerHTML = value ?? "";
|
|
1744
1810
|
}
|
|
@@ -1785,17 +1851,7 @@ function InputGroup({ className, ...props }) {
|
|
|
1785
1851
|
"data-slot": "input-group",
|
|
1786
1852
|
role: "group",
|
|
1787
1853
|
className: cn(
|
|
1788
|
-
"group/input-group
|
|
1789
|
-
"h-9 has-[>textarea]:h-auto",
|
|
1790
|
-
// Variants based on alignment.
|
|
1791
|
-
"has-[>[data-align=inline-start]]:[&>input]:pl-2",
|
|
1792
|
-
"has-[>[data-align=inline-end]]:[&>input]:pr-2",
|
|
1793
|
-
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
|
|
1794
|
-
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
|
|
1795
|
-
// Focus state.
|
|
1796
|
-
"has-[[data-slot=input-group-control]:focus-visible]:ring-ring has-[[data-slot=input-group-control]:focus-visible]:ring-1",
|
|
1797
|
-
// Error state.
|
|
1798
|
-
"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",
|
|
1854
|
+
"group/input-group relative flex h-9 w-full min-w-0 items-center rounded-md border border-input shadow-xs transition-[color,box-shadow] outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5",
|
|
1799
1855
|
className
|
|
1800
1856
|
),
|
|
1801
1857
|
...props
|
|
@@ -1803,14 +1859,14 @@ function InputGroup({ className, ...props }) {
|
|
|
1803
1859
|
);
|
|
1804
1860
|
}
|
|
1805
1861
|
var inputGroupAddonVariants = cva(
|
|
1806
|
-
"
|
|
1862
|
+
"flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
|
|
1807
1863
|
{
|
|
1808
1864
|
variants: {
|
|
1809
1865
|
align: {
|
|
1810
|
-
"inline-start": "order-first pl-
|
|
1811
|
-
"inline-end": "order-last pr-
|
|
1812
|
-
"block-start": "
|
|
1813
|
-
"block-end": "
|
|
1866
|
+
"inline-start": "order-first pl-2 has-[>button]:-ml-1 has-[>kbd]:ml-[-0.15rem]",
|
|
1867
|
+
"inline-end": "order-last pr-2 has-[>button]:-mr-1 has-[>kbd]:mr-[-0.15rem]",
|
|
1868
|
+
"block-start": "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
|
|
1869
|
+
"block-end": "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"
|
|
1814
1870
|
}
|
|
1815
1871
|
},
|
|
1816
1872
|
defaultVariants: {
|
|
@@ -1845,8 +1901,8 @@ cva(
|
|
|
1845
1901
|
{
|
|
1846
1902
|
variants: {
|
|
1847
1903
|
size: {
|
|
1848
|
-
xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-
|
|
1849
|
-
sm: "
|
|
1904
|
+
xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
|
|
1905
|
+
sm: "",
|
|
1850
1906
|
"icon-xs": "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
|
|
1851
1907
|
"icon-sm": "size-8 p-0 has-[>svg]:p-0"
|
|
1852
1908
|
}
|
|
@@ -1930,7 +1986,7 @@ function CommandItem({
|
|
|
1930
1986
|
{
|
|
1931
1987
|
"data-slot": "command-item",
|
|
1932
1988
|
className: cn(
|
|
1933
|
-
"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
|
|
1989
|
+
"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",
|
|
1934
1990
|
className
|
|
1935
1991
|
),
|
|
1936
1992
|
...props,
|
|
@@ -1952,10 +2008,10 @@ function Skeleton({ className, ...props }) {
|
|
|
1952
2008
|
);
|
|
1953
2009
|
}
|
|
1954
2010
|
function ExternalField({ value, onChange, fetchList, readOnly, label }) {
|
|
1955
|
-
const [query, setQuery] =
|
|
1956
|
-
const [results, setResults] =
|
|
1957
|
-
const [loading, setLoading] =
|
|
1958
|
-
|
|
2011
|
+
const [query, setQuery] = React17.useState("");
|
|
2012
|
+
const [results, setResults] = React17.useState([]);
|
|
2013
|
+
const [loading, setLoading] = React17.useState(false);
|
|
2014
|
+
React17.useEffect(() => {
|
|
1959
2015
|
if (!fetchList) return;
|
|
1960
2016
|
setLoading(true);
|
|
1961
2017
|
const timer = setTimeout(async () => {
|
|
@@ -2001,7 +2057,7 @@ function ExternalField({ value, onChange, fetchList, readOnly, label }) {
|
|
|
2001
2057
|
] }) });
|
|
2002
2058
|
}
|
|
2003
2059
|
|
|
2004
|
-
// src/
|
|
2060
|
+
// src/core/overrides/fields/FieldTypesRegistry.ts
|
|
2005
2061
|
var fieldTypesRegistry = {
|
|
2006
2062
|
text: TextField,
|
|
2007
2063
|
textarea: TextareaField,
|
|
@@ -2019,8 +2075,6 @@ function PuckRoot({ children }) {
|
|
|
2019
2075
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
2020
2076
|
}
|
|
2021
2077
|
var puckOverrides = {
|
|
2022
|
-
header: EditorHeader,
|
|
2023
|
-
headerActions: EditorHeaderActions,
|
|
2024
2078
|
drawer: EditorDrawer,
|
|
2025
2079
|
components: EditorComponents,
|
|
2026
2080
|
drawerItem: DrawerItem,
|
|
@@ -2040,9 +2094,9 @@ var DEFAULT_BOUNDS_OFFSET = {
|
|
|
2040
2094
|
width: 0,
|
|
2041
2095
|
height: 0
|
|
2042
2096
|
};
|
|
2043
|
-
var HighlightContext =
|
|
2097
|
+
var HighlightContext = React17.createContext(void 0);
|
|
2044
2098
|
function useHighlight() {
|
|
2045
|
-
const context =
|
|
2099
|
+
const context = React17.useContext(HighlightContext);
|
|
2046
2100
|
if (!context) {
|
|
2047
2101
|
throw new Error("useHighlight must be used within a HighlightProvider");
|
|
2048
2102
|
}
|
|
@@ -2069,21 +2123,21 @@ function Highlight({
|
|
|
2069
2123
|
exitDelay = 200,
|
|
2070
2124
|
mode = "children"
|
|
2071
2125
|
} = props;
|
|
2072
|
-
const localRef =
|
|
2073
|
-
|
|
2126
|
+
const localRef = React17.useRef(null);
|
|
2127
|
+
React17.useImperativeHandle(ref, () => localRef.current);
|
|
2074
2128
|
const propsBoundsOffset = props?.boundsOffset;
|
|
2075
2129
|
const boundsOffset = propsBoundsOffset ?? DEFAULT_BOUNDS_OFFSET;
|
|
2076
2130
|
const boundsOffsetTop = boundsOffset.top ?? 0;
|
|
2077
2131
|
const boundsOffsetLeft = boundsOffset.left ?? 0;
|
|
2078
2132
|
const boundsOffsetWidth = boundsOffset.width ?? 0;
|
|
2079
2133
|
const boundsOffsetHeight = boundsOffset.height ?? 0;
|
|
2080
|
-
const boundsOffsetRef =
|
|
2134
|
+
const boundsOffsetRef = React17.useRef({
|
|
2081
2135
|
top: boundsOffsetTop,
|
|
2082
2136
|
left: boundsOffsetLeft,
|
|
2083
2137
|
width: boundsOffsetWidth,
|
|
2084
2138
|
height: boundsOffsetHeight
|
|
2085
2139
|
});
|
|
2086
|
-
|
|
2140
|
+
React17.useEffect(() => {
|
|
2087
2141
|
boundsOffsetRef.current = {
|
|
2088
2142
|
top: boundsOffsetTop,
|
|
2089
2143
|
left: boundsOffsetLeft,
|
|
@@ -2096,11 +2150,11 @@ function Highlight({
|
|
|
2096
2150
|
boundsOffsetWidth,
|
|
2097
2151
|
boundsOffsetHeight
|
|
2098
2152
|
]);
|
|
2099
|
-
const [activeValue, setActiveValue] =
|
|
2153
|
+
const [activeValue, setActiveValue] = React17.useState(
|
|
2100
2154
|
value ?? defaultValue ?? null
|
|
2101
2155
|
);
|
|
2102
|
-
const [boundsState, setBoundsState] =
|
|
2103
|
-
const [activeClassNameState, setActiveClassNameState] =
|
|
2156
|
+
const [boundsState, setBoundsState] = React17.useState(null);
|
|
2157
|
+
const [activeClassNameState, setActiveClassNameState] = React17.useState("");
|
|
2104
2158
|
const safeSetActiveValue = (id2) => {
|
|
2105
2159
|
setActiveValue((prev) => {
|
|
2106
2160
|
if (prev !== id2) {
|
|
@@ -2110,8 +2164,8 @@ function Highlight({
|
|
|
2110
2164
|
return prev;
|
|
2111
2165
|
});
|
|
2112
2166
|
};
|
|
2113
|
-
const safeSetBoundsRef =
|
|
2114
|
-
|
|
2167
|
+
const safeSetBoundsRef = React17.useRef(void 0);
|
|
2168
|
+
React17.useEffect(() => {
|
|
2115
2169
|
safeSetBoundsRef.current = (bounds) => {
|
|
2116
2170
|
if (!localRef.current) return;
|
|
2117
2171
|
const containerRect = localRef.current.getBoundingClientRect();
|
|
@@ -2133,15 +2187,15 @@ function Highlight({
|
|
|
2133
2187
|
const safeSetBounds = (bounds) => {
|
|
2134
2188
|
safeSetBoundsRef.current?.(bounds);
|
|
2135
2189
|
};
|
|
2136
|
-
const clearBounds =
|
|
2190
|
+
const clearBounds = React17.useCallback(() => {
|
|
2137
2191
|
setBoundsState((prev) => prev === null ? prev : null);
|
|
2138
2192
|
}, []);
|
|
2139
|
-
|
|
2193
|
+
React17.useEffect(() => {
|
|
2140
2194
|
if (value !== void 0) setActiveValue(value);
|
|
2141
2195
|
else if (defaultValue !== void 0) setActiveValue(defaultValue);
|
|
2142
2196
|
}, [value, defaultValue]);
|
|
2143
|
-
const id =
|
|
2144
|
-
|
|
2197
|
+
const id = React17.useId();
|
|
2198
|
+
React17.useEffect(() => {
|
|
2145
2199
|
if (mode !== "parent") return;
|
|
2146
2200
|
const container = localRef.current;
|
|
2147
2201
|
if (!container) return;
|
|
@@ -2226,7 +2280,7 @@ function Highlight({
|
|
|
2226
2280
|
forceUpdateBounds: props?.forceUpdateBounds
|
|
2227
2281
|
},
|
|
2228
2282
|
children: enabled ? controlledItems ? render(children) : render(
|
|
2229
|
-
|
|
2283
|
+
React17.Children.map(children, (child, index) => /* @__PURE__ */ jsx(HighlightItem, { className: props?.itemsClassName, children: child }, index))
|
|
2230
2284
|
) : children
|
|
2231
2285
|
}
|
|
2232
2286
|
);
|
|
@@ -2258,7 +2312,7 @@ function HighlightItem({
|
|
|
2258
2312
|
forceUpdateBounds,
|
|
2259
2313
|
...props
|
|
2260
2314
|
}) {
|
|
2261
|
-
const itemId =
|
|
2315
|
+
const itemId = React17.useId();
|
|
2262
2316
|
const {
|
|
2263
2317
|
activeValue,
|
|
2264
2318
|
setActiveValue,
|
|
@@ -2283,12 +2337,12 @@ function HighlightItem({
|
|
|
2283
2337
|
const isActive = activeValue === childValue;
|
|
2284
2338
|
const isDisabled = disabled === void 0 ? contextDisabled : disabled;
|
|
2285
2339
|
const itemTransition = transition ?? contextTransition;
|
|
2286
|
-
const localRef =
|
|
2287
|
-
|
|
2288
|
-
const refCallback =
|
|
2340
|
+
const localRef = React17.useRef(null);
|
|
2341
|
+
React17.useImperativeHandle(ref, () => localRef.current);
|
|
2342
|
+
const refCallback = React17.useCallback((node) => {
|
|
2289
2343
|
localRef.current = node;
|
|
2290
2344
|
}, []);
|
|
2291
|
-
|
|
2345
|
+
React17.useEffect(() => {
|
|
2292
2346
|
if (mode !== "parent") return;
|
|
2293
2347
|
let rafId;
|
|
2294
2348
|
let previousBounds = null;
|
|
@@ -2322,7 +2376,7 @@ function HighlightItem({
|
|
|
2322
2376
|
forceUpdateBounds,
|
|
2323
2377
|
contextForceUpdateBounds
|
|
2324
2378
|
]);
|
|
2325
|
-
if (!
|
|
2379
|
+
if (!React17.isValidElement(children)) return children;
|
|
2326
2380
|
const dataAttributes = {
|
|
2327
2381
|
"data-active": isActive ? "true" : "false",
|
|
2328
2382
|
"aria-selected": isActive,
|
|
@@ -2347,7 +2401,7 @@ function HighlightItem({
|
|
|
2347
2401
|
} : {};
|
|
2348
2402
|
if (asChild) {
|
|
2349
2403
|
if (mode === "children") {
|
|
2350
|
-
return
|
|
2404
|
+
return React17.cloneElement(
|
|
2351
2405
|
element,
|
|
2352
2406
|
{
|
|
2353
2407
|
key: childValue,
|
|
@@ -2399,7 +2453,7 @@ function HighlightItem({
|
|
|
2399
2453
|
] })
|
|
2400
2454
|
);
|
|
2401
2455
|
}
|
|
2402
|
-
return
|
|
2456
|
+
return React17.cloneElement(element, {
|
|
2403
2457
|
ref: refCallback,
|
|
2404
2458
|
...getNonOverridingDataAttributes(element, {
|
|
2405
2459
|
...dataAttributes,
|
|
@@ -2443,7 +2497,7 @@ function HighlightItem({
|
|
|
2443
2497
|
...dataAttributes
|
|
2444
2498
|
}
|
|
2445
2499
|
) }),
|
|
2446
|
-
|
|
2500
|
+
React17.cloneElement(element, {
|
|
2447
2501
|
style: { position: "relative", zIndex: 1 },
|
|
2448
2502
|
className: element.props.className,
|
|
2449
2503
|
...getNonOverridingDataAttributes(element, {
|
|
@@ -2490,11 +2544,11 @@ function Slot({
|
|
|
2490
2544
|
...props
|
|
2491
2545
|
}) {
|
|
2492
2546
|
const isAlreadyMotion = typeof children.type === "object" && children.type !== null && isMotionComponent(children.type);
|
|
2493
|
-
const Base =
|
|
2547
|
+
const Base = React17.useMemo(
|
|
2494
2548
|
() => isAlreadyMotion ? children.type : motion.create(children.type),
|
|
2495
2549
|
[isAlreadyMotion, children.type]
|
|
2496
2550
|
);
|
|
2497
|
-
if (!
|
|
2551
|
+
if (!React17.isValidElement(children)) return null;
|
|
2498
2552
|
const { ref: childRef, ...childProps } = children.props;
|
|
2499
2553
|
const mergedProps = mergeProps4(childProps, props);
|
|
2500
2554
|
return /* @__PURE__ */ jsx(Base, { ...mergedProps, ref: mergeRefs(childRef, ref) });
|
|
@@ -2574,6 +2628,52 @@ function TabsTab2({ className, ...props }) {
|
|
|
2574
2628
|
}
|
|
2575
2629
|
) });
|
|
2576
2630
|
}
|
|
2631
|
+
var ACTIVE_TABS = [
|
|
2632
|
+
"insert",
|
|
2633
|
+
"layer",
|
|
2634
|
+
"image",
|
|
2635
|
+
"text",
|
|
2636
|
+
"copilot"
|
|
2637
|
+
];
|
|
2638
|
+
var activeTabSet = new Set(ACTIVE_TABS);
|
|
2639
|
+
function isActiveTab(value) {
|
|
2640
|
+
return activeTabSet.has(value);
|
|
2641
|
+
}
|
|
2642
|
+
function createEditorUiStore(storeId) {
|
|
2643
|
+
return createStore()(
|
|
2644
|
+
persist(
|
|
2645
|
+
(set) => ({
|
|
2646
|
+
drawerSearch: "",
|
|
2647
|
+
setDrawerSearch: (q) => set({ drawerSearch: q }),
|
|
2648
|
+
drawerCollapsed: {},
|
|
2649
|
+
toggleDrawerGroup: (group) => set((s) => ({
|
|
2650
|
+
drawerCollapsed: { ...s.drawerCollapsed, [group]: !s.drawerCollapsed[group] }
|
|
2651
|
+
})),
|
|
2652
|
+
activeTab: "insert",
|
|
2653
|
+
setActiveTab: (tab) => set({ activeTab: tab }),
|
|
2654
|
+
outlineExpanded: {},
|
|
2655
|
+
toggleOutlineItem: (id) => set((s) => ({
|
|
2656
|
+
outlineExpanded: { ...s.outlineExpanded, [id]: !s.outlineExpanded[id] }
|
|
2657
|
+
})),
|
|
2658
|
+
theme: "light",
|
|
2659
|
+
toggleTheme: () => set((s) => {
|
|
2660
|
+
const next = s.theme === "light" ? "dark" : "light";
|
|
2661
|
+
return { theme: next };
|
|
2662
|
+
})
|
|
2663
|
+
}),
|
|
2664
|
+
{
|
|
2665
|
+
name: `anvilkit-ui-${storeId}`,
|
|
2666
|
+
partialize: (s) => ({
|
|
2667
|
+
activeTab: s.activeTab,
|
|
2668
|
+
drawerCollapsed: s.drawerCollapsed,
|
|
2669
|
+
outlineExpanded: s.outlineExpanded,
|
|
2670
|
+
theme: s.theme
|
|
2671
|
+
// drawerSearch intentionally excluded — transient input
|
|
2672
|
+
})
|
|
2673
|
+
}
|
|
2674
|
+
)
|
|
2675
|
+
);
|
|
2676
|
+
}
|
|
2577
2677
|
function Aside() {
|
|
2578
2678
|
const activeTab = useActiveTab();
|
|
2579
2679
|
const setActiveTab = useSetActiveTab();
|
|
@@ -2584,10 +2684,35 @@ function Aside() {
|
|
|
2584
2684
|
{ value: "text", icon: /* @__PURE__ */ jsx(Type, { className: "h-4 w-4" }), label: useMsg("aside.text") },
|
|
2585
2685
|
{ value: "copilot", icon: /* @__PURE__ */ jsx(Bot, { className: "h-4 w-4" }), label: useMsg("aside.copilot") }
|
|
2586
2686
|
];
|
|
2587
|
-
return /* @__PURE__ */ jsx("div", { className: "w-18 h-full py-4 border-r border-neutral-200 dark:border-neutral-800/80", children: /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2687
|
+
return /* @__PURE__ */ jsx("div", { className: "w-18 h-full py-4 border-r border-neutral-200 dark:border-neutral-800/80", children: /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(
|
|
2688
|
+
Tabs2,
|
|
2689
|
+
{
|
|
2690
|
+
value: activeTab,
|
|
2691
|
+
onValueChange: (value) => {
|
|
2692
|
+
if (isActiveTab(value)) {
|
|
2693
|
+
setActiveTab(value);
|
|
2694
|
+
}
|
|
2695
|
+
},
|
|
2696
|
+
className: "w-full flex items-center justify-center",
|
|
2697
|
+
children: /* @__PURE__ */ jsx(TabsList2, { className: "flex-col h-auto bg-transparent gap-2", children: tabs.map(({ value, icon, label }) => /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
2698
|
+
/* @__PURE__ */ jsx(
|
|
2699
|
+
TooltipTrigger,
|
|
2700
|
+
{
|
|
2701
|
+
render: /* @__PURE__ */ jsx(
|
|
2702
|
+
TabsTab2,
|
|
2703
|
+
{
|
|
2704
|
+
value,
|
|
2705
|
+
className: "p-2",
|
|
2706
|
+
"aria-label": label
|
|
2707
|
+
}
|
|
2708
|
+
),
|
|
2709
|
+
children: icon
|
|
2710
|
+
}
|
|
2711
|
+
),
|
|
2712
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "right", children: label })
|
|
2713
|
+
] }, value)) })
|
|
2714
|
+
}
|
|
2715
|
+
) }) });
|
|
2591
2716
|
}
|
|
2592
2717
|
function AnimatedAsana({
|
|
2593
2718
|
trigger = false,
|
|
@@ -2779,10 +2904,10 @@ function AnimatedAsana({
|
|
|
2779
2904
|
}
|
|
2780
2905
|
);
|
|
2781
2906
|
}
|
|
2782
|
-
|
|
2907
|
+
React17__default.memo(function TriggerableAsana2(props) {
|
|
2783
2908
|
return /* @__PURE__ */ jsx(AnimatedAsana, { useTrigger: true, ...props });
|
|
2784
2909
|
});
|
|
2785
|
-
|
|
2910
|
+
React17__default.memo(function ControlledAsana2(props) {
|
|
2786
2911
|
return /* @__PURE__ */ jsx(AnimatedAsana, { useTrigger: false, ...props });
|
|
2787
2912
|
});
|
|
2788
2913
|
var [GlobalTooltipProvider, useGlobalTooltip] = getStrictContext("GlobalTooltipProvider");
|
|
@@ -2808,12 +2933,12 @@ function TooltipProvider2({
|
|
|
2808
2933
|
closeDelay = 300,
|
|
2809
2934
|
transition = { type: "spring", stiffness: 300, damping: 35 }
|
|
2810
2935
|
}) {
|
|
2811
|
-
const globalId =
|
|
2812
|
-
const [currentTooltip, setCurrentTooltip] =
|
|
2813
|
-
const timeoutRef =
|
|
2814
|
-
const lastCloseTimeRef =
|
|
2815
|
-
const referenceElRef =
|
|
2816
|
-
const showTooltip =
|
|
2936
|
+
const globalId = React17.useId();
|
|
2937
|
+
const [currentTooltip, setCurrentTooltip] = React17.useState(null);
|
|
2938
|
+
const timeoutRef = React17.useRef(null);
|
|
2939
|
+
const lastCloseTimeRef = React17.useRef(0);
|
|
2940
|
+
const referenceElRef = React17.useRef(null);
|
|
2941
|
+
const showTooltip = React17.useCallback(
|
|
2817
2942
|
(data) => {
|
|
2818
2943
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2819
2944
|
if (currentTooltip !== null) {
|
|
@@ -2829,22 +2954,22 @@ function TooltipProvider2({
|
|
|
2829
2954
|
},
|
|
2830
2955
|
[openDelay, closeDelay, currentTooltip]
|
|
2831
2956
|
);
|
|
2832
|
-
const hideTooltip =
|
|
2957
|
+
const hideTooltip = React17.useCallback(() => {
|
|
2833
2958
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2834
2959
|
timeoutRef.current = window.setTimeout(() => {
|
|
2835
2960
|
setCurrentTooltip(null);
|
|
2836
2961
|
lastCloseTimeRef.current = Date.now();
|
|
2837
2962
|
}, closeDelay);
|
|
2838
2963
|
}, [closeDelay]);
|
|
2839
|
-
const hideImmediate =
|
|
2964
|
+
const hideImmediate = React17.useCallback(() => {
|
|
2840
2965
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2841
2966
|
setCurrentTooltip(null);
|
|
2842
2967
|
lastCloseTimeRef.current = Date.now();
|
|
2843
2968
|
}, []);
|
|
2844
|
-
const setReferenceEl =
|
|
2969
|
+
const setReferenceEl = React17.useCallback((el) => {
|
|
2845
2970
|
referenceElRef.current = el;
|
|
2846
2971
|
}, []);
|
|
2847
|
-
|
|
2972
|
+
React17.useEffect(() => {
|
|
2848
2973
|
const onKeyDown = (e) => {
|
|
2849
2974
|
if (e.key === "Escape") hideImmediate();
|
|
2850
2975
|
};
|
|
@@ -2888,7 +3013,7 @@ function TooltipArrow({
|
|
|
2888
3013
|
const { side, align, open } = useRenderedTooltip();
|
|
2889
3014
|
const { context, arrowRef } = useFloatingContext();
|
|
2890
3015
|
const { transition, globalId } = useGlobalTooltip();
|
|
2891
|
-
|
|
3016
|
+
React17.useImperativeHandle(ref, () => arrowRef.current);
|
|
2892
3017
|
const deg = { top: 0, right: 90, bottom: 180, left: -90 }[side];
|
|
2893
3018
|
return /* @__PURE__ */ jsx(
|
|
2894
3019
|
MotionTooltipArrow,
|
|
@@ -2911,8 +3036,8 @@ function TooltipPortal(props) {
|
|
|
2911
3036
|
}
|
|
2912
3037
|
function TooltipOverlay() {
|
|
2913
3038
|
const { currentTooltip, transition, globalId, referenceElRef } = useGlobalTooltip();
|
|
2914
|
-
const [rendered, setRendered] =
|
|
2915
|
-
const arrowRef =
|
|
3039
|
+
const [rendered, setRendered] = React17.useState({ data: null, open: false });
|
|
3040
|
+
const arrowRef = React17.useRef(null);
|
|
2916
3041
|
const side = rendered.data?.side ?? "top";
|
|
2917
3042
|
const align = rendered.data?.align ?? "center";
|
|
2918
3043
|
const { refs, x, y, strategy, context, update } = useFloating({
|
|
@@ -2928,14 +3053,14 @@ function TooltipOverlay() {
|
|
|
2928
3053
|
arrow({ element: arrowRef })
|
|
2929
3054
|
]
|
|
2930
3055
|
});
|
|
2931
|
-
|
|
3056
|
+
React17.useEffect(() => {
|
|
2932
3057
|
if (currentTooltip) {
|
|
2933
3058
|
setRendered({ data: currentTooltip, open: true });
|
|
2934
3059
|
} else {
|
|
2935
3060
|
setRendered((p) => p.data ? { ...p, open: false } : p);
|
|
2936
3061
|
}
|
|
2937
3062
|
}, [currentTooltip]);
|
|
2938
|
-
|
|
3063
|
+
React17.useLayoutEffect(() => {
|
|
2939
3064
|
if (referenceElRef.current) {
|
|
2940
3065
|
refs.setReference(referenceElRef.current);
|
|
2941
3066
|
update();
|
|
@@ -3014,9 +3139,9 @@ function Tooltip2({
|
|
|
3014
3139
|
align = "center",
|
|
3015
3140
|
alignOffset = 0
|
|
3016
3141
|
}) {
|
|
3017
|
-
const id =
|
|
3018
|
-
const [props, setProps] =
|
|
3019
|
-
const [asChild, setAsChild] =
|
|
3142
|
+
const id = React17.useId();
|
|
3143
|
+
const [props, setProps] = React17.useState({});
|
|
3144
|
+
const [asChild, setAsChild] = React17.useState(false);
|
|
3020
3145
|
return /* @__PURE__ */ jsx(
|
|
3021
3146
|
LocalTooltipProvider,
|
|
3022
3147
|
{
|
|
@@ -3048,16 +3173,16 @@ function shallowEqualWithoutChildren(a, b) {
|
|
|
3048
3173
|
}
|
|
3049
3174
|
function TooltipContent2({ asChild = false, ...props }) {
|
|
3050
3175
|
const { setProps, setAsChild } = useTooltip();
|
|
3051
|
-
const lastPropsRef =
|
|
3176
|
+
const lastPropsRef = React17.useRef(
|
|
3052
3177
|
void 0
|
|
3053
3178
|
);
|
|
3054
|
-
|
|
3179
|
+
React17.useEffect(() => {
|
|
3055
3180
|
if (!shallowEqualWithoutChildren(lastPropsRef.current, props)) {
|
|
3056
3181
|
lastPropsRef.current = props;
|
|
3057
3182
|
setProps(props);
|
|
3058
3183
|
}
|
|
3059
3184
|
}, [props, setProps]);
|
|
3060
|
-
|
|
3185
|
+
React17.useEffect(() => {
|
|
3061
3186
|
setAsChild(asChild);
|
|
3062
3187
|
}, [asChild, setAsChild]);
|
|
3063
3188
|
return null;
|
|
@@ -3088,10 +3213,10 @@ function TooltipTrigger2({
|
|
|
3088
3213
|
currentTooltip,
|
|
3089
3214
|
setReferenceEl
|
|
3090
3215
|
} = useGlobalTooltip();
|
|
3091
|
-
const triggerRef =
|
|
3092
|
-
|
|
3093
|
-
const suppressNextFocusRef =
|
|
3094
|
-
const handleOpen =
|
|
3216
|
+
const triggerRef = React17.useRef(null);
|
|
3217
|
+
React17.useImperativeHandle(ref, () => triggerRef.current);
|
|
3218
|
+
const suppressNextFocusRef = React17.useRef(false);
|
|
3219
|
+
const handleOpen = React17.useCallback(() => {
|
|
3095
3220
|
if (!triggerRef.current) return;
|
|
3096
3221
|
setReferenceEl(triggerRef.current);
|
|
3097
3222
|
const rect = triggerRef.current.getBoundingClientRect();
|
|
@@ -3116,7 +3241,7 @@ function TooltipTrigger2({
|
|
|
3116
3241
|
alignOffset,
|
|
3117
3242
|
id
|
|
3118
3243
|
]);
|
|
3119
|
-
const handlePointerDown =
|
|
3244
|
+
const handlePointerDown = React17.useCallback(
|
|
3120
3245
|
(e) => {
|
|
3121
3246
|
onPointerDown?.(e);
|
|
3122
3247
|
if (currentTooltip?.id === id) {
|
|
@@ -3129,21 +3254,21 @@ function TooltipTrigger2({
|
|
|
3129
3254
|
},
|
|
3130
3255
|
[onPointerDown, currentTooltip?.id, id, hideImmediate]
|
|
3131
3256
|
);
|
|
3132
|
-
const handleMouseEnter =
|
|
3257
|
+
const handleMouseEnter = React17.useCallback(
|
|
3133
3258
|
(e) => {
|
|
3134
3259
|
onMouseEnter?.(e);
|
|
3135
3260
|
handleOpen();
|
|
3136
3261
|
},
|
|
3137
3262
|
[handleOpen, onMouseEnter]
|
|
3138
3263
|
);
|
|
3139
|
-
const handleMouseLeave =
|
|
3264
|
+
const handleMouseLeave = React17.useCallback(
|
|
3140
3265
|
(e) => {
|
|
3141
3266
|
onMouseLeave?.(e);
|
|
3142
3267
|
hideTooltip();
|
|
3143
3268
|
},
|
|
3144
3269
|
[hideTooltip, onMouseLeave]
|
|
3145
3270
|
);
|
|
3146
|
-
const handleFocus =
|
|
3271
|
+
const handleFocus = React17.useCallback(
|
|
3147
3272
|
(e) => {
|
|
3148
3273
|
onFocus?.(e);
|
|
3149
3274
|
if (suppressNextFocusRef.current) return;
|
|
@@ -3151,7 +3276,7 @@ function TooltipTrigger2({
|
|
|
3151
3276
|
},
|
|
3152
3277
|
[handleOpen, onFocus]
|
|
3153
3278
|
);
|
|
3154
|
-
const handleBlur =
|
|
3279
|
+
const handleBlur = React17.useCallback(
|
|
3155
3280
|
(e) => {
|
|
3156
3281
|
onBlur?.(e);
|
|
3157
3282
|
hideTooltip();
|
|
@@ -3253,7 +3378,7 @@ function AvatarGroup({
|
|
|
3253
3378
|
children: children?.map((child, index) => /* @__PURE__ */ jsx(
|
|
3254
3379
|
AvatarContainer,
|
|
3255
3380
|
{
|
|
3256
|
-
zIndex: invertOverlap ?
|
|
3381
|
+
zIndex: invertOverlap ? React17.Children.count(children) - index : index,
|
|
3257
3382
|
transition,
|
|
3258
3383
|
translate,
|
|
3259
3384
|
side,
|
|
@@ -3304,7 +3429,7 @@ function AvatarGroupTooltip2({
|
|
|
3304
3429
|
),
|
|
3305
3430
|
...props,
|
|
3306
3431
|
children: [
|
|
3307
|
-
/* @__PURE__ */ jsx(
|
|
3432
|
+
/* @__PURE__ */ jsx(motion8.div, { layout, className: "overflow-hidden", children }),
|
|
3308
3433
|
/* @__PURE__ */ jsx(
|
|
3309
3434
|
AvatarGroupTooltipArrow,
|
|
3310
3435
|
{
|
|
@@ -3327,7 +3452,7 @@ function Avatar({
|
|
|
3327
3452
|
"data-slot": "avatar",
|
|
3328
3453
|
"data-size": size,
|
|
3329
3454
|
className: cn(
|
|
3330
|
-
"
|
|
3455
|
+
"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
|
|
3331
3456
|
className
|
|
3332
3457
|
),
|
|
3333
3458
|
...props
|
|
@@ -3340,7 +3465,7 @@ function AvatarImage({ className, ...props }) {
|
|
|
3340
3465
|
{
|
|
3341
3466
|
"data-slot": "avatar-image",
|
|
3342
3467
|
className: cn(
|
|
3343
|
-
"
|
|
3468
|
+
"aspect-square size-full rounded-full object-cover",
|
|
3344
3469
|
className
|
|
3345
3470
|
),
|
|
3346
3471
|
...props
|
|
@@ -3356,7 +3481,7 @@ function AvatarFallback({
|
|
|
3356
3481
|
{
|
|
3357
3482
|
"data-slot": "avatar-fallback",
|
|
3358
3483
|
className: cn(
|
|
3359
|
-
"
|
|
3484
|
+
"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
|
|
3360
3485
|
className
|
|
3361
3486
|
),
|
|
3362
3487
|
...props
|
|
@@ -3383,8 +3508,8 @@ var Collaborators = () => {
|
|
|
3383
3508
|
] }, index)) });
|
|
3384
3509
|
};
|
|
3385
3510
|
var Share = () => {
|
|
3386
|
-
const [access, setAccess] =
|
|
3387
|
-
const [copied, setCopied] =
|
|
3511
|
+
const [access, setAccess] = React17.useState("private");
|
|
3512
|
+
const [copied, setCopied] = React17.useState(false);
|
|
3388
3513
|
const shareUrl = typeof window !== "undefined" ? window.location.href : "";
|
|
3389
3514
|
const shareButton = useMsg("share.button");
|
|
3390
3515
|
const shareTitle = useMsg("share.title");
|
|
@@ -3497,6 +3622,78 @@ var CollaboratorsPopover = () => {
|
|
|
3497
3622
|
] })
|
|
3498
3623
|
] });
|
|
3499
3624
|
};
|
|
3625
|
+
|
|
3626
|
+
// src/features/export/export-json.ts
|
|
3627
|
+
function getFilename(filenameBase) {
|
|
3628
|
+
const safeBase = filenameBase?.trim() || "page";
|
|
3629
|
+
return `${safeBase}.json`;
|
|
3630
|
+
}
|
|
3631
|
+
function exportDataAsJson(data, { filenameBase, document: targetDocument } = {}) {
|
|
3632
|
+
const resolvedDocument = targetDocument ?? (typeof document !== "undefined" ? document : void 0);
|
|
3633
|
+
if (!resolvedDocument) return;
|
|
3634
|
+
const blob = new Blob([JSON.stringify(data, null, 2)], {
|
|
3635
|
+
type: "application/json"
|
|
3636
|
+
});
|
|
3637
|
+
const url = URL.createObjectURL(blob);
|
|
3638
|
+
const link = resolvedDocument.createElement("a");
|
|
3639
|
+
link.href = url;
|
|
3640
|
+
link.download = getFilename(filenameBase);
|
|
3641
|
+
link.click();
|
|
3642
|
+
URL.revokeObjectURL(url);
|
|
3643
|
+
}
|
|
3644
|
+
function DropdownMenu({ ...props }) {
|
|
3645
|
+
return /* @__PURE__ */ jsx(Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
3646
|
+
}
|
|
3647
|
+
function DropdownMenuTrigger({ ...props }) {
|
|
3648
|
+
return /* @__PURE__ */ jsx(Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
3649
|
+
}
|
|
3650
|
+
function DropdownMenuContent({
|
|
3651
|
+
align = "start",
|
|
3652
|
+
alignOffset = 0,
|
|
3653
|
+
side = "bottom",
|
|
3654
|
+
sideOffset = 4,
|
|
3655
|
+
className,
|
|
3656
|
+
...props
|
|
3657
|
+
}) {
|
|
3658
|
+
return /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
|
|
3659
|
+
Menu.Positioner,
|
|
3660
|
+
{
|
|
3661
|
+
className: "isolate z-50 outline-none",
|
|
3662
|
+
align,
|
|
3663
|
+
alignOffset,
|
|
3664
|
+
side,
|
|
3665
|
+
sideOffset,
|
|
3666
|
+
children: /* @__PURE__ */ jsx(
|
|
3667
|
+
Menu.Popup,
|
|
3668
|
+
{
|
|
3669
|
+
"data-slot": "dropdown-menu-content",
|
|
3670
|
+
className: cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className),
|
|
3671
|
+
...props
|
|
3672
|
+
}
|
|
3673
|
+
)
|
|
3674
|
+
}
|
|
3675
|
+
) });
|
|
3676
|
+
}
|
|
3677
|
+
function DropdownMenuItem({
|
|
3678
|
+
className,
|
|
3679
|
+
inset,
|
|
3680
|
+
variant = "default",
|
|
3681
|
+
...props
|
|
3682
|
+
}) {
|
|
3683
|
+
return /* @__PURE__ */ jsx(
|
|
3684
|
+
Menu.Item,
|
|
3685
|
+
{
|
|
3686
|
+
"data-slot": "dropdown-menu-item",
|
|
3687
|
+
"data-inset": inset,
|
|
3688
|
+
"data-variant": variant,
|
|
3689
|
+
className: cn(
|
|
3690
|
+
"group/dropdown-menu-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
|
|
3691
|
+
className
|
|
3692
|
+
),
|
|
3693
|
+
...props
|
|
3694
|
+
}
|
|
3695
|
+
);
|
|
3696
|
+
}
|
|
3500
3697
|
var Header = () => {
|
|
3501
3698
|
const { history, appState } = usePuck();
|
|
3502
3699
|
const publish = useMsg("header.publish");
|
|
@@ -3511,9 +3708,7 @@ var Header = () => {
|
|
|
3511
3708
|
const themeLightLabel = useMsg("header.theme.light");
|
|
3512
3709
|
const themeDarkLabel = useMsg("header.theme.dark");
|
|
3513
3710
|
const themeLabel = theme === "dark" ? themeLightLabel : themeDarkLabel;
|
|
3514
|
-
|
|
3515
|
-
document.documentElement.classList.toggle("dark", theme === "dark");
|
|
3516
|
-
}, []);
|
|
3711
|
+
useThemeSync();
|
|
3517
3712
|
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ 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: [
|
|
3518
3713
|
/* @__PURE__ */ jsx("div", { className: "w-18 flex items-center justify-center h-full border-r border-neutral-200 dark:border-neutral-800/80", children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-10 h-10 bg-primary rounded-full", children: /* @__PURE__ */ jsx(AnimatedAsana, { className: "text-white text-2xl" }) }) }),
|
|
3519
3714
|
/* @__PURE__ */ jsxs("div", { className: "relative flex flex-1 w-full px-2", children: [
|
|
@@ -3521,31 +3716,41 @@ var Header = () => {
|
|
|
3521
3716
|
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none text-sm font-medium", children: appState?.data?.root?.props?.title || "" }),
|
|
3522
3717
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 h-full ml-auto", children: [
|
|
3523
3718
|
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3524
|
-
/* @__PURE__ */ jsx(
|
|
3525
|
-
|
|
3719
|
+
/* @__PURE__ */ jsx(
|
|
3720
|
+
TooltipTrigger,
|
|
3526
3721
|
{
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3722
|
+
render: /* @__PURE__ */ jsx(
|
|
3723
|
+
Button,
|
|
3724
|
+
{
|
|
3725
|
+
variant: "ghost",
|
|
3726
|
+
size: "icon",
|
|
3727
|
+
disabled: !history.hasPast,
|
|
3728
|
+
onClick: () => history.back(),
|
|
3729
|
+
"aria-label": undo
|
|
3730
|
+
}
|
|
3731
|
+
),
|
|
3532
3732
|
children: /* @__PURE__ */ jsx(Undo2, { className: "h-4 w-4" })
|
|
3533
3733
|
}
|
|
3534
|
-
)
|
|
3734
|
+
),
|
|
3535
3735
|
/* @__PURE__ */ jsx(TooltipContent, { children: undoTooltip })
|
|
3536
3736
|
] }),
|
|
3537
3737
|
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3538
|
-
/* @__PURE__ */ jsx(
|
|
3539
|
-
|
|
3738
|
+
/* @__PURE__ */ jsx(
|
|
3739
|
+
TooltipTrigger,
|
|
3540
3740
|
{
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3741
|
+
render: /* @__PURE__ */ jsx(
|
|
3742
|
+
Button,
|
|
3743
|
+
{
|
|
3744
|
+
variant: "ghost",
|
|
3745
|
+
size: "icon",
|
|
3746
|
+
disabled: !history.hasFuture,
|
|
3747
|
+
onClick: () => history.forward(),
|
|
3748
|
+
"aria-label": redo
|
|
3749
|
+
}
|
|
3750
|
+
),
|
|
3546
3751
|
children: /* @__PURE__ */ jsx(Redo2, { className: "h-4 w-4" })
|
|
3547
3752
|
}
|
|
3548
|
-
)
|
|
3753
|
+
),
|
|
3549
3754
|
/* @__PURE__ */ jsx(TooltipContent, { children: redoTooltip })
|
|
3550
3755
|
] }),
|
|
3551
3756
|
/* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
|
|
@@ -3555,21 +3760,34 @@ var Header = () => {
|
|
|
3555
3760
|
/* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
|
|
3556
3761
|
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
3557
3762
|
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3558
|
-
/* @__PURE__ */ jsx(
|
|
3763
|
+
/* @__PURE__ */ jsx(
|
|
3764
|
+
TooltipTrigger,
|
|
3765
|
+
{
|
|
3766
|
+
render: /* @__PURE__ */ jsx(
|
|
3767
|
+
DropdownMenuTrigger,
|
|
3768
|
+
{
|
|
3769
|
+
render: /* @__PURE__ */ jsx(
|
|
3770
|
+
Button,
|
|
3771
|
+
{
|
|
3772
|
+
variant: "ghost",
|
|
3773
|
+
size: "icon",
|
|
3774
|
+
"aria-label": exportLabel
|
|
3775
|
+
}
|
|
3776
|
+
)
|
|
3777
|
+
}
|
|
3778
|
+
),
|
|
3779
|
+
children: /* @__PURE__ */ jsx(Download, { className: "h-4 w-4" })
|
|
3780
|
+
}
|
|
3781
|
+
),
|
|
3559
3782
|
/* @__PURE__ */ jsx(TooltipContent, { children: exportLabel })
|
|
3560
3783
|
] }),
|
|
3561
3784
|
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", children: /* @__PURE__ */ jsxs(
|
|
3562
3785
|
DropdownMenuItem,
|
|
3563
3786
|
{
|
|
3564
3787
|
onClick: () => {
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
const a = document.createElement("a");
|
|
3569
|
-
a.href = url;
|
|
3570
|
-
a.download = `${appState.data.root?.props?.title || "page"}.json`;
|
|
3571
|
-
a.click();
|
|
3572
|
-
URL.revokeObjectURL(url);
|
|
3788
|
+
exportDataAsJson(appState.data, {
|
|
3789
|
+
filenameBase: appState.data.root?.props?.title
|
|
3790
|
+
});
|
|
3573
3791
|
},
|
|
3574
3792
|
children: [
|
|
3575
3793
|
/* @__PURE__ */ jsx(FileDown, { className: "h-4 w-4" }),
|
|
@@ -3581,21 +3799,79 @@ var Header = () => {
|
|
|
3581
3799
|
] }),
|
|
3582
3800
|
/* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
|
|
3583
3801
|
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3584
|
-
/* @__PURE__ */ jsx(
|
|
3802
|
+
/* @__PURE__ */ jsx(
|
|
3803
|
+
TooltipTrigger,
|
|
3804
|
+
{
|
|
3805
|
+
render: /* @__PURE__ */ jsx(
|
|
3806
|
+
Button,
|
|
3807
|
+
{
|
|
3808
|
+
variant: "ghost",
|
|
3809
|
+
size: "icon",
|
|
3810
|
+
onClick: toggleTheme,
|
|
3811
|
+
"aria-label": themeLabel
|
|
3812
|
+
}
|
|
3813
|
+
),
|
|
3814
|
+
children: theme === "dark" ? /* @__PURE__ */ jsx(Sun, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Moon, { className: "h-4 w-4" })
|
|
3815
|
+
}
|
|
3816
|
+
),
|
|
3585
3817
|
/* @__PURE__ */ jsx(TooltipContent, { children: themeLabel })
|
|
3586
3818
|
] }),
|
|
3587
3819
|
/* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "h-5 mx-1" }),
|
|
3588
3820
|
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3589
|
-
/* @__PURE__ */
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3821
|
+
/* @__PURE__ */ jsxs(
|
|
3822
|
+
TooltipTrigger,
|
|
3823
|
+
{
|
|
3824
|
+
render: /* @__PURE__ */ jsx(Button, { size: "sm", "aria-label": publish }),
|
|
3825
|
+
children: [
|
|
3826
|
+
/* @__PURE__ */ jsx(Send, { className: "h-4 w-4" }),
|
|
3827
|
+
publish
|
|
3828
|
+
]
|
|
3829
|
+
}
|
|
3830
|
+
),
|
|
3593
3831
|
/* @__PURE__ */ jsx(TooltipContent, { children: publish })
|
|
3594
3832
|
] })
|
|
3595
3833
|
] })
|
|
3596
3834
|
] })
|
|
3597
3835
|
] }) });
|
|
3598
3836
|
};
|
|
3837
|
+
function useGhostDrag({ createGhostEl }) {
|
|
3838
|
+
const ghostRef = React17.useRef(null);
|
|
3839
|
+
function moveGhost(x, y) {
|
|
3840
|
+
if (!ghostRef.current) return;
|
|
3841
|
+
ghostRef.current.style.left = `${x + 12}px`;
|
|
3842
|
+
ghostRef.current.style.top = `${y + 12}px`;
|
|
3843
|
+
}
|
|
3844
|
+
function removeGhost() {
|
|
3845
|
+
ghostRef.current?.remove();
|
|
3846
|
+
ghostRef.current = null;
|
|
3847
|
+
}
|
|
3848
|
+
const startDrag = React17.useCallback(
|
|
3849
|
+
(e, type, payload) => {
|
|
3850
|
+
e.stopPropagation();
|
|
3851
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
3852
|
+
ghostRef.current = createGhostEl(payload);
|
|
3853
|
+
moveGhost(e.clientX, e.clientY);
|
|
3854
|
+
dispatchLibraryDragStart(type);
|
|
3855
|
+
function onMove(ev) {
|
|
3856
|
+
moveGhost(ev.clientX, ev.clientY);
|
|
3857
|
+
}
|
|
3858
|
+
function onUp(ev) {
|
|
3859
|
+
removeGhost();
|
|
3860
|
+
window.removeEventListener("pointermove", onMove);
|
|
3861
|
+
window.removeEventListener("pointerup", onUp);
|
|
3862
|
+
if (type === "image") {
|
|
3863
|
+
dispatchImageDrop({ src: payload, clientX: ev.clientX, clientY: ev.clientY });
|
|
3864
|
+
} else {
|
|
3865
|
+
dispatchTextDrop({ text: payload, clientX: ev.clientX, clientY: ev.clientY });
|
|
3866
|
+
}
|
|
3867
|
+
}
|
|
3868
|
+
window.addEventListener("pointermove", onMove);
|
|
3869
|
+
window.addEventListener("pointerup", onUp);
|
|
3870
|
+
},
|
|
3871
|
+
[createGhostEl]
|
|
3872
|
+
);
|
|
3873
|
+
return { startDrag };
|
|
3874
|
+
}
|
|
3599
3875
|
var DEFAULT_SEEDS = [
|
|
3600
3876
|
"forest",
|
|
3601
3877
|
"ocean",
|
|
@@ -3627,8 +3903,7 @@ function getSearchImages(query) {
|
|
|
3627
3903
|
id: `${query}-${i}`
|
|
3628
3904
|
}));
|
|
3629
3905
|
}
|
|
3630
|
-
|
|
3631
|
-
function createGhost(src) {
|
|
3906
|
+
function createImageGhost(src) {
|
|
3632
3907
|
const el = document.createElement("div");
|
|
3633
3908
|
el.style.cssText = `
|
|
3634
3909
|
position: fixed; top: -9999px; left: -9999px; z-index: 99999;
|
|
@@ -3642,63 +3917,31 @@ function createGhost(src) {
|
|
|
3642
3917
|
document.body.appendChild(el);
|
|
3643
3918
|
return el;
|
|
3644
3919
|
}
|
|
3645
|
-
function moveGhost(x, y) {
|
|
3646
|
-
if (!ghostEl) return;
|
|
3647
|
-
ghostEl.style.left = `${x + 12}px`;
|
|
3648
|
-
ghostEl.style.top = `${y + 12}px`;
|
|
3649
|
-
}
|
|
3650
|
-
function removeGhost() {
|
|
3651
|
-
ghostEl?.remove();
|
|
3652
|
-
ghostEl = null;
|
|
3653
|
-
}
|
|
3654
3920
|
function ImageLibrary({
|
|
3655
3921
|
seeds,
|
|
3656
3922
|
items: customImages
|
|
3657
3923
|
} = {}) {
|
|
3658
3924
|
const effectiveSeeds = seeds ?? DEFAULT_SEEDS;
|
|
3659
|
-
const [query, setQuery] =
|
|
3660
|
-
const [committed, setCommitted] =
|
|
3661
|
-
const [items, setItems] =
|
|
3925
|
+
const [query, setQuery] = React17.useState("");
|
|
3926
|
+
const [committed, setCommitted] = React17.useState("");
|
|
3927
|
+
const [items, setItems] = React17.useState(
|
|
3662
3928
|
() => customImages ?? getDefaultImages(effectiveSeeds)
|
|
3663
3929
|
);
|
|
3664
3930
|
const libraryTitle = useMsg("image-library.title");
|
|
3665
3931
|
const searchPlaceholder = useMsg("image-library.search.placeholder");
|
|
3666
|
-
|
|
3932
|
+
const { startDrag } = useGhostDrag({
|
|
3933
|
+
createGhostEl: createImageGhost
|
|
3934
|
+
});
|
|
3935
|
+
React17.useEffect(() => {
|
|
3667
3936
|
const t = setTimeout(() => setCommitted(query.trim()), 400);
|
|
3668
3937
|
return () => clearTimeout(t);
|
|
3669
3938
|
}, [query]);
|
|
3670
|
-
|
|
3939
|
+
React17.useEffect(() => {
|
|
3671
3940
|
if (customImages) return;
|
|
3672
3941
|
setItems(
|
|
3673
3942
|
committed ? getSearchImages(committed) : getDefaultImages(effectiveSeeds)
|
|
3674
3943
|
);
|
|
3675
3944
|
}, [committed, customImages, effectiveSeeds]);
|
|
3676
|
-
function handlePointerDown(e, src) {
|
|
3677
|
-
e.stopPropagation();
|
|
3678
|
-
e.currentTarget.setPointerCapture(e.pointerId);
|
|
3679
|
-
ghostEl = createGhost(src);
|
|
3680
|
-
moveGhost(e.clientX, e.clientY);
|
|
3681
|
-
window.dispatchEvent(
|
|
3682
|
-
new CustomEvent("anvilkit:librarydragstart", {
|
|
3683
|
-
detail: { type: "image" }
|
|
3684
|
-
})
|
|
3685
|
-
);
|
|
3686
|
-
function onMove(ev) {
|
|
3687
|
-
moveGhost(ev.clientX, ev.clientY);
|
|
3688
|
-
}
|
|
3689
|
-
function onUp(ev) {
|
|
3690
|
-
removeGhost();
|
|
3691
|
-
window.removeEventListener("pointermove", onMove);
|
|
3692
|
-
window.removeEventListener("pointerup", onUp);
|
|
3693
|
-
window.dispatchEvent(
|
|
3694
|
-
new CustomEvent("anvilkit:imagedrop", {
|
|
3695
|
-
detail: { src, clientX: ev.clientX, clientY: ev.clientY }
|
|
3696
|
-
})
|
|
3697
|
-
);
|
|
3698
|
-
}
|
|
3699
|
-
window.addEventListener("pointermove", onMove);
|
|
3700
|
-
window.addEventListener("pointerup", onUp);
|
|
3701
|
-
}
|
|
3702
3945
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
3703
3946
|
/* @__PURE__ */ jsx("div", { className: "px-3 pt-3 pb-1 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: libraryTitle }),
|
|
3704
3947
|
/* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
@@ -3713,10 +3956,10 @@ function ImageLibrary({
|
|
|
3713
3956
|
}
|
|
3714
3957
|
)
|
|
3715
3958
|
] }) }),
|
|
3716
|
-
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsx("div", { className: "p-2 grid grid-cols-2 gap-2", children: items.map((item
|
|
3959
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsx("div", { className: "p-2 grid grid-cols-2 gap-2", children: items.map((item) => /* @__PURE__ */ jsxs(
|
|
3717
3960
|
"div",
|
|
3718
3961
|
{
|
|
3719
|
-
onPointerDown: (e) =>
|
|
3962
|
+
onPointerDown: (e) => startDrag(e, "image", item.src),
|
|
3720
3963
|
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",
|
|
3721
3964
|
children: [
|
|
3722
3965
|
/* @__PURE__ */ jsx(
|
|
@@ -3731,12 +3974,27 @@ function ImageLibrary({
|
|
|
3731
3974
|
/* @__PURE__ */ jsx("div", { className: "px-1.5 py-1 text-xs text-muted-foreground truncate capitalize", children: item.alt })
|
|
3732
3975
|
]
|
|
3733
3976
|
},
|
|
3734
|
-
|
|
3977
|
+
item.id
|
|
3735
3978
|
)) }) })
|
|
3736
3979
|
] });
|
|
3737
3980
|
}
|
|
3738
|
-
var
|
|
3739
|
-
|
|
3981
|
+
var DEFAULT_SNIPPETS = [
|
|
3982
|
+
{ category: "Headlines", label: "Bold statement", text: "The Future Starts Here" },
|
|
3983
|
+
{ category: "Headlines", label: "Question hook", text: "Ready to Transform Your Business?" },
|
|
3984
|
+
{ category: "Headlines", label: "Value prop", text: "Simple, Powerful, Built for Teams" },
|
|
3985
|
+
{ category: "Headlines", label: "Action-led", text: "Ship Faster. Break Less. Sleep Better." },
|
|
3986
|
+
{ category: "Subheadings", label: "Feature intro", text: "Everything you need, nothing you don't." },
|
|
3987
|
+
{ category: "Subheadings", label: "Social proof", text: "Trusted by over 10,000 teams worldwide." },
|
|
3988
|
+
{ category: "Subheadings", label: "CTA support", text: "Get started in minutes \u2014 no credit card required." },
|
|
3989
|
+
{ category: "Body", label: "Product description", text: "Our platform helps teams collaborate in real time, ship products faster, and stay aligned across every stage of the process." },
|
|
3990
|
+
{ category: "Body", label: "Feature benefit", text: "With built-in analytics and smart automation, you can focus on what matters most \u2014 building great products." },
|
|
3991
|
+
{ category: "Body", label: "About us", text: "We're a small team on a big mission: to make software development feel effortless for everyone." },
|
|
3992
|
+
{ category: "CTAs", label: "Primary", text: "Get Started Free" },
|
|
3993
|
+
{ category: "CTAs", label: "Secondary", text: "Learn More" },
|
|
3994
|
+
{ category: "CTAs", label: "Soft sell", text: "See How It Works" },
|
|
3995
|
+
{ category: "CTAs", label: "Urgency", text: "Start Your Free Trial Today" }
|
|
3996
|
+
];
|
|
3997
|
+
function createTextGhost(text) {
|
|
3740
3998
|
const el = document.createElement("div");
|
|
3741
3999
|
el.style.cssText = `
|
|
3742
4000
|
position: fixed; top: -9999px; left: -9999px; z-index: 99999;
|
|
@@ -3749,112 +4007,16 @@ function createGhost2(text) {
|
|
|
3749
4007
|
document.body.appendChild(el);
|
|
3750
4008
|
return el;
|
|
3751
4009
|
}
|
|
3752
|
-
function
|
|
3753
|
-
if (!ghostEl2) return;
|
|
3754
|
-
ghostEl2.style.left = `${x + 12}px`;
|
|
3755
|
-
ghostEl2.style.top = `${y + 12}px`;
|
|
3756
|
-
}
|
|
3757
|
-
function removeGhost2() {
|
|
3758
|
-
ghostEl2?.remove();
|
|
3759
|
-
ghostEl2 = null;
|
|
3760
|
-
}
|
|
3761
|
-
var DEFAULT_SNIPPETS = [
|
|
3762
|
-
// Headlines
|
|
3763
|
-
{
|
|
3764
|
-
category: "Headlines",
|
|
3765
|
-
label: "Bold statement",
|
|
3766
|
-
text: "The Future Starts Here"
|
|
3767
|
-
},
|
|
3768
|
-
{
|
|
3769
|
-
category: "Headlines",
|
|
3770
|
-
label: "Question hook",
|
|
3771
|
-
text: "Ready to Transform Your Business?"
|
|
3772
|
-
},
|
|
3773
|
-
{
|
|
3774
|
-
category: "Headlines",
|
|
3775
|
-
label: "Value prop",
|
|
3776
|
-
text: "Simple, Powerful, Built for Teams"
|
|
3777
|
-
},
|
|
3778
|
-
{
|
|
3779
|
-
category: "Headlines",
|
|
3780
|
-
label: "Action-led",
|
|
3781
|
-
text: "Ship Faster. Break Less. Sleep Better."
|
|
3782
|
-
},
|
|
3783
|
-
// Subheadings
|
|
3784
|
-
{
|
|
3785
|
-
category: "Subheadings",
|
|
3786
|
-
label: "Feature intro",
|
|
3787
|
-
text: "Everything you need, nothing you don't."
|
|
3788
|
-
},
|
|
3789
|
-
{
|
|
3790
|
-
category: "Subheadings",
|
|
3791
|
-
label: "Social proof",
|
|
3792
|
-
text: "Trusted by over 10,000 teams worldwide."
|
|
3793
|
-
},
|
|
3794
|
-
{
|
|
3795
|
-
category: "Subheadings",
|
|
3796
|
-
label: "CTA support",
|
|
3797
|
-
text: "Get started in minutes \u2014 no credit card required."
|
|
3798
|
-
},
|
|
3799
|
-
// Body
|
|
3800
|
-
{
|
|
3801
|
-
category: "Body",
|
|
3802
|
-
label: "Product description",
|
|
3803
|
-
text: "Our platform helps teams collaborate in real time, ship products faster, and stay aligned across every stage of the process."
|
|
3804
|
-
},
|
|
3805
|
-
{
|
|
3806
|
-
category: "Body",
|
|
3807
|
-
label: "Feature benefit",
|
|
3808
|
-
text: "With built-in analytics and smart automation, you can focus on what matters most \u2014 building great products."
|
|
3809
|
-
},
|
|
3810
|
-
{
|
|
3811
|
-
category: "Body",
|
|
3812
|
-
label: "About us",
|
|
3813
|
-
text: "We're a small team on a big mission: to make software development feel effortless for everyone."
|
|
3814
|
-
},
|
|
3815
|
-
// CTAs
|
|
3816
|
-
{ category: "CTAs", label: "Primary", text: "Get Started Free" },
|
|
3817
|
-
{ category: "CTAs", label: "Secondary", text: "Learn More" },
|
|
3818
|
-
{ category: "CTAs", label: "Soft sell", text: "See How It Works" },
|
|
3819
|
-
{ category: "CTAs", label: "Urgency", text: "Start Your Free Trial Today" }
|
|
3820
|
-
];
|
|
3821
|
-
function CopyLibrary({
|
|
3822
|
-
items
|
|
3823
|
-
} = {}) {
|
|
4010
|
+
function CopyLibrary({ items } = {}) {
|
|
3824
4011
|
const activeSnippets = items ?? DEFAULT_SNIPPETS;
|
|
3825
4012
|
const categories = Array.from(new Set(activeSnippets.map((s) => s.category)));
|
|
3826
|
-
const [query, setQuery] =
|
|
4013
|
+
const [query, setQuery] = React17.useState("");
|
|
3827
4014
|
const libraryTitle = useMsg("copy-library.title");
|
|
3828
4015
|
const searchPlaceholder = useMsg("copy-library.search.placeholder");
|
|
4016
|
+
const { startDrag } = useGhostDrag({ createGhostEl: createTextGhost });
|
|
3829
4017
|
const filtered = query.trim() ? activeSnippets.filter(
|
|
3830
4018
|
(s) => s.text.toLowerCase().includes(query.toLowerCase()) || s.label.toLowerCase().includes(query.toLowerCase()) || s.category.toLowerCase().includes(query.toLowerCase())
|
|
3831
4019
|
) : activeSnippets;
|
|
3832
|
-
function handlePointerDown(e, text) {
|
|
3833
|
-
e.stopPropagation();
|
|
3834
|
-
e.currentTarget.setPointerCapture(e.pointerId);
|
|
3835
|
-
ghostEl2 = createGhost2(text);
|
|
3836
|
-
moveGhost2(e.clientX, e.clientY);
|
|
3837
|
-
window.dispatchEvent(
|
|
3838
|
-
new CustomEvent("anvilkit:librarydragstart", {
|
|
3839
|
-
detail: { type: "text" }
|
|
3840
|
-
})
|
|
3841
|
-
);
|
|
3842
|
-
function onMove(ev) {
|
|
3843
|
-
moveGhost2(ev.clientX, ev.clientY);
|
|
3844
|
-
}
|
|
3845
|
-
function onUp(ev) {
|
|
3846
|
-
removeGhost2();
|
|
3847
|
-
window.removeEventListener("pointermove", onMove);
|
|
3848
|
-
window.removeEventListener("pointerup", onUp);
|
|
3849
|
-
window.dispatchEvent(
|
|
3850
|
-
new CustomEvent("anvilkit:textdrop", {
|
|
3851
|
-
detail: { text, clientX: ev.clientX, clientY: ev.clientY }
|
|
3852
|
-
})
|
|
3853
|
-
);
|
|
3854
|
-
}
|
|
3855
|
-
window.addEventListener("pointermove", onMove);
|
|
3856
|
-
window.addEventListener("pointerup", onUp);
|
|
3857
|
-
}
|
|
3858
4020
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
3859
4021
|
/* @__PURE__ */ jsx("div", { className: "px-3 pt-3 pb-1 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: libraryTitle }),
|
|
3860
4022
|
/* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
@@ -3870,24 +4032,24 @@ function CopyLibrary({
|
|
|
3870
4032
|
)
|
|
3871
4033
|
] }) }),
|
|
3872
4034
|
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsx("div", { className: "p-2 flex flex-col gap-4", children: (query.trim() ? [null] : categories).map((cat) => {
|
|
3873
|
-
const
|
|
3874
|
-
if (!
|
|
4035
|
+
const snippets = cat ? filtered.filter((s) => s.category === cat) : filtered;
|
|
4036
|
+
if (!snippets.length) return null;
|
|
3875
4037
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
3876
4038
|
cat && /* @__PURE__ */ jsxs("div", { className: "px-1 pb-1 text-xs font-semibold text-muted-foreground uppercase tracking-wider flex items-center gap-1", children: [
|
|
3877
4039
|
/* @__PURE__ */ jsx(Type, { className: "h-3 w-3" }),
|
|
3878
4040
|
cat
|
|
3879
4041
|
] }),
|
|
3880
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children:
|
|
4042
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children: snippets.map((snippet) => /* @__PURE__ */ jsxs(
|
|
3881
4043
|
"div",
|
|
3882
4044
|
{
|
|
3883
|
-
onPointerDown: (e) =>
|
|
4045
|
+
onPointerDown: (e) => startDrag(e, "text", snippet.text),
|
|
3884
4046
|
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",
|
|
3885
4047
|
children: [
|
|
3886
4048
|
/* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-foreground/70 mb-0.5", children: snippet.label }),
|
|
3887
4049
|
/* @__PURE__ */ jsx("div", { className: "text-xs text-foreground leading-snug line-clamp-2", children: snippet.text })
|
|
3888
4050
|
]
|
|
3889
4051
|
},
|
|
3890
|
-
|
|
4052
|
+
`${snippet.category}-${snippet.label}`
|
|
3891
4053
|
)) })
|
|
3892
4054
|
] }, cat ?? "results");
|
|
3893
4055
|
}) }) })
|
|
@@ -3915,42 +4077,6 @@ var EditorLayout = ({
|
|
|
3915
4077
|
] })
|
|
3916
4078
|
] });
|
|
3917
4079
|
};
|
|
3918
|
-
function createEditorUiStore(storeId) {
|
|
3919
|
-
return createStore()(
|
|
3920
|
-
persist(
|
|
3921
|
-
(set) => ({
|
|
3922
|
-
drawerSearch: "",
|
|
3923
|
-
setDrawerSearch: (q) => set({ drawerSearch: q }),
|
|
3924
|
-
drawerCollapsed: {},
|
|
3925
|
-
toggleDrawerGroup: (group) => set((s) => ({
|
|
3926
|
-
drawerCollapsed: { ...s.drawerCollapsed, [group]: !s.drawerCollapsed[group] }
|
|
3927
|
-
})),
|
|
3928
|
-
activeTab: "insert",
|
|
3929
|
-
setActiveTab: (tab) => set({ activeTab: tab }),
|
|
3930
|
-
outlineExpanded: {},
|
|
3931
|
-
toggleOutlineItem: (id) => set((s) => ({
|
|
3932
|
-
outlineExpanded: { ...s.outlineExpanded, [id]: !s.outlineExpanded[id] }
|
|
3933
|
-
})),
|
|
3934
|
-
theme: "light",
|
|
3935
|
-
toggleTheme: () => set((s) => {
|
|
3936
|
-
const next = s.theme === "light" ? "dark" : "light";
|
|
3937
|
-
document.documentElement.classList.toggle("dark", next === "dark");
|
|
3938
|
-
return { theme: next };
|
|
3939
|
-
})
|
|
3940
|
-
}),
|
|
3941
|
-
{
|
|
3942
|
-
name: `anvilkit-ui-${storeId}`,
|
|
3943
|
-
partialize: (s) => ({
|
|
3944
|
-
activeTab: s.activeTab,
|
|
3945
|
-
drawerCollapsed: s.drawerCollapsed,
|
|
3946
|
-
outlineExpanded: s.outlineExpanded,
|
|
3947
|
-
theme: s.theme
|
|
3948
|
-
// drawerSearch intentionally excluded — transient input
|
|
3949
|
-
})
|
|
3950
|
-
}
|
|
3951
|
-
)
|
|
3952
|
-
);
|
|
3953
|
-
}
|
|
3954
4080
|
function createEditorI18nStore(initial) {
|
|
3955
4081
|
return createStore()(
|
|
3956
4082
|
persist(
|
|
@@ -4024,20 +4150,33 @@ function Studio({
|
|
|
4024
4150
|
locale,
|
|
4025
4151
|
messages
|
|
4026
4152
|
}) {
|
|
4027
|
-
const uiStore2 =
|
|
4028
|
-
const i18nStore =
|
|
4153
|
+
const uiStore2 = React17.useRef(createEditorUiStore(storeId ?? "default")).current;
|
|
4154
|
+
const i18nStore = React17.useRef(
|
|
4029
4155
|
createEditorI18nStore({
|
|
4030
4156
|
locale: locale ?? "zh",
|
|
4031
4157
|
messages: messages ?? defaultMessages
|
|
4032
4158
|
})
|
|
4033
4159
|
).current;
|
|
4034
|
-
|
|
4035
|
-
()
|
|
4036
|
-
|
|
4037
|
-
);
|
|
4038
|
-
|
|
4039
|
-
()
|
|
4040
|
-
|
|
4160
|
+
React17.useEffect(() => {
|
|
4161
|
+
i18nStore.getState().setLocale(locale ?? "zh", messages ?? defaultMessages);
|
|
4162
|
+
}, [locale, messages, i18nStore]);
|
|
4163
|
+
const [aiPlugin, setAiPlugin] = React17.useState(null);
|
|
4164
|
+
React17.useEffect(() => {
|
|
4165
|
+
if (!aiHost) return;
|
|
4166
|
+
let cancelled = false;
|
|
4167
|
+
import('@puckeditor/plugin-ai').then(({ createAiPlugin }) => {
|
|
4168
|
+
if (cancelled) return;
|
|
4169
|
+
import('@puckeditor/plugin-ai/styles.css').catch(() => {
|
|
4170
|
+
});
|
|
4171
|
+
setAiPlugin(createAiPlugin({ host: aiHost }));
|
|
4172
|
+
});
|
|
4173
|
+
return () => {
|
|
4174
|
+
cancelled = true;
|
|
4175
|
+
};
|
|
4176
|
+
}, [aiHost]);
|
|
4177
|
+
const mergedOverrides = React17.useMemo(
|
|
4178
|
+
() => ({ ...aiPlugin?.overrides ?? {}, ...puckOverrides, ...overrideExtensions }),
|
|
4179
|
+
[aiPlugin, overrideExtensions]
|
|
4041
4180
|
);
|
|
4042
4181
|
return /* @__PURE__ */ jsx(EditorUiStoreProvider, { value: uiStore2, children: /* @__PURE__ */ jsx(EditorI18nStoreProvider, { value: i18nStore, children: /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(
|
|
4043
4182
|
Puck,
|
|
@@ -4047,11 +4186,11 @@ function Studio({
|
|
|
4047
4186
|
onPublish,
|
|
4048
4187
|
onChange,
|
|
4049
4188
|
overrides: mergedOverrides,
|
|
4050
|
-
plugins: [aiPlugin],
|
|
4189
|
+
plugins: aiPlugin ? [aiPlugin] : [],
|
|
4051
4190
|
children: /* @__PURE__ */ jsx(
|
|
4052
4191
|
EditorLayout,
|
|
4053
4192
|
{
|
|
4054
|
-
aiPanel: aiPlugin
|
|
4193
|
+
aiPanel: aiPlugin?.render(),
|
|
4055
4194
|
images,
|
|
4056
4195
|
copywritings
|
|
4057
4196
|
}
|
|
@@ -4061,6 +4200,6 @@ function Studio({
|
|
|
4061
4200
|
}
|
|
4062
4201
|
|
|
4063
4202
|
// src/store/index.ts
|
|
4064
|
-
|
|
4203
|
+
createEditorUiStore("default");
|
|
4065
4204
|
|
|
4066
|
-
export { Studio, createEditorI18nStore, createEditorUiStore, puckOverrides,
|
|
4205
|
+
export { EditorI18nStoreProvider, EditorUiStoreProvider, Studio, createEditorI18nStore, createEditorUiStore, defaultMessages, puckOverrides, useEditorI18nStoreApi, useEditorUiStoreApi };
|