@drawnagency/primitives 0.1.59 → 0.1.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/capabilities.d.ts +16 -0
- package/dist/auth/capabilities.d.ts.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +3 -1
- package/dist/auth/types.d.ts +26 -22
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/chunk-4OX3Z7SB.js +1421 -0
- package/dist/{chunk-RFZNNCAS.js → chunk-53DKVAB6.js} +1 -61
- package/dist/chunk-677NTHAZ.js +27 -0
- package/dist/chunk-7EOSDFS3.js +10 -0
- package/dist/{chunk-NTGSA3TI.js → chunk-AM5LZD6Q.js} +7 -30
- package/dist/{chunk-ICLXLWQ5.js → chunk-BT7STGDW.js} +31 -23
- package/dist/{chunk-L2JJFOXD.js → chunk-CBWK3KPV.js} +5 -1
- package/dist/{chunk-V7JN2DDU.js → chunk-ODCJQOVO.js} +1 -1
- package/dist/chunk-TZQPOR5A.js +24 -0
- package/dist/{chunk-XTK4BR27.js → chunk-UNWNT52N.js} +13 -0
- package/dist/chunk-UQ4OYRW7.js +670 -0
- package/dist/chunk-WDSVHKAH.js +54 -0
- package/dist/chunk-WLMJCNU7.js +70 -0
- package/dist/chunk-ZGFAYZWB.js +8 -0
- package/dist/components/editor/DropEdgeIndicator.d.ts +8 -0
- package/dist/components/editor/DropEdgeIndicator.d.ts.map +1 -0
- package/dist/components/editor/PagesModal.d.ts.map +1 -1
- package/dist/components/editor/SectionOrderingModal.d.ts.map +1 -1
- package/dist/components/editor/index.js +640 -0
- package/dist/components/primitives/defineHeadingSection.d.ts +28 -0
- package/dist/components/primitives/defineHeadingSection.d.ts.map +1 -0
- package/dist/components/primitives/index.d.ts +10 -0
- package/dist/components/primitives/index.d.ts.map +1 -0
- package/dist/components/primitives/index.js +166 -0
- package/dist/components/sections/Colors/index.d.ts.map +1 -1
- package/dist/components/sections/Container/index.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconList.d.ts +1 -6
- package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
- package/dist/components/sections/IconList/index.d.ts +11 -0
- package/dist/components/sections/IconList/index.d.ts.map +1 -1
- package/dist/components/sections/LinkHeading/index.d.ts.map +1 -1
- package/dist/components/sections/SubHeading/index.d.ts +0 -1
- package/dist/components/sections/SubHeading/index.d.ts.map +1 -1
- package/dist/components/sections/SubSubHeading/index.d.ts +0 -1
- package/dist/components/sections/SubSubHeading/index.d.ts.map +1 -1
- package/dist/components/sections/all-sections.d.ts +0 -2
- package/dist/components/sections/all-sections.d.ts.map +1 -1
- package/dist/components/sections/register-schemas.js +376 -2453
- package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
- package/dist/hooks/useEditorPublish.d.ts.map +1 -1
- package/dist/hooks/useMediaPipeline.d.ts.map +1 -1
- package/dist/hooks/useSortableRow.d.ts +25 -0
- package/dist/hooks/useSortableRow.d.ts.map +1 -0
- package/dist/index.js +46 -37
- package/dist/lib/image-refs.d.ts +21 -0
- package/dist/lib/image-refs.d.ts.map +1 -0
- package/dist/lib/index.js +21 -14
- package/dist/lib/platform-broker.d.ts +14 -0
- package/dist/lib/platform-broker.d.ts.map +1 -0
- package/dist/lib/platform-broker.js +60 -0
- package/dist/lib/reorder.d.ts +12 -0
- package/dist/lib/reorder.d.ts.map +1 -0
- package/dist/lib/text.d.ts +2 -0
- package/dist/lib/text.d.ts.map +1 -1
- package/dist/media/index.js +3 -2
- package/dist/media/utils.d.ts.map +1 -1
- package/dist/schemas/index.js +17 -17
- package/dist/schemas/link.js +13 -0
- package/dist/types/database.d.ts +46 -0
- package/dist/types/database.d.ts.map +1 -1
- package/package.json +14 -2
- package/src/auth/capabilities.ts +26 -0
- package/src/auth/index.ts +3 -0
- package/src/auth/types.ts +36 -26
- package/src/components/editor/DropEdgeIndicator.tsx +13 -0
- package/src/components/editor/PagesModal.tsx +12 -80
- package/src/components/editor/SectionOrderingModal.tsx +8 -78
- package/src/components/primitives/defineHeadingSection.tsx +56 -0
- package/src/components/primitives/index.ts +11 -0
- package/src/components/sections/Colors/index.tsx +2 -4
- package/src/components/sections/Container/index.tsx +2 -4
- package/src/components/sections/IconList/IconList.tsx +1 -7
- package/src/components/sections/IconList/index.tsx +11 -5
- package/src/components/sections/LinkHeading/index.tsx +5 -20
- package/src/components/sections/SubHeading/index.tsx +6 -23
- package/src/components/sections/SubSubHeading/index.tsx +6 -23
- package/src/components/shell/BugReportFAB.tsx +13 -9
- package/src/hooks/useEditorPublish.ts +71 -49
- package/src/hooks/useMediaPipeline.ts +11 -34
- package/src/hooks/useSortableRow.ts +99 -0
- package/src/lib/image-refs.ts +53 -0
- package/src/lib/platform-broker.ts +72 -0
- package/src/lib/reorder.ts +20 -0
- package/src/lib/text.ts +5 -0
- package/src/media/utils.ts +6 -1
- package/src/types/database.ts +41 -0
- package/dist/chunk-DKOUFIP6.js +0 -35
- /package/dist/{chunk-ZU2MKPTG.js → chunk-3DCG4DNU.js} +0 -0
|
@@ -1,979 +1,118 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
Checkbox,
|
|
3
|
+
DeleteButton,
|
|
4
|
+
DragHandle as DragHandle2,
|
|
5
|
+
FormLabel,
|
|
6
|
+
Input,
|
|
7
|
+
Popover,
|
|
8
|
+
PopoverItem,
|
|
9
|
+
SettingsButton,
|
|
10
|
+
SettingsForm,
|
|
11
|
+
buildBlockDragData,
|
|
12
|
+
buildBlockDropData,
|
|
13
|
+
canDropBlock,
|
|
14
|
+
isBlockDragData
|
|
15
|
+
} from "../../chunk-UQ4OYRW7.js";
|
|
16
|
+
import {
|
|
17
|
+
EditableGrid,
|
|
18
|
+
EditablePlainText,
|
|
19
|
+
EditableRichText,
|
|
20
|
+
MAX_CONTAINER_COLUMNS,
|
|
21
|
+
MediaBlock,
|
|
22
|
+
colSpanClass,
|
|
23
|
+
containerGridClass,
|
|
24
|
+
defineHeadingSection,
|
|
25
|
+
spacerHiddenClass,
|
|
26
|
+
useEditableCollection
|
|
27
|
+
} from "../../chunk-4OX3Z7SB.js";
|
|
28
|
+
import {
|
|
29
|
+
AddIcon,
|
|
30
|
+
DeleteIcon,
|
|
31
|
+
DragHandle,
|
|
32
|
+
IconButton
|
|
33
|
+
} from "../../chunk-WLMJCNU7.js";
|
|
34
|
+
import "../../chunk-CBWK3KPV.js";
|
|
4
35
|
import {
|
|
5
36
|
DEFAULT_LINK,
|
|
6
37
|
LinkValueSchema
|
|
7
|
-
} from "../../chunk-
|
|
38
|
+
} from "../../chunk-3DCG4DNU.js";
|
|
8
39
|
import {
|
|
9
|
-
cn,
|
|
10
40
|
curatedIcons,
|
|
11
|
-
getIcon
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
41
|
+
getIcon
|
|
42
|
+
} from "../../chunk-WDSVHKAH.js";
|
|
43
|
+
import {
|
|
44
|
+
sanitizeHtml
|
|
45
|
+
} from "../../chunk-53DKVAB6.js";
|
|
46
|
+
import {
|
|
47
|
+
cn
|
|
48
|
+
} from "../../chunk-7EOSDFS3.js";
|
|
49
|
+
import "../../chunk-ZGFAYZWB.js";
|
|
15
50
|
import {
|
|
16
|
-
ColorItemSchema,
|
|
17
|
-
SingleMediaReferenceSchema,
|
|
18
51
|
getSectionSchema
|
|
19
|
-
} from "../../chunk-
|
|
20
|
-
import "../../chunk-DKOUFIP6.js";
|
|
21
|
-
import "../../chunk-NSCT3AMV.js";
|
|
52
|
+
} from "../../chunk-TZQPOR5A.js";
|
|
22
53
|
import {
|
|
23
54
|
defineSection,
|
|
24
55
|
getSection,
|
|
25
56
|
registerRichText,
|
|
26
57
|
registerSchema
|
|
27
58
|
} from "../../chunk-VKAGMEKE.js";
|
|
59
|
+
import {
|
|
60
|
+
ColorItemSchema,
|
|
61
|
+
SingleMediaReferenceSchema
|
|
62
|
+
} from "../../chunk-BT7STGDW.js";
|
|
63
|
+
import "../../chunk-NSCT3AMV.js";
|
|
28
64
|
import "../../chunk-JSBRDJBE.js";
|
|
29
65
|
|
|
30
66
|
// src/components/sections/LinkHeading/index.tsx
|
|
31
|
-
import { z } from "zod";
|
|
32
67
|
import { Heading1 } from "lucide-react";
|
|
33
|
-
|
|
34
|
-
// src/components/primitives/EditablePlainText.tsx
|
|
35
|
-
import {
|
|
36
|
-
useRef as useRef2,
|
|
37
|
-
useEffect as useEffect2,
|
|
38
|
-
useCallback as useCallback2,
|
|
39
|
-
createElement
|
|
40
|
-
} from "react";
|
|
41
|
-
|
|
42
|
-
// src/components/primitives/useEditablePlainText.ts
|
|
43
|
-
import { useState, useEffect, useRef, useCallback } from "react";
|
|
44
|
-
function useEditablePlainText({
|
|
45
|
-
value: propValue,
|
|
46
|
-
onChange,
|
|
47
|
-
multiline = false
|
|
48
|
-
}) {
|
|
49
|
-
const [value, setValue] = useState(propValue);
|
|
50
|
-
const lastPropValue = useRef(propValue);
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
if (propValue !== lastPropValue.current) {
|
|
53
|
-
setValue(propValue);
|
|
54
|
-
lastPropValue.current = propValue;
|
|
55
|
-
}
|
|
56
|
-
}, [propValue]);
|
|
57
|
-
const handleInput = useCallback((text) => {
|
|
58
|
-
setValue(text);
|
|
59
|
-
}, []);
|
|
60
|
-
const handleBlur = useCallback(() => {
|
|
61
|
-
if (value !== propValue) {
|
|
62
|
-
onChange(value);
|
|
63
|
-
lastPropValue.current = value;
|
|
64
|
-
}
|
|
65
|
-
}, [value, propValue, onChange]);
|
|
66
|
-
return {
|
|
67
|
-
value,
|
|
68
|
-
handleInput,
|
|
69
|
-
handleBlur,
|
|
70
|
-
shouldPreventEnter: !multiline
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// src/components/primitives/EditablePlainText.tsx
|
|
75
|
-
function EditablePlainText({
|
|
76
|
-
tag,
|
|
77
|
-
value,
|
|
78
|
-
onChange,
|
|
79
|
-
isEditMode,
|
|
80
|
-
multiline = false,
|
|
81
|
-
placeholder,
|
|
82
|
-
className,
|
|
83
|
-
...htmlAttrs
|
|
84
|
-
}) {
|
|
85
|
-
const ref = useRef2(null);
|
|
86
|
-
const {
|
|
87
|
-
value: localValue,
|
|
88
|
-
handleInput,
|
|
89
|
-
handleBlur,
|
|
90
|
-
shouldPreventEnter
|
|
91
|
-
} = useEditablePlainText({ value, onChange, multiline });
|
|
92
|
-
useEffect2(() => {
|
|
93
|
-
if (ref.current && ref.current.textContent !== localValue) {
|
|
94
|
-
ref.current.textContent = localValue;
|
|
95
|
-
}
|
|
96
|
-
}, [localValue]);
|
|
97
|
-
const onInput = useCallback2(() => {
|
|
98
|
-
if (ref.current) {
|
|
99
|
-
handleInput(ref.current.textContent || "");
|
|
100
|
-
}
|
|
101
|
-
}, [handleInput]);
|
|
102
|
-
const onKeyDown = useCallback2(
|
|
103
|
-
(e) => {
|
|
104
|
-
if (e.key === "Enter" && shouldPreventEnter) {
|
|
105
|
-
e.preventDefault();
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
[shouldPreventEnter]
|
|
109
|
-
);
|
|
110
|
-
const onPaste = useCallback2(
|
|
111
|
-
(e) => {
|
|
112
|
-
e.preventDefault();
|
|
113
|
-
const text = e.clipboardData.getData("text/plain");
|
|
114
|
-
const selection = window.getSelection();
|
|
115
|
-
if (selection && selection.rangeCount > 0) {
|
|
116
|
-
const range = selection.getRangeAt(0);
|
|
117
|
-
range.deleteContents();
|
|
118
|
-
range.insertNode(document.createTextNode(text));
|
|
119
|
-
range.collapse(false);
|
|
120
|
-
selection.removeAllRanges();
|
|
121
|
-
selection.addRange(range);
|
|
122
|
-
}
|
|
123
|
-
if (ref.current) {
|
|
124
|
-
handleInput(ref.current.textContent || "");
|
|
125
|
-
}
|
|
126
|
-
},
|
|
127
|
-
[handleInput]
|
|
128
|
-
);
|
|
129
|
-
return createElement(
|
|
130
|
-
tag,
|
|
131
|
-
{
|
|
132
|
-
ref,
|
|
133
|
-
className: isEditMode && placeholder ? `editable-placeholder ${className ?? ""}` : className,
|
|
134
|
-
contentEditable: isEditMode ? "true" : void 0,
|
|
135
|
-
suppressContentEditableWarning: isEditMode || void 0,
|
|
136
|
-
onInput: isEditMode ? onInput : void 0,
|
|
137
|
-
onBlur: isEditMode ? handleBlur : void 0,
|
|
138
|
-
onKeyDown: isEditMode ? onKeyDown : void 0,
|
|
139
|
-
onPaste: isEditMode ? onPaste : void 0,
|
|
140
|
-
"data-placeholder": isEditMode && placeholder ? placeholder : void 0,
|
|
141
|
-
...htmlAttrs
|
|
142
|
-
},
|
|
143
|
-
value
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// src/components/primitives/HeadingSection.tsx
|
|
148
68
|
import { jsx } from "react/jsx-runtime";
|
|
149
|
-
|
|
150
|
-
return /* @__PURE__ */ jsx(
|
|
151
|
-
EditablePlainText,
|
|
152
|
-
{
|
|
153
|
-
tag,
|
|
154
|
-
value: heading,
|
|
155
|
-
onChange: onChange ?? (() => {
|
|
156
|
-
}),
|
|
157
|
-
isEditMode: !!onChange,
|
|
158
|
-
placeholder,
|
|
159
|
-
id: toSectionId(heading),
|
|
160
|
-
className: cn("scroll-mt-20", className)
|
|
161
|
-
}
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// src/components/sections/LinkHeading/index.tsx
|
|
166
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
167
|
-
var schema = z.object({
|
|
168
|
-
type: z.literal("link_heading"),
|
|
169
|
-
content: z.object({ heading: z.string() })
|
|
170
|
-
});
|
|
171
|
-
var LinkHeading_default = defineSection({
|
|
69
|
+
var LinkHeading_default = defineHeadingSection({
|
|
172
70
|
type: "link_heading",
|
|
173
71
|
label: "Link Heading",
|
|
174
|
-
icon: /* @__PURE__ */
|
|
175
|
-
schema,
|
|
72
|
+
icon: /* @__PURE__ */ jsx(Heading1, { size: 18 }),
|
|
176
73
|
navRole: "h1",
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
heading: content.content.heading,
|
|
181
|
-
tag: "h2",
|
|
182
|
-
placeholder: "Section heading",
|
|
183
|
-
onChange: onChange ? (heading) => onChange({ type: "link_heading", content: { heading } }) : void 0
|
|
184
|
-
}
|
|
185
|
-
),
|
|
186
|
-
defaults: () => ({ type: "link_heading", content: { heading: "New Section" } }),
|
|
187
|
-
getLabel: (content) => content.content.heading
|
|
74
|
+
tag: "h2",
|
|
75
|
+
placeholder: "Section heading",
|
|
76
|
+
defaultHeading: "New Section"
|
|
188
77
|
});
|
|
189
78
|
|
|
190
79
|
// src/components/sections/SubHeading/index.tsx
|
|
191
|
-
import { z as z2 } from "zod";
|
|
192
80
|
import { Heading2 } from "lucide-react";
|
|
193
|
-
import { jsx as
|
|
194
|
-
var
|
|
195
|
-
type: z2.literal("sub_heading"),
|
|
196
|
-
content: z2.object({ heading: z2.string(), excludeFromNav: z2.boolean().optional() })
|
|
197
|
-
});
|
|
198
|
-
var SubHeading_default = defineSection({
|
|
81
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
82
|
+
var SubHeading_default = defineHeadingSection({
|
|
199
83
|
type: "sub_heading",
|
|
200
84
|
label: "Sub Heading",
|
|
201
|
-
icon: /* @__PURE__ */
|
|
202
|
-
schema: schema2,
|
|
85
|
+
icon: /* @__PURE__ */ jsx2(Heading2, { size: 18 }),
|
|
203
86
|
navRole: "h2",
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
tag: "h3",
|
|
209
|
-
placeholder: "Sub heading",
|
|
210
|
-
onChange: onChange ? (heading) => onChange({ ...content, content: { ...content.content, heading } }) : void 0
|
|
211
|
-
}
|
|
212
|
-
),
|
|
213
|
-
defaults: () => ({ type: "sub_heading", content: { heading: "New Sub Heading" } }),
|
|
214
|
-
getLabel: (content) => content.content.heading,
|
|
215
|
-
settings: {
|
|
216
|
-
excludeFromNav: { type: "checkbox", label: "Exclude from navigation", default: false, target: "content" }
|
|
217
|
-
}
|
|
87
|
+
tag: "h3",
|
|
88
|
+
placeholder: "Sub heading",
|
|
89
|
+
defaultHeading: "New Sub Heading",
|
|
90
|
+
navExclusion: true
|
|
218
91
|
});
|
|
219
92
|
|
|
220
93
|
// src/components/sections/SubSubHeading/index.tsx
|
|
221
|
-
import { z as z3 } from "zod";
|
|
222
94
|
import { Heading3 } from "lucide-react";
|
|
223
|
-
import { jsx as
|
|
224
|
-
var
|
|
225
|
-
type: z3.literal("sub_sub_heading"),
|
|
226
|
-
content: z3.object({ heading: z3.string(), excludeFromNav: z3.boolean().optional() })
|
|
227
|
-
});
|
|
228
|
-
var SubSubHeading_default = defineSection({
|
|
95
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
96
|
+
var SubSubHeading_default = defineHeadingSection({
|
|
229
97
|
type: "sub_sub_heading",
|
|
230
98
|
label: "Sub Sub Heading",
|
|
231
|
-
icon: /* @__PURE__ */
|
|
232
|
-
schema: schema3,
|
|
99
|
+
icon: /* @__PURE__ */ jsx3(Heading3, { size: 18 }),
|
|
233
100
|
navRole: "h3",
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
defaults: () => ({ type: "sub_sub_heading", content: { heading: "New Sub Sub Heading" } }),
|
|
244
|
-
getLabel: (content) => content.content.heading,
|
|
245
|
-
settings: {
|
|
246
|
-
excludeFromNav: { type: "checkbox", label: "Exclude from navigation", default: false, target: "content" }
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
// src/components/sections/Prose/index.tsx
|
|
251
|
-
import { z as z4 } from "zod";
|
|
252
|
-
import { AlignLeft } from "lucide-react";
|
|
253
|
-
|
|
254
|
-
// src/components/primitives/EditableRichText.tsx
|
|
255
|
-
import { useRef as useRef4, useCallback as useCallback4, useEffect as useEffect4 } from "react";
|
|
256
|
-
import { EditorContent } from "@tiptap/react";
|
|
257
|
-
import { BubbleMenu } from "@tiptap/react/menus";
|
|
258
|
-
|
|
259
|
-
// src/components/primitives/useEditableRichText.ts
|
|
260
|
-
import { useState as useState2, useRef as useRef3, useCallback as useCallback3, useEffect as useEffect3 } from "react";
|
|
261
|
-
import { Editor } from "@tiptap/core";
|
|
262
|
-
import Placeholder from "@tiptap/extension-placeholder";
|
|
263
|
-
|
|
264
|
-
// src/components/primitives/tiptap-presets.ts
|
|
265
|
-
import StarterKit from "@tiptap/starter-kit";
|
|
266
|
-
import Underline from "@tiptap/extension-underline";
|
|
267
|
-
import Link from "@tiptap/extension-link";
|
|
268
|
-
|
|
269
|
-
// ../../node_modules/.pnpm/@tiptap+extension-paragraph@3.22.4_@tiptap+core@3.22.4_@tiptap+pm@3.22.4_/node_modules/@tiptap/extension-paragraph/dist/index.js
|
|
270
|
-
import { mergeAttributes, Node } from "@tiptap/core";
|
|
271
|
-
var EMPTY_PARAGRAPH_MARKDOWN = " ";
|
|
272
|
-
var NBSP_CHAR = "\xA0";
|
|
273
|
-
var Paragraph = Node.create({
|
|
274
|
-
name: "paragraph",
|
|
275
|
-
priority: 1e3,
|
|
276
|
-
addOptions() {
|
|
277
|
-
return {
|
|
278
|
-
HTMLAttributes: {}
|
|
279
|
-
};
|
|
280
|
-
},
|
|
281
|
-
group: "block",
|
|
282
|
-
content: "inline*",
|
|
283
|
-
parseHTML() {
|
|
284
|
-
return [{ tag: "p" }];
|
|
285
|
-
},
|
|
286
|
-
renderHTML({ HTMLAttributes }) {
|
|
287
|
-
return ["p", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
|
|
288
|
-
},
|
|
289
|
-
parseMarkdown: (token, helpers) => {
|
|
290
|
-
const tokens = token.tokens || [];
|
|
291
|
-
if (tokens.length === 1 && tokens[0].type === "image") {
|
|
292
|
-
return helpers.parseChildren([tokens[0]]);
|
|
293
|
-
}
|
|
294
|
-
const content = helpers.parseInline(tokens);
|
|
295
|
-
const hasExplicitEmptyParagraphMarker = tokens.length === 1 && tokens[0].type === "text" && (tokens[0].raw === EMPTY_PARAGRAPH_MARKDOWN || tokens[0].text === EMPTY_PARAGRAPH_MARKDOWN || tokens[0].raw === NBSP_CHAR || tokens[0].text === NBSP_CHAR);
|
|
296
|
-
if (hasExplicitEmptyParagraphMarker && content.length === 1 && content[0].type === "text" && (content[0].text === EMPTY_PARAGRAPH_MARKDOWN || content[0].text === NBSP_CHAR)) {
|
|
297
|
-
return helpers.createNode("paragraph", void 0, []);
|
|
298
|
-
}
|
|
299
|
-
return helpers.createNode("paragraph", void 0, content);
|
|
300
|
-
},
|
|
301
|
-
renderMarkdown: (node, h, ctx) => {
|
|
302
|
-
var _a, _b;
|
|
303
|
-
if (!node) {
|
|
304
|
-
return "";
|
|
305
|
-
}
|
|
306
|
-
const content = Array.isArray(node.content) ? node.content : [];
|
|
307
|
-
if (content.length === 0) {
|
|
308
|
-
const previousContent = Array.isArray((_a = ctx == null ? void 0 : ctx.previousNode) == null ? void 0 : _a.content) ? ctx.previousNode.content : [];
|
|
309
|
-
const previousNodeIsEmptyParagraph = ((_b = ctx == null ? void 0 : ctx.previousNode) == null ? void 0 : _b.type) === "paragraph" && previousContent.length === 0;
|
|
310
|
-
return previousNodeIsEmptyParagraph ? EMPTY_PARAGRAPH_MARKDOWN : "";
|
|
311
|
-
}
|
|
312
|
-
return h.renderChildren(content);
|
|
313
|
-
},
|
|
314
|
-
addCommands() {
|
|
315
|
-
return {
|
|
316
|
-
setParagraph: () => ({ commands }) => {
|
|
317
|
-
return commands.setNode(this.name);
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
},
|
|
321
|
-
addKeyboardShortcuts() {
|
|
322
|
-
return {
|
|
323
|
-
"Mod-Alt-0": () => this.editor.commands.setParagraph()
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
var index_default = Paragraph;
|
|
328
|
-
|
|
329
|
-
// src/components/primitives/CustomParagraph.ts
|
|
330
|
-
var ALLOWED_CLASSES = ["large", "lead-in"];
|
|
331
|
-
var CustomParagraph = index_default.extend({
|
|
332
|
-
addAttributes() {
|
|
333
|
-
return {
|
|
334
|
-
...this.parent?.(),
|
|
335
|
-
class: {
|
|
336
|
-
default: null,
|
|
337
|
-
parseHTML: (element) => {
|
|
338
|
-
const cls = element.getAttribute("class");
|
|
339
|
-
if (cls && ALLOWED_CLASSES.includes(cls)) {
|
|
340
|
-
return cls;
|
|
341
|
-
}
|
|
342
|
-
return null;
|
|
343
|
-
},
|
|
344
|
-
renderHTML: (attributes) => {
|
|
345
|
-
if (!attributes.class) return {};
|
|
346
|
-
return { class: attributes.class };
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
// src/components/primitives/tiptap-presets.ts
|
|
354
|
-
var basic = [
|
|
355
|
-
StarterKit.configure({
|
|
356
|
-
paragraph: false,
|
|
357
|
-
heading: false,
|
|
358
|
-
blockquote: false,
|
|
359
|
-
bulletList: false,
|
|
360
|
-
orderedList: false,
|
|
361
|
-
listItem: false,
|
|
362
|
-
codeBlock: false,
|
|
363
|
-
horizontalRule: false,
|
|
364
|
-
code: false,
|
|
365
|
-
strike: false
|
|
366
|
-
}),
|
|
367
|
-
CustomParagraph,
|
|
368
|
-
Underline
|
|
369
|
-
];
|
|
370
|
-
var rich = [
|
|
371
|
-
StarterKit.configure({
|
|
372
|
-
paragraph: false,
|
|
373
|
-
heading: { levels: [3, 4] },
|
|
374
|
-
blockquote: false,
|
|
375
|
-
codeBlock: false,
|
|
376
|
-
horizontalRule: false,
|
|
377
|
-
code: false,
|
|
378
|
-
strike: false
|
|
379
|
-
}),
|
|
380
|
-
CustomParagraph,
|
|
381
|
-
Underline,
|
|
382
|
-
// `page` protocol: stable internal-page hrefs (page://{pageId}#{sectionId})
|
|
383
|
-
// resolved to real routes at SSR — see lib/links.ts.
|
|
384
|
-
Link.configure({ openOnClick: false, protocols: ["page"] })
|
|
385
|
-
];
|
|
386
|
-
var presets = { basic, rich };
|
|
387
|
-
|
|
388
|
-
// src/components/primitives/useEditableRichText.ts
|
|
389
|
-
function useEditableRichText({
|
|
390
|
-
value,
|
|
391
|
-
onChange,
|
|
392
|
-
preset,
|
|
393
|
-
placeholder
|
|
394
|
-
}) {
|
|
395
|
-
const editorRef = useRef3(null);
|
|
396
|
-
const [editor, setEditor] = useState2(null);
|
|
397
|
-
const valueRef = useRef3(value);
|
|
398
|
-
const onChangeRef = useRef3(onChange);
|
|
399
|
-
useEffect3(() => {
|
|
400
|
-
valueRef.current = value;
|
|
401
|
-
}, [value]);
|
|
402
|
-
useEffect3(() => {
|
|
403
|
-
onChangeRef.current = onChange;
|
|
404
|
-
}, [onChange]);
|
|
405
|
-
const activate = useCallback3(() => {
|
|
406
|
-
if (editorRef.current) return;
|
|
407
|
-
const extensions = placeholder ? [...presets[preset], Placeholder.configure({ placeholder })] : presets[preset];
|
|
408
|
-
const ed = new Editor({
|
|
409
|
-
extensions,
|
|
410
|
-
content: valueRef.current,
|
|
411
|
-
// Commit edits to onChange on every transaction, not only on deactivate().
|
|
412
|
-
// Without this, content lives only inside TipTap until blur; clicking a
|
|
413
|
-
// Save button while the editor is still focused flushes persistence before
|
|
414
|
-
// the (150ms-delayed) blur->deactivate commit fires, silently dropping the
|
|
415
|
-
// in-progress edit. Live-committing keeps persistence in sync continuously.
|
|
416
|
-
onUpdate: ({ editor: updated }) => {
|
|
417
|
-
const html = updated.getHTML();
|
|
418
|
-
if (html !== valueRef.current) {
|
|
419
|
-
valueRef.current = html;
|
|
420
|
-
onChangeRef.current(html);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
editorRef.current = ed;
|
|
425
|
-
setEditor(ed);
|
|
426
|
-
}, [preset, placeholder]);
|
|
427
|
-
const deactivate = useCallback3(() => {
|
|
428
|
-
const ed = editorRef.current;
|
|
429
|
-
if (!ed) return;
|
|
430
|
-
const html = ed.getHTML();
|
|
431
|
-
ed.destroy();
|
|
432
|
-
editorRef.current = null;
|
|
433
|
-
setEditor(null);
|
|
434
|
-
if (html !== valueRef.current) {
|
|
435
|
-
onChangeRef.current(html);
|
|
436
|
-
}
|
|
437
|
-
}, []);
|
|
438
|
-
useEffect3(() => {
|
|
439
|
-
return () => {
|
|
440
|
-
editorRef.current?.destroy();
|
|
441
|
-
editorRef.current = null;
|
|
442
|
-
};
|
|
443
|
-
}, []);
|
|
444
|
-
return {
|
|
445
|
-
isEditorActive: editor !== null,
|
|
446
|
-
editor,
|
|
447
|
-
activate,
|
|
448
|
-
deactivate
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// src/components/primitives/RichTextToolbar.tsx
|
|
453
|
-
import { useState as useState4 } from "react";
|
|
454
|
-
import { useEditorState } from "@tiptap/react";
|
|
455
|
-
|
|
456
|
-
// src/components/primitives/LinkPopover.tsx
|
|
457
|
-
import { useState as useState3 } from "react";
|
|
458
|
-
|
|
459
|
-
// src/components/shared/Button.tsx
|
|
460
|
-
import { forwardRef } from "react";
|
|
461
|
-
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
462
|
-
var boxSize = {
|
|
463
|
-
sm: "rounded px-3 py-1.5 text-xs font-medium",
|
|
464
|
-
md: "rounded px-4 py-2 text-sm font-medium"
|
|
465
|
-
};
|
|
466
|
-
var ghostSize = {
|
|
467
|
-
sm: "text-xs font-medium",
|
|
468
|
-
md: "text-sm font-medium"
|
|
469
|
-
};
|
|
470
|
-
var variantClasses = {
|
|
471
|
-
primary: "bg-base-contrast text-base-accent hover:bg-base-contrast/90",
|
|
472
|
-
brand: "bg-primary text-primary-contrast hover:opacity-90",
|
|
473
|
-
secondary: "border border-base-200 text-base-contrast hover:bg-base-accent",
|
|
474
|
-
destructive: "border border-red-600 text-red-600 hover:bg-red-600 hover:text-white"
|
|
475
|
-
};
|
|
476
|
-
var ghostToneClasses = {
|
|
477
|
-
neutral: "text-base-contrast-light hover:text-base-contrast",
|
|
478
|
-
destructive: "text-red-600 hover:text-red-800"
|
|
479
|
-
};
|
|
480
|
-
var Button = forwardRef(function Button2({
|
|
481
|
-
variant = "primary",
|
|
482
|
-
size = "sm",
|
|
483
|
-
tone = "neutral",
|
|
484
|
-
fullWidth = false,
|
|
485
|
-
isLoading = false,
|
|
486
|
-
loadingLabel,
|
|
487
|
-
disabled,
|
|
488
|
-
className,
|
|
489
|
-
children,
|
|
490
|
-
...rest
|
|
491
|
-
}, ref) {
|
|
492
|
-
const isGhost = variant === "ghost";
|
|
493
|
-
const resolvedDisabled = disabled || isLoading;
|
|
494
|
-
const label = isLoading && loadingLabel ? loadingLabel : children;
|
|
495
|
-
return /* @__PURE__ */ jsx5(
|
|
496
|
-
"button",
|
|
497
|
-
{
|
|
498
|
-
ref,
|
|
499
|
-
disabled: resolvedDisabled,
|
|
500
|
-
className: cn(
|
|
501
|
-
"inline-flex items-center justify-center transition-colors",
|
|
502
|
-
isGhost ? ghostSize[size] : boxSize[size],
|
|
503
|
-
isGhost ? ghostToneClasses[tone] : variantClasses[variant],
|
|
504
|
-
fullWidth && "w-full",
|
|
505
|
-
resolvedDisabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
|
|
506
|
-
className
|
|
507
|
-
),
|
|
508
|
-
...rest,
|
|
509
|
-
children: label
|
|
510
|
-
}
|
|
511
|
-
);
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
// src/components/shared/PagesContext.tsx
|
|
515
|
-
import { createContext, useContext } from "react";
|
|
516
|
-
var PagesContext = createContext({ pages: [], getPageHeadings: () => [] });
|
|
517
|
-
function usePages() {
|
|
518
|
-
return useContext(PagesContext);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// src/lib/links.ts
|
|
522
|
-
function internalHref(pageId, anchorSectionId) {
|
|
523
|
-
return `page://${pageId}${anchorSectionId ? `#${anchorSectionId}` : ""}`;
|
|
524
|
-
}
|
|
525
|
-
function parseInternalHref(href) {
|
|
526
|
-
const m = /^page:\/\/([^#]+)(?:#(.+))?$/.exec(href);
|
|
527
|
-
return m ? { pageId: m[1], anchorSectionId: m[2] ?? null } : null;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// src/components/primitives/LinkPopover.tsx
|
|
531
|
-
import { Fragment, jsx as jsx6, jsxs } from "react/jsx-runtime";
|
|
532
|
-
var selectClasses = "w-full rounded border border-base-contrast/20 bg-base px-2 py-1 text-sm text-base-contrast focus:outline-none focus:ring-1 focus:ring-primary";
|
|
533
|
-
function LinkPopover({ editor, onClose }) {
|
|
534
|
-
const { pages, getPageHeadings } = usePages();
|
|
535
|
-
const existingAttrs = editor.getAttributes("link");
|
|
536
|
-
const existingInternal = parseInternalHref(existingAttrs.href ?? "");
|
|
537
|
-
const [mode, setMode] = useState3(existingInternal ? "internal" : "external");
|
|
538
|
-
const [url, setUrl] = useState3(existingInternal ? "" : existingAttrs.href ?? "");
|
|
539
|
-
const [pageId, setPageId] = useState3(existingInternal?.pageId ?? "");
|
|
540
|
-
const [anchorId, setAnchorId] = useState3(existingInternal?.anchorSectionId ?? "");
|
|
541
|
-
const [openInNewTab, setOpenInNewTab] = useState3(
|
|
542
|
-
existingAttrs.target === "_blank"
|
|
543
|
-
);
|
|
544
|
-
const hasLink = Boolean(existingAttrs.href);
|
|
545
|
-
const headings = pageId ? getPageHeadings(pageId) : [];
|
|
546
|
-
const handleApply = () => {
|
|
547
|
-
if (mode === "internal") {
|
|
548
|
-
if (pageId) {
|
|
549
|
-
editor.chain().focus().extendMarkRange("link").setLink({ href: internalHref(pageId, anchorId || null), target: null }).run();
|
|
550
|
-
}
|
|
551
|
-
} else if (url.trim()) {
|
|
552
|
-
editor.chain().focus().extendMarkRange("link").setLink({ href: url.trim(), target: openInNewTab ? "_blank" : null }).run();
|
|
553
|
-
}
|
|
554
|
-
onClose();
|
|
555
|
-
};
|
|
556
|
-
const handleRemove = () => {
|
|
557
|
-
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
558
|
-
onClose();
|
|
559
|
-
};
|
|
560
|
-
const handleKeyDown = (e) => {
|
|
561
|
-
if (e.key === "Enter") {
|
|
562
|
-
e.preventDefault();
|
|
563
|
-
handleApply();
|
|
564
|
-
} else if (e.key === "Escape") {
|
|
565
|
-
e.preventDefault();
|
|
566
|
-
onClose();
|
|
567
|
-
}
|
|
568
|
-
};
|
|
569
|
-
return /* @__PURE__ */ jsxs(
|
|
570
|
-
"div",
|
|
571
|
-
{
|
|
572
|
-
className: "flex w-64 flex-col gap-2 rounded bg-base-accent p-3 shadow-lg",
|
|
573
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
574
|
-
onKeyDown: handleKeyDown,
|
|
575
|
-
children: [
|
|
576
|
-
/* @__PURE__ */ jsx6("div", { className: "flex gap-2", role: "tablist", children: ["external", "internal"].map((kind) => /* @__PURE__ */ jsx6(
|
|
577
|
-
"button",
|
|
578
|
-
{
|
|
579
|
-
type: "button",
|
|
580
|
-
role: "tab",
|
|
581
|
-
"aria-selected": mode === kind,
|
|
582
|
-
onClick: () => setMode(kind),
|
|
583
|
-
className: cn(
|
|
584
|
-
"cursor-pointer rounded border px-2 py-0.5 text-xs",
|
|
585
|
-
mode === kind ? "border-primary bg-primary text-primary-contrast" : "border-base-200 text-base-contrast"
|
|
586
|
-
),
|
|
587
|
-
children: kind === "external" ? "External URL" : "Internal page"
|
|
588
|
-
},
|
|
589
|
-
kind
|
|
590
|
-
)) }),
|
|
591
|
-
mode === "external" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
592
|
-
/* @__PURE__ */ jsx6(
|
|
593
|
-
"input",
|
|
594
|
-
{
|
|
595
|
-
autoFocus: true,
|
|
596
|
-
type: "url",
|
|
597
|
-
value: url,
|
|
598
|
-
onChange: (e) => setUrl(e.target.value),
|
|
599
|
-
placeholder: "https://example.com",
|
|
600
|
-
className: "rounded border border-base-contrast/20 bg-base px-2 py-1 text-sm text-base-contrast placeholder:text-base-contrast/40 focus:outline-none focus:ring-1 focus:ring-primary"
|
|
601
|
-
}
|
|
602
|
-
),
|
|
603
|
-
/* @__PURE__ */ jsxs("label", { className: "flex cursor-pointer items-center gap-2 text-sm text-base-contrast", children: [
|
|
604
|
-
/* @__PURE__ */ jsx6(
|
|
605
|
-
"input",
|
|
606
|
-
{
|
|
607
|
-
type: "checkbox",
|
|
608
|
-
checked: openInNewTab,
|
|
609
|
-
onChange: (e) => setOpenInNewTab(e.target.checked),
|
|
610
|
-
className: "accent-primary"
|
|
611
|
-
}
|
|
612
|
-
),
|
|
613
|
-
"Open in new tab"
|
|
614
|
-
] })
|
|
615
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
616
|
-
/* @__PURE__ */ jsxs(
|
|
617
|
-
"select",
|
|
618
|
-
{
|
|
619
|
-
autoFocus: true,
|
|
620
|
-
"aria-label": "Page",
|
|
621
|
-
value: pageId,
|
|
622
|
-
onChange: (e) => {
|
|
623
|
-
setPageId(e.target.value);
|
|
624
|
-
setAnchorId("");
|
|
625
|
-
},
|
|
626
|
-
className: selectClasses,
|
|
627
|
-
children: [
|
|
628
|
-
/* @__PURE__ */ jsx6("option", { value: "", children: "Select a page\u2026" }),
|
|
629
|
-
pages.map((p) => /* @__PURE__ */ jsx6("option", { value: p.id, children: p.title }, p.id))
|
|
630
|
-
]
|
|
631
|
-
}
|
|
632
|
-
),
|
|
633
|
-
/* @__PURE__ */ jsxs(
|
|
634
|
-
"select",
|
|
635
|
-
{
|
|
636
|
-
"aria-label": "Section",
|
|
637
|
-
value: anchorId,
|
|
638
|
-
disabled: !pageId,
|
|
639
|
-
onChange: (e) => setAnchorId(e.target.value),
|
|
640
|
-
className: cn(selectClasses, !pageId && "cursor-not-allowed opacity-50"),
|
|
641
|
-
children: [
|
|
642
|
-
/* @__PURE__ */ jsx6("option", { value: "", children: "None (top of page)" }),
|
|
643
|
-
headings.map((h) => /* @__PURE__ */ jsx6("option", { value: h.id, children: h.label }, h.id))
|
|
644
|
-
]
|
|
645
|
-
}
|
|
646
|
-
)
|
|
647
|
-
] }),
|
|
648
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
649
|
-
/* @__PURE__ */ jsx6(
|
|
650
|
-
Button,
|
|
651
|
-
{
|
|
652
|
-
variant: "brand",
|
|
653
|
-
size: "sm",
|
|
654
|
-
onMouseDown: (e) => {
|
|
655
|
-
e.preventDefault();
|
|
656
|
-
handleApply();
|
|
657
|
-
},
|
|
658
|
-
children: "Apply"
|
|
659
|
-
}
|
|
660
|
-
),
|
|
661
|
-
hasLink && /* @__PURE__ */ jsx6(
|
|
662
|
-
Button,
|
|
663
|
-
{
|
|
664
|
-
variant: "secondary",
|
|
665
|
-
size: "sm",
|
|
666
|
-
onMouseDown: (e) => {
|
|
667
|
-
e.preventDefault();
|
|
668
|
-
handleRemove();
|
|
669
|
-
},
|
|
670
|
-
children: "Remove"
|
|
671
|
-
}
|
|
672
|
-
),
|
|
673
|
-
/* @__PURE__ */ jsx6(
|
|
674
|
-
Button,
|
|
675
|
-
{
|
|
676
|
-
variant: "secondary",
|
|
677
|
-
size: "sm",
|
|
678
|
-
onMouseDown: (e) => {
|
|
679
|
-
e.preventDefault();
|
|
680
|
-
onClose();
|
|
681
|
-
},
|
|
682
|
-
children: "Cancel"
|
|
683
|
-
}
|
|
684
|
-
)
|
|
685
|
-
] })
|
|
686
|
-
]
|
|
687
|
-
}
|
|
688
|
-
);
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
// src/components/primitives/RichTextToolbar.tsx
|
|
692
|
-
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
693
|
-
function ToolbarButton({ isActive, onClick, title, children }) {
|
|
694
|
-
return /* @__PURE__ */ jsx7(
|
|
695
|
-
"button",
|
|
696
|
-
{
|
|
697
|
-
type: "button",
|
|
698
|
-
title,
|
|
699
|
-
"aria-label": title,
|
|
700
|
-
"aria-pressed": isActive,
|
|
701
|
-
onMouseDown: (e) => {
|
|
702
|
-
e.preventDefault();
|
|
703
|
-
onClick();
|
|
704
|
-
},
|
|
705
|
-
className: cn(
|
|
706
|
-
"cursor-pointer rounded px-2 py-1 text-sm font-medium transition-colors",
|
|
707
|
-
isActive ? "bg-primary text-primary-contrast" : "bg-base-accent text-base-contrast hover:opacity-80"
|
|
708
|
-
),
|
|
709
|
-
children
|
|
710
|
-
}
|
|
711
|
-
);
|
|
712
|
-
}
|
|
713
|
-
function Separator() {
|
|
714
|
-
return /* @__PURE__ */ jsx7("div", { className: "mx-1 h-5 w-px bg-base-contrast/20" });
|
|
715
|
-
}
|
|
716
|
-
function RichTextToolbar({ editor, preset }) {
|
|
717
|
-
const [showLinkPopover, setShowLinkPopover] = useState4(false);
|
|
718
|
-
const state = useEditorState({
|
|
719
|
-
editor,
|
|
720
|
-
selector: ({ editor: ed }) => ({
|
|
721
|
-
isBold: ed.isActive("bold"),
|
|
722
|
-
isItalic: ed.isActive("italic"),
|
|
723
|
-
isUnderline: ed.isActive("underline"),
|
|
724
|
-
isLink: ed.isActive("link"),
|
|
725
|
-
isBulletList: ed.isActive("bulletList"),
|
|
726
|
-
isOrderedList: ed.isActive("orderedList"),
|
|
727
|
-
isH3: ed.isActive("heading", { level: 3 }),
|
|
728
|
-
isH4: ed.isActive("heading", { level: 4 }),
|
|
729
|
-
isLarge: ed.isActive("paragraph", { class: "large" }),
|
|
730
|
-
isLeadIn: ed.isActive("paragraph", { class: "lead-in" })
|
|
731
|
-
})
|
|
732
|
-
});
|
|
733
|
-
const toggleParagraphVariant = (cls, isCurrentlyActive) => {
|
|
734
|
-
if (isCurrentlyActive) {
|
|
735
|
-
editor.chain().focus().setNode("paragraph").run();
|
|
736
|
-
} else {
|
|
737
|
-
editor.chain().focus().setNode("paragraph", { class: cls }).run();
|
|
738
|
-
}
|
|
739
|
-
};
|
|
740
|
-
return /* @__PURE__ */ jsxs2(
|
|
741
|
-
"div",
|
|
742
|
-
{
|
|
743
|
-
"data-testid": "rich-text-toolbar",
|
|
744
|
-
className: "flex items-center gap-1 rounded border border-base-contrast/10 bg-base-accent p-1 shadow-md",
|
|
745
|
-
children: [
|
|
746
|
-
/* @__PURE__ */ jsx7(
|
|
747
|
-
ToolbarButton,
|
|
748
|
-
{
|
|
749
|
-
isActive: state.isBold,
|
|
750
|
-
onClick: () => editor.chain().focus().toggleBold().run(),
|
|
751
|
-
title: "Bold",
|
|
752
|
-
children: /* @__PURE__ */ jsx7("strong", { children: "B" })
|
|
753
|
-
}
|
|
754
|
-
),
|
|
755
|
-
/* @__PURE__ */ jsx7(
|
|
756
|
-
ToolbarButton,
|
|
757
|
-
{
|
|
758
|
-
isActive: state.isItalic,
|
|
759
|
-
onClick: () => editor.chain().focus().toggleItalic().run(),
|
|
760
|
-
title: "Italic",
|
|
761
|
-
children: /* @__PURE__ */ jsx7("em", { children: "I" })
|
|
762
|
-
}
|
|
763
|
-
),
|
|
764
|
-
/* @__PURE__ */ jsx7(
|
|
765
|
-
ToolbarButton,
|
|
766
|
-
{
|
|
767
|
-
isActive: state.isUnderline,
|
|
768
|
-
onClick: () => editor.chain().focus().toggleUnderline().run(),
|
|
769
|
-
title: "Underline",
|
|
770
|
-
children: /* @__PURE__ */ jsx7("span", { className: "underline", children: "U" })
|
|
771
|
-
}
|
|
772
|
-
),
|
|
773
|
-
preset === "rich" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
774
|
-
/* @__PURE__ */ jsx7(Separator, {}),
|
|
775
|
-
/* @__PURE__ */ jsxs2("div", { className: "relative", children: [
|
|
776
|
-
/* @__PURE__ */ jsx7(
|
|
777
|
-
ToolbarButton,
|
|
778
|
-
{
|
|
779
|
-
isActive: state.isLink || showLinkPopover,
|
|
780
|
-
onClick: () => setShowLinkPopover((prev) => !prev),
|
|
781
|
-
title: "Link",
|
|
782
|
-
children: "\u{1F517}"
|
|
783
|
-
}
|
|
784
|
-
),
|
|
785
|
-
showLinkPopover && /* @__PURE__ */ jsx7("div", { className: "absolute left-0 top-full z-50 mt-1", children: /* @__PURE__ */ jsx7(
|
|
786
|
-
LinkPopover,
|
|
787
|
-
{
|
|
788
|
-
editor,
|
|
789
|
-
onClose: () => setShowLinkPopover(false)
|
|
790
|
-
}
|
|
791
|
-
) })
|
|
792
|
-
] }),
|
|
793
|
-
/* @__PURE__ */ jsx7(Separator, {}),
|
|
794
|
-
/* @__PURE__ */ jsx7(
|
|
795
|
-
ToolbarButton,
|
|
796
|
-
{
|
|
797
|
-
isActive: state.isBulletList,
|
|
798
|
-
onClick: () => editor.chain().focus().toggleBulletList().run(),
|
|
799
|
-
title: "Bullet List",
|
|
800
|
-
children: "\u2022\u2261"
|
|
801
|
-
}
|
|
802
|
-
),
|
|
803
|
-
/* @__PURE__ */ jsx7(
|
|
804
|
-
ToolbarButton,
|
|
805
|
-
{
|
|
806
|
-
isActive: state.isOrderedList,
|
|
807
|
-
onClick: () => editor.chain().focus().toggleOrderedList().run(),
|
|
808
|
-
title: "Ordered List",
|
|
809
|
-
children: "1\u2261"
|
|
810
|
-
}
|
|
811
|
-
),
|
|
812
|
-
/* @__PURE__ */ jsx7(Separator, {}),
|
|
813
|
-
/* @__PURE__ */ jsx7(
|
|
814
|
-
ToolbarButton,
|
|
815
|
-
{
|
|
816
|
-
isActive: state.isH3,
|
|
817
|
-
onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
|
|
818
|
-
title: "Heading 3",
|
|
819
|
-
children: "H3"
|
|
820
|
-
}
|
|
821
|
-
),
|
|
822
|
-
/* @__PURE__ */ jsx7(
|
|
823
|
-
ToolbarButton,
|
|
824
|
-
{
|
|
825
|
-
isActive: state.isH4,
|
|
826
|
-
onClick: () => editor.chain().focus().toggleHeading({ level: 4 }).run(),
|
|
827
|
-
title: "Heading 4",
|
|
828
|
-
children: "H4"
|
|
829
|
-
}
|
|
830
|
-
),
|
|
831
|
-
/* @__PURE__ */ jsx7(
|
|
832
|
-
ToolbarButton,
|
|
833
|
-
{
|
|
834
|
-
isActive: state.isLarge,
|
|
835
|
-
onClick: () => toggleParagraphVariant("large", state.isLarge),
|
|
836
|
-
title: "Large Paragraph",
|
|
837
|
-
children: "Lg"
|
|
838
|
-
}
|
|
839
|
-
),
|
|
840
|
-
/* @__PURE__ */ jsx7(
|
|
841
|
-
ToolbarButton,
|
|
842
|
-
{
|
|
843
|
-
isActive: state.isLeadIn,
|
|
844
|
-
onClick: () => toggleParagraphVariant("lead-in", state.isLeadIn),
|
|
845
|
-
title: "Lead-In",
|
|
846
|
-
children: "Li"
|
|
847
|
-
}
|
|
848
|
-
)
|
|
849
|
-
] })
|
|
850
|
-
]
|
|
851
|
-
}
|
|
852
|
-
);
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
// src/components/primitives/EditableRichText.tsx
|
|
856
|
-
import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
857
|
-
function isContentEmpty(html) {
|
|
858
|
-
return html.replace(/<[^>]*>/g, "").trim().length === 0;
|
|
859
|
-
}
|
|
860
|
-
var DEFAULT_PLACEHOLDER = "Click to edit\u2026";
|
|
861
|
-
function EditableRichText({
|
|
862
|
-
value,
|
|
863
|
-
onChange,
|
|
864
|
-
isEditMode,
|
|
865
|
-
preset = "rich",
|
|
866
|
-
className,
|
|
867
|
-
placeholder = DEFAULT_PLACEHOLDER
|
|
868
|
-
}) {
|
|
869
|
-
const { isEditorActive, editor, activate, deactivate } = useEditableRichText({ value, onChange, preset, placeholder });
|
|
870
|
-
const wrapperRef = useRef4(null);
|
|
871
|
-
const blurTimeoutRef = useRef4(null);
|
|
872
|
-
const clickCoordsRef = useRef4(null);
|
|
873
|
-
useEffect4(() => {
|
|
874
|
-
return () => {
|
|
875
|
-
if (blurTimeoutRef.current) {
|
|
876
|
-
clearTimeout(blurTimeoutRef.current);
|
|
877
|
-
}
|
|
878
|
-
};
|
|
879
|
-
}, []);
|
|
880
|
-
useEffect4(() => {
|
|
881
|
-
if (!isEditorActive || !editor) return;
|
|
882
|
-
requestAnimationFrame(() => {
|
|
883
|
-
if (editor.isDestroyed) return;
|
|
884
|
-
const coords = clickCoordsRef.current;
|
|
885
|
-
if (coords) {
|
|
886
|
-
try {
|
|
887
|
-
const pos = editor.view.posAtCoords(coords);
|
|
888
|
-
if (pos) {
|
|
889
|
-
editor.commands.focus();
|
|
890
|
-
editor.commands.setTextSelection(pos.pos);
|
|
891
|
-
} else {
|
|
892
|
-
editor.commands.focus("end");
|
|
893
|
-
}
|
|
894
|
-
} catch {
|
|
895
|
-
editor.commands.focus("end");
|
|
896
|
-
} finally {
|
|
897
|
-
clickCoordsRef.current = null;
|
|
898
|
-
}
|
|
899
|
-
} else {
|
|
900
|
-
editor.commands.focus("end");
|
|
901
|
-
}
|
|
902
|
-
});
|
|
903
|
-
}, [isEditorActive, editor]);
|
|
904
|
-
const handleClick = useCallback4((e) => {
|
|
905
|
-
if (isEditMode && !isEditorActive) {
|
|
906
|
-
clickCoordsRef.current = { left: e.clientX, top: e.clientY };
|
|
907
|
-
activate();
|
|
908
|
-
}
|
|
909
|
-
}, [isEditMode, isEditorActive, activate]);
|
|
910
|
-
const handleFocus = useCallback4(() => {
|
|
911
|
-
if (blurTimeoutRef.current) {
|
|
912
|
-
clearTimeout(blurTimeoutRef.current);
|
|
913
|
-
blurTimeoutRef.current = null;
|
|
914
|
-
}
|
|
915
|
-
}, []);
|
|
916
|
-
const handleBlur = useCallback4(() => {
|
|
917
|
-
blurTimeoutRef.current = setTimeout(() => {
|
|
918
|
-
if (wrapperRef.current && !wrapperRef.current.contains(document.activeElement)) {
|
|
919
|
-
deactivate();
|
|
920
|
-
}
|
|
921
|
-
}, 150);
|
|
922
|
-
}, [deactivate]);
|
|
923
|
-
if (!isEditMode) {
|
|
924
|
-
return /* @__PURE__ */ jsx8(
|
|
925
|
-
"div",
|
|
926
|
-
{
|
|
927
|
-
className,
|
|
928
|
-
dangerouslySetInnerHTML: { __html: sanitizeHtml(value) }
|
|
929
|
-
}
|
|
930
|
-
);
|
|
931
|
-
}
|
|
932
|
-
if (!isEditorActive || !editor) {
|
|
933
|
-
const empty = isContentEmpty(value);
|
|
934
|
-
if (empty) {
|
|
935
|
-
return /* @__PURE__ */ jsx8("div", { className, onClick: handleClick, children: /* @__PURE__ */ jsx8("p", { className: "tiptap-placeholder", children: placeholder }) });
|
|
936
|
-
}
|
|
937
|
-
return /* @__PURE__ */ jsx8(
|
|
938
|
-
"div",
|
|
939
|
-
{
|
|
940
|
-
className,
|
|
941
|
-
onClick: handleClick,
|
|
942
|
-
dangerouslySetInnerHTML: { __html: sanitizeHtml(value) }
|
|
943
|
-
}
|
|
944
|
-
);
|
|
945
|
-
}
|
|
946
|
-
return /* @__PURE__ */ jsxs3(
|
|
947
|
-
"div",
|
|
948
|
-
{
|
|
949
|
-
ref: wrapperRef,
|
|
950
|
-
className,
|
|
951
|
-
onFocus: handleFocus,
|
|
952
|
-
onBlur: handleBlur,
|
|
953
|
-
children: [
|
|
954
|
-
/* @__PURE__ */ jsx8(
|
|
955
|
-
BubbleMenu,
|
|
956
|
-
{
|
|
957
|
-
editor,
|
|
958
|
-
className: "z-50",
|
|
959
|
-
shouldShow: ({ editor: ed, state }) => {
|
|
960
|
-
const { from, to } = state.selection;
|
|
961
|
-
return ed.isFocused && from !== to;
|
|
962
|
-
},
|
|
963
|
-
children: /* @__PURE__ */ jsx8(RichTextToolbar, { editor, preset })
|
|
964
|
-
}
|
|
965
|
-
),
|
|
966
|
-
/* @__PURE__ */ jsx8(EditorContent, { editor })
|
|
967
|
-
]
|
|
968
|
-
}
|
|
969
|
-
);
|
|
970
|
-
}
|
|
101
|
+
tag: "h4",
|
|
102
|
+
placeholder: "Sub sub heading",
|
|
103
|
+
defaultHeading: "New Sub Sub Heading",
|
|
104
|
+
navExclusion: true
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// src/components/sections/Prose/index.tsx
|
|
108
|
+
import { z } from "zod";
|
|
109
|
+
import { AlignLeft } from "lucide-react";
|
|
971
110
|
|
|
972
111
|
// src/components/sections/Prose/Prose.tsx
|
|
973
|
-
import { jsx as
|
|
112
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
974
113
|
function Prose({ body, onChange }) {
|
|
975
114
|
if (onChange) {
|
|
976
|
-
return /* @__PURE__ */
|
|
115
|
+
return /* @__PURE__ */ jsx4("div", { className: "prose-content", children: /* @__PURE__ */ jsx4(
|
|
977
116
|
EditableRichText,
|
|
978
117
|
{
|
|
979
118
|
value: body,
|
|
@@ -984,7 +123,7 @@ function Prose({ body, onChange }) {
|
|
|
984
123
|
}
|
|
985
124
|
) });
|
|
986
125
|
}
|
|
987
|
-
return /* @__PURE__ */
|
|
126
|
+
return /* @__PURE__ */ jsx4(
|
|
988
127
|
"div",
|
|
989
128
|
{
|
|
990
129
|
className: "prose-content",
|
|
@@ -1001,237 +140,51 @@ function truncate(text, maxLength) {
|
|
|
1001
140
|
if (text.length <= maxLength) return text;
|
|
1002
141
|
return text.slice(0, maxLength) + "...";
|
|
1003
142
|
}
|
|
143
|
+
function pluralize(n, word) {
|
|
144
|
+
return `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
145
|
+
}
|
|
1004
146
|
|
|
1005
147
|
// src/components/sections/Prose/index.tsx
|
|
1006
|
-
import { jsx as
|
|
1007
|
-
var
|
|
1008
|
-
type:
|
|
1009
|
-
content:
|
|
148
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
149
|
+
var schema = z.object({
|
|
150
|
+
type: z.literal("prose"),
|
|
151
|
+
content: z.object({ body: z.string() })
|
|
1010
152
|
});
|
|
1011
153
|
var Prose_default = defineSection({
|
|
1012
154
|
type: "prose",
|
|
1013
155
|
label: "Prose",
|
|
1014
|
-
icon: /* @__PURE__ */
|
|
1015
|
-
schema
|
|
156
|
+
icon: /* @__PURE__ */ jsx5(AlignLeft, { size: 18 }),
|
|
157
|
+
schema,
|
|
1016
158
|
richTextFields: ["body"],
|
|
1017
|
-
component: ({ content, onChange }) => /* @__PURE__ */
|
|
159
|
+
component: ({ content, onChange }) => /* @__PURE__ */ jsx5(Prose, { body: content.content.body, onChange: onChange ? (c) => onChange(c) : void 0 }),
|
|
1018
160
|
defaults: () => ({ type: "prose", content: { body: "<p></p>" } }),
|
|
1019
161
|
getLabel: (content) => truncate(stripHtmlToPlainText(content.content.body), 60)
|
|
1020
162
|
});
|
|
1021
163
|
|
|
1022
164
|
// src/components/sections/Media/index.tsx
|
|
1023
|
-
import { z as
|
|
1024
|
-
import { Image as
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
// src/components/primitives/ResolvedMedia.tsx
|
|
1030
|
-
import { ImageIcon } from "lucide-react";
|
|
1031
|
-
|
|
1032
|
-
// src/hooks/useResolvedMedia.ts
|
|
1033
|
-
import { useMemo } from "react";
|
|
1034
|
-
|
|
1035
|
-
// src/components/shell/MediaLibraryContext.tsx
|
|
1036
|
-
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
1037
|
-
var MediaLibraryContext = createContext2(null);
|
|
1038
|
-
function useMediaLibrary() {
|
|
1039
|
-
return useContext2(MediaLibraryContext);
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
// src/hooks/useResolvedMedia.ts
|
|
1043
|
-
function useResolvedMedia(imageId) {
|
|
1044
|
-
const ctx = useMediaLibrary();
|
|
1045
|
-
return useMemo(() => {
|
|
1046
|
-
if (!imageId || !ctx) {
|
|
1047
|
-
return { src: void 0, srcset: void 0, poster: void 0, alt: "", kind: "image" };
|
|
1048
|
-
}
|
|
1049
|
-
const { manifest, pendingItems, pendingLocalUrls, siteConfig } = ctx;
|
|
1050
|
-
const sizes = siteConfig?.media?.sizes ?? [640, 1080, 1920];
|
|
1051
|
-
const manifestItem = manifest.images[imageId];
|
|
1052
|
-
const pendingItem = pendingItems.find((i) => i.id === imageId);
|
|
1053
|
-
const item = manifestItem ?? pendingItem;
|
|
1054
|
-
const alt = item?.alt ?? "";
|
|
1055
|
-
const kind = item?.kind ?? "image";
|
|
1056
|
-
const localUrl = pendingLocalUrls[imageId];
|
|
1057
|
-
if (localUrl) {
|
|
1058
|
-
return { src: localUrl, srcset: void 0, poster: void 0, alt, kind };
|
|
1059
|
-
}
|
|
1060
|
-
if (manifestItem) {
|
|
1061
|
-
const provider = getMediaProvider();
|
|
1062
|
-
const resolved = provider.resolve(manifestItem, sizes);
|
|
1063
|
-
if (resolved && resolved.tag === "img") {
|
|
1064
|
-
return {
|
|
1065
|
-
src: resolved.src,
|
|
1066
|
-
srcset: "srcSet" in resolved ? resolved.srcSet : void 0,
|
|
1067
|
-
poster: void 0,
|
|
1068
|
-
alt,
|
|
1069
|
-
kind
|
|
1070
|
-
};
|
|
1071
|
-
}
|
|
1072
|
-
if (resolved && resolved.tag === "video") {
|
|
1073
|
-
return { src: resolved.src, srcset: void 0, poster: resolved.poster, alt, kind };
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
return { src: void 0, srcset: void 0, poster: void 0, alt, kind };
|
|
1077
|
-
}, [imageId, ctx]);
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
// src/components/primitives/ResolvedMedia.tsx
|
|
1081
|
-
import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1082
|
-
function ResolvedMedia({
|
|
1083
|
-
imageId,
|
|
1084
|
-
src: propSrc,
|
|
1085
|
-
srcset: propSrcset,
|
|
1086
|
-
alt: propAlt,
|
|
1087
|
-
className,
|
|
1088
|
-
imgClassName,
|
|
1089
|
-
invertFrom
|
|
1090
|
-
}) {
|
|
1091
|
-
const resolved = useResolvedMedia(imageId);
|
|
1092
|
-
const src = propSrc || resolved.src;
|
|
1093
|
-
const srcset = propSrcset || resolved.srcset;
|
|
1094
|
-
const poster = resolved.poster;
|
|
1095
|
-
const alt = propAlt ?? resolved.alt;
|
|
1096
|
-
const kind = resolved.kind;
|
|
1097
|
-
const invertClass = invertFrom === "light" ? "invert dark:invert-0" : invertFrom === "dark" ? "dark:invert" : void 0;
|
|
1098
|
-
const mediaClass = cn("h-full w-full", imgClassName, invertClass);
|
|
1099
|
-
return /* @__PURE__ */ jsx11("div", { className, children: src ? kind === "video" ? /* @__PURE__ */ jsx11("video", { src, poster, muted: true, playsInline: true, loop: true, autoPlay: true, className: mediaClass }) : /* @__PURE__ */ jsx11("img", { src, srcSet: srcset, alt, className: mediaClass }) : /* @__PURE__ */ jsxs4("div", { className: "flex aspect-video h-full w-full flex-col items-center justify-center gap-1 rounded bg-base-accent text-base-contrast-light/50", children: [
|
|
1100
|
-
/* @__PURE__ */ jsx11(ImageIcon, { size: 24 }),
|
|
1101
|
-
/* @__PURE__ */ jsx11("span", { className: "text-sm", children: "No Image" })
|
|
1102
|
-
] }) });
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
// src/components/primitives/ImageDropZone.tsx
|
|
1106
|
-
import { useState as useState5 } from "react";
|
|
1107
|
-
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1108
|
-
var ACCEPTED = /^(image|video)\//;
|
|
1109
|
-
function ImageDropZone({ onImageSelected, className, children }) {
|
|
1110
|
-
const mediaLibrary = useMediaLibrary();
|
|
1111
|
-
const [dragging, setDragging] = useState5(false);
|
|
1112
|
-
if (!mediaLibrary) return /* @__PURE__ */ jsx12(Fragment3, { children });
|
|
1113
|
-
const maxFileSize = mediaLibrary.siteConfig?.media.maxFileSize;
|
|
1114
|
-
const hasFiles = (e) => e.dataTransfer.types.includes("Files");
|
|
1115
|
-
const handleDragOver = (e) => {
|
|
1116
|
-
if (!hasFiles(e)) return;
|
|
1117
|
-
e.preventDefault();
|
|
1118
|
-
e.dataTransfer.dropEffect = "copy";
|
|
1119
|
-
setDragging(true);
|
|
1120
|
-
};
|
|
1121
|
-
const handleDragLeave = (e) => {
|
|
1122
|
-
if (!hasFiles(e)) return;
|
|
1123
|
-
const related = e.relatedTarget;
|
|
1124
|
-
if (related && e.currentTarget.contains(related)) return;
|
|
1125
|
-
setDragging(false);
|
|
1126
|
-
};
|
|
1127
|
-
const handleDrop = (e) => {
|
|
1128
|
-
if (!hasFiles(e)) return;
|
|
1129
|
-
e.preventDefault();
|
|
1130
|
-
e.stopPropagation();
|
|
1131
|
-
setDragging(false);
|
|
1132
|
-
const file = e.dataTransfer.files[0];
|
|
1133
|
-
if (!file) return;
|
|
1134
|
-
if (!ACCEPTED.test(file.type)) {
|
|
1135
|
-
mediaLibrary.reportRejectedUploads([{ name: file.name, reason: "type" }]);
|
|
1136
|
-
return;
|
|
1137
|
-
}
|
|
1138
|
-
if (maxFileSize && file.size > maxFileSize) {
|
|
1139
|
-
mediaLibrary.reportRejectedUploads([{ name: file.name, reason: "size" }]);
|
|
1140
|
-
return;
|
|
1141
|
-
}
|
|
1142
|
-
mediaLibrary.uploadFileWithCallback(file, onImageSelected);
|
|
1143
|
-
};
|
|
1144
|
-
return /* @__PURE__ */ jsxs5(
|
|
1145
|
-
"div",
|
|
1146
|
-
{
|
|
1147
|
-
className: cn("relative", className),
|
|
1148
|
-
onDragOver: handleDragOver,
|
|
1149
|
-
onDragLeave: handleDragLeave,
|
|
1150
|
-
onDrop: handleDrop,
|
|
1151
|
-
children: [
|
|
1152
|
-
children,
|
|
1153
|
-
dragging && /* @__PURE__ */ jsx12("div", { className: "pointer-events-none absolute inset-0 z-10 rounded-md border-2 border-primary bg-primary/5" })
|
|
1154
|
-
]
|
|
1155
|
-
}
|
|
1156
|
-
);
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
// src/components/sections/Media/MediaBlock.tsx
|
|
1160
|
-
import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1161
|
-
function MediaBlock({ refValue, options, link, dodont, isEditMode, onRefChange }) {
|
|
1162
|
-
const mediaLibrary = useMediaLibrary();
|
|
1163
|
-
const fit = refValue.objectFit ?? options.objectFit;
|
|
1164
|
-
const fitClass = fit === "cover" ? "object-cover" : "object-contain";
|
|
1165
|
-
const showBorder = refValue.border ?? options.border;
|
|
1166
|
-
const captionStr = refValue.caption ? Array.isArray(refValue.caption) ? refValue.caption.join("\n") : refValue.caption : "";
|
|
1167
|
-
const replace = onRefChange ? (imageId) => onRefChange({ ...refValue, imageId }) : void 0;
|
|
1168
|
-
const resolved = /* @__PURE__ */ jsx13(
|
|
1169
|
-
ResolvedMedia,
|
|
1170
|
-
{
|
|
1171
|
-
imageId: refValue.imageId || void 0,
|
|
1172
|
-
className: "h-full w-full",
|
|
1173
|
-
imgClassName: fitClass,
|
|
1174
|
-
invertFrom: refValue.invertFrom
|
|
1175
|
-
}
|
|
1176
|
-
);
|
|
1177
|
-
let media = isEditMode && replace ? /* @__PURE__ */ jsx13(ImageDropZone, { onImageSelected: replace, className: "h-full w-full", children: resolved }) : resolved;
|
|
1178
|
-
if (!isEditMode && link && link.kind === "external" && link.href) {
|
|
1179
|
-
media = /* @__PURE__ */ jsx13("a", { href: link.href, target: link.target, className: "group block", children: media });
|
|
1180
|
-
}
|
|
1181
|
-
const onImageClick = isEditMode && replace && mediaLibrary ? () => mediaLibrary.openSelectModal((imageId) => replace(imageId)) : void 0;
|
|
1182
|
-
return /* @__PURE__ */ jsxs6("figure", { children: [
|
|
1183
|
-
dodont && /* @__PURE__ */ jsx13("div", { className: "flex h-10 items-center justify-center pb-1", children: dodont === "do" ? /* @__PURE__ */ jsx13(Check, { size: 28, className: "text-green-600" }) : /* @__PURE__ */ jsx13(X, { size: 28, className: "text-red-600" }) }),
|
|
1184
|
-
/* @__PURE__ */ jsx13(
|
|
1185
|
-
"div",
|
|
1186
|
-
{
|
|
1187
|
-
"data-testid": "media-open-surface",
|
|
1188
|
-
className: cn(
|
|
1189
|
-
"overflow-hidden rounded-md",
|
|
1190
|
-
showBorder && "border border-base-200",
|
|
1191
|
-
options.square && "aspect-square",
|
|
1192
|
-
onImageClick && "cursor-pointer"
|
|
1193
|
-
),
|
|
1194
|
-
onClick: onImageClick,
|
|
1195
|
-
onPointerDown: onImageClick ? (e) => e.stopPropagation() : void 0,
|
|
1196
|
-
children: media
|
|
1197
|
-
}
|
|
1198
|
-
),
|
|
1199
|
-
options.showCaption && /* @__PURE__ */ jsx13("figcaption", { className: "mt-2 min-h-[1em] text-sm text-base-contrast-light", children: isEditMode && onRefChange ? /* @__PURE__ */ jsx13(
|
|
1200
|
-
EditablePlainText,
|
|
1201
|
-
{
|
|
1202
|
-
tag: "span",
|
|
1203
|
-
value: captionStr,
|
|
1204
|
-
onChange: (caption) => onRefChange({ ...refValue, caption: caption || void 0 }),
|
|
1205
|
-
isEditMode: true,
|
|
1206
|
-
placeholder: "Caption",
|
|
1207
|
-
className: "block min-h-[1em]"
|
|
1208
|
-
}
|
|
1209
|
-
) : captionStr || " " })
|
|
1210
|
-
] });
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
// src/components/sections/Media/index.tsx
|
|
1214
|
-
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1215
|
-
var schema5 = z5.object({
|
|
1216
|
-
type: z5.literal("media"),
|
|
1217
|
-
content: z5.object({
|
|
165
|
+
import { z as z2 } from "zod";
|
|
166
|
+
import { Image as ImageIcon } from "lucide-react";
|
|
167
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
168
|
+
var schema2 = z2.object({
|
|
169
|
+
type: z2.literal("media"),
|
|
170
|
+
content: z2.object({
|
|
1218
171
|
ref: SingleMediaReferenceSchema,
|
|
1219
172
|
link: LinkValueSchema.optional(),
|
|
1220
|
-
dodont:
|
|
173
|
+
dodont: z2.enum(["do", "dont"]).optional()
|
|
1221
174
|
}),
|
|
1222
|
-
options:
|
|
1223
|
-
square:
|
|
1224
|
-
showCaption:
|
|
1225
|
-
border:
|
|
1226
|
-
objectFit:
|
|
175
|
+
options: z2.object({
|
|
176
|
+
square: z2.boolean().optional(),
|
|
177
|
+
showCaption: z2.boolean().optional(),
|
|
178
|
+
border: z2.boolean().optional(),
|
|
179
|
+
objectFit: z2.enum(["cover", "contain"]).optional()
|
|
1227
180
|
}).default({})
|
|
1228
181
|
});
|
|
1229
182
|
var Media_default = defineSection({
|
|
1230
183
|
type: "media",
|
|
1231
184
|
label: "Media",
|
|
1232
|
-
icon: /* @__PURE__ */
|
|
1233
|
-
schema:
|
|
1234
|
-
component: ({ content, options, onChange }) => /* @__PURE__ */
|
|
185
|
+
icon: /* @__PURE__ */ jsx6(ImageIcon, { size: 18 }),
|
|
186
|
+
schema: schema2,
|
|
187
|
+
component: ({ content, options, onChange }) => /* @__PURE__ */ jsx6(
|
|
1235
188
|
MediaBlock,
|
|
1236
189
|
{
|
|
1237
190
|
refValue: content.content.ref,
|
|
@@ -1285,19 +238,19 @@ var Media_default = defineSection({
|
|
|
1285
238
|
});
|
|
1286
239
|
|
|
1287
240
|
// src/components/sections/Button/index.tsx
|
|
1288
|
-
import { z as
|
|
241
|
+
import { z as z3 } from "zod";
|
|
1289
242
|
import { RectangleHorizontal } from "lucide-react";
|
|
1290
243
|
|
|
1291
244
|
// src/components/sections/Button/CTAButton.tsx
|
|
1292
245
|
import { Download } from "lucide-react";
|
|
1293
|
-
import { jsx as
|
|
1294
|
-
function
|
|
246
|
+
import { jsx as jsx7, jsxs } from "react/jsx-runtime";
|
|
247
|
+
function Button({ text, link, download, onChange }) {
|
|
1295
248
|
const base = "inline-block rounded-md px-6 py-3 font-bold transition-colors";
|
|
1296
249
|
const variant = "border-2 border-primary text-primary hover:bg-primary hover:text-primary-contrast";
|
|
1297
250
|
if (onChange) {
|
|
1298
|
-
return /* @__PURE__ */
|
|
1299
|
-
download && /* @__PURE__ */
|
|
1300
|
-
/* @__PURE__ */
|
|
251
|
+
return /* @__PURE__ */ jsxs("span", { className: cn(base, variant, "inline-flex items-center gap-2"), children: [
|
|
252
|
+
download && /* @__PURE__ */ jsx7(Download, { size: 16, className: "shrink-0" }),
|
|
253
|
+
/* @__PURE__ */ jsx7(
|
|
1301
254
|
EditablePlainText,
|
|
1302
255
|
{
|
|
1303
256
|
tag: "span",
|
|
@@ -1312,7 +265,7 @@ function Button3({ text, link, download, onChange }) {
|
|
|
1312
265
|
const href = link && link.kind === "external" ? link.href : "";
|
|
1313
266
|
const target = link?.target;
|
|
1314
267
|
if (href) {
|
|
1315
|
-
return /* @__PURE__ */
|
|
268
|
+
return /* @__PURE__ */ jsxs(
|
|
1316
269
|
"a",
|
|
1317
270
|
{
|
|
1318
271
|
href,
|
|
@@ -1320,488 +273,63 @@ function Button3({ text, link, download, onChange }) {
|
|
|
1320
273
|
download: download ? "" : void 0,
|
|
1321
274
|
className: cn(base, variant, download && "inline-flex items-center gap-2"),
|
|
1322
275
|
children: [
|
|
1323
|
-
download && /* @__PURE__ */
|
|
276
|
+
download && /* @__PURE__ */ jsx7(Download, { size: 16, className: "shrink-0" }),
|
|
1324
277
|
text
|
|
1325
278
|
]
|
|
1326
279
|
}
|
|
1327
280
|
);
|
|
1328
281
|
}
|
|
1329
|
-
return /* @__PURE__ */
|
|
282
|
+
return /* @__PURE__ */ jsx7("button", { className: cn("cursor-pointer", base, variant), children: text });
|
|
1330
283
|
}
|
|
1331
284
|
|
|
1332
285
|
// src/components/sections/Button/index.tsx
|
|
1333
|
-
import { jsx as
|
|
1334
|
-
var
|
|
1335
|
-
type:
|
|
1336
|
-
content:
|
|
1337
|
-
text:
|
|
286
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
287
|
+
var schema3 = z3.object({
|
|
288
|
+
type: z3.literal("button"),
|
|
289
|
+
content: z3.object({
|
|
290
|
+
text: z3.string(),
|
|
1338
291
|
link: LinkValueSchema.optional(),
|
|
1339
|
-
download:
|
|
292
|
+
download: z3.boolean().optional()
|
|
1340
293
|
})
|
|
1341
294
|
});
|
|
1342
295
|
var Button_default = defineSection({
|
|
1343
296
|
type: "button",
|
|
1344
297
|
label: "Button",
|
|
1345
|
-
icon: /* @__PURE__ */
|
|
1346
|
-
schema:
|
|
1347
|
-
component: ({ content, onChange }) => /* @__PURE__ */
|
|
1348
|
-
|
|
298
|
+
icon: /* @__PURE__ */ jsx8(RectangleHorizontal, { size: 18 }),
|
|
299
|
+
schema: schema3,
|
|
300
|
+
component: ({ content, onChange }) => /* @__PURE__ */ jsx8(
|
|
301
|
+
Button,
|
|
1349
302
|
{
|
|
1350
303
|
text: content.content.text,
|
|
1351
304
|
link: content.content.link,
|
|
1352
|
-
download: content.content.download,
|
|
1353
|
-
onChange: onChange ? (c) => onChange(c) : void 0
|
|
1354
|
-
}
|
|
1355
|
-
),
|
|
1356
|
-
defaults: () => ({ type: "button", content: { text: "Button" } }),
|
|
1357
|
-
getLabel: (content) => content.content.text,
|
|
1358
|
-
settings: {
|
|
1359
|
-
link: { type: "link", label: "Link", default: DEFAULT_LINK, target: "content" },
|
|
1360
|
-
download: { type: "checkbox", label: "Download link", default: false, target: "content" }
|
|
1361
|
-
}
|
|
1362
|
-
});
|
|
1363
|
-
|
|
1364
|
-
// src/components/sections/Colors/index.tsx
|
|
1365
|
-
import { z as z7 } from "zod";
|
|
1366
|
-
import { Palette } from "lucide-react";
|
|
1367
|
-
|
|
1368
|
-
// src/components/brandguide/Colors.tsx
|
|
1369
|
-
import { useState as useState9, useEffect as useEffect7 } from "react";
|
|
1370
|
-
import { Eye, EyeOff } from "lucide-react";
|
|
1371
|
-
|
|
1372
|
-
// src/lib/container-grid.ts
|
|
1373
|
-
var MAX_CONTAINER_COLUMNS = 6;
|
|
1374
|
-
var containerGridClass = {
|
|
1375
|
-
1: "grid-cols-1",
|
|
1376
|
-
2: "grid-cols-1 @sm:grid-cols-2",
|
|
1377
|
-
3: "grid-cols-1 @sm:grid-cols-2 @lg:grid-cols-3",
|
|
1378
|
-
4: "grid-cols-1 @xs:grid-cols-2 @lg:grid-cols-4",
|
|
1379
|
-
5: "grid-cols-1 @xs:grid-cols-2 @md:grid-cols-3 @xl:grid-cols-5",
|
|
1380
|
-
6: "grid-cols-1 @xs:grid-cols-2 @md:grid-cols-3 @2xl:grid-cols-6"
|
|
1381
|
-
};
|
|
1382
|
-
var colSpanClass = {
|
|
1383
|
-
1: { 1: "" },
|
|
1384
|
-
2: { 1: "", 2: "col-span-1 @sm:col-span-2" },
|
|
1385
|
-
3: { 1: "", 2: "col-span-1 @sm:col-span-2", 3: "col-span-1 @sm:col-span-2 @lg:col-span-3" },
|
|
1386
|
-
4: { 1: "", 2: "col-span-1 @xs:col-span-2", 3: "col-span-1 @xs:col-span-2 @lg:col-span-3", 4: "col-span-1 @xs:col-span-2 @lg:col-span-4" },
|
|
1387
|
-
5: { 1: "", 2: "col-span-1 @xs:col-span-2", 3: "col-span-1 @xs:col-span-2 @md:col-span-3", 4: "col-span-1 @xs:col-span-2 @md:col-span-3 @xl:col-span-4", 5: "col-span-1 @xs:col-span-2 @md:col-span-3 @xl:col-span-5" },
|
|
1388
|
-
6: { 1: "", 2: "col-span-1 @xs:col-span-2", 3: "col-span-1 @xs:col-span-2 @md:col-span-3", 4: "col-span-1 @xs:col-span-2 @md:col-span-3 @2xl:col-span-4", 5: "col-span-1 @xs:col-span-2 @md:col-span-3 @2xl:col-span-5", 6: "col-span-1 @xs:col-span-2 @md:col-span-3 @2xl:col-span-6" }
|
|
1389
|
-
};
|
|
1390
|
-
var spacerHiddenClass = {
|
|
1391
|
-
1: "hidden",
|
|
1392
|
-
2: "hidden @sm:block",
|
|
1393
|
-
3: "hidden @sm:block",
|
|
1394
|
-
4: "hidden @xs:block",
|
|
1395
|
-
5: "hidden @xs:block",
|
|
1396
|
-
6: "hidden @xs:block"
|
|
1397
|
-
};
|
|
1398
|
-
|
|
1399
|
-
// src/components/primitives/EditableGrid.tsx
|
|
1400
|
-
import { useRef as useRef6, useEffect as useEffect6, useState as useState7 } from "react";
|
|
1401
|
-
import { ImageIcon as ImageIcon3 } from "lucide-react";
|
|
1402
|
-
|
|
1403
|
-
// src/components/shared/icons.tsx
|
|
1404
|
-
import { GripVertical, Plus, Trash2, X as X2, Settings } from "lucide-react";
|
|
1405
|
-
import { GripVertical as GripVertical2, Plus as Plus2, Trash2 as Trash22, X as X3, Settings as Settings2 } from "lucide-react";
|
|
1406
|
-
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1407
|
-
function DragHandle({ size = 16 }) {
|
|
1408
|
-
return /* @__PURE__ */ jsx17(GripVertical, { size });
|
|
1409
|
-
}
|
|
1410
|
-
function AddIcon({ size = 14 }) {
|
|
1411
|
-
return /* @__PURE__ */ jsx17(Plus, { size });
|
|
1412
|
-
}
|
|
1413
|
-
function DeleteIcon({ size = 14 }) {
|
|
1414
|
-
return /* @__PURE__ */ jsx17(Trash2, { size });
|
|
1415
|
-
}
|
|
1416
|
-
function SettingsIcon({ size = 14 }) {
|
|
1417
|
-
return /* @__PURE__ */ jsx17(Settings, { size });
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
// src/components/shared/IconButton.tsx
|
|
1421
|
-
import { forwardRef as forwardRef2 } from "react";
|
|
1422
|
-
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
1423
|
-
var sizeClasses = {
|
|
1424
|
-
sm: "h-chrome-sm w-chrome-sm",
|
|
1425
|
-
md: "h-chrome-md w-chrome-md",
|
|
1426
|
-
lg: "h-chrome-lg w-chrome-lg"
|
|
1427
|
-
};
|
|
1428
|
-
var intentClasses = {
|
|
1429
|
-
default: "text-base-contrast-light hover:text-base-contrast",
|
|
1430
|
-
destructive: "text-destructive hover:text-destructive-hover",
|
|
1431
|
-
primary: "text-primary/60 hover:text-primary"
|
|
1432
|
-
};
|
|
1433
|
-
var IconButton = forwardRef2(
|
|
1434
|
-
function IconButton2({ icon, label, size = "md", intent = "default", className, ...rest }, ref) {
|
|
1435
|
-
return /* @__PURE__ */ jsx18(
|
|
1436
|
-
"button",
|
|
1437
|
-
{
|
|
1438
|
-
ref,
|
|
1439
|
-
type: "button",
|
|
1440
|
-
className: cn(
|
|
1441
|
-
"cursor-pointer flex items-center justify-center rounded transition-colors",
|
|
1442
|
-
sizeClasses[size],
|
|
1443
|
-
intentClasses[intent],
|
|
1444
|
-
className
|
|
1445
|
-
),
|
|
1446
|
-
"aria-label": label,
|
|
1447
|
-
...rest,
|
|
1448
|
-
children: icon
|
|
1449
|
-
}
|
|
1450
|
-
);
|
|
1451
|
-
}
|
|
1452
|
-
);
|
|
1453
|
-
|
|
1454
|
-
// src/components/primitives/useEditableCollection.ts
|
|
1455
|
-
import { useState as useState6, useCallback as useCallback5, useRef as useRef5, useEffect as useEffect5 } from "react";
|
|
1456
|
-
var nextId = 0;
|
|
1457
|
-
function uid() {
|
|
1458
|
-
return typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `_id_${nextId++}_${Date.now()}`;
|
|
1459
|
-
}
|
|
1460
|
-
function wrapItems(items) {
|
|
1461
|
-
return items.map((data) => ({ id: uid(), data }));
|
|
1462
|
-
}
|
|
1463
|
-
function useEditableCollection({
|
|
1464
|
-
items,
|
|
1465
|
-
onChange,
|
|
1466
|
-
createItem
|
|
1467
|
-
}) {
|
|
1468
|
-
const [wrappedItems, setWrappedItems] = useState6(
|
|
1469
|
-
() => wrapItems(items)
|
|
1470
|
-
);
|
|
1471
|
-
const prevItemsRef = useRef5(items);
|
|
1472
|
-
useEffect5(() => {
|
|
1473
|
-
if (items === prevItemsRef.current) return;
|
|
1474
|
-
prevItemsRef.current = items;
|
|
1475
|
-
setWrappedItems((prev) => {
|
|
1476
|
-
return items.map((data, i) => {
|
|
1477
|
-
if (i < prev.length) {
|
|
1478
|
-
return { id: prev[i].id, data };
|
|
1479
|
-
}
|
|
1480
|
-
return { id: uid(), data };
|
|
1481
|
-
});
|
|
1482
|
-
});
|
|
1483
|
-
}, [items]);
|
|
1484
|
-
const onReorder = useCallback5(
|
|
1485
|
-
(fromIndex, toIndex) => {
|
|
1486
|
-
setWrappedItems((prev) => {
|
|
1487
|
-
const next = [...prev];
|
|
1488
|
-
const [moved] = next.splice(fromIndex, 1);
|
|
1489
|
-
next.splice(toIndex, 0, moved);
|
|
1490
|
-
onChange(next.map((w) => w.data));
|
|
1491
|
-
return next;
|
|
1492
|
-
});
|
|
1493
|
-
},
|
|
1494
|
-
[onChange]
|
|
1495
|
-
);
|
|
1496
|
-
const onAdd = useCallback5(() => {
|
|
1497
|
-
const newItem = createItem();
|
|
1498
|
-
setWrappedItems((prev) => {
|
|
1499
|
-
const next = [...prev, { id: uid(), data: newItem }];
|
|
1500
|
-
onChange(next.map((w) => w.data));
|
|
1501
|
-
return next;
|
|
1502
|
-
});
|
|
1503
|
-
}, [createItem, onChange]);
|
|
1504
|
-
const onInsert = useCallback5(
|
|
1505
|
-
(index) => {
|
|
1506
|
-
const newItem = createItem();
|
|
1507
|
-
setWrappedItems((prev) => {
|
|
1508
|
-
const next = [...prev];
|
|
1509
|
-
next.splice(index, 0, { id: uid(), data: newItem });
|
|
1510
|
-
onChange(next.map((w) => w.data));
|
|
1511
|
-
return next;
|
|
1512
|
-
});
|
|
1513
|
-
},
|
|
1514
|
-
[createItem, onChange]
|
|
1515
|
-
);
|
|
1516
|
-
const onRemove = useCallback5(
|
|
1517
|
-
(id) => {
|
|
1518
|
-
setWrappedItems((prev) => {
|
|
1519
|
-
const next = prev.filter((w) => w.id !== id);
|
|
1520
|
-
onChange(next.map((w) => w.data));
|
|
1521
|
-
return next;
|
|
1522
|
-
});
|
|
1523
|
-
},
|
|
1524
|
-
[onChange]
|
|
1525
|
-
);
|
|
1526
|
-
return { wrappedItems, onReorder, onAdd, onInsert, onRemove };
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
// src/components/primitives/EditableGrid.tsx
|
|
1530
|
-
import { jsx as jsx19, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1531
|
-
function EditableGrid({
|
|
1532
|
-
items,
|
|
1533
|
-
columns,
|
|
1534
|
-
onChange,
|
|
1535
|
-
createItem,
|
|
1536
|
-
isEditMode,
|
|
1537
|
-
renderItem,
|
|
1538
|
-
onItemSettings,
|
|
1539
|
-
onItemImageClick,
|
|
1540
|
-
chromeTopClass,
|
|
1541
|
-
className
|
|
1542
|
-
}) {
|
|
1543
|
-
const { wrappedItems, onReorder, onAdd, onInsert, onRemove } = useEditableCollection({
|
|
1544
|
-
items,
|
|
1545
|
-
onChange,
|
|
1546
|
-
createItem
|
|
1547
|
-
});
|
|
1548
|
-
const [dragState, setDragState] = useState7({ sourceId: null, closestEdge: null });
|
|
1549
|
-
const [isDragging, setIsDragging] = useState7(false);
|
|
1550
|
-
useEffect6(() => {
|
|
1551
|
-
let cleanup;
|
|
1552
|
-
let cancelled = false;
|
|
1553
|
-
import("../../adapter-HH47ZPGM.js").then(({ monitorForElements }) => {
|
|
1554
|
-
if (cancelled) return;
|
|
1555
|
-
cleanup = monitorForElements({
|
|
1556
|
-
onDragStart: ({ source }) => {
|
|
1557
|
-
if (source.data.dragType === "grid-cell") setIsDragging(true);
|
|
1558
|
-
},
|
|
1559
|
-
onDrop: ({ source }) => {
|
|
1560
|
-
if (source.data.dragType === "grid-cell") setIsDragging(false);
|
|
1561
|
-
}
|
|
1562
|
-
});
|
|
1563
|
-
});
|
|
1564
|
-
return () => {
|
|
1565
|
-
cancelled = true;
|
|
1566
|
-
cleanup?.();
|
|
1567
|
-
};
|
|
1568
|
-
}, []);
|
|
1569
|
-
if (!isEditMode) {
|
|
1570
|
-
return /* @__PURE__ */ jsx19("div", { className: "@container", children: /* @__PURE__ */ jsx19("div", { className: cn("grid gap-4", containerGridClass[columns] || containerGridClass[1], className), children: wrappedItems.map((wrapped, index) => /* @__PURE__ */ jsx19("div", { children: renderItem(wrapped.data, { isEditMode: false, index }) }, wrapped.id)) }) });
|
|
1571
|
-
}
|
|
1572
|
-
return /* @__PURE__ */ jsx19("div", { className: "@container", children: /* @__PURE__ */ jsxs8("div", { className: cn("group/grid relative grid gap-4", containerGridClass[columns] || containerGridClass[1], className), children: [
|
|
1573
|
-
wrappedItems.map((wrapped, index) => /* @__PURE__ */ jsx19(
|
|
1574
|
-
GridCell,
|
|
1575
|
-
{
|
|
1576
|
-
id: wrapped.id,
|
|
1577
|
-
index,
|
|
1578
|
-
isLast: index === wrappedItems.length - 1,
|
|
1579
|
-
isDragging,
|
|
1580
|
-
onReorder,
|
|
1581
|
-
onRemove,
|
|
1582
|
-
onInsert,
|
|
1583
|
-
onSettings: onItemSettings ? () => onItemSettings(index) : void 0,
|
|
1584
|
-
onImageClick: onItemImageClick ? () => onItemImageClick(index) : void 0,
|
|
1585
|
-
chromeTopClass,
|
|
1586
|
-
dragState,
|
|
1587
|
-
setDragState,
|
|
1588
|
-
children: renderItem(wrapped.data, { isEditMode: true, index })
|
|
1589
|
-
},
|
|
1590
|
-
wrapped.id
|
|
1591
|
-
)),
|
|
1592
|
-
/* @__PURE__ */ jsx19(
|
|
1593
|
-
IconButton,
|
|
1594
|
-
{
|
|
1595
|
-
icon: /* @__PURE__ */ jsx19(AddIcon, { size: 16 }),
|
|
1596
|
-
label: "Add item",
|
|
1597
|
-
size: "lg",
|
|
1598
|
-
intent: "primary",
|
|
1599
|
-
onClick: onAdd,
|
|
1600
|
-
className: "absolute -bottom-6 left-1/2 z-20 -translate-x-1/2 rounded-full border border-base-200 bg-base opacity-0 transition-opacity group-hover/grid:opacity-100"
|
|
1601
|
-
}
|
|
1602
|
-
)
|
|
1603
|
-
] }) });
|
|
1604
|
-
}
|
|
1605
|
-
function GridCell({
|
|
1606
|
-
id,
|
|
1607
|
-
index,
|
|
1608
|
-
isLast,
|
|
1609
|
-
isDragging,
|
|
1610
|
-
onReorder,
|
|
1611
|
-
onRemove,
|
|
1612
|
-
onInsert,
|
|
1613
|
-
onSettings,
|
|
1614
|
-
onImageClick,
|
|
1615
|
-
chromeTopClass,
|
|
1616
|
-
dragState,
|
|
1617
|
-
setDragState,
|
|
1618
|
-
children
|
|
1619
|
-
}) {
|
|
1620
|
-
const cellRef = useRef6(null);
|
|
1621
|
-
const handleRef = useRef6(null);
|
|
1622
|
-
useEffect6(() => {
|
|
1623
|
-
const cell = cellRef.current;
|
|
1624
|
-
const handle = handleRef.current;
|
|
1625
|
-
if (!cell || !handle) return;
|
|
1626
|
-
let cleanup;
|
|
1627
|
-
let cancelled = false;
|
|
1628
|
-
Promise.all([
|
|
1629
|
-
import("../../adapter-HH47ZPGM.js"),
|
|
1630
|
-
import("../../closest-edge-EBOXL3YW.js")
|
|
1631
|
-
]).then(([{ draggable, dropTargetForElements }, { attachClosestEdge, extractClosestEdge }]) => {
|
|
1632
|
-
if (cancelled) return;
|
|
1633
|
-
const cleanupDraggable = draggable({
|
|
1634
|
-
element: handle,
|
|
1635
|
-
getInitialData: () => ({ dragType: "grid-cell", id, index }),
|
|
1636
|
-
onDragStart: () => setDragState({ sourceId: id, closestEdge: null }),
|
|
1637
|
-
onDrop: () => setDragState({ sourceId: null, closestEdge: null })
|
|
1638
|
-
});
|
|
1639
|
-
const cleanupDropTarget = dropTargetForElements({
|
|
1640
|
-
element: cell,
|
|
1641
|
-
canDrop: ({ source }) => source.data.dragType === "grid-cell",
|
|
1642
|
-
getData: ({ input, element }) => attachClosestEdge(
|
|
1643
|
-
{ id, index },
|
|
1644
|
-
{ input, element, allowedEdges: ["left", "right"] }
|
|
1645
|
-
),
|
|
1646
|
-
onDragEnter: ({ self }) => {
|
|
1647
|
-
const edge = extractClosestEdge(self.data);
|
|
1648
|
-
if (edge) setDragState((prev) => ({ ...prev, closestEdge: { id, edge } }));
|
|
1649
|
-
},
|
|
1650
|
-
onDrag: ({ self }) => {
|
|
1651
|
-
const edge = extractClosestEdge(self.data);
|
|
1652
|
-
if (edge) setDragState((prev) => ({ ...prev, closestEdge: { id, edge } }));
|
|
1653
|
-
},
|
|
1654
|
-
onDragLeave: () => {
|
|
1655
|
-
setDragState((prev) => prev.closestEdge?.id === id ? { ...prev, closestEdge: null } : prev);
|
|
1656
|
-
},
|
|
1657
|
-
onDrop: ({ source, self }) => {
|
|
1658
|
-
const fromIndex = source.data.index;
|
|
1659
|
-
const edge = extractClosestEdge(self.data);
|
|
1660
|
-
let toIndex = index;
|
|
1661
|
-
if (edge === "right") toIndex = index + 1;
|
|
1662
|
-
if (fromIndex < toIndex) toIndex--;
|
|
1663
|
-
if (fromIndex !== toIndex) {
|
|
1664
|
-
onReorder(fromIndex, toIndex);
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
});
|
|
1668
|
-
cleanup = () => {
|
|
1669
|
-
cleanupDraggable();
|
|
1670
|
-
cleanupDropTarget();
|
|
1671
|
-
};
|
|
1672
|
-
});
|
|
1673
|
-
return () => {
|
|
1674
|
-
cancelled = true;
|
|
1675
|
-
cleanup?.();
|
|
1676
|
-
};
|
|
1677
|
-
}, [id, index, onReorder, setDragState]);
|
|
1678
|
-
const isCellDragging = dragState.sourceId === id;
|
|
1679
|
-
const showLeftEdge = dragState.closestEdge?.id === id && dragState.closestEdge.edge === "left" && dragState.sourceId !== id;
|
|
1680
|
-
const showRightEdge = dragState.closestEdge?.id === id && dragState.closestEdge.edge === "right" && dragState.sourceId !== id;
|
|
1681
|
-
return /* @__PURE__ */ jsxs8(
|
|
1682
|
-
"div",
|
|
1683
|
-
{
|
|
1684
|
-
ref: cellRef,
|
|
1685
|
-
className: cn(
|
|
1686
|
-
"group/cell relative",
|
|
1687
|
-
isCellDragging && "opacity-50"
|
|
1688
|
-
),
|
|
1689
|
-
children: [
|
|
1690
|
-
showLeftEdge && /* @__PURE__ */ jsx19("div", { className: "absolute top-0 bottom-0 left-0 z-10 w-0.5 -translate-x-2 bg-primary" }),
|
|
1691
|
-
showRightEdge && /* @__PURE__ */ jsx19("div", { className: "absolute top-0 right-0 bottom-0 z-10 w-0.5 translate-x-2 bg-primary" }),
|
|
1692
|
-
!isDragging && !isLast && /* @__PURE__ */ jsx19(
|
|
1693
|
-
IconButton,
|
|
1694
|
-
{
|
|
1695
|
-
icon: /* @__PURE__ */ jsx19(AddIcon, { size: 12 }),
|
|
1696
|
-
label: "Insert item",
|
|
1697
|
-
size: "sm",
|
|
1698
|
-
intent: "primary",
|
|
1699
|
-
onClick: () => onInsert(index + 1),
|
|
1700
|
-
className: "absolute top-1/2 -right-2 z-20 -translate-y-1/2 translate-x-1/2 rounded-full border border-base-200 bg-base opacity-0 group-hover/cell:opacity-100"
|
|
1701
|
-
}
|
|
1702
|
-
),
|
|
1703
|
-
/* @__PURE__ */ jsx19(
|
|
1704
|
-
IconButton,
|
|
1705
|
-
{
|
|
1706
|
-
ref: handleRef,
|
|
1707
|
-
icon: /* @__PURE__ */ jsx19(DragHandle, { size: 16 }),
|
|
1708
|
-
label: "Drag to reorder",
|
|
1709
|
-
className: cn("absolute left-1.5 z-10 cursor-grab bg-base/80 opacity-0 shadow-sm group-hover/cell:opacity-100 no-hover:opacity-100", chromeTopClass || "top-1.5"),
|
|
1710
|
-
tabIndex: -1
|
|
1711
|
-
}
|
|
1712
|
-
),
|
|
1713
|
-
/* @__PURE__ */ jsxs8("div", { className: cn("absolute right-1.5 z-10 flex items-center gap-1 opacity-0 group-hover/cell:opacity-100 no-hover:opacity-100", chromeTopClass || "top-1.5"), children: [
|
|
1714
|
-
onImageClick && /* @__PURE__ */ jsx19(
|
|
1715
|
-
IconButton,
|
|
1716
|
-
{
|
|
1717
|
-
icon: /* @__PURE__ */ jsx19(ImageIcon3, { size: 16 }),
|
|
1718
|
-
label: "Change image",
|
|
1719
|
-
onClick: onImageClick,
|
|
1720
|
-
className: "bg-base/80 shadow-sm"
|
|
1721
|
-
}
|
|
1722
|
-
),
|
|
1723
|
-
onSettings && /* @__PURE__ */ jsx19(
|
|
1724
|
-
IconButton,
|
|
1725
|
-
{
|
|
1726
|
-
icon: /* @__PURE__ */ jsx19(SettingsIcon, { size: 16 }),
|
|
1727
|
-
label: "Item settings",
|
|
1728
|
-
onClick: onSettings,
|
|
1729
|
-
className: "bg-base/80 shadow-sm"
|
|
1730
|
-
}
|
|
1731
|
-
),
|
|
1732
|
-
/* @__PURE__ */ jsx19(
|
|
1733
|
-
IconButton,
|
|
1734
|
-
{
|
|
1735
|
-
icon: /* @__PURE__ */ jsx19(DeleteIcon, { size: 16 }),
|
|
1736
|
-
label: "Delete item",
|
|
1737
|
-
intent: "destructive",
|
|
1738
|
-
onClick: () => onRemove(id),
|
|
1739
|
-
className: "bg-base/80 shadow-sm"
|
|
1740
|
-
}
|
|
1741
|
-
)
|
|
1742
|
-
] }),
|
|
1743
|
-
children
|
|
1744
|
-
]
|
|
1745
|
-
}
|
|
1746
|
-
);
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
// src/components/brandguide/ColorSwatchSettings.tsx
|
|
1750
|
-
import { useState as useState8 } from "react";
|
|
1751
|
-
|
|
1752
|
-
// src/components/shared/Input.tsx
|
|
1753
|
-
import { forwardRef as forwardRef3, useId } from "react";
|
|
1754
|
-
|
|
1755
|
-
// src/components/shared/FormLabel.tsx
|
|
1756
|
-
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
1757
|
-
function FormLabel({ htmlFor, children, className }) {
|
|
1758
|
-
return /* @__PURE__ */ jsx20(
|
|
1759
|
-
"label",
|
|
1760
|
-
{
|
|
1761
|
-
htmlFor,
|
|
1762
|
-
className: cn("mb-1.5 block text-sm font-medium text-base-contrast", className),
|
|
1763
|
-
children
|
|
305
|
+
download: content.content.download,
|
|
306
|
+
onChange: onChange ? (c) => onChange(c) : void 0
|
|
1764
307
|
}
|
|
1765
|
-
)
|
|
1766
|
-
}
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
const errorId = `${id}-error`;
|
|
1773
|
-
return /* @__PURE__ */ jsxs9("div", { className, children: [
|
|
1774
|
-
/* @__PURE__ */ jsx21(FormLabel, { htmlFor: id, children: label }),
|
|
1775
|
-
/* @__PURE__ */ jsx21(
|
|
1776
|
-
"input",
|
|
1777
|
-
{
|
|
1778
|
-
ref,
|
|
1779
|
-
id,
|
|
1780
|
-
type,
|
|
1781
|
-
value,
|
|
1782
|
-
onChange: (e) => onChange(e.target.value),
|
|
1783
|
-
disabled,
|
|
1784
|
-
"aria-invalid": error ? true : void 0,
|
|
1785
|
-
"aria-describedby": error ? errorId : void 0,
|
|
1786
|
-
className: cn(
|
|
1787
|
-
"w-full rounded border bg-base px-3 py-2 text-sm text-base-contrast focus:outline-none focus:ring-1",
|
|
1788
|
-
error ? "border-red-600 focus:border-red-600 focus:ring-red-600" : "border-base-200 focus:border-base-contrast focus:ring-base-contrast",
|
|
1789
|
-
disabled && "cursor-not-allowed opacity-50"
|
|
1790
|
-
),
|
|
1791
|
-
...rest
|
|
1792
|
-
}
|
|
1793
|
-
),
|
|
1794
|
-
error && /* @__PURE__ */ jsx21("p", { id: errorId, className: "mt-1 text-xs text-red-600", children: error })
|
|
1795
|
-
] });
|
|
308
|
+
),
|
|
309
|
+
defaults: () => ({ type: "button", content: { text: "Button" } }),
|
|
310
|
+
getLabel: (content) => content.content.text,
|
|
311
|
+
settings: {
|
|
312
|
+
link: { type: "link", label: "Link", default: DEFAULT_LINK, target: "content" },
|
|
313
|
+
download: { type: "checkbox", label: "Download link", default: false, target: "content" }
|
|
314
|
+
}
|
|
1796
315
|
});
|
|
1797
316
|
|
|
317
|
+
// src/components/sections/Colors/index.tsx
|
|
318
|
+
import { z as z4 } from "zod";
|
|
319
|
+
import { Palette } from "lucide-react";
|
|
320
|
+
|
|
321
|
+
// src/components/brandguide/Colors.tsx
|
|
322
|
+
import { useState as useState2, useEffect } from "react";
|
|
323
|
+
import { Eye, EyeOff } from "lucide-react";
|
|
324
|
+
|
|
1798
325
|
// src/components/brandguide/ColorSwatchSettings.tsx
|
|
1799
|
-
import {
|
|
326
|
+
import { useState } from "react";
|
|
327
|
+
import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1800
328
|
function mergeSpaces(spaces) {
|
|
1801
329
|
return Object.assign({}, ...spaces);
|
|
1802
330
|
}
|
|
1803
331
|
function ColorSwatchSettings({ color, onChange }) {
|
|
1804
|
-
const [localColor, setLocalColor] =
|
|
332
|
+
const [localColor, setLocalColor] = useState(() => ({
|
|
1805
333
|
...color,
|
|
1806
334
|
spaces: [mergeSpaces(color.spaces)]
|
|
1807
335
|
}));
|
|
@@ -1814,8 +342,8 @@ function ColorSwatchSettings({ color, onChange }) {
|
|
|
1814
342
|
const newSpace = { ...space, [key]: value || void 0 };
|
|
1815
343
|
update({ ...localColor, spaces: [newSpace] });
|
|
1816
344
|
};
|
|
1817
|
-
return /* @__PURE__ */
|
|
1818
|
-
/* @__PURE__ */
|
|
345
|
+
return /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
|
|
346
|
+
/* @__PURE__ */ jsx9(
|
|
1819
347
|
Input,
|
|
1820
348
|
{
|
|
1821
349
|
label: "Name",
|
|
@@ -1823,7 +351,7 @@ function ColorSwatchSettings({ color, onChange }) {
|
|
|
1823
351
|
onChange: (name) => update({ ...localColor, name })
|
|
1824
352
|
}
|
|
1825
353
|
),
|
|
1826
|
-
["hex", "rgb", "cmyk", "pantone"].map((key) => /* @__PURE__ */
|
|
354
|
+
["hex", "rgb", "cmyk", "pantone"].map((key) => /* @__PURE__ */ jsx9(
|
|
1827
355
|
Input,
|
|
1828
356
|
{
|
|
1829
357
|
label: key.toUpperCase(),
|
|
@@ -1836,7 +364,7 @@ function ColorSwatchSettings({ color, onChange }) {
|
|
|
1836
364
|
}
|
|
1837
365
|
|
|
1838
366
|
// src/components/brandguide/Colors.tsx
|
|
1839
|
-
import { jsx as
|
|
367
|
+
import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1840
368
|
function getContrastClass(hex) {
|
|
1841
369
|
if (!hex) return "text-white";
|
|
1842
370
|
const h = hex.replace("#", "");
|
|
@@ -1861,7 +389,7 @@ function buildContent(colors, options) {
|
|
|
1861
389
|
}
|
|
1862
390
|
function Colors({ colors, columns = 3, label, collapsing, showLabel = true, onChange, openModal }) {
|
|
1863
391
|
if (onChange && openModal) {
|
|
1864
|
-
return /* @__PURE__ */
|
|
392
|
+
return /* @__PURE__ */ jsx10(
|
|
1865
393
|
ColorsEditable,
|
|
1866
394
|
{
|
|
1867
395
|
colors,
|
|
@@ -1874,7 +402,7 @@ function Colors({ colors, columns = 3, label, collapsing, showLabel = true, onCh
|
|
|
1874
402
|
}
|
|
1875
403
|
);
|
|
1876
404
|
}
|
|
1877
|
-
return /* @__PURE__ */
|
|
405
|
+
return /* @__PURE__ */ jsx10(ColorsView, { colors, columns, label, collapsing, showLabel });
|
|
1878
406
|
}
|
|
1879
407
|
function ColorsView({
|
|
1880
408
|
colors,
|
|
@@ -1883,8 +411,8 @@ function ColorsView({
|
|
|
1883
411
|
collapsing,
|
|
1884
412
|
showLabel
|
|
1885
413
|
}) {
|
|
1886
|
-
const [expanded, setExpanded] =
|
|
1887
|
-
const [copiedIndex, setCopiedIndex] =
|
|
414
|
+
const [expanded, setExpanded] = useState2(!collapsing);
|
|
415
|
+
const [copiedIndex, setCopiedIndex] = useState2(null);
|
|
1888
416
|
const handleCopy = (value, colorIndex) => {
|
|
1889
417
|
if (navigator.clipboard?.writeText) {
|
|
1890
418
|
navigator.clipboard.writeText(value);
|
|
@@ -1901,37 +429,37 @@ function ColorsView({
|
|
|
1901
429
|
setCopiedIndex(colorIndex);
|
|
1902
430
|
setTimeout(() => setCopiedIndex(null), 1500);
|
|
1903
431
|
};
|
|
1904
|
-
return /* @__PURE__ */
|
|
1905
|
-
(showLabel && !!label || collapsing) && /* @__PURE__ */
|
|
1906
|
-
showLabel && !!label && /* @__PURE__ */
|
|
1907
|
-
collapsing && /* @__PURE__ */
|
|
432
|
+
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
433
|
+
(showLabel && !!label || collapsing) && /* @__PURE__ */ jsxs3("div", { className: "mb-4 flex items-center gap-2", children: [
|
|
434
|
+
showLabel && !!label && /* @__PURE__ */ jsx10("span", { className: "text-lg font-bold", children: label }),
|
|
435
|
+
collapsing && /* @__PURE__ */ jsxs3(
|
|
1908
436
|
"button",
|
|
1909
437
|
{
|
|
1910
438
|
onClick: () => setExpanded(!expanded),
|
|
1911
439
|
className: "cursor-pointer ml-auto flex items-center gap-1.5 text-sm text-base-contrast-light hover:text-base-contrast",
|
|
1912
440
|
children: [
|
|
1913
|
-
/* @__PURE__ */
|
|
1914
|
-
expanded ? /* @__PURE__ */
|
|
441
|
+
/* @__PURE__ */ jsx10("span", { children: expanded ? "Hide Details" : "Show Details" }),
|
|
442
|
+
expanded ? /* @__PURE__ */ jsx10(EyeOff, { size: 16 }) : /* @__PURE__ */ jsx10(Eye, { size: 16 })
|
|
1915
443
|
]
|
|
1916
444
|
}
|
|
1917
445
|
)
|
|
1918
446
|
] }),
|
|
1919
|
-
/* @__PURE__ */
|
|
447
|
+
/* @__PURE__ */ jsx10("div", { className: "@container", children: /* @__PURE__ */ jsx10("div", { className: cn("grid gap-4", containerGridClass[columns] || containerGridClass[3]), children: colors.map((color, i) => {
|
|
1920
448
|
const hex = color.spaces[0]?.hex;
|
|
1921
449
|
const contrast = getContrastClass(hex);
|
|
1922
|
-
return /* @__PURE__ */
|
|
1923
|
-
/* @__PURE__ */
|
|
1924
|
-
color.name && /* @__PURE__ */
|
|
1925
|
-
copiedIndex === i && /* @__PURE__ */
|
|
450
|
+
return /* @__PURE__ */ jsxs3("div", { className: "overflow-hidden rounded-md border border-base-200", children: [
|
|
451
|
+
/* @__PURE__ */ jsxs3("div", { className: cn("relative flex min-h-[80px] items-end p-3", contrast), style: { backgroundColor: hex || "#ccc" }, children: [
|
|
452
|
+
color.name && /* @__PURE__ */ jsx10("span", { className: "text-sm font-bold", children: color.name }),
|
|
453
|
+
copiedIndex === i && /* @__PURE__ */ jsx10("span", { className: cn(
|
|
1926
454
|
"absolute top-2 right-2 rounded-full px-2.5 py-0.5 text-xs font-medium",
|
|
1927
455
|
getContrastClass(hex) === "text-black" ? "bg-black/15 text-black" : "bg-white/25 text-white"
|
|
1928
456
|
), children: "Copied!" })
|
|
1929
457
|
] }),
|
|
1930
|
-
expanded && /* @__PURE__ */
|
|
458
|
+
expanded && /* @__PURE__ */ jsx10("div", { className: "space-y-1 bg-base-accent p-3 text-sm", children: color.spaces.map(
|
|
1931
459
|
(space, j) => Object.entries(space).map(
|
|
1932
|
-
([key, value]) => value ? /* @__PURE__ */
|
|
1933
|
-
/* @__PURE__ */
|
|
1934
|
-
/* @__PURE__ */
|
|
460
|
+
([key, value]) => value ? /* @__PURE__ */ jsxs3("button", { onClick: () => handleCopy(value, i), className: "cursor-pointer flex w-full justify-between hover:text-primary", children: [
|
|
461
|
+
/* @__PURE__ */ jsx10("span", { className: "font-medium uppercase", children: key }),
|
|
462
|
+
/* @__PURE__ */ jsx10("span", { children: value })
|
|
1935
463
|
] }, `${j}-${key}`) : null
|
|
1936
464
|
)
|
|
1937
465
|
) })
|
|
@@ -1948,24 +476,24 @@ function ColorsEditable({
|
|
|
1948
476
|
onChange,
|
|
1949
477
|
openModal
|
|
1950
478
|
}) {
|
|
1951
|
-
const [expanded, setExpanded] =
|
|
479
|
+
const [expanded, setExpanded] = useState2(!collapsing);
|
|
1952
480
|
const options = { label, columns, collapsing, showLabel };
|
|
1953
|
-
|
|
481
|
+
useEffect(() => {
|
|
1954
482
|
setExpanded(!collapsing);
|
|
1955
483
|
}, [collapsing]);
|
|
1956
484
|
const handleItemSettings = (index) => {
|
|
1957
485
|
const color = colors[index];
|
|
1958
486
|
openModal(
|
|
1959
487
|
"Color Settings",
|
|
1960
|
-
/* @__PURE__ */
|
|
488
|
+
/* @__PURE__ */ jsx10(ColorSwatchSettings, { color, onChange: (updated) => {
|
|
1961
489
|
const newColors = colors.map((c, i) => i === index ? updated : c);
|
|
1962
490
|
onChange(buildContent(newColors, options));
|
|
1963
491
|
} })
|
|
1964
492
|
);
|
|
1965
493
|
};
|
|
1966
|
-
return /* @__PURE__ */
|
|
1967
|
-
(showLabel && !!label || collapsing) && /* @__PURE__ */
|
|
1968
|
-
showLabel && !!label && /* @__PURE__ */
|
|
494
|
+
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
495
|
+
(showLabel && !!label || collapsing) && /* @__PURE__ */ jsxs3("div", { className: "mb-4 flex items-center gap-2", children: [
|
|
496
|
+
showLabel && !!label && /* @__PURE__ */ jsx10(
|
|
1969
497
|
EditablePlainText,
|
|
1970
498
|
{
|
|
1971
499
|
tag: "span",
|
|
@@ -1975,19 +503,19 @@ function ColorsEditable({
|
|
|
1975
503
|
className: "text-lg font-bold"
|
|
1976
504
|
}
|
|
1977
505
|
),
|
|
1978
|
-
collapsing && /* @__PURE__ */
|
|
506
|
+
collapsing && /* @__PURE__ */ jsxs3(
|
|
1979
507
|
"button",
|
|
1980
508
|
{
|
|
1981
509
|
onClick: () => setExpanded(!expanded),
|
|
1982
510
|
className: "cursor-pointer ml-auto flex items-center gap-1.5 text-sm text-base-contrast-light hover:text-base-contrast",
|
|
1983
511
|
children: [
|
|
1984
|
-
/* @__PURE__ */
|
|
1985
|
-
expanded ? /* @__PURE__ */
|
|
512
|
+
/* @__PURE__ */ jsx10("span", { children: expanded ? "Hide Details" : "Show Details" }),
|
|
513
|
+
expanded ? /* @__PURE__ */ jsx10(EyeOff, { size: 16 }) : /* @__PURE__ */ jsx10(Eye, { size: 16 })
|
|
1986
514
|
]
|
|
1987
515
|
}
|
|
1988
516
|
)
|
|
1989
517
|
] }),
|
|
1990
|
-
/* @__PURE__ */
|
|
518
|
+
/* @__PURE__ */ jsx10(
|
|
1991
519
|
EditableGrid,
|
|
1992
520
|
{
|
|
1993
521
|
items: colors,
|
|
@@ -1996,7 +524,7 @@ function ColorsEditable({
|
|
|
1996
524
|
createItem: createColorItem,
|
|
1997
525
|
isEditMode: true,
|
|
1998
526
|
onItemSettings: handleItemSettings,
|
|
1999
|
-
renderItem: (color, { index }) => /* @__PURE__ */
|
|
527
|
+
renderItem: (color, { index }) => /* @__PURE__ */ jsx10(
|
|
2000
528
|
ColorSwatchEditable,
|
|
2001
529
|
{
|
|
2002
530
|
color,
|
|
@@ -2025,8 +553,8 @@ function ColorSwatchEditable({
|
|
|
2025
553
|
const newColors = colors.map((c, i) => i === index ? updated : c);
|
|
2026
554
|
onChange(buildContent(newColors, options));
|
|
2027
555
|
};
|
|
2028
|
-
return /* @__PURE__ */
|
|
2029
|
-
/* @__PURE__ */
|
|
556
|
+
return /* @__PURE__ */ jsxs3("div", { className: "overflow-hidden rounded-md border border-base-200", children: [
|
|
557
|
+
/* @__PURE__ */ jsx10("div", { className: cn("flex min-h-[80px] items-end p-3", contrast), style: { backgroundColor: hex || "#ccc" }, children: /* @__PURE__ */ jsx10(
|
|
2030
558
|
EditablePlainText,
|
|
2031
559
|
{
|
|
2032
560
|
tag: "span",
|
|
@@ -2037,11 +565,11 @@ function ColorSwatchEditable({
|
|
|
2037
565
|
className: "text-sm font-bold"
|
|
2038
566
|
}
|
|
2039
567
|
) }),
|
|
2040
|
-
expanded && /* @__PURE__ */
|
|
568
|
+
expanded && /* @__PURE__ */ jsx10("div", { className: "space-y-1 bg-base-accent p-3 text-sm", children: color.spaces.map(
|
|
2041
569
|
(space, j) => Object.entries(space).map(
|
|
2042
|
-
([key, value]) => value ? /* @__PURE__ */
|
|
2043
|
-
/* @__PURE__ */
|
|
2044
|
-
/* @__PURE__ */
|
|
570
|
+
([key, value]) => value ? /* @__PURE__ */ jsxs3("div", { className: "flex w-full justify-between", children: [
|
|
571
|
+
/* @__PURE__ */ jsx10("span", { className: "font-medium uppercase", children: key }),
|
|
572
|
+
/* @__PURE__ */ jsx10("span", { children: value })
|
|
2045
573
|
] }, `${j}-${key}`) : null
|
|
2046
574
|
)
|
|
2047
575
|
) })
|
|
@@ -2049,23 +577,23 @@ function ColorSwatchEditable({
|
|
|
2049
577
|
}
|
|
2050
578
|
|
|
2051
579
|
// src/components/sections/Colors/index.tsx
|
|
2052
|
-
import { jsx as
|
|
2053
|
-
var
|
|
2054
|
-
type:
|
|
2055
|
-
content:
|
|
2056
|
-
options:
|
|
2057
|
-
label:
|
|
2058
|
-
columns:
|
|
2059
|
-
collapsing:
|
|
2060
|
-
showLabel:
|
|
580
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
581
|
+
var schema4 = z4.object({
|
|
582
|
+
type: z4.literal("colors"),
|
|
583
|
+
content: z4.object({ colors: z4.array(ColorItemSchema) }),
|
|
584
|
+
options: z4.object({
|
|
585
|
+
label: z4.string().optional(),
|
|
586
|
+
columns: z4.number().int().min(2).max(4).optional(),
|
|
587
|
+
collapsing: z4.boolean().optional(),
|
|
588
|
+
showLabel: z4.boolean().optional()
|
|
2061
589
|
}).optional()
|
|
2062
590
|
});
|
|
2063
591
|
var Colors_default = defineSection({
|
|
2064
592
|
type: "colors",
|
|
2065
593
|
label: "Colors",
|
|
2066
|
-
icon: /* @__PURE__ */
|
|
2067
|
-
schema:
|
|
2068
|
-
component: ({ content, options, onChange, openModal }) => /* @__PURE__ */
|
|
594
|
+
icon: /* @__PURE__ */ jsx11(Palette, { size: 18 }),
|
|
595
|
+
schema: schema4,
|
|
596
|
+
component: ({ content, options, onChange, openModal }) => /* @__PURE__ */ jsx11(
|
|
2069
597
|
Colors,
|
|
2070
598
|
{
|
|
2071
599
|
colors: content.content.colors,
|
|
@@ -2081,10 +609,7 @@ var Colors_default = defineSection({
|
|
|
2081
609
|
type: "colors",
|
|
2082
610
|
content: { colors: [{ spaces: [{ hex: "#000000" }] }] }
|
|
2083
611
|
}),
|
|
2084
|
-
getLabel: (content) =>
|
|
2085
|
-
const n = content.content.colors.length;
|
|
2086
|
-
return `${n} color${n === 1 ? "" : "s"}`;
|
|
2087
|
-
},
|
|
612
|
+
getLabel: (content) => pluralize(content.content.colors.length, "color"),
|
|
2088
613
|
getThumbnails: (content) => content.content.colors.filter((c) => c.spaces[0]?.hex).map((c) => ({ type: "color", value: c.spaces[0].hex })),
|
|
2089
614
|
settings: {
|
|
2090
615
|
columns: {
|
|
@@ -2101,17 +626,17 @@ var Colors_default = defineSection({
|
|
|
2101
626
|
});
|
|
2102
627
|
|
|
2103
628
|
// src/components/sections/IconList/index.tsx
|
|
2104
|
-
import { z as
|
|
629
|
+
import { z as z5 } from "zod";
|
|
2105
630
|
import { List } from "lucide-react";
|
|
2106
631
|
|
|
2107
632
|
// src/components/sections/IconList/IconList.tsx
|
|
2108
|
-
import { useRef as
|
|
633
|
+
import { useRef as useRef2, useEffect as useEffect3, useState as useState4, useCallback } from "react";
|
|
2109
634
|
import { CopyPlus, Pencil } from "lucide-react";
|
|
2110
635
|
|
|
2111
636
|
// src/components/primitives/IconPicker.tsx
|
|
2112
|
-
import { useEffect as
|
|
2113
|
-
import { Check
|
|
2114
|
-
import { Fragment
|
|
637
|
+
import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
|
|
638
|
+
import { Check, X } from "lucide-react";
|
|
639
|
+
import { Fragment, jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2115
640
|
function IconPicker({
|
|
2116
641
|
selected,
|
|
2117
642
|
onSelect,
|
|
@@ -2121,9 +646,9 @@ function IconPicker({
|
|
|
2121
646
|
dodont,
|
|
2122
647
|
onSelectDoDont
|
|
2123
648
|
}) {
|
|
2124
|
-
const panelRef =
|
|
2125
|
-
const [mode, setMode] =
|
|
2126
|
-
|
|
649
|
+
const panelRef = useRef(null);
|
|
650
|
+
const [mode, setMode] = useState3(dodont ? "dodont" : "none");
|
|
651
|
+
useEffect2(() => {
|
|
2127
652
|
function handleMouseDown(e) {
|
|
2128
653
|
if (panelRef.current && !panelRef.current.contains(e.target)) {
|
|
2129
654
|
onClose();
|
|
@@ -2133,14 +658,14 @@ function IconPicker({
|
|
|
2133
658
|
return () => document.removeEventListener("mousedown", handleMouseDown);
|
|
2134
659
|
}, [onClose]);
|
|
2135
660
|
const showDoDont = allowDoDont && mode === "dodont";
|
|
2136
|
-
return /* @__PURE__ */
|
|
661
|
+
return /* @__PURE__ */ jsxs4(
|
|
2137
662
|
"div",
|
|
2138
663
|
{
|
|
2139
664
|
ref: panelRef,
|
|
2140
665
|
className: "absolute z-50 w-56 rounded-lg border border-base-200 bg-base p-2 shadow-lg",
|
|
2141
666
|
children: [
|
|
2142
|
-
allowDoDont && /* @__PURE__ */
|
|
2143
|
-
/* @__PURE__ */
|
|
667
|
+
allowDoDont && /* @__PURE__ */ jsxs4("div", { role: "tablist", "aria-label": "Icon mode", className: "mb-2 flex gap-1 rounded-md bg-base-200 p-0.5", children: [
|
|
668
|
+
/* @__PURE__ */ jsx12(
|
|
2144
669
|
"button",
|
|
2145
670
|
{
|
|
2146
671
|
type: "button",
|
|
@@ -2158,7 +683,7 @@ function IconPicker({
|
|
|
2158
683
|
children: "None"
|
|
2159
684
|
}
|
|
2160
685
|
),
|
|
2161
|
-
/* @__PURE__ */
|
|
686
|
+
/* @__PURE__ */ jsx12(
|
|
2162
687
|
"button",
|
|
2163
688
|
{
|
|
2164
689
|
type: "button",
|
|
@@ -2174,8 +699,8 @@ function IconPicker({
|
|
|
2174
699
|
}
|
|
2175
700
|
)
|
|
2176
701
|
] }),
|
|
2177
|
-
showDoDont ? /* @__PURE__ */
|
|
2178
|
-
/* @__PURE__ */
|
|
702
|
+
showDoDont ? /* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
703
|
+
/* @__PURE__ */ jsxs4(
|
|
2179
704
|
"button",
|
|
2180
705
|
{
|
|
2181
706
|
type: "button",
|
|
@@ -2187,12 +712,12 @@ function IconPicker({
|
|
|
2187
712
|
),
|
|
2188
713
|
onClick: () => onSelectDoDont?.("do"),
|
|
2189
714
|
children: [
|
|
2190
|
-
/* @__PURE__ */
|
|
2191
|
-
/* @__PURE__ */
|
|
715
|
+
/* @__PURE__ */ jsx12(Check, { size: 20 }),
|
|
716
|
+
/* @__PURE__ */ jsx12("span", { className: "text-xs font-medium", children: "Do" })
|
|
2192
717
|
]
|
|
2193
718
|
}
|
|
2194
719
|
),
|
|
2195
|
-
/* @__PURE__ */
|
|
720
|
+
/* @__PURE__ */ jsxs4(
|
|
2196
721
|
"button",
|
|
2197
722
|
{
|
|
2198
723
|
type: "button",
|
|
@@ -2204,16 +729,16 @@ function IconPicker({
|
|
|
2204
729
|
),
|
|
2205
730
|
onClick: () => onSelectDoDont?.("dont"),
|
|
2206
731
|
children: [
|
|
2207
|
-
/* @__PURE__ */
|
|
2208
|
-
/* @__PURE__ */
|
|
732
|
+
/* @__PURE__ */ jsx12(X, { size: 20 }),
|
|
733
|
+
/* @__PURE__ */ jsx12("span", { className: "text-xs font-medium", children: "Don't" })
|
|
2209
734
|
]
|
|
2210
735
|
}
|
|
2211
736
|
)
|
|
2212
|
-
] }) : /* @__PURE__ */
|
|
2213
|
-
/* @__PURE__ */
|
|
737
|
+
] }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
738
|
+
/* @__PURE__ */ jsx12("div", { className: "grid grid-cols-5 gap-1", children: curatedIcons.map((entry) => {
|
|
2214
739
|
const Icon = entry.icon;
|
|
2215
740
|
const isSelected = selected === entry.id;
|
|
2216
|
-
return /* @__PURE__ */
|
|
741
|
+
return /* @__PURE__ */ jsx12(
|
|
2217
742
|
"button",
|
|
2218
743
|
{
|
|
2219
744
|
"aria-label": entry.label,
|
|
@@ -2223,12 +748,12 @@ function IconPicker({
|
|
|
2223
748
|
isSelected && "ring-2 ring-primary bg-base-accent text-primary"
|
|
2224
749
|
),
|
|
2225
750
|
onClick: () => onSelect(entry.id),
|
|
2226
|
-
children: /* @__PURE__ */
|
|
751
|
+
children: /* @__PURE__ */ jsx12(Icon, { size: 18 })
|
|
2227
752
|
},
|
|
2228
753
|
entry.id
|
|
2229
754
|
);
|
|
2230
755
|
}) }),
|
|
2231
|
-
showRemove && /* @__PURE__ */
|
|
756
|
+
showRemove && /* @__PURE__ */ jsx12(
|
|
2232
757
|
"button",
|
|
2233
758
|
{
|
|
2234
759
|
className: "cursor-pointer mt-2 w-full rounded px-2 py-1.5 text-center text-xs text-base-contrast-light hover:bg-base-accent hover:text-base-contrast",
|
|
@@ -2243,7 +768,7 @@ function IconPicker({
|
|
|
2243
768
|
}
|
|
2244
769
|
|
|
2245
770
|
// src/components/sections/IconList/IconList.tsx
|
|
2246
|
-
import { jsx as
|
|
771
|
+
import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2247
772
|
function IconList({
|
|
2248
773
|
items,
|
|
2249
774
|
icon = null,
|
|
@@ -2256,7 +781,7 @@ function IconList({
|
|
|
2256
781
|
onItemsChange
|
|
2257
782
|
}) {
|
|
2258
783
|
const isEditMode = !!onChange || !!onItemsChange;
|
|
2259
|
-
const emitItems =
|
|
784
|
+
const emitItems = useCallback(
|
|
2260
785
|
(newItems) => {
|
|
2261
786
|
onChange?.({
|
|
2262
787
|
type: "icon_list",
|
|
@@ -2268,7 +793,7 @@ function IconList({
|
|
|
2268
793
|
[onChange, onItemsChange, icon, showLabel, stackText]
|
|
2269
794
|
);
|
|
2270
795
|
if (!isEditMode) {
|
|
2271
|
-
return /* @__PURE__ */
|
|
796
|
+
return /* @__PURE__ */ jsx13(
|
|
2272
797
|
ViewIconList,
|
|
2273
798
|
{
|
|
2274
799
|
items,
|
|
@@ -2281,7 +806,7 @@ function IconList({
|
|
|
2281
806
|
}
|
|
2282
807
|
);
|
|
2283
808
|
}
|
|
2284
|
-
return /* @__PURE__ */
|
|
809
|
+
return /* @__PURE__ */ jsx13(
|
|
2285
810
|
EditIconList,
|
|
2286
811
|
{
|
|
2287
812
|
items,
|
|
@@ -2316,10 +841,10 @@ function ViewIconList({
|
|
|
2316
841
|
iconClassName
|
|
2317
842
|
}) {
|
|
2318
843
|
const hasAnyIcon = items.some((item) => resolveIcon(item, defaultIcon));
|
|
2319
|
-
return /* @__PURE__ */
|
|
844
|
+
return /* @__PURE__ */ jsx13("div", { className: "grid gap-4 pb-4", children: items.map((item, i) => {
|
|
2320
845
|
const iconEntry = resolveIcon(item, defaultIcon);
|
|
2321
846
|
const iconColor = resolveIconColor(item, iconClassName);
|
|
2322
|
-
return /* @__PURE__ */
|
|
847
|
+
return /* @__PURE__ */ jsxs5(
|
|
2323
848
|
"div",
|
|
2324
849
|
{
|
|
2325
850
|
className: cn(
|
|
@@ -2327,25 +852,25 @@ function ViewIconList({
|
|
|
2327
852
|
hasAnyIcon ? "grid-cols-[24px_1fr]" : "grid-cols-1"
|
|
2328
853
|
),
|
|
2329
854
|
children: [
|
|
2330
|
-
hasAnyIcon && /* @__PURE__ */
|
|
855
|
+
hasAnyIcon && /* @__PURE__ */ jsx13(
|
|
2331
856
|
"div",
|
|
2332
857
|
{
|
|
2333
858
|
"data-testid": "icon-list-icon",
|
|
2334
859
|
className: cn("flex items-start pt-0.5", iconColor),
|
|
2335
|
-
children: iconEntry && /* @__PURE__ */
|
|
860
|
+
children: iconEntry && /* @__PURE__ */ jsx13(iconEntry.icon, { size: 18 })
|
|
2336
861
|
}
|
|
2337
862
|
),
|
|
2338
|
-
/* @__PURE__ */
|
|
863
|
+
/* @__PURE__ */ jsxs5(
|
|
2339
864
|
"div",
|
|
2340
865
|
{
|
|
2341
866
|
"data-testid": "icon-list-content",
|
|
2342
867
|
className: stackText ? "flex flex-col" : void 0,
|
|
2343
868
|
children: [
|
|
2344
|
-
showLabel && /* @__PURE__ */
|
|
869
|
+
showLabel && /* @__PURE__ */ jsxs5("span", { className: labelClassName, children: [
|
|
2345
870
|
item.label,
|
|
2346
871
|
!stackText && " "
|
|
2347
872
|
] }),
|
|
2348
|
-
/* @__PURE__ */
|
|
873
|
+
/* @__PURE__ */ jsx13("span", { className: textClassName, children: item.text })
|
|
2349
874
|
]
|
|
2350
875
|
}
|
|
2351
876
|
)
|
|
@@ -2370,8 +895,8 @@ function EditIconList({
|
|
|
2370
895
|
onChange: onItemsChange,
|
|
2371
896
|
createItem: () => ({ label: "", text: "" })
|
|
2372
897
|
});
|
|
2373
|
-
const [dragState, setDragState] =
|
|
2374
|
-
const updateItem =
|
|
898
|
+
const [dragState, setDragState] = useState4({ sourceId: null, targetId: null });
|
|
899
|
+
const updateItem = useCallback(
|
|
2375
900
|
(index, patch) => {
|
|
2376
901
|
const updated = wrappedItems.map(
|
|
2377
902
|
(w, i) => i === index ? { ...w.data, ...patch } : w.data
|
|
@@ -2380,7 +905,7 @@ function EditIconList({
|
|
|
2380
905
|
},
|
|
2381
906
|
[wrappedItems, onItemsChange]
|
|
2382
907
|
);
|
|
2383
|
-
const duplicateItem =
|
|
908
|
+
const duplicateItem = useCallback(
|
|
2384
909
|
(index) => {
|
|
2385
910
|
const copy = { ...wrappedItems[index].data };
|
|
2386
911
|
const next = [
|
|
@@ -2393,8 +918,8 @@ function EditIconList({
|
|
|
2393
918
|
[wrappedItems, onItemsChange]
|
|
2394
919
|
);
|
|
2395
920
|
const hasAnyIcon = true;
|
|
2396
|
-
return /* @__PURE__ */
|
|
2397
|
-
wrappedItems.map((wrapped, index) => /* @__PURE__ */
|
|
921
|
+
return /* @__PURE__ */ jsxs5("div", { className: "group/list relative grid gap-4 pb-4", children: [
|
|
922
|
+
wrappedItems.map((wrapped, index) => /* @__PURE__ */ jsx13(
|
|
2398
923
|
EditableRow,
|
|
2399
924
|
{
|
|
2400
925
|
id: wrapped.id,
|
|
@@ -2416,7 +941,7 @@ function EditIconList({
|
|
|
2416
941
|
},
|
|
2417
942
|
wrapped.id
|
|
2418
943
|
)),
|
|
2419
|
-
/* @__PURE__ */
|
|
944
|
+
/* @__PURE__ */ jsx13(
|
|
2420
945
|
TrailingDropZone,
|
|
2421
946
|
{
|
|
2422
947
|
index: wrappedItems.length,
|
|
@@ -2425,10 +950,10 @@ function EditIconList({
|
|
|
2425
950
|
onReorder
|
|
2426
951
|
}
|
|
2427
952
|
),
|
|
2428
|
-
/* @__PURE__ */
|
|
953
|
+
/* @__PURE__ */ jsx13(
|
|
2429
954
|
IconButton,
|
|
2430
955
|
{
|
|
2431
|
-
icon: /* @__PURE__ */
|
|
956
|
+
icon: /* @__PURE__ */ jsx13(AddIcon, { size: 16 }),
|
|
2432
957
|
label: "Add item",
|
|
2433
958
|
size: "lg",
|
|
2434
959
|
intent: "primary",
|
|
@@ -2456,15 +981,15 @@ function EditableRow({
|
|
|
2456
981
|
onUpdateItem,
|
|
2457
982
|
onDuplicate
|
|
2458
983
|
}) {
|
|
2459
|
-
const rowRef =
|
|
2460
|
-
const handleRef =
|
|
2461
|
-
const [iconHover, setIconHover] =
|
|
2462
|
-
const [pickerOpen, setPickerOpen] =
|
|
2463
|
-
const [editingSuppressed, setEditingSuppressed] =
|
|
984
|
+
const rowRef = useRef2(null);
|
|
985
|
+
const handleRef = useRef2(null);
|
|
986
|
+
const [iconHover, setIconHover] = useState4(false);
|
|
987
|
+
const [pickerOpen, setPickerOpen] = useState4(false);
|
|
988
|
+
const [editingSuppressed, setEditingSuppressed] = useState4(false);
|
|
2464
989
|
const iconEntry = resolveIcon(item, defaultIcon);
|
|
2465
990
|
const effectiveIconId = item.icon ?? defaultIcon ?? null;
|
|
2466
991
|
const iconColor = resolveIconColor(item, iconClassName);
|
|
2467
|
-
|
|
992
|
+
useEffect3(() => {
|
|
2468
993
|
const row = rowRef.current;
|
|
2469
994
|
const handle = handleRef.current;
|
|
2470
995
|
if (!row || !handle) return;
|
|
@@ -2508,7 +1033,7 @@ function EditableRow({
|
|
|
2508
1033
|
setEditingSuppressed(true);
|
|
2509
1034
|
}
|
|
2510
1035
|
};
|
|
2511
|
-
return /* @__PURE__ */
|
|
1036
|
+
return /* @__PURE__ */ jsxs5(
|
|
2512
1037
|
"div",
|
|
2513
1038
|
{
|
|
2514
1039
|
ref: rowRef,
|
|
@@ -2521,7 +1046,7 @@ function EditableRow({
|
|
|
2521
1046
|
onInput: onEditableActivity,
|
|
2522
1047
|
onMouseMove: () => setEditingSuppressed(false),
|
|
2523
1048
|
children: [
|
|
2524
|
-
hasAnyIcon && /* @__PURE__ */
|
|
1049
|
+
hasAnyIcon && /* @__PURE__ */ jsxs5(
|
|
2525
1050
|
"div",
|
|
2526
1051
|
{
|
|
2527
1052
|
"data-testid": "icon-list-icon",
|
|
@@ -2529,16 +1054,16 @@ function EditableRow({
|
|
|
2529
1054
|
onMouseEnter: () => setIconHover(true),
|
|
2530
1055
|
onMouseLeave: () => setIconHover(false),
|
|
2531
1056
|
children: [
|
|
2532
|
-
/* @__PURE__ */
|
|
1057
|
+
/* @__PURE__ */ jsx13(
|
|
2533
1058
|
"button",
|
|
2534
1059
|
{
|
|
2535
1060
|
className: "cursor-pointer transition-opacity hover:opacity-70",
|
|
2536
1061
|
"aria-label": "Change icon",
|
|
2537
1062
|
onClick: () => setPickerOpen((prev) => !prev),
|
|
2538
|
-
children: iconHover && !pickerOpen ? /* @__PURE__ */
|
|
1063
|
+
children: iconHover && !pickerOpen ? /* @__PURE__ */ jsx13(Pencil, { size: 18, className: "text-base-contrast-light" }) : iconEntry ? /* @__PURE__ */ jsx13(iconEntry.icon, { size: 18 }) : /* @__PURE__ */ jsx13("span", { className: "flex h-[18px] w-[18px] items-center justify-center rounded-sm border border-dashed border-base-contrast-light/40" })
|
|
2539
1064
|
}
|
|
2540
1065
|
),
|
|
2541
|
-
pickerOpen && /* @__PURE__ */
|
|
1066
|
+
pickerOpen && /* @__PURE__ */ jsx13("div", { className: "absolute top-full left-0 z-50 mt-1", children: /* @__PURE__ */ jsx13(
|
|
2542
1067
|
IconPicker,
|
|
2543
1068
|
{
|
|
2544
1069
|
selected: effectiveIconId,
|
|
@@ -2566,8 +1091,8 @@ function EditableRow({
|
|
|
2566
1091
|
]
|
|
2567
1092
|
}
|
|
2568
1093
|
),
|
|
2569
|
-
/* @__PURE__ */
|
|
2570
|
-
showLabel && /* @__PURE__ */
|
|
1094
|
+
/* @__PURE__ */ jsxs5("div", { className: stackText ? "flex flex-col" : void 0, children: [
|
|
1095
|
+
showLabel && /* @__PURE__ */ jsx13(
|
|
2571
1096
|
EditablePlainText,
|
|
2572
1097
|
{
|
|
2573
1098
|
tag: "span",
|
|
@@ -2578,7 +1103,7 @@ function EditableRow({
|
|
|
2578
1103
|
className: cn(labelClassName, !stackText && "mr-1")
|
|
2579
1104
|
}
|
|
2580
1105
|
),
|
|
2581
|
-
/* @__PURE__ */
|
|
1106
|
+
/* @__PURE__ */ jsx13(
|
|
2582
1107
|
EditablePlainText,
|
|
2583
1108
|
{
|
|
2584
1109
|
tag: "span",
|
|
@@ -2590,7 +1115,7 @@ function EditableRow({
|
|
|
2590
1115
|
}
|
|
2591
1116
|
)
|
|
2592
1117
|
] }),
|
|
2593
|
-
/* @__PURE__ */
|
|
1118
|
+
/* @__PURE__ */ jsxs5(
|
|
2594
1119
|
"div",
|
|
2595
1120
|
{
|
|
2596
1121
|
className: cn(
|
|
@@ -2598,30 +1123,30 @@ function EditableRow({
|
|
|
2598
1123
|
editingSuppressed ? "opacity-0 pointer-events-none" : "opacity-0 group-hover/row:opacity-100 no-hover:opacity-100"
|
|
2599
1124
|
),
|
|
2600
1125
|
children: [
|
|
2601
|
-
/* @__PURE__ */
|
|
1126
|
+
/* @__PURE__ */ jsx13(
|
|
2602
1127
|
IconButton,
|
|
2603
1128
|
{
|
|
2604
1129
|
ref: handleRef,
|
|
2605
|
-
icon: /* @__PURE__ */
|
|
1130
|
+
icon: /* @__PURE__ */ jsx13(DragHandle, { size: 14 }),
|
|
2606
1131
|
label: "Drag to reorder",
|
|
2607
1132
|
size: "sm",
|
|
2608
1133
|
className: "cursor-grab rounded bg-base/80 p-1 shadow-sm text-base-contrast-light/80 hover:text-base-contrast active:cursor-grabbing",
|
|
2609
1134
|
tabIndex: -1
|
|
2610
1135
|
}
|
|
2611
1136
|
),
|
|
2612
|
-
/* @__PURE__ */
|
|
1137
|
+
/* @__PURE__ */ jsx13(
|
|
2613
1138
|
"button",
|
|
2614
1139
|
{
|
|
2615
1140
|
"aria-label": "Duplicate item",
|
|
2616
1141
|
onClick: onDuplicate,
|
|
2617
1142
|
className: "cursor-pointer rounded bg-base/80 p-1 shadow-sm text-base-contrast-light hover:text-primary",
|
|
2618
|
-
children: /* @__PURE__ */
|
|
1143
|
+
children: /* @__PURE__ */ jsx13(CopyPlus, { size: 14 })
|
|
2619
1144
|
}
|
|
2620
1145
|
),
|
|
2621
|
-
/* @__PURE__ */
|
|
1146
|
+
/* @__PURE__ */ jsx13(
|
|
2622
1147
|
IconButton,
|
|
2623
1148
|
{
|
|
2624
|
-
icon: /* @__PURE__ */
|
|
1149
|
+
icon: /* @__PURE__ */ jsx13(DeleteIcon, { size: 14 }),
|
|
2625
1150
|
label: "Delete item",
|
|
2626
1151
|
size: "sm",
|
|
2627
1152
|
intent: "destructive",
|
|
@@ -2642,9 +1167,9 @@ function TrailingDropZone({
|
|
|
2642
1167
|
setDragState,
|
|
2643
1168
|
onReorder
|
|
2644
1169
|
}) {
|
|
2645
|
-
const ref =
|
|
1170
|
+
const ref = useRef2(null);
|
|
2646
1171
|
const trailingId = "__trailing__";
|
|
2647
|
-
|
|
1172
|
+
useEffect3(() => {
|
|
2648
1173
|
const el = ref.current;
|
|
2649
1174
|
if (!el) return;
|
|
2650
1175
|
let cleanup;
|
|
@@ -2671,7 +1196,7 @@ function TrailingDropZone({
|
|
|
2671
1196
|
};
|
|
2672
1197
|
}, [index, onReorder, setDragState]);
|
|
2673
1198
|
const isDropTarget = dragState.targetId === trailingId && dragState.sourceId !== null;
|
|
2674
|
-
return /* @__PURE__ */
|
|
1199
|
+
return /* @__PURE__ */ jsx13(
|
|
2675
1200
|
"div",
|
|
2676
1201
|
{
|
|
2677
1202
|
ref,
|
|
@@ -2681,110 +1206,38 @@ function TrailingDropZone({
|
|
|
2681
1206
|
}
|
|
2682
1207
|
|
|
2683
1208
|
// src/components/sections/IconList/IconListSettings.tsx
|
|
2684
|
-
import { useState as
|
|
2685
|
-
|
|
2686
|
-
// src/components/shared/Checkbox.tsx
|
|
2687
|
-
import { useId as useId2 } from "react";
|
|
2688
|
-
import { Check as Check3 } from "lucide-react";
|
|
2689
|
-
import { jsx as jsx27, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2690
|
-
function Checkbox({
|
|
2691
|
-
checked,
|
|
2692
|
-
onChange,
|
|
2693
|
-
label,
|
|
2694
|
-
description,
|
|
2695
|
-
disabled,
|
|
2696
|
-
className,
|
|
2697
|
-
startAdornment,
|
|
2698
|
-
align = "start"
|
|
2699
|
-
}) {
|
|
2700
|
-
const id = useId2();
|
|
2701
|
-
return /* @__PURE__ */ jsxs14(
|
|
2702
|
-
"label",
|
|
2703
|
-
{
|
|
2704
|
-
htmlFor: id,
|
|
2705
|
-
className: cn(
|
|
2706
|
-
"flex cursor-pointer gap-3 select-none hover:opacity-80",
|
|
2707
|
-
align === "start" ? "items-start" : "items-center",
|
|
2708
|
-
disabled && "cursor-not-allowed opacity-50",
|
|
2709
|
-
className
|
|
2710
|
-
),
|
|
2711
|
-
children: [
|
|
2712
|
-
/* @__PURE__ */ jsxs14(
|
|
2713
|
-
"span",
|
|
2714
|
-
{
|
|
2715
|
-
className: cn(
|
|
2716
|
-
"relative flex h-5 w-5 shrink-0 items-center justify-center",
|
|
2717
|
-
align === "start" && "mt-0.5"
|
|
2718
|
-
),
|
|
2719
|
-
children: [
|
|
2720
|
-
/* @__PURE__ */ jsx27(
|
|
2721
|
-
"input",
|
|
2722
|
-
{
|
|
2723
|
-
id,
|
|
2724
|
-
type: "checkbox",
|
|
2725
|
-
checked,
|
|
2726
|
-
disabled,
|
|
2727
|
-
onChange: (e) => onChange(e.target.checked),
|
|
2728
|
-
className: "sr-only"
|
|
2729
|
-
}
|
|
2730
|
-
),
|
|
2731
|
-
/* @__PURE__ */ jsx27(
|
|
2732
|
-
"span",
|
|
2733
|
-
{
|
|
2734
|
-
"aria-hidden": "true",
|
|
2735
|
-
className: cn(
|
|
2736
|
-
"flex h-5 w-5 items-center justify-center rounded border transition-colors",
|
|
2737
|
-
checked ? "border-primary bg-primary text-primary-contrast" : "border-base-300 bg-base hover:border-primary",
|
|
2738
|
-
disabled && "pointer-events-none"
|
|
2739
|
-
),
|
|
2740
|
-
children: checked && /* @__PURE__ */ jsx27(Check3, { size: 14, strokeWidth: 3 })
|
|
2741
|
-
}
|
|
2742
|
-
)
|
|
2743
|
-
]
|
|
2744
|
-
}
|
|
2745
|
-
),
|
|
2746
|
-
startAdornment,
|
|
2747
|
-
/* @__PURE__ */ jsxs14("div", { className: "text-sm", children: [
|
|
2748
|
-
/* @__PURE__ */ jsx27("span", { className: "font-medium text-base-contrast", children: label }),
|
|
2749
|
-
description && /* @__PURE__ */ jsx27("span", { className: "block text-base-contrast-light", children: description })
|
|
2750
|
-
] })
|
|
2751
|
-
]
|
|
2752
|
-
}
|
|
2753
|
-
);
|
|
2754
|
-
}
|
|
2755
|
-
|
|
2756
|
-
// src/components/sections/IconList/IconListSettings.tsx
|
|
2757
|
-
import { jsx as jsx28, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1209
|
+
import { useState as useState5 } from "react";
|
|
1210
|
+
import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2758
1211
|
function IconListSettings({
|
|
2759
1212
|
icon: initialIcon,
|
|
2760
1213
|
showLabel: initialShowLabel,
|
|
2761
1214
|
stackText: initialStackText,
|
|
2762
1215
|
onChange
|
|
2763
1216
|
}) {
|
|
2764
|
-
const [icon, setIcon] =
|
|
2765
|
-
const [showLabel, setShowLabel] =
|
|
2766
|
-
const [stackText, setStackText] =
|
|
2767
|
-
const [pickerOpen, setPickerOpen] =
|
|
1217
|
+
const [icon, setIcon] = useState5(initialIcon);
|
|
1218
|
+
const [showLabel, setShowLabel] = useState5(initialShowLabel);
|
|
1219
|
+
const [stackText, setStackText] = useState5(initialStackText);
|
|
1220
|
+
const [pickerOpen, setPickerOpen] = useState5(false);
|
|
2768
1221
|
const emit = (overrides) => onChange({ content: {}, options: { icon, showLabel, stackText, ...overrides } });
|
|
2769
1222
|
const showIcons = icon !== null;
|
|
2770
1223
|
const iconEntry = icon ? getIcon(icon) : null;
|
|
2771
|
-
return /* @__PURE__ */
|
|
2772
|
-
/* @__PURE__ */
|
|
2773
|
-
/* @__PURE__ */
|
|
2774
|
-
/* @__PURE__ */
|
|
2775
|
-
/* @__PURE__ */
|
|
1224
|
+
return /* @__PURE__ */ jsxs6("div", { className: "space-y-4", children: [
|
|
1225
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative", children: [
|
|
1226
|
+
/* @__PURE__ */ jsx14(FormLabel, { htmlFor: "icon-picker-btn", children: "Default Icon" }),
|
|
1227
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
1228
|
+
/* @__PURE__ */ jsxs6(
|
|
2776
1229
|
"button",
|
|
2777
1230
|
{
|
|
2778
1231
|
id: "icon-picker-btn",
|
|
2779
1232
|
className: "cursor-pointer flex items-center gap-2 rounded border border-base-200 px-3 py-1.5 text-sm text-base-contrast-light hover:border-primary hover:text-primary",
|
|
2780
1233
|
onClick: () => setPickerOpen((prev) => !prev),
|
|
2781
1234
|
children: [
|
|
2782
|
-
iconEntry && /* @__PURE__ */
|
|
2783
|
-
/* @__PURE__ */
|
|
1235
|
+
iconEntry && /* @__PURE__ */ jsx14(iconEntry.icon, { size: 16 }),
|
|
1236
|
+
/* @__PURE__ */ jsx14("span", { children: iconEntry?.label ?? "None" })
|
|
2784
1237
|
]
|
|
2785
1238
|
}
|
|
2786
1239
|
),
|
|
2787
|
-
icon && /* @__PURE__ */
|
|
1240
|
+
icon && /* @__PURE__ */ jsx14(
|
|
2788
1241
|
"button",
|
|
2789
1242
|
{
|
|
2790
1243
|
className: "cursor-pointer text-xs text-base-contrast-light hover:text-base-contrast",
|
|
@@ -2796,7 +1249,7 @@ function IconListSettings({
|
|
|
2796
1249
|
}
|
|
2797
1250
|
)
|
|
2798
1251
|
] }),
|
|
2799
|
-
pickerOpen && /* @__PURE__ */
|
|
1252
|
+
pickerOpen && /* @__PURE__ */ jsx14("div", { className: "absolute top-full left-0 z-50 mt-1", children: /* @__PURE__ */ jsx14(
|
|
2800
1253
|
IconPicker,
|
|
2801
1254
|
{
|
|
2802
1255
|
selected: icon,
|
|
@@ -2811,7 +1264,7 @@ function IconListSettings({
|
|
|
2811
1264
|
}
|
|
2812
1265
|
) })
|
|
2813
1266
|
] }),
|
|
2814
|
-
/* @__PURE__ */
|
|
1267
|
+
/* @__PURE__ */ jsx14(
|
|
2815
1268
|
Checkbox,
|
|
2816
1269
|
{
|
|
2817
1270
|
checked: showLabel,
|
|
@@ -2822,7 +1275,7 @@ function IconListSettings({
|
|
|
2822
1275
|
label: "Show labels"
|
|
2823
1276
|
}
|
|
2824
1277
|
),
|
|
2825
|
-
showLabel && /* @__PURE__ */
|
|
1278
|
+
showLabel && /* @__PURE__ */ jsx14(
|
|
2826
1279
|
Checkbox,
|
|
2827
1280
|
{
|
|
2828
1281
|
checked: stackText,
|
|
@@ -2837,24 +1290,30 @@ function IconListSettings({
|
|
|
2837
1290
|
}
|
|
2838
1291
|
|
|
2839
1292
|
// src/components/sections/IconList/index.tsx
|
|
2840
|
-
import { jsx as
|
|
2841
|
-
var
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
1293
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1294
|
+
var IconListItemSchema = z5.object({
|
|
1295
|
+
label: z5.string(),
|
|
1296
|
+
text: z5.string(),
|
|
1297
|
+
icon: z5.string().optional(),
|
|
1298
|
+
dodont: z5.enum(["do", "dont"]).optional()
|
|
1299
|
+
});
|
|
1300
|
+
var schema5 = z5.object({
|
|
1301
|
+
type: z5.literal("icon_list"),
|
|
1302
|
+
content: z5.object({
|
|
1303
|
+
items: z5.array(IconListItemSchema)
|
|
2845
1304
|
}),
|
|
2846
|
-
options:
|
|
2847
|
-
icon:
|
|
2848
|
-
showLabel:
|
|
2849
|
-
stackText:
|
|
1305
|
+
options: z5.object({
|
|
1306
|
+
icon: z5.string().nullable().optional(),
|
|
1307
|
+
showLabel: z5.boolean().optional(),
|
|
1308
|
+
stackText: z5.boolean().optional()
|
|
2850
1309
|
}).optional()
|
|
2851
1310
|
});
|
|
2852
1311
|
var IconList_default = defineSection({
|
|
2853
1312
|
type: "icon_list",
|
|
2854
1313
|
label: "Icon List",
|
|
2855
|
-
icon: /* @__PURE__ */
|
|
2856
|
-
schema:
|
|
2857
|
-
component: ({ content, options, onChange }) => /* @__PURE__ */
|
|
1314
|
+
icon: /* @__PURE__ */ jsx15(List, { size: 18 }),
|
|
1315
|
+
schema: schema5,
|
|
1316
|
+
component: ({ content, options, onChange }) => /* @__PURE__ */ jsx15(
|
|
2858
1317
|
IconList,
|
|
2859
1318
|
{
|
|
2860
1319
|
items: content.content.items,
|
|
@@ -2868,245 +1327,32 @@ var IconList_default = defineSection({
|
|
|
2868
1327
|
type: "icon_list",
|
|
2869
1328
|
content: { items: [{ label: "", text: "" }] }
|
|
2870
1329
|
}),
|
|
2871
|
-
getLabel: (content) =>
|
|
2872
|
-
const n = content.content.items.length;
|
|
2873
|
-
return `${n} icon${n === 1 ? "" : "s"}`;
|
|
2874
|
-
},
|
|
1330
|
+
getLabel: (content) => pluralize(content.content.items.length, "icon"),
|
|
2875
1331
|
settingsForm: IconListSettings
|
|
2876
1332
|
});
|
|
2877
1333
|
|
|
2878
1334
|
// src/components/sections/Container/index.tsx
|
|
2879
|
-
import { z as
|
|
1335
|
+
import { z as z6 } from "zod";
|
|
2880
1336
|
import { LayoutTemplate } from "lucide-react";
|
|
2881
1337
|
|
|
2882
1338
|
// src/components/sections/Container/Container.tsx
|
|
2883
1339
|
import "react";
|
|
2884
1340
|
|
|
2885
1341
|
// src/components/editor/ChildBlockWrapper.tsx
|
|
2886
|
-
import { forwardRef
|
|
1342
|
+
import { forwardRef } from "react";
|
|
2887
1343
|
import { CopyPlus as CopyPlus2 } from "lucide-react";
|
|
2888
1344
|
|
|
2889
|
-
// src/components/editor/DragHandle.tsx
|
|
2890
|
-
import { forwardRef as forwardRef4 } from "react";
|
|
2891
|
-
|
|
2892
|
-
// src/components/shared/Tooltip.tsx
|
|
2893
|
-
import { jsx as jsx30, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2894
|
-
function Tooltip({ content, children, className }) {
|
|
2895
|
-
return /* @__PURE__ */ jsxs16("div", { className: cn("group/tooltip relative inline-flex", className), children: [
|
|
2896
|
-
children,
|
|
2897
|
-
/* @__PURE__ */ jsx30(
|
|
2898
|
-
"span",
|
|
2899
|
-
{
|
|
2900
|
-
className: "pointer-events-none absolute left-1/2 top-full z-50 mt-1.5 -translate-x-1/2 opacity-0 transition-opacity delay-300 group-hover/tooltip:opacity-100",
|
|
2901
|
-
role: "tooltip",
|
|
2902
|
-
children: /* @__PURE__ */ jsx30("span", { className: "block whitespace-nowrap rounded bg-tooltip px-2 py-1 text-center text-xs leading-relaxed text-tooltip-muted", children: content })
|
|
2903
|
-
}
|
|
2904
|
-
)
|
|
2905
|
-
] });
|
|
2906
|
-
}
|
|
2907
|
-
function Kbd({ children }) {
|
|
2908
|
-
return /* @__PURE__ */ jsx30("strong", { className: "text-tooltip-contrast", children });
|
|
2909
|
-
}
|
|
2910
|
-
|
|
2911
|
-
// src/components/editor/DragHandle.tsx
|
|
2912
|
-
import { Fragment as Fragment5, jsx as jsx31, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2913
|
-
var DragHandle2 = forwardRef4(function DragHandle3(_, ref) {
|
|
2914
|
-
return /* @__PURE__ */ jsx31(Tooltip, { content: /* @__PURE__ */ jsxs17(Fragment5, { children: [
|
|
2915
|
-
/* @__PURE__ */ jsx31(Kbd, { children: "Drag" }),
|
|
2916
|
-
" to move"
|
|
2917
|
-
] }), children: /* @__PURE__ */ jsx31(
|
|
2918
|
-
IconButton,
|
|
2919
|
-
{
|
|
2920
|
-
ref,
|
|
2921
|
-
icon: /* @__PURE__ */ jsx31(DragHandle, { size: 18 }),
|
|
2922
|
-
label: "Drag to reorder section",
|
|
2923
|
-
className: "pointer-events-auto cursor-grab active:cursor-grabbing rounded-md text-base-contrast-light/80 hover:bg-base-contrast-light/10 hover:text-base-contrast",
|
|
2924
|
-
tabIndex: -1
|
|
2925
|
-
}
|
|
2926
|
-
) });
|
|
2927
|
-
});
|
|
2928
|
-
|
|
2929
|
-
// src/components/editor/DeleteButton.tsx
|
|
2930
|
-
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
2931
|
-
function DeleteButton({ onDelete }) {
|
|
2932
|
-
return /* @__PURE__ */ jsx32(
|
|
2933
|
-
IconButton,
|
|
2934
|
-
{
|
|
2935
|
-
icon: /* @__PURE__ */ jsx32(DeleteIcon, { size: 16 }),
|
|
2936
|
-
label: "Delete section",
|
|
2937
|
-
intent: "destructive",
|
|
2938
|
-
onClick: onDelete,
|
|
2939
|
-
className: "pointer-events-auto"
|
|
2940
|
-
}
|
|
2941
|
-
);
|
|
2942
|
-
}
|
|
2943
|
-
|
|
2944
|
-
// src/components/editor/SettingsButton.tsx
|
|
2945
|
-
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
2946
|
-
function SettingsButton({ onClick }) {
|
|
2947
|
-
return /* @__PURE__ */ jsx33(
|
|
2948
|
-
IconButton,
|
|
2949
|
-
{
|
|
2950
|
-
icon: /* @__PURE__ */ jsx33(SettingsIcon, { size: 16 }),
|
|
2951
|
-
label: "Section settings",
|
|
2952
|
-
onClick,
|
|
2953
|
-
className: "pointer-events-auto"
|
|
2954
|
-
}
|
|
2955
|
-
);
|
|
2956
|
-
}
|
|
2957
|
-
|
|
2958
1345
|
// src/components/editor/ColSpanControl.tsx
|
|
2959
|
-
import { useRef as
|
|
1346
|
+
import { useRef as useRef3, useState as useState6 } from "react";
|
|
2960
1347
|
import { Columns3 } from "lucide-react";
|
|
2961
|
-
|
|
2962
|
-
// src/components/shared/Popover.tsx
|
|
2963
|
-
import { useEffect as useEffect11, useLayoutEffect, useRef as useRef9, useState as useState13 } from "react";
|
|
2964
|
-
|
|
2965
|
-
// src/hooks/useFocusTrap.ts
|
|
2966
|
-
import { useEffect as useEffect10 } from "react";
|
|
2967
|
-
var FOCUSABLE_SELECTOR = [
|
|
2968
|
-
"a[href]",
|
|
2969
|
-
"button:not([disabled])",
|
|
2970
|
-
"input:not([disabled])",
|
|
2971
|
-
"select:not([disabled])",
|
|
2972
|
-
"textarea:not([disabled])",
|
|
2973
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
2974
|
-
].join(", ");
|
|
2975
|
-
function useFocusTrap(ref, active) {
|
|
2976
|
-
useEffect10(() => {
|
|
2977
|
-
if (!active || !ref.current) return;
|
|
2978
|
-
const container = ref.current;
|
|
2979
|
-
const previouslyFocused = document.activeElement;
|
|
2980
|
-
const getFocusable = () => Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
2981
|
-
const focusable = getFocusable();
|
|
2982
|
-
if (focusable.length > 0) {
|
|
2983
|
-
focusable[0].focus();
|
|
2984
|
-
}
|
|
2985
|
-
const handleKeyDown = (e) => {
|
|
2986
|
-
if (e.key !== "Tab") return;
|
|
2987
|
-
const elements = getFocusable();
|
|
2988
|
-
if (elements.length === 0) return;
|
|
2989
|
-
const first = elements[0];
|
|
2990
|
-
const last = elements[elements.length - 1];
|
|
2991
|
-
if (e.shiftKey) {
|
|
2992
|
-
if (document.activeElement === first) {
|
|
2993
|
-
e.preventDefault();
|
|
2994
|
-
last.focus();
|
|
2995
|
-
}
|
|
2996
|
-
} else {
|
|
2997
|
-
if (document.activeElement === last) {
|
|
2998
|
-
e.preventDefault();
|
|
2999
|
-
first.focus();
|
|
3000
|
-
}
|
|
3001
|
-
}
|
|
3002
|
-
};
|
|
3003
|
-
container.addEventListener("keydown", handleKeyDown);
|
|
3004
|
-
return () => {
|
|
3005
|
-
container.removeEventListener("keydown", handleKeyDown);
|
|
3006
|
-
if (previouslyFocused && document.body.contains(previouslyFocused)) {
|
|
3007
|
-
previouslyFocused.focus();
|
|
3008
|
-
}
|
|
3009
|
-
};
|
|
3010
|
-
}, [active, ref]);
|
|
3011
|
-
}
|
|
3012
|
-
|
|
3013
|
-
// src/components/shared/Popover.tsx
|
|
3014
|
-
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
3015
|
-
function Popover({
|
|
3016
|
-
isOpen,
|
|
3017
|
-
onClose,
|
|
3018
|
-
anchorRef,
|
|
3019
|
-
children,
|
|
3020
|
-
align = "auto",
|
|
3021
|
-
className
|
|
3022
|
-
}) {
|
|
3023
|
-
const panelRef = useRef9(null);
|
|
3024
|
-
const [resolvedAlign, setResolvedAlign] = useState13("start");
|
|
3025
|
-
useFocusTrap(panelRef, isOpen);
|
|
3026
|
-
useLayoutEffect(() => {
|
|
3027
|
-
if (!isOpen || align !== "auto") {
|
|
3028
|
-
if (!isOpen) setResolvedAlign("start");
|
|
3029
|
-
return;
|
|
3030
|
-
}
|
|
3031
|
-
const panel = panelRef.current;
|
|
3032
|
-
if (!panel) return;
|
|
3033
|
-
panel.style.left = "0";
|
|
3034
|
-
panel.style.right = "auto";
|
|
3035
|
-
const rect = panel.getBoundingClientRect();
|
|
3036
|
-
if (rect.right > window.innerWidth) {
|
|
3037
|
-
setResolvedAlign("end");
|
|
3038
|
-
} else {
|
|
3039
|
-
setResolvedAlign("start");
|
|
3040
|
-
}
|
|
3041
|
-
panel.style.left = "";
|
|
3042
|
-
panel.style.right = "";
|
|
3043
|
-
}, [isOpen, align]);
|
|
3044
|
-
useEffect11(() => {
|
|
3045
|
-
if (!isOpen) return;
|
|
3046
|
-
function onKeyDown(e) {
|
|
3047
|
-
if (e.key === "Escape") onClose();
|
|
3048
|
-
}
|
|
3049
|
-
function onMouseDown(e) {
|
|
3050
|
-
const target = e.target;
|
|
3051
|
-
if (panelRef.current?.contains(target)) return;
|
|
3052
|
-
if (anchorRef.current?.contains(target)) return;
|
|
3053
|
-
onClose();
|
|
3054
|
-
}
|
|
3055
|
-
document.addEventListener("keydown", onKeyDown);
|
|
3056
|
-
document.addEventListener("mousedown", onMouseDown);
|
|
3057
|
-
return () => {
|
|
3058
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
3059
|
-
document.removeEventListener("mousedown", onMouseDown);
|
|
3060
|
-
};
|
|
3061
|
-
}, [isOpen, onClose, anchorRef]);
|
|
3062
|
-
if (!isOpen) return null;
|
|
3063
|
-
const effectiveAlign = align === "auto" ? resolvedAlign : align;
|
|
3064
|
-
return /* @__PURE__ */ jsx34(
|
|
3065
|
-
"div",
|
|
3066
|
-
{
|
|
3067
|
-
ref: panelRef,
|
|
3068
|
-
role: "dialog",
|
|
3069
|
-
"aria-modal": "false",
|
|
3070
|
-
className: cn(
|
|
3071
|
-
"absolute top-full z-50 mt-1 rounded-md border border-base-200 bg-base shadow-lg",
|
|
3072
|
-
effectiveAlign === "end" ? "right-0" : "left-0",
|
|
3073
|
-
className
|
|
3074
|
-
),
|
|
3075
|
-
children
|
|
3076
|
-
}
|
|
3077
|
-
);
|
|
3078
|
-
}
|
|
3079
|
-
|
|
3080
|
-
// src/components/shared/PopoverItem.tsx
|
|
3081
|
-
import { forwardRef as forwardRef5 } from "react";
|
|
3082
|
-
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
3083
|
-
var PopoverItem = forwardRef5(
|
|
3084
|
-
function PopoverItem2({ className, children, ...rest }, ref) {
|
|
3085
|
-
return /* @__PURE__ */ jsx35(
|
|
3086
|
-
"button",
|
|
3087
|
-
{
|
|
3088
|
-
ref,
|
|
3089
|
-
type: "button",
|
|
3090
|
-
className: cn(
|
|
3091
|
-
"flex w-full cursor-pointer items-center gap-3 px-3 py-1.5 text-left text-xs hover:bg-base-accent",
|
|
3092
|
-
className
|
|
3093
|
-
),
|
|
3094
|
-
...rest,
|
|
3095
|
-
children
|
|
3096
|
-
}
|
|
3097
|
-
);
|
|
3098
|
-
}
|
|
3099
|
-
);
|
|
3100
|
-
|
|
3101
|
-
// src/components/editor/ColSpanControl.tsx
|
|
3102
|
-
import { jsx as jsx36, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1348
|
+
import { jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3103
1349
|
function ColSpanControl({ colSpan, columns, onChange }) {
|
|
3104
|
-
const buttonRef =
|
|
3105
|
-
const [open, setOpen] =
|
|
1350
|
+
const buttonRef = useRef3(null);
|
|
1351
|
+
const [open, setOpen] = useState6(false);
|
|
3106
1352
|
if (columns <= 1) return null;
|
|
3107
1353
|
const current = Math.min(Math.max(colSpan, 1), columns);
|
|
3108
|
-
return /* @__PURE__ */
|
|
3109
|
-
/* @__PURE__ */
|
|
1354
|
+
return /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
|
|
1355
|
+
/* @__PURE__ */ jsx16(
|
|
3110
1356
|
"button",
|
|
3111
1357
|
{
|
|
3112
1358
|
ref: buttonRef,
|
|
@@ -3116,10 +1362,10 @@ function ColSpanControl({ colSpan, columns, onChange }) {
|
|
|
3116
1362
|
"aria-expanded": open,
|
|
3117
1363
|
onClick: () => setOpen((v) => !v),
|
|
3118
1364
|
className: "pointer-events-auto inline-flex cursor-pointer items-center gap-1 rounded p-1 text-xs text-base-contrast-light hover:text-primary",
|
|
3119
|
-
children: /* @__PURE__ */
|
|
1365
|
+
children: /* @__PURE__ */ jsx16(Columns3, { size: 14 })
|
|
3120
1366
|
}
|
|
3121
1367
|
),
|
|
3122
|
-
/* @__PURE__ */
|
|
1368
|
+
/* @__PURE__ */ jsx16(Popover, { isOpen: open, onClose: () => setOpen(false), anchorRef: buttonRef, className: "min-w-28", children: /* @__PURE__ */ jsx16("ul", { role: "list", className: "py-1", children: Array.from({ length: columns }, (_, i) => i + 1).map((span) => /* @__PURE__ */ jsx16("li", { children: /* @__PURE__ */ jsxs7(
|
|
3123
1369
|
PopoverItem,
|
|
3124
1370
|
{
|
|
3125
1371
|
"aria-current": span === current,
|
|
@@ -3138,8 +1384,8 @@ function ColSpanControl({ colSpan, columns, onChange }) {
|
|
|
3138
1384
|
}
|
|
3139
1385
|
|
|
3140
1386
|
// src/components/editor/ChildBlockWrapper.tsx
|
|
3141
|
-
import { jsx as
|
|
3142
|
-
var ChildBlockWrapper =
|
|
1387
|
+
import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1388
|
+
var ChildBlockWrapper = forwardRef(
|
|
3143
1389
|
function ChildBlockWrapper2({
|
|
3144
1390
|
label,
|
|
3145
1391
|
columns,
|
|
@@ -3154,7 +1400,7 @@ var ChildBlockWrapper = forwardRef6(
|
|
|
3154
1400
|
onOpenSettings,
|
|
3155
1401
|
children
|
|
3156
1402
|
}, ref) {
|
|
3157
|
-
return /* @__PURE__ */
|
|
1403
|
+
return /* @__PURE__ */ jsxs8(
|
|
3158
1404
|
"div",
|
|
3159
1405
|
{
|
|
3160
1406
|
ref,
|
|
@@ -3164,39 +1410,39 @@ var ChildBlockWrapper = forwardRef6(
|
|
|
3164
1410
|
"hover:outline hover:outline-2 hover:outline-primary/30"
|
|
3165
1411
|
),
|
|
3166
1412
|
children: [
|
|
3167
|
-
/* @__PURE__ */
|
|
3168
|
-
/* @__PURE__ */
|
|
3169
|
-
/* @__PURE__ */
|
|
3170
|
-
/* @__PURE__ */
|
|
3171
|
-
hasSettings && onOpenSettings && /* @__PURE__ */
|
|
3172
|
-
/* @__PURE__ */
|
|
1413
|
+
/* @__PURE__ */ jsxs8("div", { className: "absolute top-0 left-0 -translate-x-full z-20 flex flex-col items-center gap-1 opacity-0 transition-opacity group-hover/childblock:opacity-100 group-focus-within/childblock:opacity-100 pointer-events-none", children: [
|
|
1414
|
+
/* @__PURE__ */ jsx17("span", { className: "sr-only", children: label }),
|
|
1415
|
+
/* @__PURE__ */ jsx17("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx17(DragHandle2, { ref: dragHandleRef }) }),
|
|
1416
|
+
/* @__PURE__ */ jsx17("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx17(ColSpanControl, { colSpan, columns, onChange: onColSpanChange }) }),
|
|
1417
|
+
hasSettings && onOpenSettings && /* @__PURE__ */ jsx17("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx17(SettingsButton, { onClick: onOpenSettings }) }),
|
|
1418
|
+
/* @__PURE__ */ jsx17("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx17(
|
|
3173
1419
|
"button",
|
|
3174
1420
|
{
|
|
3175
1421
|
type: "button",
|
|
3176
1422
|
"aria-label": "Duplicate block",
|
|
3177
1423
|
onClick: onDuplicate,
|
|
3178
1424
|
className: "cursor-pointer rounded p-1 text-base-contrast-light hover:text-primary",
|
|
3179
|
-
children: /* @__PURE__ */
|
|
1425
|
+
children: /* @__PURE__ */ jsx17(CopyPlus2, { size: 16 })
|
|
3180
1426
|
}
|
|
3181
1427
|
) }),
|
|
3182
|
-
/* @__PURE__ */
|
|
1428
|
+
/* @__PURE__ */ jsx17("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx17(DeleteButton, { onDelete }) })
|
|
3183
1429
|
] }),
|
|
3184
|
-
closestEdge === "left" && /* @__PURE__ */
|
|
1430
|
+
closestEdge === "left" && /* @__PURE__ */ jsx17(
|
|
3185
1431
|
"div",
|
|
3186
1432
|
{
|
|
3187
1433
|
"data-drop-edge": "left",
|
|
3188
1434
|
className: "absolute bottom-0 left-0 top-0 z-10 w-0.5 -translate-x-1 bg-primary"
|
|
3189
1435
|
}
|
|
3190
1436
|
),
|
|
3191
|
-
closestEdge === "right" && /* @__PURE__ */
|
|
1437
|
+
closestEdge === "right" && /* @__PURE__ */ jsx17(
|
|
3192
1438
|
"div",
|
|
3193
1439
|
{
|
|
3194
1440
|
"data-drop-edge": "right",
|
|
3195
1441
|
className: "absolute bottom-0 right-0 top-0 z-10 w-0.5 translate-x-1 bg-primary"
|
|
3196
1442
|
}
|
|
3197
1443
|
),
|
|
3198
|
-
closestEdge === "top" && /* @__PURE__ */
|
|
3199
|
-
closestEdge === "bottom" && /* @__PURE__ */
|
|
1444
|
+
closestEdge === "top" && /* @__PURE__ */ jsx17("div", { "data-drop-edge": "top", className: "absolute left-0 right-0 top-0 z-10 h-0.5 -translate-y-1 bg-primary" }),
|
|
1445
|
+
closestEdge === "bottom" && /* @__PURE__ */ jsx17("div", { "data-drop-edge": "bottom", className: "absolute left-0 right-0 bottom-0 z-10 h-0.5 translate-y-1 bg-primary" }),
|
|
3200
1446
|
children
|
|
3201
1447
|
]
|
|
3202
1448
|
}
|
|
@@ -3204,334 +1450,14 @@ var ChildBlockWrapper = forwardRef6(
|
|
|
3204
1450
|
}
|
|
3205
1451
|
);
|
|
3206
1452
|
|
|
3207
|
-
// src/components/editor/SettingsForm.tsx
|
|
3208
|
-
import { useId as useId4, useState as useState16 } from "react";
|
|
3209
|
-
|
|
3210
|
-
// src/components/shared/Select.tsx
|
|
3211
|
-
import { useId as useId3 } from "react";
|
|
3212
|
-
import { ChevronDown } from "lucide-react";
|
|
3213
|
-
import { jsx as jsx38, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3214
|
-
function Select({
|
|
3215
|
-
label,
|
|
3216
|
-
value,
|
|
3217
|
-
onChange,
|
|
3218
|
-
options,
|
|
3219
|
-
disabled,
|
|
3220
|
-
className,
|
|
3221
|
-
selectClassName
|
|
3222
|
-
}) {
|
|
3223
|
-
const id = useId3();
|
|
3224
|
-
return /* @__PURE__ */ jsxs20("div", { className, children: [
|
|
3225
|
-
label && /* @__PURE__ */ jsx38(FormLabel, { htmlFor: id, children: label }),
|
|
3226
|
-
/* @__PURE__ */ jsxs20("div", { className: "relative", children: [
|
|
3227
|
-
/* @__PURE__ */ jsx38(
|
|
3228
|
-
"select",
|
|
3229
|
-
{
|
|
3230
|
-
id,
|
|
3231
|
-
value,
|
|
3232
|
-
onChange: (e) => onChange(e.target.value),
|
|
3233
|
-
disabled,
|
|
3234
|
-
className: cn(
|
|
3235
|
-
"w-full appearance-none rounded border border-base-200 bg-base py-2 pr-8 pl-3 text-sm text-base-contrast",
|
|
3236
|
-
"focus:border-base-contrast focus:outline-none focus:ring-1 focus:ring-base-contrast",
|
|
3237
|
-
disabled && "cursor-not-allowed opacity-50",
|
|
3238
|
-
selectClassName
|
|
3239
|
-
),
|
|
3240
|
-
children: options.map((opt) => /* @__PURE__ */ jsx38("option", { value: opt.value, children: opt.label }, opt.value))
|
|
3241
|
-
}
|
|
3242
|
-
),
|
|
3243
|
-
/* @__PURE__ */ jsx38(
|
|
3244
|
-
ChevronDown,
|
|
3245
|
-
{
|
|
3246
|
-
size: 14,
|
|
3247
|
-
className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 text-base-contrast-light"
|
|
3248
|
-
}
|
|
3249
|
-
)
|
|
3250
|
-
] })
|
|
3251
|
-
] });
|
|
3252
|
-
}
|
|
3253
|
-
|
|
3254
|
-
// src/components/shared/LinkField.tsx
|
|
3255
|
-
import { Fragment as Fragment6, jsx as jsx39, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3256
|
-
var TARGET_OPTIONS = [
|
|
3257
|
-
{ label: "Same tab (_self)", value: "_self" },
|
|
3258
|
-
{ label: "New tab (_blank)", value: "_blank" }
|
|
3259
|
-
];
|
|
3260
|
-
function LinkField({ label, value, onChange }) {
|
|
3261
|
-
const { pages, getPageHeadings } = usePages();
|
|
3262
|
-
const isInternal = value.kind === "internal";
|
|
3263
|
-
function setMode(kind) {
|
|
3264
|
-
if (kind === value.kind) return;
|
|
3265
|
-
onChange(kind === "external" ? { kind: "external", href: "", target: value.target } : { kind: "internal", pageId: "", anchorSectionId: null, target: "_self" });
|
|
3266
|
-
}
|
|
3267
|
-
const pageId = isInternal ? value.pageId : "";
|
|
3268
|
-
const headings = pageId ? getPageHeadings(pageId) : [];
|
|
3269
|
-
return /* @__PURE__ */ jsxs21("div", { className: "flex flex-col gap-3", children: [
|
|
3270
|
-
/* @__PURE__ */ jsx39(FormLabel, { children: label }),
|
|
3271
|
-
/* @__PURE__ */ jsx39("div", { className: "flex gap-2", role: "tablist", children: ["external", "internal"].map((kind) => /* @__PURE__ */ jsx39(
|
|
3272
|
-
"button",
|
|
3273
|
-
{
|
|
3274
|
-
type: "button",
|
|
3275
|
-
role: "tab",
|
|
3276
|
-
"aria-selected": value.kind === kind,
|
|
3277
|
-
onClick: () => setMode(kind),
|
|
3278
|
-
className: cn(
|
|
3279
|
-
"cursor-pointer rounded border px-3 py-1 text-sm capitalize",
|
|
3280
|
-
value.kind === kind ? "border-primary bg-primary text-primary-contrast" : "border-base-200 text-base-contrast"
|
|
3281
|
-
),
|
|
3282
|
-
children: kind === "external" ? "External URL" : "Internal page"
|
|
3283
|
-
},
|
|
3284
|
-
kind
|
|
3285
|
-
)) }),
|
|
3286
|
-
value.kind === "external" ? /* @__PURE__ */ jsx39(
|
|
3287
|
-
Input,
|
|
3288
|
-
{
|
|
3289
|
-
label: "URL",
|
|
3290
|
-
value: value.href,
|
|
3291
|
-
placeholder: "https://...",
|
|
3292
|
-
onChange: (href) => onChange({ kind: "external", href, target: value.target })
|
|
3293
|
-
}
|
|
3294
|
-
) : /* @__PURE__ */ jsxs21(Fragment6, { children: [
|
|
3295
|
-
/* @__PURE__ */ jsx39(
|
|
3296
|
-
Select,
|
|
3297
|
-
{
|
|
3298
|
-
label: "Page",
|
|
3299
|
-
value: value.pageId,
|
|
3300
|
-
options: [{ label: "Select a page\u2026", value: "" }, ...pages.map((p) => ({ label: p.title, value: p.id }))],
|
|
3301
|
-
onChange: (pid) => onChange({ kind: "internal", pageId: pid, anchorSectionId: null, target: value.target })
|
|
3302
|
-
}
|
|
3303
|
-
),
|
|
3304
|
-
/* @__PURE__ */ jsx39(
|
|
3305
|
-
Select,
|
|
3306
|
-
{
|
|
3307
|
-
label: "Section",
|
|
3308
|
-
value: value.anchorSectionId ?? "",
|
|
3309
|
-
disabled: !pageId,
|
|
3310
|
-
options: [{ label: "None (top of page)", value: "" }, ...headings.map((h) => ({ label: h.label, value: h.id }))],
|
|
3311
|
-
onChange: (anchor) => onChange({ kind: "internal", pageId, anchorSectionId: anchor || null, target: value.target })
|
|
3312
|
-
}
|
|
3313
|
-
)
|
|
3314
|
-
] }),
|
|
3315
|
-
value.kind === "external" && /* @__PURE__ */ jsx39(
|
|
3316
|
-
Select,
|
|
3317
|
-
{
|
|
3318
|
-
label: "Opens in",
|
|
3319
|
-
value: value.target,
|
|
3320
|
-
options: TARGET_OPTIONS,
|
|
3321
|
-
onChange: (t) => onChange({ ...value, target: t })
|
|
3322
|
-
}
|
|
3323
|
-
)
|
|
3324
|
-
] });
|
|
3325
|
-
}
|
|
3326
|
-
|
|
3327
|
-
// src/components/shared/Tabs.tsx
|
|
3328
|
-
import { useState as useState15 } from "react";
|
|
3329
|
-
import { jsx as jsx40, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3330
|
-
function Tabs({ tabs, defaultTabId, activeTabId, onTabChange, fullBleedTabBar }) {
|
|
3331
|
-
const [uncontrolledId, setUncontrolledId] = useState15(defaultTabId ?? tabs[0]?.id);
|
|
3332
|
-
const isControlled = activeTabId !== void 0;
|
|
3333
|
-
const activeId = isControlled ? activeTabId : uncontrolledId;
|
|
3334
|
-
const activeTab = tabs.find((t) => t.id === activeId) ?? tabs[0];
|
|
3335
|
-
function handleSelect(id) {
|
|
3336
|
-
if (!isControlled) setUncontrolledId(id);
|
|
3337
|
-
onTabChange?.(id);
|
|
3338
|
-
}
|
|
3339
|
-
return /* @__PURE__ */ jsxs22("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
|
|
3340
|
-
/* @__PURE__ */ jsx40("div", { className: cn("border-b border-base-200", fullBleedTabBar && "-mx-6 px-6"), children: /* @__PURE__ */ jsx40("div", { className: "flex", role: "tablist", children: tabs.map((tab) => /* @__PURE__ */ jsx40(
|
|
3341
|
-
"button",
|
|
3342
|
-
{
|
|
3343
|
-
type: "button",
|
|
3344
|
-
role: "tab",
|
|
3345
|
-
"aria-selected": activeTab?.id === tab.id,
|
|
3346
|
-
onClick: () => handleSelect(tab.id),
|
|
3347
|
-
className: cn(
|
|
3348
|
-
"cursor-pointer px-4 py-2 text-sm font-medium border-b-2 -mb-px",
|
|
3349
|
-
activeTab?.id === tab.id ? "border-brand text-brand" : "border-transparent text-base-contrast-light hover:text-base-contrast"
|
|
3350
|
-
),
|
|
3351
|
-
children: tab.label
|
|
3352
|
-
},
|
|
3353
|
-
tab.id
|
|
3354
|
-
)) }) }),
|
|
3355
|
-
/* @__PURE__ */ jsx40("div", { role: "tabpanel", children: activeTab?.content })
|
|
3356
|
-
] });
|
|
3357
|
-
}
|
|
3358
|
-
|
|
3359
|
-
// src/components/editor/SettingsForm.tsx
|
|
3360
|
-
import { jsx as jsx41, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3361
|
-
function resolveValues(schema11, values) {
|
|
3362
|
-
const resolved = {};
|
|
3363
|
-
for (const [key, field] of Object.entries(schema11)) {
|
|
3364
|
-
resolved[key] = values[key] ?? field.default;
|
|
3365
|
-
}
|
|
3366
|
-
return resolved;
|
|
3367
|
-
}
|
|
3368
|
-
function coerceValue(field, value) {
|
|
3369
|
-
if (field.type === "select" && "coerce" in field && field.coerce === "number") {
|
|
3370
|
-
return Number(value);
|
|
3371
|
-
}
|
|
3372
|
-
return value;
|
|
3373
|
-
}
|
|
3374
|
-
function normalizeEmpty(field, value) {
|
|
3375
|
-
if (field.type === "select" && "emptyIsUndefined" in field && field.emptyIsUndefined && value === "") {
|
|
3376
|
-
return void 0;
|
|
3377
|
-
}
|
|
3378
|
-
return value;
|
|
3379
|
-
}
|
|
3380
|
-
function splitByTarget(schema11, allValues) {
|
|
3381
|
-
const content = {};
|
|
3382
|
-
const options = {};
|
|
3383
|
-
for (const [key, field] of Object.entries(schema11)) {
|
|
3384
|
-
const value = normalizeEmpty(field, coerceValue(field, allValues[key]));
|
|
3385
|
-
const target = field.target ?? "options";
|
|
3386
|
-
if (target === "content") {
|
|
3387
|
-
content[key] = value;
|
|
3388
|
-
} else {
|
|
3389
|
-
options[key] = value;
|
|
3390
|
-
}
|
|
3391
|
-
}
|
|
3392
|
-
return { content, options };
|
|
3393
|
-
}
|
|
3394
|
-
function RangeField({
|
|
3395
|
-
field,
|
|
3396
|
-
value,
|
|
3397
|
-
onChange
|
|
3398
|
-
}) {
|
|
3399
|
-
const id = useId4();
|
|
3400
|
-
return /* @__PURE__ */ jsxs23("div", { children: [
|
|
3401
|
-
/* @__PURE__ */ jsx41(FormLabel, { htmlFor: id, children: field.label }),
|
|
3402
|
-
/* @__PURE__ */ jsx41(
|
|
3403
|
-
"input",
|
|
3404
|
-
{
|
|
3405
|
-
id,
|
|
3406
|
-
type: "range",
|
|
3407
|
-
min: field.min,
|
|
3408
|
-
max: field.max,
|
|
3409
|
-
step: field.step,
|
|
3410
|
-
value,
|
|
3411
|
-
onChange: (e) => onChange(Number(e.target.value)),
|
|
3412
|
-
className: cn(
|
|
3413
|
-
"w-full accent-primary"
|
|
3414
|
-
)
|
|
3415
|
-
}
|
|
3416
|
-
)
|
|
3417
|
-
] });
|
|
3418
|
-
}
|
|
3419
|
-
function renderField(key, field, value, handleFieldChange) {
|
|
3420
|
-
switch (field.type) {
|
|
3421
|
-
case "text":
|
|
3422
|
-
return /* @__PURE__ */ jsx41(
|
|
3423
|
-
Input,
|
|
3424
|
-
{
|
|
3425
|
-
label: field.label,
|
|
3426
|
-
value: String(value ?? ""),
|
|
3427
|
-
placeholder: field.placeholder,
|
|
3428
|
-
onChange: (v) => handleFieldChange(key, v)
|
|
3429
|
-
},
|
|
3430
|
-
key
|
|
3431
|
-
);
|
|
3432
|
-
case "number":
|
|
3433
|
-
return /* @__PURE__ */ jsx41(
|
|
3434
|
-
Input,
|
|
3435
|
-
{
|
|
3436
|
-
label: field.label,
|
|
3437
|
-
type: "number",
|
|
3438
|
-
value: String(value ?? ""),
|
|
3439
|
-
onChange: (v) => handleFieldChange(key, v === "" ? "" : Number(v))
|
|
3440
|
-
},
|
|
3441
|
-
key
|
|
3442
|
-
);
|
|
3443
|
-
case "checkbox":
|
|
3444
|
-
return /* @__PURE__ */ jsx41(
|
|
3445
|
-
Checkbox,
|
|
3446
|
-
{
|
|
3447
|
-
label: field.label,
|
|
3448
|
-
checked: Boolean(value),
|
|
3449
|
-
onChange: (checked) => handleFieldChange(key, checked)
|
|
3450
|
-
},
|
|
3451
|
-
key
|
|
3452
|
-
);
|
|
3453
|
-
case "select":
|
|
3454
|
-
return /* @__PURE__ */ jsx41(
|
|
3455
|
-
Select,
|
|
3456
|
-
{
|
|
3457
|
-
label: field.label,
|
|
3458
|
-
value: String(value ?? ""),
|
|
3459
|
-
options: field.options,
|
|
3460
|
-
onChange: (v) => handleFieldChange(key, v)
|
|
3461
|
-
},
|
|
3462
|
-
key
|
|
3463
|
-
);
|
|
3464
|
-
case "range":
|
|
3465
|
-
return /* @__PURE__ */ jsx41(
|
|
3466
|
-
RangeField,
|
|
3467
|
-
{
|
|
3468
|
-
field,
|
|
3469
|
-
value: Number(value ?? field.min),
|
|
3470
|
-
onChange: (v) => handleFieldChange(key, v)
|
|
3471
|
-
},
|
|
3472
|
-
key
|
|
3473
|
-
);
|
|
3474
|
-
case "link":
|
|
3475
|
-
return /* @__PURE__ */ jsx41(
|
|
3476
|
-
LinkField,
|
|
3477
|
-
{
|
|
3478
|
-
label: field.label,
|
|
3479
|
-
value: value ?? field.default,
|
|
3480
|
-
onChange: (v) => handleFieldChange(key, v)
|
|
3481
|
-
},
|
|
3482
|
-
key
|
|
3483
|
-
);
|
|
3484
|
-
default:
|
|
3485
|
-
return null;
|
|
3486
|
-
}
|
|
3487
|
-
}
|
|
3488
|
-
function SettingsForm({ schema: schema11, values, onChange, tabs }) {
|
|
3489
|
-
const [local, setLocal] = useState16(() => resolveValues(schema11, values));
|
|
3490
|
-
function handleFieldChange(key, newValue) {
|
|
3491
|
-
const next = { ...local, [key]: newValue };
|
|
3492
|
-
setLocal(next);
|
|
3493
|
-
onChange(splitByTarget(schema11, next));
|
|
3494
|
-
}
|
|
3495
|
-
if (tabs) {
|
|
3496
|
-
const fields = (keys) => keys.filter((key) => key in schema11).map((key) => renderField(key, schema11[key], local[key], handleFieldChange));
|
|
3497
|
-
const listed = new Set(tabs.flatMap((t) => t.fields));
|
|
3498
|
-
const otherKeys = Object.keys(schema11).filter((key) => !listed.has(key));
|
|
3499
|
-
const tabItems = [
|
|
3500
|
-
...tabs.map((t) => ({ id: t.label, label: t.label, content: /* @__PURE__ */ jsx41("div", { className: "flex flex-col gap-4", children: fields(t.fields) }) })),
|
|
3501
|
-
...otherKeys.length > 0 ? [{ id: "__other__", label: "Other", content: /* @__PURE__ */ jsx41("div", { className: "flex flex-col gap-4", children: fields(otherKeys) }) }] : []
|
|
3502
|
-
];
|
|
3503
|
-
return /* @__PURE__ */ jsx41(Tabs, { tabs: tabItems, fullBleedTabBar: true });
|
|
3504
|
-
}
|
|
3505
|
-
return /* @__PURE__ */ jsx41("div", { className: "flex flex-col gap-4", children: Object.entries(schema11).map(([key, field]) => renderField(key, field, local[key], handleFieldChange)) });
|
|
3506
|
-
}
|
|
3507
|
-
|
|
3508
|
-
// src/hooks/useBlockDnd.ts
|
|
3509
|
-
import { useEffect as useEffect12, useRef as useRef11, useState as useState17 } from "react";
|
|
3510
|
-
|
|
3511
|
-
// src/lib/block-dnd.ts
|
|
3512
|
-
var ROOT_CONTAINER_ID = "__root__";
|
|
3513
|
-
function buildBlockDragData(args) {
|
|
3514
|
-
return { dragType: "block", ...args };
|
|
3515
|
-
}
|
|
3516
|
-
function buildBlockDropData(args) {
|
|
3517
|
-
return { ...args };
|
|
3518
|
-
}
|
|
3519
|
-
function isBlockDragData(data) {
|
|
3520
|
-
return data.dragType === "block";
|
|
3521
|
-
}
|
|
3522
|
-
function canDropBlock(source, dropContainerId) {
|
|
3523
|
-
if (source.blockId === dropContainerId) return false;
|
|
3524
|
-
if (source.isContainer && dropContainerId !== ROOT_CONTAINER_ID) return false;
|
|
3525
|
-
return true;
|
|
3526
|
-
}
|
|
3527
|
-
|
|
3528
1453
|
// src/hooks/useBlockDnd.ts
|
|
1454
|
+
import { useEffect as useEffect4, useRef as useRef4, useState as useState7 } from "react";
|
|
3529
1455
|
function useBlockDnd({ blockId, containerId, index, isContainer, allowedEdges, enabled }) {
|
|
3530
|
-
const dragRef =
|
|
3531
|
-
const handleRef =
|
|
3532
|
-
const [closestEdge, setClosestEdge] =
|
|
3533
|
-
const [isDragging, setIsDragging] =
|
|
3534
|
-
|
|
1456
|
+
const dragRef = useRef4(null);
|
|
1457
|
+
const handleRef = useRef4(null);
|
|
1458
|
+
const [closestEdge, setClosestEdge] = useState7(null);
|
|
1459
|
+
const [isDragging, setIsDragging] = useState7(false);
|
|
1460
|
+
useEffect4(() => {
|
|
3535
1461
|
const element = dragRef.current;
|
|
3536
1462
|
const handle = handleRef.current;
|
|
3537
1463
|
if (!element || !enabled) return;
|
|
@@ -3587,9 +1513,9 @@ function useBlockDnd({ blockId, containerId, index, isContainer, allowedEdges, e
|
|
|
3587
1513
|
return { dragRef, handleRef, closestEdge, isDragging };
|
|
3588
1514
|
}
|
|
3589
1515
|
function useBlockDropZone({ containerId, index, toColumn, allowedEdges, enabled }) {
|
|
3590
|
-
const dropRef =
|
|
3591
|
-
const [closestEdge, setClosestEdge] =
|
|
3592
|
-
|
|
1516
|
+
const dropRef = useRef4(null);
|
|
1517
|
+
const [closestEdge, setClosestEdge] = useState7(null);
|
|
1518
|
+
useEffect4(() => {
|
|
3593
1519
|
const element = dropRef.current;
|
|
3594
1520
|
if (!element || !enabled) return;
|
|
3595
1521
|
let cleanup;
|
|
@@ -3686,7 +1612,7 @@ function trimTrailingSpacers(container) {
|
|
|
3686
1612
|
}
|
|
3687
1613
|
|
|
3688
1614
|
// src/components/sections/Container/Container.tsx
|
|
3689
|
-
import { jsx as
|
|
1615
|
+
import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3690
1616
|
var ROW_EDGES = ["left", "right"];
|
|
3691
1617
|
var COL_EDGES = ["top", "bottom"];
|
|
3692
1618
|
function ContainerChild({
|
|
@@ -3717,14 +1643,14 @@ function ContainerChild({
|
|
|
3717
1643
|
allowedEdges: flow === "column" ? COL_EDGES : ROW_EDGES,
|
|
3718
1644
|
enabled: true
|
|
3719
1645
|
});
|
|
3720
|
-
return /* @__PURE__ */
|
|
1646
|
+
return /* @__PURE__ */ jsx18(
|
|
3721
1647
|
"div",
|
|
3722
1648
|
{
|
|
3723
1649
|
ref: dragRef,
|
|
3724
1650
|
className: cellClass,
|
|
3725
1651
|
"data-child-index": index,
|
|
3726
1652
|
"data-child-id": child.id,
|
|
3727
|
-
children: /* @__PURE__ */
|
|
1653
|
+
children: /* @__PURE__ */ jsx18(
|
|
3728
1654
|
ChildBlockWrapper,
|
|
3729
1655
|
{
|
|
3730
1656
|
label,
|
|
@@ -3738,7 +1664,7 @@ function ContainerChild({
|
|
|
3738
1664
|
onDuplicate,
|
|
3739
1665
|
onColSpanChange,
|
|
3740
1666
|
onOpenSettings,
|
|
3741
|
-
children: /* @__PURE__ */
|
|
1667
|
+
children: /* @__PURE__ */ jsx18(
|
|
3742
1668
|
ChildComp,
|
|
3743
1669
|
{
|
|
3744
1670
|
content: child,
|
|
@@ -3766,7 +1692,7 @@ function EmptyColumnCell({
|
|
|
3766
1692
|
enabled: true
|
|
3767
1693
|
});
|
|
3768
1694
|
const active = closestEdge !== null;
|
|
3769
|
-
return /* @__PURE__ */
|
|
1695
|
+
return /* @__PURE__ */ jsx18(
|
|
3770
1696
|
"div",
|
|
3771
1697
|
{
|
|
3772
1698
|
ref: dropRef,
|
|
@@ -3804,7 +1730,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
3804
1730
|
flow === "column" && "grid-flow-col"
|
|
3805
1731
|
);
|
|
3806
1732
|
if (!editable) {
|
|
3807
|
-
return /* @__PURE__ */
|
|
1733
|
+
return /* @__PURE__ */ jsx18("div", { className: "@container", children: /* @__PURE__ */ jsx18("div", { className: gridClass, children: children.map((child, index) => {
|
|
3808
1734
|
const def = getSection(child.type);
|
|
3809
1735
|
if (!def) return null;
|
|
3810
1736
|
const Child = def.component;
|
|
@@ -3815,7 +1741,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
3815
1741
|
colSpanClass[columns]?.[Math.min(span, columns)] || void 0,
|
|
3816
1742
|
child.type === "spacer" && spacerHiddenClass[columns]
|
|
3817
1743
|
);
|
|
3818
|
-
return /* @__PURE__ */
|
|
1744
|
+
return /* @__PURE__ */ jsx18("div", { className: cellClass, children: /* @__PURE__ */ jsx18(Child, { content: child, options: mergedOptions, isEditMode }) }, child.id ?? index);
|
|
3819
1745
|
}) }) });
|
|
3820
1746
|
}
|
|
3821
1747
|
function columnStartOf(index) {
|
|
@@ -3829,7 +1755,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
3829
1755
|
const def = getSection(child.type);
|
|
3830
1756
|
if (!def) return null;
|
|
3831
1757
|
if (isSpacer(child)) {
|
|
3832
|
-
return /* @__PURE__ */
|
|
1758
|
+
return /* @__PURE__ */ jsx18(
|
|
3833
1759
|
EmptyColumnCell,
|
|
3834
1760
|
{
|
|
3835
1761
|
containerId: container.id,
|
|
@@ -3857,12 +1783,12 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
3857
1783
|
const CustomForm = def.settingsForm;
|
|
3858
1784
|
openModal(
|
|
3859
1785
|
`${def.label} Settings`,
|
|
3860
|
-
/* @__PURE__ */
|
|
1786
|
+
/* @__PURE__ */ jsx18(CustomForm, { ...seed, onChange: applyResult })
|
|
3861
1787
|
);
|
|
3862
1788
|
} else if (def.settings) {
|
|
3863
1789
|
openModal(
|
|
3864
1790
|
`${def.label} Settings`,
|
|
3865
|
-
/* @__PURE__ */
|
|
1791
|
+
/* @__PURE__ */ jsx18(
|
|
3866
1792
|
SettingsForm,
|
|
3867
1793
|
{
|
|
3868
1794
|
schema: def.settings,
|
|
@@ -3874,7 +1800,7 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
3874
1800
|
);
|
|
3875
1801
|
}
|
|
3876
1802
|
} : void 0;
|
|
3877
|
-
return /* @__PURE__ */
|
|
1803
|
+
return /* @__PURE__ */ jsx18(
|
|
3878
1804
|
ContainerChild,
|
|
3879
1805
|
{
|
|
3880
1806
|
containerId: container.id,
|
|
@@ -3900,9 +1826,9 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
3900
1826
|
}
|
|
3901
1827
|
const occupied = occupiedColumns(children, columns);
|
|
3902
1828
|
const emptyCols = occupied < columns ? columns - occupied : 0;
|
|
3903
|
-
return /* @__PURE__ */
|
|
1829
|
+
return /* @__PURE__ */ jsx18("div", { className: "@container", children: /* @__PURE__ */ jsxs9("div", { className: gridClass, children: [
|
|
3904
1830
|
children.map(renderEditChild),
|
|
3905
|
-
Array.from({ length: emptyCols }, (_, i) => /* @__PURE__ */
|
|
1831
|
+
Array.from({ length: emptyCols }, (_, i) => /* @__PURE__ */ jsx18(
|
|
3906
1832
|
EmptyColumnCell,
|
|
3907
1833
|
{
|
|
3908
1834
|
containerId: container.id,
|
|
@@ -3915,8 +1841,8 @@ function Container({ content, isEditMode, onChange, openModal }) {
|
|
|
3915
1841
|
}
|
|
3916
1842
|
|
|
3917
1843
|
// src/components/sections/Container/ContainerSettingsForm.tsx
|
|
3918
|
-
import { useState as
|
|
3919
|
-
import { jsx as
|
|
1844
|
+
import { useState as useState8 } from "react";
|
|
1845
|
+
import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3920
1846
|
function inheritableSchema(children) {
|
|
3921
1847
|
const out = {};
|
|
3922
1848
|
for (const child of children) {
|
|
@@ -3936,8 +1862,8 @@ function ContainerSettingsForm({
|
|
|
3936
1862
|
children = [],
|
|
3937
1863
|
onChange
|
|
3938
1864
|
}) {
|
|
3939
|
-
const [layout, setLayout] =
|
|
3940
|
-
const [defaults, setDefaults] =
|
|
1865
|
+
const [layout, setLayout] = useState8({ columns, flow });
|
|
1866
|
+
const [defaults, setDefaults] = useState8(childDefaults);
|
|
3941
1867
|
const childSchema = inheritableSchema(children);
|
|
3942
1868
|
const hasChildDefaults = Object.keys(childSchema).length > 0;
|
|
3943
1869
|
function emit(nextLayout, nextDefaults) {
|
|
@@ -3966,10 +1892,10 @@ function ContainerSettingsForm({
|
|
|
3966
1892
|
]
|
|
3967
1893
|
}
|
|
3968
1894
|
};
|
|
3969
|
-
return /* @__PURE__ */
|
|
3970
|
-
/* @__PURE__ */
|
|
3971
|
-
/* @__PURE__ */
|
|
3972
|
-
/* @__PURE__ */
|
|
1895
|
+
return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-6", children: [
|
|
1896
|
+
/* @__PURE__ */ jsxs10("fieldset", { className: "flex flex-col gap-4", children: [
|
|
1897
|
+
/* @__PURE__ */ jsx19("legend", { className: "mb-2 text-sm font-semibold text-base-contrast", children: "Layout" }),
|
|
1898
|
+
/* @__PURE__ */ jsx19(
|
|
3973
1899
|
SettingsForm,
|
|
3974
1900
|
{
|
|
3975
1901
|
schema: layoutSchema,
|
|
@@ -3985,9 +1911,9 @@ function ContainerSettingsForm({
|
|
|
3985
1911
|
}
|
|
3986
1912
|
)
|
|
3987
1913
|
] }),
|
|
3988
|
-
hasChildDefaults && /* @__PURE__ */
|
|
3989
|
-
/* @__PURE__ */
|
|
3990
|
-
/* @__PURE__ */
|
|
1914
|
+
hasChildDefaults && /* @__PURE__ */ jsxs10("fieldset", { className: "flex flex-col gap-4 border-t border-base-200 pt-4", children: [
|
|
1915
|
+
/* @__PURE__ */ jsx19("legend", { className: "mb-2 text-sm font-semibold text-base-contrast", children: "Apply to all items" }),
|
|
1916
|
+
/* @__PURE__ */ jsx19(
|
|
3991
1917
|
SettingsForm,
|
|
3992
1918
|
{
|
|
3993
1919
|
schema: childSchema,
|
|
@@ -4004,16 +1930,16 @@ function ContainerSettingsForm({
|
|
|
4004
1930
|
}
|
|
4005
1931
|
|
|
4006
1932
|
// src/components/sections/Container/index.tsx
|
|
4007
|
-
import { jsx as
|
|
4008
|
-
var
|
|
4009
|
-
type:
|
|
4010
|
-
content:
|
|
4011
|
-
columns:
|
|
4012
|
-
flow:
|
|
4013
|
-
childDefaults:
|
|
1933
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
1934
|
+
var schema6 = z6.object({
|
|
1935
|
+
type: z6.literal("container"),
|
|
1936
|
+
content: z6.object({
|
|
1937
|
+
columns: z6.number().int().min(1).max(MAX_CONTAINER_COLUMNS).default(1),
|
|
1938
|
+
flow: z6.enum(["row", "column"]).default("row"),
|
|
1939
|
+
childDefaults: z6.record(z6.string(), z6.unknown()).optional(),
|
|
4014
1940
|
// Recursive: children are full blocks. z.lazy defers evaluation to parse
|
|
4015
1941
|
// time, by which point every section schema (incl. container) is registered.
|
|
4016
|
-
children:
|
|
1942
|
+
children: z6.array(z6.lazy(() => getSectionSchema())).default([])
|
|
4017
1943
|
}).transform((c) => ({
|
|
4018
1944
|
...c,
|
|
4019
1945
|
children: c.children.map(
|
|
@@ -4024,42 +1950,39 @@ var schema9 = z9.object({
|
|
|
4024
1950
|
var Container_default = defineSection({
|
|
4025
1951
|
type: "container",
|
|
4026
1952
|
label: "Container",
|
|
4027
|
-
icon: /* @__PURE__ */
|
|
4028
|
-
schema:
|
|
4029
|
-
component: ({ content, onChange, isEditMode, openModal }) => /* @__PURE__ */
|
|
1953
|
+
icon: /* @__PURE__ */ jsx20(LayoutTemplate, { size: 18 }),
|
|
1954
|
+
schema: schema6,
|
|
1955
|
+
component: ({ content, onChange, isEditMode, openModal }) => /* @__PURE__ */ jsx20(Container, { content, isEditMode: !!isEditMode, onChange, openModal }),
|
|
4030
1956
|
defaults: () => ({
|
|
4031
1957
|
type: "container",
|
|
4032
1958
|
content: { columns: 1, flow: "row", children: [] }
|
|
4033
1959
|
}),
|
|
4034
|
-
getLabel: (content) => {
|
|
4035
|
-
const n = content.content.children.length;
|
|
4036
|
-
return `Container (${n} item${n === 1 ? "" : "s"})`;
|
|
4037
|
-
},
|
|
1960
|
+
getLabel: (content) => `Container (${pluralize(content.content.children.length, "item")})`,
|
|
4038
1961
|
settingsForm: ContainerSettingsForm
|
|
4039
1962
|
});
|
|
4040
1963
|
|
|
4041
1964
|
// src/components/sections/Spacer/index.tsx
|
|
4042
|
-
import { z as
|
|
1965
|
+
import { z as z7 } from "zod";
|
|
4043
1966
|
import { SquareDashed } from "lucide-react";
|
|
4044
1967
|
|
|
4045
1968
|
// src/components/sections/Spacer/Spacer.tsx
|
|
4046
|
-
import { jsx as
|
|
1969
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
4047
1970
|
function Spacer() {
|
|
4048
|
-
return /* @__PURE__ */
|
|
1971
|
+
return /* @__PURE__ */ jsx21("div", { "data-spacer": true, "aria-hidden": "true", className: "h-full" });
|
|
4049
1972
|
}
|
|
4050
1973
|
|
|
4051
1974
|
// src/components/sections/Spacer/index.tsx
|
|
4052
|
-
import { jsx as
|
|
4053
|
-
var
|
|
4054
|
-
type:
|
|
4055
|
-
content:
|
|
1975
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
1976
|
+
var schema7 = z7.object({
|
|
1977
|
+
type: z7.literal("spacer"),
|
|
1978
|
+
content: z7.object({}).default({})
|
|
4056
1979
|
});
|
|
4057
1980
|
var Spacer_default = defineSection({
|
|
4058
1981
|
type: "spacer",
|
|
4059
1982
|
label: "Spacer",
|
|
4060
|
-
icon: /* @__PURE__ */
|
|
4061
|
-
schema:
|
|
4062
|
-
component: () => /* @__PURE__ */
|
|
1983
|
+
icon: /* @__PURE__ */ jsx22(SquareDashed, { size: 18 }),
|
|
1984
|
+
schema: schema7,
|
|
1985
|
+
component: () => /* @__PURE__ */ jsx22(Spacer, {}),
|
|
4063
1986
|
defaults: () => ({ type: "spacer", content: {} })
|
|
4064
1987
|
});
|
|
4065
1988
|
|