react-tailwind-email-editor 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,4679 @@
1
+ 'use strict';
2
+
3
+ var React9 = require('react');
4
+ var core = require('@craftjs/core');
5
+ var AccordionPrimitive = require('@radix-ui/react-accordion');
6
+ var lucideReact = require('lucide-react');
7
+ var clsx = require('clsx');
8
+ var tailwindMerge = require('tailwind-merge');
9
+ var jsxRuntime = require('react/jsx-runtime');
10
+ var reactSlot = require('@radix-ui/react-slot');
11
+ var classVarianceAuthority = require('class-variance-authority');
12
+ var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
13
+ var DialogPrimitive = require('@radix-ui/react-dialog');
14
+ var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
15
+
16
+ function _interopNamespace(e) {
17
+ if (e && e.__esModule) return e;
18
+ var n = Object.create(null);
19
+ if (e) {
20
+ Object.keys(e).forEach(function (k) {
21
+ if (k !== 'default') {
22
+ var d = Object.getOwnPropertyDescriptor(e, k);
23
+ Object.defineProperty(n, k, d.get ? d : {
24
+ enumerable: true,
25
+ get: function () { return e[k]; }
26
+ });
27
+ }
28
+ });
29
+ }
30
+ n.default = e;
31
+ return Object.freeze(n);
32
+ }
33
+
34
+ var React9__namespace = /*#__PURE__*/_interopNamespace(React9);
35
+ var AccordionPrimitive__namespace = /*#__PURE__*/_interopNamespace(AccordionPrimitive);
36
+ var ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespace(ScrollAreaPrimitive);
37
+ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
38
+ var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
39
+
40
+ // src/components/editor/EmailEditor.tsx
41
+ function cn(...inputs) {
42
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
43
+ }
44
+ var Accordion = AccordionPrimitive__namespace.Root;
45
+ var AccordionItem = React9__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
46
+ AccordionPrimitive__namespace.Item,
47
+ {
48
+ ref,
49
+ className: cn("border-b", className),
50
+ ...props
51
+ }
52
+ ));
53
+ AccordionItem.displayName = "AccordionItem";
54
+ var AccordionTrigger = React9__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(AccordionPrimitive__namespace.Header, { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsxs(
55
+ AccordionPrimitive__namespace.Trigger,
56
+ {
57
+ ref,
58
+ className: cn(
59
+ "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
60
+ className
61
+ ),
62
+ ...props,
63
+ children: [
64
+ children,
65
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4 shrink-0 transition-transform duration-200" })
66
+ ]
67
+ }
68
+ ) }));
69
+ AccordionTrigger.displayName = AccordionPrimitive__namespace.Trigger.displayName;
70
+ var AccordionContent = React9__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
71
+ AccordionPrimitive__namespace.Content,
72
+ {
73
+ ref,
74
+ className: "overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
75
+ ...props,
76
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("pb-4 pt-0", className), children })
77
+ }
78
+ ));
79
+ AccordionContent.displayName = AccordionPrimitive__namespace.Content.displayName;
80
+ var defaultTheme = {
81
+ paperWidth: 600,
82
+ paperMinHeight: 800,
83
+ paperBackground: "#ffffff"
84
+ };
85
+ var EditorContext = React9.createContext({
86
+ components: {},
87
+ theme: defaultTheme,
88
+ slots: {},
89
+ templates: [],
90
+ callbacks: {},
91
+ htmlRenderers: {},
92
+ title: "Email Editor",
93
+ showToolbar: true,
94
+ showToolbox: true,
95
+ showSettingsPanel: true
96
+ });
97
+ var useEditorConfig = () => React9.useContext(EditorContext);
98
+ var EditorProvider = ({ children, value }) => {
99
+ const mergedTheme = React9.useMemo(
100
+ () => ({ ...defaultTheme, ...value.theme }),
101
+ [value.theme]
102
+ );
103
+ const ctx = React9.useMemo(
104
+ () => ({ ...value, theme: mergedTheme }),
105
+ [value, mergedTheme]
106
+ );
107
+ return /* @__PURE__ */ jsxRuntime.jsx(EditorContext.Provider, { value: ctx, children });
108
+ };
109
+ var ToolboxItem = ({ name, config }) => {
110
+ const { connectors } = core.useEditor();
111
+ const Component = config.component;
112
+ const element = config.createElement ? config.createElement() : /* @__PURE__ */ jsxRuntime.jsx(Component, {});
113
+ const IconComp = config.icon;
114
+ return /* @__PURE__ */ jsxRuntime.jsxs(
115
+ "div",
116
+ {
117
+ ref: (ref) => ref && connectors.create(ref, element),
118
+ className: "flex items-center gap-3 p-2.5 border rounded-lg cursor-grab hover:bg-accent hover:border-primary/50 transition-all group",
119
+ title: config.description,
120
+ children: [
121
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-9 h-9 rounded-md bg-muted flex items-center justify-center text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary transition-colors", children: IconComp && /* @__PURE__ */ jsxRuntime.jsx(IconComp, { className: "h-4 w-4" }) }),
122
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
123
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground block truncate", children: config.label }),
124
+ config.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground block truncate", children: config.description })
125
+ ] })
126
+ ]
127
+ }
128
+ );
129
+ };
130
+ var Toolbox = () => {
131
+ const { components } = useEditorConfig();
132
+ const grouped = React9__namespace.default.useMemo(() => {
133
+ const map = {};
134
+ for (const [name, config] of Object.entries(components)) {
135
+ const cat = config.category || "Other";
136
+ if (!map[cat]) map[cat] = [];
137
+ map[cat].push([name, config]);
138
+ }
139
+ return map;
140
+ }, [components]);
141
+ const categoryKeys = Object.keys(grouped);
142
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsx(Accordion, { type: "multiple", defaultValue: categoryKeys, children: categoryKeys.map((category, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
143
+ AccordionItem,
144
+ {
145
+ value: category,
146
+ className: idx < categoryKeys.length - 1 ? "border-b" : "border-b-0",
147
+ children: [
148
+ /* @__PURE__ */ jsxRuntime.jsx(AccordionTrigger, { className: "py-3 text-xs font-semibold uppercase tracking-wider text-muted-foreground hover:no-underline", children: category }),
149
+ /* @__PURE__ */ jsxRuntime.jsxs(AccordionContent, { className: "pb-3", children: [
150
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: grouped[category].map(([name, config]) => /* @__PURE__ */ jsxRuntime.jsx(ToolboxItem, { name, config }, name)) }),
151
+ category === "Dynamic" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 p-3 bg-muted/50 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
152
+ "Use variables like",
153
+ " ",
154
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "bg-primary/10 text-primary px-1 rounded", children: "{{first_name}}" }),
155
+ " ",
156
+ "for personalized emails"
157
+ ] }) })
158
+ ] })
159
+ ]
160
+ },
161
+ category
162
+ )) }) });
163
+ };
164
+ var buttonVariants = classVarianceAuthority.cva(
165
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
166
+ {
167
+ variants: {
168
+ variant: {
169
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
170
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
171
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
172
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
173
+ ghost: "hover:bg-accent hover:text-accent-foreground",
174
+ link: "text-primary underline-offset-4 hover:underline"
175
+ },
176
+ size: {
177
+ default: "h-10 px-4 py-2",
178
+ sm: "h-9 rounded-md px-3",
179
+ lg: "h-11 rounded-md px-8",
180
+ icon: "h-10 w-10"
181
+ }
182
+ },
183
+ defaultVariants: {
184
+ variant: "default",
185
+ size: "default"
186
+ }
187
+ }
188
+ );
189
+ var Button = React9__namespace.forwardRef(
190
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
191
+ const Comp = asChild ? reactSlot.Slot : "button";
192
+ return /* @__PURE__ */ jsxRuntime.jsx(
193
+ Comp,
194
+ {
195
+ className: cn(buttonVariants({ variant, size, className })),
196
+ ref,
197
+ ...props
198
+ }
199
+ );
200
+ }
201
+ );
202
+ Button.displayName = "Button";
203
+ var ScrollArea = React9__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
204
+ ScrollAreaPrimitive__namespace.Root,
205
+ {
206
+ ref,
207
+ className: cn("relative overflow-hidden", className),
208
+ ...props,
209
+ children: [
210
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollAreaPrimitive__namespace.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
211
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollBar, {}),
212
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollAreaPrimitive__namespace.Corner, {})
213
+ ]
214
+ }
215
+ ));
216
+ ScrollArea.displayName = ScrollAreaPrimitive__namespace.Root.displayName;
217
+ var ScrollBar = React9__namespace.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
218
+ ScrollAreaPrimitive__namespace.ScrollAreaScrollbar,
219
+ {
220
+ ref,
221
+ orientation,
222
+ className: cn(
223
+ "flex touch-none select-none transition-colors",
224
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
225
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
226
+ className
227
+ ),
228
+ ...props,
229
+ children: /* @__PURE__ */ jsxRuntime.jsx(ScrollAreaPrimitive__namespace.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
230
+ }
231
+ ));
232
+ ScrollBar.displayName = ScrollAreaPrimitive__namespace.ScrollAreaScrollbar.displayName;
233
+ var SettingsPanel = () => {
234
+ const { slots } = useEditorConfig();
235
+ const { selected, actions, query } = core.useEditor((state) => {
236
+ var _a;
237
+ const [currentNodeId] = state.events.selected;
238
+ let selected2;
239
+ if (currentNodeId) {
240
+ selected2 = {
241
+ id: currentNodeId,
242
+ name: state.nodes[currentNodeId].data.name,
243
+ displayName: state.nodes[currentNodeId].data.displayName || state.nodes[currentNodeId].data.name,
244
+ settings: (_a = state.nodes[currentNodeId].related) == null ? void 0 : _a.settings,
245
+ isDeletable: state.nodes[currentNodeId].data.name !== "Paper",
246
+ parent: state.nodes[currentNodeId].data.parent,
247
+ props: state.nodes[currentNodeId].data.props
248
+ };
249
+ }
250
+ return { selected: selected2 };
251
+ });
252
+ const handleDuplicate = () => {
253
+ if (!selected || !selected.isDeletable) return;
254
+ const node = query.node(selected.id).get();
255
+ const parent = node.data.parent;
256
+ if (parent) {
257
+ try {
258
+ const serializedNode = query.node(selected.id).toSerializedNode();
259
+ const parentNode = query.node(parent).get();
260
+ const siblings = parentNode.data.nodes || [];
261
+ const currentIndex = siblings.indexOf(selected.id);
262
+ const newNode = query.parseSerializedNode(serializedNode).toNode((node2) => {
263
+ node2.id = `${node2.data.name}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
264
+ return node2;
265
+ });
266
+ actions.addNodeTree(
267
+ { rootNodeId: newNode.id, nodes: { [newNode.id]: newNode } },
268
+ parent,
269
+ currentIndex + 1
270
+ );
271
+ } catch (e) {
272
+ console.log("Duplicate error:", e);
273
+ }
274
+ }
275
+ };
276
+ const handleMoveUp = () => {
277
+ if (!selected || !selected.parent) return;
278
+ const parentNode = query.node(selected.parent).get();
279
+ const siblings = parentNode.data.nodes || [];
280
+ const currentIndex = siblings.indexOf(selected.id);
281
+ if (currentIndex > 0) {
282
+ actions.move(selected.id, selected.parent, currentIndex - 1);
283
+ }
284
+ };
285
+ const handleMoveDown = () => {
286
+ if (!selected || !selected.parent) return;
287
+ const parentNode = query.node(selected.parent).get();
288
+ const siblings = parentNode.data.nodes || [];
289
+ const currentIndex = siblings.indexOf(selected.id);
290
+ if (currentIndex < siblings.length - 1) {
291
+ actions.move(selected.id, selected.parent, currentIndex + 2);
292
+ }
293
+ };
294
+ if (slots.settingsPanel && selected) {
295
+ return React9__namespace.default.createElement(slots.settingsPanel, {
296
+ selectedId: selected.id,
297
+ selectedName: selected.displayName || selected.name,
298
+ //@ts-ignore
299
+ selectedSettings: selected.settings,
300
+ onDelete: selected.isDeletable ? () => actions.delete(selected.id) : void 0,
301
+ onDuplicate: handleDuplicate,
302
+ onMoveUp: handleMoveUp,
303
+ onMoveDown: handleMoveDown
304
+ });
305
+ }
306
+ if (!selected) {
307
+ if (slots.settingsEmptyState) {
308
+ return React9__namespace.default.createElement(slots.settingsEmptyState);
309
+ }
310
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 text-center", children: [
311
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 mx-auto mb-4 rounded-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Layers, { className: "h-8 w-8 text-muted-foreground" }) }),
312
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-medium text-foreground mb-2", children: "No Element Selected" }),
313
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Click on a component in the canvas to edit its properties" })
314
+ ] });
315
+ }
316
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col", children: [
317
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b bg-muted/30", children: [
318
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
319
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 rounded-full bg-primary" }),
320
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-semibold text-sm", children: selected.displayName || selected.name })
321
+ ] }) }),
322
+ selected.isDeletable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5", children: [
323
+ /* @__PURE__ */ jsxRuntime.jsxs(
324
+ Button,
325
+ {
326
+ variant: "outline",
327
+ size: "sm",
328
+ className: "flex-1 h-8 text-xs",
329
+ onClick: handleMoveUp,
330
+ title: "Move Up",
331
+ children: [
332
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "h-3.5 w-3.5 mr-1" }),
333
+ " Up"
334
+ ]
335
+ }
336
+ ),
337
+ /* @__PURE__ */ jsxRuntime.jsxs(
338
+ Button,
339
+ {
340
+ variant: "outline",
341
+ size: "sm",
342
+ className: "flex-1 h-8 text-xs",
343
+ onClick: handleMoveDown,
344
+ title: "Move Down",
345
+ children: [
346
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5 mr-1" }),
347
+ " Down"
348
+ ]
349
+ }
350
+ ),
351
+ /* @__PURE__ */ jsxRuntime.jsxs(
352
+ Button,
353
+ {
354
+ variant: "outline",
355
+ size: "sm",
356
+ className: "flex-1 h-8 text-xs",
357
+ onClick: handleDuplicate,
358
+ title: "Duplicate",
359
+ children: [
360
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3.5 w-3.5 mr-1" }),
361
+ " Copy"
362
+ ]
363
+ }
364
+ ),
365
+ /* @__PURE__ */ jsxRuntime.jsx(
366
+ Button,
367
+ {
368
+ variant: "destructive",
369
+ size: "sm",
370
+ className: "h-8 w-8 p-0",
371
+ onClick: () => actions.delete(selected.id),
372
+ title: "Delete",
373
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" })
374
+ }
375
+ )
376
+ ] })
377
+ ] }),
378
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: selected.settings ? /* @__PURE__ */ jsxRuntime.jsx(Accordion, { type: "multiple", defaultValue: ["content"], children: /* @__PURE__ */ jsxRuntime.jsxs(AccordionItem, { value: "content", className: "border-b", children: [
379
+ /* @__PURE__ */ jsxRuntime.jsx(AccordionTrigger, { className: "py-3 text-sm hover:no-underline", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
380
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { className: "h-4 w-4 text-muted-foreground" }),
381
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Properties" })
382
+ ] }) }),
383
+ /* @__PURE__ */ jsxRuntime.jsx(AccordionContent, { className: "pb-4", children: React9__namespace.default.createElement(selected.settings) })
384
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-muted-foreground text-sm py-8", children: [
385
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paintbrush, { className: "h-8 w-8 mx-auto mb-2 opacity-50" }),
386
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "No editable properties" })
387
+ ] }) }) }),
388
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 border-t bg-muted/20 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
389
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
390
+ "Component: ",
391
+ selected.name
392
+ ] }),
393
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px]", children: selected.id.slice(0, 8) })
394
+ ] }) })
395
+ ] });
396
+ };
397
+ var Paper = ({ children, background }) => {
398
+ const { connectors: { connect } } = core.useNode();
399
+ const { theme } = useEditorConfig();
400
+ const bg = background || theme.paperBackground || "#ffffff";
401
+ return /* @__PURE__ */ jsxRuntime.jsx(
402
+ "div",
403
+ {
404
+ ref: (ref) => connect(ref),
405
+ style: {
406
+ width: `${theme.paperWidth || 600}px`,
407
+ minHeight: `${theme.paperMinHeight || 800}px`,
408
+ margin: "0 auto",
409
+ backgroundColor: bg,
410
+ boxShadow: "0 4px 20px rgba(0, 0, 0, 0.15)",
411
+ position: "relative"
412
+ },
413
+ children
414
+ }
415
+ );
416
+ };
417
+ var PaperSettings = () => {
418
+ const { actions: { setProp }, background } = core.useNode((node) => ({
419
+ background: node.data.props.background
420
+ }));
421
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
422
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Email Background" }),
423
+ /* @__PURE__ */ jsxRuntime.jsx(
424
+ "input",
425
+ {
426
+ type: "color",
427
+ value: background || "#ffffff",
428
+ onChange: (e) => setProp((props) => props.background = e.target.value),
429
+ className: "w-full h-10 rounded border cursor-pointer"
430
+ }
431
+ )
432
+ ] }) });
433
+ };
434
+ Paper.craft = {
435
+ props: {
436
+ background: "#ffffff"
437
+ },
438
+ related: {
439
+ settings: PaperSettings
440
+ }
441
+ };
442
+ var RenderNode = ({ render }) => {
443
+ const { id } = core.useNode();
444
+ const { actions, query, isActive } = core.useEditor((_, query2) => ({
445
+ isActive: query2.getEvent("selected").contains(id)
446
+ }));
447
+ const {
448
+ isHover,
449
+ dom,
450
+ name,
451
+ moveable,
452
+ deletable,
453
+ connectors: { drag },
454
+ parent
455
+ } = core.useNode((node) => ({
456
+ isHover: node.events.hovered,
457
+ dom: node.dom,
458
+ name: node.data.custom.displayName || node.data.displayName,
459
+ moveable: query.node(node.id).isDraggable(),
460
+ deletable: query.node(node.id).isDeletable(),
461
+ parent: node.data.parent
462
+ }));
463
+ React9.useEffect(() => {
464
+ if (dom) {
465
+ if (isActive || isHover) {
466
+ dom.classList.add("component-selected");
467
+ } else {
468
+ dom.classList.remove("component-selected");
469
+ }
470
+ }
471
+ }, [dom, isActive, isHover]);
472
+ const getPos = React9.useCallback((dom2) => {
473
+ const { top, left, bottom } = dom2 ? dom2.getBoundingClientRect() : { top: 0, left: 0, bottom: 0 };
474
+ return {
475
+ top: `${top > 0 ? top : bottom}px`,
476
+ left: `${left}px`
477
+ };
478
+ }, []);
479
+ const scroll = React9.useCallback(() => {
480
+ const currentDOM = dom;
481
+ if (!currentDOM) return;
482
+ const { top, left } = getPos(currentDOM);
483
+ }, [dom, getPos]);
484
+ React9.useEffect(() => {
485
+ var _a;
486
+ (_a = document.querySelector(".craftjs-renderer")) == null ? void 0 : _a.addEventListener("scroll", scroll);
487
+ return () => {
488
+ var _a2;
489
+ (_a2 = document.querySelector(".craftjs-renderer")) == null ? void 0 : _a2.removeEventListener("scroll", scroll);
490
+ };
491
+ }, [scroll]);
492
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
493
+ isHover || isActive ? /* @__PURE__ */ jsxRuntime.jsxs(
494
+ "div",
495
+ {
496
+ className: "absolute -top-7 left-0 bg-primary text-primary-foreground text-xs px-2 py-1 rounded flex items-center gap-1 z-50",
497
+ style: {
498
+ pointerEvents: "auto"
499
+ },
500
+ children: [
501
+ moveable && /* @__PURE__ */ jsxRuntime.jsx(
502
+ "span",
503
+ {
504
+ ref: (ref) => ref && drag(ref),
505
+ className: "cursor-grab",
506
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Move, { className: "h-3 w-3" })
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: name }),
510
+ parent && /* @__PURE__ */ jsxRuntime.jsx(
511
+ "button",
512
+ {
513
+ onClick: () => actions.selectNode(parent),
514
+ className: "ml-1 hover:bg-primary-foreground/20 rounded p-0.5",
515
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-3 w-3" })
516
+ }
517
+ )
518
+ ]
519
+ }
520
+ ) : null,
521
+ render
522
+ ] });
523
+ };
524
+ var Container = ({ background = "#ffffff", padding = 20, children }) => {
525
+ const { connectors: { connect, drag } } = core.useNode();
526
+ return /* @__PURE__ */ jsxRuntime.jsx(
527
+ "div",
528
+ {
529
+ ref: (ref) => connect(drag(ref)),
530
+ style: {
531
+ background,
532
+ padding: `${padding}px`,
533
+ minHeight: "50px",
534
+ width: "100%"
535
+ },
536
+ children
537
+ }
538
+ );
539
+ };
540
+ var ContainerSettings = () => {
541
+ const { actions: { setProp }, background, padding } = core.useNode((node) => ({
542
+ background: node.data.props.background,
543
+ padding: node.data.props.padding
544
+ }));
545
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
546
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
547
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
548
+ /* @__PURE__ */ jsxRuntime.jsx(
549
+ "input",
550
+ {
551
+ type: "color",
552
+ value: background || "#ffffff",
553
+ onChange: (e) => setProp((props) => props.background = e.target.value),
554
+ className: "w-full h-10 rounded border cursor-pointer"
555
+ }
556
+ )
557
+ ] }),
558
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
559
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
560
+ /* @__PURE__ */ jsxRuntime.jsx(
561
+ "input",
562
+ {
563
+ type: "range",
564
+ min: 0,
565
+ max: 60,
566
+ value: padding || 20,
567
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
568
+ className: "w-full"
569
+ }
570
+ ),
571
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
572
+ padding,
573
+ "px"
574
+ ] })
575
+ ] })
576
+ ] });
577
+ };
578
+ Container.craft = {
579
+ props: {
580
+ background: "#ffffff",
581
+ padding: 20
582
+ },
583
+ related: {
584
+ settings: ContainerSettings
585
+ }
586
+ };
587
+ var EmailHeader = ({
588
+ logoUrl = "",
589
+ companyName = "Your Company",
590
+ backgroundColor = "#1a1a2e",
591
+ textColor = "#ffffff",
592
+ padding = 24
593
+ }) => {
594
+ const { connectors: { connect, drag } } = core.useNode();
595
+ return /* @__PURE__ */ jsxRuntime.jsxs(
596
+ "div",
597
+ {
598
+ ref: (ref) => connect(drag(ref)),
599
+ style: {
600
+ backgroundColor,
601
+ padding: `${padding}px`,
602
+ textAlign: "center"
603
+ },
604
+ children: [
605
+ logoUrl && /* @__PURE__ */ jsxRuntime.jsx(
606
+ "img",
607
+ {
608
+ src: logoUrl,
609
+ alt: "Logo",
610
+ style: { maxHeight: "60px", marginBottom: "12px" }
611
+ }
612
+ ),
613
+ /* @__PURE__ */ jsxRuntime.jsx(
614
+ "h1",
615
+ {
616
+ style: {
617
+ color: textColor,
618
+ fontSize: "24px",
619
+ fontWeight: "bold",
620
+ margin: 0,
621
+ fontFamily: "Arial, sans-serif"
622
+ },
623
+ children: companyName
624
+ }
625
+ )
626
+ ]
627
+ }
628
+ );
629
+ };
630
+ var EmailHeaderSettings = () => {
631
+ const { actions: { setProp }, logoUrl, companyName, backgroundColor, textColor, padding } = core.useNode((node) => ({
632
+ logoUrl: node.data.props.logoUrl,
633
+ companyName: node.data.props.companyName,
634
+ backgroundColor: node.data.props.backgroundColor,
635
+ textColor: node.data.props.textColor,
636
+ padding: node.data.props.padding
637
+ }));
638
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
639
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
640
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Company Name" }),
641
+ /* @__PURE__ */ jsxRuntime.jsx(
642
+ "input",
643
+ {
644
+ type: "text",
645
+ value: companyName || "",
646
+ onChange: (e) => setProp((props) => props.companyName = e.target.value),
647
+ className: "w-full px-3 py-2 border rounded-md text-sm"
648
+ }
649
+ )
650
+ ] }),
651
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
652
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Logo URL" }),
653
+ /* @__PURE__ */ jsxRuntime.jsx(
654
+ "input",
655
+ {
656
+ type: "text",
657
+ value: logoUrl || "",
658
+ onChange: (e) => setProp((props) => props.logoUrl = e.target.value),
659
+ className: "w-full px-3 py-2 border rounded-md text-sm",
660
+ placeholder: "https://example.com/logo.png"
661
+ }
662
+ )
663
+ ] }),
664
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
665
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
666
+ /* @__PURE__ */ jsxRuntime.jsx(
667
+ "input",
668
+ {
669
+ type: "color",
670
+ value: backgroundColor || "#1a1a2e",
671
+ onChange: (e) => setProp((props) => props.backgroundColor = e.target.value),
672
+ className: "w-full h-10 rounded border cursor-pointer"
673
+ }
674
+ )
675
+ ] }),
676
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
677
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Text Color" }),
678
+ /* @__PURE__ */ jsxRuntime.jsx(
679
+ "input",
680
+ {
681
+ type: "color",
682
+ value: textColor || "#ffffff",
683
+ onChange: (e) => setProp((props) => props.textColor = e.target.value),
684
+ className: "w-full h-10 rounded border cursor-pointer"
685
+ }
686
+ )
687
+ ] }),
688
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
689
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
690
+ /* @__PURE__ */ jsxRuntime.jsx(
691
+ "input",
692
+ {
693
+ type: "range",
694
+ min: 0,
695
+ max: 60,
696
+ value: padding || 24,
697
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
698
+ className: "w-full"
699
+ }
700
+ ),
701
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
702
+ padding,
703
+ "px"
704
+ ] })
705
+ ] })
706
+ ] });
707
+ };
708
+ EmailHeader.craft = {
709
+ props: {
710
+ logoUrl: "",
711
+ companyName: "Your Company",
712
+ backgroundColor: "#1a1a2e",
713
+ textColor: "#ffffff",
714
+ padding: 24
715
+ },
716
+ related: {
717
+ settings: EmailHeaderSettings
718
+ }
719
+ };
720
+ var EmailFooter = ({
721
+ companyName = "Your Company",
722
+ address = "123 Business St, City, Country",
723
+ email = "info@company.com",
724
+ phone = "+1 234 567 890",
725
+ backgroundColor = "#f5f5f5",
726
+ textColor = "#666666",
727
+ padding = 24
728
+ }) => {
729
+ const { connectors: { connect, drag } } = core.useNode();
730
+ return /* @__PURE__ */ jsxRuntime.jsxs(
731
+ "div",
732
+ {
733
+ ref: (ref) => connect(drag(ref)),
734
+ style: {
735
+ backgroundColor,
736
+ padding: `${padding}px`,
737
+ textAlign: "center",
738
+ fontFamily: "Arial, sans-serif"
739
+ },
740
+ children: [
741
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: textColor, fontSize: "14px", margin: "0 0 8px 0", fontWeight: "bold" }, children: companyName }),
742
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: textColor, fontSize: "12px", margin: "0 0 4px 0" }, children: address }),
743
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { color: textColor, fontSize: "12px", margin: "0 0 4px 0" }, children: [
744
+ "Email: ",
745
+ email,
746
+ " | Phone: ",
747
+ phone
748
+ ] }),
749
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { color: textColor, fontSize: "11px", margin: "12px 0 0 0", opacity: 0.7 }, children: [
750
+ "\xA9 ",
751
+ (/* @__PURE__ */ new Date()).getFullYear(),
752
+ " ",
753
+ companyName,
754
+ ". All rights reserved."
755
+ ] })
756
+ ]
757
+ }
758
+ );
759
+ };
760
+ var EmailFooterSettings = () => {
761
+ const { actions: { setProp }, companyName, address, email, phone, backgroundColor, textColor, padding } = core.useNode((node) => ({
762
+ companyName: node.data.props.companyName,
763
+ address: node.data.props.address,
764
+ email: node.data.props.email,
765
+ phone: node.data.props.phone,
766
+ backgroundColor: node.data.props.backgroundColor,
767
+ textColor: node.data.props.textColor,
768
+ padding: node.data.props.padding
769
+ }));
770
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
771
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
772
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Company Name" }),
773
+ /* @__PURE__ */ jsxRuntime.jsx(
774
+ "input",
775
+ {
776
+ type: "text",
777
+ value: companyName || "",
778
+ onChange: (e) => setProp((props) => props.companyName = e.target.value),
779
+ className: "w-full px-3 py-2 border rounded-md text-sm"
780
+ }
781
+ )
782
+ ] }),
783
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
784
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Address" }),
785
+ /* @__PURE__ */ jsxRuntime.jsx(
786
+ "input",
787
+ {
788
+ type: "text",
789
+ value: address || "",
790
+ onChange: (e) => setProp((props) => props.address = e.target.value),
791
+ className: "w-full px-3 py-2 border rounded-md text-sm"
792
+ }
793
+ )
794
+ ] }),
795
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
796
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Email" }),
797
+ /* @__PURE__ */ jsxRuntime.jsx(
798
+ "input",
799
+ {
800
+ type: "email",
801
+ value: email || "",
802
+ onChange: (e) => setProp((props) => props.email = e.target.value),
803
+ className: "w-full px-3 py-2 border rounded-md text-sm"
804
+ }
805
+ )
806
+ ] }),
807
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
808
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Phone" }),
809
+ /* @__PURE__ */ jsxRuntime.jsx(
810
+ "input",
811
+ {
812
+ type: "text",
813
+ value: phone || "",
814
+ onChange: (e) => setProp((props) => props.phone = e.target.value),
815
+ className: "w-full px-3 py-2 border rounded-md text-sm"
816
+ }
817
+ )
818
+ ] }),
819
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
820
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
821
+ /* @__PURE__ */ jsxRuntime.jsx(
822
+ "input",
823
+ {
824
+ type: "color",
825
+ value: backgroundColor || "#f5f5f5",
826
+ onChange: (e) => setProp((props) => props.backgroundColor = e.target.value),
827
+ className: "w-full h-10 rounded border cursor-pointer"
828
+ }
829
+ )
830
+ ] }),
831
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
832
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Text Color" }),
833
+ /* @__PURE__ */ jsxRuntime.jsx(
834
+ "input",
835
+ {
836
+ type: "color",
837
+ value: textColor || "#666666",
838
+ onChange: (e) => setProp((props) => props.textColor = e.target.value),
839
+ className: "w-full h-10 rounded border cursor-pointer"
840
+ }
841
+ )
842
+ ] }),
843
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
844
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
845
+ /* @__PURE__ */ jsxRuntime.jsx(
846
+ "input",
847
+ {
848
+ type: "range",
849
+ min: 0,
850
+ max: 60,
851
+ value: padding || 24,
852
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
853
+ className: "w-full"
854
+ }
855
+ ),
856
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
857
+ padding,
858
+ "px"
859
+ ] })
860
+ ] })
861
+ ] });
862
+ };
863
+ EmailFooter.craft = {
864
+ props: {
865
+ companyName: "Your Company",
866
+ address: "123 Business St, City, Country",
867
+ email: "info@company.com",
868
+ phone: "+1 234 567 890",
869
+ backgroundColor: "#f5f5f5",
870
+ textColor: "#666666",
871
+ padding: 24
872
+ },
873
+ related: {
874
+ settings: EmailFooterSettings
875
+ }
876
+ };
877
+ var EmailButton = ({
878
+ text = "Click Here",
879
+ href = "#",
880
+ backgroundColor = "#0066cc",
881
+ textColor = "#ffffff",
882
+ borderRadius = 6,
883
+ paddingX = 24,
884
+ paddingY = 12,
885
+ fontSize = 16,
886
+ align = "center"
887
+ }) => {
888
+ const { connectors: { connect, drag } } = core.useNode();
889
+ return /* @__PURE__ */ jsxRuntime.jsx(
890
+ "div",
891
+ {
892
+ ref: (ref) => connect(drag(ref)),
893
+ style: {
894
+ textAlign: align,
895
+ padding: "10px 0"
896
+ },
897
+ children: /* @__PURE__ */ jsxRuntime.jsx(
898
+ "a",
899
+ {
900
+ href,
901
+ style: {
902
+ display: "inline-block",
903
+ backgroundColor,
904
+ color: textColor,
905
+ padding: `${paddingY}px ${paddingX}px`,
906
+ borderRadius: `${borderRadius}px`,
907
+ textDecoration: "none",
908
+ fontSize: `${fontSize}px`,
909
+ fontWeight: "bold",
910
+ fontFamily: "Arial, sans-serif"
911
+ },
912
+ children: text
913
+ }
914
+ )
915
+ }
916
+ );
917
+ };
918
+ var EmailButtonSettings = () => {
919
+ const { actions: { setProp }, text, href, backgroundColor, textColor, borderRadius, paddingX, paddingY, fontSize, align } = core.useNode((node) => ({
920
+ text: node.data.props.text,
921
+ href: node.data.props.href,
922
+ backgroundColor: node.data.props.backgroundColor,
923
+ textColor: node.data.props.textColor,
924
+ borderRadius: node.data.props.borderRadius,
925
+ paddingX: node.data.props.paddingX,
926
+ paddingY: node.data.props.paddingY,
927
+ fontSize: node.data.props.fontSize,
928
+ align: node.data.props.align
929
+ }));
930
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
931
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
932
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Button Text" }),
933
+ /* @__PURE__ */ jsxRuntime.jsx(
934
+ "input",
935
+ {
936
+ type: "text",
937
+ value: text || "",
938
+ onChange: (e) => setProp((props) => props.text = e.target.value),
939
+ className: "w-full px-3 py-2 border rounded-md text-sm"
940
+ }
941
+ )
942
+ ] }),
943
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
944
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Link URL" }),
945
+ /* @__PURE__ */ jsxRuntime.jsx(
946
+ "input",
947
+ {
948
+ type: "text",
949
+ value: href || "",
950
+ onChange: (e) => setProp((props) => props.href = e.target.value),
951
+ className: "w-full px-3 py-2 border rounded-md text-sm"
952
+ }
953
+ )
954
+ ] }),
955
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
956
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Alignment" }),
957
+ /* @__PURE__ */ jsxRuntime.jsxs(
958
+ "select",
959
+ {
960
+ value: align || "center",
961
+ onChange: (e) => setProp((props) => props.align = e.target.value),
962
+ className: "w-full px-3 py-2 border rounded-md text-sm",
963
+ children: [
964
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "left", children: "Left" }),
965
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "center", children: "Center" }),
966
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "right", children: "Right" })
967
+ ]
968
+ }
969
+ )
970
+ ] }),
971
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
972
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
973
+ /* @__PURE__ */ jsxRuntime.jsx(
974
+ "input",
975
+ {
976
+ type: "color",
977
+ value: backgroundColor || "#0066cc",
978
+ onChange: (e) => setProp((props) => props.backgroundColor = e.target.value),
979
+ className: "w-full h-10 rounded border cursor-pointer"
980
+ }
981
+ )
982
+ ] }),
983
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
984
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Text Color" }),
985
+ /* @__PURE__ */ jsxRuntime.jsx(
986
+ "input",
987
+ {
988
+ type: "color",
989
+ value: textColor || "#ffffff",
990
+ onChange: (e) => setProp((props) => props.textColor = e.target.value),
991
+ className: "w-full h-10 rounded border cursor-pointer"
992
+ }
993
+ )
994
+ ] }),
995
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
996
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Border Radius" }),
997
+ /* @__PURE__ */ jsxRuntime.jsx(
998
+ "input",
999
+ {
1000
+ type: "range",
1001
+ min: 0,
1002
+ max: 30,
1003
+ value: borderRadius || 6,
1004
+ onChange: (e) => setProp((props) => props.borderRadius = parseInt(e.target.value)),
1005
+ className: "w-full"
1006
+ }
1007
+ ),
1008
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1009
+ borderRadius,
1010
+ "px"
1011
+ ] })
1012
+ ] }),
1013
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1014
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Font Size" }),
1015
+ /* @__PURE__ */ jsxRuntime.jsx(
1016
+ "input",
1017
+ {
1018
+ type: "range",
1019
+ min: 12,
1020
+ max: 24,
1021
+ value: fontSize || 16,
1022
+ onChange: (e) => setProp((props) => props.fontSize = parseInt(e.target.value)),
1023
+ className: "w-full"
1024
+ }
1025
+ ),
1026
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1027
+ fontSize,
1028
+ "px"
1029
+ ] })
1030
+ ] })
1031
+ ] });
1032
+ };
1033
+ EmailButton.craft = {
1034
+ props: {
1035
+ text: "Click Here",
1036
+ href: "#",
1037
+ backgroundColor: "#0066cc",
1038
+ textColor: "#ffffff",
1039
+ borderRadius: 6,
1040
+ paddingX: 24,
1041
+ paddingY: 12,
1042
+ fontSize: 16,
1043
+ align: "center"
1044
+ },
1045
+ related: {
1046
+ settings: EmailButtonSettings
1047
+ }
1048
+ };
1049
+ var TextBlock = ({
1050
+ text = "Enter your text here...",
1051
+ fontSize = 14,
1052
+ fontWeight = "normal",
1053
+ color = "#333333",
1054
+ align = "left",
1055
+ padding = 10,
1056
+ lineHeight = 1.6
1057
+ }) => {
1058
+ const { connectors: { connect, drag } } = core.useNode();
1059
+ return /* @__PURE__ */ jsxRuntime.jsx(
1060
+ "div",
1061
+ {
1062
+ ref: (ref) => connect(drag(ref)),
1063
+ style: {
1064
+ padding: `${padding}px`
1065
+ },
1066
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1067
+ "p",
1068
+ {
1069
+ style: {
1070
+ fontSize: `${fontSize}px`,
1071
+ fontWeight,
1072
+ color,
1073
+ textAlign: align,
1074
+ lineHeight,
1075
+ margin: 0,
1076
+ fontFamily: "Arial, sans-serif"
1077
+ },
1078
+ children: text
1079
+ }
1080
+ )
1081
+ }
1082
+ );
1083
+ };
1084
+ var TextBlockSettings = () => {
1085
+ const { actions: { setProp }, text, fontSize, fontWeight, color, align, padding, lineHeight } = core.useNode((node) => ({
1086
+ text: node.data.props.text,
1087
+ fontSize: node.data.props.fontSize,
1088
+ fontWeight: node.data.props.fontWeight,
1089
+ color: node.data.props.color,
1090
+ align: node.data.props.align,
1091
+ padding: node.data.props.padding,
1092
+ lineHeight: node.data.props.lineHeight
1093
+ }));
1094
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1095
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1096
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Text Content" }),
1097
+ /* @__PURE__ */ jsxRuntime.jsx(
1098
+ "textarea",
1099
+ {
1100
+ value: text || "",
1101
+ onChange: (e) => setProp((props) => props.text = e.target.value),
1102
+ className: "w-full px-3 py-2 border rounded-md text-sm min-h-[80px]"
1103
+ }
1104
+ )
1105
+ ] }),
1106
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1107
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Font Size" }),
1108
+ /* @__PURE__ */ jsxRuntime.jsx(
1109
+ "input",
1110
+ {
1111
+ type: "range",
1112
+ min: 10,
1113
+ max: 32,
1114
+ value: fontSize || 14,
1115
+ onChange: (e) => setProp((props) => props.fontSize = parseInt(e.target.value)),
1116
+ className: "w-full"
1117
+ }
1118
+ ),
1119
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1120
+ fontSize,
1121
+ "px"
1122
+ ] })
1123
+ ] }),
1124
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1125
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Font Weight" }),
1126
+ /* @__PURE__ */ jsxRuntime.jsxs(
1127
+ "select",
1128
+ {
1129
+ value: fontWeight || "normal",
1130
+ onChange: (e) => setProp((props) => props.fontWeight = e.target.value),
1131
+ className: "w-full px-3 py-2 border rounded-md text-sm",
1132
+ children: [
1133
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "normal", children: "Normal" }),
1134
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "bold", children: "Bold" })
1135
+ ]
1136
+ }
1137
+ )
1138
+ ] }),
1139
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1140
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Text Color" }),
1141
+ /* @__PURE__ */ jsxRuntime.jsx(
1142
+ "input",
1143
+ {
1144
+ type: "color",
1145
+ value: color || "#333333",
1146
+ onChange: (e) => setProp((props) => props.color = e.target.value),
1147
+ className: "w-full h-10 rounded border cursor-pointer"
1148
+ }
1149
+ )
1150
+ ] }),
1151
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1152
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Alignment" }),
1153
+ /* @__PURE__ */ jsxRuntime.jsxs(
1154
+ "select",
1155
+ {
1156
+ value: align || "left",
1157
+ onChange: (e) => setProp((props) => props.align = e.target.value),
1158
+ className: "w-full px-3 py-2 border rounded-md text-sm",
1159
+ children: [
1160
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "left", children: "Left" }),
1161
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "center", children: "Center" }),
1162
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "right", children: "Right" })
1163
+ ]
1164
+ }
1165
+ )
1166
+ ] }),
1167
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1168
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
1169
+ /* @__PURE__ */ jsxRuntime.jsx(
1170
+ "input",
1171
+ {
1172
+ type: "range",
1173
+ min: 0,
1174
+ max: 40,
1175
+ value: padding || 10,
1176
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
1177
+ className: "w-full"
1178
+ }
1179
+ ),
1180
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1181
+ padding,
1182
+ "px"
1183
+ ] })
1184
+ ] }),
1185
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1186
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Line Height" }),
1187
+ /* @__PURE__ */ jsxRuntime.jsx(
1188
+ "input",
1189
+ {
1190
+ type: "range",
1191
+ min: 1,
1192
+ max: 2.5,
1193
+ step: 0.1,
1194
+ value: lineHeight || 1.6,
1195
+ onChange: (e) => setProp((props) => props.lineHeight = parseFloat(e.target.value)),
1196
+ className: "w-full"
1197
+ }
1198
+ ),
1199
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: lineHeight })
1200
+ ] })
1201
+ ] });
1202
+ };
1203
+ TextBlock.craft = {
1204
+ props: {
1205
+ text: "Enter your text here...",
1206
+ fontSize: 14,
1207
+ fontWeight: "normal",
1208
+ color: "#333333",
1209
+ align: "left",
1210
+ padding: 10,
1211
+ lineHeight: 1.6
1212
+ },
1213
+ related: {
1214
+ settings: TextBlockSettings
1215
+ }
1216
+ };
1217
+ var ImageBlock = ({
1218
+ src = "https://via.placeholder.com/400x200",
1219
+ alt = "Image",
1220
+ width = "100%",
1221
+ align = "center",
1222
+ padding = 10,
1223
+ borderRadius = 0
1224
+ }) => {
1225
+ const { connectors: { connect, drag } } = core.useNode();
1226
+ return /* @__PURE__ */ jsxRuntime.jsx(
1227
+ "div",
1228
+ {
1229
+ ref: (ref) => connect(drag(ref)),
1230
+ style: {
1231
+ textAlign: align,
1232
+ padding: `${padding}px`
1233
+ },
1234
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1235
+ "img",
1236
+ {
1237
+ src,
1238
+ alt,
1239
+ style: {
1240
+ width,
1241
+ maxWidth: "100%",
1242
+ borderRadius: `${borderRadius}px`,
1243
+ display: "inline-block"
1244
+ }
1245
+ }
1246
+ )
1247
+ }
1248
+ );
1249
+ };
1250
+ var ImageBlockSettings = () => {
1251
+ const { actions: { setProp }, src, alt, width, align, padding, borderRadius } = core.useNode((node) => ({
1252
+ src: node.data.props.src,
1253
+ alt: node.data.props.alt,
1254
+ width: node.data.props.width,
1255
+ align: node.data.props.align,
1256
+ padding: node.data.props.padding,
1257
+ borderRadius: node.data.props.borderRadius
1258
+ }));
1259
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1260
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1261
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Image URL" }),
1262
+ /* @__PURE__ */ jsxRuntime.jsx(
1263
+ "input",
1264
+ {
1265
+ type: "text",
1266
+ value: src || "",
1267
+ onChange: (e) => setProp((props) => props.src = e.target.value),
1268
+ className: "w-full px-3 py-2 border rounded-md text-sm",
1269
+ placeholder: "https://example.com/image.png"
1270
+ }
1271
+ )
1272
+ ] }),
1273
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1274
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Alt Text" }),
1275
+ /* @__PURE__ */ jsxRuntime.jsx(
1276
+ "input",
1277
+ {
1278
+ type: "text",
1279
+ value: alt || "",
1280
+ onChange: (e) => setProp((props) => props.alt = e.target.value),
1281
+ className: "w-full px-3 py-2 border rounded-md text-sm"
1282
+ }
1283
+ )
1284
+ ] }),
1285
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1286
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Width" }),
1287
+ /* @__PURE__ */ jsxRuntime.jsx(
1288
+ "input",
1289
+ {
1290
+ type: "text",
1291
+ value: width || "100%",
1292
+ onChange: (e) => setProp((props) => props.width = e.target.value),
1293
+ className: "w-full px-3 py-2 border rounded-md text-sm",
1294
+ placeholder: "100% or 300px"
1295
+ }
1296
+ )
1297
+ ] }),
1298
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1299
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Alignment" }),
1300
+ /* @__PURE__ */ jsxRuntime.jsxs(
1301
+ "select",
1302
+ {
1303
+ value: align || "center",
1304
+ onChange: (e) => setProp((props) => props.align = e.target.value),
1305
+ className: "w-full px-3 py-2 border rounded-md text-sm",
1306
+ children: [
1307
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "left", children: "Left" }),
1308
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "center", children: "Center" }),
1309
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "right", children: "Right" })
1310
+ ]
1311
+ }
1312
+ )
1313
+ ] }),
1314
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1315
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
1316
+ /* @__PURE__ */ jsxRuntime.jsx(
1317
+ "input",
1318
+ {
1319
+ type: "range",
1320
+ min: 0,
1321
+ max: 40,
1322
+ value: padding || 10,
1323
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
1324
+ className: "w-full"
1325
+ }
1326
+ ),
1327
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1328
+ padding,
1329
+ "px"
1330
+ ] })
1331
+ ] }),
1332
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1333
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Border Radius" }),
1334
+ /* @__PURE__ */ jsxRuntime.jsx(
1335
+ "input",
1336
+ {
1337
+ type: "range",
1338
+ min: 0,
1339
+ max: 30,
1340
+ value: borderRadius || 0,
1341
+ onChange: (e) => setProp((props) => props.borderRadius = parseInt(e.target.value)),
1342
+ className: "w-full"
1343
+ }
1344
+ ),
1345
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1346
+ borderRadius,
1347
+ "px"
1348
+ ] })
1349
+ ] })
1350
+ ] });
1351
+ };
1352
+ ImageBlock.craft = {
1353
+ props: {
1354
+ src: "https://via.placeholder.com/400x200",
1355
+ alt: "Image",
1356
+ width: "100%",
1357
+ align: "center",
1358
+ padding: 10,
1359
+ borderRadius: 0
1360
+ },
1361
+ related: {
1362
+ settings: ImageBlockSettings
1363
+ }
1364
+ };
1365
+ var Divider = ({
1366
+ color = "#e0e0e0",
1367
+ thickness = 1,
1368
+ margin = 20,
1369
+ width = "100%"
1370
+ }) => {
1371
+ const { connectors: { connect, drag } } = core.useNode();
1372
+ return /* @__PURE__ */ jsxRuntime.jsx(
1373
+ "div",
1374
+ {
1375
+ ref: (ref) => connect(drag(ref)),
1376
+ style: {
1377
+ padding: `${margin}px 0`,
1378
+ textAlign: "center"
1379
+ },
1380
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1381
+ "hr",
1382
+ {
1383
+ style: {
1384
+ border: "none",
1385
+ borderTop: `${thickness}px solid ${color}`,
1386
+ width,
1387
+ margin: "0 auto"
1388
+ }
1389
+ }
1390
+ )
1391
+ }
1392
+ );
1393
+ };
1394
+ var DividerSettings = () => {
1395
+ const { actions: { setProp }, color, thickness, margin, width } = core.useNode((node) => ({
1396
+ color: node.data.props.color,
1397
+ thickness: node.data.props.thickness,
1398
+ margin: node.data.props.margin,
1399
+ width: node.data.props.width
1400
+ }));
1401
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1402
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1403
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Color" }),
1404
+ /* @__PURE__ */ jsxRuntime.jsx(
1405
+ "input",
1406
+ {
1407
+ type: "color",
1408
+ value: color || "#e0e0e0",
1409
+ onChange: (e) => setProp((props) => props.color = e.target.value),
1410
+ className: "w-full h-10 rounded border cursor-pointer"
1411
+ }
1412
+ )
1413
+ ] }),
1414
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1415
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Thickness" }),
1416
+ /* @__PURE__ */ jsxRuntime.jsx(
1417
+ "input",
1418
+ {
1419
+ type: "range",
1420
+ min: 1,
1421
+ max: 10,
1422
+ value: thickness || 1,
1423
+ onChange: (e) => setProp((props) => props.thickness = parseInt(e.target.value)),
1424
+ className: "w-full"
1425
+ }
1426
+ ),
1427
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1428
+ thickness,
1429
+ "px"
1430
+ ] })
1431
+ ] }),
1432
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1433
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Margin (Top/Bottom)" }),
1434
+ /* @__PURE__ */ jsxRuntime.jsx(
1435
+ "input",
1436
+ {
1437
+ type: "range",
1438
+ min: 0,
1439
+ max: 40,
1440
+ value: margin || 20,
1441
+ onChange: (e) => setProp((props) => props.margin = parseInt(e.target.value)),
1442
+ className: "w-full"
1443
+ }
1444
+ ),
1445
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1446
+ margin,
1447
+ "px"
1448
+ ] })
1449
+ ] }),
1450
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1451
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Width" }),
1452
+ /* @__PURE__ */ jsxRuntime.jsx(
1453
+ "input",
1454
+ {
1455
+ type: "text",
1456
+ value: width || "100%",
1457
+ onChange: (e) => setProp((props) => props.width = e.target.value),
1458
+ className: "w-full px-3 py-2 border rounded-md text-sm",
1459
+ placeholder: "100% or 80%"
1460
+ }
1461
+ )
1462
+ ] })
1463
+ ] });
1464
+ };
1465
+ Divider.craft = {
1466
+ props: {
1467
+ color: "#e0e0e0",
1468
+ thickness: 1,
1469
+ margin: 20,
1470
+ width: "100%"
1471
+ },
1472
+ related: {
1473
+ settings: DividerSettings
1474
+ }
1475
+ };
1476
+ var InvoiceTable = ({
1477
+ items = [
1478
+ { description: "Service Item 1", quantity: 1, unitPrice: 100 },
1479
+ { description: "Service Item 2", quantity: 2, unitPrice: 50 }
1480
+ ],
1481
+ headerBg = "#1a1a2e",
1482
+ headerColor = "#ffffff",
1483
+ borderColor = "#e0e0e0",
1484
+ showTotal = true,
1485
+ currency = "$"
1486
+ }) => {
1487
+ const {
1488
+ connectors: { connect, drag }
1489
+ } = core.useNode();
1490
+ const total = items.reduce(
1491
+ (sum, item) => sum + item.quantity * item.unitPrice,
1492
+ 0
1493
+ );
1494
+ const cellStyle = {
1495
+ padding: "12px 16px",
1496
+ borderBottom: `1px solid ${borderColor}`,
1497
+ fontFamily: "Arial, sans-serif",
1498
+ fontSize: "14px"
1499
+ };
1500
+ const headerStyle = {
1501
+ ...cellStyle,
1502
+ backgroundColor: headerBg,
1503
+ color: headerColor,
1504
+ fontWeight: "bold",
1505
+ textAlign: "left"
1506
+ };
1507
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: (ref) => connect(drag(ref)), style: { padding: "10px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
1508
+ "table",
1509
+ {
1510
+ style: {
1511
+ width: "100%",
1512
+ borderCollapse: "collapse",
1513
+ border: `1px solid ${borderColor}`
1514
+ },
1515
+ children: [
1516
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1517
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: headerStyle, children: "Description" }),
1518
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { ...headerStyle, textAlign: "center", width: "80px" }, children: "Qty" }),
1519
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { ...headerStyle, textAlign: "right", width: "100px" }, children: "Unit Price" }),
1520
+ /* @__PURE__ */ jsxRuntime.jsx("th", { style: { ...headerStyle, textAlign: "right", width: "100px" }, children: "Amount" })
1521
+ ] }) }),
1522
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1523
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: cellStyle, children: item.description }),
1524
+ /* @__PURE__ */ jsxRuntime.jsx("td", { style: { ...cellStyle, textAlign: "center" }, children: item.quantity }),
1525
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { style: { ...cellStyle, textAlign: "right" }, children: [
1526
+ currency,
1527
+ item.unitPrice.toFixed(2)
1528
+ ] }),
1529
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { style: { ...cellStyle, textAlign: "right" }, children: [
1530
+ currency,
1531
+ (item.quantity * item.unitPrice).toFixed(2)
1532
+ ] })
1533
+ ] }, index)) }),
1534
+ showTotal && /* @__PURE__ */ jsxRuntime.jsx("tfoot", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
1535
+ /* @__PURE__ */ jsxRuntime.jsx(
1536
+ "td",
1537
+ {
1538
+ colSpan: 3,
1539
+ style: { ...cellStyle, textAlign: "right", fontWeight: "bold" },
1540
+ children: "Total:"
1541
+ }
1542
+ ),
1543
+ /* @__PURE__ */ jsxRuntime.jsxs(
1544
+ "td",
1545
+ {
1546
+ style: {
1547
+ ...cellStyle,
1548
+ textAlign: "right",
1549
+ fontWeight: "bold",
1550
+ backgroundColor: "#f5f5f5"
1551
+ },
1552
+ children: [
1553
+ currency,
1554
+ total.toFixed(2)
1555
+ ]
1556
+ }
1557
+ )
1558
+ ] }) })
1559
+ ]
1560
+ }
1561
+ ) });
1562
+ };
1563
+ var InvoiceTableSettings = () => {
1564
+ const {
1565
+ actions: { setProp },
1566
+ items,
1567
+ headerBg,
1568
+ headerColor,
1569
+ borderColor,
1570
+ showTotal,
1571
+ currency
1572
+ } = core.useNode((node) => ({
1573
+ items: node.data.props.items,
1574
+ headerBg: node.data.props.headerBg,
1575
+ headerColor: node.data.props.headerColor,
1576
+ borderColor: node.data.props.borderColor,
1577
+ showTotal: node.data.props.showTotal,
1578
+ currency: node.data.props.currency
1579
+ }));
1580
+ const updateItem = (index, field, value) => {
1581
+ setProp((props) => {
1582
+ const newItems = [...props.items || []];
1583
+ newItems[index] = { ...newItems[index], [field]: value };
1584
+ props.items = newItems;
1585
+ });
1586
+ };
1587
+ const addItem = () => {
1588
+ setProp((props) => {
1589
+ props.items = [
1590
+ ...props.items || [],
1591
+ { description: "New Item", quantity: 1, unitPrice: 0 }
1592
+ ];
1593
+ });
1594
+ };
1595
+ const removeItem = (index) => {
1596
+ setProp((props) => {
1597
+ props.items = (props.items || []).filter((_, i) => i !== index);
1598
+ });
1599
+ };
1600
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1601
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1602
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-2", children: "Invoice Items" }),
1603
+ (items || []).map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-3 p-3 border rounded-md bg-muted/30", children: [
1604
+ /* @__PURE__ */ jsxRuntime.jsx(
1605
+ "input",
1606
+ {
1607
+ type: "text",
1608
+ value: item.description,
1609
+ onChange: (e) => updateItem(index, "description", e.target.value),
1610
+ className: "w-full px-2 py-1 border rounded text-sm mb-2",
1611
+ placeholder: "Description"
1612
+ }
1613
+ ),
1614
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
1615
+ /* @__PURE__ */ jsxRuntime.jsx(
1616
+ "input",
1617
+ {
1618
+ type: "number",
1619
+ value: item.quantity,
1620
+ onChange: (e) => updateItem(index, "quantity", parseInt(e.target.value) || 0),
1621
+ className: "w-20 px-2 py-1 border rounded text-sm",
1622
+ placeholder: "Qty"
1623
+ }
1624
+ ),
1625
+ /* @__PURE__ */ jsxRuntime.jsx(
1626
+ "input",
1627
+ {
1628
+ type: "number",
1629
+ value: item.unitPrice,
1630
+ onChange: (e) => updateItem(
1631
+ index,
1632
+ "unitPrice",
1633
+ parseFloat(e.target.value) || 0
1634
+ ),
1635
+ className: "flex-1 px-2 py-1 border rounded text-sm",
1636
+ placeholder: "Price"
1637
+ }
1638
+ ),
1639
+ /* @__PURE__ */ jsxRuntime.jsx(
1640
+ "button",
1641
+ {
1642
+ onClick: () => removeItem(index),
1643
+ className: "px-2 py-1 bg-destructive text-destructive-foreground rounded text-sm",
1644
+ children: "\xD7"
1645
+ }
1646
+ )
1647
+ ] })
1648
+ ] }, index)),
1649
+ /* @__PURE__ */ jsxRuntime.jsx(
1650
+ "button",
1651
+ {
1652
+ onClick: addItem,
1653
+ className: "w-full py-2 border-2 border-dashed rounded-md text-sm text-muted-foreground hover:bg-muted/50",
1654
+ children: "+ Add Item"
1655
+ }
1656
+ )
1657
+ ] }),
1658
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1659
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Currency Symbol" }),
1660
+ /* @__PURE__ */ jsxRuntime.jsx(
1661
+ "input",
1662
+ {
1663
+ type: "text",
1664
+ value: currency || "$",
1665
+ onChange: (e) => setProp(
1666
+ (props) => props.currency = e.target.value
1667
+ ),
1668
+ className: "w-full px-3 py-2 border rounded-md text-sm"
1669
+ }
1670
+ )
1671
+ ] }),
1672
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1673
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Header Background" }),
1674
+ /* @__PURE__ */ jsxRuntime.jsx(
1675
+ "input",
1676
+ {
1677
+ type: "color",
1678
+ value: headerBg || "#1a1a2e",
1679
+ onChange: (e) => setProp(
1680
+ (props) => props.headerBg = e.target.value
1681
+ ),
1682
+ className: "w-full h-10 rounded border cursor-pointer"
1683
+ }
1684
+ )
1685
+ ] }),
1686
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1687
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Header Text Color" }),
1688
+ /* @__PURE__ */ jsxRuntime.jsx(
1689
+ "input",
1690
+ {
1691
+ type: "color",
1692
+ value: headerColor || "#ffffff",
1693
+ onChange: (e) => setProp(
1694
+ (props) => props.headerColor = e.target.value
1695
+ ),
1696
+ className: "w-full h-10 rounded border cursor-pointer"
1697
+ }
1698
+ )
1699
+ ] }),
1700
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1701
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Border Color" }),
1702
+ /* @__PURE__ */ jsxRuntime.jsx(
1703
+ "input",
1704
+ {
1705
+ type: "color",
1706
+ value: borderColor || "#e0e0e0",
1707
+ onChange: (e) => setProp(
1708
+ (props) => props.borderColor = e.target.value
1709
+ ),
1710
+ className: "w-full h-10 rounded border cursor-pointer"
1711
+ }
1712
+ )
1713
+ ] }),
1714
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1715
+ /* @__PURE__ */ jsxRuntime.jsx(
1716
+ "input",
1717
+ {
1718
+ type: "checkbox",
1719
+ checked: showTotal != null ? showTotal : true,
1720
+ onChange: (e) => setProp(
1721
+ (props) => props.showTotal = e.target.checked
1722
+ ),
1723
+ className: "rounded"
1724
+ }
1725
+ ),
1726
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Show Total Row" })
1727
+ ] })
1728
+ ] });
1729
+ };
1730
+ InvoiceTable.craft = {
1731
+ props: {
1732
+ items: [
1733
+ { description: "Service Item 1", quantity: 1, unitPrice: 100 },
1734
+ { description: "Service Item 2", quantity: 2, unitPrice: 50 }
1735
+ ],
1736
+ headerBg: "#1a1a2e",
1737
+ headerColor: "#ffffff",
1738
+ borderColor: "#e0e0e0",
1739
+ showTotal: true,
1740
+ currency: "$"
1741
+ },
1742
+ related: {
1743
+ settings: InvoiceTableSettings
1744
+ }
1745
+ };
1746
+ var Spacer = ({ height = 20 }) => {
1747
+ const { connectors: { connect, drag } } = core.useNode();
1748
+ return /* @__PURE__ */ jsxRuntime.jsx(
1749
+ "div",
1750
+ {
1751
+ ref: (ref) => connect(drag(ref)),
1752
+ style: {
1753
+ height: `${height}px`,
1754
+ width: "100%",
1755
+ backgroundColor: "transparent"
1756
+ }
1757
+ }
1758
+ );
1759
+ };
1760
+ var SpacerSettings = () => {
1761
+ const { actions: { setProp }, height } = core.useNode((node) => ({
1762
+ height: node.data.props.height
1763
+ }));
1764
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1765
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Height" }),
1766
+ /* @__PURE__ */ jsxRuntime.jsx(
1767
+ "input",
1768
+ {
1769
+ type: "range",
1770
+ min: 5,
1771
+ max: 100,
1772
+ value: height || 20,
1773
+ onChange: (e) => setProp((props) => props.height = parseInt(e.target.value)),
1774
+ className: "w-full"
1775
+ }
1776
+ ),
1777
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1778
+ height,
1779
+ "px"
1780
+ ] })
1781
+ ] }) });
1782
+ };
1783
+ Spacer.craft = {
1784
+ props: {
1785
+ height: 20
1786
+ },
1787
+ related: {
1788
+ settings: SpacerSettings
1789
+ }
1790
+ };
1791
+ var socialIcons = {
1792
+ facebook: "https://cdn-icons-png.flaticon.com/128/733/733547.png",
1793
+ twitter: "https://cdn-icons-png.flaticon.com/128/733/733579.png",
1794
+ instagram: "https://cdn-icons-png.flaticon.com/128/2111/2111463.png",
1795
+ linkedin: "https://cdn-icons-png.flaticon.com/128/3536/3536505.png",
1796
+ youtube: "https://cdn-icons-png.flaticon.com/128/1384/1384060.png",
1797
+ tiktok: "https://cdn-icons-png.flaticon.com/128/3046/3046121.png"
1798
+ };
1799
+ var SocialLinks = ({
1800
+ links = [
1801
+ { platform: "facebook", url: "#" },
1802
+ { platform: "twitter", url: "#" },
1803
+ { platform: "instagram", url: "#" },
1804
+ { platform: "linkedin", url: "#" }
1805
+ ],
1806
+ iconSize = 32,
1807
+ iconColor = "#333333",
1808
+ backgroundColor = "transparent",
1809
+ align = "center",
1810
+ padding = 16,
1811
+ gap = 16
1812
+ }) => {
1813
+ const { connectors: { connect, drag } } = core.useNode();
1814
+ return /* @__PURE__ */ jsxRuntime.jsx(
1815
+ "div",
1816
+ {
1817
+ ref: (ref) => connect(drag(ref)),
1818
+ style: {
1819
+ textAlign: align,
1820
+ padding: `${padding}px`,
1821
+ backgroundColor
1822
+ },
1823
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "inline-flex", gap: `${gap}px` }, children: links.map((link, index) => /* @__PURE__ */ jsxRuntime.jsx(
1824
+ "a",
1825
+ {
1826
+ href: link.url,
1827
+ style: {
1828
+ display: "inline-block",
1829
+ width: iconSize,
1830
+ height: iconSize
1831
+ },
1832
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1833
+ "img",
1834
+ {
1835
+ src: socialIcons[link.platform],
1836
+ alt: link.platform,
1837
+ style: {
1838
+ width: "100%",
1839
+ height: "100%",
1840
+ objectFit: "contain"
1841
+ }
1842
+ }
1843
+ )
1844
+ },
1845
+ index
1846
+ )) })
1847
+ }
1848
+ );
1849
+ };
1850
+ var SocialLinksSettings = () => {
1851
+ const { actions: { setProp }, links, iconSize, align, padding, gap, backgroundColor } = core.useNode((node) => ({
1852
+ links: node.data.props.links,
1853
+ iconSize: node.data.props.iconSize,
1854
+ align: node.data.props.align,
1855
+ padding: node.data.props.padding,
1856
+ gap: node.data.props.gap,
1857
+ backgroundColor: node.data.props.backgroundColor
1858
+ }));
1859
+ const platforms = ["facebook", "twitter", "instagram", "linkedin", "youtube", "tiktok"];
1860
+ const currentLinks = links || [];
1861
+ const togglePlatform = (platform) => {
1862
+ const exists = currentLinks.find((l) => l.platform === platform);
1863
+ if (exists) {
1864
+ setProp((props) => {
1865
+ props.links = currentLinks.filter((l) => l.platform !== platform);
1866
+ });
1867
+ } else {
1868
+ setProp((props) => {
1869
+ props.links = [...currentLinks, { platform, url: "#" }];
1870
+ });
1871
+ }
1872
+ };
1873
+ const updateUrl = (platform, url) => {
1874
+ setProp((props) => {
1875
+ props.links = currentLinks.map(
1876
+ (l) => l.platform === platform ? { ...l, url } : l
1877
+ );
1878
+ });
1879
+ };
1880
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1881
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1882
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-2", children: "Platforms" }),
1883
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2", children: platforms.map((platform) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer", children: [
1884
+ /* @__PURE__ */ jsxRuntime.jsx(
1885
+ "input",
1886
+ {
1887
+ type: "checkbox",
1888
+ checked: currentLinks.some((l) => l.platform === platform),
1889
+ onChange: () => togglePlatform(platform),
1890
+ className: "rounded"
1891
+ }
1892
+ ),
1893
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "capitalize", children: platform })
1894
+ ] }, platform)) })
1895
+ ] }),
1896
+ currentLinks.map((link) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1897
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block text-sm font-medium mb-1 capitalize", children: [
1898
+ link.platform,
1899
+ " URL"
1900
+ ] }),
1901
+ /* @__PURE__ */ jsxRuntime.jsx(
1902
+ "input",
1903
+ {
1904
+ type: "text",
1905
+ value: link.url,
1906
+ onChange: (e) => updateUrl(link.platform, e.target.value),
1907
+ className: "w-full px-3 py-2 border rounded-md text-sm",
1908
+ placeholder: "https://..."
1909
+ }
1910
+ )
1911
+ ] }, link.platform)),
1912
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1913
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Icon Size" }),
1914
+ /* @__PURE__ */ jsxRuntime.jsx(
1915
+ "input",
1916
+ {
1917
+ type: "range",
1918
+ min: 20,
1919
+ max: 48,
1920
+ value: iconSize || 32,
1921
+ onChange: (e) => setProp((props) => props.iconSize = parseInt(e.target.value)),
1922
+ className: "w-full"
1923
+ }
1924
+ ),
1925
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1926
+ iconSize,
1927
+ "px"
1928
+ ] })
1929
+ ] }),
1930
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1931
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Gap" }),
1932
+ /* @__PURE__ */ jsxRuntime.jsx(
1933
+ "input",
1934
+ {
1935
+ type: "range",
1936
+ min: 8,
1937
+ max: 32,
1938
+ value: gap || 16,
1939
+ onChange: (e) => setProp((props) => props.gap = parseInt(e.target.value)),
1940
+ className: "w-full"
1941
+ }
1942
+ ),
1943
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1944
+ gap,
1945
+ "px"
1946
+ ] })
1947
+ ] }),
1948
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1949
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Alignment" }),
1950
+ /* @__PURE__ */ jsxRuntime.jsxs(
1951
+ "select",
1952
+ {
1953
+ value: align || "center",
1954
+ onChange: (e) => setProp((props) => props.align = e.target.value),
1955
+ className: "w-full px-3 py-2 border rounded-md text-sm",
1956
+ children: [
1957
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "left", children: "Left" }),
1958
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "center", children: "Center" }),
1959
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "right", children: "Right" })
1960
+ ]
1961
+ }
1962
+ )
1963
+ ] }),
1964
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1965
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
1966
+ /* @__PURE__ */ jsxRuntime.jsx(
1967
+ "input",
1968
+ {
1969
+ type: "color",
1970
+ value: backgroundColor || "#ffffff",
1971
+ onChange: (e) => setProp((props) => props.backgroundColor = e.target.value),
1972
+ className: "w-full h-10 rounded border cursor-pointer"
1973
+ }
1974
+ )
1975
+ ] }),
1976
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1977
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
1978
+ /* @__PURE__ */ jsxRuntime.jsx(
1979
+ "input",
1980
+ {
1981
+ type: "range",
1982
+ min: 0,
1983
+ max: 40,
1984
+ value: padding || 16,
1985
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
1986
+ className: "w-full"
1987
+ }
1988
+ ),
1989
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
1990
+ padding,
1991
+ "px"
1992
+ ] })
1993
+ ] })
1994
+ ] });
1995
+ };
1996
+ SocialLinks.craft = {
1997
+ props: {
1998
+ links: [
1999
+ { platform: "facebook", url: "#" },
2000
+ { platform: "twitter", url: "#" },
2001
+ { platform: "instagram", url: "#" },
2002
+ { platform: "linkedin", url: "#" }
2003
+ ],
2004
+ iconSize: 32,
2005
+ iconColor: "#333333",
2006
+ backgroundColor: "transparent",
2007
+ align: "center",
2008
+ padding: 16,
2009
+ gap: 16
2010
+ },
2011
+ related: {
2012
+ settings: SocialLinksSettings
2013
+ }
2014
+ };
2015
+ var TwoColumn = ({
2016
+ leftWidth = 50,
2017
+ gap = 20,
2018
+ padding = 10,
2019
+ backgroundColor = "#ffffff"
2020
+ }) => {
2021
+ const { connectors: { connect, drag } } = core.useNode();
2022
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2023
+ "div",
2024
+ {
2025
+ ref: (ref) => connect(drag(ref)),
2026
+ style: {
2027
+ display: "flex",
2028
+ gap: `${gap}px`,
2029
+ padding: `${padding}px`,
2030
+ backgroundColor,
2031
+ width: "100%"
2032
+ },
2033
+ children: [
2034
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: `${leftWidth}%` }, children: /* @__PURE__ */ jsxRuntime.jsx(core.Element, { id: "left-column", is: Container, canvas: true, background: "#f9f9f9", padding: 10 }) }),
2035
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: `${100 - leftWidth}%` }, children: /* @__PURE__ */ jsxRuntime.jsx(core.Element, { id: "right-column", is: Container, canvas: true, background: "#f9f9f9", padding: 10 }) })
2036
+ ]
2037
+ }
2038
+ );
2039
+ };
2040
+ var TwoColumnSettings = () => {
2041
+ const { actions: { setProp }, leftWidth, gap, padding, backgroundColor } = core.useNode((node) => ({
2042
+ leftWidth: node.data.props.leftWidth,
2043
+ gap: node.data.props.gap,
2044
+ padding: node.data.props.padding,
2045
+ backgroundColor: node.data.props.backgroundColor
2046
+ }));
2047
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
2048
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2049
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Left Column Width" }),
2050
+ /* @__PURE__ */ jsxRuntime.jsx(
2051
+ "input",
2052
+ {
2053
+ type: "range",
2054
+ min: 20,
2055
+ max: 80,
2056
+ value: leftWidth || 50,
2057
+ onChange: (e) => setProp((props) => props.leftWidth = parseInt(e.target.value)),
2058
+ className: "w-full"
2059
+ }
2060
+ ),
2061
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm text-muted-foreground", children: [
2062
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2063
+ "Left: ",
2064
+ leftWidth,
2065
+ "%"
2066
+ ] }),
2067
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2068
+ "Right: ",
2069
+ 100 - (leftWidth || 50),
2070
+ "%"
2071
+ ] })
2072
+ ] })
2073
+ ] }),
2074
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2075
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Gap" }),
2076
+ /* @__PURE__ */ jsxRuntime.jsx(
2077
+ "input",
2078
+ {
2079
+ type: "range",
2080
+ min: 0,
2081
+ max: 40,
2082
+ value: gap || 20,
2083
+ onChange: (e) => setProp((props) => props.gap = parseInt(e.target.value)),
2084
+ className: "w-full"
2085
+ }
2086
+ ),
2087
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
2088
+ gap,
2089
+ "px"
2090
+ ] })
2091
+ ] }),
2092
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2093
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
2094
+ /* @__PURE__ */ jsxRuntime.jsx(
2095
+ "input",
2096
+ {
2097
+ type: "range",
2098
+ min: 0,
2099
+ max: 40,
2100
+ value: padding || 10,
2101
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
2102
+ className: "w-full"
2103
+ }
2104
+ ),
2105
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
2106
+ padding,
2107
+ "px"
2108
+ ] })
2109
+ ] }),
2110
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2111
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
2112
+ /* @__PURE__ */ jsxRuntime.jsx(
2113
+ "input",
2114
+ {
2115
+ type: "color",
2116
+ value: backgroundColor || "#ffffff",
2117
+ onChange: (e) => setProp((props) => props.backgroundColor = e.target.value),
2118
+ className: "w-full h-10 rounded border cursor-pointer"
2119
+ }
2120
+ )
2121
+ ] })
2122
+ ] });
2123
+ };
2124
+ TwoColumn.craft = {
2125
+ props: {
2126
+ leftWidth: 50,
2127
+ gap: 20,
2128
+ padding: 10,
2129
+ backgroundColor: "#ffffff"
2130
+ },
2131
+ related: {
2132
+ settings: TwoColumnSettings
2133
+ }
2134
+ };
2135
+ var Countdown = ({
2136
+ title = "Sale Ends In",
2137
+ days = 3,
2138
+ hours = 12,
2139
+ minutes = 45,
2140
+ seconds = 30,
2141
+ backgroundColor = "#ff6b6b",
2142
+ numberColor = "#ffffff",
2143
+ labelColor = "#ffffff",
2144
+ titleColor = "#ffffff",
2145
+ boxBackground = "rgba(0,0,0,0.2)",
2146
+ padding = 24
2147
+ }) => {
2148
+ const { connectors: { connect, drag } } = core.useNode();
2149
+ const TimeBox = ({ value, label }) => /* @__PURE__ */ jsxRuntime.jsxs(
2150
+ "div",
2151
+ {
2152
+ style: {
2153
+ background: boxBackground,
2154
+ padding: "12px 16px",
2155
+ borderRadius: "8px",
2156
+ textAlign: "center",
2157
+ minWidth: "60px"
2158
+ },
2159
+ children: [
2160
+ /* @__PURE__ */ jsxRuntime.jsx(
2161
+ "div",
2162
+ {
2163
+ style: {
2164
+ fontSize: "28px",
2165
+ fontWeight: "bold",
2166
+ color: numberColor,
2167
+ fontFamily: "Arial, sans-serif",
2168
+ lineHeight: 1.2
2169
+ },
2170
+ children: String(value).padStart(2, "0")
2171
+ }
2172
+ ),
2173
+ /* @__PURE__ */ jsxRuntime.jsx(
2174
+ "div",
2175
+ {
2176
+ style: {
2177
+ fontSize: "11px",
2178
+ color: labelColor,
2179
+ textTransform: "uppercase",
2180
+ letterSpacing: "1px",
2181
+ marginTop: "4px"
2182
+ },
2183
+ children: label
2184
+ }
2185
+ )
2186
+ ]
2187
+ }
2188
+ );
2189
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2190
+ "div",
2191
+ {
2192
+ ref: (ref) => connect(drag(ref)),
2193
+ style: {
2194
+ backgroundColor,
2195
+ padding: `${padding}px`,
2196
+ textAlign: "center"
2197
+ },
2198
+ children: [
2199
+ title && /* @__PURE__ */ jsxRuntime.jsx(
2200
+ "h3",
2201
+ {
2202
+ style: {
2203
+ color: titleColor,
2204
+ fontSize: "18px",
2205
+ fontWeight: "bold",
2206
+ marginBottom: "16px",
2207
+ fontFamily: "Arial, sans-serif",
2208
+ margin: "0 0 16px 0"
2209
+ },
2210
+ children: title
2211
+ }
2212
+ ),
2213
+ /* @__PURE__ */ jsxRuntime.jsxs(
2214
+ "div",
2215
+ {
2216
+ style: {
2217
+ display: "inline-flex",
2218
+ gap: "12px",
2219
+ justifyContent: "center"
2220
+ },
2221
+ children: [
2222
+ /* @__PURE__ */ jsxRuntime.jsx(TimeBox, { value: days, label: "Days" }),
2223
+ /* @__PURE__ */ jsxRuntime.jsx(TimeBox, { value: hours, label: "Hours" }),
2224
+ /* @__PURE__ */ jsxRuntime.jsx(TimeBox, { value: minutes, label: "Mins" }),
2225
+ /* @__PURE__ */ jsxRuntime.jsx(TimeBox, { value: seconds, label: "Secs" })
2226
+ ]
2227
+ }
2228
+ )
2229
+ ]
2230
+ }
2231
+ );
2232
+ };
2233
+ var CountdownSettings = () => {
2234
+ const {
2235
+ actions: { setProp },
2236
+ title,
2237
+ days,
2238
+ hours,
2239
+ minutes,
2240
+ seconds,
2241
+ backgroundColor,
2242
+ numberColor,
2243
+ labelColor,
2244
+ titleColor,
2245
+ boxBackground,
2246
+ padding
2247
+ } = core.useNode((node) => ({
2248
+ title: node.data.props.title,
2249
+ days: node.data.props.days,
2250
+ hours: node.data.props.hours,
2251
+ minutes: node.data.props.minutes,
2252
+ seconds: node.data.props.seconds,
2253
+ backgroundColor: node.data.props.backgroundColor,
2254
+ numberColor: node.data.props.numberColor,
2255
+ labelColor: node.data.props.labelColor,
2256
+ titleColor: node.data.props.titleColor,
2257
+ boxBackground: node.data.props.boxBackground,
2258
+ padding: node.data.props.padding
2259
+ }));
2260
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
2261
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2262
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Title" }),
2263
+ /* @__PURE__ */ jsxRuntime.jsx(
2264
+ "input",
2265
+ {
2266
+ type: "text",
2267
+ value: title || "",
2268
+ onChange: (e) => setProp((props) => props.title = e.target.value),
2269
+ className: "w-full px-3 py-2 border rounded-md text-sm"
2270
+ }
2271
+ )
2272
+ ] }),
2273
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
2274
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2275
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Days" }),
2276
+ /* @__PURE__ */ jsxRuntime.jsx(
2277
+ "input",
2278
+ {
2279
+ type: "number",
2280
+ min: 0,
2281
+ value: days || 0,
2282
+ onChange: (e) => setProp((props) => props.days = parseInt(e.target.value)),
2283
+ className: "w-full px-3 py-2 border rounded-md text-sm"
2284
+ }
2285
+ )
2286
+ ] }),
2287
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2288
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Hours" }),
2289
+ /* @__PURE__ */ jsxRuntime.jsx(
2290
+ "input",
2291
+ {
2292
+ type: "number",
2293
+ min: 0,
2294
+ max: 23,
2295
+ value: hours || 0,
2296
+ onChange: (e) => setProp((props) => props.hours = parseInt(e.target.value)),
2297
+ className: "w-full px-3 py-2 border rounded-md text-sm"
2298
+ }
2299
+ )
2300
+ ] }),
2301
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2302
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Minutes" }),
2303
+ /* @__PURE__ */ jsxRuntime.jsx(
2304
+ "input",
2305
+ {
2306
+ type: "number",
2307
+ min: 0,
2308
+ max: 59,
2309
+ value: minutes || 0,
2310
+ onChange: (e) => setProp((props) => props.minutes = parseInt(e.target.value)),
2311
+ className: "w-full px-3 py-2 border rounded-md text-sm"
2312
+ }
2313
+ )
2314
+ ] }),
2315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2316
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Seconds" }),
2317
+ /* @__PURE__ */ jsxRuntime.jsx(
2318
+ "input",
2319
+ {
2320
+ type: "number",
2321
+ min: 0,
2322
+ max: 59,
2323
+ value: seconds || 0,
2324
+ onChange: (e) => setProp((props) => props.seconds = parseInt(e.target.value)),
2325
+ className: "w-full px-3 py-2 border rounded-md text-sm"
2326
+ }
2327
+ )
2328
+ ] })
2329
+ ] }),
2330
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2331
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
2332
+ /* @__PURE__ */ jsxRuntime.jsx(
2333
+ "input",
2334
+ {
2335
+ type: "color",
2336
+ value: backgroundColor || "#ff6b6b",
2337
+ onChange: (e) => setProp((props) => props.backgroundColor = e.target.value),
2338
+ className: "w-full h-10 rounded border cursor-pointer"
2339
+ }
2340
+ )
2341
+ ] }),
2342
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2343
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Title Color" }),
2344
+ /* @__PURE__ */ jsxRuntime.jsx(
2345
+ "input",
2346
+ {
2347
+ type: "color",
2348
+ value: titleColor || "#ffffff",
2349
+ onChange: (e) => setProp((props) => props.titleColor = e.target.value),
2350
+ className: "w-full h-10 rounded border cursor-pointer"
2351
+ }
2352
+ )
2353
+ ] }),
2354
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2355
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Number Color" }),
2356
+ /* @__PURE__ */ jsxRuntime.jsx(
2357
+ "input",
2358
+ {
2359
+ type: "color",
2360
+ value: numberColor || "#ffffff",
2361
+ onChange: (e) => setProp((props) => props.numberColor = e.target.value),
2362
+ className: "w-full h-10 rounded border cursor-pointer"
2363
+ }
2364
+ )
2365
+ ] }),
2366
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2367
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
2368
+ /* @__PURE__ */ jsxRuntime.jsx(
2369
+ "input",
2370
+ {
2371
+ type: "range",
2372
+ min: 8,
2373
+ max: 48,
2374
+ value: padding || 24,
2375
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
2376
+ className: "w-full"
2377
+ }
2378
+ ),
2379
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
2380
+ padding,
2381
+ "px"
2382
+ ] })
2383
+ ] })
2384
+ ] });
2385
+ };
2386
+ Countdown.craft = {
2387
+ props: {
2388
+ title: "Sale Ends In",
2389
+ days: 3,
2390
+ hours: 12,
2391
+ minutes: 45,
2392
+ seconds: 30,
2393
+ backgroundColor: "#ff6b6b",
2394
+ numberColor: "#ffffff",
2395
+ labelColor: "#ffffff",
2396
+ titleColor: "#ffffff",
2397
+ boxBackground: "rgba(0,0,0,0.2)",
2398
+ padding: 24
2399
+ },
2400
+ related: {
2401
+ settings: CountdownSettings
2402
+ }
2403
+ };
2404
+ var PromoCode = ({
2405
+ title = "\u{1F389} Special Offer!",
2406
+ code = "SAVE20",
2407
+ description = "Use this code at checkout to get 20% off your order",
2408
+ backgroundColor = "#fff8e1",
2409
+ borderColor = "#ffc107",
2410
+ codeBackground = "#ffffff",
2411
+ textColor = "#333333",
2412
+ codeColor = "#e65100",
2413
+ padding = 24,
2414
+ borderStyle = "dashed"
2415
+ }) => {
2416
+ const { connectors: { connect, drag } } = core.useNode();
2417
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2418
+ "div",
2419
+ {
2420
+ ref: (ref) => connect(drag(ref)),
2421
+ style: {
2422
+ backgroundColor,
2423
+ border: `2px ${borderStyle} ${borderColor}`,
2424
+ borderRadius: "8px",
2425
+ padding: `${padding}px`,
2426
+ textAlign: "center",
2427
+ margin: "10px"
2428
+ },
2429
+ children: [
2430
+ title && /* @__PURE__ */ jsxRuntime.jsx(
2431
+ "div",
2432
+ {
2433
+ style: {
2434
+ fontSize: "18px",
2435
+ fontWeight: "bold",
2436
+ color: textColor,
2437
+ marginBottom: "12px",
2438
+ fontFamily: "Arial, sans-serif"
2439
+ },
2440
+ children: title
2441
+ }
2442
+ ),
2443
+ /* @__PURE__ */ jsxRuntime.jsx(
2444
+ "div",
2445
+ {
2446
+ style: {
2447
+ display: "inline-block",
2448
+ backgroundColor: codeBackground,
2449
+ border: `1px solid ${borderColor}`,
2450
+ borderRadius: "6px",
2451
+ padding: "12px 24px",
2452
+ marginBottom: "12px"
2453
+ },
2454
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2455
+ "span",
2456
+ {
2457
+ style: {
2458
+ fontSize: "24px",
2459
+ fontWeight: "bold",
2460
+ fontFamily: "monospace",
2461
+ letterSpacing: "3px",
2462
+ color: codeColor
2463
+ },
2464
+ children: code
2465
+ }
2466
+ )
2467
+ }
2468
+ ),
2469
+ description && /* @__PURE__ */ jsxRuntime.jsx(
2470
+ "div",
2471
+ {
2472
+ style: {
2473
+ fontSize: "14px",
2474
+ color: textColor,
2475
+ fontFamily: "Arial, sans-serif",
2476
+ opacity: 0.8
2477
+ },
2478
+ children: description
2479
+ }
2480
+ )
2481
+ ]
2482
+ }
2483
+ );
2484
+ };
2485
+ var PromoCodeSettings = () => {
2486
+ const {
2487
+ actions: { setProp },
2488
+ title,
2489
+ code,
2490
+ description,
2491
+ backgroundColor,
2492
+ borderColor,
2493
+ codeBackground,
2494
+ textColor,
2495
+ codeColor,
2496
+ padding,
2497
+ borderStyle
2498
+ } = core.useNode((node) => ({
2499
+ title: node.data.props.title,
2500
+ code: node.data.props.code,
2501
+ description: node.data.props.description,
2502
+ backgroundColor: node.data.props.backgroundColor,
2503
+ borderColor: node.data.props.borderColor,
2504
+ codeBackground: node.data.props.codeBackground,
2505
+ textColor: node.data.props.textColor,
2506
+ codeColor: node.data.props.codeColor,
2507
+ padding: node.data.props.padding,
2508
+ borderStyle: node.data.props.borderStyle
2509
+ }));
2510
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
2511
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2512
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Title" }),
2513
+ /* @__PURE__ */ jsxRuntime.jsx(
2514
+ "input",
2515
+ {
2516
+ type: "text",
2517
+ value: title || "",
2518
+ onChange: (e) => setProp((props) => props.title = e.target.value),
2519
+ className: "w-full px-3 py-2 border rounded-md text-sm"
2520
+ }
2521
+ )
2522
+ ] }),
2523
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2524
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Promo Code" }),
2525
+ /* @__PURE__ */ jsxRuntime.jsx(
2526
+ "input",
2527
+ {
2528
+ type: "text",
2529
+ value: code || "",
2530
+ onChange: (e) => setProp((props) => props.code = e.target.value.toUpperCase()),
2531
+ className: "w-full px-3 py-2 border rounded-md text-sm font-mono"
2532
+ }
2533
+ )
2534
+ ] }),
2535
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2536
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Description" }),
2537
+ /* @__PURE__ */ jsxRuntime.jsx(
2538
+ "textarea",
2539
+ {
2540
+ value: description || "",
2541
+ onChange: (e) => setProp((props) => props.description = e.target.value),
2542
+ className: "w-full px-3 py-2 border rounded-md text-sm min-h-[60px]"
2543
+ }
2544
+ )
2545
+ ] }),
2546
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2547
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Border Style" }),
2548
+ /* @__PURE__ */ jsxRuntime.jsxs(
2549
+ "select",
2550
+ {
2551
+ value: borderStyle || "dashed",
2552
+ onChange: (e) => setProp((props) => props.borderStyle = e.target.value),
2553
+ className: "w-full px-3 py-2 border rounded-md text-sm",
2554
+ children: [
2555
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "solid", children: "Solid" }),
2556
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "dashed", children: "Dashed" }),
2557
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "dotted", children: "Dotted" })
2558
+ ]
2559
+ }
2560
+ )
2561
+ ] }),
2562
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2563
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
2564
+ /* @__PURE__ */ jsxRuntime.jsx(
2565
+ "input",
2566
+ {
2567
+ type: "color",
2568
+ value: backgroundColor || "#fff8e1",
2569
+ onChange: (e) => setProp((props) => props.backgroundColor = e.target.value),
2570
+ className: "w-full h-10 rounded border cursor-pointer"
2571
+ }
2572
+ )
2573
+ ] }),
2574
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2575
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Border Color" }),
2576
+ /* @__PURE__ */ jsxRuntime.jsx(
2577
+ "input",
2578
+ {
2579
+ type: "color",
2580
+ value: borderColor || "#ffc107",
2581
+ onChange: (e) => setProp((props) => props.borderColor = e.target.value),
2582
+ className: "w-full h-10 rounded border cursor-pointer"
2583
+ }
2584
+ )
2585
+ ] }),
2586
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2587
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Code Color" }),
2588
+ /* @__PURE__ */ jsxRuntime.jsx(
2589
+ "input",
2590
+ {
2591
+ type: "color",
2592
+ value: codeColor || "#e65100",
2593
+ onChange: (e) => setProp((props) => props.codeColor = e.target.value),
2594
+ className: "w-full h-10 rounded border cursor-pointer"
2595
+ }
2596
+ )
2597
+ ] }),
2598
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2599
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
2600
+ /* @__PURE__ */ jsxRuntime.jsx(
2601
+ "input",
2602
+ {
2603
+ type: "range",
2604
+ min: 12,
2605
+ max: 48,
2606
+ value: padding || 24,
2607
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
2608
+ className: "w-full"
2609
+ }
2610
+ ),
2611
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
2612
+ padding,
2613
+ "px"
2614
+ ] })
2615
+ ] })
2616
+ ] });
2617
+ };
2618
+ PromoCode.craft = {
2619
+ props: {
2620
+ title: "\u{1F389} Special Offer!",
2621
+ code: "SAVE20",
2622
+ description: "Use this code at checkout to get 20% off your order",
2623
+ backgroundColor: "#fff8e1",
2624
+ borderColor: "#ffc107",
2625
+ codeBackground: "#ffffff",
2626
+ textColor: "#333333",
2627
+ codeColor: "#e65100",
2628
+ padding: 24,
2629
+ borderStyle: "dashed"
2630
+ },
2631
+ related: {
2632
+ settings: PromoCodeSettings
2633
+ }
2634
+ };
2635
+ var Testimonial = ({
2636
+ quote = "This product has completely transformed how we do business. The results have been incredible!",
2637
+ authorName = "Sarah Johnson",
2638
+ authorTitle = "CEO, TechCorp",
2639
+ authorImage = "",
2640
+ backgroundColor = "#f8f9fa",
2641
+ quoteColor = "#333333",
2642
+ authorColor = "#666666",
2643
+ accentColor = "#0066cc",
2644
+ padding = 24,
2645
+ showQuoteIcon = true
2646
+ }) => {
2647
+ const { connectors: { connect, drag } } = core.useNode();
2648
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2649
+ "div",
2650
+ {
2651
+ ref: (ref) => connect(drag(ref)),
2652
+ style: {
2653
+ backgroundColor,
2654
+ padding: `${padding}px`,
2655
+ borderLeft: `4px solid ${accentColor}`,
2656
+ margin: "10px"
2657
+ },
2658
+ children: [
2659
+ showQuoteIcon && /* @__PURE__ */ jsxRuntime.jsx(
2660
+ "div",
2661
+ {
2662
+ style: {
2663
+ fontSize: "48px",
2664
+ color: accentColor,
2665
+ opacity: 0.3,
2666
+ lineHeight: 1,
2667
+ marginBottom: "-20px",
2668
+ fontFamily: "Georgia, serif"
2669
+ },
2670
+ children: '"'
2671
+ }
2672
+ ),
2673
+ /* @__PURE__ */ jsxRuntime.jsx(
2674
+ "p",
2675
+ {
2676
+ style: {
2677
+ fontSize: "16px",
2678
+ fontStyle: "italic",
2679
+ color: quoteColor,
2680
+ lineHeight: 1.7,
2681
+ margin: "0 0 16px 0",
2682
+ fontFamily: "Georgia, serif"
2683
+ },
2684
+ children: quote
2685
+ }
2686
+ ),
2687
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [
2688
+ authorImage && /* @__PURE__ */ jsxRuntime.jsx(
2689
+ "img",
2690
+ {
2691
+ src: authorImage,
2692
+ alt: authorName,
2693
+ style: {
2694
+ width: "48px",
2695
+ height: "48px",
2696
+ borderRadius: "50%",
2697
+ objectFit: "cover"
2698
+ }
2699
+ }
2700
+ ),
2701
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2702
+ /* @__PURE__ */ jsxRuntime.jsx(
2703
+ "div",
2704
+ {
2705
+ style: {
2706
+ fontSize: "14px",
2707
+ fontWeight: "bold",
2708
+ color: quoteColor,
2709
+ fontFamily: "Arial, sans-serif"
2710
+ },
2711
+ children: authorName
2712
+ }
2713
+ ),
2714
+ authorTitle && /* @__PURE__ */ jsxRuntime.jsx(
2715
+ "div",
2716
+ {
2717
+ style: {
2718
+ fontSize: "12px",
2719
+ color: authorColor,
2720
+ fontFamily: "Arial, sans-serif"
2721
+ },
2722
+ children: authorTitle
2723
+ }
2724
+ )
2725
+ ] })
2726
+ ] })
2727
+ ]
2728
+ }
2729
+ );
2730
+ };
2731
+ var TestimonialSettings = () => {
2732
+ const {
2733
+ actions: { setProp },
2734
+ quote,
2735
+ authorName,
2736
+ authorTitle,
2737
+ authorImage,
2738
+ backgroundColor,
2739
+ quoteColor,
2740
+ authorColor,
2741
+ accentColor,
2742
+ padding,
2743
+ showQuoteIcon
2744
+ } = core.useNode((node) => ({
2745
+ quote: node.data.props.quote,
2746
+ authorName: node.data.props.authorName,
2747
+ authorTitle: node.data.props.authorTitle,
2748
+ authorImage: node.data.props.authorImage,
2749
+ backgroundColor: node.data.props.backgroundColor,
2750
+ quoteColor: node.data.props.quoteColor,
2751
+ authorColor: node.data.props.authorColor,
2752
+ accentColor: node.data.props.accentColor,
2753
+ padding: node.data.props.padding,
2754
+ showQuoteIcon: node.data.props.showQuoteIcon
2755
+ }));
2756
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
2757
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2758
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Quote" }),
2759
+ /* @__PURE__ */ jsxRuntime.jsx(
2760
+ "textarea",
2761
+ {
2762
+ value: quote || "",
2763
+ onChange: (e) => setProp((props) => props.quote = e.target.value),
2764
+ className: "w-full px-3 py-2 border rounded-md text-sm min-h-[80px]"
2765
+ }
2766
+ )
2767
+ ] }),
2768
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2769
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Author Name" }),
2770
+ /* @__PURE__ */ jsxRuntime.jsx(
2771
+ "input",
2772
+ {
2773
+ type: "text",
2774
+ value: authorName || "",
2775
+ onChange: (e) => setProp((props) => props.authorName = e.target.value),
2776
+ className: "w-full px-3 py-2 border rounded-md text-sm"
2777
+ }
2778
+ )
2779
+ ] }),
2780
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2781
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Author Title" }),
2782
+ /* @__PURE__ */ jsxRuntime.jsx(
2783
+ "input",
2784
+ {
2785
+ type: "text",
2786
+ value: authorTitle || "",
2787
+ onChange: (e) => setProp((props) => props.authorTitle = e.target.value),
2788
+ className: "w-full px-3 py-2 border rounded-md text-sm"
2789
+ }
2790
+ )
2791
+ ] }),
2792
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2793
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Author Image URL" }),
2794
+ /* @__PURE__ */ jsxRuntime.jsx(
2795
+ "input",
2796
+ {
2797
+ type: "text",
2798
+ value: authorImage || "",
2799
+ onChange: (e) => setProp((props) => props.authorImage = e.target.value),
2800
+ className: "w-full px-3 py-2 border rounded-md text-sm",
2801
+ placeholder: "https://..."
2802
+ }
2803
+ )
2804
+ ] }),
2805
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer", children: [
2806
+ /* @__PURE__ */ jsxRuntime.jsx(
2807
+ "input",
2808
+ {
2809
+ type: "checkbox",
2810
+ checked: showQuoteIcon !== false,
2811
+ onChange: (e) => setProp((props) => props.showQuoteIcon = e.target.checked),
2812
+ className: "rounded"
2813
+ }
2814
+ ),
2815
+ "Show Quote Icon"
2816
+ ] }) }),
2817
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2818
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Background Color" }),
2819
+ /* @__PURE__ */ jsxRuntime.jsx(
2820
+ "input",
2821
+ {
2822
+ type: "color",
2823
+ value: backgroundColor || "#f8f9fa",
2824
+ onChange: (e) => setProp((props) => props.backgroundColor = e.target.value),
2825
+ className: "w-full h-10 rounded border cursor-pointer"
2826
+ }
2827
+ )
2828
+ ] }),
2829
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2830
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Accent Color" }),
2831
+ /* @__PURE__ */ jsxRuntime.jsx(
2832
+ "input",
2833
+ {
2834
+ type: "color",
2835
+ value: accentColor || "#0066cc",
2836
+ onChange: (e) => setProp((props) => props.accentColor = e.target.value),
2837
+ className: "w-full h-10 rounded border cursor-pointer"
2838
+ }
2839
+ )
2840
+ ] }),
2841
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2842
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Quote Color" }),
2843
+ /* @__PURE__ */ jsxRuntime.jsx(
2844
+ "input",
2845
+ {
2846
+ type: "color",
2847
+ value: quoteColor || "#333333",
2848
+ onChange: (e) => setProp((props) => props.quoteColor = e.target.value),
2849
+ className: "w-full h-10 rounded border cursor-pointer"
2850
+ }
2851
+ )
2852
+ ] }),
2853
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2854
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
2855
+ /* @__PURE__ */ jsxRuntime.jsx(
2856
+ "input",
2857
+ {
2858
+ type: "range",
2859
+ min: 12,
2860
+ max: 48,
2861
+ value: padding || 24,
2862
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
2863
+ className: "w-full"
2864
+ }
2865
+ ),
2866
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
2867
+ padding,
2868
+ "px"
2869
+ ] })
2870
+ ] })
2871
+ ] });
2872
+ };
2873
+ Testimonial.craft = {
2874
+ props: {
2875
+ quote: "This product has completely transformed how we do business. The results have been incredible!",
2876
+ authorName: "Sarah Johnson",
2877
+ authorTitle: "CEO, TechCorp",
2878
+ authorImage: "",
2879
+ backgroundColor: "#f8f9fa",
2880
+ quoteColor: "#333333",
2881
+ authorColor: "#666666",
2882
+ accentColor: "#0066cc",
2883
+ padding: 24,
2884
+ showQuoteIcon: true
2885
+ },
2886
+ related: {
2887
+ settings: TestimonialSettings
2888
+ }
2889
+ };
2890
+ var VideoPlaceholder = ({
2891
+ thumbnailUrl = "https://images.unsplash.com/photo-1611162617474-5b21e879e113?w=600&h=338&fit=crop",
2892
+ videoUrl = "#",
2893
+ width = "100%",
2894
+ align = "center",
2895
+ padding = 10,
2896
+ borderRadius = 8,
2897
+ playButtonColor = "#ffffff",
2898
+ overlayOpacity = 0.3
2899
+ }) => {
2900
+ const { connectors: { connect, drag } } = core.useNode();
2901
+ return /* @__PURE__ */ jsxRuntime.jsx(
2902
+ "div",
2903
+ {
2904
+ ref: (ref) => connect(drag(ref)),
2905
+ style: {
2906
+ textAlign: align,
2907
+ padding: `${padding}px`
2908
+ },
2909
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2910
+ "a",
2911
+ {
2912
+ href: videoUrl,
2913
+ style: {
2914
+ display: "inline-block",
2915
+ position: "relative",
2916
+ width,
2917
+ maxWidth: "100%"
2918
+ },
2919
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
2920
+ "div",
2921
+ {
2922
+ style: {
2923
+ position: "relative",
2924
+ borderRadius: `${borderRadius}px`,
2925
+ overflow: "hidden"
2926
+ },
2927
+ children: [
2928
+ /* @__PURE__ */ jsxRuntime.jsx(
2929
+ "img",
2930
+ {
2931
+ src: thumbnailUrl,
2932
+ alt: "Video thumbnail",
2933
+ style: {
2934
+ width: "100%",
2935
+ display: "block"
2936
+ }
2937
+ }
2938
+ ),
2939
+ /* @__PURE__ */ jsxRuntime.jsx(
2940
+ "div",
2941
+ {
2942
+ style: {
2943
+ position: "absolute",
2944
+ top: 0,
2945
+ left: 0,
2946
+ right: 0,
2947
+ bottom: 0,
2948
+ backgroundColor: `rgba(0,0,0,${overlayOpacity})`,
2949
+ display: "flex",
2950
+ alignItems: "center",
2951
+ justifyContent: "center"
2952
+ },
2953
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2954
+ "div",
2955
+ {
2956
+ style: {
2957
+ width: "64px",
2958
+ height: "64px",
2959
+ backgroundColor: "rgba(0,0,0,0.6)",
2960
+ borderRadius: "50%",
2961
+ display: "flex",
2962
+ alignItems: "center",
2963
+ justifyContent: "center",
2964
+ border: `3px solid ${playButtonColor}`
2965
+ },
2966
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2967
+ "div",
2968
+ {
2969
+ style: {
2970
+ width: 0,
2971
+ height: 0,
2972
+ borderTop: "12px solid transparent",
2973
+ borderBottom: "12px solid transparent",
2974
+ borderLeft: `20px solid ${playButtonColor}`,
2975
+ marginLeft: "4px"
2976
+ }
2977
+ }
2978
+ )
2979
+ }
2980
+ )
2981
+ }
2982
+ )
2983
+ ]
2984
+ }
2985
+ )
2986
+ }
2987
+ )
2988
+ }
2989
+ );
2990
+ };
2991
+ var VideoPlaceholderSettings = () => {
2992
+ const {
2993
+ actions: { setProp },
2994
+ thumbnailUrl,
2995
+ videoUrl,
2996
+ width,
2997
+ align,
2998
+ padding,
2999
+ borderRadius,
3000
+ playButtonColor,
3001
+ overlayOpacity
3002
+ } = core.useNode((node) => ({
3003
+ thumbnailUrl: node.data.props.thumbnailUrl,
3004
+ videoUrl: node.data.props.videoUrl,
3005
+ width: node.data.props.width,
3006
+ align: node.data.props.align,
3007
+ padding: node.data.props.padding,
3008
+ borderRadius: node.data.props.borderRadius,
3009
+ playButtonColor: node.data.props.playButtonColor,
3010
+ overlayOpacity: node.data.props.overlayOpacity
3011
+ }));
3012
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
3013
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3014
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Thumbnail URL" }),
3015
+ /* @__PURE__ */ jsxRuntime.jsx(
3016
+ "input",
3017
+ {
3018
+ type: "text",
3019
+ value: thumbnailUrl || "",
3020
+ onChange: (e) => setProp((props) => props.thumbnailUrl = e.target.value),
3021
+ className: "w-full px-3 py-2 border rounded-md text-sm",
3022
+ placeholder: "https://..."
3023
+ }
3024
+ )
3025
+ ] }),
3026
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3027
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Video URL" }),
3028
+ /* @__PURE__ */ jsxRuntime.jsx(
3029
+ "input",
3030
+ {
3031
+ type: "text",
3032
+ value: videoUrl || "",
3033
+ onChange: (e) => setProp((props) => props.videoUrl = e.target.value),
3034
+ className: "w-full px-3 py-2 border rounded-md text-sm",
3035
+ placeholder: "https://youtube.com/watch?v=..."
3036
+ }
3037
+ )
3038
+ ] }),
3039
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3040
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Width" }),
3041
+ /* @__PURE__ */ jsxRuntime.jsx(
3042
+ "input",
3043
+ {
3044
+ type: "text",
3045
+ value: width || "100%",
3046
+ onChange: (e) => setProp((props) => props.width = e.target.value),
3047
+ className: "w-full px-3 py-2 border rounded-md text-sm",
3048
+ placeholder: "100% or 400px"
3049
+ }
3050
+ )
3051
+ ] }),
3052
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3053
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Alignment" }),
3054
+ /* @__PURE__ */ jsxRuntime.jsxs(
3055
+ "select",
3056
+ {
3057
+ value: align || "center",
3058
+ onChange: (e) => setProp((props) => props.align = e.target.value),
3059
+ className: "w-full px-3 py-2 border rounded-md text-sm",
3060
+ children: [
3061
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "left", children: "Left" }),
3062
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "center", children: "Center" }),
3063
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "right", children: "Right" })
3064
+ ]
3065
+ }
3066
+ )
3067
+ ] }),
3068
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3069
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Play Button Color" }),
3070
+ /* @__PURE__ */ jsxRuntime.jsx(
3071
+ "input",
3072
+ {
3073
+ type: "color",
3074
+ value: playButtonColor || "#ffffff",
3075
+ onChange: (e) => setProp((props) => props.playButtonColor = e.target.value),
3076
+ className: "w-full h-10 rounded border cursor-pointer"
3077
+ }
3078
+ )
3079
+ ] }),
3080
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3081
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Overlay Opacity" }),
3082
+ /* @__PURE__ */ jsxRuntime.jsx(
3083
+ "input",
3084
+ {
3085
+ type: "range",
3086
+ min: 0,
3087
+ max: 0.8,
3088
+ step: 0.1,
3089
+ value: overlayOpacity || 0.3,
3090
+ onChange: (e) => setProp((props) => props.overlayOpacity = parseFloat(e.target.value)),
3091
+ className: "w-full"
3092
+ }
3093
+ ),
3094
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: (overlayOpacity || 0.3).toFixed(1) })
3095
+ ] }),
3096
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3097
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Border Radius" }),
3098
+ /* @__PURE__ */ jsxRuntime.jsx(
3099
+ "input",
3100
+ {
3101
+ type: "range",
3102
+ min: 0,
3103
+ max: 24,
3104
+ value: borderRadius || 8,
3105
+ onChange: (e) => setProp((props) => props.borderRadius = parseInt(e.target.value)),
3106
+ className: "w-full"
3107
+ }
3108
+ ),
3109
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
3110
+ borderRadius,
3111
+ "px"
3112
+ ] })
3113
+ ] }),
3114
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3115
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
3116
+ /* @__PURE__ */ jsxRuntime.jsx(
3117
+ "input",
3118
+ {
3119
+ type: "range",
3120
+ min: 0,
3121
+ max: 40,
3122
+ value: padding || 10,
3123
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
3124
+ className: "w-full"
3125
+ }
3126
+ ),
3127
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
3128
+ padding,
3129
+ "px"
3130
+ ] })
3131
+ ] })
3132
+ ] });
3133
+ };
3134
+ VideoPlaceholder.craft = {
3135
+ props: {
3136
+ thumbnailUrl: "https://images.unsplash.com/photo-1611162617474-5b21e879e113?w=600&h=338&fit=crop",
3137
+ videoUrl: "#",
3138
+ width: "100%",
3139
+ align: "center",
3140
+ padding: 10,
3141
+ borderRadius: 8,
3142
+ playButtonColor: "#ffffff",
3143
+ overlayOpacity: 0.3
3144
+ },
3145
+ related: {
3146
+ settings: VideoPlaceholderSettings
3147
+ }
3148
+ };
3149
+ var AVAILABLE_VARIABLES = [
3150
+ { key: "{{first_name}}", label: "First Name", preview: "John" },
3151
+ { key: "{{last_name}}", label: "Last Name", preview: "Doe" },
3152
+ { key: "{{full_name}}", label: "Full Name", preview: "John Doe" },
3153
+ { key: "{{email}}", label: "Email", preview: "john@example.com" },
3154
+ { key: "{{company}}", label: "Company", preview: "Acme Inc" },
3155
+ { key: "{{invoice_number}}", label: "Invoice #", preview: "INV-001" },
3156
+ { key: "{{invoice_date}}", label: "Invoice Date", preview: "2024-01-15" },
3157
+ { key: "{{due_date}}", label: "Due Date", preview: "2024-01-30" },
3158
+ { key: "{{total_amount}}", label: "Total Amount", preview: "$1,500.00" },
3159
+ { key: "{{order_number}}", label: "Order #", preview: "ORD-12345" }
3160
+ ];
3161
+ var renderWithVariables = (text) => {
3162
+ let rendered = text;
3163
+ AVAILABLE_VARIABLES.forEach(({ key, preview }) => {
3164
+ rendered = rendered.replace(
3165
+ new RegExp(key.replace(/[{}]/g, "\\$&"), "g"),
3166
+ `<span style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.9em;">${preview}</span>`
3167
+ );
3168
+ });
3169
+ return rendered;
3170
+ };
3171
+ var VariableText = ({
3172
+ text = "Hello {{first_name}}, thank you for your order {{order_number}}!",
3173
+ fontSize = 14,
3174
+ fontWeight = "normal",
3175
+ color = "#333333",
3176
+ align = "left",
3177
+ padding = 10,
3178
+ lineHeight = 1.6
3179
+ }) => {
3180
+ const { connectors: { connect, drag } } = core.useNode();
3181
+ return /* @__PURE__ */ jsxRuntime.jsx(
3182
+ "div",
3183
+ {
3184
+ ref: (ref) => connect(drag(ref)),
3185
+ style: {
3186
+ padding: `${padding}px`
3187
+ },
3188
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3189
+ "p",
3190
+ {
3191
+ style: {
3192
+ fontSize: `${fontSize}px`,
3193
+ fontWeight,
3194
+ color,
3195
+ textAlign: align,
3196
+ lineHeight,
3197
+ margin: 0,
3198
+ fontFamily: "Arial, sans-serif"
3199
+ },
3200
+ dangerouslySetInnerHTML: { __html: renderWithVariables(text) }
3201
+ }
3202
+ )
3203
+ }
3204
+ );
3205
+ };
3206
+ var VariableTextSettings = () => {
3207
+ const { actions: { setProp }, text, fontSize, fontWeight, color, align, padding, lineHeight } = core.useNode((node) => ({
3208
+ text: node.data.props.text,
3209
+ fontSize: node.data.props.fontSize,
3210
+ fontWeight: node.data.props.fontWeight,
3211
+ color: node.data.props.color,
3212
+ align: node.data.props.align,
3213
+ padding: node.data.props.padding,
3214
+ lineHeight: node.data.props.lineHeight
3215
+ }));
3216
+ const insertVariable = (variable) => {
3217
+ setProp((props) => {
3218
+ props.text = (props.text || "") + variable;
3219
+ });
3220
+ };
3221
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
3222
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3223
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Text Content" }),
3224
+ /* @__PURE__ */ jsxRuntime.jsx(
3225
+ "textarea",
3226
+ {
3227
+ value: text || "",
3228
+ onChange: (e) => setProp((props) => props.text = e.target.value),
3229
+ className: "w-full px-3 py-2 border rounded-md text-sm min-h-[80px] font-mono"
3230
+ }
3231
+ )
3232
+ ] }),
3233
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3234
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-2", children: "Insert Variable" }),
3235
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: AVAILABLE_VARIABLES.map((v) => /* @__PURE__ */ jsxRuntime.jsx(
3236
+ "button",
3237
+ {
3238
+ onClick: () => insertVariable(v.key),
3239
+ className: "px-2 py-1 text-xs bg-primary/10 hover:bg-primary/20 text-primary rounded border border-primary/20 transition-colors",
3240
+ children: v.label
3241
+ },
3242
+ v.key
3243
+ )) })
3244
+ ] }),
3245
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3246
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Font Size" }),
3247
+ /* @__PURE__ */ jsxRuntime.jsx(
3248
+ "input",
3249
+ {
3250
+ type: "range",
3251
+ min: 10,
3252
+ max: 32,
3253
+ value: fontSize || 14,
3254
+ onChange: (e) => setProp((props) => props.fontSize = parseInt(e.target.value)),
3255
+ className: "w-full"
3256
+ }
3257
+ ),
3258
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
3259
+ fontSize,
3260
+ "px"
3261
+ ] })
3262
+ ] }),
3263
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3264
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Font Weight" }),
3265
+ /* @__PURE__ */ jsxRuntime.jsxs(
3266
+ "select",
3267
+ {
3268
+ value: fontWeight || "normal",
3269
+ onChange: (e) => setProp((props) => props.fontWeight = e.target.value),
3270
+ className: "w-full px-3 py-2 border rounded-md text-sm",
3271
+ children: [
3272
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "normal", children: "Normal" }),
3273
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "bold", children: "Bold" })
3274
+ ]
3275
+ }
3276
+ )
3277
+ ] }),
3278
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3279
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Text Color" }),
3280
+ /* @__PURE__ */ jsxRuntime.jsx(
3281
+ "input",
3282
+ {
3283
+ type: "color",
3284
+ value: color || "#333333",
3285
+ onChange: (e) => setProp((props) => props.color = e.target.value),
3286
+ className: "w-full h-10 rounded border cursor-pointer"
3287
+ }
3288
+ )
3289
+ ] }),
3290
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3291
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Alignment" }),
3292
+ /* @__PURE__ */ jsxRuntime.jsxs(
3293
+ "select",
3294
+ {
3295
+ value: align || "left",
3296
+ onChange: (e) => setProp((props) => props.align = e.target.value),
3297
+ className: "w-full px-3 py-2 border rounded-md text-sm",
3298
+ children: [
3299
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "left", children: "Left" }),
3300
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "center", children: "Center" }),
3301
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "right", children: "Right" })
3302
+ ]
3303
+ }
3304
+ )
3305
+ ] }),
3306
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3307
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
3308
+ /* @__PURE__ */ jsxRuntime.jsx(
3309
+ "input",
3310
+ {
3311
+ type: "range",
3312
+ min: 0,
3313
+ max: 40,
3314
+ value: padding || 10,
3315
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
3316
+ className: "w-full"
3317
+ }
3318
+ ),
3319
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
3320
+ padding,
3321
+ "px"
3322
+ ] })
3323
+ ] }),
3324
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3325
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Line Height" }),
3326
+ /* @__PURE__ */ jsxRuntime.jsx(
3327
+ "input",
3328
+ {
3329
+ type: "range",
3330
+ min: 1,
3331
+ max: 2.5,
3332
+ step: 0.1,
3333
+ value: lineHeight || 1.6,
3334
+ onChange: (e) => setProp((props) => props.lineHeight = parseFloat(e.target.value)),
3335
+ className: "w-full"
3336
+ }
3337
+ ),
3338
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: lineHeight })
3339
+ ] })
3340
+ ] });
3341
+ };
3342
+ VariableText.craft = {
3343
+ props: {
3344
+ text: "Hello {{first_name}}, thank you for your order {{order_number}}!",
3345
+ fontSize: 14,
3346
+ fontWeight: "normal",
3347
+ color: "#333333",
3348
+ align: "left",
3349
+ padding: 10,
3350
+ lineHeight: 1.6
3351
+ },
3352
+ related: {
3353
+ settings: VariableTextSettings
3354
+ }
3355
+ };
3356
+ var ICONS = {
3357
+ check: "\u2713",
3358
+ star: "\u2605",
3359
+ arrow: "\u2192",
3360
+ bullet: "\u2022",
3361
+ heart: "\u2764",
3362
+ fire: "\u{1F525}",
3363
+ rocket: "\u{1F680}",
3364
+ sparkle: "\u2728",
3365
+ gift: "\u{1F381}",
3366
+ clock: "\u23F0"
3367
+ };
3368
+ var IconList = ({
3369
+ items = [
3370
+ { icon: "check", text: "Fast and reliable delivery" },
3371
+ { icon: "check", text: "Premium quality products" },
3372
+ { icon: "check", text: "24/7 customer support" },
3373
+ { icon: "check", text: "30-day money back guarantee" }
3374
+ ],
3375
+ iconColor = "#22c55e",
3376
+ textColor = "#333333",
3377
+ backgroundColor = "transparent",
3378
+ fontSize = 14,
3379
+ iconSize = 18,
3380
+ gap = 12,
3381
+ padding = 16
3382
+ }) => {
3383
+ const { connectors: { connect, drag } } = core.useNode();
3384
+ return /* @__PURE__ */ jsxRuntime.jsx(
3385
+ "div",
3386
+ {
3387
+ ref: (ref) => connect(drag(ref)),
3388
+ style: {
3389
+ padding: `${padding}px`,
3390
+ backgroundColor
3391
+ },
3392
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3393
+ "ul",
3394
+ {
3395
+ style: {
3396
+ listStyle: "none",
3397
+ margin: 0,
3398
+ padding: 0,
3399
+ display: "flex",
3400
+ flexDirection: "column",
3401
+ gap: `${gap}px`
3402
+ },
3403
+ children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
3404
+ "li",
3405
+ {
3406
+ style: {
3407
+ display: "flex",
3408
+ alignItems: "flex-start",
3409
+ gap: "10px",
3410
+ fontFamily: "Arial, sans-serif"
3411
+ },
3412
+ children: [
3413
+ /* @__PURE__ */ jsxRuntime.jsx(
3414
+ "span",
3415
+ {
3416
+ style: {
3417
+ color: iconColor,
3418
+ fontSize: `${iconSize}px`,
3419
+ lineHeight: 1.4,
3420
+ flexShrink: 0
3421
+ },
3422
+ children: ICONS[item.icon] || item.icon
3423
+ }
3424
+ ),
3425
+ /* @__PURE__ */ jsxRuntime.jsx(
3426
+ "span",
3427
+ {
3428
+ style: {
3429
+ color: textColor,
3430
+ fontSize: `${fontSize}px`,
3431
+ lineHeight: 1.5
3432
+ },
3433
+ children: item.text
3434
+ }
3435
+ )
3436
+ ]
3437
+ },
3438
+ index
3439
+ ))
3440
+ }
3441
+ )
3442
+ }
3443
+ );
3444
+ };
3445
+ var IconListSettings = () => {
3446
+ const {
3447
+ actions: { setProp },
3448
+ items,
3449
+ iconColor,
3450
+ textColor,
3451
+ backgroundColor,
3452
+ fontSize,
3453
+ iconSize,
3454
+ gap,
3455
+ padding
3456
+ } = core.useNode((node) => ({
3457
+ items: node.data.props.items,
3458
+ iconColor: node.data.props.iconColor,
3459
+ textColor: node.data.props.textColor,
3460
+ backgroundColor: node.data.props.backgroundColor,
3461
+ fontSize: node.data.props.fontSize,
3462
+ iconSize: node.data.props.iconSize,
3463
+ gap: node.data.props.gap,
3464
+ padding: node.data.props.padding
3465
+ }));
3466
+ const currentItems = items || [];
3467
+ const updateItem = (index, field, value) => {
3468
+ setProp((props) => {
3469
+ props.items = currentItems.map(
3470
+ (item, i) => i === index ? { ...item, [field]: value } : item
3471
+ );
3472
+ });
3473
+ };
3474
+ const addItem = () => {
3475
+ setProp((props) => {
3476
+ props.items = [...currentItems, { icon: "check", text: "New item" }];
3477
+ });
3478
+ };
3479
+ const removeItem = (index) => {
3480
+ setProp((props) => {
3481
+ props.items = currentItems.filter((_, i) => i !== index);
3482
+ });
3483
+ };
3484
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
3485
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3486
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-2", children: "List Items" }),
3487
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: currentItems.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-start", children: [
3488
+ /* @__PURE__ */ jsxRuntime.jsx(
3489
+ "select",
3490
+ {
3491
+ value: item.icon,
3492
+ onChange: (e) => updateItem(index, "icon", e.target.value),
3493
+ className: "w-16 px-2 py-2 border rounded-md text-sm",
3494
+ children: Object.entries(ICONS).map(([key, icon]) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: key, children: icon }, key))
3495
+ }
3496
+ ),
3497
+ /* @__PURE__ */ jsxRuntime.jsx(
3498
+ "input",
3499
+ {
3500
+ type: "text",
3501
+ value: item.text,
3502
+ onChange: (e) => updateItem(index, "text", e.target.value),
3503
+ className: "flex-1 px-3 py-2 border rounded-md text-sm"
3504
+ }
3505
+ ),
3506
+ /* @__PURE__ */ jsxRuntime.jsx(
3507
+ "button",
3508
+ {
3509
+ onClick: () => removeItem(index),
3510
+ className: "px-2 py-2 text-destructive hover:bg-destructive/10 rounded",
3511
+ children: "\xD7"
3512
+ }
3513
+ )
3514
+ ] }, index)) }),
3515
+ /* @__PURE__ */ jsxRuntime.jsx(
3516
+ "button",
3517
+ {
3518
+ onClick: addItem,
3519
+ className: "mt-2 w-full py-2 text-sm border border-dashed rounded-md hover:bg-accent transition-colors",
3520
+ children: "+ Add Item"
3521
+ }
3522
+ )
3523
+ ] }),
3524
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3525
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Icon Color" }),
3526
+ /* @__PURE__ */ jsxRuntime.jsx(
3527
+ "input",
3528
+ {
3529
+ type: "color",
3530
+ value: iconColor || "#22c55e",
3531
+ onChange: (e) => setProp((props) => props.iconColor = e.target.value),
3532
+ className: "w-full h-10 rounded border cursor-pointer"
3533
+ }
3534
+ )
3535
+ ] }),
3536
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3537
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Text Color" }),
3538
+ /* @__PURE__ */ jsxRuntime.jsx(
3539
+ "input",
3540
+ {
3541
+ type: "color",
3542
+ value: textColor || "#333333",
3543
+ onChange: (e) => setProp((props) => props.textColor = e.target.value),
3544
+ className: "w-full h-10 rounded border cursor-pointer"
3545
+ }
3546
+ )
3547
+ ] }),
3548
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3549
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Font Size" }),
3550
+ /* @__PURE__ */ jsxRuntime.jsx(
3551
+ "input",
3552
+ {
3553
+ type: "range",
3554
+ min: 12,
3555
+ max: 20,
3556
+ value: fontSize || 14,
3557
+ onChange: (e) => setProp((props) => props.fontSize = parseInt(e.target.value)),
3558
+ className: "w-full"
3559
+ }
3560
+ ),
3561
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
3562
+ fontSize,
3563
+ "px"
3564
+ ] })
3565
+ ] }),
3566
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3567
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Icon Size" }),
3568
+ /* @__PURE__ */ jsxRuntime.jsx(
3569
+ "input",
3570
+ {
3571
+ type: "range",
3572
+ min: 14,
3573
+ max: 28,
3574
+ value: iconSize || 18,
3575
+ onChange: (e) => setProp((props) => props.iconSize = parseInt(e.target.value)),
3576
+ className: "w-full"
3577
+ }
3578
+ ),
3579
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
3580
+ iconSize,
3581
+ "px"
3582
+ ] })
3583
+ ] }),
3584
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3585
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Gap" }),
3586
+ /* @__PURE__ */ jsxRuntime.jsx(
3587
+ "input",
3588
+ {
3589
+ type: "range",
3590
+ min: 4,
3591
+ max: 24,
3592
+ value: gap || 12,
3593
+ onChange: (e) => setProp((props) => props.gap = parseInt(e.target.value)),
3594
+ className: "w-full"
3595
+ }
3596
+ ),
3597
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
3598
+ gap,
3599
+ "px"
3600
+ ] })
3601
+ ] }),
3602
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3603
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium mb-1", children: "Padding" }),
3604
+ /* @__PURE__ */ jsxRuntime.jsx(
3605
+ "input",
3606
+ {
3607
+ type: "range",
3608
+ min: 0,
3609
+ max: 40,
3610
+ value: padding || 16,
3611
+ onChange: (e) => setProp((props) => props.padding = parseInt(e.target.value)),
3612
+ className: "w-full"
3613
+ }
3614
+ ),
3615
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
3616
+ padding,
3617
+ "px"
3618
+ ] })
3619
+ ] })
3620
+ ] });
3621
+ };
3622
+ IconList.craft = {
3623
+ props: {
3624
+ items: [
3625
+ { icon: "check", text: "Fast and reliable delivery" },
3626
+ { icon: "check", text: "Premium quality products" },
3627
+ { icon: "check", text: "24/7 customer support" },
3628
+ { icon: "check", text: "30-day money back guarantee" }
3629
+ ],
3630
+ iconColor: "#22c55e",
3631
+ textColor: "#333333",
3632
+ backgroundColor: "transparent",
3633
+ fontSize: 14,
3634
+ iconSize: 18,
3635
+ gap: 12,
3636
+ padding: 16
3637
+ },
3638
+ related: {
3639
+ settings: IconListSettings
3640
+ }
3641
+ };
3642
+ var DEFAULT_COMPONENTS = {
3643
+ EmailHeader: {
3644
+ component: EmailHeader,
3645
+ label: "Header",
3646
+ description: "Email header with logo",
3647
+ icon: lucideReact.PanelTop,
3648
+ category: "Layout"
3649
+ },
3650
+ EmailFooter: {
3651
+ component: EmailFooter,
3652
+ label: "Footer",
3653
+ description: "Contact info & copyright",
3654
+ icon: lucideReact.PanelBottom,
3655
+ category: "Layout"
3656
+ },
3657
+ Container: {
3658
+ component: Container,
3659
+ label: "Container",
3660
+ description: "Group elements together",
3661
+ icon: lucideReact.LayoutTemplate,
3662
+ category: "Layout",
3663
+ createElement: () => /* @__PURE__ */ jsxRuntime.jsx(core.Element, { is: Container, canvas: true })
3664
+ },
3665
+ TwoColumn: {
3666
+ component: TwoColumn,
3667
+ label: "Two Columns",
3668
+ description: "Side-by-side layout",
3669
+ icon: lucideReact.Columns,
3670
+ category: "Layout"
3671
+ },
3672
+ Spacer: {
3673
+ component: Spacer,
3674
+ label: "Spacer",
3675
+ description: "Add vertical space",
3676
+ icon: lucideReact.ArrowUpDown,
3677
+ category: "Layout"
3678
+ },
3679
+ Divider: {
3680
+ component: Divider,
3681
+ label: "Divider",
3682
+ description: "Horizontal line separator",
3683
+ icon: lucideReact.Minus,
3684
+ category: "Layout"
3685
+ },
3686
+ TextBlock: {
3687
+ component: TextBlock,
3688
+ label: "Text Block",
3689
+ description: "Paragraph or heading",
3690
+ icon: lucideReact.Type,
3691
+ category: "Content"
3692
+ },
3693
+ ImageBlock: {
3694
+ component: ImageBlock,
3695
+ label: "Image",
3696
+ description: "Add photos or graphics",
3697
+ icon: lucideReact.Image,
3698
+ category: "Content"
3699
+ },
3700
+ EmailButton: {
3701
+ component: EmailButton,
3702
+ label: "Button",
3703
+ description: "Call-to-action button",
3704
+ icon: lucideReact.MousePointer2,
3705
+ category: "Content"
3706
+ },
3707
+ VideoPlaceholder: {
3708
+ component: VideoPlaceholder,
3709
+ label: "Video",
3710
+ description: "Video thumbnail with play",
3711
+ icon: lucideReact.PlayCircle,
3712
+ category: "Content"
3713
+ },
3714
+ IconList: {
3715
+ component: IconList,
3716
+ label: "Icon List",
3717
+ description: "List with icons",
3718
+ icon: lucideReact.List,
3719
+ category: "Content"
3720
+ },
3721
+ SocialLinks: {
3722
+ component: SocialLinks,
3723
+ label: "Social Links",
3724
+ description: "Social media icons",
3725
+ icon: lucideReact.Share2,
3726
+ category: "Content"
3727
+ },
3728
+ Countdown: {
3729
+ component: Countdown,
3730
+ label: "Countdown",
3731
+ description: "Urgency timer display",
3732
+ icon: lucideReact.Timer,
3733
+ category: "Marketing"
3734
+ },
3735
+ PromoCode: {
3736
+ component: PromoCode,
3737
+ label: "Promo Code",
3738
+ description: "Discount code box",
3739
+ icon: lucideReact.Tag,
3740
+ category: "Marketing"
3741
+ },
3742
+ Testimonial: {
3743
+ component: Testimonial,
3744
+ label: "Testimonial",
3745
+ description: "Customer review quote",
3746
+ icon: lucideReact.Quote,
3747
+ category: "Marketing"
3748
+ },
3749
+ VariableText: {
3750
+ component: VariableText,
3751
+ label: "Variable Text",
3752
+ description: "Personalized content",
3753
+ icon: lucideReact.Variable,
3754
+ category: "Dynamic"
3755
+ },
3756
+ InvoiceTable: {
3757
+ component: InvoiceTable,
3758
+ label: "Invoice Table",
3759
+ description: "Itemized billing table",
3760
+ icon: lucideReact.Table,
3761
+ category: "Invoice"
3762
+ }
3763
+ };
3764
+ var buildResolver = (registry) => {
3765
+ const resolver = {};
3766
+ for (const [name, config] of Object.entries(registry)) {
3767
+ resolver[name] = config.component;
3768
+ }
3769
+ return resolver;
3770
+ };
3771
+ var getCategories = (registry) => {
3772
+ const cats = /* @__PURE__ */ new Set();
3773
+ for (const config of Object.values(registry)) {
3774
+ if (config.category) cats.add(config.category);
3775
+ }
3776
+ return Array.from(cats);
3777
+ };
3778
+
3779
+ // src/lib/htmlExporter.ts
3780
+ var generateEmailHtml = (nodes, customRenderers) => {
3781
+ const renderNode = (nodeId) => {
3782
+ const node = nodes[nodeId];
3783
+ if (!node) return "";
3784
+ const { type, props, nodes: childNodes, linkedNodes } = node;
3785
+ const typeName = type.resolvedName;
3786
+ let childrenHtml = "";
3787
+ if (childNodes && childNodes.length > 0) {
3788
+ childrenHtml = childNodes.map((childId) => renderNode(childId)).join("");
3789
+ }
3790
+ if (linkedNodes) {
3791
+ Object.values(linkedNodes).forEach((linkedId) => {
3792
+ childrenHtml += renderNode(linkedId);
3793
+ });
3794
+ }
3795
+ if (customRenderers == null ? void 0 : customRenderers[typeName]) {
3796
+ const result = customRenderers[typeName](typeName, props, childrenHtml, linkedNodes);
3797
+ if (result !== null) return result;
3798
+ }
3799
+ switch (typeName) {
3800
+ case "Paper":
3801
+ return `
3802
+ <!DOCTYPE html>
3803
+ <html lang="en">
3804
+ <head>
3805
+ <meta charset="UTF-8">
3806
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
3807
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
3808
+ <title>Email Template</title>
3809
+ <!--[if mso]>
3810
+ <noscript>
3811
+ <xml>
3812
+ <o:OfficeDocumentSettings>
3813
+ <o:PixelsPerInch>96</o:PixelsPerInch>
3814
+ </o:OfficeDocumentSettings>
3815
+ </xml>
3816
+ </noscript>
3817
+ <![endif]-->
3818
+ </head>
3819
+ <body style="margin: 0; padding: 0; background-color: #f4f4f4; font-family: Arial, sans-serif;">
3820
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%" style="background-color: #f4f4f4;">
3821
+ <tr>
3822
+ <td align="center" style="padding: 20px 0;">
3823
+ <table role="presentation" cellpadding="0" cellspacing="0" width="600" style="background-color: ${props.background || "#ffffff"}; max-width: 600px;">
3824
+ <tr>
3825
+ <td>
3826
+ ${childrenHtml}
3827
+ </td>
3828
+ </tr>
3829
+ </table>
3830
+ </td>
3831
+ </tr>
3832
+ </table>
3833
+ </body>
3834
+ </html>`;
3835
+ case "Container":
3836
+ return `
3837
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3838
+ <tr>
3839
+ <td style="background-color: ${props.background || "#ffffff"}; padding: ${props.padding || 20}px;">
3840
+ ${childrenHtml}
3841
+ </td>
3842
+ </tr>
3843
+ </table>`;
3844
+ case "TwoColumn": {
3845
+ const leftWidth = props.leftWidth || 50;
3846
+ const rightWidth = 100 - leftWidth;
3847
+ const leftHtml = (linkedNodes == null ? void 0 : linkedNodes["left-column"]) ? renderNode(linkedNodes["left-column"]) : "";
3848
+ const rightHtml = (linkedNodes == null ? void 0 : linkedNodes["right-column"]) ? renderNode(linkedNodes["right-column"]) : "";
3849
+ return `
3850
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%" style="background-color: ${props.backgroundColor || "#ffffff"}; padding: ${props.padding || 10}px;">
3851
+ <tr>
3852
+ <td width="${leftWidth}%" valign="top" style="padding-right: ${props.gap / 2 || 10}px;">
3853
+ ${leftHtml}
3854
+ </td>
3855
+ <td width="${rightWidth}%" valign="top" style="padding-left: ${props.gap / 2 || 10}px;">
3856
+ ${rightHtml}
3857
+ </td>
3858
+ </tr>
3859
+ </table>`;
3860
+ }
3861
+ case "EmailHeader":
3862
+ return `
3863
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3864
+ <tr>
3865
+ <td style="background-color: ${props.backgroundColor || "#1a1a2e"}; padding: ${props.padding || 24}px; text-align: center;">
3866
+ ${props.logoUrl ? `<img src="${props.logoUrl}" alt="Logo" style="max-height: 60px; margin-bottom: 12px;">` : ""}
3867
+ <h1 style="color: ${props.textColor || "#ffffff"}; font-size: 24px; font-weight: bold; margin: 0; font-family: Arial, sans-serif;">${props.companyName || "Your Company"}</h1>
3868
+ </td>
3869
+ </tr>
3870
+ </table>`;
3871
+ case "EmailFooter":
3872
+ return `
3873
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3874
+ <tr>
3875
+ <td style="background-color: ${props.backgroundColor || "#f5f5f5"}; padding: ${props.padding || 24}px; text-align: center; font-family: Arial, sans-serif;">
3876
+ <p style="color: ${props.textColor || "#666666"}; font-size: 14px; margin: 0 0 8px 0; font-weight: bold;">${props.companyName || "Your Company"}</p>
3877
+ <p style="color: ${props.textColor || "#666666"}; font-size: 12px; margin: 0 0 4px 0;">${props.address || "123 Business St, City, Country"}</p>
3878
+ <p style="color: ${props.textColor || "#666666"}; font-size: 12px; margin: 0 0 4px 0;">Email: ${props.email || "info@company.com"} | Phone: ${props.phone || "+1 234 567 890"}</p>
3879
+ <p style="color: ${props.textColor || "#666666"}; font-size: 11px; margin: 12px 0 0 0; opacity: 0.7;">\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${props.companyName || "Your Company"}. All rights reserved.</p>
3880
+ </td>
3881
+ </tr>
3882
+ </table>`;
3883
+ case "EmailButton":
3884
+ return `
3885
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3886
+ <tr>
3887
+ <td style="text-align: ${props.align || "center"}; padding: 10px 0;">
3888
+ <a href="${props.href || "#"}" style="display: inline-block; background-color: ${props.backgroundColor || "#0066cc"}; color: ${props.textColor || "#ffffff"}; padding: ${props.paddingY || 12}px ${props.paddingX || 24}px; border-radius: ${props.borderRadius || 6}px; text-decoration: none; font-size: ${props.fontSize || 16}px; font-weight: bold; font-family: Arial, sans-serif;">${props.text || "Click Here"}</a>
3889
+ </td>
3890
+ </tr>
3891
+ </table>`;
3892
+ case "TextBlock":
3893
+ return `
3894
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3895
+ <tr>
3896
+ <td style="padding: ${props.padding || 10}px;">
3897
+ <p style="font-size: ${props.fontSize || 14}px; font-weight: ${props.fontWeight || "normal"}; color: ${props.color || "#333333"}; text-align: ${props.align || "left"}; line-height: ${props.lineHeight || 1.6}; margin: 0; font-family: Arial, sans-serif;">${props.text || "Enter your text here..."}</p>
3898
+ </td>
3899
+ </tr>
3900
+ </table>`;
3901
+ case "VariableText":
3902
+ return `
3903
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3904
+ <tr>
3905
+ <td style="padding: ${props.padding || 10}px;">
3906
+ <p style="font-size: ${props.fontSize || 14}px; font-weight: ${props.fontWeight || "normal"}; color: ${props.color || "#333333"}; text-align: ${props.align || "left"}; line-height: ${props.lineHeight || 1.6}; margin: 0; font-family: Arial, sans-serif;">${props.text || ""}</p>
3907
+ </td>
3908
+ </tr>
3909
+ </table>`;
3910
+ case "ImageBlock":
3911
+ return `
3912
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3913
+ <tr>
3914
+ <td style="text-align: ${props.align || "center"}; padding: ${props.padding || 10}px;">
3915
+ <img src="${props.src || "https://via.placeholder.com/400x200"}" alt="${props.alt || "Image"}" style="width: ${props.width || "100%"}; max-width: 100%; border-radius: ${props.borderRadius || 0}px; display: inline-block;">
3916
+ </td>
3917
+ </tr>
3918
+ </table>`;
3919
+ case "VideoPlaceholder":
3920
+ return `
3921
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3922
+ <tr>
3923
+ <td style="text-align: ${props.align || "center"}; padding: ${props.padding || 10}px;">
3924
+ <a href="${props.videoUrl || "#"}" style="display: inline-block; position: relative; text-decoration: none;">
3925
+ <img src="${props.thumbnailUrl || "https://via.placeholder.com/600x338"}" alt="Video thumbnail" style="width: ${props.width || "100%"}; max-width: 100%; border-radius: ${props.borderRadius || 8}px; display: block;">
3926
+ <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 64px; height: 64px; background: rgba(0,0,0,0.6); border-radius: 50%; border: 3px solid ${props.playButtonColor || "#ffffff"};">
3927
+ <div style="position: absolute; top: 50%; left: 50%; transform: translate(-40%, -50%); width: 0; height: 0; border-top: 12px solid transparent; border-bottom: 12px solid transparent; border-left: 20px solid ${props.playButtonColor || "#ffffff"};"></div>
3928
+ </div>
3929
+ </a>
3930
+ </td>
3931
+ </tr>
3932
+ </table>`;
3933
+ case "Divider":
3934
+ return `
3935
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3936
+ <tr>
3937
+ <td style="padding: ${props.margin || 20}px 0; text-align: center;">
3938
+ <hr style="border: none; border-top: ${props.thickness || 1}px solid ${props.color || "#e0e0e0"}; width: ${props.width || "100%"}; margin: 0 auto;">
3939
+ </td>
3940
+ </tr>
3941
+ </table>`;
3942
+ case "Spacer":
3943
+ return `
3944
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3945
+ <tr>
3946
+ <td style="height: ${props.height || 20}px; line-height: ${props.height || 20}px; font-size: 1px;">&nbsp;</td>
3947
+ </tr>
3948
+ </table>`;
3949
+ case "SocialLinks": {
3950
+ const links = props.links || [];
3951
+ const iconSize = props.iconSize || 32;
3952
+ const gap = props.gap || 16;
3953
+ const socialIcons2 = {
3954
+ facebook: "https://cdn-icons-png.flaticon.com/128/733/733547.png",
3955
+ twitter: "https://cdn-icons-png.flaticon.com/128/733/733579.png",
3956
+ instagram: "https://cdn-icons-png.flaticon.com/128/2111/2111463.png",
3957
+ linkedin: "https://cdn-icons-png.flaticon.com/128/3536/3536505.png",
3958
+ youtube: "https://cdn-icons-png.flaticon.com/128/1384/1384060.png",
3959
+ tiktok: "https://cdn-icons-png.flaticon.com/128/3046/3046121.png"
3960
+ };
3961
+ const iconsHtml = links.map((link) => `
3962
+ <a href="${link.url}" style="display: inline-block; margin: 0 ${gap / 2}px;">
3963
+ <img src="${socialIcons2[link.platform] || ""}" alt="${link.platform}" style="width: ${iconSize}px; height: ${iconSize}px;">
3964
+ </a>
3965
+ `).join("");
3966
+ return `
3967
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3968
+ <tr>
3969
+ <td style="text-align: ${props.align || "center"}; padding: ${props.padding || 16}px; background-color: ${props.backgroundColor || "transparent"};">
3970
+ ${iconsHtml}
3971
+ </td>
3972
+ </tr>
3973
+ </table>`;
3974
+ }
3975
+ case "Countdown": {
3976
+ const boxStyle = `background: ${props.boxBackground || "rgba(0,0,0,0.2)"}; padding: 12px 16px; border-radius: 8px; text-align: center; display: inline-block; margin: 0 6px;`;
3977
+ const numberStyle = `font-size: 28px; font-weight: bold; color: ${props.numberColor || "#ffffff"}; font-family: Arial, sans-serif;`;
3978
+ const labelStyle = `font-size: 11px; color: ${props.labelColor || "#ffffff"}; text-transform: uppercase; letter-spacing: 1px;`;
3979
+ return `
3980
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
3981
+ <tr>
3982
+ <td style="background-color: ${props.backgroundColor || "#ff6b6b"}; padding: ${props.padding || 24}px; text-align: center;">
3983
+ ${props.title ? `<h3 style="color: ${props.titleColor || "#ffffff"}; font-size: 18px; font-weight: bold; margin: 0 0 16px 0; font-family: Arial, sans-serif;">${props.title}</h3>` : ""}
3984
+ <table role="presentation" cellpadding="0" cellspacing="0" align="center">
3985
+ <tr>
3986
+ <td style="${boxStyle}">
3987
+ <div style="${numberStyle}">${String(props.days || 0).padStart(2, "0")}</div>
3988
+ <div style="${labelStyle}">Days</div>
3989
+ </td>
3990
+ <td style="${boxStyle}">
3991
+ <div style="${numberStyle}">${String(props.hours || 0).padStart(2, "0")}</div>
3992
+ <div style="${labelStyle}">Hours</div>
3993
+ </td>
3994
+ <td style="${boxStyle}">
3995
+ <div style="${numberStyle}">${String(props.minutes || 0).padStart(2, "0")}</div>
3996
+ <div style="${labelStyle}">Mins</div>
3997
+ </td>
3998
+ <td style="${boxStyle}">
3999
+ <div style="${numberStyle}">${String(props.seconds || 0).padStart(2, "0")}</div>
4000
+ <div style="${labelStyle}">Secs</div>
4001
+ </td>
4002
+ </tr>
4003
+ </table>
4004
+ </td>
4005
+ </tr>
4006
+ </table>`;
4007
+ }
4008
+ case "PromoCode":
4009
+ return `
4010
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
4011
+ <tr>
4012
+ <td style="padding: 10px;">
4013
+ <div style="background-color: ${props.backgroundColor || "#fff8e1"}; border: 2px ${props.borderStyle || "dashed"} ${props.borderColor || "#ffc107"}; border-radius: 8px; padding: ${props.padding || 24}px; text-align: center;">
4014
+ ${props.title ? `<div style="font-size: 18px; font-weight: bold; color: ${props.textColor || "#333333"}; margin-bottom: 12px; font-family: Arial, sans-serif;">${props.title}</div>` : ""}
4015
+ <div style="display: inline-block; background-color: ${props.codeBackground || "#ffffff"}; border: 1px solid ${props.borderColor || "#ffc107"}; border-radius: 6px; padding: 12px 24px; margin-bottom: 12px;">
4016
+ <span style="font-size: 24px; font-weight: bold; font-family: monospace; letter-spacing: 3px; color: ${props.codeColor || "#e65100"};">${props.code || "SAVE20"}</span>
4017
+ </div>
4018
+ ${props.description ? `<div style="font-size: 14px; color: ${props.textColor || "#333333"}; font-family: Arial, sans-serif; opacity: 0.8;">${props.description}</div>` : ""}
4019
+ </div>
4020
+ </td>
4021
+ </tr>
4022
+ </table>`;
4023
+ case "Testimonial":
4024
+ return `
4025
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
4026
+ <tr>
4027
+ <td style="padding: 10px;">
4028
+ <div style="background-color: ${props.backgroundColor || "#f8f9fa"}; padding: ${props.padding || 24}px; border-left: 4px solid ${props.accentColor || "#0066cc"};">
4029
+ ${props.showQuoteIcon !== false ? `<div style="font-size: 48px; color: ${props.accentColor || "#0066cc"}; opacity: 0.3; line-height: 1; margin-bottom: -20px; font-family: Georgia, serif;">"</div>` : ""}
4030
+ <p style="font-size: 16px; font-style: italic; color: ${props.quoteColor || "#333333"}; line-height: 1.7; margin: 0 0 16px 0; font-family: Georgia, serif;">${props.quote || ""}</p>
4031
+ <table role="presentation" cellpadding="0" cellspacing="0">
4032
+ <tr>
4033
+ ${props.authorImage ? `<td style="vertical-align: middle; padding-right: 12px;"><img src="${props.authorImage}" alt="${props.authorName}" style="width: 48px; height: 48px; border-radius: 50%;"></td>` : ""}
4034
+ <td style="vertical-align: middle;">
4035
+ <div style="font-size: 14px; font-weight: bold; color: ${props.quoteColor || "#333333"}; font-family: Arial, sans-serif;">${props.authorName || ""}</div>
4036
+ ${props.authorTitle ? `<div style="font-size: 12px; color: ${props.authorColor || "#666666"}; font-family: Arial, sans-serif;">${props.authorTitle}</div>` : ""}
4037
+ </td>
4038
+ </tr>
4039
+ </table>
4040
+ </div>
4041
+ </td>
4042
+ </tr>
4043
+ </table>`;
4044
+ case "IconList": {
4045
+ const items = props.items || [];
4046
+ const icons = {
4047
+ check: "\u2713",
4048
+ star: "\u2605",
4049
+ arrow: "\u2192",
4050
+ bullet: "\u2022",
4051
+ heart: "\u2764",
4052
+ fire: "\u{1F525}",
4053
+ rocket: "\u{1F680}",
4054
+ sparkle: "\u2728",
4055
+ gift: "\u{1F381}",
4056
+ clock: "\u23F0"
4057
+ };
4058
+ const listHtml = items.map((item) => `
4059
+ <tr>
4060
+ <td style="vertical-align: top; padding-right: 10px; color: ${props.iconColor || "#22c55e"}; font-size: ${props.iconSize || 18}px; line-height: 1.5;">${icons[item.icon] || item.icon}</td>
4061
+ <td style="vertical-align: top; color: ${props.textColor || "#333333"}; font-size: ${props.fontSize || 14}px; line-height: 1.5; padding-bottom: ${props.gap || 12}px; font-family: Arial, sans-serif;">${item.text}</td>
4062
+ </tr>
4063
+ `).join("");
4064
+ return `
4065
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
4066
+ <tr>
4067
+ <td style="padding: ${props.padding || 16}px; background-color: ${props.backgroundColor || "transparent"};">
4068
+ <table role="presentation" cellpadding="0" cellspacing="0">
4069
+ ${listHtml}
4070
+ </table>
4071
+ </td>
4072
+ </tr>
4073
+ </table>`;
4074
+ }
4075
+ case "InvoiceTable": {
4076
+ const items = props.items || [];
4077
+ const currency = props.currency || "$";
4078
+ const total = items.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0);
4079
+ const headerStyle = `background-color: ${props.headerBg || "#1a1a2e"}; color: ${props.headerColor || "#ffffff"}; padding: 12px 16px; font-weight: bold; text-align: left; border-bottom: 1px solid ${props.borderColor || "#e0e0e0"};`;
4080
+ const cellStyle = `padding: 12px 16px; border-bottom: 1px solid ${props.borderColor || "#e0e0e0"}; font-family: Arial, sans-serif; font-size: 14px;`;
4081
+ return `
4082
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%">
4083
+ <tr>
4084
+ <td style="padding: 10px;">
4085
+ <table role="presentation" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; border: 1px solid ${props.borderColor || "#e0e0e0"};">
4086
+ <tr>
4087
+ <th style="${headerStyle}">Description</th>
4088
+ <th style="${headerStyle} text-align: center; width: 80px;">Qty</th>
4089
+ <th style="${headerStyle} text-align: right; width: 100px;">Unit Price</th>
4090
+ <th style="${headerStyle} text-align: right; width: 100px;">Amount</th>
4091
+ </tr>
4092
+ ${items.map((item) => `
4093
+ <tr>
4094
+ <td style="${cellStyle}">${item.description}</td>
4095
+ <td style="${cellStyle} text-align: center;">${item.quantity}</td>
4096
+ <td style="${cellStyle} text-align: right;">${currency}${item.unitPrice.toFixed(2)}</td>
4097
+ <td style="${cellStyle} text-align: right;">${currency}${(item.quantity * item.unitPrice).toFixed(2)}</td>
4098
+ </tr>`).join("")}
4099
+ ${props.showTotal !== false ? `
4100
+ <tr>
4101
+ <td colspan="3" style="${cellStyle} text-align: right; font-weight: bold;">Total:</td>
4102
+ <td style="${cellStyle} text-align: right; font-weight: bold; background-color: #f5f5f5;">${currency}${total.toFixed(2)}</td>
4103
+ </tr>` : ""}
4104
+ </table>
4105
+ </td>
4106
+ </tr>
4107
+ </table>`;
4108
+ }
4109
+ default:
4110
+ return childrenHtml;
4111
+ }
4112
+ };
4113
+ return renderNode("ROOT");
4114
+ };
4115
+ var Dialog = DialogPrimitive__namespace.Root;
4116
+ var DialogPortal = DialogPrimitive__namespace.Portal;
4117
+ var DialogOverlay = React9__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4118
+ DialogPrimitive__namespace.Overlay,
4119
+ {
4120
+ ref,
4121
+ className: cn(
4122
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
4123
+ className
4124
+ ),
4125
+ ...props
4126
+ }
4127
+ ));
4128
+ DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
4129
+ var DialogContent = React9__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
4130
+ /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
4131
+ /* @__PURE__ */ jsxRuntime.jsxs(
4132
+ DialogPrimitive__namespace.Content,
4133
+ {
4134
+ ref,
4135
+ className: cn(
4136
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
4137
+ className
4138
+ ),
4139
+ ...props,
4140
+ children: [
4141
+ children,
4142
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none", children: [
4143
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }),
4144
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
4145
+ ] })
4146
+ ]
4147
+ }
4148
+ )
4149
+ ] }));
4150
+ DialogContent.displayName = DialogPrimitive__namespace.Content.displayName;
4151
+ var DialogHeader = ({
4152
+ className,
4153
+ ...props
4154
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
4155
+ "div",
4156
+ {
4157
+ className: cn(
4158
+ "flex flex-col space-y-1.5 text-center sm:text-left",
4159
+ className
4160
+ ),
4161
+ ...props
4162
+ }
4163
+ );
4164
+ DialogHeader.displayName = "DialogHeader";
4165
+ var DialogTitle = React9__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4166
+ DialogPrimitive__namespace.Title,
4167
+ {
4168
+ ref,
4169
+ className: cn(
4170
+ "text-lg font-semibold leading-none tracking-tight",
4171
+ className
4172
+ ),
4173
+ ...props
4174
+ }
4175
+ ));
4176
+ DialogTitle.displayName = DialogPrimitive__namespace.Title.displayName;
4177
+ var DialogDescription = React9__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4178
+ DialogPrimitive__namespace.Description,
4179
+ {
4180
+ ref,
4181
+ className: cn("text-sm text-muted-foreground", className),
4182
+ ...props
4183
+ }
4184
+ ));
4185
+ DialogDescription.displayName = DialogPrimitive__namespace.Description.displayName;
4186
+ var DropdownMenu = DropdownMenuPrimitive__namespace.Root;
4187
+ var DropdownMenuTrigger = DropdownMenuPrimitive__namespace.Trigger;
4188
+ var DropdownMenuSubTrigger = React9__namespace.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
4189
+ DropdownMenuPrimitive__namespace.SubTrigger,
4190
+ {
4191
+ ref,
4192
+ className: cn(
4193
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[state=open]:bg-accent focus:bg-accent",
4194
+ inset && "pl-8",
4195
+ className
4196
+ ),
4197
+ ...props,
4198
+ children: [
4199
+ children,
4200
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "ml-auto h-4 w-4" })
4201
+ ]
4202
+ }
4203
+ ));
4204
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive__namespace.SubTrigger.displayName;
4205
+ var DropdownMenuSubContent = React9__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4206
+ DropdownMenuPrimitive__namespace.SubContent,
4207
+ {
4208
+ ref,
4209
+ className: cn(
4210
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4211
+ className
4212
+ ),
4213
+ ...props
4214
+ }
4215
+ ));
4216
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive__namespace.SubContent.displayName;
4217
+ var DropdownMenuContent = React9__namespace.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
4218
+ DropdownMenuPrimitive__namespace.Content,
4219
+ {
4220
+ ref,
4221
+ sideOffset,
4222
+ className: cn(
4223
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4224
+ className
4225
+ ),
4226
+ ...props
4227
+ }
4228
+ ) }));
4229
+ DropdownMenuContent.displayName = DropdownMenuPrimitive__namespace.Content.displayName;
4230
+ var DropdownMenuItem = React9__namespace.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4231
+ DropdownMenuPrimitive__namespace.Item,
4232
+ {
4233
+ ref,
4234
+ className: cn(
4235
+ "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
4236
+ inset && "pl-8",
4237
+ className
4238
+ ),
4239
+ ...props
4240
+ }
4241
+ ));
4242
+ DropdownMenuItem.displayName = DropdownMenuPrimitive__namespace.Item.displayName;
4243
+ var DropdownMenuCheckboxItem = React9__namespace.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
4244
+ DropdownMenuPrimitive__namespace.CheckboxItem,
4245
+ {
4246
+ ref,
4247
+ className: cn(
4248
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
4249
+ className
4250
+ ),
4251
+ checked,
4252
+ ...props,
4253
+ children: [
4254
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.ItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4" }) }) }),
4255
+ children
4256
+ ]
4257
+ }
4258
+ ));
4259
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive__namespace.CheckboxItem.displayName;
4260
+ var DropdownMenuRadioItem = React9__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
4261
+ DropdownMenuPrimitive__namespace.RadioItem,
4262
+ {
4263
+ ref,
4264
+ className: cn(
4265
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
4266
+ className
4267
+ ),
4268
+ ...props,
4269
+ children: [
4270
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.ItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Circle, { className: "h-2 w-2 fill-current" }) }) }),
4271
+ children
4272
+ ]
4273
+ }
4274
+ ));
4275
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive__namespace.RadioItem.displayName;
4276
+ var DropdownMenuLabel = React9__namespace.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4277
+ DropdownMenuPrimitive__namespace.Label,
4278
+ {
4279
+ ref,
4280
+ className: cn(
4281
+ "px-2 py-1.5 text-sm font-semibold",
4282
+ inset && "pl-8",
4283
+ className
4284
+ ),
4285
+ ...props
4286
+ }
4287
+ ));
4288
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive__namespace.Label.displayName;
4289
+ var DropdownMenuSeparator = React9__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4290
+ DropdownMenuPrimitive__namespace.Separator,
4291
+ {
4292
+ ref,
4293
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
4294
+ ...props
4295
+ }
4296
+ ));
4297
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive__namespace.Separator.displayName;
4298
+ var TopBar = () => {
4299
+ const { actions, query, canUndo, canRedo } = core.useEditor((state, query2) => ({
4300
+ canUndo: state.options.enabled && query2.history.canUndo(),
4301
+ canRedo: state.options.enabled && query2.history.canRedo()
4302
+ }));
4303
+ const { title, logo, templates, callbacks, slots, htmlRenderers } = useEditorConfig();
4304
+ const [showCode, setShowCode] = React9.useState(false);
4305
+ const [showPreview, setShowPreview] = React9.useState(false);
4306
+ const [copied, setCopied] = React9.useState(false);
4307
+ const [htmlCode, setHtmlCode] = React9.useState("");
4308
+ const [previewDevice, setPreviewDevice] = React9.useState(
4309
+ "desktop"
4310
+ );
4311
+ const getHtml = React9.useCallback(() => {
4312
+ const json = query.serialize();
4313
+ const nodes = JSON.parse(json);
4314
+ return generateEmailHtml(nodes, htmlRenderers);
4315
+ }, [query, htmlRenderers]);
4316
+ const handleExport = () => {
4317
+ var _a;
4318
+ const html = getHtml();
4319
+ setHtmlCode(html);
4320
+ setShowCode(true);
4321
+ (_a = callbacks.onExport) == null ? void 0 : _a.call(callbacks, html);
4322
+ };
4323
+ const handlePreview = () => {
4324
+ const html = getHtml();
4325
+ setHtmlCode(html);
4326
+ setShowPreview(true);
4327
+ };
4328
+ const handleCopy = async () => {
4329
+ await navigator.clipboard.writeText(htmlCode);
4330
+ setCopied(true);
4331
+ setTimeout(() => setCopied(false), 2e3);
4332
+ };
4333
+ const handleDownload = () => {
4334
+ const blob = new Blob([htmlCode], { type: "text/html" });
4335
+ const url = URL.createObjectURL(blob);
4336
+ const a = document.createElement("a");
4337
+ a.href = url;
4338
+ a.download = "email-template.html";
4339
+ document.body.appendChild(a);
4340
+ a.click();
4341
+ document.body.removeChild(a);
4342
+ URL.revokeObjectURL(url);
4343
+ };
4344
+ const handleClearCanvas = () => {
4345
+ var _a;
4346
+ actions.clearEvents();
4347
+ actions.deserialize(`{
4348
+ "ROOT": {
4349
+ "type": {"resolvedName": "Paper"},
4350
+ "isCanvas": true,
4351
+ "props": {"background": "#ffffff"},
4352
+ "displayName": "Paper",
4353
+ "custom": {},
4354
+ "hidden": false,
4355
+ "nodes": [],
4356
+ "linkedNodes": {}
4357
+ }
4358
+ }`);
4359
+ (_a = callbacks.onClear) == null ? void 0 : _a.call(callbacks);
4360
+ };
4361
+ const handleLoadTemplate = (template) => {
4362
+ var _a;
4363
+ try {
4364
+ actions.deserialize(template.data);
4365
+ (_a = callbacks.onTemplateLoad) == null ? void 0 : _a.call(callbacks, template.id);
4366
+ } catch (e) {
4367
+ console.error("Failed to load template:", e);
4368
+ }
4369
+ };
4370
+ if (slots.toolbar) {
4371
+ return React9__namespace.default.createElement(slots.toolbar, {
4372
+ onExport: getHtml,
4373
+ onPreview: getHtml,
4374
+ onClear: handleClearCanvas,
4375
+ title,
4376
+ logo
4377
+ });
4378
+ }
4379
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4380
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b bg-background", children: [
4381
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
4382
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4383
+ logo || /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 rounded-lg bg-gradient-to-br from-primary to-primary/60 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Palette, { className: "h-4 w-4 text-primary-foreground" }) }),
4384
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4385
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-sm font-bold leading-tight", children: title }),
4386
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-muted-foreground", children: "Drag & Drop Builder" })
4387
+ ] })
4388
+ ] }),
4389
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-px bg-border" }),
4390
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
4391
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", className: "gap-2", children: [
4392
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutTemplate, { className: "h-4 w-4" }),
4393
+ "Templates"
4394
+ ] }) }),
4395
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "start", className: "w-56", children: [
4396
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuLabel, { children: "Quick Start Templates" }),
4397
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
4398
+ templates.map((template) => /* @__PURE__ */ jsxRuntime.jsxs(
4399
+ DropdownMenuItem,
4400
+ {
4401
+ className: "gap-2",
4402
+ onClick: () => handleLoadTemplate(template),
4403
+ children: [
4404
+ template.icon && React9__namespace.default.createElement(template.icon, {
4405
+ className: "h-4 w-4 text-muted-foreground"
4406
+ }),
4407
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4408
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: template.name }),
4409
+ template.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: template.description })
4410
+ ] })
4411
+ ]
4412
+ },
4413
+ template.id
4414
+ )),
4415
+ templates.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
4416
+ /* @__PURE__ */ jsxRuntime.jsx(
4417
+ DropdownMenuItem,
4418
+ {
4419
+ onClick: handleClearCanvas,
4420
+ className: "text-destructive",
4421
+ children: "Clear Canvas"
4422
+ }
4423
+ )
4424
+ ] })
4425
+ ] })
4426
+ ] }),
4427
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4428
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 bg-muted rounded-md p-0.5", children: [
4429
+ /* @__PURE__ */ jsxRuntime.jsx(
4430
+ Button,
4431
+ {
4432
+ variant: "ghost",
4433
+ size: "sm",
4434
+ disabled: !canUndo,
4435
+ onClick: () => actions.history.undo(),
4436
+ className: "h-8 w-8 p-0",
4437
+ title: "Undo",
4438
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo2, { className: "h-4 w-4" })
4439
+ }
4440
+ ),
4441
+ /* @__PURE__ */ jsxRuntime.jsx(
4442
+ Button,
4443
+ {
4444
+ variant: "ghost",
4445
+ size: "sm",
4446
+ disabled: !canRedo,
4447
+ onClick: () => actions.history.redo(),
4448
+ className: "h-8 w-8 p-0",
4449
+ title: "Redo",
4450
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Redo2, { className: "h-4 w-4" })
4451
+ }
4452
+ )
4453
+ ] }),
4454
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-6 bg-border" }),
4455
+ /* @__PURE__ */ jsxRuntime.jsxs(
4456
+ Button,
4457
+ {
4458
+ variant: "outline",
4459
+ size: "sm",
4460
+ onClick: handlePreview,
4461
+ className: "gap-2",
4462
+ children: [
4463
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "h-4 w-4" }),
4464
+ " Preview"
4465
+ ]
4466
+ }
4467
+ ),
4468
+ /* @__PURE__ */ jsxRuntime.jsxs(
4469
+ Button,
4470
+ {
4471
+ variant: "default",
4472
+ size: "sm",
4473
+ onClick: handleExport,
4474
+ className: "gap-2",
4475
+ children: [
4476
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code, { className: "h-4 w-4" }),
4477
+ " Export HTML"
4478
+ ]
4479
+ }
4480
+ )
4481
+ ] })
4482
+ ] }),
4483
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: showCode, onOpenChange: setShowCode, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-w-4xl max-h-[80vh]", children: [
4484
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
4485
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Export HTML" }),
4486
+ /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Copy this HTML code to use in your email client or system." })
4487
+ ] }),
4488
+ slots.exportDialog ? React9__namespace.default.createElement(slots.exportDialog, {
4489
+ html: htmlCode,
4490
+ onClose: () => setShowCode(false)
4491
+ }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4492
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 mb-2", children: [
4493
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: handleCopy, children: [
4494
+ copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 mr-2" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-4 w-4 mr-2" }),
4495
+ copied ? "Copied!" : "Copy"
4496
+ ] }),
4497
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: handleDownload, children: [
4498
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { className: "h-4 w-4 mr-2" }),
4499
+ " Download"
4500
+ ] })
4501
+ ] }),
4502
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "h-[400px] border rounded-md", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-4 text-xs font-mono whitespace-pre-wrap", children: htmlCode }) })
4503
+ ] })
4504
+ ] }) }),
4505
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: showPreview, onOpenChange: setShowPreview, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-w-5xl max-h-[90vh]", children: [
4506
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
4507
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center justify-between", children: [
4508
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Email Preview" }),
4509
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1 bg-muted rounded-lg p-1" })
4510
+ ] }),
4511
+ /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Preview how your email will look in email clients." })
4512
+ ] }),
4513
+ slots.previewDialog ? React9__namespace.default.createElement(slots.previewDialog, {
4514
+ html: htmlCode,
4515
+ onClose: () => setShowPreview(false)
4516
+ }) : /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "h-[600px]", children: /* @__PURE__ */ jsxRuntime.jsx(
4517
+ "div",
4518
+ {
4519
+ className: `mx-auto transition-all duration-300 ${previewDevice === "mobile" ? "max-w-[375px]" : "max-w-full"}`,
4520
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border rounded-lg bg-muted/30 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
4521
+ "iframe",
4522
+ {
4523
+ srcDoc: htmlCode,
4524
+ className: "w-full min-h-[500px] bg-white",
4525
+ title: "Email Preview",
4526
+ style: {
4527
+ height: previewDevice === "mobile" ? "667px" : "600px"
4528
+ }
4529
+ }
4530
+ ) })
4531
+ }
4532
+ ) })
4533
+ ] }) })
4534
+ ] });
4535
+ };
4536
+ var defaultEmailContent = /* @__PURE__ */ jsxRuntime.jsxs(core.Element, { is: Paper, canvas: true, children: [
4537
+ /* @__PURE__ */ jsxRuntime.jsx(EmailHeader, {}),
4538
+ /* @__PURE__ */ jsxRuntime.jsxs(core.Element, { is: Container, canvas: true, children: [
4539
+ /* @__PURE__ */ jsxRuntime.jsx(
4540
+ TextBlock,
4541
+ {
4542
+ text: "Thank you for your business! Please find your invoice details below.",
4543
+ fontSize: 16,
4544
+ align: "center"
4545
+ }
4546
+ ),
4547
+ /* @__PURE__ */ jsxRuntime.jsx(Spacer, { height: 10 }),
4548
+ /* @__PURE__ */ jsxRuntime.jsx(InvoiceTable, {}),
4549
+ /* @__PURE__ */ jsxRuntime.jsx(Spacer, { height: 20 }),
4550
+ /* @__PURE__ */ jsxRuntime.jsx(EmailButton, { text: "Pay Now", href: "#" })
4551
+ ] }),
4552
+ /* @__PURE__ */ jsxRuntime.jsx(EmailFooter, {})
4553
+ ] });
4554
+ var EmailEditor = ({
4555
+ components: userComponents,
4556
+ replaceBuiltins = false,
4557
+ theme = {},
4558
+ slots = {},
4559
+ templates = [],
4560
+ callbacks = {},
4561
+ initialState,
4562
+ defaultContent,
4563
+ title = "Email Editor",
4564
+ logo,
4565
+ htmlRenderers = {},
4566
+ showToolbar = true,
4567
+ showToolbox = true,
4568
+ showSettingsPanel = true,
4569
+ className,
4570
+ style
4571
+ }) => {
4572
+ const mergedComponents = React9.useMemo(() => {
4573
+ if (replaceBuiltins) return userComponents || {};
4574
+ return { ...DEFAULT_COMPONENTS, ...userComponents || {} };
4575
+ }, [userComponents, replaceBuiltins]);
4576
+ const resolver = React9.useMemo(() => {
4577
+ const res = buildResolver(mergedComponents);
4578
+ res.Paper = Paper;
4579
+ return res;
4580
+ }, [mergedComponents]);
4581
+ const renderNodeFn = slots.renderNode || RenderNode;
4582
+ return /* @__PURE__ */ jsxRuntime.jsx(
4583
+ EditorProvider,
4584
+ {
4585
+ value: {
4586
+ components: mergedComponents,
4587
+ theme,
4588
+ slots,
4589
+ templates,
4590
+ callbacks,
4591
+ htmlRenderers,
4592
+ title,
4593
+ logo,
4594
+ showToolbar,
4595
+ showToolbox,
4596
+ showSettingsPanel
4597
+ },
4598
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4599
+ "div",
4600
+ {
4601
+ className: `h-screen flex flex-col bg-muted/30 ${className || ""}`,
4602
+ style,
4603
+ children: /* @__PURE__ */ jsxRuntime.jsxs(core.Editor, { resolver, onRender: renderNodeFn, children: [
4604
+ showToolbar && /* @__PURE__ */ jsxRuntime.jsx(TopBar, {}),
4605
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex overflow-hidden", children: [
4606
+ showToolbox && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-72 border-r bg-background flex flex-col", children: [
4607
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b", children: [
4608
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4609
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Palette, { className: "h-4 w-4 text-primary" }),
4610
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-sm", children: "Components" })
4611
+ ] }),
4612
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Drag components to canvas" })
4613
+ ] }),
4614
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: slots.toolbox ? React9__namespace.default.createElement(slots.toolbox, {
4615
+ components: mergedComponents,
4616
+ categories: Object.keys(mergedComponents).reduce((acc, k) => {
4617
+ const cat = mergedComponents[k].category || "Other";
4618
+ if (!acc.includes(cat)) acc.push(cat);
4619
+ return acc;
4620
+ }, [])
4621
+ }) : /* @__PURE__ */ jsxRuntime.jsx(Toolbox, {}) })
4622
+ ] }),
4623
+ /* @__PURE__ */ jsxRuntime.jsx(
4624
+ "div",
4625
+ {
4626
+ className: "flex-1 overflow-auto p-8 craftjs-renderer",
4627
+ style: { backgroundColor: "#e5e5e5" },
4628
+ children: initialState ? /* @__PURE__ */ jsxRuntime.jsx(core.Frame, { data: initialState, children: defaultEmailContent }) : /* @__PURE__ */ jsxRuntime.jsx(core.Frame, { children: defaultContent || defaultEmailContent })
4629
+ }
4630
+ ),
4631
+ showSettingsPanel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-80 border-l bg-background flex flex-col", children: [
4632
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b", children: [
4633
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4634
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "h-4 w-4 text-primary" }),
4635
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-sm", children: "Properties" })
4636
+ ] }),
4637
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Edit selected component" })
4638
+ ] }),
4639
+ /* @__PURE__ */ jsxRuntime.jsx(SettingsPanel, {})
4640
+ ] })
4641
+ ] })
4642
+ ] })
4643
+ }
4644
+ )
4645
+ }
4646
+ );
4647
+ };
4648
+
4649
+ exports.AVAILABLE_VARIABLES = AVAILABLE_VARIABLES;
4650
+ exports.Container = Container;
4651
+ exports.Countdown = Countdown;
4652
+ exports.DEFAULT_COMPONENTS = DEFAULT_COMPONENTS;
4653
+ exports.Divider = Divider;
4654
+ exports.EditorProvider = EditorProvider;
4655
+ exports.EmailButton = EmailButton;
4656
+ exports.EmailEditor = EmailEditor;
4657
+ exports.EmailFooter = EmailFooter;
4658
+ exports.EmailHeader = EmailHeader;
4659
+ exports.IconList = IconList;
4660
+ exports.ImageBlock = ImageBlock;
4661
+ exports.InvoiceTable = InvoiceTable;
4662
+ exports.Paper = Paper;
4663
+ exports.PromoCode = PromoCode;
4664
+ exports.RenderNode = RenderNode;
4665
+ exports.SettingsPanel = SettingsPanel;
4666
+ exports.SocialLinks = SocialLinks;
4667
+ exports.Spacer = Spacer;
4668
+ exports.Testimonial = Testimonial;
4669
+ exports.TextBlock = TextBlock;
4670
+ exports.Toolbox = Toolbox;
4671
+ exports.TwoColumn = TwoColumn;
4672
+ exports.VariableText = VariableText;
4673
+ exports.VideoPlaceholder = VideoPlaceholder;
4674
+ exports.buildResolver = buildResolver;
4675
+ exports.generateEmailHtml = generateEmailHtml;
4676
+ exports.getCategories = getCategories;
4677
+ exports.useEditorConfig = useEditorConfig;
4678
+ //# sourceMappingURL=index.js.map
4679
+ //# sourceMappingURL=index.js.map