@simple-builder/react 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/build-container-client-5QC5KVS3.mjs +8 -0
  2. package/dist/build-container-client-7Z6WZVBX.js +2291 -0
  3. package/dist/build-container-client-DWKVE65B.mjs +2258 -0
  4. package/dist/build-container-client-FN3PZMM7.mjs +2253 -0
  5. package/dist/build-container-client-GV52F5RP.js +2294 -0
  6. package/dist/build-container-client-J56NWFBF.mjs +2257 -0
  7. package/dist/build-container-client-L3WD4CG7.mjs +2255 -0
  8. package/dist/build-container-client-NXIMV3RF.js +8 -0
  9. package/dist/build-container-client-THZHNQ5S.mjs +2260 -0
  10. package/dist/build-container-client-WGVIYK47.css +1968 -0
  11. package/dist/build-container-client-WHIUDBOZ.mjs +2259 -0
  12. package/dist/build-container-client-WIGFVNOW.css +1971 -0
  13. package/dist/build-container-client-WYIHRPSW.js +2295 -0
  14. package/dist/build-container-client-XOHYMPBB.js +2289 -0
  15. package/dist/build-container-client-YDRPPWCU.js +2293 -0
  16. package/dist/build-container-client-YWNDWXO2.css +1967 -0
  17. package/dist/build-container-client-ZXO66OL5.js +2296 -0
  18. package/dist/builder-content-2MA6BKJ5.js +42 -0
  19. package/dist/builder-content-2ZXIEMS3.js +42 -0
  20. package/dist/builder-content-73ZKCEIT.mjs +20 -0
  21. package/dist/builder-content-BKE4JZ75.js +42 -0
  22. package/dist/builder-content-BU4BXER7.mjs +20 -0
  23. package/dist/builder-content-CP5VLMVD.mjs +20 -0
  24. package/dist/builder-content-CY43LFAA.js +42 -0
  25. package/dist/builder-content-FMTTH7R2.js +42 -0
  26. package/dist/builder-content-GJ4HYIOA.mjs +20 -0
  27. package/dist/builder-content-HQXSXBFZ.mjs +20 -0
  28. package/dist/builder-content-MI55X5HA.css +1971 -0
  29. package/dist/builder-content-PWV6LNFT.mjs +20 -0
  30. package/dist/builder-content-RROSPBT4.css +1968 -0
  31. package/dist/builder-content-RV3DPWFH.js +42 -0
  32. package/dist/builder-content-V2MDRHJI.css +1967 -0
  33. package/dist/chunk-2GOYHVMW.mjs +123 -0
  34. package/dist/chunk-2OHBCAZQ.mjs +244 -0
  35. package/dist/chunk-2OYBZSJQ.mjs +123 -0
  36. package/dist/chunk-3QWMKMTN.js +269 -0
  37. package/dist/chunk-454D7NIH.js +153 -0
  38. package/dist/chunk-4TVSMCQU.js +42 -0
  39. package/dist/chunk-5Q4KJW4A.mjs +20 -0
  40. package/dist/chunk-6GCMYFBT.mjs +20 -0
  41. package/dist/chunk-6KNCX5O5.mjs +123 -0
  42. package/dist/chunk-6VINC5E2.mjs +244 -0
  43. package/dist/chunk-C5GHD62W.mjs +20 -0
  44. package/dist/chunk-CARNMQP6.mjs +20 -0
  45. package/dist/chunk-CJNSRJNF.js +42 -0
  46. package/dist/chunk-DZLUIOVD.js +153 -0
  47. package/dist/chunk-EVMN5SX2.js +269 -0
  48. package/dist/chunk-EZFQOJHG.mjs +244 -0
  49. package/dist/chunk-H357GPTV.mjs +244 -0
  50. package/dist/chunk-H6OM2V2U.mjs +20 -0
  51. package/dist/chunk-HCM5NR6G.js +269 -0
  52. package/dist/chunk-IQX5LONG.js +153 -0
  53. package/dist/chunk-MBISMJDL.js +269 -0
  54. package/dist/chunk-NDE4WSBA.js +269 -0
  55. package/dist/chunk-OWZPAOR6.mjs +244 -0
  56. package/dist/chunk-PADTJYXB.mjs +20 -0
  57. package/dist/chunk-QZQRUNAY.js +153 -0
  58. package/dist/chunk-RZFAIM2Q.mjs +123 -0
  59. package/dist/chunk-SFYJAJOD.js +42 -0
  60. package/dist/chunk-SLWJHIVH.mjs +123 -0
  61. package/dist/chunk-TMDKQB2L.js +153 -0
  62. package/dist/chunk-VCXFPTGD.js +42 -0
  63. package/dist/chunk-VNNNLYSW.js +42 -0
  64. package/dist/chunk-WA7TKN6M.js +42 -0
  65. package/dist/chunk-WPBR7BJZ.js +269 -0
  66. package/dist/chunk-X5A4S44V.mjs +244 -0
  67. package/dist/chunk-XZNO7DXS.js +153 -0
  68. package/dist/chunk-ZZT7HGAM.mjs +123 -0
  69. package/dist/index.css +3 -0
  70. package/dist/index.js +6 -6
  71. package/dist/index.mjs +2 -2
  72. package/package.json +2 -2
@@ -0,0 +1,2289 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ require('./chunk-CJNSRJNF.js');
5
+ var chunk3QWMKMTN_js = require('./chunk-3QWMKMTN.js');
6
+ var chunkTMDKQB2L_js = require('./chunk-TMDKQB2L.js');
7
+ var React25 = require('react');
8
+ var lucideReact = require('lucide-react');
9
+ var AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
10
+ var PopoverPrimitive = require('@radix-ui/react-popover');
11
+ var react = require('@tiptap/react');
12
+ var extensionColor = require('@tiptap/extension-color');
13
+ var extensionTextStyle = require('@tiptap/extension-text-style');
14
+ var extensionUnderline = require('@tiptap/extension-underline');
15
+ var starterKit = require('@tiptap/starter-kit');
16
+ var TiptapLink = require('@tiptap/extension-link');
17
+ var state = require('@tiptap/pm/state');
18
+ var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
19
+ var SeparatorPrimitive = require('@radix-ui/react-separator');
20
+ var TogglePrimitive = require('@radix-ui/react-toggle');
21
+ var classVarianceAuthority = require('class-variance-authority');
22
+ var lu = require('react-icons/lu');
23
+ var ToggleGroupPrimitive = require('@radix-ui/react-toggle-group');
24
+ var DialogPrimitive = require('@radix-ui/react-dialog');
25
+ var reactSlot = require('@radix-ui/react-slot');
26
+ var reactHookForm = require('react-hook-form');
27
+ var LabelPrimitive = require('@radix-ui/react-label');
28
+ var SwitchPrimitives = require('@radix-ui/react-switch');
29
+ var zod$1 = require('@hookform/resolvers/zod');
30
+ var zod = require('zod');
31
+ var dateFns = require('date-fns');
32
+ var reactDayPicker = require('react-day-picker');
33
+ var SelectPrimitive = require('@radix-ui/react-select');
34
+ var TabsPrimitive = require('@radix-ui/react-tabs');
35
+ var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
36
+
37
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
38
+
39
+ function _interopNamespace(e) {
40
+ if (e && e.__esModule) return e;
41
+ var n = Object.create(null);
42
+ if (e) {
43
+ Object.keys(e).forEach(function (k) {
44
+ if (k !== 'default') {
45
+ var d = Object.getOwnPropertyDescriptor(e, k);
46
+ Object.defineProperty(n, k, d.get ? d : {
47
+ enumerable: true,
48
+ get: function () { return e[k]; }
49
+ });
50
+ }
51
+ });
52
+ }
53
+ n.default = e;
54
+ return Object.freeze(n);
55
+ }
56
+
57
+ var React25__namespace = /*#__PURE__*/_interopNamespace(React25);
58
+ var AlertDialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(AlertDialogPrimitive);
59
+ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
60
+ var TiptapLink__default = /*#__PURE__*/_interopDefault(TiptapLink);
61
+ var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
62
+ var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
63
+ var TogglePrimitive__namespace = /*#__PURE__*/_interopNamespace(TogglePrimitive);
64
+ var ToggleGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(ToggleGroupPrimitive);
65
+ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
66
+ var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
67
+ var SwitchPrimitives__namespace = /*#__PURE__*/_interopNamespace(SwitchPrimitives);
68
+ var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
69
+ var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
70
+ var ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespace(ScrollAreaPrimitive);
71
+
72
+ var AlertDialog = AlertDialogPrimitive__namespace.Root;
73
+ var AlertDialogTrigger = AlertDialogPrimitive__namespace.Trigger;
74
+ var AlertDialogPortal = AlertDialogPrimitive__namespace.Portal;
75
+ var AlertDialogOverlay = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
76
+ AlertDialogPrimitive__namespace.Overlay,
77
+ {
78
+ className: chunkTMDKQB2L_js.cn(
79
+ "sb:fixed sb:inset-0 sb:z-50 sb:bg-background/80 sb:backdrop-blur-sm data-[state=open]:sb-animate-in data-[state=closed]:sb-animate-out data-[state=closed]:sb-fade-out-0 data-[state=open]:sb-fade-in-0",
80
+ className
81
+ ),
82
+ ...props,
83
+ ref
84
+ }
85
+ ));
86
+ AlertDialogOverlay.displayName = AlertDialogPrimitive__namespace.Overlay.displayName;
87
+ var AlertDialogContent = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(AlertDialogPortal, null, /* @__PURE__ */ React25__namespace.createElement(AlertDialogOverlay, null), /* @__PURE__ */ React25__namespace.createElement(
88
+ AlertDialogPrimitive__namespace.Content,
89
+ {
90
+ ref,
91
+ className: chunkTMDKQB2L_js.cn(
92
+ "sb:fixed sb:font-roboto sb:left-[50%] sb:top-[50%] sb:z-50 sb:grid sb:w-full sb:max-w-lg sb:translate-x-[-50%] sb:translate-y-[-50%] sb:gap-4 sb:border sb:bg-background sb:p-6 sb:shadow-lg sb:duration-200 data-[state=open]:sb-animate-in data-[state=closed]:sb-animate-out data-[state=closed]:sb-fade-out-0 data-[state=open]:sb-fade-in-0 data-[state=closed]:sb-zoom-out-95 data-[state=open]:sb-zoom-in-95 data-[state=closed]:sb-slide-out-to-left-1/2 data-[state=closed]:sb-slide-out-to-top-[48%] data-[state=open]:sb-slide-in-from-left-1/2 data-[state=open]:sb-slide-in-from-top-[48%] sb:sm:rounded-lg",
93
+ className
94
+ ),
95
+ ...props
96
+ }
97
+ )));
98
+ AlertDialogContent.displayName = AlertDialogPrimitive__namespace.Content.displayName;
99
+ var AlertDialogFooter = ({
100
+ className,
101
+ ...props
102
+ }) => /* @__PURE__ */ React25__namespace.createElement(
103
+ "div",
104
+ {
105
+ className: chunkTMDKQB2L_js.cn(
106
+ "sb:flex sb:flex-col-reverse sb:sm:flex-row sb:sm:justify-end sb:sm:gap-2",
107
+ className
108
+ ),
109
+ ...props
110
+ }
111
+ );
112
+ AlertDialogFooter.displayName = "AlertDialogFooter";
113
+ var AlertDialogTitle = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
114
+ AlertDialogPrimitive__namespace.Title,
115
+ {
116
+ ref,
117
+ className: chunkTMDKQB2L_js.cn("sb:text-lg sb:font-semibold", className),
118
+ ...props
119
+ }
120
+ ));
121
+ AlertDialogTitle.displayName = AlertDialogPrimitive__namespace.Title.displayName;
122
+ var AlertDialogDescription = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
123
+ AlertDialogPrimitive__namespace.Description,
124
+ {
125
+ ref,
126
+ className: chunkTMDKQB2L_js.cn("sb:text-sm sb:text-muted-foreground", className),
127
+ ...props
128
+ }
129
+ ));
130
+ AlertDialogDescription.displayName = AlertDialogPrimitive__namespace.Description.displayName;
131
+ var AlertDialogAction = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
132
+ AlertDialogPrimitive__namespace.Action,
133
+ {
134
+ ref,
135
+ className: chunkTMDKQB2L_js.cn(chunk3QWMKMTN_js.buttonVariants(), className),
136
+ ...props
137
+ }
138
+ ));
139
+ AlertDialogAction.displayName = AlertDialogPrimitive__namespace.Action.displayName;
140
+ var AlertDialogCancel = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
141
+ AlertDialogPrimitive__namespace.Cancel,
142
+ {
143
+ ref,
144
+ className: chunkTMDKQB2L_js.cn(
145
+ chunk3QWMKMTN_js.buttonVariants({ variant: "outline" }),
146
+ "sb:mt-2 sb:sm:mt-0",
147
+ className
148
+ ),
149
+ ...props
150
+ }
151
+ ));
152
+ AlertDialogCancel.displayName = AlertDialogPrimitive__namespace.Cancel.displayName;
153
+ var Popover = PopoverPrimitive__namespace.Root;
154
+ var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
155
+ var PopoverClose = PopoverPrimitive__namespace.Close;
156
+ var PopoverContent = React25__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(PopoverPrimitive__namespace.Portal, null, /* @__PURE__ */ React25__namespace.createElement(
157
+ PopoverPrimitive__namespace.Content,
158
+ {
159
+ ref,
160
+ align,
161
+ sideOffset,
162
+ className: chunkTMDKQB2L_js.cn(
163
+ "sb:z-50 sb:w-72 sb:rounded-md sb:border sb:bg-popover sb:text-popover-foreground sb:shadow-md sb:outline-hidden data-[state=open]:sb-animate-in data-[state=closed]:sb-animate-out data-[state=closed]:sb-fade-out-0 data-[state=open]:sb-fade-in-0 data-[state=closed]:sb-zoom-out-95 data-[state=open]:sb-zoom-in-95 data-[side=bottom]:sb-slide-in-from-top-2 data-[side=left]:sb-slide-in-from-right-2 data-[side=right]:sb-slide-in-from-left-2 data-[side=top]:sb-slide-in-from-bottom-2 sb:origin-(--radix-popover-content-transform-origin)",
164
+ className
165
+ ),
166
+ ...props
167
+ }
168
+ )));
169
+ PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
170
+ var Link = TiptapLink__default.default.extend({
171
+ inclusive: false,
172
+ parseHTML() {
173
+ return [{ tag: 'a[href]:not([data-type="button"]):not([href *= "javascript:" i])' }];
174
+ },
175
+ renderHTML({ HTMLAttributes }) {
176
+ return ["a", react.mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
177
+ },
178
+ addOptions() {
179
+ return {
180
+ ...this.parent?.(),
181
+ openOnClick: false
182
+ };
183
+ },
184
+ addProseMirrorPlugins() {
185
+ return [
186
+ ...this.parent?.() || [],
187
+ new state.Plugin({
188
+ props: {
189
+ handleClick(view, pos) {
190
+ const { schema: schema2, doc, tr } = view.state;
191
+ const range = react.getMarkRange(doc.resolve(pos), schema2.marks.link);
192
+ if (!range) {
193
+ return;
194
+ }
195
+ const { from, to } = range;
196
+ const start = Math.min(from, to);
197
+ const end = Math.max(from, to);
198
+ if (pos < start || pos > end) {
199
+ return;
200
+ }
201
+ const $start = doc.resolve(start);
202
+ const $end = doc.resolve(end);
203
+ const transaction = tr.setSelection(new state.TextSelection($start, $end));
204
+ view.dispatch(transaction);
205
+ }
206
+ }
207
+ })
208
+ ];
209
+ }
210
+ });
211
+
212
+ // src/features/rich-text-editor/utils/get-output.ts
213
+ var getOutput = (editor, format2) => {
214
+ switch (format2) {
215
+ case "json":
216
+ return editor.getJSON();
217
+ case "html":
218
+ return editor.isEmpty ? "" : editor.getHTML();
219
+ default:
220
+ return editor.getText();
221
+ }
222
+ };
223
+
224
+ // src/features/rich-text-editor/hooks/useRichTextEditor.ts
225
+ var useRichTextEditor = ({
226
+ value,
227
+ output = "html",
228
+ editorClassName,
229
+ onUpdate,
230
+ onBlur,
231
+ ...options
232
+ }) => {
233
+ const handleCreate = React25.useCallback(
234
+ (editor2) => {
235
+ console.count("useRichTextEditor:handleCreate");
236
+ if (value && editor2.isEmpty) {
237
+ editor2.commands.setContent(value);
238
+ }
239
+ },
240
+ [value]
241
+ );
242
+ const handleUpdate = React25.useCallback(
243
+ (editor2) => {
244
+ console.count("useRichTextEditor:handleUpdate");
245
+ onUpdate?.(getOutput(editor2, output));
246
+ },
247
+ [output, onUpdate]
248
+ );
249
+ const handleBlur = React25.useCallback(
250
+ (editor2) => {
251
+ console.count("useRichTextEditor:handleBlur");
252
+ onBlur?.(getOutput(editor2, output));
253
+ },
254
+ [output, onBlur]
255
+ );
256
+ const editor = react.useEditor({
257
+ extensions: [starterKit.StarterKit, extensionUnderline.Underline, extensionColor.Color, extensionTextStyle.TextStyle, Link],
258
+ editorProps: {
259
+ attributes: {
260
+ autocomplete: "off",
261
+ autocorrect: "off",
262
+ autocapitalize: "off",
263
+ class: chunkTMDKQB2L_js.cn("sb-focus:outline-none", editorClassName)
264
+ }
265
+ },
266
+ onCreate: ({ editor: editor2 }) => handleCreate(editor2),
267
+ onUpdate: ({ editor: editor2 }) => handleUpdate(editor2),
268
+ onBlur: ({ editor: editor2 }) => handleBlur(editor2),
269
+ ...options
270
+ });
271
+ console.count("useRichTextEditor");
272
+ return editor;
273
+ };
274
+ var DropdownMenu = DropdownMenuPrimitive__namespace.Root;
275
+ var DropdownMenuTrigger = DropdownMenuPrimitive__namespace.Trigger;
276
+ var DropdownMenuSubTrigger = React25__namespace.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
277
+ DropdownMenuPrimitive__namespace.SubTrigger,
278
+ {
279
+ ref,
280
+ className: chunkTMDKQB2L_js.cn(
281
+ "sb:flex sb:cursor-default sb:select-none sb:items-center sb:gap-2 sb:rounded-sm sb:px-2 sb:py-1.5 sb:text-sm sb:outline-hidden sb:focus:bg-accent sb:data-[state=open]:bg-accent sb:[&_svg]:pointer-events-none sb:[&_svg]:size-4 sb:[&_svg]:shrink-0",
282
+ inset && "sb:pl-8",
283
+ className
284
+ ),
285
+ ...props
286
+ },
287
+ children,
288
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.ChevronRight, { className: "sb:ml-auto" })
289
+ ));
290
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive__namespace.SubTrigger.displayName;
291
+ var DropdownMenuSubContent = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
292
+ DropdownMenuPrimitive__namespace.SubContent,
293
+ {
294
+ ref,
295
+ className: chunkTMDKQB2L_js.cn(
296
+ "sb:z-50 sb:min-w-32 sb:overflow-hidden sb:rounded-md sb:border sb:bg-popover sb:p-1 sb:text-popover-foreground sb:shadow-lg data-[state=open]:sb-animate-in data-[state=closed]:sb-animate-out data-[state=closed]:sb-fade-out-0 data-[state=open]:sb-fade-in-0 data-[state=closed]:sb-zoom-out-95 data-[state=open]:sb-zoom-in-95 data-[side=bottom]:sb-slide-in-from-top-2 data-[side=left]:sb-slide-in-from-right-2 data-[side=right]:sb-slide-in-from-left-2 data-[side=top]:sb-slide-in-from-bottom-2 sb:origin-(--radix-dropdown-menu-content-transform-origin)",
297
+ className
298
+ ),
299
+ ...props
300
+ }
301
+ ));
302
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive__namespace.SubContent.displayName;
303
+ var DropdownMenuContent = React25__namespace.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(DropdownMenuPrimitive__namespace.Portal, null, /* @__PURE__ */ React25__namespace.createElement(
304
+ DropdownMenuPrimitive__namespace.Content,
305
+ {
306
+ ref,
307
+ sideOffset,
308
+ className: chunkTMDKQB2L_js.cn(
309
+ "sb:z-50 sb:max-h-(--radix-dropdown-menu-content-available-height) sb:min-w-32 sb:overflow-y-auto sb:overflow-x-hidden sb:rounded-md sb:border sb:bg-popover sb:p-1 sb:text-popover-foreground sb:shadow-md",
310
+ "data-[state=open]:sb-animate-in data-[state=closed]:sb-animate-out data-[state=closed]:sb-fade-out-0 data-[state=open]:sb-fade-in-0 data-[state=closed]:sb-zoom-out-95 data-[state=open]:sb-zoom-in-95 data-[side=bottom]:sb-slide-in-from-top-2 data-[side=left]:sb-slide-in-from-right-2 data-[side=right]:sb-slide-in-from-left-2 data-[side=top]:sb-slide-in-from-bottom-2 sb:origin-(--radix-dropdown-menu-content-transform-origin)",
311
+ className
312
+ ),
313
+ ...props
314
+ }
315
+ )));
316
+ DropdownMenuContent.displayName = DropdownMenuPrimitive__namespace.Content.displayName;
317
+ var DropdownMenuItem = React25__namespace.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
318
+ DropdownMenuPrimitive__namespace.Item,
319
+ {
320
+ ref,
321
+ className: chunkTMDKQB2L_js.cn(
322
+ "sb:relative sb:flex sb:cursor-default sb:select-none sb:items-center sb:gap-2 sb:rounded-sm sb:px-2 sb:py-1.5 sb:text-sm sb:outline-hidden sb:transition-colors sb:focus:bg-accent sb:focus:text-accent-foreground sb:data-disabled:pointer-events-none sb:data-disabled:opacity-50 sb:[&>svg]:size-4 sb:[&>svg]:shrink-0",
323
+ inset && "sb:pl-8",
324
+ className
325
+ ),
326
+ ...props
327
+ }
328
+ ));
329
+ DropdownMenuItem.displayName = DropdownMenuPrimitive__namespace.Item.displayName;
330
+ var DropdownMenuCheckboxItem = React25__namespace.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
331
+ DropdownMenuPrimitive__namespace.CheckboxItem,
332
+ {
333
+ ref,
334
+ className: chunkTMDKQB2L_js.cn(
335
+ "sb:relative sb:flex sb:cursor-default sb:select-none sb:items-center sb:rounded-sm sb:py-1.5 sb:pl-8 sb:pr-2 sb:text-sm sb:outline-hidden sb:transition-colors sb:focus:bg-accent sb:focus:text-accent-foreground sb:data-disabled:pointer-events-none sb:data-disabled:opacity-50",
336
+ className
337
+ ),
338
+ checked,
339
+ ...props
340
+ },
341
+ /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:absolute sb:left-2 sb:flex sb:h-3.5 sb:w-3.5 sb:items-center sb:justify-center" }, /* @__PURE__ */ React25__namespace.createElement(DropdownMenuPrimitive__namespace.ItemIndicator, null, /* @__PURE__ */ React25__namespace.createElement(lucideReact.Check, { className: "sb:h-4 sb:w-4" }))),
342
+ children
343
+ ));
344
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive__namespace.CheckboxItem.displayName;
345
+ var DropdownMenuRadioItem = React25__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
346
+ DropdownMenuPrimitive__namespace.RadioItem,
347
+ {
348
+ ref,
349
+ className: chunkTMDKQB2L_js.cn(
350
+ "sb:relative sb:flex sb:cursor-default sb:select-none sb:items-center sb:rounded-sm sb:py-1.5 sb:pl-8 sb:pr-2 sb:text-sm sb:outline-hidden sb:transition-colors sb:focus:bg-accent sb:focus:text-accent-foreground sb:data-disabled:pointer-events-none sb:data-disabled:opacity-50",
351
+ className
352
+ ),
353
+ ...props
354
+ },
355
+ /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:absolute sb:left-2 sb:flex sb:h-3.5 sb:w-3.5 sb:items-center sb:justify-center" }, /* @__PURE__ */ React25__namespace.createElement(DropdownMenuPrimitive__namespace.ItemIndicator, null, /* @__PURE__ */ React25__namespace.createElement(lucideReact.Circle, { className: "sb:h-2 sb:w-2 sb:fill-current" }))),
356
+ children
357
+ ));
358
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive__namespace.RadioItem.displayName;
359
+ var DropdownMenuLabel = React25__namespace.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
360
+ DropdownMenuPrimitive__namespace.Label,
361
+ {
362
+ ref,
363
+ className: chunkTMDKQB2L_js.cn(
364
+ "sb:px-2 sb:py-1.5 sb:text-sm sb:font-semibold",
365
+ inset && "sb:pl-8",
366
+ className
367
+ ),
368
+ ...props
369
+ }
370
+ ));
371
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive__namespace.Label.displayName;
372
+ var DropdownMenuSeparator = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
373
+ DropdownMenuPrimitive__namespace.Separator,
374
+ {
375
+ ref,
376
+ className: chunkTMDKQB2L_js.cn("sb:-mx-1 sb:my-1 sb:h-px sb:bg-muted", className),
377
+ ...props
378
+ }
379
+ ));
380
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive__namespace.Separator.displayName;
381
+ var Separator2 = React25__namespace.forwardRef(
382
+ ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
383
+ SeparatorPrimitive__namespace.Root,
384
+ {
385
+ ref,
386
+ decorative,
387
+ orientation,
388
+ className: chunkTMDKQB2L_js.cn(
389
+ "sb:shrink-0 sb:bg-border",
390
+ orientation === "horizontal" ? "sb:h-px sb:w-full" : "sb:h-full sb:w-px",
391
+ className
392
+ ),
393
+ ...props
394
+ }
395
+ )
396
+ );
397
+ Separator2.displayName = SeparatorPrimitive__namespace.Root.displayName;
398
+ var toggleVariants = classVarianceAuthority.cva(
399
+ "sb:inline-flex sb:items-center sb:justify-center sb:gap-2 sb:rounded-md sb:text-sm sb:font-medium sb:transition-colors sb:hover:bg-muted sb:hover:text-muted-foreground sb:focus-visible:outline-hidden sb:focus-visible:ring-1 sb:focus-visible:ring-ring sb:disabled:pointer-events-none sb:disabled:opacity-50 sb:data-[state=on]:bg-accent sb:data-[state=on]:text-accent-foreground sb:[&_svg]:pointer-events-none sb:[&_svg]:size-4 sb:[&_svg]:shrink-0",
400
+ {
401
+ variants: {
402
+ variant: {
403
+ default: "sb:bg-transparent",
404
+ outline: "sb:border sb:border-input sb:bg-transparent sb:shadow-sm sb:hover:bg-accent sb:hover:text-accent-foreground"
405
+ },
406
+ size: {
407
+ default: "sb:h-9 sb:px-2 sb:min-w-9",
408
+ sm: "sb:h-8 sb:px-1.5 sb:min-w-8",
409
+ lg: "sb:h-10 sb:px-2.5 sb:min-w-10"
410
+ }
411
+ },
412
+ defaultVariants: {
413
+ variant: "default",
414
+ size: "default"
415
+ }
416
+ }
417
+ );
418
+ var Toggle = React25__namespace.forwardRef(({ className, variant, size, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
419
+ TogglePrimitive__namespace.Root,
420
+ {
421
+ ref,
422
+ className: chunkTMDKQB2L_js.cn(toggleVariants({ variant, size, className })),
423
+ ...props
424
+ }
425
+ ));
426
+ Toggle.displayName = TogglePrimitive__namespace.Root.displayName;
427
+ var ToggleGroupContext = React25__namespace.createContext({
428
+ size: "default",
429
+ variant: "default"
430
+ });
431
+ var ToggleGroup = React25__namespace.forwardRef(({ className, variant, size, children, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
432
+ ToggleGroupPrimitive__namespace.Root,
433
+ {
434
+ ref,
435
+ className: chunkTMDKQB2L_js.cn("sb:flex sb:items-center sb:justify-center sb:gap-1", className),
436
+ ...props
437
+ },
438
+ /* @__PURE__ */ React25__namespace.createElement(ToggleGroupContext.Provider, { value: { variant, size } }, children)
439
+ ));
440
+ ToggleGroup.displayName = ToggleGroupPrimitive__namespace.Root.displayName;
441
+ var ToggleGroupItem = React25__namespace.forwardRef(({ className, children, variant, size, ...props }, ref) => {
442
+ const context = React25__namespace.useContext(ToggleGroupContext);
443
+ return /* @__PURE__ */ React25__namespace.createElement(
444
+ ToggleGroupPrimitive__namespace.Item,
445
+ {
446
+ ref,
447
+ className: chunkTMDKQB2L_js.cn(
448
+ toggleVariants({
449
+ variant: context.variant || variant,
450
+ size: context.size || size
451
+ }),
452
+ className
453
+ ),
454
+ ...props
455
+ },
456
+ children
457
+ );
458
+ });
459
+ ToggleGroupItem.displayName = ToggleGroupPrimitive__namespace.Item.displayName;
460
+ var PALETTES = [
461
+ {
462
+ inverse: "hsl(var(--background))",
463
+ colors: [
464
+ { cssVar: "hsl(var(--foreground))" },
465
+ { cssVar: "hsl(var(--primary-foreground))" },
466
+ { cssVar: "hsl(var(--secondary-foreground))" },
467
+ { cssVar: "hsl(var(--tertiary-foreground))" },
468
+ { cssVar: "hsl(var(--muted-foreground))" },
469
+ { cssVar: "hsl(var(--accent-foreground))" },
470
+ { cssVar: "hsl(var(--destructive-foreground))" }
471
+ ]
472
+ },
473
+ {
474
+ inverse: "hsl(var(--foreground))",
475
+ colors: [
476
+ { cssVar: "hsl(var(--background))" },
477
+ { cssVar: "hsl(var(--primary))" },
478
+ { cssVar: "hsl(var(--secondary))" },
479
+ { cssVar: "hsl(var(--tertiary))" },
480
+ { cssVar: "hsl(var(--muted))" },
481
+ { cssVar: "hsl(var(--accent))" },
482
+ { cssVar: "hsl(var(--destructive))" }
483
+ ]
484
+ }
485
+ ];
486
+ var ColorTool = ({ editor }) => {
487
+ const color = editor.getAttributes("textStyle")?.color || "hsl(var(--foreground))";
488
+ const [selectedColor, setSelectedColor] = React25__namespace.useState(color);
489
+ React25__namespace.useEffect(() => {
490
+ setSelectedColor(color);
491
+ }, [color]);
492
+ const handleColorChange = React25__namespace.useCallback(
493
+ (value) => {
494
+ setSelectedColor(value);
495
+ editor.chain().focus().setColor(value).run();
496
+ },
497
+ [editor]
498
+ );
499
+ return /* @__PURE__ */ React25__namespace.createElement(Popover, { modal: true }, /* @__PURE__ */ React25__namespace.createElement(PopoverTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(ToolbarButton, { className: "sb:w-12" }, /* @__PURE__ */ React25__namespace.createElement(
500
+ "svg",
501
+ {
502
+ xmlns: "http://www.w3.org/2000/svg",
503
+ width: "24",
504
+ height: "24",
505
+ viewBox: "0 0 24 24",
506
+ fill: "none",
507
+ stroke: "currentColor",
508
+ strokeWidth: "2",
509
+ strokeLinecap: "round",
510
+ strokeLinejoin: "round",
511
+ className: "sb:size-5",
512
+ style: { color: selectedColor }
513
+ },
514
+ /* @__PURE__ */ React25__namespace.createElement("path", { d: "M4 20h16" }),
515
+ /* @__PURE__ */ React25__namespace.createElement("path", { d: "m6 16 6-12 6 12" }),
516
+ /* @__PURE__ */ React25__namespace.createElement("path", { d: "M8 12h8" })
517
+ ), /* @__PURE__ */ React25__namespace.createElement(lu.LuChevronDown, { className: "sb:size-5" }))), /* @__PURE__ */ React25__namespace.createElement(PopoverContent, { align: "start", className: "sb:w-full" }, /* @__PURE__ */ React25__namespace.createElement(
518
+ ToggleGroup,
519
+ {
520
+ type: "single",
521
+ value: selectedColor,
522
+ onValueChange: handleColorChange,
523
+ className: "sb:flex-col sb:gap-1.5"
524
+ },
525
+ PALETTES.map((pallete, i) => /* @__PURE__ */ React25__namespace.createElement("div", { key: i, className: "sb:flex sb:gap-1.5" }, pallete.colors.map((color2, j) => /* @__PURE__ */ React25__namespace.createElement(
526
+ ToggleGroupItem,
527
+ {
528
+ tabIndex: 0,
529
+ key: j,
530
+ className: "sb:relative sb:size-7 sb:rounded-md sb:border sb:p-0",
531
+ value: color2.cssVar,
532
+ style: { backgroundColor: color2.cssVar }
533
+ },
534
+ selectedColor === color2.cssVar && /* @__PURE__ */ React25__namespace.createElement(
535
+ lu.LuCheck,
536
+ {
537
+ className: "sb:absolute sb:inset-0 sb:m-auto sb:size-6",
538
+ style: { color: pallete.inverse }
539
+ }
540
+ )
541
+ ))))
542
+ )));
543
+ };
544
+ var formatActions = [
545
+ {
546
+ label: "Normal Text",
547
+ element: "span",
548
+ className: "sb:grow"
549
+ },
550
+ {
551
+ label: "Heading 1",
552
+ element: "h1",
553
+ level: 1,
554
+ className: "sb:m-0 sb:grow sb:text-3xl sb:font-extrabold"
555
+ },
556
+ {
557
+ label: "Heading 2",
558
+ element: "h2",
559
+ level: 2,
560
+ className: "sb:m-0 sb:grow sb:text-xl sb:font-bold"
561
+ },
562
+ {
563
+ label: "Heading 3",
564
+ element: "h3",
565
+ level: 3,
566
+ className: "sb:m-0 sb:grow sb:text-lg sb:font-semibold"
567
+ },
568
+ {
569
+ label: "Heading 4",
570
+ element: "h4",
571
+ level: 4,
572
+ className: "sb:m-0 sb:grow sb:text-base sb:font-semibold"
573
+ }
574
+ ];
575
+ var ElementTool = ({ editor }) => {
576
+ const isActive = editor.isActive("heading");
577
+ const handleFormatChange = React25__namespace.useCallback(
578
+ (level) => {
579
+ if (level) {
580
+ editor.chain().focus().toggleHeading({ level }).run();
581
+ } else {
582
+ editor.chain().focus().setParagraph().run();
583
+ }
584
+ },
585
+ [editor]
586
+ );
587
+ return /* @__PURE__ */ React25__namespace.createElement(DropdownMenu, null, /* @__PURE__ */ React25__namespace.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(
588
+ ToolbarButton,
589
+ {
590
+ className: "sb:w-12 sb:data-[state=open]:bg-accent",
591
+ pressed: isActive
592
+ },
593
+ /* @__PURE__ */ React25__namespace.createElement(lu.LuHeading, { className: "sb:size-5" }),
594
+ /* @__PURE__ */ React25__namespace.createElement(lu.LuChevronDown, { className: "sb:size-5" })
595
+ )), /* @__PURE__ */ React25__namespace.createElement(DropdownMenuContent, { align: "start" }, formatActions.map(({ element: Element, ...action }) => /* @__PURE__ */ React25__namespace.createElement(
596
+ DropdownMenuItem,
597
+ {
598
+ key: action.label,
599
+ className: chunkTMDKQB2L_js.cn({
600
+ "sb:bg-accent": action.level ? editor.isActive("heading", { level: action.level }) : editor.isActive("paragraph")
601
+ }),
602
+ onClick: () => handleFormatChange(action.level)
603
+ },
604
+ /* @__PURE__ */ React25__namespace.createElement(Element, { className: action.className }, action.label)
605
+ ))));
606
+ };
607
+ var actions = [
608
+ {
609
+ value: "bold",
610
+ label: "Bold",
611
+ icon: lu.LuBold,
612
+ action: (editor) => editor.chain().focus().toggleBold().run(),
613
+ isActive: (editor) => editor.isActive("bold"),
614
+ canExecute: (editor) => editor.can().chain().focus().toggleBold().run() && !editor.isActive("codeBlock")
615
+ },
616
+ {
617
+ value: "italic",
618
+ label: "Italic",
619
+ icon: lu.LuItalic,
620
+ action: (editor) => editor.chain().focus().toggleItalic().run(),
621
+ isActive: (editor) => editor.isActive("italic"),
622
+ canExecute: (editor) => editor.can().chain().focus().toggleItalic().run() && !editor.isActive("codeBlock")
623
+ },
624
+ {
625
+ value: "underline",
626
+ label: "Underline",
627
+ icon: lu.LuUnderline,
628
+ action: (editor) => editor.chain().focus().toggleUnderline().run(),
629
+ isActive: (editor) => editor.isActive("underline"),
630
+ canExecute: (editor) => editor.can().chain().focus().toggleUnderline().run() && !editor.isActive("codeBlock")
631
+ },
632
+ {
633
+ value: "strikethrough",
634
+ label: "Strikethrough",
635
+ icon: lu.LuStrikethrough,
636
+ action: (editor) => editor.chain().focus().toggleStrike().run(),
637
+ isActive: (editor) => editor.isActive("strike"),
638
+ canExecute: (editor) => editor.can().chain().focus().toggleStrike().run() && !editor.isActive("codeBlock")
639
+ },
640
+ {
641
+ value: "code",
642
+ label: "Code",
643
+ icon: lu.LuCode,
644
+ action: (editor) => editor.chain().focus().toggleCode().run(),
645
+ isActive: (editor) => editor.isActive("code"),
646
+ canExecute: (editor) => editor.can().chain().focus().toggleCode().run() && !editor.isActive("codeBlock")
647
+ },
648
+ {
649
+ value: "clearFormatting",
650
+ label: "Clear formatting",
651
+ icon: lu.LuRemoveFormatting,
652
+ action: (editor) => editor.chain().focus().unsetAllMarks().run(),
653
+ isActive: () => false,
654
+ canExecute: (editor) => editor.can().chain().focus().unsetAllMarks().run() && !editor.isActive("codeBlock")
655
+ }
656
+ ];
657
+ var FormatTool = ({ editor }) => {
658
+ return /* @__PURE__ */ React25__namespace.createElement(ToolbarSection, { editor, actions, mainActionCount: 1 });
659
+ };
660
+ var actions2 = [
661
+ {
662
+ value: "codeBlock",
663
+ label: "Code block",
664
+ icon: lu.LuCode,
665
+ action: (editor) => editor.chain().focus().toggleCodeBlock().run(),
666
+ isActive: (editor) => editor.isActive("codeBlock"),
667
+ canExecute: (editor) => editor.can().chain().focus().toggleCodeBlock().run()
668
+ },
669
+ {
670
+ value: "blockquote",
671
+ label: "Blockquote",
672
+ icon: lu.LuQuote,
673
+ action: (editor) => editor.chain().focus().toggleBlockquote().run(),
674
+ isActive: (editor) => editor.isActive("blockquote"),
675
+ canExecute: (editor) => editor.can().chain().focus().toggleBlockquote().run()
676
+ },
677
+ {
678
+ value: "horizontalRule",
679
+ label: "Divider",
680
+ icon: lu.LuMinus,
681
+ action: (editor) => editor.chain().focus().setHorizontalRule().run(),
682
+ isActive: () => false,
683
+ canExecute: (editor) => editor.can().chain().focus().setHorizontalRule().run()
684
+ }
685
+ ];
686
+ var InsertTool = ({ editor }) => {
687
+ return /* @__PURE__ */ React25__namespace.createElement(ToolbarSection, { editor, actions: actions2, mainActionCount: 0 });
688
+ };
689
+ var Dialog = DialogPrimitive__namespace.Root;
690
+ var DialogTrigger = DialogPrimitive__namespace.Trigger;
691
+ var DialogPortal = DialogPrimitive__namespace.Portal;
692
+ var DialogOverlay = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
693
+ DialogPrimitive__namespace.Overlay,
694
+ {
695
+ ref,
696
+ className: chunkTMDKQB2L_js.cn(
697
+ "sb:fixed sb:inset-0 sb:z-50 sb:bg-black/80 sb- data-[state=open]:sb-animate-in data-[state=closed]:sb-animate-out data-[state=closed]:sb-fade-out-0 data-[state=open]:sb-fade-in-0",
698
+ className
699
+ ),
700
+ ...props
701
+ }
702
+ ));
703
+ DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
704
+ var DialogContent = React25__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(DialogPortal, null, /* @__PURE__ */ React25__namespace.createElement(DialogOverlay, null), /* @__PURE__ */ React25__namespace.createElement(
705
+ DialogPrimitive__namespace.Content,
706
+ {
707
+ ref,
708
+ className: chunkTMDKQB2L_js.cn(
709
+ "sb:fixed sb:left-[50%] sb:top-[50%] sb:z-50 sb:grid sb:w-full sb:max-w-lg sb:translate-x-[-50%] sb:translate-y-[-50%] sb:gap-4 sb:border sb:bg-background sb:p-6 sb:shadow-lg sb:duration-200 data-[state=open]:sb-animate-in data-[state=closed]:sb-animate-out data-[state=closed]:sb-fade-out-0 data-[state=open]:sb-fade-in-0 data-[state=closed]:sb-zoom-out-95 data-[state=open]:sb-zoom-in-95 data-[state=closed]:sb-slide-out-to-left-1/2 data-[state=closed]:sb-slide-out-to-top-[48%] data-[state=open]:sb-slide-in-from-left-1/2 data-[state=open]:sb-slide-in-from-top-[48%] sb:sm:rounded-lg",
710
+ className
711
+ ),
712
+ ...props
713
+ },
714
+ children,
715
+ /* @__PURE__ */ React25__namespace.createElement(DialogPrimitive__namespace.Close, { className: "sb:absolute sb:right-4 sb:top-4 sb:rounded-sm sb:opacity-70 sb:ring-offset-background sb:transition-opacity sb:hover:opacity-100 sb:focus:outline-hidden sb:focus:ring-2 sb:focus:ring-ring sb:focus:ring-offset-2 sb:disabled:pointer-events-none sb:data-[state=open]:bg-accent sb:data-[state=open]:text-muted-foreground" }, /* @__PURE__ */ React25__namespace.createElement(lucideReact.X, { className: "sb:h-4 sb:w-4" }), /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:sr-only" }, "Close"))
716
+ )));
717
+ DialogContent.displayName = DialogPrimitive__namespace.Content.displayName;
718
+ var DialogHeader = ({
719
+ className,
720
+ ...props
721
+ }) => /* @__PURE__ */ React25__namespace.createElement(
722
+ "div",
723
+ {
724
+ className: chunkTMDKQB2L_js.cn(
725
+ "sb:flex sb:flex-col sb:gap-1.5 sb:text-center sb:sm:text-left",
726
+ className
727
+ ),
728
+ ...props
729
+ }
730
+ );
731
+ DialogHeader.displayName = "DialogHeader";
732
+ var DialogTitle = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
733
+ DialogPrimitive__namespace.Title,
734
+ {
735
+ ref,
736
+ className: chunkTMDKQB2L_js.cn(
737
+ "sb:text-lg sb:font-semibold sb:leading-none sb:tracking-tight",
738
+ className
739
+ ),
740
+ ...props
741
+ }
742
+ ));
743
+ DialogTitle.displayName = DialogPrimitive__namespace.Title.displayName;
744
+ var DialogDescription = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
745
+ DialogPrimitive__namespace.Description,
746
+ {
747
+ ref,
748
+ className: chunkTMDKQB2L_js.cn("sb:text-sm sb:text-muted-foreground", className),
749
+ ...props
750
+ }
751
+ ));
752
+ DialogDescription.displayName = DialogPrimitive__namespace.Description.displayName;
753
+ var labelVariants = classVarianceAuthority.cva(
754
+ "sb:text-sm sb:font-medium sb:leading-none sb:peer-disabled:cursor-not-allowed sb:peer-disabled:opacity-70"
755
+ );
756
+ var Label2 = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
757
+ LabelPrimitive__namespace.Root,
758
+ {
759
+ ref,
760
+ className: chunkTMDKQB2L_js.cn(labelVariants(), className),
761
+ ...props
762
+ }
763
+ ));
764
+ Label2.displayName = LabelPrimitive__namespace.Root.displayName;
765
+
766
+ // src/components/ui/form.tsx
767
+ var Form = reactHookForm.FormProvider;
768
+ var FormFieldContext = React25__namespace.createContext(
769
+ {}
770
+ );
771
+ var FormField = ({
772
+ ...props
773
+ }) => {
774
+ return /* @__PURE__ */ React25__namespace.createElement(FormFieldContext.Provider, { value: { name: props.name } }, /* @__PURE__ */ React25__namespace.createElement(reactHookForm.Controller, { ...props }));
775
+ };
776
+ var useFormField = () => {
777
+ const fieldContext = React25__namespace.useContext(FormFieldContext);
778
+ const itemContext = React25__namespace.useContext(FormItemContext);
779
+ const { getFieldState, formState } = reactHookForm.useFormContext();
780
+ const fieldState = getFieldState(fieldContext.name, formState);
781
+ if (!fieldContext) {
782
+ throw new Error("useFormField should be used within <FormField>");
783
+ }
784
+ const { id } = itemContext;
785
+ return {
786
+ id,
787
+ name: fieldContext.name,
788
+ formItemId: `${id}-form-item`,
789
+ formDescriptionId: `${id}-form-item-description`,
790
+ formMessageId: `${id}-form-item-message`,
791
+ ...fieldState
792
+ };
793
+ };
794
+ var FormItemContext = React25__namespace.createContext(
795
+ {}
796
+ );
797
+ var FormItem = React25__namespace.forwardRef(({ className, ...props }, ref) => {
798
+ const id = React25__namespace.useId();
799
+ return /* @__PURE__ */ React25__namespace.createElement(FormItemContext.Provider, { value: { id } }, /* @__PURE__ */ React25__namespace.createElement("div", { ref, className: chunkTMDKQB2L_js.cn("sb:flex sb:flex-col sb:gap-2", className), ...props }));
800
+ });
801
+ FormItem.displayName = "FormItem";
802
+ var FormLabel = React25__namespace.forwardRef(({ className, ...props }, ref) => {
803
+ const { error, formItemId } = useFormField();
804
+ return /* @__PURE__ */ React25__namespace.createElement(
805
+ Label2,
806
+ {
807
+ ref,
808
+ className: chunkTMDKQB2L_js.cn(error && "sb:text-destructive", className),
809
+ htmlFor: formItemId,
810
+ ...props
811
+ }
812
+ );
813
+ });
814
+ FormLabel.displayName = "FormLabel";
815
+ var FormControl = React25__namespace.forwardRef(({ ...props }, ref) => {
816
+ const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
817
+ return /* @__PURE__ */ React25__namespace.createElement(
818
+ reactSlot.Slot,
819
+ {
820
+ ref,
821
+ id: formItemId,
822
+ "aria-describedby": !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`,
823
+ "aria-invalid": !!error,
824
+ ...props
825
+ }
826
+ );
827
+ });
828
+ FormControl.displayName = "FormControl";
829
+ var FormDescription = React25__namespace.forwardRef(({ className, ...props }, ref) => {
830
+ const { formDescriptionId } = useFormField();
831
+ return /* @__PURE__ */ React25__namespace.createElement(
832
+ "p",
833
+ {
834
+ ref,
835
+ id: formDescriptionId,
836
+ className: chunkTMDKQB2L_js.cn("sb:text-[0.8rem] sb:text-muted-foreground", className),
837
+ ...props
838
+ }
839
+ );
840
+ });
841
+ FormDescription.displayName = "FormDescription";
842
+ var FormMessage = React25__namespace.forwardRef(({ className, children, ...props }, ref) => {
843
+ const { error, formMessageId } = useFormField();
844
+ const body = error ? String(error?.message ?? "") : children;
845
+ if (!body) {
846
+ return null;
847
+ }
848
+ return /* @__PURE__ */ React25__namespace.createElement(
849
+ "p",
850
+ {
851
+ ref,
852
+ id: formMessageId,
853
+ className: chunkTMDKQB2L_js.cn("sb:text-[0.8rem] sb:font-medium sb:text-destructive", className),
854
+ ...props
855
+ },
856
+ body
857
+ );
858
+ });
859
+ FormMessage.displayName = "FormMessage";
860
+ var Input = React25__namespace.forwardRef(
861
+ ({ className, type, ...props }, ref) => {
862
+ return /* @__PURE__ */ React25__namespace.createElement(
863
+ "input",
864
+ {
865
+ type,
866
+ className: chunkTMDKQB2L_js.cn(
867
+ "sb:flex sb:h-9 sb:w-full sb:rounded-md sb:border sb:border-input sb:bg-transparent sb:px-3 sb:py-1 sb:text-base sb:shadow-sm sb:transition-colors sb:file:border-0 sb:file:bg-transparent sb:file:text-sm sb:file:font-medium sb:file:text-foreground sb:placeholder:text-muted-foreground sb:focus-visible:outline-hidden sb:focus-visible:ring-1 sb:focus-visible:ring-ring sb:disabled:cursor-not-allowed sb:disabled:opacity-50 sb:md:text-sm",
868
+ className
869
+ ),
870
+ ref,
871
+ ...props
872
+ }
873
+ );
874
+ }
875
+ );
876
+ Input.displayName = "Input";
877
+ var AdvancedInput = React25__namespace.forwardRef(
878
+ ({ prepend, append, ...props }, ref) => {
879
+ return /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:relative" }, /* @__PURE__ */ React25__namespace.createElement(Input, { ref, className: "sb:pl-9 sb:pr-7 sb:text-right", ...props }), prepend && /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:absolute sb:font-roboto sb:top-1/2 sb:left-3 sb:-translate-y-1/2" }, prepend), append && /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:absolute sb:font-roboto sb:top-1/2 sb:right-3 sb:-translate-y-1/2" }, append));
880
+ }
881
+ );
882
+ AdvancedInput.displayName = "AdvancedInput";
883
+ var Switch = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
884
+ SwitchPrimitives__namespace.Root,
885
+ {
886
+ className: chunkTMDKQB2L_js.cn(
887
+ "sb:peer sb:inline-flex sb:h-5 sb:w-9 sb:shrink-0 sb:cursor-pointer sb:items-center sb:rounded-full sb:border-2 sb:border-transparent sb:shadow-sm sb:transition-colors sb:focus-visible:outline-hidden sb:focus-visible:ring-2 sb:focus-visible:ring-ring sb:focus-visible:ring-offset-2 sb:focus-visible:ring-offset-background sb:disabled:cursor-not-allowed sb:disabled:opacity-50 sb:data-[state=checked]:bg-primary sb:data-[state=unchecked]:bg-input",
888
+ className
889
+ ),
890
+ ...props,
891
+ ref
892
+ },
893
+ /* @__PURE__ */ React25__namespace.createElement(
894
+ SwitchPrimitives__namespace.Thumb,
895
+ {
896
+ className: chunkTMDKQB2L_js.cn(
897
+ "sb:pointer-events-none sb:block sb:h-4 sb:w-4 sb:rounded-full sb:bg-background sb:shadow-lg sb:ring-0 sb:transition-transform sb:data-[state=checked]:translate-x-4 sb:data-[state=unchecked]:translate-x-0"
898
+ )
899
+ }
900
+ )
901
+ ));
902
+ Switch.displayName = SwitchPrimitives__namespace.Root.displayName;
903
+ var LinkTool = ({ editor }) => {
904
+ const [open, setOpen] = React25__namespace.useState(false);
905
+ const { from, to } = editor.state.selection;
906
+ const text = editor.state.doc.textBetween(from, to, " ");
907
+ const handleSetLink = React25__namespace.useCallback(
908
+ (url, text2, openInNewTab) => {
909
+ editor.chain().focus().extendMarkRange("link").insertContent({
910
+ type: "text",
911
+ text: text2 || url,
912
+ marks: [
913
+ {
914
+ type: "link",
915
+ attrs: {
916
+ href: url,
917
+ target: openInNewTab ? "_blank" : ""
918
+ }
919
+ }
920
+ ]
921
+ }).setLink({ href: url }).run();
922
+ editor.commands.enter();
923
+ setOpen(false);
924
+ },
925
+ [editor]
926
+ );
927
+ return /* @__PURE__ */ React25__namespace.createElement(Dialog, { open, onOpenChange: setOpen }, /* @__PURE__ */ React25__namespace.createElement(DialogTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(
928
+ ToolbarButton,
929
+ {
930
+ pressed: editor.isActive("link"),
931
+ disabled: editor.isActive("codeBlock")
932
+ },
933
+ /* @__PURE__ */ React25__namespace.createElement(lu.LuLink2, { className: "sb:size-5" })
934
+ )), /* @__PURE__ */ React25__namespace.createElement(DialogContent, { className: "sb:w-full sb:min-w-80" }, /* @__PURE__ */ React25__namespace.createElement(LinkForm, { onSave: handleSetLink, defaultText: text })));
935
+ };
936
+ var schema = zod.z.object({
937
+ url: zod.z.string().min(0),
938
+ text: zod.z.string().optional(),
939
+ isNewTab: zod.z.boolean().optional()
940
+ });
941
+ var LinkForm = ({
942
+ onSave,
943
+ defaultIsNewTab,
944
+ defaultUrl,
945
+ defaultText
946
+ }) => {
947
+ const form = reactHookForm.useForm({
948
+ resolver: zod$1.zodResolver(schema),
949
+ defaultValues: {
950
+ url: defaultUrl || "",
951
+ text: defaultText || "",
952
+ isNewTab: defaultIsNewTab || false
953
+ }
954
+ });
955
+ const handleSubmit = (values) => {
956
+ onSave(values.url, values.text, values.isNewTab);
957
+ };
958
+ return /* @__PURE__ */ React25__namespace.createElement(Form, { ...form }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:flex-col sb:gap-6" }, /* @__PURE__ */ React25__namespace.createElement(
959
+ FormField,
960
+ {
961
+ control: form.control,
962
+ name: "url",
963
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "URL"), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(Input, { type: "url", ...field, autoFocus: true })), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
964
+ }
965
+ ), /* @__PURE__ */ React25__namespace.createElement(
966
+ FormField,
967
+ {
968
+ control: form.control,
969
+ name: "text",
970
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "Text"), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(Input, { ...field })), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
971
+ }
972
+ ), /* @__PURE__ */ React25__namespace.createElement(
973
+ FormField,
974
+ {
975
+ control: form.control,
976
+ name: "isNewTab",
977
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:items-center sb:gap-2" }, /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(
978
+ Switch,
979
+ {
980
+ checked: field.value,
981
+ onCheckedChange: field.onChange
982
+ }
983
+ )), /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "Open in new tab")), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
984
+ }
985
+ ), /* @__PURE__ */ React25__namespace.createElement(chunk3QWMKMTN_js.Button, { type: "button", onClick: form.handleSubmit(handleSubmit) }, "Save")));
986
+ };
987
+ var actions3 = [
988
+ {
989
+ value: "orderedList",
990
+ label: "Numbered list",
991
+ icon: lu.LuListOrdered,
992
+ action: (editor) => editor.chain().focus().toggleOrderedList().run(),
993
+ isActive: (editor) => editor.isActive("orderedList"),
994
+ canExecute: (editor) => editor.can().chain().focus().toggleOrderedList().run()
995
+ },
996
+ {
997
+ value: "bulletList",
998
+ label: "Bullet list",
999
+ icon: lu.LuList,
1000
+ action: (editor) => editor.chain().focus().toggleBulletList().run(),
1001
+ isActive: (editor) => editor.isActive("bulletList"),
1002
+ canExecute: (editor) => editor.can().chain().focus().toggleBulletList().run()
1003
+ }
1004
+ ];
1005
+ var ListTool = ({ editor }) => {
1006
+ return /* @__PURE__ */ React25__namespace.createElement(ToolbarSection, { editor, actions: actions3, mainActionCount: 2 });
1007
+ };
1008
+
1009
+ // src/features/rich-text-editor/components/toolbar.tsx
1010
+ var Toolbar = ({ editor }) => {
1011
+ return /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:shrink-0 sb:overflow-x-auto sb:border-b sb:border-border sb:p-2" }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:w-max sb:items-center sb:gap-px" }, /* @__PURE__ */ React25__namespace.createElement(ElementTool, { editor }), /* @__PURE__ */ React25__namespace.createElement(Separator2, { orientation: "vertical", className: "sb:mx-2 sb:h-7" }), /* @__PURE__ */ React25__namespace.createElement(FormatTool, { editor }), /* @__PURE__ */ React25__namespace.createElement(Separator2, { orientation: "vertical", className: "sb:mx-2 sb:h-7" }), /* @__PURE__ */ React25__namespace.createElement(ColorTool, { editor }), /* @__PURE__ */ React25__namespace.createElement(Separator2, { orientation: "vertical", className: "sb:mx-2 sb:h-7" }), /* @__PURE__ */ React25__namespace.createElement(ListTool, { editor }), /* @__PURE__ */ React25__namespace.createElement(Separator2, { orientation: "vertical", className: "sb:mx-2 sb:h-7" }), /* @__PURE__ */ React25__namespace.createElement(LinkTool, { editor }), /* @__PURE__ */ React25__namespace.createElement(InsertTool, { editor })));
1012
+ };
1013
+ var ToolbarSection = ({
1014
+ editor,
1015
+ actions: actions4,
1016
+ mainActionCount = 0
1017
+ }) => {
1018
+ const { mainActions, dropdownActions } = React25__namespace.useMemo(() => {
1019
+ return {
1020
+ mainActions: actions4.slice(0, mainActionCount),
1021
+ dropdownActions: actions4.slice(mainActionCount)
1022
+ };
1023
+ }, [actions4, mainActionCount]);
1024
+ const isDropdownActive = React25__namespace.useMemo(() => {
1025
+ return dropdownActions.some((action) => action.isActive(editor));
1026
+ }, [dropdownActions, editor]);
1027
+ return /* @__PURE__ */ React25__namespace.createElement(React25__namespace.Fragment, null, mainActions.map((action) => /* @__PURE__ */ React25__namespace.createElement(
1028
+ ToolbarButton,
1029
+ {
1030
+ key: action.label,
1031
+ onClick: () => action.action(editor),
1032
+ disabled: !action.canExecute(editor),
1033
+ pressed: action.isActive(editor)
1034
+ },
1035
+ /* @__PURE__ */ React25__namespace.createElement(action.icon, { className: "sb:size-5" })
1036
+ )), dropdownActions.length > 0 && /* @__PURE__ */ React25__namespace.createElement(DropdownMenu, null, /* @__PURE__ */ React25__namespace.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(ToolbarButton, { pressed: isDropdownActive }, /* @__PURE__ */ React25__namespace.createElement(lu.LuEllipsis, { className: "sb:size-5" }))), /* @__PURE__ */ React25__namespace.createElement(DropdownMenuContent, { align: "start" }, dropdownActions.map((action) => /* @__PURE__ */ React25__namespace.createElement(
1037
+ DropdownMenuItem,
1038
+ {
1039
+ key: action.label,
1040
+ className: chunkTMDKQB2L_js.cn("sb:flex sb:flex-row sb:items-center sb:gap-2", {
1041
+ "sb:bg-accent": action.isActive(editor)
1042
+ }),
1043
+ onClick: () => action.action(editor),
1044
+ disabled: !action.canExecute(editor)
1045
+ },
1046
+ /* @__PURE__ */ React25__namespace.createElement(action.icon, { className: "sb:size-4" }),
1047
+ /* @__PURE__ */ React25__namespace.createElement("span", null, action.label)
1048
+ )))));
1049
+ };
1050
+ var ToolbarButton = React25__namespace.forwardRef(({ className, ...props }, ref) => {
1051
+ return /* @__PURE__ */ React25__namespace.createElement(
1052
+ Toggle,
1053
+ {
1054
+ size: "sm",
1055
+ className: chunkTMDKQB2L_js.cn(
1056
+ "sb:size-8 sb:p-0 sb:data-[state=on]:bg-accent",
1057
+ { "sb:bg-accent": props.pressed },
1058
+ className
1059
+ ),
1060
+ ref,
1061
+ ...props
1062
+ }
1063
+ );
1064
+ });
1065
+ ToolbarButton.displayName = "ToolbarButton";
1066
+
1067
+ // src/features/rich-text-editor/components/rich-text-editor.tsx
1068
+ var RichTextEditor = ({
1069
+ value,
1070
+ onChange,
1071
+ className,
1072
+ editorClassName,
1073
+ editorContentClassName,
1074
+ ...props
1075
+ }) => {
1076
+ console.count("re-render RichTextEditor");
1077
+ const editor = useRichTextEditor({
1078
+ value,
1079
+ onUpdate: onChange,
1080
+ editorClassName: chunkTMDKQB2L_js.cn("sb:flex-1 sb:px-3 sb:py-1", editorClassName),
1081
+ ...props
1082
+ });
1083
+ if (!editor) {
1084
+ return null;
1085
+ }
1086
+ return /* @__PURE__ */ React25__namespace.createElement(
1087
+ "div",
1088
+ {
1089
+ className: chunkTMDKQB2L_js.cn(
1090
+ "sb:flex sb:h-auto sb:min-h-72 sb:w-full sb:flex-col sb:rounded-md sb:border sb:border-input sb:shadow-sm sb:focus-within:border-primary",
1091
+ className
1092
+ )
1093
+ },
1094
+ /* @__PURE__ */ React25__namespace.createElement(Toolbar, { editor }),
1095
+ /* @__PURE__ */ React25__namespace.createElement(
1096
+ react.EditorContent,
1097
+ {
1098
+ editor,
1099
+ className: chunkTMDKQB2L_js.cn(
1100
+ "sb-editflow prose sb:flex sb:flex-1",
1101
+ editorContentClassName
1102
+ )
1103
+ }
1104
+ )
1105
+ );
1106
+ };
1107
+ function Calendar({
1108
+ className,
1109
+ classNames,
1110
+ showOutsideDays = true,
1111
+ ...props
1112
+ }) {
1113
+ return /* @__PURE__ */ React25__namespace.createElement(
1114
+ reactDayPicker.DayPicker,
1115
+ {
1116
+ showOutsideDays,
1117
+ className: chunkTMDKQB2L_js.cn("sb:p-3 sb:font-roboto", className),
1118
+ classNames: {
1119
+ months: "sb:flex sb:flex-col sb:sm:flex-row sb:gap-y-4 sb:sm:gap-x-4 sb:sm:gap-y-0",
1120
+ month: "sb:gap-y-4",
1121
+ caption: "sb:flex sb:justify-center sb:pt-1 sb:relative sb:items-center",
1122
+ caption_label: "sb:text-sm sb:font-medium",
1123
+ nav: "sb:gap-x-1 sb:flex sb:items-center",
1124
+ nav_button: chunkTMDKQB2L_js.cn(
1125
+ chunk3QWMKMTN_js.buttonVariants({ variant: "outline" }),
1126
+ "sb:h-7 sb:w-7 sb:bg-transparent sb:p-0 sb:opacity-50 sb:hover:opacity-100"
1127
+ ),
1128
+ nav_button_previous: "sb:absolute sb:left-1",
1129
+ nav_button_next: "sb:absolute sb:right-1",
1130
+ table: "sb:w-full sb:border-collapse sb:flex sb:flex-col sb:gap-y-1",
1131
+ head_row: "sb:flex",
1132
+ head_cell: "sb:text-muted-foreground sb:rounded-md sb:w-8 sb:font-normal sb:text-[0.8rem]",
1133
+ row: "sb:flex sb:w-full sb:mt-2",
1134
+ cell: chunkTMDKQB2L_js.cn(
1135
+ "sb:relative sb:p-0 sb:text-center sb:text-sm sb:focus-within:relative sb:focus-within:z-20 sb:[&:has([aria-selected])]:bg-accent sb:[&:has([aria-selected].day-outside)]:bg-accent/50 sb:[&:has([aria-selected].day-range-end)]:rounded-r-md",
1136
+ props.mode === "range" ? "sb:[&:has(>.day-range-end)]:rounded-r-md sb:[&:has(>.day-range-start)]:rounded-l-md sb:first:[&:has([aria-selected])]:rounded-l-md sb:last:[&:has([aria-selected])]:rounded-r-md" : "sb:[&:has([aria-selected])]:rounded-md"
1137
+ ),
1138
+ day: chunkTMDKQB2L_js.cn(
1139
+ chunk3QWMKMTN_js.buttonVariants({ variant: "ghost" }),
1140
+ "sb:h-8 sb:w-8 sb:p-0 sb:font-normal sb:aria-selected:opacity-100"
1141
+ ),
1142
+ day_range_start: "day-range-start",
1143
+ day_range_end: "day-range-end",
1144
+ day_selected: "sb:bg-primary sb:text-primary-foreground sb:hover:bg-primary sb:hover:text-primary-foreground sb:focus:bg-primary sb:focus:text-primary-foreground",
1145
+ day_today: "sb:bg-accent sb:text-accent-foreground",
1146
+ day_outside: "day-outside sb:text-muted-foreground sb:opacity-50 sb:aria-selected:bg-accent/50 sb:aria-selected:text-muted-foreground sb:aria-selected:opacity-30",
1147
+ day_disabled: "sb:text-muted-foreground sb:opacity-50",
1148
+ day_range_middle: "sb:aria-selected:bg-accent sb:aria-selected:text-accent-foreground",
1149
+ day_hidden: "invisible",
1150
+ ...classNames
1151
+ },
1152
+ components: {
1153
+ IconLeft: () => /* @__PURE__ */ React25__namespace.createElement(lucideReact.ChevronLeftIcon, { className: "sb:h-4 sb:w-4" }),
1154
+ IconRight: () => /* @__PURE__ */ React25__namespace.createElement(lucideReact.ChevronRightIcon, { className: "sb:h-4 sb:w-4" })
1155
+ },
1156
+ ...props
1157
+ }
1158
+ );
1159
+ }
1160
+ Calendar.displayName = "Calendar";
1161
+ var ColorPicker = (props) => {
1162
+ const { color, onColorChange, className } = props;
1163
+ const colors = props.colors ?? [
1164
+ "#000000",
1165
+ "#ffffff",
1166
+ "#0f172a",
1167
+ "#F1F5F9",
1168
+ "#64748B",
1169
+ "#E6007E",
1170
+ "#F8FAFC",
1171
+ "#009DD1",
1172
+ "#FF0000"
1173
+ ];
1174
+ return /* @__PURE__ */ React25__namespace.createElement(Popover, null, /* @__PURE__ */ React25__namespace.createElement(PopoverTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(
1175
+ chunk3QWMKMTN_js.Button,
1176
+ {
1177
+ variant: "outline",
1178
+ size: "sm",
1179
+ className: chunkTMDKQB2L_js.cn(
1180
+ "sb:justify-start sb:text-left sb:font-normal sb:normal-case sb:w-full",
1181
+ !color && "sb:text-muted-foreground",
1182
+ className
1183
+ )
1184
+ },
1185
+ /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:w-full sb:flex sb:items-center sb:gap-2" }, color ? /* @__PURE__ */ React25__namespace.createElement(
1186
+ "div",
1187
+ {
1188
+ className: "sb:h-4 sb:w-4 sb:rounded sb:bg-center! sb:bg-cover! sb:transition-all sb:border",
1189
+ style: { background: color }
1190
+ }
1191
+ ) : /* @__PURE__ */ React25__namespace.createElement(lucideReact.PaintbrushIcon, { className: "sb:h-4 sb:w-4" }), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:truncate sb:flex-1" }, color ? color : "Kies een kleur"))
1192
+ )), /* @__PURE__ */ React25__namespace.createElement(PopoverContent, { className: "sb:w-64 sb:p-4 sb:flex sb:flex-wrap sb:gap-1" }, colors.map((s) => /* @__PURE__ */ React25__namespace.createElement(
1193
+ "div",
1194
+ {
1195
+ key: s,
1196
+ style: { background: s },
1197
+ className: "sb:rounded-md sb:h-6 sb:w-6 sb:cursor-pointer sb:active:scale-105 sb:border",
1198
+ onClick: () => onColorChange(s)
1199
+ }
1200
+ ))));
1201
+ };
1202
+ var MediaInput = (props) => {
1203
+ const { onFilesChange, limit = 32, multiple = false, onError } = props;
1204
+ const id = React25__namespace.useId();
1205
+ const [queue, setQueue] = React25__namespace.useState([]);
1206
+ const [sources, setSources] = React25__namespace.useState(props.files ?? []);
1207
+ const maxConcurrentUploads = 3;
1208
+ const uploadingCountRef = React25__namespace.useRef(0);
1209
+ const handleFilesAdd = async (e) => {
1210
+ const files = e.target.files;
1211
+ if (!files || files.length === 0) {
1212
+ return;
1213
+ }
1214
+ if (files.length + sources.length > (multiple ? limit : 1)) {
1215
+ onError?.(
1216
+ new MediaInputError(
1217
+ `Maximaal ${limit} bestanden.`,
1218
+ `Je probeerde nu ${files.length + sources.length} bestanden toe te voegen, maar je mag er maximaal ${limit} toevoegen.`
1219
+ )
1220
+ );
1221
+ return;
1222
+ }
1223
+ const queue2 = Array.from(files);
1224
+ setQueue(queue2);
1225
+ for (const file of queue2) {
1226
+ try {
1227
+ while (uploadingCountRef.current >= maxConcurrentUploads && uploadingCountRef.current > 0) {
1228
+ await new Promise((resolve) => setTimeout(resolve, 300));
1229
+ }
1230
+ uploadingCountRef.current++;
1231
+ const formData = new FormData();
1232
+ formData.append("file", file);
1233
+ const res = await fetch("/api/simple-builder/file/upload", {
1234
+ method: "POST",
1235
+ body: formData
1236
+ });
1237
+ if (res === void 0 || !res.ok) {
1238
+ onError?.(
1239
+ new MediaInputError(
1240
+ "Bestand uploaden misulukt",
1241
+ `Bestand ${file.name} kon niet worden ge\xFCpload.`
1242
+ )
1243
+ );
1244
+ continue;
1245
+ }
1246
+ const { data: url } = await res.json();
1247
+ if (!url) {
1248
+ onError?.(
1249
+ new MediaInputError(
1250
+ "Bestand uploaden misulukt",
1251
+ `De URL van bestand ${file.name} kon niet worden opgehaald.`
1252
+ )
1253
+ );
1254
+ continue;
1255
+ }
1256
+ setSources((prev) => [...prev, url]);
1257
+ onFilesChange?.([...sources, url]);
1258
+ } catch (e2) {
1259
+ onError?.(
1260
+ new MediaInputError(
1261
+ "Bestand uploaden misulukt",
1262
+ `Bestand ${file.name} kon niet worden ge\xFCpload.`
1263
+ )
1264
+ );
1265
+ } finally {
1266
+ setQueue((prev) => prev.filter((f) => f !== file));
1267
+ uploadingCountRef.current--;
1268
+ }
1269
+ }
1270
+ };
1271
+ const handleSourceDelete = async (src) => {
1272
+ setSources((prev) => prev.filter((s) => s !== src));
1273
+ onFilesChange?.(sources.filter((s) => s !== src));
1274
+ await fetch("/api/uploadthing/delete", {
1275
+ method: "POST",
1276
+ body: JSON.stringify({ src })
1277
+ });
1278
+ };
1279
+ return /* @__PURE__ */ React25__namespace.createElement("div", { className: chunkTMDKQB2L_js.cn("flex flex-wrap gap-4", props.className) }, sources.map((src) => /* @__PURE__ */ React25__namespace.createElement(MediaInputItem, { key: src, className: chunkTMDKQB2L_js.cn("group", props.itemClassName) }, /* @__PURE__ */ React25__namespace.createElement(
1280
+ chunkTMDKQB2L_js.Image,
1281
+ {
1282
+ src,
1283
+ alt: "",
1284
+ fill: true,
1285
+ className: "sb:absolute sb:inset-0 sb:object-cover sb:pointer-events-none"
1286
+ }
1287
+ ), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:absolute sb:right-1 sb:top-1 sb:z-30 sb:flex sb:items-center sb:justify-end sb:gap-3 sb:opacity-0 sb:transition-opacity sb:group-hover:opacity-100" }, /* @__PURE__ */ React25__namespace.createElement(
1288
+ "button",
1289
+ {
1290
+ className: "sb:flex sb:h-8 sb:w-8 sb:items-center sb:justify-center sb:rounded-full sb:border sb:bg-secondary sb:text-secondary-foreground sb:opacity-90 sb:shadow sb:transition-opacity sb:hover:opacity-100",
1291
+ onClick: () => handleSourceDelete(src)
1292
+ },
1293
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.Trash2Icon, { className: "sb:h-4 sb:w-4" })
1294
+ )))), queue.map((_, i) => /* @__PURE__ */ React25__namespace.createElement(
1295
+ MediaInputItem,
1296
+ {
1297
+ key: i,
1298
+ className: chunkTMDKQB2L_js.cn(
1299
+ "sb:flex sb:h-28 sb:w-28 sb:items-center sb:justify-center",
1300
+ props.itemClassName
1301
+ )
1302
+ },
1303
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.Loader2Icon, { className: "sb:h-6 sb:w-6 sb:animate-spin" })
1304
+ )), multiple || !multiple && !sources.length && !queue.length ? /* @__PURE__ */ React25__namespace.createElement(
1305
+ "label",
1306
+ {
1307
+ htmlFor: id,
1308
+ className: chunkTMDKQB2L_js.cn(
1309
+ "sb:flex sb:h-28 sb:w-28 sb:cursor-pointer sb:items-center sb:justify-center sb:rounded-lg sb:border",
1310
+ props.itemClassName
1311
+ )
1312
+ },
1313
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.PlusIcon, { className: "sb:h-6 sb:w-6" }),
1314
+ /* @__PURE__ */ React25__namespace.createElement(
1315
+ "input",
1316
+ {
1317
+ id,
1318
+ type: "file",
1319
+ onChange: handleFilesAdd,
1320
+ multiple,
1321
+ accept: ".png,.jpg,.jpeg,.webp,.gif,.svg",
1322
+ className: "sb:hidden"
1323
+ }
1324
+ )
1325
+ ) : null);
1326
+ };
1327
+ var MediaInputItem = (props) => {
1328
+ return /* @__PURE__ */ React25__namespace.createElement(
1329
+ "div",
1330
+ {
1331
+ className: chunkTMDKQB2L_js.cn(
1332
+ "sb:relative sb:h-28 sb:w-28 sb:overflow-hidden sb:rounded-lg sb:border",
1333
+ props.className
1334
+ )
1335
+ },
1336
+ props.children
1337
+ );
1338
+ };
1339
+ var MediaInputError = class extends Error {
1340
+ title;
1341
+ description;
1342
+ constructor(message, description) {
1343
+ super(message);
1344
+ this.title = message;
1345
+ this.description = description;
1346
+ }
1347
+ };
1348
+ var Select = SelectPrimitive__namespace.Root;
1349
+ var SelectValue = SelectPrimitive__namespace.Value;
1350
+ var SelectTrigger = React25__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1351
+ SelectPrimitive__namespace.Trigger,
1352
+ {
1353
+ ref,
1354
+ className: chunkTMDKQB2L_js.cn(
1355
+ "sb:flex sb:h-10 sb:w-full sb:items-center sb:justify-between sb:rounded-md sb:border sb:border-input sb:bg-background sb:px-3 sb:py-2 sb:text-sm sb:ring-offset-background sb:placeholder:text-muted-foreground sb:focus:outline-hidden sb:focus:ring-2 sb:focus:ring-ring sb:focus:ring-offset-2 sb:disabled:cursor-not-allowed sb:disabled:opacity-50 sb:[&>span]:line-clamp-1",
1356
+ className
1357
+ ),
1358
+ ...props
1359
+ },
1360
+ children,
1361
+ /* @__PURE__ */ React25__namespace.createElement(SelectPrimitive__namespace.Icon, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(lucideReact.ChevronDown, { className: "sb:h-4 sb:w-4 sb:opacity-50" }))
1362
+ ));
1363
+ SelectTrigger.displayName = SelectPrimitive__namespace.Trigger.displayName;
1364
+ var SelectScrollUpButton = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1365
+ SelectPrimitive__namespace.ScrollUpButton,
1366
+ {
1367
+ ref,
1368
+ className: chunkTMDKQB2L_js.cn(
1369
+ "sb:flex sb:cursor-default sb:items-center sb:justify-center sb:py-1",
1370
+ className
1371
+ ),
1372
+ ...props
1373
+ },
1374
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.ChevronUp, { className: "sb:h-4 sb:w-4" })
1375
+ ));
1376
+ SelectScrollUpButton.displayName = SelectPrimitive__namespace.ScrollUpButton.displayName;
1377
+ var SelectScrollDownButton = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1378
+ SelectPrimitive__namespace.ScrollDownButton,
1379
+ {
1380
+ ref,
1381
+ className: chunkTMDKQB2L_js.cn(
1382
+ "sb:flex sb:cursor-default sb:items-center sb:justify-center sb:py-1",
1383
+ className
1384
+ ),
1385
+ ...props
1386
+ },
1387
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.ChevronDown, { className: "sb:h-4 sb:w-4" })
1388
+ ));
1389
+ SelectScrollDownButton.displayName = SelectPrimitive__namespace.ScrollDownButton.displayName;
1390
+ var SelectContent = React25__namespace.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(SelectPrimitive__namespace.Portal, null, /* @__PURE__ */ React25__namespace.createElement(
1391
+ SelectPrimitive__namespace.Content,
1392
+ {
1393
+ ref,
1394
+ className: chunkTMDKQB2L_js.cn(
1395
+ "sb:relative sb:z-50 sb:max-h-96 sb:min-w-32 sb:overflow-hidden sb:rounded-md sb:border sb:bg-popover sb:text-popover-foreground sb:shadow-md data-[state=open]:sb-animate-in data-[state=closed]:sb-animate-out data-[state=closed]:sb-fade-out-0 data-[state=open]:sb-fade-in-0 data-[state=closed]:sb-zoom-out-95 data-[state=open]:sb-zoom-in-95 data-[side=bottom]:sb-slide-in-from-top-2 data-[side=left]:sb-slide-in-from-right-2 data-[side=right]:sb-slide-in-from-left-2 data-[side=top]:sb-slide-in-from-bottom-2",
1396
+ position === "popper" && "sb:data-[side=bottom]:translate-y-1 sb:data-[side=left]:-translate-x-1 sb:data-[side=right]:translate-x-1 sb:data-[side=top]:-translate-y-1",
1397
+ className
1398
+ ),
1399
+ position,
1400
+ ...props
1401
+ },
1402
+ /* @__PURE__ */ React25__namespace.createElement(SelectScrollUpButton, null),
1403
+ /* @__PURE__ */ React25__namespace.createElement(
1404
+ SelectPrimitive__namespace.Viewport,
1405
+ {
1406
+ className: chunkTMDKQB2L_js.cn(
1407
+ "sb:p-1",
1408
+ position === "popper" && "sb:h-(--radix-select-trigger-height) sb:w-full sb:min-w-(--radix-select-trigger-width)"
1409
+ )
1410
+ },
1411
+ children
1412
+ ),
1413
+ /* @__PURE__ */ React25__namespace.createElement(SelectScrollDownButton, null)
1414
+ )));
1415
+ SelectContent.displayName = SelectPrimitive__namespace.Content.displayName;
1416
+ var SelectLabel = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1417
+ SelectPrimitive__namespace.Label,
1418
+ {
1419
+ ref,
1420
+ className: chunkTMDKQB2L_js.cn(
1421
+ "sb:py-1.5 sb:pl-8 sb:pr-2 sb:text-sm sb:font-semibold",
1422
+ className
1423
+ ),
1424
+ ...props
1425
+ }
1426
+ ));
1427
+ SelectLabel.displayName = SelectPrimitive__namespace.Label.displayName;
1428
+ var SelectItem = React25__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1429
+ SelectPrimitive__namespace.Item,
1430
+ {
1431
+ ref,
1432
+ className: chunkTMDKQB2L_js.cn(
1433
+ "sb:relative sb:flex sb:w-full sb:cursor-default sb:select-none sb:items-center sb:rounded-sm sb:py-1.5 sb:pl-8 sb:pr-2 sb:text-sm sb:outline-hidden sb:focus:bg-accent sb:focus:text-accent-foreground sb:data-disabled:pointer-events-none sb:data-disabled:opacity-50",
1434
+ className
1435
+ ),
1436
+ ...props
1437
+ },
1438
+ /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:absolute sb:left-2 sb:flex sb:h-3.5 sb:w-3.5 sb:items-center sb:justify-center" }, /* @__PURE__ */ React25__namespace.createElement(SelectPrimitive__namespace.ItemIndicator, null, /* @__PURE__ */ React25__namespace.createElement(lucideReact.Check, { className: "sb:h-4 sb:w-4" }))),
1439
+ /* @__PURE__ */ React25__namespace.createElement(SelectPrimitive__namespace.ItemText, null, children)
1440
+ ));
1441
+ SelectItem.displayName = SelectPrimitive__namespace.Item.displayName;
1442
+ var SelectSeparator = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1443
+ SelectPrimitive__namespace.Separator,
1444
+ {
1445
+ ref,
1446
+ className: chunkTMDKQB2L_js.cn("sb:-mx-1 sb:my-1 sb:h-px sb:bg-muted", className),
1447
+ ...props
1448
+ }
1449
+ ));
1450
+ SelectSeparator.displayName = SelectPrimitive__namespace.Separator.displayName;
1451
+ var Textarea = React25__namespace.forwardRef(
1452
+ ({ className, ...props }, ref) => {
1453
+ return /* @__PURE__ */ React25__namespace.createElement(
1454
+ "textarea",
1455
+ {
1456
+ className: chunkTMDKQB2L_js.cn(
1457
+ "sb:flex sb:min-h-[60px] sb:font-roboto sb:w-full sb:rounded-md sb:border sb:border-input sb:bg-transparent sb:px-3 sb:py-2 sb:text-sm sb:shadow-sm sb:placeholder:text-muted-foreground sb:focus-visible:outline-hidden sb:focus-visible:ring-1 sb:focus-visible:ring-ring sb:disabled:cursor-not-allowed sb:disabled:opacity-50",
1458
+ className
1459
+ ),
1460
+ ref,
1461
+ ...props
1462
+ }
1463
+ );
1464
+ }
1465
+ );
1466
+ Textarea.displayName = "Textarea";
1467
+
1468
+ // src/components/container-item-form.tsx
1469
+ var ContainerItemForm = (props) => {
1470
+ const { item } = props;
1471
+ const { patchItem } = chunk3QWMKMTN_js.useBuilder();
1472
+ const component = chunkTMDKQB2L_js.builder.getComponent(item.component);
1473
+ if (!component) {
1474
+ throw new Error(
1475
+ `[simple-builder]: Component with id ${item.component} not found in container item form component`
1476
+ );
1477
+ }
1478
+ const form = reactHookForm.useForm({
1479
+ defaultValues: (component.inputs || []).reduce(
1480
+ (acc, input) => ({
1481
+ ...acc,
1482
+ [input.name]: item?.props?.[input.name] ?? input.defaultValue
1483
+ }),
1484
+ {}
1485
+ )
1486
+ });
1487
+ const onSubmit = React25__namespace.useCallback(
1488
+ (values) => {
1489
+ patchItem(item.id, {
1490
+ props: values
1491
+ });
1492
+ },
1493
+ [patchItem, item.id]
1494
+ );
1495
+ return /* @__PURE__ */ React25__namespace.createElement(Form, { ...form }, /* @__PURE__ */ React25__namespace.createElement("form", { onSubmit: form.handleSubmit(onSubmit) }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:flex-col sb:gap-4 sb:p-4" }, (component.inputs || []).map((input) => /* @__PURE__ */ React25__namespace.createElement(
1496
+ RenderFormField,
1497
+ {
1498
+ key: input.name,
1499
+ type: input.type,
1500
+ input,
1501
+ form
1502
+ }
1503
+ )), /* @__PURE__ */ React25__namespace.createElement(chunk3QWMKMTN_js.Button, { type: "submit", className: "w-full" }, "Opslaan"))));
1504
+ };
1505
+ var RenderFormField = (props) => {
1506
+ const { type, input, form } = props;
1507
+ const fieldArray = reactHookForm.useFieldArray({
1508
+ control: form.control,
1509
+ name: input.name
1510
+ });
1511
+ if (input.multiple) {
1512
+ return /* @__PURE__ */ React25__namespace.createElement("fieldset", { className: "sb:flex sb:flex-col sb:gap-2" }, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, input.friendlyName || input.name), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:flex-col sb:gap-4" }, fieldArray.fields.map(
1513
+ (field, i) => type !== "grouped" ? /* @__PURE__ */ React25__namespace.createElement(
1514
+ FormField,
1515
+ {
1516
+ key: field.id,
1517
+ control: form.control,
1518
+ name: `${input.name}.${i}`,
1519
+ render: ({ field: field2 }) => /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:items-center sb:gap-3" }, /* @__PURE__ */ React25__namespace.createElement(RenderInput, { field: field2, type: input.type }), /* @__PURE__ */ React25__namespace.createElement("button", { type: "button", onClick: () => fieldArray.remove(i) }, /* @__PURE__ */ React25__namespace.createElement(lucideReact.XIcon, { className: "sb:h-4 sb:w-4" })))
1520
+ }
1521
+ ) : /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:items-center sb:relative" }, /* @__PURE__ */ React25__namespace.createElement(
1522
+ RenderFormField,
1523
+ {
1524
+ key: field.id,
1525
+ form,
1526
+ type,
1527
+ input: {
1528
+ ...input,
1529
+ name: `${input.name}.${i}`,
1530
+ multiple: false,
1531
+ friendlyName: ""
1532
+ }
1533
+ }
1534
+ ), /* @__PURE__ */ React25__namespace.createElement(
1535
+ "button",
1536
+ {
1537
+ type: "button",
1538
+ onClick: () => fieldArray.remove(i),
1539
+ className: "sb:absolute sb:top-2 sb:right-2 sb:text-foreground/70 sb:hover:text-foreground"
1540
+ },
1541
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.XIcon, { className: "sb:h-4 sb:w-4" })
1542
+ ))
1543
+ ), /* @__PURE__ */ React25__namespace.createElement(
1544
+ chunk3QWMKMTN_js.Button,
1545
+ {
1546
+ type: "button",
1547
+ variant: "outline",
1548
+ size: "sm",
1549
+ className: chunkTMDKQB2L_js.cn(
1550
+ "sb:w-[89%] sb:border-2 sb:border-dashed sb:text-muted-foreground",
1551
+ type === "grouped" && "sb:w-full"
1552
+ ),
1553
+ onClick: () => fieldArray.append(void 0)
1554
+ },
1555
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.PlusCircleIcon, { className: "sb:h-4 sb:w-4" })
1556
+ )));
1557
+ }
1558
+ switch (type) {
1559
+ case "string":
1560
+ case "number":
1561
+ case "longText":
1562
+ case "color":
1563
+ case "date":
1564
+ case "file":
1565
+ return /* @__PURE__ */ React25__namespace.createElement(
1566
+ FormField,
1567
+ {
1568
+ key: input.name,
1569
+ control: form.control,
1570
+ name: input.name,
1571
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, input.friendlyName || input.name), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(RenderInput, { type, field, options: input?.enum })), input.helperText && /* @__PURE__ */ React25__namespace.createElement(FormDescription, null, input.helperText), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
1572
+ }
1573
+ );
1574
+ case "richText":
1575
+ return /* @__PURE__ */ React25__namespace.createElement(Dialog, null, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:flex-col sb:gap-2" }, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, input.friendlyName || input.name), /* @__PURE__ */ React25__namespace.createElement(DialogTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(chunk3QWMKMTN_js.Button, { variant: "outline", className: "sb:w-full", type: "button" }, input.friendlyName || input.name, " bewerken"))), /* @__PURE__ */ React25__namespace.createElement(DialogContent, { className: "sb:max-w-3xl sb:p-0" }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:h-full sb:max-h-svh sb:w-full sb:flex-col sb:sm:max-h-[90svh]" }, /* @__PURE__ */ React25__namespace.createElement(DialogHeader, { className: "sb:flex-none sb:border-b sb:p-6" }, /* @__PURE__ */ React25__namespace.createElement(DialogTitle, null, input.friendlyName || input.name, " editor")), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex-1 sb:overflow-y-auto" }, /* @__PURE__ */ React25__namespace.createElement(
1576
+ FormField,
1577
+ {
1578
+ key: input.name,
1579
+ control: form.control,
1580
+ name: input.name,
1581
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(RenderInput, { type, field })), input.helperText && /* @__PURE__ */ React25__namespace.createElement(FormDescription, null, input.helperText), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
1582
+ }
1583
+ )))));
1584
+ case "boolean":
1585
+ return /* @__PURE__ */ React25__namespace.createElement(
1586
+ FormField,
1587
+ {
1588
+ key: input.name,
1589
+ control: form.control,
1590
+ name: input.name,
1591
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, { className: "sb:flex sb:flex-row sb:items-center sb:justify-between sb:space-y-0" }, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, input.friendlyName || input.name), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(RenderInput, { type, field })), input.helperText && /* @__PURE__ */ React25__namespace.createElement(FormDescription, null, input.helperText), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
1592
+ }
1593
+ );
1594
+ case "grouped":
1595
+ return /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:flex-col sb:gap-2 sb:w-full" }, input.friendlyName !== "" && /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, input.friendlyName || input.name), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:flex-col sb:gap-2 sb:p-3 sb:w-full sb:border sb:rounded-lg" }, input.inputs.map((sub) => /* @__PURE__ */ React25__namespace.createElement(
1596
+ RenderFormField,
1597
+ {
1598
+ key: `${input.name}.${sub.name}`,
1599
+ type: sub.type,
1600
+ input: {
1601
+ ...sub,
1602
+ name: `${input.name}.${sub.name}`
1603
+ },
1604
+ form
1605
+ }
1606
+ ))));
1607
+ default:
1608
+ throw new Error(
1609
+ `[simple-builder]: Input type "${props.type}" not supported in render form field.`
1610
+ );
1611
+ }
1612
+ };
1613
+ var RenderInput = (props) => {
1614
+ const { type, options, field } = props;
1615
+ switch (type) {
1616
+ case "string":
1617
+ if (!options)
1618
+ return /* @__PURE__ */ React25__namespace.createElement(Input, { ...field });
1619
+ return /* @__PURE__ */ React25__namespace.createElement(Select, { onValueChange: field.onChange, defaultValue: field.value }, /* @__PURE__ */ React25__namespace.createElement(SelectTrigger, null, /* @__PURE__ */ React25__namespace.createElement(SelectValue, null)), /* @__PURE__ */ React25__namespace.createElement(SelectContent, null, options.map((option) => /* @__PURE__ */ React25__namespace.createElement(SelectItem, { key: option, value: option }, option))));
1620
+ case "longText":
1621
+ return /* @__PURE__ */ React25__namespace.createElement(Textarea, { ...field });
1622
+ case "richText":
1623
+ return /* @__PURE__ */ React25__namespace.createElement(RichTextEditor, { ...field });
1624
+ case "number":
1625
+ return /* @__PURE__ */ React25__namespace.createElement(Input, { type: "number", ...field });
1626
+ case "color":
1627
+ return /* @__PURE__ */ React25__namespace.createElement(ColorPicker, { color: field.value, onColorChange: field.onChange });
1628
+ case "date":
1629
+ return /* @__PURE__ */ React25__namespace.createElement(Popover, null, /* @__PURE__ */ React25__namespace.createElement(PopoverTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(
1630
+ chunk3QWMKMTN_js.Button,
1631
+ {
1632
+ variant: "outline",
1633
+ size: "sm",
1634
+ className: chunkTMDKQB2L_js.cn(
1635
+ "sb:w-full sb:flex sb:justify-start sb:text-left sb:font-normal",
1636
+ !field.value && "sb:text-muted-foreground"
1637
+ )
1638
+ },
1639
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.CalendarIcon, { className: "sb:mr-2 sb:h-4 sb:w-4" }),
1640
+ field.value && !Array.isArray(field.value) ? dateFns.format(field.value, "PPP") : /* @__PURE__ */ React25__namespace.createElement("span", null, "Pick a date")
1641
+ )), /* @__PURE__ */ React25__namespace.createElement(PopoverContent, { className: "sb:w-auto sb:p-0", align: "start" }, /* @__PURE__ */ React25__namespace.createElement(
1642
+ Calendar,
1643
+ {
1644
+ mode: "single",
1645
+ selected: field.value,
1646
+ onSelect: field.onChange,
1647
+ initialFocus: true
1648
+ }
1649
+ )));
1650
+ case "boolean":
1651
+ return /* @__PURE__ */ React25__namespace.createElement(Switch, { checked: field.value, onCheckedChange: field.onChange });
1652
+ case "file":
1653
+ return /* @__PURE__ */ React25__namespace.createElement(
1654
+ MediaInput,
1655
+ {
1656
+ className: "sb:grid sb:grid-cols-2 sb:gap-1",
1657
+ itemClassName: "sb:aspect-video sb:h-auto sb:w-full",
1658
+ multiple: false,
1659
+ files: field.value ? [field.value] : [],
1660
+ onFilesChange: (files) => field.onChange(files[0]),
1661
+ onError: (e) => console.error(
1662
+ "[media-input]: Title: " + e?.title,
1663
+ "media-input: Error: " + e?.description
1664
+ )
1665
+ }
1666
+ );
1667
+ default:
1668
+ throw new Error(
1669
+ `[simple-builder]: Input type "${props.type}" not supported in render input.`
1670
+ );
1671
+ }
1672
+ };
1673
+ var Tabs = TabsPrimitive__namespace.Root;
1674
+ var tabsListVariants = chunkTMDKQB2L_js.tv({
1675
+ variants: {
1676
+ variant: {
1677
+ contained: "sb:inline-flex sb:h-10 sb:items-center sb:justify-center sb:rounded-md sb:bg-muted sb:p-1 sb:text-muted-foreground",
1678
+ text: "sb:flex sb:items-center sb:border-b sb:px-4 sb:gap-6"
1679
+ }
1680
+ },
1681
+ defaultVariants: {
1682
+ variant: "contained"
1683
+ }
1684
+ });
1685
+ var TabsList = React25__namespace.forwardRef(({ variant, className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1686
+ TabsPrimitive__namespace.List,
1687
+ {
1688
+ ref,
1689
+ className: tabsListVariants({ variant, className }),
1690
+ ...props
1691
+ }
1692
+ ));
1693
+ TabsList.displayName = TabsPrimitive__namespace.List.displayName;
1694
+ var tabsTriggerVariants = chunkTMDKQB2L_js.tv({
1695
+ variants: {
1696
+ variant: {
1697
+ contained: "sb:inline-flex sb:items-center sb:justify-center sb:whitespace-nowrap sb:rounded-sm sb:px-3 sb:py-1.5 sb:text-sm sb:font-medium sb:ring-offset-background sb:transition-all sb:focus-visible:outline-hidden sb:focus-visible:ring-2 sb:focus-visible:ring-ring sb:focus-visible:ring-offset-2 sb:disabled:pointer-events-none sb:disabled:opacity-50 sb:data-[state=active]:bg-background sb:data-[state=active]:text-foreground sb:data-[state=active]:shadow-sm",
1698
+ text: "sb:inline-flex sb:font-roboto sb:items-center sb:justify-center sb:whitespace-nowrap sb:py-3 sb:text-sm sb:font-medium sb:transition-all sb:focus-visible:outline-hidden sb:disabled:pointer-events-none sb:disabled:opacity-50 sb:data-[state=active]:border-black sb:border-b-2 sb:border-transparent sb:data-[state=active]:text-foreground sb:text-muted-foreground"
1699
+ }
1700
+ },
1701
+ defaultVariants: {
1702
+ variant: "contained"
1703
+ }
1704
+ });
1705
+ var TabsTrigger = React25__namespace.forwardRef(({ variant, className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1706
+ TabsPrimitive__namespace.Trigger,
1707
+ {
1708
+ ref,
1709
+ className: tabsTriggerVariants({ variant, className }),
1710
+ ...props
1711
+ }
1712
+ ));
1713
+ TabsTrigger.displayName = TabsPrimitive__namespace.Trigger.displayName;
1714
+ var TabsContent = React25__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
1715
+ TabsPrimitive__namespace.Content,
1716
+ {
1717
+ ref,
1718
+ className: chunkTMDKQB2L_js.cn(
1719
+ "sb:ring-offset-background sb:font-roboto sb:focus-visible:outline-hidden sb:focus-visible:ring-2 sb:focus-visible:ring-ring sb:focus-visible:ring-offset-2",
1720
+ className
1721
+ ),
1722
+ ...props
1723
+ }
1724
+ ));
1725
+ TabsContent.displayName = TabsPrimitive__namespace.Content.displayName;
1726
+
1727
+ // src/components/ui/background-picker.tsx
1728
+ var BackgroundPicker = (props) => {
1729
+ const { background, onBackgroundChange, className } = props;
1730
+ const solids = props.solids ?? [
1731
+ "#000000",
1732
+ "#ffffff",
1733
+ "#0f172a",
1734
+ "#F1F5F9",
1735
+ "#64748B",
1736
+ "#E6007E",
1737
+ "#F8FAFC",
1738
+ "#009DD1",
1739
+ "#FF0000"
1740
+ ];
1741
+ const gradients = props.gradients ?? [
1742
+ "linear-gradient(to top left,#accbee,#e7f0fd)",
1743
+ "linear-gradient(to top left,#d5d4d0,#d5d4d0,#eeeeec)"
1744
+ ];
1745
+ const images = props.images ?? [
1746
+ "url(https://images.unsplash.com/photo-1688822863426-8c5f9b257090?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2532&q=90)",
1747
+ "url(https://images.unsplash.com/photo-1691225850735-6e4e51834cad?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2532&q=90)"
1748
+ ];
1749
+ const defaultTab = React25__namespace.useMemo(() => {
1750
+ if (background.includes("url"))
1751
+ return "image";
1752
+ if (background.includes("gradient"))
1753
+ return "gradient";
1754
+ return "solid";
1755
+ }, [background]);
1756
+ return /* @__PURE__ */ React25__namespace.createElement(Popover, null, /* @__PURE__ */ React25__namespace.createElement(PopoverTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(
1757
+ chunk3QWMKMTN_js.Button,
1758
+ {
1759
+ variant: "outline",
1760
+ size: "sm",
1761
+ className: chunkTMDKQB2L_js.cn(
1762
+ "sb:justify-start sb:text-left sb:font-normal sb:normal-case sb:w-full",
1763
+ !background && "sb:text-muted-foreground",
1764
+ className
1765
+ )
1766
+ },
1767
+ /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:w-full sb:flex sb:items-center sb:gap-2" }, background ? /* @__PURE__ */ React25__namespace.createElement(
1768
+ "div",
1769
+ {
1770
+ className: "sb:h-4 sb:w-4 sb:rounded sb:bg-center! sb:bg-cover! sb:transition-all sb:border",
1771
+ style: { background }
1772
+ }
1773
+ ) : /* @__PURE__ */ React25__namespace.createElement(lucideReact.PaintbrushIcon, { className: "sb:h-4 sb:w-4" }), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:truncate sb:flex-1" }, background ? background : "Kies een achtergrond"))
1774
+ )), /* @__PURE__ */ React25__namespace.createElement(PopoverContent, { className: "sb:w-64 sb:p-0" }, /* @__PURE__ */ React25__namespace.createElement(Tabs, { defaultValue: defaultTab }, /* @__PURE__ */ React25__namespace.createElement(TabsList, { className: "sb:w-full" }, /* @__PURE__ */ React25__namespace.createElement(TabsTrigger, { className: "sb:flex-1", value: "solid" }, "Solid"), /* @__PURE__ */ React25__namespace.createElement(TabsTrigger, { className: "sb:flex-1", value: "gradient" }, "Gradient"), /* @__PURE__ */ React25__namespace.createElement(TabsTrigger, { className: "sb:flex-1", value: "image" }, "Image")), /* @__PURE__ */ React25__namespace.createElement(
1775
+ TabsContent,
1776
+ {
1777
+ value: "solid",
1778
+ className: "sb:data-[state=active]:flex sb:flex-wrap sb:gap-1 sb:p-4"
1779
+ },
1780
+ solids.map((s) => /* @__PURE__ */ React25__namespace.createElement(
1781
+ "div",
1782
+ {
1783
+ key: s,
1784
+ style: { background: s },
1785
+ className: "sb:rounded-md sb:h-6 sb:w-6 sb:cursor-pointer sb:active:scale-105 sb:border",
1786
+ onClick: () => onBackgroundChange(s)
1787
+ }
1788
+ ))
1789
+ ), /* @__PURE__ */ React25__namespace.createElement(
1790
+ TabsContent,
1791
+ {
1792
+ value: "gradient",
1793
+ className: "sb:data-[state=active]:flex sb:flex-wrap sb:gap-1 sb:p-4"
1794
+ },
1795
+ gradients.map((s) => /* @__PURE__ */ React25__namespace.createElement(
1796
+ "div",
1797
+ {
1798
+ key: s,
1799
+ style: { background: s },
1800
+ className: "rounded-md h-6 w-6 cursor-pointer active:scale-105 border",
1801
+ onClick: () => onBackgroundChange(s)
1802
+ }
1803
+ ))
1804
+ ), /* @__PURE__ */ React25__namespace.createElement(TabsContent, { value: "image" }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:p-4 sb:border-b" }, /* @__PURE__ */ React25__namespace.createElement(
1805
+ MediaInput,
1806
+ {
1807
+ className: "sb:grid sb:grid-cols-2 sb:gap-1",
1808
+ itemClassName: "sb:aspect-video sb:h-auto sb:w-full",
1809
+ multiple: false,
1810
+ onFilesChange: (files) => {
1811
+ if (!files.length)
1812
+ return;
1813
+ onBackgroundChange(`url(${files[0]})`);
1814
+ },
1815
+ onError: (e) => console.error(
1816
+ "[media-input]: Title: " + e?.title,
1817
+ "media-input: Error: " + e?.description
1818
+ )
1819
+ }
1820
+ )), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:grid sb:grid-cols-2 sb:gap-1 sb:p-4" }, images.map((s) => /* @__PURE__ */ React25__namespace.createElement(
1821
+ "div",
1822
+ {
1823
+ key: s,
1824
+ style: { backgroundImage: s },
1825
+ className: "sb:rounded-md sb:bg-cover sb:bg-center sb:aspect-video sb:w-full sb:cursor-pointer sb:border sb:active:scale-105",
1826
+ onClick: () => onBackgroundChange(s)
1827
+ }
1828
+ )))))));
1829
+ };
1830
+ var SpacingInput = (props) => {
1831
+ const [value, setValue] = React25__namespace.useState(parse(props.value || "0px"));
1832
+ const [indipendent, setIndipendent] = React25__namespace.useState(
1833
+ isIndipendent(parse(props.value || "0px"))
1834
+ );
1835
+ React25__namespace.useEffect(() => {
1836
+ if (!props.onChange)
1837
+ return;
1838
+ props.onChange(stringify(value));
1839
+ }, [value, props.onChange]);
1840
+ return /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:grid sb:grid-cols-[1fr_auto] sb:gap-3" }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:grid sb:grid-cols-2 sb:items-center sb:gap-3" }, !indipendent ? /* @__PURE__ */ React25__namespace.createElement(React25__namespace.Fragment, null, /* @__PURE__ */ React25__namespace.createElement(
1841
+ AdvancedInput,
1842
+ {
1843
+ value: value.left,
1844
+ pattern: "\\d+",
1845
+ onChange: ({ target: { value: value2 } }) => setValue((prev) => ({ ...prev, left: +value2, right: +value2 })),
1846
+ prepend: /* @__PURE__ */ React25__namespace.createElement(lucideReact.AlignHorizontalSpaceAroundIcon, { className: "sb:h-4 sb:w-4" }),
1847
+ append: /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:text-muted-foreground" }, "px")
1848
+ }
1849
+ ), /* @__PURE__ */ React25__namespace.createElement(
1850
+ AdvancedInput,
1851
+ {
1852
+ value: value.top,
1853
+ pattern: "\\d+",
1854
+ onChange: ({ target: { value: value2 } }) => setValue((prev) => ({ ...prev, top: +value2, bottom: +value2 })),
1855
+ prepend: /* @__PURE__ */ React25__namespace.createElement(lucideReact.AlignHorizontalSpaceAroundIcon, { className: "sb:h-4 sb:w-4 sb:rotate-90" }),
1856
+ append: /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:text-muted-foreground" }, "px")
1857
+ }
1858
+ )) : /* @__PURE__ */ React25__namespace.createElement(React25__namespace.Fragment, null, /* @__PURE__ */ React25__namespace.createElement(
1859
+ AdvancedInput,
1860
+ {
1861
+ value: value.left,
1862
+ pattern: "\\d+",
1863
+ onChange: ({ target: { value: value2 } }) => setValue((prev) => ({ ...prev, left: +value2 })),
1864
+ prepend: /* @__PURE__ */ React25__namespace.createElement(lucideReact.AlignHorizontalJustifyStartIcon, { className: "sb:h-4 sb:w-4" }),
1865
+ append: /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:text-muted-foreground" }, "px")
1866
+ }
1867
+ ), /* @__PURE__ */ React25__namespace.createElement(
1868
+ AdvancedInput,
1869
+ {
1870
+ value: value.top,
1871
+ pattern: "\\d+",
1872
+ onChange: ({ target: { value: value2 } }) => setValue((prev) => ({ ...prev, top: +value2 })),
1873
+ prepend: /* @__PURE__ */ React25__namespace.createElement(lucideReact.AlignHorizontalJustifyStartIcon, { className: "sb:h-4 sb:w-4 sb:rotate-90" }),
1874
+ append: /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:text-muted-foreground" }, "px")
1875
+ }
1876
+ ), /* @__PURE__ */ React25__namespace.createElement(
1877
+ AdvancedInput,
1878
+ {
1879
+ value: value.right,
1880
+ pattern: "\\d+",
1881
+ onChange: ({ target: { value: value2 } }) => setValue((prev) => ({ ...prev, right: +value2 })),
1882
+ prepend: /* @__PURE__ */ React25__namespace.createElement(lucideReact.AlignHorizontalJustifyStartIcon, { className: "sb:h-4 sb:w-4 sb:rotate-180" }),
1883
+ append: /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:text-muted-foreground" }, "px")
1884
+ }
1885
+ ), /* @__PURE__ */ React25__namespace.createElement(
1886
+ AdvancedInput,
1887
+ {
1888
+ value: value.bottom,
1889
+ pattern: "\\d+",
1890
+ onChange: ({ target: { value: value2 } }) => setValue((prev) => ({ ...prev, bottom: +value2 })),
1891
+ prepend: /* @__PURE__ */ React25__namespace.createElement(lucideReact.AlignHorizontalJustifyStartIcon, { className: "sb:h-4 sb:w-4 sb:-rotate-90" }),
1892
+ append: /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:text-muted-foreground" }, "px")
1893
+ }
1894
+ ))), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:shrink-0" }, /* @__PURE__ */ React25__namespace.createElement(
1895
+ Toggle,
1896
+ {
1897
+ className: "sb:shrink-0 sb:flex sb:w-8 sb:h-8 sb:p-0",
1898
+ variant: "outline",
1899
+ size: "sm",
1900
+ pressed: indipendent,
1901
+ onPressedChange: setIndipendent
1902
+ },
1903
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.ScanIcon, { className: "sb:h-4 sb:w-4" })
1904
+ )));
1905
+ };
1906
+ var isIndipendent = (value) => {
1907
+ const { top, right, bottom, left } = value;
1908
+ return top !== bottom || right !== left;
1909
+ };
1910
+ var parse = (value) => {
1911
+ const matches = value.match(/(\d+)/gm);
1912
+ const [top = 0, right = 0, bottom = 0, left = 0] = matches?.map((match) => +match) || [];
1913
+ switch (matches?.length) {
1914
+ case 1:
1915
+ return { top, right: top, bottom: top, left: top };
1916
+ case 2:
1917
+ return { top, bottom: top, left: right, right };
1918
+ case 3:
1919
+ return { top, right, left: right, bottom };
1920
+ default:
1921
+ return { top, right, bottom, left };
1922
+ }
1923
+ };
1924
+ var stringify = (value) => {
1925
+ const { top, right, bottom, left } = value;
1926
+ if (top === right && top === bottom && top === left) {
1927
+ return `${top}px`;
1928
+ }
1929
+ if (top === bottom && right === left) {
1930
+ return `${top}px ${right}px`;
1931
+ }
1932
+ if (right === left) {
1933
+ return `${top}px ${right}px ${bottom}px`;
1934
+ }
1935
+ return `${top}px ${right}px ${bottom}px ${left}px`;
1936
+ };
1937
+
1938
+ // src/components/item-design-form.tsx
1939
+ var designSchema = zod.z.object({
1940
+ container: zod.z.coerce.boolean(),
1941
+ hidden: zod.z.enum(["always", "mobile", "desktop", "never"]),
1942
+ desktop: zod.z.object({
1943
+ background: zod.z.string(),
1944
+ color: zod.z.string(),
1945
+ padding: zod.z.string(),
1946
+ margin: zod.z.string()
1947
+ }),
1948
+ mobile: zod.z.object({
1949
+ background: zod.z.string(),
1950
+ color: zod.z.string(),
1951
+ padding: zod.z.string(),
1952
+ margin: zod.z.string()
1953
+ })
1954
+ });
1955
+ var ItemDesignForm = (props) => {
1956
+ const { item } = props;
1957
+ const component = chunkTMDKQB2L_js.builder.getComponent(item.component);
1958
+ if (!component) {
1959
+ throw new Error(
1960
+ `[simple-builder]: Component "${item.component}" not found`
1961
+ );
1962
+ }
1963
+ const getDefaultDeviceValue = (params) => {
1964
+ const { device: device2 = "desktop", key, fallback = "" } = params;
1965
+ if (item.styles?.[device2]?.[key] !== void 0) {
1966
+ return item.styles[device2][key];
1967
+ }
1968
+ if (component.defaultStyles?.[device2]?.[key] !== void 0) {
1969
+ return component.defaultStyles[device2][key];
1970
+ }
1971
+ if (device2 === "mobile") {
1972
+ const desktopValue = getDefaultDeviceValue({
1973
+ ...params,
1974
+ device: "desktop"
1975
+ });
1976
+ if (desktopValue !== void 0) {
1977
+ return desktopValue;
1978
+ }
1979
+ }
1980
+ return fallback;
1981
+ };
1982
+ const getDefaultDeviceValues = (device2) => {
1983
+ return {
1984
+ background: getDefaultDeviceValue({ device: device2, key: "background" }),
1985
+ color: getDefaultDeviceValue({ device: device2, key: "color" }),
1986
+ padding: getDefaultDeviceValue({ device: device2, key: "padding" }),
1987
+ margin: getDefaultDeviceValue({ device: device2, key: "margin" })
1988
+ };
1989
+ };
1990
+ const form = reactHookForm.useForm({
1991
+ resolver: zod$1.zodResolver(designSchema),
1992
+ values: {
1993
+ container: item.styles?.container ?? true,
1994
+ hidden: item.styles?.hidden ?? "never",
1995
+ desktop: getDefaultDeviceValues("desktop"),
1996
+ mobile: getDefaultDeviceValues("mobile")
1997
+ }
1998
+ });
1999
+ const { patchItem } = chunk3QWMKMTN_js.useBuilder();
2000
+ const onSubmit = React25__namespace.useCallback(
2001
+ (values) => {
2002
+ const { container, hidden, desktop, mobile } = values;
2003
+ const dirtyFields = form.formState.dirtyFields;
2004
+ const desktopPatch = Object.entries(desktop).reduce(
2005
+ (acc, [key, value]) => ({
2006
+ ...acc,
2007
+ ...value && { [key]: value }
2008
+ }),
2009
+ { ...item.styles?.desktop }
2010
+ );
2011
+ const mobilePatch = Object.entries(mobile).reduce(
2012
+ (acc, [key, value]) => {
2013
+ const desktopValue = desktop[key];
2014
+ const isDirty = dirtyFields.desktop?.[key];
2015
+ if (value === desktopValue || isDirty) {
2016
+ return acc;
2017
+ }
2018
+ if (["padding", "margin"].includes(key)) {
2019
+ if (value === "0px" && desktopValue === "0px") {
2020
+ return acc;
2021
+ }
2022
+ }
2023
+ return {
2024
+ ...acc,
2025
+ ...value && { [key]: value }
2026
+ };
2027
+ },
2028
+ { ...item.styles?.mobile }
2029
+ );
2030
+ patchItem(item.id, {
2031
+ styles: {
2032
+ ...container === false && { container },
2033
+ ...hidden !== "never" && { hidden },
2034
+ ...Object.keys(desktopPatch).length && { desktop: desktopPatch },
2035
+ ...Object.keys(mobilePatch).length && { mobile: mobilePatch }
2036
+ }
2037
+ });
2038
+ },
2039
+ [patchItem, item.id, form.formState.dirtyFields]
2040
+ );
2041
+ const [device, setDevice] = React25__namespace.useState("desktop");
2042
+ return /* @__PURE__ */ React25__namespace.createElement(Form, { ...form }, /* @__PURE__ */ React25__namespace.createElement("form", { onSubmit: form.handleSubmit(onSubmit) }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:flex-col sb:gap-4 sb:p-4" }, /* @__PURE__ */ React25__namespace.createElement(
2043
+ Tabs,
2044
+ {
2045
+ defaultValue: device,
2046
+ onValueChange: (device2) => setDevice(device2)
2047
+ },
2048
+ /* @__PURE__ */ React25__namespace.createElement(TabsList, { className: "sb:h-9 sb:grid sb:w-full sb:grid-cols-2" }, /* @__PURE__ */ React25__namespace.createElement(TabsTrigger, { value: "desktop", className: "sb:text-xs" }, /* @__PURE__ */ React25__namespace.createElement(lucideReact.MonitorIcon, { className: "sb:h-4 sb:w-4 sb:mr-2" }), /* @__PURE__ */ React25__namespace.createElement("span", null, "Desktop")), /* @__PURE__ */ React25__namespace.createElement(TabsTrigger, { value: "mobile", className: "sb:text-xs" }, /* @__PURE__ */ React25__namespace.createElement(lucideReact.SmartphoneIcon, { className: "sb:h-4 sb:w-4 sb:mr-2" }), /* @__PURE__ */ React25__namespace.createElement("span", null, "Mobiel")))
2049
+ ), /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:flex-col sb:gap-4" }, /* @__PURE__ */ React25__namespace.createElement(
2050
+ FormField,
2051
+ {
2052
+ control: form.control,
2053
+ key: `${device}.background`,
2054
+ name: `${device}.background`,
2055
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "Achtergrond"), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(
2056
+ BackgroundPicker,
2057
+ {
2058
+ background: field.value,
2059
+ onBackgroundChange: field.onChange
2060
+ }
2061
+ )), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
2062
+ }
2063
+ ), /* @__PURE__ */ React25__namespace.createElement(
2064
+ FormField,
2065
+ {
2066
+ control: form.control,
2067
+ key: `${device}.color`,
2068
+ name: `${device}.color`,
2069
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "Inhoud kleur"), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(
2070
+ ColorPicker,
2071
+ {
2072
+ color: field.value,
2073
+ onColorChange: field.onChange
2074
+ }
2075
+ )), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
2076
+ }
2077
+ ), /* @__PURE__ */ React25__namespace.createElement("hr", null), /* @__PURE__ */ React25__namespace.createElement(
2078
+ FormField,
2079
+ {
2080
+ control: form.control,
2081
+ name: "hidden",
2082
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "Verbergen"), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(Select, { value: field.value, onValueChange: field.onChange }, /* @__PURE__ */ React25__namespace.createElement(SelectTrigger, null, /* @__PURE__ */ React25__namespace.createElement(SelectValue, null)), /* @__PURE__ */ React25__namespace.createElement(SelectContent, null, /* @__PURE__ */ React25__namespace.createElement(SelectItem, { value: "never" }, "Nooit"), /* @__PURE__ */ React25__namespace.createElement(SelectItem, { value: "desktop" }, "Op desktop"), /* @__PURE__ */ React25__namespace.createElement(SelectItem, { value: "mobile" }, "Op mobiel"), /* @__PURE__ */ React25__namespace.createElement(SelectItem, { value: "always" }, "Altijd")))), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
2083
+ }
2084
+ ), /* @__PURE__ */ React25__namespace.createElement("hr", null), /* @__PURE__ */ React25__namespace.createElement(
2085
+ FormField,
2086
+ {
2087
+ control: form.control,
2088
+ name: "container",
2089
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, { className: "sb:flex sb:flex-row sb:items-center sb:justify-between sb:space-y-0" }, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "Volledige breedte"), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(
2090
+ Switch,
2091
+ {
2092
+ checked: !field.value,
2093
+ onCheckedChange: (v) => field.onChange(!v)
2094
+ }
2095
+ )), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
2096
+ }
2097
+ ), /* @__PURE__ */ React25__namespace.createElement("hr", null), /* @__PURE__ */ React25__namespace.createElement(
2098
+ FormField,
2099
+ {
2100
+ control: form.control,
2101
+ key: `${device}.padding`,
2102
+ name: `${device}.padding`,
2103
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "Padding"), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(
2104
+ SpacingInput,
2105
+ {
2106
+ value: field.value,
2107
+ onChange: field.onChange
2108
+ }
2109
+ )), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
2110
+ }
2111
+ ), /* @__PURE__ */ React25__namespace.createElement(
2112
+ FormField,
2113
+ {
2114
+ control: form.control,
2115
+ key: `${device}.margin`,
2116
+ name: `${device}.margin`,
2117
+ render: ({ field }) => /* @__PURE__ */ React25__namespace.createElement(FormItem, null, /* @__PURE__ */ React25__namespace.createElement(FormLabel, null, "Margin"), /* @__PURE__ */ React25__namespace.createElement(FormControl, null, /* @__PURE__ */ React25__namespace.createElement(
2118
+ SpacingInput,
2119
+ {
2120
+ value: field.value,
2121
+ onChange: field.onChange
2122
+ }
2123
+ )), /* @__PURE__ */ React25__namespace.createElement(FormMessage, null))
2124
+ }
2125
+ )), /* @__PURE__ */ React25__namespace.createElement(chunk3QWMKMTN_js.Button, { type: "submit", className: "w-full" }, "Opslaan"))));
2126
+ };
2127
+ var ScrollArea = React25__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
2128
+ ScrollAreaPrimitive__namespace.Root,
2129
+ {
2130
+ ref,
2131
+ className: chunkTMDKQB2L_js.cn("sb:relative sb:overflow-hidden", className),
2132
+ ...props
2133
+ },
2134
+ /* @__PURE__ */ React25__namespace.createElement(ScrollAreaPrimitive__namespace.Viewport, { className: "sb:h-full sb:max-h-[80vh] sb:w-full sb:rounded-[inherit]" }, children),
2135
+ /* @__PURE__ */ React25__namespace.createElement(ScrollBar, null),
2136
+ /* @__PURE__ */ React25__namespace.createElement(ScrollAreaPrimitive__namespace.Corner, null)
2137
+ ));
2138
+ ScrollArea.displayName = ScrollAreaPrimitive__namespace.Root.displayName;
2139
+ var ScrollBar = React25__namespace.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ React25__namespace.createElement(
2140
+ ScrollAreaPrimitive__namespace.ScrollAreaScrollbar,
2141
+ {
2142
+ ref,
2143
+ orientation,
2144
+ className: chunkTMDKQB2L_js.cn(
2145
+ "sb:flex sb:touch-none sb:select-none sb:transition-colors",
2146
+ orientation === "vertical" && "sb:h-full sb:w-2.5 sb:border-l sb:border-l-transparent sb:p-px",
2147
+ orientation === "horizontal" && "sb:h-2.5 sb:flex-col sb:border-t sb:border-t-transparent sb:p-px",
2148
+ className
2149
+ ),
2150
+ ...props
2151
+ },
2152
+ /* @__PURE__ */ React25__namespace.createElement(ScrollAreaPrimitive__namespace.ScrollAreaThumb, { className: "sb:relative sb:flex-1 sb:rounded-full sb:bg-border" })
2153
+ ));
2154
+ ScrollBar.displayName = ScrollAreaPrimitive__namespace.ScrollAreaScrollbar.displayName;
2155
+
2156
+ // src/components/container-item-toolbar.tsx
2157
+ var ContainerItemToolbar = (props) => {
2158
+ const { contentId, canBringUp = false, canBringDown = false } = props;
2159
+ const { bringUp, bringDown } = chunk3QWMKMTN_js.useBuilder();
2160
+ return /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:absolute sb:z-20 sb:top-1 sb:right-1 sb:rounded-md sb:shadow sb:flex sb:flex-col sb:gap-1 sb:p-1 sb:bg-card sb:text-card-foreground sb-item-toolbar sb:opacity-0 sb:transition-opacity" }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:h-10 sb:p-1 sb:border sb:border-input sb:bg-background sb:rounded-md sb:text-sm sb:font-medium sb:flex sb:gap-1 sb:items-center sb:justify-start" }, /* @__PURE__ */ React25__namespace.createElement(EditButton, { id: contentId }), /* @__PURE__ */ React25__namespace.createElement(
2161
+ chunk3QWMKMTN_js.Button,
2162
+ {
2163
+ variant: "ghost",
2164
+ className: "sb:w-8 sb:h-8 sb:p-0",
2165
+ onClick: () => bringUp(contentId),
2166
+ disabled: !canBringUp
2167
+ },
2168
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.ArrowUp, { className: "sb:h-5 sb:w-5" })
2169
+ ), /* @__PURE__ */ React25__namespace.createElement(
2170
+ chunk3QWMKMTN_js.Button,
2171
+ {
2172
+ variant: "ghost",
2173
+ className: "sb:w-8 sb:h-8 sb:p-0",
2174
+ onClick: () => bringDown(contentId),
2175
+ disabled: !canBringDown
2176
+ },
2177
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.ArrowDown, { className: "sb:h-5 sb:w-5" })
2178
+ ), /* @__PURE__ */ React25__namespace.createElement(DeleteButton, { contentId })));
2179
+ };
2180
+ var EditButton = ({ id }) => {
2181
+ return /* @__PURE__ */ React25__namespace.createElement(Popover, { modal: true }, /* @__PURE__ */ React25__namespace.createElement(PopoverTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(chunk3QWMKMTN_js.Button, { variant: "ghost", className: "sb:w-8 sb:h-8 sb:p-0" }, /* @__PURE__ */ React25__namespace.createElement(lucideReact.Edit2Icon, { className: "sb:h-5 sb:w-5" }))), /* @__PURE__ */ React25__namespace.createElement(
2182
+ PopoverContent,
2183
+ {
2184
+ side: "left",
2185
+ align: "start",
2186
+ sideOffset: 16,
2187
+ alignOffset: -8,
2188
+ className: "sb:p-0 sb:relative",
2189
+ collisionPadding: 16
2190
+ },
2191
+ /* @__PURE__ */ React25__namespace.createElement(EditPopoverInner, { id })
2192
+ ));
2193
+ };
2194
+ var EditPopoverInner = (props) => {
2195
+ const { id } = props;
2196
+ const { getItem } = chunk3QWMKMTN_js.useBuilder();
2197
+ const item = getItem(id);
2198
+ if (!item) {
2199
+ throw new Error(
2200
+ `[simple-builder]: Item with id ${id} not found in container item form component`
2201
+ );
2202
+ }
2203
+ return /* @__PURE__ */ React25__namespace.createElement(Tabs, null, /* @__PURE__ */ React25__namespace.createElement(TabsList, { variant: "text", defaultValue: "content" }, /* @__PURE__ */ React25__namespace.createElement(TabsTrigger, { variant: "text", value: "content" }, "Inhoud"), /* @__PURE__ */ React25__namespace.createElement(TabsTrigger, { variant: "text", value: "design" }, "Design")), /* @__PURE__ */ React25__namespace.createElement(TabsContent, { value: "content" }, /* @__PURE__ */ React25__namespace.createElement(ScrollArea, null, /* @__PURE__ */ React25__namespace.createElement(ContainerItemForm, { item }))), /* @__PURE__ */ React25__namespace.createElement(TabsContent, { value: "design" }, /* @__PURE__ */ React25__namespace.createElement(ItemDesignForm, { item })));
2204
+ };
2205
+ var DeleteButton = ({ contentId }) => {
2206
+ const { deleteContent } = chunk3QWMKMTN_js.useBuilder();
2207
+ return /* @__PURE__ */ React25__namespace.createElement(AlertDialog, null, /* @__PURE__ */ React25__namespace.createElement(AlertDialogTrigger, { asChild: true }, /* @__PURE__ */ React25__namespace.createElement(
2208
+ chunk3QWMKMTN_js.Button,
2209
+ {
2210
+ variant: "ghost",
2211
+ className: "sb:w-8 sb:h-8 sb:p-0 sb:text-destructive"
2212
+ },
2213
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.Trash2Icon, { className: "sb:h-5 sb:w-5" })
2214
+ )), /* @__PURE__ */ React25__namespace.createElement(AlertDialogContent, null, /* @__PURE__ */ React25__namespace.createElement(AlertDialogDescription, null, "Weet je zeker dat je dit blok wilt verwijderen?"), /* @__PURE__ */ React25__namespace.createElement(AlertDialogFooter, null, /* @__PURE__ */ React25__namespace.createElement(AlertDialogCancel, null, "Annuleren"), /* @__PURE__ */ React25__namespace.createElement(
2215
+ AlertDialogAction,
2216
+ {
2217
+ className: chunk3QWMKMTN_js.buttonVariants({ variant: "destructive" }),
2218
+ onClick: () => deleteContent(contentId)
2219
+ },
2220
+ "Verwijderen"
2221
+ ))));
2222
+ };
2223
+
2224
+ // src/components/build-container-client.tsx
2225
+ var BuildContainerInner = (props) => {
2226
+ const { id, name, content, multiple = false } = props;
2227
+ const items = Array.isArray(content) ? content : content?.[name] || [];
2228
+ if (!multiple && items.length > 1) {
2229
+ console.error(
2230
+ "[simple-builder]: Multiple content blocks detected when using property multiple false."
2231
+ );
2232
+ }
2233
+ return /* @__PURE__ */ React25__namespace.createElement("div", null, items.length <= 0 ? /* @__PURE__ */ React25__namespace.createElement(AddContentPlaceholder, { parent: id, container: name, index: 0 }) : multiple && /* @__PURE__ */ React25__namespace.createElement(AddContentDividerButton, { parent: id, container: name, index: 0 }), items.map((item, i) => /* @__PURE__ */ React25__namespace.createElement(React25__namespace.Fragment, { key: item.id }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:relative sb-container-item" }, /* @__PURE__ */ React25__namespace.createElement(chunkTMDKQB2L_js.DesignWrapper, { building: true, styles: item.styles }, chunkTMDKQB2L_js.builder.bindComponent(item, true)), /* @__PURE__ */ React25__namespace.createElement(
2234
+ ContainerItemToolbar,
2235
+ {
2236
+ contentId: item.id,
2237
+ canBringUp: i > 0,
2238
+ canBringDown: i < items.length - 1
2239
+ }
2240
+ )), multiple && /* @__PURE__ */ React25__namespace.createElement(
2241
+ AddContentDividerButton,
2242
+ {
2243
+ parent: id,
2244
+ container: name,
2245
+ index: i + 1
2246
+ }
2247
+ ))));
2248
+ };
2249
+ var build_container_client_default = BuildContainerInner;
2250
+ var AddContentButton = (props) => {
2251
+ const components = chunkTMDKQB2L_js.builder.getComponents();
2252
+ const { addContent } = chunk3QWMKMTN_js.useBuilder();
2253
+ return /* @__PURE__ */ React25__namespace.createElement(Popover, null, /* @__PURE__ */ React25__namespace.createElement(PopoverTrigger, { asChild: true }, props.children), /* @__PURE__ */ React25__namespace.createElement(PopoverContent, { className: "sb:p-1 sb:w-screen sb:max-w-lg" }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:grid sb:grid-cols-2 sb:gap-2" }, components.map((component) => {
2254
+ const Icon2 = component.icon ?? lucideReact.ImageIcon;
2255
+ return /* @__PURE__ */ React25__namespace.createElement(PopoverClose, { key: component.name, asChild: true }, /* @__PURE__ */ React25__namespace.createElement(
2256
+ chunk3QWMKMTN_js.Button,
2257
+ {
2258
+ variant: "ghost",
2259
+ className: "sb:justify-start",
2260
+ onClick: () => {
2261
+ addContent(
2262
+ component.name,
2263
+ props.container,
2264
+ props.parent,
2265
+ props.index
2266
+ );
2267
+ }
2268
+ },
2269
+ /* @__PURE__ */ React25__namespace.createElement(Icon2, { className: "sb:mr-2 sb:h-4 sb:w-4 sb:shrink-0" }),
2270
+ /* @__PURE__ */ React25__namespace.createElement("span", { className: "sb:truncate" }, component.friendlyName ?? component.name)
2271
+ ));
2272
+ }))));
2273
+ };
2274
+ var AddContentPlaceholder = (props) => {
2275
+ return /* @__PURE__ */ React25__namespace.createElement(AddContentButton, { ...props }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:flex sb:justify-center sb:bg-primary/50 p-4" }, /* @__PURE__ */ React25__namespace.createElement(chunk3QWMKMTN_js.Button, { size: "sm" }, /* @__PURE__ */ React25__namespace.createElement(lucideReact.PlusIcon, { className: "sb:mr-2 sb:h-4 sb:w-4" }), "Blok Toevoegen")));
2276
+ };
2277
+ var AddContentDividerButton = (props) => {
2278
+ return /* @__PURE__ */ React25__namespace.createElement(AddContentButton, { ...props }, /* @__PURE__ */ React25__namespace.createElement("div", { className: "sb:w-full sb:h-1 sb:-my-[2px] sb:bg-primary sb:relative sb:z-20 sb:opacity-0 add-content-divider-button sb:transition-opacity" }, /* @__PURE__ */ React25__namespace.createElement(
2279
+ chunk3QWMKMTN_js.Button,
2280
+ {
2281
+ size: "sm",
2282
+ className: "sb:absolute sb:left-1/2 sb:top-1/2 sb:-translate-y-1/2 sb:-translate-x-1/2 sb:shadow"
2283
+ },
2284
+ /* @__PURE__ */ React25__namespace.createElement(lucideReact.PlusIcon, { className: "sb:mr-2 sb:h-4 sb:w-4" }),
2285
+ "Blok Toevoegen"
2286
+ )));
2287
+ };
2288
+
2289
+ module.exports = build_container_client_default;