@commercetools-demo/puck-editor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,3311 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Button: () => Button,
34
+ Card: () => Card,
35
+ CategoryGrid: () => CategoryGrid,
36
+ CategoryHero: () => CategoryHero,
37
+ CheckoutPromoBanner: () => CheckoutPromoBanner,
38
+ Columns: () => Columns,
39
+ ComponentItemFilter: () => ComponentItemFilter,
40
+ ComponentSearchProvider: () => ComponentSearchProvider,
41
+ ComponentsPanel: () => ComponentsPanel,
42
+ CountdownBanner: () => CountdownBanner,
43
+ CrossSellBlock: () => CrossSellBlock,
44
+ DatasourceField: () => DatasourceField,
45
+ DeliveryMessage: () => DeliveryMessage,
46
+ Divider: () => Divider,
47
+ EditorToolbar: () => EditorToolbar,
48
+ EmptyState: () => EmptyState,
49
+ FAQAccordion: () => FAQAccordion,
50
+ FooterBlock: () => FooterBlock,
51
+ Hero: () => Hero,
52
+ HeroBanner: () => HeroBanner,
53
+ Image: () => Image,
54
+ ImageBlock: () => ImageBlock,
55
+ ImagePickerField: () => ImagePickerField,
56
+ NewsletterSignup: () => NewsletterSignup,
57
+ ProductBanner: () => ProductBanner,
58
+ ProductGridHeader: () => ProductGridHeader,
59
+ ProductSlider: () => ProductSlider,
60
+ ProductTeaser: () => ProductTeaser,
61
+ PromotionalBanner: () => PromotionalBanner,
62
+ PuckEditor: () => PuckEditor,
63
+ RelatedProductsSlider: () => RelatedProductsSlider,
64
+ RichText: () => RichText,
65
+ SocialLinks: () => SocialLinks,
66
+ Spacer: () => Spacer,
67
+ TabContent: () => TabContent,
68
+ TestimonialsSlider: () => TestimonialsSlider,
69
+ TextBlock: () => TextBlock,
70
+ ThankYouContent: () => ThankYouContent,
71
+ TrustBadges: () => TrustBadges,
72
+ VideoBlock: () => VideoBlock,
73
+ WebsiteLogo: () => WebsiteLogo,
74
+ defaultPuckConfig: () => defaultPuckConfig
75
+ });
76
+ module.exports = __toCommonJS(index_exports);
77
+
78
+ // src/PuckEditor.tsx
79
+ var import_react6 = require("react");
80
+ var import_puck2 = require("@measured/puck");
81
+ var import_puck3 = require("@measured/puck/puck.css");
82
+ var import_puck_api7 = require("@commercetools-demo/puck-api");
83
+ var import_puck_api8 = require("@commercetools-demo/puck-api");
84
+
85
+ // src/config/defaultPuckConfig.ts
86
+ var import_react4 = __toESM(require("react"));
87
+
88
+ // src/components/Hero.tsx
89
+ var import_jsx_runtime = require("react/jsx-runtime");
90
+ var Hero = {
91
+ label: "Hero",
92
+ fields: {
93
+ heading: { type: "text", label: "Heading" },
94
+ subheading: { type: "textarea", label: "Subheading" },
95
+ backgroundImage: { type: "text", label: "Background Image URL" },
96
+ ctaText: { type: "text", label: "CTA Button Text" },
97
+ ctaUrl: { type: "text", label: "CTA Button URL" },
98
+ layout: {
99
+ type: "select",
100
+ label: "Layout",
101
+ options: [
102
+ { value: "centered", label: "Centered" },
103
+ { value: "left-aligned", label: "Left Aligned" }
104
+ ]
105
+ },
106
+ minHeight: { type: "text", label: "Min Height (CSS, e.g. 400px)" }
107
+ },
108
+ defaultProps: {
109
+ heading: "Welcome",
110
+ layout: "centered",
111
+ minHeight: "400px"
112
+ },
113
+ render: ({
114
+ heading,
115
+ subheading,
116
+ backgroundImage,
117
+ ctaText,
118
+ ctaUrl,
119
+ layout,
120
+ minHeight
121
+ }) => {
122
+ const isCenter = layout !== "left-aligned";
123
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
124
+ "section",
125
+ {
126
+ style: {
127
+ position: "relative",
128
+ minHeight: minHeight ?? "400px",
129
+ display: "flex",
130
+ alignItems: "center",
131
+ justifyContent: isCenter ? "center" : "flex-start",
132
+ padding: "48px 32px",
133
+ backgroundImage: backgroundImage ? `url(${backgroundImage})` : void 0,
134
+ backgroundSize: "cover",
135
+ backgroundPosition: "center",
136
+ backgroundColor: backgroundImage ? void 0 : "#1a1a2e",
137
+ color: "#fff",
138
+ boxSizing: "border-box"
139
+ },
140
+ children: [
141
+ backgroundImage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
142
+ "div",
143
+ {
144
+ style: {
145
+ position: "absolute",
146
+ inset: 0,
147
+ background: "rgba(0,0,0,0.45)"
148
+ }
149
+ }
150
+ ),
151
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
152
+ "div",
153
+ {
154
+ style: {
155
+ position: "relative",
156
+ maxWidth: "720px",
157
+ textAlign: isCenter ? "center" : "left"
158
+ },
159
+ children: [
160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { style: { margin: "0 0 16px", fontSize: "2.5rem", fontWeight: 700 }, children: heading }),
161
+ subheading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { margin: "0 0 24px", fontSize: "1.2rem", opacity: 0.85 }, children: subheading }),
162
+ ctaText && ctaUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
163
+ "a",
164
+ {
165
+ href: ctaUrl,
166
+ style: {
167
+ display: "inline-block",
168
+ padding: "12px 28px",
169
+ background: "#e94560",
170
+ color: "#fff",
171
+ borderRadius: "4px",
172
+ textDecoration: "none",
173
+ fontWeight: 600
174
+ },
175
+ children: ctaText
176
+ }
177
+ )
178
+ ]
179
+ }
180
+ )
181
+ ]
182
+ }
183
+ );
184
+ }
185
+ };
186
+
187
+ // src/components/RichText.tsx
188
+ var import_jsx_runtime2 = require("react/jsx-runtime");
189
+ var RichText = {
190
+ label: "Rich Text",
191
+ fields: {
192
+ content: {
193
+ type: "textarea",
194
+ label: "Content (HTML supported)"
195
+ },
196
+ align: {
197
+ type: "select",
198
+ label: "Text Alignment",
199
+ options: [
200
+ { value: "left", label: "Left" },
201
+ { value: "center", label: "Center" },
202
+ { value: "right", label: "Right" }
203
+ ]
204
+ },
205
+ maxWidth: { type: "text", label: "Max Width (CSS)" },
206
+ padding: { type: "text", label: "Padding (CSS)" }
207
+ },
208
+ defaultProps: {
209
+ content: "<p>Add your content here\u2026</p>",
210
+ align: "left",
211
+ padding: "32px"
212
+ },
213
+ render: ({ content, align, maxWidth, padding }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
214
+ "div",
215
+ {
216
+ style: {
217
+ padding: padding ?? "32px",
218
+ textAlign: align ?? "left",
219
+ maxWidth,
220
+ margin: maxWidth ? "0 auto" : void 0,
221
+ boxSizing: "border-box"
222
+ },
223
+ dangerouslySetInnerHTML: { __html: content }
224
+ }
225
+ )
226
+ };
227
+
228
+ // src/components/Columns.tsx
229
+ var import_puck = require("@measured/puck");
230
+ var import_jsx_runtime3 = require("react/jsx-runtime");
231
+ var Columns = {
232
+ label: "Columns",
233
+ fields: {
234
+ columnCount: {
235
+ type: "select",
236
+ label: "Number of Columns",
237
+ options: [
238
+ { value: 2, label: "2 Columns" },
239
+ { value: 3, label: "3 Columns" },
240
+ { value: 4, label: "4 Columns" }
241
+ ]
242
+ },
243
+ gap: { type: "text", label: "Column Gap (CSS)" },
244
+ padding: { type: "text", label: "Padding (CSS)" }
245
+ },
246
+ defaultProps: {
247
+ columnCount: 2,
248
+ gap: "16px",
249
+ padding: "16px"
250
+ },
251
+ render: ({ columnCount = 2, gap = "16px", padding = "16px" }) => {
252
+ const cols = Array.from({ length: columnCount }, (_, i) => i);
253
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
254
+ "div",
255
+ {
256
+ style: {
257
+ display: "grid",
258
+ gridTemplateColumns: `repeat(${columnCount}, 1fr)`,
259
+ gap,
260
+ padding,
261
+ boxSizing: "border-box"
262
+ },
263
+ children: cols.map((i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_puck.DropZone, { zone: `column-${i}` }) }, i))
264
+ }
265
+ );
266
+ }
267
+ };
268
+
269
+ // src/fields/ImagePickerField.tsx
270
+ var import_react = require("react");
271
+ var import_puck_api = require("@commercetools-demo/puck-api");
272
+ var import_jsx_runtime4 = require("react/jsx-runtime");
273
+ var s = {
274
+ root: {
275
+ display: "flex",
276
+ flexDirection: "column",
277
+ gap: "8px",
278
+ fontFamily: "inherit",
279
+ fontSize: "13px"
280
+ },
281
+ preview: {
282
+ display: "flex",
283
+ alignItems: "center",
284
+ gap: "10px",
285
+ padding: "8px",
286
+ border: "1px solid #d1d5db",
287
+ borderRadius: "6px",
288
+ background: "#f9fafb"
289
+ },
290
+ previewImg: {
291
+ width: "48px",
292
+ height: "48px",
293
+ objectFit: "cover",
294
+ borderRadius: "4px",
295
+ flexShrink: 0
296
+ },
297
+ previewInfo: { flex: 1, minWidth: 0 },
298
+ previewUrl: {
299
+ fontSize: "12px",
300
+ color: "#374151",
301
+ overflow: "hidden",
302
+ textOverflow: "ellipsis",
303
+ whiteSpace: "nowrap"
304
+ },
305
+ btnRow: { display: "flex", gap: "6px", flexWrap: "wrap" },
306
+ btn: (primary) => ({
307
+ padding: "5px 12px",
308
+ borderRadius: "4px",
309
+ border: primary ? "none" : "1px solid #d1d5db",
310
+ background: primary ? "#1a1a2e" : "#fff",
311
+ color: primary ? "#fff" : "#374151",
312
+ fontWeight: 500,
313
+ fontSize: "12px",
314
+ cursor: "pointer",
315
+ whiteSpace: "nowrap"
316
+ }),
317
+ dangerBtn: {
318
+ padding: "5px 12px",
319
+ borderRadius: "4px",
320
+ border: "1px solid #fca5a5",
321
+ background: "#fff",
322
+ color: "#dc2626",
323
+ fontWeight: 500,
324
+ fontSize: "12px",
325
+ cursor: "pointer"
326
+ },
327
+ // Modal
328
+ overlay: {
329
+ position: "fixed",
330
+ inset: 0,
331
+ background: "rgba(0,0,0,0.5)",
332
+ zIndex: 9999,
333
+ display: "flex",
334
+ alignItems: "center",
335
+ justifyContent: "center"
336
+ },
337
+ modal: {
338
+ background: "#fff",
339
+ borderRadius: "8px",
340
+ width: "640px",
341
+ maxWidth: "95vw",
342
+ maxHeight: "85vh",
343
+ display: "flex",
344
+ flexDirection: "column",
345
+ boxShadow: "0 20px 60px rgba(0,0,0,0.3)"
346
+ },
347
+ modalHeader: {
348
+ display: "flex",
349
+ alignItems: "center",
350
+ justifyContent: "space-between",
351
+ padding: "16px 20px",
352
+ borderBottom: "1px solid #e5e7eb"
353
+ },
354
+ modalTitle: { margin: 0, fontSize: "16px", fontWeight: 600 },
355
+ modalClose: {
356
+ background: "none",
357
+ border: "none",
358
+ fontSize: "20px",
359
+ cursor: "pointer",
360
+ color: "#6b7280",
361
+ lineHeight: 1
362
+ },
363
+ modalBody: {
364
+ flex: 1,
365
+ overflow: "auto",
366
+ padding: "20px"
367
+ },
368
+ modalFooter: {
369
+ display: "flex",
370
+ justifyContent: "space-between",
371
+ alignItems: "center",
372
+ padding: "12px 20px",
373
+ borderTop: "1px solid #e5e7eb",
374
+ gap: "12px"
375
+ },
376
+ // Upload form
377
+ formGroup: {
378
+ display: "flex",
379
+ flexDirection: "column",
380
+ gap: "4px",
381
+ marginBottom: "12px"
382
+ },
383
+ label: { fontSize: "12px", fontWeight: 600, color: "#374151" },
384
+ input: {
385
+ padding: "7px 10px",
386
+ border: "1px solid #d1d5db",
387
+ borderRadius: "4px",
388
+ fontSize: "13px",
389
+ width: "100%",
390
+ boxSizing: "border-box"
391
+ },
392
+ dropZone: {
393
+ border: "2px dashed #d1d5db",
394
+ borderRadius: "6px",
395
+ padding: "24px",
396
+ textAlign: "center",
397
+ cursor: "pointer",
398
+ color: "#6b7280",
399
+ fontSize: "13px",
400
+ transition: "border-color .2s"
401
+ },
402
+ dropZoneActive: {
403
+ border: "2px dashed #3b82f6",
404
+ borderRadius: "6px",
405
+ padding: "24px",
406
+ textAlign: "center",
407
+ cursor: "pointer",
408
+ color: "#3b82f6",
409
+ fontSize: "13px"
410
+ },
411
+ // Media grid
412
+ grid: {
413
+ display: "grid",
414
+ gridTemplateColumns: "repeat(auto-fill, minmax(110px, 1fr))",
415
+ gap: "12px",
416
+ marginTop: "4px"
417
+ },
418
+ gridItem: (selected) => ({
419
+ display: "flex",
420
+ flexDirection: "column",
421
+ alignItems: "center",
422
+ cursor: "pointer",
423
+ border: `2px solid ${selected ? "#3b82f6" : "transparent"}`,
424
+ borderRadius: "6px",
425
+ padding: "6px",
426
+ background: selected ? "rgba(59,130,246,0.07)" : "#f9fafb"
427
+ }),
428
+ thumb: {
429
+ width: "80px",
430
+ height: "80px",
431
+ objectFit: "cover",
432
+ borderRadius: "4px",
433
+ background: "#e5e7eb"
434
+ },
435
+ thumbPlaceholder: {
436
+ width: "80px",
437
+ height: "80px",
438
+ borderRadius: "4px",
439
+ background: "#e5e7eb",
440
+ display: "flex",
441
+ alignItems: "center",
442
+ justifyContent: "center",
443
+ fontSize: "28px"
444
+ },
445
+ itemName: {
446
+ marginTop: "6px",
447
+ fontSize: "11px",
448
+ textAlign: "center",
449
+ maxWidth: "100%",
450
+ overflow: "hidden",
451
+ textOverflow: "ellipsis",
452
+ whiteSpace: "nowrap",
453
+ color: "#374151"
454
+ },
455
+ pagination: {
456
+ display: "flex",
457
+ justifyContent: "center",
458
+ alignItems: "center",
459
+ gap: "12px",
460
+ marginTop: "16px",
461
+ fontSize: "12px",
462
+ color: "#6b7280"
463
+ },
464
+ errorMsg: {
465
+ fontSize: "12px",
466
+ color: "#dc2626",
467
+ marginTop: "4px"
468
+ },
469
+ selectedInfo: {
470
+ flex: 1,
471
+ fontSize: "12px",
472
+ color: "#374151",
473
+ overflow: "hidden",
474
+ textOverflow: "ellipsis",
475
+ whiteSpace: "nowrap"
476
+ }
477
+ };
478
+ var UploadModal = ({
479
+ uploading,
480
+ error,
481
+ onUpload,
482
+ onClose
483
+ }) => {
484
+ const [file, setFile] = (0, import_react.useState)(null);
485
+ const [title, setTitle] = (0, import_react.useState)("");
486
+ const [description, setDescription] = (0, import_react.useState)("");
487
+ const [dragging, setDragging] = (0, import_react.useState)(false);
488
+ const inputRef = (0, import_react.useRef)(null);
489
+ const handleFile = (f) => {
490
+ setFile(f);
491
+ if (!title) setTitle(f.name);
492
+ };
493
+ const handleDrop = (e) => {
494
+ e.preventDefault();
495
+ setDragging(false);
496
+ const f = e.dataTransfer.files[0];
497
+ if (f) handleFile(f);
498
+ };
499
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.overlay, onClick: (e) => e.target === e.currentTarget && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.modal, children: [
500
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.modalHeader, children: [
501
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { style: s.modalTitle, children: "Upload a file" }),
502
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: s.modalClose, onClick: onClose, children: "\xD7" })
503
+ ] }),
504
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.modalBody, children: [
505
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.formGroup, children: [
506
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: s.label, children: "Title" }),
507
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
508
+ "input",
509
+ {
510
+ style: s.input,
511
+ value: title,
512
+ onChange: (e) => setTitle(e.target.value),
513
+ placeholder: "File title"
514
+ }
515
+ )
516
+ ] }),
517
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.formGroup, children: [
518
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: s.label, children: "Description" }),
519
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
520
+ "input",
521
+ {
522
+ style: s.input,
523
+ value: description,
524
+ onChange: (e) => setDescription(e.target.value),
525
+ placeholder: "Optional description"
526
+ }
527
+ )
528
+ ] }),
529
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
530
+ "div",
531
+ {
532
+ style: dragging ? s.dropZoneActive : s.dropZone,
533
+ onClick: () => inputRef.current?.click(),
534
+ onDragOver: (e) => {
535
+ e.preventDefault();
536
+ setDragging(true);
537
+ },
538
+ onDragLeave: () => setDragging(false),
539
+ onDrop: handleDrop,
540
+ children: [
541
+ file ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
542
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
543
+ "\u{1F4CE} ",
544
+ file.name
545
+ ] }),
546
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: "11px", marginTop: "4px", color: "#9ca3af" }, children: [
547
+ (file.size / 1024).toFixed(0),
548
+ " KB"
549
+ ] })
550
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: "\u{1F4C1} Click or drag & drop to select a file" }) }),
551
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
552
+ "input",
553
+ {
554
+ ref: inputRef,
555
+ type: "file",
556
+ accept: "image/*",
557
+ style: { display: "none" },
558
+ onChange: (e) => {
559
+ const f = e.target.files?.[0];
560
+ if (f) handleFile(f);
561
+ }
562
+ }
563
+ )
564
+ ]
565
+ }
566
+ ),
567
+ error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.errorMsg, children: error })
568
+ ] }),
569
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.modalFooter, children: [
570
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: s.selectedInfo, children: file?.name ?? "No file selected" }),
571
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.btnRow, children: [
572
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: s.btn(), onClick: onClose, children: "Cancel" }),
573
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
574
+ "button",
575
+ {
576
+ style: s.btn(true),
577
+ disabled: !file || uploading,
578
+ onClick: () => file && onUpload(file, title, description),
579
+ children: uploading ? "Uploading\u2026" : "Upload"
580
+ }
581
+ )
582
+ ] })
583
+ ] })
584
+ ] }) });
585
+ };
586
+ var LibraryModal = ({
587
+ files,
588
+ pagination,
589
+ loading,
590
+ error,
591
+ onNextPage,
592
+ onPrevPage,
593
+ onSelect,
594
+ onClose
595
+ }) => {
596
+ const [selected, setSelected] = (0, import_react.useState)(null);
597
+ const handleConfirm = () => {
598
+ if (selected) onSelect(selected);
599
+ };
600
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.overlay, onClick: (e) => e.target === e.currentTarget && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.modal, children: [
601
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.modalHeader, children: [
602
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { style: s.modalTitle, children: "Select from Media Library" }),
603
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: s.modalClose, onClick: onClose, children: "\xD7" })
604
+ ] }),
605
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.modalBody, children: [
606
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "#6b7280", fontSize: "13px" }, children: "Loading\u2026" }) : files.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "#6b7280", fontSize: "13px" }, children: "No files found." }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
607
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.grid, children: files.map((file) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
608
+ "div",
609
+ {
610
+ style: s.gridItem(selected?.url === file.url),
611
+ onClick: () => setSelected(file),
612
+ title: file.title ?? file.name,
613
+ children: [
614
+ file.isImage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: file.url, alt: file.name, style: s.thumb }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.thumbPlaceholder, children: "\u{1F4C4}" }),
615
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.itemName, children: file.title ?? file.name })
616
+ ]
617
+ },
618
+ file.url
619
+ )) }),
620
+ pagination.totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.pagination, children: [
621
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
622
+ "button",
623
+ {
624
+ style: s.btn(),
625
+ disabled: pagination.currentPage <= 1,
626
+ onClick: onPrevPage,
627
+ children: "\u2190 Prev"
628
+ }
629
+ ),
630
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
631
+ pagination.currentPage,
632
+ " / ",
633
+ pagination.totalPages
634
+ ] }),
635
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
636
+ "button",
637
+ {
638
+ style: s.btn(),
639
+ disabled: pagination.currentPage >= pagination.totalPages,
640
+ onClick: onNextPage,
641
+ children: "Next \u2192"
642
+ }
643
+ )
644
+ ] })
645
+ ] }),
646
+ error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.errorMsg, children: error })
647
+ ] }),
648
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.modalFooter, children: [
649
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: s.selectedInfo, children: selected ? selected.title ?? selected.name : "Nothing selected" }),
650
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.btnRow, children: [
651
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: s.btn(), onClick: onClose, children: "Cancel" }),
652
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
653
+ "button",
654
+ {
655
+ style: s.btn(true),
656
+ disabled: !selected,
657
+ onClick: handleConfirm,
658
+ children: "Select"
659
+ }
660
+ )
661
+ ] })
662
+ ] })
663
+ ] }) });
664
+ };
665
+ var ImagePickerField = ({
666
+ value,
667
+ onChange,
668
+ imagesOnly = true
669
+ }) => {
670
+ const {
671
+ files,
672
+ pagination,
673
+ loading,
674
+ uploading,
675
+ error,
676
+ fetchMedia,
677
+ uploadFile,
678
+ loadNextPage,
679
+ loadPreviousPage
680
+ } = (0, import_puck_api.useMediaLibrary)();
681
+ const [showUpload, setShowUpload] = (0, import_react.useState)(false);
682
+ const [showLibrary, setShowLibrary] = (0, import_react.useState)(false);
683
+ const extensions = imagesOnly ? ["jpg", "jpeg", "png", "gif", "webp", "svg"] : [];
684
+ const openLibrary = (0, import_react.useCallback)(() => {
685
+ void fetchMedia(extensions, 1, 20);
686
+ setShowLibrary(true);
687
+ }, [fetchMedia, extensions]);
688
+ const handleUpload = (0, import_react.useCallback)(
689
+ async (file, title, description) => {
690
+ const mediaFile = await uploadFile(file, title, description);
691
+ onChange(mediaFile.url);
692
+ setShowUpload(false);
693
+ },
694
+ [uploadFile, onChange]
695
+ );
696
+ const handleSelect = (0, import_react.useCallback)(
697
+ (file) => {
698
+ onChange(file.url);
699
+ setShowLibrary(false);
700
+ },
701
+ [onChange]
702
+ );
703
+ (0, import_react.useEffect)(() => {
704
+ const onKey = (e) => {
705
+ if (e.key === "Escape") {
706
+ setShowUpload(false);
707
+ setShowLibrary(false);
708
+ }
709
+ };
710
+ window.addEventListener("keydown", onKey);
711
+ return () => window.removeEventListener("keydown", onKey);
712
+ }, []);
713
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.root, children: [
714
+ value ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.preview, children: [
715
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { src: value, alt: "", style: s.previewImg }),
716
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.previewInfo, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: s.previewUrl, children: value }) }),
717
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: s.dangerBtn, onClick: () => onChange(""), children: "Remove" })
718
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "#9ca3af", fontSize: "12px", padding: "4px 0" }, children: "No image selected" }),
719
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s.btnRow, children: [
720
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: s.btn(), onClick: () => setShowUpload(true), children: "Upload" }),
721
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: s.btn(true), onClick: openLibrary, children: "Media Library" })
722
+ ] }),
723
+ showUpload && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
724
+ UploadModal,
725
+ {
726
+ uploading,
727
+ error,
728
+ onUpload: (file, title, desc) => void handleUpload(file, title, desc),
729
+ onClose: () => setShowUpload(false)
730
+ }
731
+ ),
732
+ showLibrary && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
733
+ LibraryModal,
734
+ {
735
+ files,
736
+ pagination,
737
+ loading,
738
+ error,
739
+ onNextPage: () => void loadNextPage(extensions),
740
+ onPrevPage: () => void loadPreviousPage(extensions),
741
+ onSelect: handleSelect,
742
+ onClose: () => setShowLibrary(false)
743
+ }
744
+ )
745
+ ] });
746
+ };
747
+
748
+ // src/components/Image.tsx
749
+ var import_jsx_runtime5 = require("react/jsx-runtime");
750
+ var Image = {
751
+ label: "Image",
752
+ fields: {
753
+ src: {
754
+ type: "custom",
755
+ label: "Image",
756
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
757
+ ImagePickerField,
758
+ {
759
+ value,
760
+ onChange,
761
+ imagesOnly: true
762
+ }
763
+ )
764
+ },
765
+ alt: { type: "text", label: "Alt Text" },
766
+ caption: { type: "text", label: "Caption" },
767
+ width: { type: "text", label: "Width (CSS, e.g. 100%)" },
768
+ height: { type: "text", label: "Height (CSS, e.g. 300px)" },
769
+ objectFit: {
770
+ type: "select",
771
+ label: "Object Fit",
772
+ options: [
773
+ { value: "cover", label: "Cover" },
774
+ { value: "contain", label: "Contain" },
775
+ { value: "fill", label: "Fill" }
776
+ ]
777
+ },
778
+ borderRadius: { type: "text", label: "Border Radius (CSS)" },
779
+ align: {
780
+ type: "select",
781
+ label: "Alignment",
782
+ options: [
783
+ { value: "left", label: "Left" },
784
+ { value: "center", label: "Center" },
785
+ { value: "right", label: "Right" }
786
+ ]
787
+ }
788
+ },
789
+ defaultProps: {
790
+ src: "",
791
+ alt: "",
792
+ width: "100%",
793
+ objectFit: "cover",
794
+ align: "center"
795
+ },
796
+ render: ({ src, alt, caption, width, height, objectFit, borderRadius, align }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
797
+ "figure",
798
+ {
799
+ style: {
800
+ margin: 0,
801
+ padding: "16px",
802
+ textAlign: align ?? "center",
803
+ boxSizing: "border-box"
804
+ },
805
+ children: [
806
+ src ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
807
+ "img",
808
+ {
809
+ src,
810
+ alt: alt ?? "",
811
+ style: {
812
+ width: width ?? "100%",
813
+ height,
814
+ objectFit: objectFit ?? "cover",
815
+ borderRadius,
816
+ display: "inline-block",
817
+ maxWidth: "100%"
818
+ }
819
+ }
820
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
821
+ "div",
822
+ {
823
+ style: {
824
+ width: width ?? "100%",
825
+ height: height ?? "200px",
826
+ background: "#e0e0e0",
827
+ display: "flex",
828
+ alignItems: "center",
829
+ justifyContent: "center",
830
+ color: "#888",
831
+ fontSize: "14px",
832
+ borderRadius
833
+ },
834
+ children: "No image selected"
835
+ }
836
+ ),
837
+ caption && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
838
+ "figcaption",
839
+ {
840
+ style: { marginTop: "8px", fontSize: "14px", color: "#666" },
841
+ children: caption
842
+ }
843
+ )
844
+ ]
845
+ }
846
+ )
847
+ };
848
+
849
+ // src/components/Button.tsx
850
+ var import_jsx_runtime6 = require("react/jsx-runtime");
851
+ var VARIANT_STYLES = {
852
+ primary: { background: "#1a1a2e", color: "#fff", border: "2px solid #1a1a2e" },
853
+ secondary: { background: "#e94560", color: "#fff", border: "2px solid #e94560" },
854
+ outline: { background: "transparent", color: "#1a1a2e", border: "2px solid #1a1a2e" }
855
+ };
856
+ var SIZE_STYLES = {
857
+ sm: { padding: "6px 16px", fontSize: "14px" },
858
+ md: { padding: "10px 24px", fontSize: "16px" },
859
+ lg: { padding: "14px 32px", fontSize: "18px" }
860
+ };
861
+ var Button = {
862
+ label: "Button",
863
+ fields: {
864
+ label: { type: "text", label: "Button Label" },
865
+ href: { type: "text", label: "Link URL" },
866
+ variant: {
867
+ type: "select",
868
+ label: "Variant",
869
+ options: [
870
+ { value: "primary", label: "Primary" },
871
+ { value: "secondary", label: "Secondary" },
872
+ { value: "outline", label: "Outline" }
873
+ ]
874
+ },
875
+ size: {
876
+ type: "select",
877
+ label: "Size",
878
+ options: [
879
+ { value: "sm", label: "Small" },
880
+ { value: "md", label: "Medium" },
881
+ { value: "lg", label: "Large" }
882
+ ]
883
+ },
884
+ align: {
885
+ type: "select",
886
+ label: "Alignment",
887
+ options: [
888
+ { value: "left", label: "Left" },
889
+ { value: "center", label: "Center" },
890
+ { value: "right", label: "Right" }
891
+ ]
892
+ },
893
+ openInNewTab: { type: "radio", label: "Open in New Tab", options: [
894
+ { value: true, label: "Yes" },
895
+ { value: false, label: "No" }
896
+ ] }
897
+ },
898
+ defaultProps: {
899
+ label: "Click me",
900
+ variant: "primary",
901
+ size: "md",
902
+ align: "left",
903
+ openInNewTab: false
904
+ },
905
+ render: ({ label, href, variant = "primary", size = "md", align = "left", openInNewTab }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { padding: "12px 16px", textAlign: align, boxSizing: "border-box" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
906
+ "a",
907
+ {
908
+ href: href ?? "#",
909
+ target: openInNewTab ? "_blank" : void 0,
910
+ rel: openInNewTab ? "noopener noreferrer" : void 0,
911
+ style: {
912
+ display: "inline-block",
913
+ borderRadius: "4px",
914
+ textDecoration: "none",
915
+ fontWeight: 600,
916
+ cursor: "pointer",
917
+ ...VARIANT_STYLES[variant],
918
+ ...SIZE_STYLES[size]
919
+ },
920
+ children: label
921
+ }
922
+ ) })
923
+ };
924
+
925
+ // src/components/Card.tsx
926
+ var import_jsx_runtime7 = require("react/jsx-runtime");
927
+ var Card = {
928
+ label: "Card",
929
+ fields: {
930
+ title: { type: "text", label: "Title" },
931
+ body: { type: "textarea", label: "Body Text" },
932
+ imageUrl: { type: "text", label: "Image URL" },
933
+ ctaText: { type: "text", label: "CTA Text" },
934
+ ctaUrl: { type: "text", label: "CTA URL" },
935
+ shadow: {
936
+ type: "radio",
937
+ label: "Drop Shadow",
938
+ options: [
939
+ { value: true, label: "Yes" },
940
+ { value: false, label: "No" }
941
+ ]
942
+ },
943
+ borderRadius: { type: "text", label: "Border Radius (CSS)" }
944
+ },
945
+ defaultProps: {
946
+ title: "Card Title",
947
+ body: "Card description goes here.",
948
+ shadow: true,
949
+ borderRadius: "8px"
950
+ },
951
+ render: ({ title, body, imageUrl, ctaText, ctaUrl, shadow, borderRadius }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
952
+ "div",
953
+ {
954
+ style: {
955
+ border: "1px solid #e0e0e0",
956
+ borderRadius: borderRadius ?? "8px",
957
+ overflow: "hidden",
958
+ boxShadow: shadow ? "0 2px 8px rgba(0,0,0,0.12)" : void 0,
959
+ background: "#fff",
960
+ margin: "8px",
961
+ boxSizing: "border-box"
962
+ },
963
+ children: [
964
+ imageUrl && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
965
+ "img",
966
+ {
967
+ src: imageUrl,
968
+ alt: title,
969
+ style: { width: "100%", height: "200px", objectFit: "cover", display: "block" }
970
+ }
971
+ ),
972
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { padding: "16px" }, children: [
973
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { style: { margin: "0 0 8px", fontSize: "1.1rem" }, children: title }),
974
+ body && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { margin: "0 0 16px", color: "#555", fontSize: "14px" }, children: body }),
975
+ ctaText && ctaUrl && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
976
+ "a",
977
+ {
978
+ href: ctaUrl,
979
+ style: {
980
+ color: "#e94560",
981
+ fontWeight: 600,
982
+ textDecoration: "none",
983
+ fontSize: "14px"
984
+ },
985
+ children: [
986
+ ctaText,
987
+ " \u2192"
988
+ ]
989
+ }
990
+ )
991
+ ] })
992
+ ]
993
+ }
994
+ )
995
+ };
996
+
997
+ // src/components/Spacer.tsx
998
+ var import_jsx_runtime8 = require("react/jsx-runtime");
999
+ var Spacer = {
1000
+ label: "Spacer",
1001
+ fields: {
1002
+ height: { type: "text", label: "Height (CSS, e.g. 48px)" },
1003
+ showLine: {
1004
+ type: "radio",
1005
+ label: "Show Divider Line",
1006
+ options: [
1007
+ { value: true, label: "Yes" },
1008
+ { value: false, label: "No" }
1009
+ ]
1010
+ },
1011
+ lineColor: { type: "text", label: "Line Color (CSS color)" }
1012
+ },
1013
+ defaultProps: {
1014
+ height: "48px",
1015
+ showLine: false,
1016
+ lineColor: "#e0e0e0"
1017
+ },
1018
+ render: ({ height = "48px", showLine = false, lineColor = "#e0e0e0" }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1019
+ "div",
1020
+ {
1021
+ style: {
1022
+ height,
1023
+ display: "flex",
1024
+ alignItems: "center",
1025
+ padding: "0 16px",
1026
+ boxSizing: "border-box"
1027
+ },
1028
+ children: showLine && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("hr", { style: { width: "100%", border: "none", borderTop: `1px solid ${lineColor}` } })
1029
+ }
1030
+ )
1031
+ };
1032
+
1033
+ // src/components/ProductTeaser.tsx
1034
+ var import_puck_api2 = require("@commercetools-demo/puck-api");
1035
+
1036
+ // src/fields/DatasourceField.tsx
1037
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1038
+ var s2 = {
1039
+ root: {
1040
+ display: "flex",
1041
+ flexDirection: "column",
1042
+ gap: "10px",
1043
+ fontFamily: "inherit",
1044
+ fontSize: "13px"
1045
+ },
1046
+ label: { fontSize: "12px", fontWeight: 600, color: "#374151" },
1047
+ select: {
1048
+ width: "100%",
1049
+ padding: "7px 10px",
1050
+ border: "1px solid #d1d5db",
1051
+ borderRadius: "4px",
1052
+ fontSize: "13px",
1053
+ background: "#fff",
1054
+ boxSizing: "border-box"
1055
+ },
1056
+ skuRow: {
1057
+ display: "flex",
1058
+ alignItems: "center",
1059
+ gap: "6px"
1060
+ },
1061
+ input: {
1062
+ flex: 1,
1063
+ padding: "7px 10px",
1064
+ border: "1px solid #d1d5db",
1065
+ borderRadius: "4px",
1066
+ fontSize: "13px",
1067
+ boxSizing: "border-box"
1068
+ },
1069
+ removeBtn: {
1070
+ padding: "5px 8px",
1071
+ border: "1px solid #fca5a5",
1072
+ borderRadius: "4px",
1073
+ background: "#fff",
1074
+ color: "#dc2626",
1075
+ fontWeight: 600,
1076
+ fontSize: "13px",
1077
+ cursor: "pointer",
1078
+ lineHeight: 1,
1079
+ flexShrink: 0
1080
+ },
1081
+ addBtn: {
1082
+ padding: "5px 12px",
1083
+ border: "1px solid #d1d5db",
1084
+ borderRadius: "4px",
1085
+ background: "#fff",
1086
+ color: "#374151",
1087
+ fontWeight: 500,
1088
+ fontSize: "12px",
1089
+ cursor: "pointer",
1090
+ alignSelf: "flex-start"
1091
+ },
1092
+ skuList: {
1093
+ display: "flex",
1094
+ flexDirection: "column",
1095
+ gap: "6px"
1096
+ }
1097
+ };
1098
+ var EMPTY_VALUE = { type: "product-by-sku", skus: [""] };
1099
+ var DatasourceField = ({
1100
+ value,
1101
+ onChange
1102
+ }) => {
1103
+ const current = value ?? EMPTY_VALUE;
1104
+ const handleTypeChange = (e) => {
1105
+ const newType = e.target.value;
1106
+ onChange({ type: newType, skus: newType === "product-by-sku" ? [current.skus[0] ?? ""] : current.skus });
1107
+ };
1108
+ const handleSingleSkuChange = (e) => {
1109
+ onChange({ ...current, skus: [e.target.value] });
1110
+ };
1111
+ const handleMultiSkuChange = (index, val) => {
1112
+ const updated = [...current.skus];
1113
+ updated[index] = val;
1114
+ onChange({ ...current, skus: updated });
1115
+ };
1116
+ const addSku = () => {
1117
+ onChange({ ...current, skus: [...current.skus, ""] });
1118
+ };
1119
+ const removeSku = (index) => {
1120
+ const updated = current.skus.filter((_, i) => i !== index);
1121
+ onChange({ ...current, skus: updated.length > 0 ? updated : [""] });
1122
+ };
1123
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: s2.root, children: [
1124
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
1125
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: s2.label, children: "Datasource type" }),
1126
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("select", { style: s2.select, value: current.type, onChange: handleTypeChange, children: [
1127
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "product-by-sku", children: "Product by SKU" }),
1128
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "products-by-sku", children: "Products by SKU" })
1129
+ ] })
1130
+ ] }),
1131
+ current.type === "product-by-sku" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
1132
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: s2.label, children: "SKU" }),
1133
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1134
+ "input",
1135
+ {
1136
+ style: s2.input,
1137
+ type: "text",
1138
+ placeholder: "Enter product SKU",
1139
+ value: current.skus[0] ?? "",
1140
+ onChange: handleSingleSkuChange
1141
+ }
1142
+ )
1143
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
1144
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: s2.label, children: "SKUs" }),
1145
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: s2.skuList, children: [
1146
+ current.skus.map((sku, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: s2.skuRow, children: [
1147
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1148
+ "input",
1149
+ {
1150
+ style: s2.input,
1151
+ type: "text",
1152
+ placeholder: `SKU ${i + 1}`,
1153
+ value: sku,
1154
+ onChange: (e) => handleMultiSkuChange(i, e.target.value)
1155
+ }
1156
+ ),
1157
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1158
+ "button",
1159
+ {
1160
+ style: s2.removeBtn,
1161
+ onClick: () => removeSku(i),
1162
+ title: "Remove SKU",
1163
+ children: "\xD7"
1164
+ }
1165
+ )
1166
+ ] }, i)),
1167
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { style: s2.addBtn, onClick: addSku, children: "+ Add SKU" })
1168
+ ] })
1169
+ ] })
1170
+ ] });
1171
+ };
1172
+
1173
+ // src/components/ProductTeaser.tsx
1174
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1175
+ var getLocalizedName = (name) => {
1176
+ if (!name) return "";
1177
+ return name["en"] ?? name["en-US"] ?? Object.values(name)[0] ?? "";
1178
+ };
1179
+ var formatPrice = (centAmount, currencyCode, fractionDigits) => {
1180
+ const amount = centAmount / Math.pow(10, fractionDigits);
1181
+ return `${currencyCode} ${amount.toFixed(fractionDigits)}`;
1182
+ };
1183
+ var ProductTeaserRender = ({
1184
+ datasource,
1185
+ richText
1186
+ }) => {
1187
+ const hasPreResolved = datasource?.resolvedData != null;
1188
+ const { data: fetchedData, loading, error } = (0, import_puck_api2.useDatasource)(
1189
+ hasPreResolved ? void 0 : datasource?.type,
1190
+ hasPreResolved ? [] : datasource?.skus ?? []
1191
+ );
1192
+ const data = hasPreResolved ? datasource.resolvedData : fetchedData;
1193
+ const product = data ? Array.isArray(data) ? data[0] ?? null : data : null;
1194
+ const imageUrl = product?.masterVariant?.images?.[0]?.url;
1195
+ const priceValue = product?.masterVariant?.prices?.[0]?.value;
1196
+ const productName = getLocalizedName(product?.name);
1197
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1198
+ "div",
1199
+ {
1200
+ style: {
1201
+ display: "flex",
1202
+ gap: "24px",
1203
+ padding: "16px",
1204
+ alignItems: "flex-start",
1205
+ fontFamily: "inherit"
1206
+ },
1207
+ children: [
1208
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { flexShrink: 0, width: "200px" }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1209
+ "div",
1210
+ {
1211
+ style: {
1212
+ width: "200px",
1213
+ height: "200px",
1214
+ background: "#f3f4f6",
1215
+ borderRadius: "8px",
1216
+ display: "flex",
1217
+ alignItems: "center",
1218
+ justifyContent: "center",
1219
+ color: "#9ca3af",
1220
+ fontSize: "13px"
1221
+ },
1222
+ children: "Loading\u2026"
1223
+ }
1224
+ ) : imageUrl ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1225
+ "img",
1226
+ {
1227
+ src: imageUrl,
1228
+ alt: productName,
1229
+ style: {
1230
+ width: "200px",
1231
+ height: "200px",
1232
+ objectFit: "cover",
1233
+ borderRadius: "8px",
1234
+ display: "block"
1235
+ }
1236
+ }
1237
+ ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1238
+ "div",
1239
+ {
1240
+ style: {
1241
+ width: "200px",
1242
+ height: "200px",
1243
+ background: "#f3f4f6",
1244
+ borderRadius: "8px",
1245
+ display: "flex",
1246
+ alignItems: "center",
1247
+ justifyContent: "center",
1248
+ color: "#9ca3af",
1249
+ fontSize: "13px"
1250
+ },
1251
+ children: error ? "Error loading product" : "No product selected"
1252
+ }
1253
+ ) }),
1254
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1255
+ "div",
1256
+ {
1257
+ style: {
1258
+ display: "flex",
1259
+ flexDirection: "column",
1260
+ gap: "12px",
1261
+ flex: 1,
1262
+ minWidth: 0
1263
+ },
1264
+ children: [
1265
+ richText ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { dangerouslySetInnerHTML: { __html: richText } }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { color: "#9ca3af", fontSize: "13px" }, children: "No description" }),
1266
+ priceValue && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1267
+ "div",
1268
+ {
1269
+ style: {
1270
+ fontSize: "20px",
1271
+ fontWeight: 700,
1272
+ color: "#111827"
1273
+ },
1274
+ children: formatPrice(
1275
+ priceValue.centAmount,
1276
+ priceValue.currencyCode,
1277
+ priceValue.fractionDigits
1278
+ )
1279
+ }
1280
+ )
1281
+ ]
1282
+ }
1283
+ )
1284
+ ]
1285
+ }
1286
+ );
1287
+ };
1288
+ var ProductTeaser = {
1289
+ label: "Product Teaser",
1290
+ fields: {
1291
+ datasource: {
1292
+ type: "custom",
1293
+ label: "Product Datasource",
1294
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DatasourceField, { value, onChange })
1295
+ },
1296
+ richText: {
1297
+ type: "textarea",
1298
+ label: "Rich Text (HTML)"
1299
+ }
1300
+ },
1301
+ defaultProps: {
1302
+ datasource: { type: "product-by-sku", skus: [""] },
1303
+ richText: ""
1304
+ },
1305
+ render: (props) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ProductTeaserRender, { ...props })
1306
+ };
1307
+
1308
+ // src/components/cms/HeroBanner.tsx
1309
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1310
+ var HeroBanner = {
1311
+ label: "Hero Banner",
1312
+ fields: {
1313
+ title: { type: "text", label: "Title" },
1314
+ subtitle: { type: "text", label: "Subtitle" },
1315
+ image: {
1316
+ type: "custom",
1317
+ label: "Image",
1318
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ImagePickerField, { value: value ?? "", onChange })
1319
+ }
1320
+ },
1321
+ defaultProps: { title: "", subtitle: "", image: "" },
1322
+ render: ({ title, subtitle, image }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1323
+ "div",
1324
+ {
1325
+ style: {
1326
+ position: "relative",
1327
+ width: "100%",
1328
+ paddingBottom: "56.25%",
1329
+ overflow: "hidden",
1330
+ backgroundColor: "#f0f0f0"
1331
+ },
1332
+ children: [
1333
+ image && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1334
+ "img",
1335
+ {
1336
+ src: image,
1337
+ alt: title || "Hero banner",
1338
+ style: {
1339
+ position: "absolute",
1340
+ top: 0,
1341
+ left: 0,
1342
+ width: "100%",
1343
+ height: "100%",
1344
+ objectFit: "cover",
1345
+ objectPosition: "center"
1346
+ }
1347
+ }
1348
+ ),
1349
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1350
+ "div",
1351
+ {
1352
+ style: {
1353
+ position: "absolute",
1354
+ top: 0,
1355
+ left: 0,
1356
+ width: "100%",
1357
+ height: "100%",
1358
+ background: "rgba(0,0,0,0.3)",
1359
+ zIndex: 1
1360
+ }
1361
+ }
1362
+ ),
1363
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1364
+ "div",
1365
+ {
1366
+ style: {
1367
+ position: "absolute",
1368
+ top: "50%",
1369
+ left: "50%",
1370
+ transform: "translate(-50%,-50%)",
1371
+ textAlign: "center",
1372
+ color: "white",
1373
+ zIndex: 2,
1374
+ padding: "2rem",
1375
+ maxWidth: "90%"
1376
+ },
1377
+ children: [
1378
+ title && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1379
+ "h1",
1380
+ {
1381
+ style: {
1382
+ fontSize: "3rem",
1383
+ fontWeight: "bold",
1384
+ margin: "0 0 1rem 0",
1385
+ textShadow: "2px 2px 4px rgba(0,0,0,0.7)"
1386
+ },
1387
+ children: title
1388
+ }
1389
+ ),
1390
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1391
+ "p",
1392
+ {
1393
+ style: {
1394
+ fontSize: "1.25rem",
1395
+ margin: 0,
1396
+ textShadow: "1px 1px 2px rgba(0,0,0,0.7)",
1397
+ opacity: 0.95
1398
+ },
1399
+ children: subtitle
1400
+ }
1401
+ )
1402
+ ]
1403
+ }
1404
+ )
1405
+ ]
1406
+ }
1407
+ )
1408
+ };
1409
+
1410
+ // src/components/cms/TextBlock.tsx
1411
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1412
+ var TextBlock = {
1413
+ label: "Text Block",
1414
+ fields: {
1415
+ content: { type: "textarea", label: "Content (HTML)" }
1416
+ },
1417
+ defaultProps: { content: "" },
1418
+ render: ({ content }) => {
1419
+ if (!content) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, {});
1420
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1421
+ "div",
1422
+ {
1423
+ dangerouslySetInnerHTML: { __html: content },
1424
+ style: {
1425
+ maxWidth: "720px",
1426
+ margin: "0 auto",
1427
+ padding: "1.5rem 1rem",
1428
+ lineHeight: 1.6,
1429
+ color: "#333"
1430
+ }
1431
+ }
1432
+ );
1433
+ }
1434
+ };
1435
+
1436
+ // src/components/cms/CategoryGrid.tsx
1437
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1438
+ var imgField = (label) => ({
1439
+ type: "custom",
1440
+ label,
1441
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ImagePickerField, { value: value ?? "", onChange })
1442
+ });
1443
+ var CategoryGrid = {
1444
+ label: "Category Grid",
1445
+ fields: {
1446
+ category1Image: imgField("Category 1 Image"),
1447
+ category1Label: { type: "text", label: "Category 1 Label" },
1448
+ category1Link: { type: "text", label: "Category 1 Link" },
1449
+ category2Image: imgField("Category 2 Image"),
1450
+ category2Label: { type: "text", label: "Category 2 Label" },
1451
+ category2Link: { type: "text", label: "Category 2 Link" },
1452
+ category3Image: imgField("Category 3 Image"),
1453
+ category3Label: { type: "text", label: "Category 3 Label" },
1454
+ category3Link: { type: "text", label: "Category 3 Link" },
1455
+ category4Image: imgField("Category 4 Image"),
1456
+ category4Label: { type: "text", label: "Category 4 Label" },
1457
+ category4Link: { type: "text", label: "Category 4 Link" }
1458
+ },
1459
+ defaultProps: {
1460
+ category1Image: "",
1461
+ category1Label: "",
1462
+ category1Link: "",
1463
+ category2Image: "",
1464
+ category2Label: "",
1465
+ category2Link: "",
1466
+ category3Image: "",
1467
+ category3Label: "",
1468
+ category3Link: "",
1469
+ category4Image: "",
1470
+ category4Label: "",
1471
+ category4Link: ""
1472
+ },
1473
+ render: (props) => {
1474
+ const categories = [
1475
+ [props.category1Image, props.category1Label, props.category1Link],
1476
+ [props.category2Image, props.category2Label, props.category2Link],
1477
+ [props.category3Image, props.category3Label, props.category3Link],
1478
+ [props.category4Image, props.category4Label, props.category4Link]
1479
+ ].filter(([, label, link]) => label && link);
1480
+ if (categories.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { padding: "2rem", textAlign: "center", color: "#999", fontSize: "13px" }, children: "No categories configured" });
1481
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1482
+ "div",
1483
+ {
1484
+ style: {
1485
+ display: "grid",
1486
+ gridTemplateColumns: "repeat(auto-fill, minmax(200px, 1fr))",
1487
+ gap: "1.5rem",
1488
+ padding: "2rem 1rem"
1489
+ },
1490
+ children: categories.map(([image, label, link], i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1491
+ "a",
1492
+ {
1493
+ href: link,
1494
+ style: {
1495
+ display: "block",
1496
+ textAlign: "center",
1497
+ textDecoration: "none",
1498
+ color: "inherit",
1499
+ borderRadius: "8px",
1500
+ overflow: "hidden",
1501
+ boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
1502
+ },
1503
+ children: [
1504
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { aspectRatio: "1", background: "#f0f0f0", overflow: "hidden" }, children: image && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1505
+ "img",
1506
+ {
1507
+ src: image,
1508
+ alt: label,
1509
+ style: { width: "100%", height: "100%", objectFit: "cover" }
1510
+ }
1511
+ ) }),
1512
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1513
+ "span",
1514
+ {
1515
+ style: {
1516
+ display: "block",
1517
+ padding: "1rem",
1518
+ fontWeight: 600,
1519
+ color: "#333"
1520
+ },
1521
+ children: label
1522
+ }
1523
+ )
1524
+ ]
1525
+ },
1526
+ i
1527
+ ))
1528
+ }
1529
+ );
1530
+ }
1531
+ };
1532
+
1533
+ // src/components/cms/CategoryHero.tsx
1534
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1535
+ var CategoryHero = {
1536
+ label: "Category Hero",
1537
+ fields: {
1538
+ title: { type: "text", label: "Title" },
1539
+ subtitle: { type: "text", label: "Subtitle" },
1540
+ image: {
1541
+ type: "custom",
1542
+ label: "Background Image",
1543
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ImagePickerField, { value: value ?? "", onChange })
1544
+ },
1545
+ ctaText: { type: "text", label: "CTA Text" },
1546
+ ctaLink: { type: "text", label: "CTA Link" }
1547
+ },
1548
+ defaultProps: { title: "", subtitle: "", image: "", ctaText: "", ctaLink: "" },
1549
+ render: ({ title, subtitle, image, ctaText, ctaLink }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1550
+ "div",
1551
+ {
1552
+ style: {
1553
+ position: "relative",
1554
+ minHeight: "220px",
1555
+ display: "flex",
1556
+ alignItems: "center",
1557
+ justifyContent: "center",
1558
+ background: "#f0f0f0",
1559
+ borderRadius: "8px",
1560
+ overflow: "hidden",
1561
+ margin: "1rem 0"
1562
+ },
1563
+ children: [
1564
+ image && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1565
+ "img",
1566
+ {
1567
+ src: image,
1568
+ alt: title || "Category",
1569
+ style: {
1570
+ position: "absolute",
1571
+ top: 0,
1572
+ left: 0,
1573
+ width: "100%",
1574
+ height: "100%",
1575
+ objectFit: "cover",
1576
+ opacity: 0.85
1577
+ }
1578
+ }
1579
+ ),
1580
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.25)" } }),
1581
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1582
+ "div",
1583
+ {
1584
+ style: {
1585
+ position: "relative",
1586
+ zIndex: 1,
1587
+ textAlign: "center",
1588
+ padding: "2rem",
1589
+ color: "white",
1590
+ textShadow: "0 1px 3px rgba(0,0,0,0.5)"
1591
+ },
1592
+ children: [
1593
+ title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h1", { style: { fontSize: "2.5rem", marginBottom: "0.5rem" }, children: title }),
1594
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { fontSize: "1.1rem", marginBottom: "1rem" }, children: subtitle }),
1595
+ ctaText && ctaLink && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1596
+ "a",
1597
+ {
1598
+ href: ctaLink,
1599
+ style: {
1600
+ display: "inline-block",
1601
+ background: "white",
1602
+ color: "#2c5530",
1603
+ padding: "0.75rem 2rem",
1604
+ borderRadius: "4px",
1605
+ textDecoration: "none",
1606
+ fontWeight: 600
1607
+ },
1608
+ children: ctaText
1609
+ }
1610
+ )
1611
+ ]
1612
+ }
1613
+ )
1614
+ ]
1615
+ }
1616
+ )
1617
+ };
1618
+
1619
+ // src/components/cms/CheckoutPromoBanner.tsx
1620
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1621
+ var CheckoutPromoBanner = {
1622
+ label: "Checkout Promo Banner",
1623
+ fields: {
1624
+ title: { type: "text", label: "Title" },
1625
+ message: { type: "text", label: "Message" },
1626
+ ctaText: { type: "text", label: "CTA Text" },
1627
+ ctaLink: { type: "text", label: "CTA Link" }
1628
+ },
1629
+ defaultProps: { title: "", message: "", ctaText: "", ctaLink: "" },
1630
+ render: ({ title, message, ctaText, ctaLink }) => {
1631
+ if (!title && !message && !ctaText) return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, {});
1632
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1633
+ "div",
1634
+ {
1635
+ style: {
1636
+ padding: "1rem 1.25rem",
1637
+ background: "#f0f7f0",
1638
+ border: "1px solid #c8e6c8",
1639
+ borderRadius: "4px",
1640
+ marginBottom: "1rem",
1641
+ fontSize: "0.95rem"
1642
+ },
1643
+ children: [
1644
+ title && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontWeight: 600, color: "#2c5530", marginBottom: "0.25rem" }, children: title }),
1645
+ message && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: { margin: "0 0 0.5rem 0", color: "#333" }, children: message }),
1646
+ ctaText && ctaLink && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("a", { href: ctaLink, style: { color: "#2c5530", fontWeight: 600, textDecoration: "none" }, children: ctaText })
1647
+ ]
1648
+ }
1649
+ );
1650
+ }
1651
+ };
1652
+
1653
+ // src/components/cms/CountdownBanner.tsx
1654
+ var import_react2 = require("react");
1655
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1656
+ var calcTimeLeft = (endDate) => {
1657
+ if (!endDate) return "";
1658
+ const end = new Date(endDate);
1659
+ const now = /* @__PURE__ */ new Date();
1660
+ if (end <= now) return "Offer ended";
1661
+ const diff = end.getTime() - now.getTime();
1662
+ const d = Math.floor(diff / 864e5);
1663
+ const h = Math.floor(diff % 864e5 / 36e5);
1664
+ const m = Math.floor(diff % 36e5 / 6e4);
1665
+ const s3 = Math.floor(diff % 6e4 / 1e3);
1666
+ if (d > 0) return `${d}d ${h}h ${m}m left`;
1667
+ if (h > 0) return `${h}h ${m}m ${s3}s left`;
1668
+ return `${m}m ${s3}s left`;
1669
+ };
1670
+ var CountdownRender = ({
1671
+ headline,
1672
+ subline,
1673
+ endDate,
1674
+ ctaText,
1675
+ ctaLink,
1676
+ background
1677
+ }) => {
1678
+ const [timeLeft, setTimeLeft] = (0, import_react2.useState)(() => calcTimeLeft(endDate));
1679
+ (0, import_react2.useEffect)(() => {
1680
+ if (!endDate) return;
1681
+ const id = setInterval(() => setTimeLeft(calcTimeLeft(endDate)), 1e3);
1682
+ return () => clearInterval(id);
1683
+ }, [endDate]);
1684
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1685
+ "div",
1686
+ {
1687
+ style: {
1688
+ background: background || "#2c5530",
1689
+ color: "white",
1690
+ padding: "2rem 1rem",
1691
+ textAlign: "center",
1692
+ borderRadius: "4px",
1693
+ margin: "1rem 0"
1694
+ },
1695
+ children: [
1696
+ headline && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { style: { fontSize: "1.75rem", marginBottom: "0.5rem" }, children: headline }),
1697
+ subline && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { style: { fontSize: "1rem", opacity: 0.9, marginBottom: "1rem" }, children: subline }),
1698
+ timeLeft && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { style: { fontSize: "1.25rem", fontWeight: 600, margin: "0 0 1rem 0", letterSpacing: "0.05em" }, children: timeLeft }),
1699
+ ctaText && ctaLink && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1700
+ "a",
1701
+ {
1702
+ href: ctaLink,
1703
+ style: {
1704
+ display: "inline-block",
1705
+ background: "white",
1706
+ color: "#2c5530",
1707
+ padding: "0.75rem 2rem",
1708
+ borderRadius: "4px",
1709
+ textDecoration: "none",
1710
+ fontWeight: 600
1711
+ },
1712
+ children: ctaText
1713
+ }
1714
+ )
1715
+ ]
1716
+ }
1717
+ );
1718
+ };
1719
+ var CountdownBanner = {
1720
+ label: "Countdown Banner",
1721
+ fields: {
1722
+ headline: { type: "text", label: "Headline" },
1723
+ subline: { type: "text", label: "Subline" },
1724
+ endDate: { type: "text", label: "End Date (ISO, e.g. 2025-12-31T23:59:59)" },
1725
+ ctaText: { type: "text", label: "CTA Text" },
1726
+ ctaLink: { type: "text", label: "CTA Link" },
1727
+ background: { type: "text", label: "Background Color" }
1728
+ },
1729
+ defaultProps: {
1730
+ headline: "",
1731
+ subline: "",
1732
+ endDate: "",
1733
+ ctaText: "",
1734
+ ctaLink: "",
1735
+ background: "#2c5530"
1736
+ },
1737
+ render: (props) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CountdownRender, { ...props })
1738
+ };
1739
+
1740
+ // src/components/cms/CrossSellBlock.tsx
1741
+ var import_puck_api3 = require("@commercetools-demo/puck-api");
1742
+
1743
+ // src/components/cms/shared.ts
1744
+ var getLocalizedText = (obj) => {
1745
+ if (!obj) return "";
1746
+ return obj["en-US"] ?? obj["en"] ?? Object.values(obj)[0] ?? "";
1747
+ };
1748
+ var formatPrice2 = (centAmount, currencyCode = "USD", fractionDigits = 2) => {
1749
+ const amount = centAmount / Math.pow(10, fractionDigits);
1750
+ return new Intl.NumberFormat("en-US", {
1751
+ style: "currency",
1752
+ currency: currencyCode
1753
+ }).format(amount);
1754
+ };
1755
+ var getFirstPrice = (product) => {
1756
+ const p = product;
1757
+ return p?.masterVariant?.prices?.[0]?.value ?? null;
1758
+ };
1759
+ var getProductImage = (product) => {
1760
+ const p = product;
1761
+ return p?.masterVariant?.images?.[0]?.url ?? null;
1762
+ };
1763
+ var getProductSlug = (product) => {
1764
+ const p = product;
1765
+ return getLocalizedText(p?.slug) || p?.id || "#";
1766
+ };
1767
+
1768
+ // src/components/cms/CrossSellBlock.tsx
1769
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1770
+ var CrossSellRender = ({ title, products, ctaText }) => {
1771
+ const hasPreResolved = products?.resolvedData != null;
1772
+ const { data: fetchedData, loading } = (0, import_puck_api3.useDatasource)(
1773
+ hasPreResolved ? void 0 : products?.type,
1774
+ hasPreResolved ? [] : products?.skus ?? []
1775
+ );
1776
+ const items = hasPreResolved ? Array.isArray(products.resolvedData) ? products.resolvedData : [] : Array.isArray(fetchedData) ? fetchedData : [];
1777
+ if (!loading && items.length === 0) return null;
1778
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { padding: "2rem 0", borderTop: "1px solid #eee" }, children: [
1779
+ title && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h3", { style: { fontSize: "1.5rem", marginBottom: "1.5rem", color: "#333" }, children: title || "Frequently bought together" }),
1780
+ loading && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { color: "#999", padding: "1rem" }, children: "Loading\u2026" }),
1781
+ items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1782
+ "div",
1783
+ {
1784
+ style: {
1785
+ display: "grid",
1786
+ gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))",
1787
+ gap: "1rem"
1788
+ },
1789
+ children: items.map((product, i) => {
1790
+ const name = getLocalizedText(product?.name);
1791
+ const imageUrl = getProductImage(product);
1792
+ const priceVal = getFirstPrice(product);
1793
+ const slug = getProductSlug(product);
1794
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1795
+ "a",
1796
+ {
1797
+ href: slug,
1798
+ style: {
1799
+ textAlign: "center",
1800
+ textDecoration: "none",
1801
+ color: "inherit",
1802
+ padding: "1rem",
1803
+ borderRadius: "8px",
1804
+ border: "1px solid #eee"
1805
+ },
1806
+ children: [
1807
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { height: "120px", marginBottom: "0.75rem", display: "flex", alignItems: "center", justifyContent: "center", background: "#f9f9f9", borderRadius: "4px" }, children: imageUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { src: imageUrl, alt: name, style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } }) : null }),
1808
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { fontWeight: 600, fontSize: "0.95rem", marginBottom: "0.25rem" }, children: name }),
1809
+ priceVal && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { fontSize: "1.1rem", color: "#2c5530", fontWeight: "bold" }, children: formatPrice2(priceVal.centAmount, priceVal.currencyCode, priceVal.fractionDigits) })
1810
+ ]
1811
+ },
1812
+ product?.id ?? i
1813
+ );
1814
+ })
1815
+ }
1816
+ ),
1817
+ ctaText && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("a", { href: "#", style: { display: "inline-block", marginTop: "1rem", color: "#2c5530", fontWeight: 600, textDecoration: "none" }, children: ctaText })
1818
+ ] });
1819
+ };
1820
+ var CrossSellBlock = {
1821
+ label: "Cross-Sell Block",
1822
+ fields: {
1823
+ title: { type: "text", label: "Title" },
1824
+ products: {
1825
+ type: "custom",
1826
+ label: "Products",
1827
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DatasourceField, { value, onChange })
1828
+ },
1829
+ ctaText: { type: "text", label: "CTA Text" }
1830
+ },
1831
+ defaultProps: {
1832
+ title: "Frequently bought together",
1833
+ products: { type: "products-by-sku", skus: [""] },
1834
+ ctaText: ""
1835
+ },
1836
+ render: (props) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CrossSellRender, { ...props })
1837
+ };
1838
+
1839
+ // src/components/cms/DeliveryMessage.tsx
1840
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1841
+ var DeliveryMessage = {
1842
+ label: "Delivery Message",
1843
+ fields: {
1844
+ message: { type: "text", label: "Message (use $XX for threshold)" },
1845
+ threshold: { type: "text", label: "Threshold Amount (e.g. 50)" }
1846
+ },
1847
+ defaultProps: { message: "Free delivery on orders over $50", threshold: "" },
1848
+ render: ({ message, threshold }) => {
1849
+ if (!message) return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, {});
1850
+ const text = threshold ? message.replace(/\$\d+/g, `$${threshold}`) : message;
1851
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1852
+ "div",
1853
+ {
1854
+ style: {
1855
+ padding: "0.75rem 1rem",
1856
+ background: "#f0f7f0",
1857
+ borderRadius: "4px",
1858
+ fontSize: "0.95rem",
1859
+ color: "#2c5530"
1860
+ },
1861
+ children: text
1862
+ }
1863
+ );
1864
+ }
1865
+ };
1866
+
1867
+ // src/components/cms/Divider.tsx
1868
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1869
+ var Divider = {
1870
+ label: "Divider",
1871
+ fields: {
1872
+ lineStyle: {
1873
+ type: "select",
1874
+ label: "Line Style",
1875
+ options: [
1876
+ { value: "solid", label: "Solid" },
1877
+ { value: "dashed", label: "Dashed" },
1878
+ { value: "dotted", label: "Dotted" }
1879
+ ]
1880
+ },
1881
+ spacing: { type: "text", label: "Spacing (px)" }
1882
+ },
1883
+ defaultProps: { lineStyle: "solid", spacing: "24" },
1884
+ render: ({ lineStyle, spacing }) => {
1885
+ const s3 = parseInt(spacing, 10) || 24;
1886
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1887
+ "hr",
1888
+ {
1889
+ style: {
1890
+ border: "none",
1891
+ borderTop: `1px ${lineStyle} #ddd`,
1892
+ margin: `${s3 / 2}px 0`
1893
+ }
1894
+ }
1895
+ );
1896
+ }
1897
+ };
1898
+
1899
+ // src/components/cms/EmptyState.tsx
1900
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1901
+ var EmptyState = {
1902
+ label: "Empty State",
1903
+ fields: {
1904
+ image: {
1905
+ type: "custom",
1906
+ label: "Image",
1907
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ImagePickerField, { value: value ?? "", onChange })
1908
+ },
1909
+ title: { type: "text", label: "Title" },
1910
+ description: { type: "text", label: "Description" },
1911
+ ctaText: { type: "text", label: "CTA Text" },
1912
+ ctaLink: { type: "text", label: "CTA Link" }
1913
+ },
1914
+ defaultProps: { image: "", title: "", description: "", ctaText: "", ctaLink: "" },
1915
+ render: ({ image, title, description, ctaText, ctaLink }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { textAlign: "center", padding: "3rem 1rem" }, children: [
1916
+ image && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1917
+ "img",
1918
+ {
1919
+ src: image,
1920
+ alt: title || "Empty state",
1921
+ style: { maxWidth: "200px", height: "auto", marginBottom: "1.5rem", opacity: 0.8 }
1922
+ }
1923
+ ),
1924
+ title && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { style: { fontSize: "1.5rem", color: "#333", marginBottom: "0.5rem" }, children: title }),
1925
+ description && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { style: { color: "#666", marginBottom: "1.5rem", maxWidth: "400px", margin: "0 auto 1.5rem" }, children: description }),
1926
+ ctaText && ctaLink && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1927
+ "a",
1928
+ {
1929
+ href: ctaLink,
1930
+ style: {
1931
+ display: "inline-block",
1932
+ background: "#2c5530",
1933
+ color: "white",
1934
+ padding: "0.75rem 2rem",
1935
+ borderRadius: "4px",
1936
+ textDecoration: "none",
1937
+ fontWeight: 600
1938
+ },
1939
+ children: ctaText
1940
+ }
1941
+ )
1942
+ ] })
1943
+ };
1944
+
1945
+ // src/components/cms/FAQAccordion.tsx
1946
+ var import_react3 = require("react");
1947
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1948
+ var FAQRender = (props) => {
1949
+ const items = [
1950
+ [props.question1, props.answer1],
1951
+ [props.question2, props.answer2],
1952
+ [props.question3, props.answer3],
1953
+ [props.question4, props.answer4]
1954
+ ].filter(([q]) => q);
1955
+ const [open, setOpen] = (0, import_react3.useState)(null);
1956
+ if (items.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { padding: "1rem", color: "#999", fontSize: "13px" }, children: "No FAQ items configured" });
1957
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { border: "1px solid #eee", borderRadius: "8px", overflow: "hidden" }, children: items.map(([question, answer], i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { borderBottom: i < items.length - 1 ? "1px solid #eee" : "none" }, children: [
1958
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1959
+ "button",
1960
+ {
1961
+ onClick: () => setOpen(open === i ? null : i),
1962
+ style: {
1963
+ width: "100%",
1964
+ padding: "1rem 1.25rem",
1965
+ textAlign: "left",
1966
+ fontWeight: 600,
1967
+ fontSize: "1rem",
1968
+ background: "#fafafa",
1969
+ border: "none",
1970
+ cursor: "pointer",
1971
+ display: "flex",
1972
+ justifyContent: "space-between",
1973
+ alignItems: "center"
1974
+ },
1975
+ children: [
1976
+ question,
1977
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: "1.2rem", lineHeight: 1 }, children: open === i ? "\u2212" : "+" })
1978
+ ]
1979
+ }
1980
+ ),
1981
+ open === i && answer && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1982
+ "div",
1983
+ {
1984
+ dangerouslySetInnerHTML: { __html: answer },
1985
+ style: {
1986
+ padding: "1rem 1.25rem",
1987
+ background: "white",
1988
+ fontSize: "0.95rem",
1989
+ lineHeight: 1.5,
1990
+ color: "#555"
1991
+ }
1992
+ }
1993
+ )
1994
+ ] }, i)) });
1995
+ };
1996
+ var FAQAccordion = {
1997
+ label: "FAQ Accordion",
1998
+ fields: {
1999
+ question1: { type: "text", label: "Question 1" },
2000
+ answer1: { type: "textarea", label: "Answer 1 (HTML)" },
2001
+ question2: { type: "text", label: "Question 2" },
2002
+ answer2: { type: "textarea", label: "Answer 2 (HTML)" },
2003
+ question3: { type: "text", label: "Question 3" },
2004
+ answer3: { type: "textarea", label: "Answer 3 (HTML)" },
2005
+ question4: { type: "text", label: "Question 4" },
2006
+ answer4: { type: "textarea", label: "Answer 4 (HTML)" }
2007
+ },
2008
+ defaultProps: {
2009
+ question1: "",
2010
+ answer1: "",
2011
+ question2: "",
2012
+ answer2: "",
2013
+ question3: "",
2014
+ answer3: "",
2015
+ question4: "",
2016
+ answer4: ""
2017
+ },
2018
+ render: (props) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FAQRender, { ...props })
2019
+ };
2020
+
2021
+ // src/components/cms/FooterBlock.tsx
2022
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2023
+ var FooterBlock = {
2024
+ label: "Footer Block",
2025
+ fields: {
2026
+ column1: { type: "textarea", label: "Column 1 (HTML)" },
2027
+ column2: { type: "textarea", label: "Column 2 (HTML)" },
2028
+ column3: { type: "textarea", label: "Column 3 (HTML)" },
2029
+ copyright: { type: "text", label: "Copyright Text" }
2030
+ },
2031
+ defaultProps: { column1: "", column2: "", column3: "", copyright: "" },
2032
+ render: ({ column1, column2, column3, copyright }) => {
2033
+ const columns = [column1, column2, column3].filter(Boolean);
2034
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("footer", { style: { background: "#333", color: "#eee", padding: "2rem 1rem", marginTop: "3rem" }, children: [
2035
+ columns.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2036
+ "div",
2037
+ {
2038
+ style: {
2039
+ display: "grid",
2040
+ gridTemplateColumns: `repeat(${columns.length}, 1fr)`,
2041
+ gap: "2rem",
2042
+ maxWidth: "1200px",
2043
+ margin: "0 auto 2rem"
2044
+ },
2045
+ children: columns.map((html, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2046
+ "div",
2047
+ {
2048
+ dangerouslySetInnerHTML: { __html: html },
2049
+ style: { fontSize: "0.9rem", lineHeight: 1.6 }
2050
+ },
2051
+ i
2052
+ ))
2053
+ }
2054
+ ),
2055
+ copyright && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { style: { textAlign: "center", fontSize: "0.85rem", color: "#999", margin: 0 }, children: copyright })
2056
+ ] });
2057
+ }
2058
+ };
2059
+
2060
+ // src/components/cms/ImageBlock.tsx
2061
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2062
+ var ImageBlock = {
2063
+ label: "Image Block",
2064
+ fields: {
2065
+ image: {
2066
+ type: "custom",
2067
+ label: "Image",
2068
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ImagePickerField, { value: value ?? "", onChange })
2069
+ },
2070
+ caption: { type: "text", label: "Caption" },
2071
+ link: { type: "text", label: "Link URL" }
2072
+ },
2073
+ defaultProps: { image: "", caption: "", link: "" },
2074
+ render: ({ image, caption, link }) => {
2075
+ if (!image) return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { padding: "2rem", textAlign: "center", color: "#999", background: "#f5f5f5", borderRadius: "4px" }, children: "No image selected" });
2076
+ const img = /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2077
+ "img",
2078
+ {
2079
+ src: image,
2080
+ alt: caption || "Image",
2081
+ style: { maxWidth: "100%", height: "auto", borderRadius: "4px" }
2082
+ }
2083
+ );
2084
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("figure", { style: { margin: "1rem 0", textAlign: "center" }, children: [
2085
+ link ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("a", { href: link, style: { display: "inline-block" }, children: img }) : img,
2086
+ caption && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("figcaption", { style: { marginTop: "0.5rem", fontSize: "0.9rem", color: "#666" }, children: caption })
2087
+ ] });
2088
+ }
2089
+ };
2090
+
2091
+ // src/components/cms/NewsletterSignup.tsx
2092
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2093
+ var NewsletterSignup = {
2094
+ label: "Newsletter Signup",
2095
+ fields: {
2096
+ title: { type: "text", label: "Title" },
2097
+ subtitle: { type: "text", label: "Subtitle" },
2098
+ ctaText: { type: "text", label: "Button Text" },
2099
+ placeholder: { type: "text", label: "Input Placeholder" }
2100
+ },
2101
+ defaultProps: { title: "", subtitle: "", ctaText: "Subscribe", placeholder: "Enter your email" },
2102
+ render: ({ title, subtitle, ctaText, placeholder }) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2103
+ "div",
2104
+ {
2105
+ style: {
2106
+ textAlign: "center",
2107
+ padding: "2rem 1rem",
2108
+ background: "#f5f5f5",
2109
+ borderRadius: "8px",
2110
+ maxWidth: "480px",
2111
+ margin: "0 auto"
2112
+ },
2113
+ children: [
2114
+ title && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { style: { fontSize: "1.5rem", marginBottom: "0.5rem", color: "#333" }, children: title }),
2115
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { fontSize: "0.95rem", color: "#666", marginBottom: "1.5rem" }, children: subtitle }),
2116
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2117
+ "form",
2118
+ {
2119
+ onSubmit: (e) => e.preventDefault(),
2120
+ style: { display: "flex", gap: "0.5rem", flexWrap: "wrap", justifyContent: "center" },
2121
+ children: [
2122
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2123
+ "input",
2124
+ {
2125
+ type: "email",
2126
+ placeholder,
2127
+ "aria-label": "Email",
2128
+ style: {
2129
+ padding: "0.75rem 1rem",
2130
+ border: "1px solid #ddd",
2131
+ borderRadius: "4px",
2132
+ fontSize: "1rem",
2133
+ minWidth: "200px"
2134
+ }
2135
+ }
2136
+ ),
2137
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2138
+ "button",
2139
+ {
2140
+ type: "submit",
2141
+ style: {
2142
+ padding: "0.75rem 1.5rem",
2143
+ background: "#2c5530",
2144
+ color: "white",
2145
+ border: "none",
2146
+ borderRadius: "4px",
2147
+ fontWeight: 600,
2148
+ cursor: "pointer"
2149
+ },
2150
+ children: ctaText || "Subscribe"
2151
+ }
2152
+ )
2153
+ ]
2154
+ }
2155
+ )
2156
+ ]
2157
+ }
2158
+ )
2159
+ };
2160
+
2161
+ // src/components/cms/ProductBanner.tsx
2162
+ var import_puck_api4 = require("@commercetools-demo/puck-api");
2163
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2164
+ var ProductBannerRender = ({
2165
+ title,
2166
+ description,
2167
+ ctaText,
2168
+ ctaLink,
2169
+ product,
2170
+ productOnLeft,
2171
+ background
2172
+ }) => {
2173
+ const hasPreResolved = product?.resolvedData != null;
2174
+ const { data: fetchedData, loading } = (0, import_puck_api4.useDatasource)(
2175
+ hasPreResolved ? void 0 : product?.type,
2176
+ hasPreResolved ? [] : product?.skus ?? []
2177
+ );
2178
+ const raw = hasPreResolved ? product.resolvedData : fetchedData;
2179
+ const p = raw;
2180
+ const name = getLocalizedText(p?.name);
2181
+ const description2 = getLocalizedText(p?.description);
2182
+ const imageUrl = p?.masterVariant?.images?.[0]?.url;
2183
+ const sku = p?.masterVariant?.sku;
2184
+ const priceVal = getFirstPrice(p);
2185
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
2186
+ "div",
2187
+ {
2188
+ style: {
2189
+ display: "flex",
2190
+ alignItems: "center",
2191
+ minHeight: "400px",
2192
+ backgroundColor: background || "#f5f5f5",
2193
+ padding: "2rem",
2194
+ borderRadius: "2px",
2195
+ margin: "1rem 0",
2196
+ gap: "2rem",
2197
+ flexDirection: productOnLeft ? "row-reverse" : "row",
2198
+ flexWrap: "wrap"
2199
+ },
2200
+ children: [
2201
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { flex: 1, minWidth: "200px" }, children: [
2202
+ title && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { style: { fontSize: "2rem", fontWeight: "bold", marginBottom: "1rem", color: "#333" }, children: title }),
2203
+ description && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2204
+ "div",
2205
+ {
2206
+ dangerouslySetInnerHTML: { __html: description },
2207
+ style: { marginBottom: "2rem", color: "#555", lineHeight: 1.6 }
2208
+ }
2209
+ ),
2210
+ ctaText && ctaLink && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2211
+ "a",
2212
+ {
2213
+ href: ctaLink,
2214
+ style: {
2215
+ display: "inline-block",
2216
+ backgroundColor: "#2c5530",
2217
+ color: "white",
2218
+ padding: "0.75rem 2rem",
2219
+ borderRadius: "2px",
2220
+ textDecoration: "none",
2221
+ fontWeight: 600
2222
+ },
2223
+ children: ctaText
2224
+ }
2225
+ )
2226
+ ] }),
2227
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { flex: 1, minWidth: "200px", display: "flex", flexDirection: "column", alignItems: "center" }, children: [
2228
+ loading && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { color: "#999", padding: "2rem" }, children: "Loading product\u2026" }),
2229
+ name && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { style: { fontSize: "1.5rem", fontWeight: 600, marginBottom: "0.5rem", textAlign: "center" }, children: name }),
2230
+ description2 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { style: { fontSize: "0.9rem", color: "#666", textAlign: "center", marginBottom: "1rem", fontStyle: "italic" }, children: description2 }),
2231
+ imageUrl && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2232
+ "img",
2233
+ {
2234
+ src: imageUrl,
2235
+ alt: name || "Product",
2236
+ style: { maxWidth: "100%", maxHeight: "300px", objectFit: "cover", borderRadius: "2px", marginBottom: "1rem", boxShadow: "0 4px 12px rgba(0,0,0,0.1)" }
2237
+ }
2238
+ ),
2239
+ priceVal && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2240
+ "span",
2241
+ {
2242
+ style: {
2243
+ fontSize: "1.25rem",
2244
+ fontWeight: "bold",
2245
+ color: "#2c5530",
2246
+ background: "rgba(255,255,255,0.8)",
2247
+ padding: "0.5rem 1rem",
2248
+ borderRadius: "2px",
2249
+ marginBottom: "0.5rem"
2250
+ },
2251
+ children: formatPrice2(priceVal.centAmount, priceVal.currencyCode, priceVal.fractionDigits)
2252
+ }
2253
+ ),
2254
+ sku && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { style: { fontSize: "0.85rem", color: "#666", background: "rgba(255,255,255,0.6)", padding: "0.25rem 0.75rem", borderRadius: "2px" }, children: [
2255
+ "SKU: ",
2256
+ sku
2257
+ ] }),
2258
+ !loading && !p && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { color: "#999", fontSize: "13px", padding: "2rem", textAlign: "center" }, children: "No product selected" })
2259
+ ] })
2260
+ ]
2261
+ }
2262
+ );
2263
+ };
2264
+ var ProductBanner = {
2265
+ label: "Product Banner",
2266
+ fields: {
2267
+ title: { type: "text", label: "Title" },
2268
+ description: { type: "textarea", label: "Description (HTML)" },
2269
+ ctaText: { type: "text", label: "CTA Text" },
2270
+ ctaLink: { type: "text", label: "CTA Link" },
2271
+ product: {
2272
+ type: "custom",
2273
+ label: "Product",
2274
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DatasourceField, { value, onChange })
2275
+ },
2276
+ productOnLeft: {
2277
+ type: "radio",
2278
+ label: "Product Position",
2279
+ options: [
2280
+ { value: false, label: "Product on Right" },
2281
+ { value: true, label: "Product on Left" }
2282
+ ]
2283
+ },
2284
+ background: { type: "text", label: "Background Color" }
2285
+ },
2286
+ defaultProps: {
2287
+ title: "",
2288
+ description: "",
2289
+ ctaText: "",
2290
+ ctaLink: "",
2291
+ product: { type: "product-by-sku", skus: [""] },
2292
+ productOnLeft: false,
2293
+ background: "#f5f5f5"
2294
+ },
2295
+ render: (props) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProductBannerRender, { ...props })
2296
+ };
2297
+
2298
+ // src/components/cms/ProductGridHeader.tsx
2299
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2300
+ var ProductGridHeader = {
2301
+ label: "Product Grid Header",
2302
+ fields: {
2303
+ title: { type: "text", label: "Title" },
2304
+ description: { type: "textarea", label: "Description (HTML)" }
2305
+ },
2306
+ defaultProps: { title: "", description: "" },
2307
+ render: ({ title, description }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { marginBottom: "2rem", padding: "0 1rem" }, children: [
2308
+ title && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h1", { style: { fontSize: "2rem", fontWeight: "bold", color: "#333", marginBottom: "0.75rem" }, children: title }),
2309
+ description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2310
+ "div",
2311
+ {
2312
+ dangerouslySetInnerHTML: { __html: description },
2313
+ style: { fontSize: "1rem", color: "#666", lineHeight: 1.5, maxWidth: "720px" }
2314
+ }
2315
+ )
2316
+ ] })
2317
+ };
2318
+
2319
+ // src/components/cms/ProductSlider.tsx
2320
+ var import_puck_api5 = require("@commercetools-demo/puck-api");
2321
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2322
+ var ProductSliderRender = ({ title, subtitle, products }) => {
2323
+ const hasPreResolved = products?.resolvedData != null;
2324
+ const { data: fetchedData, loading } = (0, import_puck_api5.useDatasource)(
2325
+ hasPreResolved ? void 0 : products?.type,
2326
+ hasPreResolved ? [] : products?.skus ?? []
2327
+ );
2328
+ const items = hasPreResolved ? Array.isArray(products.resolvedData) ? products.resolvedData : [] : Array.isArray(fetchedData) ? fetchedData : [];
2329
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { style: { padding: "2rem 0" }, children: [
2330
+ (title || subtitle) && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { style: { textAlign: "center", marginBottom: "1.5rem" }, children: [
2331
+ title && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h2", { style: { fontSize: "2rem", fontWeight: "bold", color: "#333", marginBottom: "0.5rem" }, children: title }),
2332
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { style: { fontSize: "1.1rem", color: "#666", margin: 0 }, children: subtitle })
2333
+ ] }),
2334
+ loading && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { style: { textAlign: "center", color: "#999", padding: "2rem" }, children: "Loading products\u2026" }),
2335
+ !loading && items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { style: { textAlign: "center", color: "#999", padding: "2rem", fontSize: "13px" }, children: "No products configured" }),
2336
+ items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2337
+ "div",
2338
+ {
2339
+ style: {
2340
+ display: "flex",
2341
+ gap: "1rem",
2342
+ overflowX: "auto",
2343
+ scrollSnapType: "x mandatory",
2344
+ paddingBottom: "1rem"
2345
+ },
2346
+ children: items.map((product, i) => {
2347
+ const name = getLocalizedText(product?.name);
2348
+ const desc = getLocalizedText(product?.description);
2349
+ const imageUrl = getProductImage(product);
2350
+ const priceVal = getFirstPrice(product);
2351
+ const slug = getProductSlug(product);
2352
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
2353
+ "a",
2354
+ {
2355
+ href: slug,
2356
+ style: {
2357
+ flex: "0 0 280px",
2358
+ background: "white",
2359
+ borderRadius: "12px",
2360
+ boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
2361
+ overflow: "hidden",
2362
+ textDecoration: "none",
2363
+ color: "inherit",
2364
+ scrollSnapAlign: "start"
2365
+ },
2366
+ children: [
2367
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { style: { width: "100%", height: "200px", background: "#f5f5f5", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden" }, children: imageUrl ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("img", { src: imageUrl, alt: name, style: { width: "100%", height: "100%", objectFit: "contain" } }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { color: "#999", fontSize: "0.85rem" }, children: "No image" }) }),
2368
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { style: { padding: "1.5rem" }, children: [
2369
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h3", { style: { fontSize: "1.1rem", fontWeight: 600, color: "#333", marginBottom: "0.5rem", lineHeight: 1.3 }, children: name }),
2370
+ desc && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { style: { fontSize: "0.9rem", color: "#666", marginBottom: "1rem", display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden" }, children: desc }),
2371
+ priceVal && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { style: { fontSize: "1.2rem", fontWeight: "bold", color: "#2c5530" }, children: formatPrice2(priceVal.centAmount, priceVal.currencyCode, priceVal.fractionDigits) })
2372
+ ] })
2373
+ ]
2374
+ },
2375
+ product?.id ?? i
2376
+ );
2377
+ })
2378
+ }
2379
+ )
2380
+ ] });
2381
+ };
2382
+ var ProductSlider = {
2383
+ label: "Product Slider",
2384
+ fields: {
2385
+ title: { type: "text", label: "Title" },
2386
+ subtitle: { type: "text", label: "Subtitle" },
2387
+ products: {
2388
+ type: "custom",
2389
+ label: "Products",
2390
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(DatasourceField, { value, onChange })
2391
+ }
2392
+ },
2393
+ defaultProps: {
2394
+ title: "",
2395
+ subtitle: "",
2396
+ products: { type: "products-by-sku", skus: [""] }
2397
+ },
2398
+ render: (props) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ProductSliderRender, { ...props })
2399
+ };
2400
+
2401
+ // src/components/cms/PromotionalBanner.tsx
2402
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2403
+ var PromotionalBanner = {
2404
+ label: "Promotional Banner",
2405
+ fields: {
2406
+ image: {
2407
+ type: "custom",
2408
+ label: "Image",
2409
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ImagePickerField, { value: value ?? "", onChange })
2410
+ },
2411
+ title: { type: "text", label: "Title" },
2412
+ subtitle: { type: "text", label: "Subtitle" },
2413
+ ctaText: { type: "text", label: "CTA Text" },
2414
+ ctaLink: { type: "text", label: "CTA Link" },
2415
+ background: { type: "text", label: "Background Color" }
2416
+ },
2417
+ defaultProps: { image: "", title: "", subtitle: "", ctaText: "", ctaLink: "", background: "#f5f5f5" },
2418
+ render: ({ image, title, subtitle, ctaText, ctaLink, background }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
2419
+ "div",
2420
+ {
2421
+ style: {
2422
+ display: "flex",
2423
+ alignItems: "center",
2424
+ justifyContent: "center",
2425
+ minHeight: "280px",
2426
+ backgroundColor: background || "#f5f5f5",
2427
+ padding: "2rem",
2428
+ borderRadius: "2px",
2429
+ margin: "1rem 0",
2430
+ gap: "2rem",
2431
+ flexWrap: "wrap"
2432
+ },
2433
+ children: [
2434
+ image && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { flex: "0 0 auto", maxWidth: "40%" }, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("img", { src: image, alt: title || "Promo", style: { maxWidth: "100%", height: "auto", borderRadius: "2px" } }) }),
2435
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { style: { flex: 1, minWidth: "200px" }, children: [
2436
+ title && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h2", { style: { fontSize: "1.75rem", fontWeight: "bold", marginBottom: "0.5rem", color: "#333" }, children: title }),
2437
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { style: { fontSize: "1rem", color: "#666", marginBottom: "1rem" }, children: subtitle }),
2438
+ ctaText && ctaLink && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2439
+ "a",
2440
+ {
2441
+ href: ctaLink,
2442
+ style: {
2443
+ display: "inline-block",
2444
+ backgroundColor: "#2c5530",
2445
+ color: "white",
2446
+ padding: "0.75rem 2rem",
2447
+ borderRadius: "2px",
2448
+ textDecoration: "none",
2449
+ fontWeight: 600
2450
+ },
2451
+ children: ctaText
2452
+ }
2453
+ )
2454
+ ] })
2455
+ ]
2456
+ }
2457
+ )
2458
+ };
2459
+
2460
+ // src/components/cms/RelatedProductsSlider.tsx
2461
+ var import_puck_api6 = require("@commercetools-demo/puck-api");
2462
+ var import_jsx_runtime29 = require("react/jsx-runtime");
2463
+ var RelatedProductsRender = ({ title, subtitle, products }) => {
2464
+ const hasPreResolved = products?.resolvedData != null;
2465
+ const { data: fetchedData, loading } = (0, import_puck_api6.useDatasource)(
2466
+ hasPreResolved ? void 0 : products?.type,
2467
+ hasPreResolved ? [] : products?.skus ?? []
2468
+ );
2469
+ const items = hasPreResolved ? Array.isArray(products.resolvedData) ? products.resolvedData : [] : Array.isArray(fetchedData) ? fetchedData : [];
2470
+ if (!loading && items.length === 0) return null;
2471
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { padding: "2rem 0" }, children: [
2472
+ (title || subtitle) && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { textAlign: "center", marginBottom: "1.5rem" }, children: [
2473
+ title && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h2", { style: { fontSize: "2rem", fontWeight: "bold", color: "#333", marginBottom: "0.5rem" }, children: title }),
2474
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { style: { fontSize: "1.1rem", color: "#666", margin: 0 }, children: subtitle })
2475
+ ] }),
2476
+ loading && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { style: { textAlign: "center", color: "#999", padding: "2rem" }, children: "Loading\u2026" }),
2477
+ items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2478
+ "div",
2479
+ {
2480
+ style: {
2481
+ display: "flex",
2482
+ gap: "1rem",
2483
+ overflowX: "auto",
2484
+ scrollSnapType: "x mandatory",
2485
+ paddingBottom: "1rem"
2486
+ },
2487
+ children: items.map((product, i) => {
2488
+ const name = getLocalizedText(product?.name);
2489
+ const imageUrl = getProductImage(product);
2490
+ const priceVal = getFirstPrice(product);
2491
+ const slug = getProductSlug(product);
2492
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
2493
+ "a",
2494
+ {
2495
+ href: slug,
2496
+ style: {
2497
+ flex: "0 0 280px",
2498
+ background: "white",
2499
+ borderRadius: "12px",
2500
+ boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
2501
+ overflow: "hidden",
2502
+ textDecoration: "none",
2503
+ color: "inherit",
2504
+ scrollSnapAlign: "start"
2505
+ },
2506
+ children: [
2507
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { style: { width: "100%", height: "200px", background: "#f5f5f5", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden" }, children: imageUrl ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("img", { src: imageUrl, alt: name, style: { width: "100%", height: "100%", objectFit: "contain" } }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { style: { color: "#999", fontSize: "0.85rem" }, children: "No image" }) }),
2508
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { padding: "1.5rem" }, children: [
2509
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h3", { style: { fontSize: "1.1rem", fontWeight: 600, color: "#333", marginBottom: "0.5rem" }, children: name }),
2510
+ priceVal && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { style: { fontSize: "1.2rem", fontWeight: "bold", color: "#2c5530" }, children: formatPrice2(priceVal.centAmount, priceVal.currencyCode, priceVal.fractionDigits) })
2511
+ ] })
2512
+ ]
2513
+ },
2514
+ product?.id ?? i
2515
+ );
2516
+ })
2517
+ }
2518
+ )
2519
+ ] });
2520
+ };
2521
+ var RelatedProductsSlider = {
2522
+ label: "Related Products",
2523
+ fields: {
2524
+ title: { type: "text", label: "Title" },
2525
+ subtitle: { type: "text", label: "Subtitle" },
2526
+ products: {
2527
+ type: "custom",
2528
+ label: "Products",
2529
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(DatasourceField, { value, onChange })
2530
+ }
2531
+ },
2532
+ defaultProps: {
2533
+ title: "Related Products",
2534
+ subtitle: "",
2535
+ products: { type: "products-by-sku", skus: [""] }
2536
+ },
2537
+ render: (props) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RelatedProductsRender, { ...props })
2538
+ };
2539
+
2540
+ // src/components/cms/SocialLinks.tsx
2541
+ var import_jsx_runtime30 = require("react/jsx-runtime");
2542
+ var SocialLinks = {
2543
+ label: "Social Links",
2544
+ fields: {
2545
+ link1Label: { type: "text", label: "Link 1 Label" },
2546
+ link1Url: { type: "text", label: "Link 1 URL" },
2547
+ link2Label: { type: "text", label: "Link 2 Label" },
2548
+ link2Url: { type: "text", label: "Link 2 URL" },
2549
+ link3Label: { type: "text", label: "Link 3 Label" },
2550
+ link3Url: { type: "text", label: "Link 3 URL" },
2551
+ link4Label: { type: "text", label: "Link 4 Label" },
2552
+ link4Url: { type: "text", label: "Link 4 URL" }
2553
+ },
2554
+ defaultProps: {
2555
+ link1Label: "",
2556
+ link1Url: "",
2557
+ link2Label: "",
2558
+ link2Url: "",
2559
+ link3Label: "",
2560
+ link3Url: "",
2561
+ link4Label: "",
2562
+ link4Url: ""
2563
+ },
2564
+ render: (props) => {
2565
+ const links = [
2566
+ [props.link1Label, props.link1Url],
2567
+ [props.link2Label, props.link2Url],
2568
+ [props.link3Label, props.link3Url],
2569
+ [props.link4Label, props.link4Url]
2570
+ ].filter(([label, url]) => label && url);
2571
+ if (links.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, {});
2572
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "1rem", padding: "0.5rem 0" }, children: links.map(([label, url], i) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
2573
+ "a",
2574
+ {
2575
+ href: url,
2576
+ target: "_blank",
2577
+ rel: "noopener noreferrer",
2578
+ style: { color: "#2c5530", textDecoration: "none", fontWeight: 500, fontSize: "0.95rem" },
2579
+ children: label
2580
+ },
2581
+ i
2582
+ )) });
2583
+ }
2584
+ };
2585
+
2586
+ // src/components/cms/TabContent.tsx
2587
+ var import_jsx_runtime31 = require("react/jsx-runtime");
2588
+ var TabContent = {
2589
+ label: "Tab Content",
2590
+ fields: {
2591
+ tabLabel: { type: "text", label: "Tab Label" },
2592
+ content: { type: "textarea", label: "Content (HTML)" }
2593
+ },
2594
+ defaultProps: { tabLabel: "", content: "" },
2595
+ render: ({ tabLabel, content }) => {
2596
+ if (!content) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_jsx_runtime31.Fragment, {});
2597
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { style: { padding: "1.5rem 0", lineHeight: 1.6, color: "#333" }, children: [
2598
+ tabLabel && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("h3", { style: { marginBottom: "1rem" }, children: tabLabel }),
2599
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { dangerouslySetInnerHTML: { __html: content } })
2600
+ ] });
2601
+ }
2602
+ };
2603
+
2604
+ // src/components/cms/TestimonialsSlider.tsx
2605
+ var import_jsx_runtime32 = require("react/jsx-runtime");
2606
+ var TestimonialsSlider = {
2607
+ label: "Testimonials",
2608
+ fields: {
2609
+ quote1: { type: "textarea", label: "Quote 1" },
2610
+ author1: { type: "text", label: "Author 1" },
2611
+ role1: { type: "text", label: "Role 1" },
2612
+ quote2: { type: "textarea", label: "Quote 2" },
2613
+ author2: { type: "text", label: "Author 2" },
2614
+ role2: { type: "text", label: "Role 2" },
2615
+ quote3: { type: "textarea", label: "Quote 3" },
2616
+ author3: { type: "text", label: "Author 3" },
2617
+ role3: { type: "text", label: "Role 3" }
2618
+ },
2619
+ defaultProps: {
2620
+ quote1: "",
2621
+ author1: "",
2622
+ role1: "",
2623
+ quote2: "",
2624
+ author2: "",
2625
+ role2: "",
2626
+ quote3: "",
2627
+ author3: "",
2628
+ role3: ""
2629
+ },
2630
+ render: (props) => {
2631
+ const items = [
2632
+ [props.quote1, props.author1, props.role1],
2633
+ [props.quote2, props.author2, props.role2],
2634
+ [props.quote3, props.author3, props.role3]
2635
+ ].filter(([q]) => q);
2636
+ if (items.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, {});
2637
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { style: { padding: "2rem 1rem", background: "#f9f9f9", borderRadius: "8px", margin: "1rem 0" }, children: items.map(([quote, author, role], i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { marginBottom: i < items.length - 1 ? "2rem" : 0 }, children: [
2638
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
2639
+ "blockquote",
2640
+ {
2641
+ style: {
2642
+ fontSize: "1.15rem",
2643
+ fontStyle: "italic",
2644
+ color: "#444",
2645
+ margin: "0 0 0.75rem 0",
2646
+ paddingLeft: "1rem",
2647
+ borderLeft: "4px solid #2c5530"
2648
+ },
2649
+ children: quote
2650
+ }
2651
+ ),
2652
+ author && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("cite", { style: { fontStyle: "normal", fontSize: "0.95rem", fontWeight: 600, color: "#333" }, children: [
2653
+ "\u2014 ",
2654
+ author,
2655
+ role && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { style: { fontWeight: "normal", color: "#666" }, children: [
2656
+ " (",
2657
+ role,
2658
+ ")"
2659
+ ] })
2660
+ ] })
2661
+ ] }, i)) });
2662
+ }
2663
+ };
2664
+
2665
+ // src/components/cms/ThankYouContent.tsx
2666
+ var import_jsx_runtime33 = require("react/jsx-runtime");
2667
+ var ThankYouContent = {
2668
+ label: "Thank You Content",
2669
+ fields: {
2670
+ headline: { type: "text", label: "Headline" },
2671
+ message: { type: "textarea", label: "Message (HTML)" },
2672
+ ctaText: { type: "text", label: "CTA Text" },
2673
+ ctaLink: { type: "text", label: "CTA Link" }
2674
+ },
2675
+ defaultProps: { headline: "Thank you for your order!", message: "", ctaText: "", ctaLink: "" },
2676
+ render: ({ headline, message, ctaText, ctaLink }) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { style: { textAlign: "center", padding: "3rem 1rem", maxWidth: "560px", margin: "0 auto" }, children: [
2677
+ headline && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("h1", { style: { fontSize: "2rem", color: "#2c5530", marginBottom: "1rem" }, children: headline }),
2678
+ message && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
2679
+ "div",
2680
+ {
2681
+ dangerouslySetInnerHTML: { __html: message },
2682
+ style: { fontSize: "1rem", lineHeight: 1.6, color: "#555", marginBottom: "2rem" }
2683
+ }
2684
+ ),
2685
+ ctaText && ctaLink && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
2686
+ "a",
2687
+ {
2688
+ href: ctaLink,
2689
+ style: {
2690
+ display: "inline-block",
2691
+ background: "#2c5530",
2692
+ color: "white",
2693
+ padding: "0.75rem 2rem",
2694
+ borderRadius: "4px",
2695
+ textDecoration: "none",
2696
+ fontWeight: 600
2697
+ },
2698
+ children: ctaText
2699
+ }
2700
+ )
2701
+ ] })
2702
+ };
2703
+
2704
+ // src/components/cms/TrustBadges.tsx
2705
+ var import_jsx_runtime34 = require("react/jsx-runtime");
2706
+ var iconField = (label) => ({
2707
+ type: "custom",
2708
+ label,
2709
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ImagePickerField, { value: value ?? "", onChange })
2710
+ });
2711
+ var TrustBadges = {
2712
+ label: "Trust Badges",
2713
+ fields: {
2714
+ badge1Icon: iconField("Badge 1 Icon"),
2715
+ badge1Label: { type: "text", label: "Badge 1 Label" },
2716
+ badge2Icon: iconField("Badge 2 Icon"),
2717
+ badge2Label: { type: "text", label: "Badge 2 Label" },
2718
+ badge3Icon: iconField("Badge 3 Icon"),
2719
+ badge3Label: { type: "text", label: "Badge 3 Label" },
2720
+ badge4Icon: iconField("Badge 4 Icon"),
2721
+ badge4Label: { type: "text", label: "Badge 4 Label" }
2722
+ },
2723
+ defaultProps: {
2724
+ badge1Icon: "",
2725
+ badge1Label: "",
2726
+ badge2Icon: "",
2727
+ badge2Label: "",
2728
+ badge3Icon: "",
2729
+ badge3Label: "",
2730
+ badge4Icon: "",
2731
+ badge4Label: ""
2732
+ },
2733
+ render: (props) => {
2734
+ const badges = [
2735
+ [props.badge1Icon, props.badge1Label],
2736
+ [props.badge2Icon, props.badge2Label],
2737
+ [props.badge3Icon, props.badge3Label],
2738
+ [props.badge4Icon, props.badge4Label]
2739
+ ].filter(([, label]) => label);
2740
+ if (badges.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_jsx_runtime34.Fragment, {});
2741
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2742
+ "div",
2743
+ {
2744
+ style: {
2745
+ display: "flex",
2746
+ flexWrap: "wrap",
2747
+ justifyContent: "center",
2748
+ gap: "2rem",
2749
+ padding: "2rem 1rem",
2750
+ background: "#f9f9f9",
2751
+ borderRadius: "4px"
2752
+ },
2753
+ children: badges.map(([icon, label], i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.75rem" }, children: [
2754
+ icon && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2755
+ "img",
2756
+ {
2757
+ src: icon,
2758
+ alt: label,
2759
+ style: { width: "40px", height: "40px", objectFit: "contain" }
2760
+ }
2761
+ ),
2762
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { style: { fontSize: "0.95rem", fontWeight: 500, color: "#333" }, children: label })
2763
+ ] }, i))
2764
+ }
2765
+ );
2766
+ }
2767
+ };
2768
+
2769
+ // src/components/cms/VideoBlock.tsx
2770
+ var import_jsx_runtime35 = require("react/jsx-runtime");
2771
+ var VideoBlock = {
2772
+ label: "Video Block",
2773
+ fields: {
2774
+ videoUrl: { type: "text", label: "Video URL" },
2775
+ posterImage: {
2776
+ type: "custom",
2777
+ label: "Poster Image",
2778
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ImagePickerField, { value: value ?? "", onChange })
2779
+ },
2780
+ title: { type: "text", label: "Title" },
2781
+ caption: { type: "text", label: "Caption" }
2782
+ },
2783
+ defaultProps: { videoUrl: "", posterImage: "", title: "", caption: "" },
2784
+ render: ({ videoUrl, posterImage, title, caption }) => {
2785
+ if (!videoUrl) return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { style: { padding: "2rem", textAlign: "center", color: "#999", background: "#f5f5f5", borderRadius: "8px" }, children: "No video URL configured" });
2786
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { style: { margin: "1.5rem 0" }, children: [
2787
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2788
+ "div",
2789
+ {
2790
+ style: {
2791
+ position: "relative",
2792
+ paddingBottom: "56.25%",
2793
+ height: 0,
2794
+ overflow: "hidden",
2795
+ background: "#000",
2796
+ borderRadius: "8px"
2797
+ },
2798
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2799
+ "video",
2800
+ {
2801
+ src: videoUrl,
2802
+ poster: posterImage || void 0,
2803
+ controls: true,
2804
+ preload: "metadata",
2805
+ style: {
2806
+ position: "absolute",
2807
+ top: 0,
2808
+ left: 0,
2809
+ width: "100%",
2810
+ height: "100%",
2811
+ objectFit: "contain"
2812
+ }
2813
+ }
2814
+ )
2815
+ }
2816
+ ),
2817
+ title && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h4", { style: { marginTop: "0.75rem", fontSize: "1.1rem", color: "#333" }, children: title }),
2818
+ caption && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { style: { fontSize: "0.9rem", color: "#666", marginTop: "0.25rem" }, children: caption })
2819
+ ] });
2820
+ }
2821
+ };
2822
+
2823
+ // src/components/cms/WebsiteLogo.tsx
2824
+ var import_jsx_runtime36 = require("react/jsx-runtime");
2825
+ var WebsiteLogo = {
2826
+ label: "Website Logo",
2827
+ fields: {
2828
+ logo: {
2829
+ type: "custom",
2830
+ label: "Logo",
2831
+ render: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ImagePickerField, { value: value ?? "", onChange })
2832
+ },
2833
+ maxWidth: { type: "text", label: "Max Width (px)" },
2834
+ maxHeight: { type: "text", label: "Max Height (px)" }
2835
+ },
2836
+ defaultProps: { logo: "", maxWidth: "180", maxHeight: "50" },
2837
+ render: ({ logo, maxWidth, maxHeight }) => {
2838
+ if (!logo) return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { style: { width: `${parseInt(maxWidth, 10) || 180}px`, height: `${parseInt(maxHeight, 10) || 50}px`, background: "#f0f0f0", borderRadius: "4px" } });
2839
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
2840
+ "div",
2841
+ {
2842
+ style: {
2843
+ maxWidth: `${parseInt(maxWidth, 10) || 180}px`,
2844
+ maxHeight: `${parseInt(maxHeight, 10) || 50}px`
2845
+ },
2846
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
2847
+ "img",
2848
+ {
2849
+ src: logo,
2850
+ alt: "Logo",
2851
+ style: { width: "100%", height: "100%", objectFit: "contain" }
2852
+ }
2853
+ )
2854
+ }
2855
+ );
2856
+ }
2857
+ };
2858
+
2859
+ // src/config/defaultPuckConfig.ts
2860
+ var defaultPuckConfig = {
2861
+ components: {
2862
+ Hero,
2863
+ RichText,
2864
+ Columns,
2865
+ Image,
2866
+ Button,
2867
+ Card,
2868
+ Spacer,
2869
+ ProductTeaser,
2870
+ // CMS components
2871
+ HeroBanner,
2872
+ TextBlock,
2873
+ CategoryGrid,
2874
+ CategoryHero,
2875
+ CheckoutPromoBanner,
2876
+ CountdownBanner,
2877
+ CrossSellBlock,
2878
+ DeliveryMessage,
2879
+ Divider,
2880
+ EmptyState,
2881
+ FAQAccordion,
2882
+ FooterBlock,
2883
+ ImageBlock,
2884
+ NewsletterSignup,
2885
+ ProductBanner,
2886
+ ProductGridHeader,
2887
+ ProductSlider,
2888
+ PromotionalBanner,
2889
+ RelatedProductsSlider,
2890
+ SocialLinks,
2891
+ TabContent,
2892
+ TestimonialsSlider,
2893
+ ThankYouContent,
2894
+ TrustBadges,
2895
+ VideoBlock,
2896
+ WebsiteLogo
2897
+ },
2898
+ root: {
2899
+ fields: {
2900
+ title: { type: "text", label: "Page Title" },
2901
+ backgroundColor: { type: "text", label: "Background Color (CSS)" }
2902
+ },
2903
+ defaultProps: {
2904
+ title: "New Page",
2905
+ backgroundColor: "#ffffff"
2906
+ },
2907
+ render: ({ children, backgroundColor }) => import_react4.default.createElement(
2908
+ "div",
2909
+ {
2910
+ style: {
2911
+ background: backgroundColor ?? "#ffffff",
2912
+ minHeight: "100vh",
2913
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'
2914
+ }
2915
+ },
2916
+ children
2917
+ )
2918
+ }
2919
+ };
2920
+
2921
+ // src/toolbar/EditorToolbar.tsx
2922
+ var import_jsx_runtime37 = require("react/jsx-runtime");
2923
+ var BADGE_STYLES = {
2924
+ saving: { bg: "rgba(251, 191, 36, 0.12)", color: "var(--status-saving)", border: "rgba(251, 191, 36, 0.3)" },
2925
+ unsaved: { bg: "rgba(100, 116, 139, 0.12)", color: "var(--text-muted)", border: "rgba(100, 116, 139, 0.3)" },
2926
+ draft: { bg: "rgba(129, 140, 248, 0.12)", color: "var(--status-draft)", border: "rgba(129, 140, 248, 0.3)" },
2927
+ published: { bg: "rgba(6, 214, 160, 0.12)", color: "var(--status-published)", border: "rgba(6, 214, 160, 0.3)" }
2928
+ };
2929
+ var StatusBadge = ({ label, variant }) => {
2930
+ const s3 = BADGE_STYLES[variant];
2931
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2932
+ "span",
2933
+ {
2934
+ style: {
2935
+ display: "inline-flex",
2936
+ alignItems: "center",
2937
+ gap: "4px",
2938
+ padding: "2px 10px",
2939
+ borderRadius: "12px",
2940
+ fontSize: "12px",
2941
+ fontWeight: 600,
2942
+ background: s3.bg,
2943
+ color: s3.color,
2944
+ border: `1px solid ${s3.border}`
2945
+ },
2946
+ children: label
2947
+ }
2948
+ );
2949
+ };
2950
+ var EditorToolbar = ({
2951
+ saving,
2952
+ isDirty,
2953
+ states,
2954
+ onSave,
2955
+ onPublish,
2956
+ onRevert,
2957
+ showPublishButton
2958
+ }) => {
2959
+ const hasDraft = Boolean(states.draft);
2960
+ const hasPublished = Boolean(states.published);
2961
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
2962
+ "div",
2963
+ {
2964
+ style: {
2965
+ display: "flex",
2966
+ alignItems: "center",
2967
+ gap: "12px",
2968
+ flexWrap: "wrap"
2969
+ },
2970
+ children: [
2971
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
2972
+ saving && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(StatusBadge, { label: "Saving\u2026", variant: "saving" }),
2973
+ !saving && isDirty && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(StatusBadge, { label: "Unsaved", variant: "unsaved" }),
2974
+ !saving && !isDirty && hasDraft && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(StatusBadge, { label: "Draft", variant: "draft" }),
2975
+ hasPublished && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(StatusBadge, { label: "Published", variant: "published" })
2976
+ ] }),
2977
+ hasDraft && hasPublished && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2978
+ "button",
2979
+ {
2980
+ onClick: onRevert,
2981
+ disabled: saving,
2982
+ style: {
2983
+ padding: "6px 14px",
2984
+ borderRadius: "4px",
2985
+ border: "1px solid var(--border-glow)",
2986
+ background: "transparent",
2987
+ color: "var(--text-muted)",
2988
+ fontWeight: 500,
2989
+ fontSize: "13px",
2990
+ cursor: saving ? "not-allowed" : "pointer",
2991
+ opacity: saving ? 0.5 : 1
2992
+ },
2993
+ children: "Revert to Published"
2994
+ }
2995
+ ),
2996
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2997
+ "button",
2998
+ {
2999
+ onClick: onSave,
3000
+ disabled: !isDirty || saving,
3001
+ style: {
3002
+ padding: "6px 14px",
3003
+ borderRadius: "4px",
3004
+ border: "1px solid var(--border-glow)",
3005
+ background: "transparent",
3006
+ color: "var(--text-muted)",
3007
+ fontWeight: 500,
3008
+ fontSize: "13px",
3009
+ cursor: !isDirty || saving ? "not-allowed" : "pointer",
3010
+ opacity: !isDirty || saving ? 0.4 : 1
3011
+ },
3012
+ children: "Save"
3013
+ }
3014
+ ),
3015
+ showPublishButton && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
3016
+ "button",
3017
+ {
3018
+ onClick: onPublish,
3019
+ disabled: saving,
3020
+ style: {
3021
+ padding: "6px 16px",
3022
+ borderRadius: "4px",
3023
+ border: "1px solid var(--accent-cyan)",
3024
+ background: "rgba(0, 212, 255, 0.1)",
3025
+ color: "var(--accent-cyan)",
3026
+ fontWeight: 600,
3027
+ fontSize: "13px",
3028
+ cursor: saving ? "not-allowed" : "pointer",
3029
+ opacity: saving ? 0.5 : 1,
3030
+ boxShadow: "0 0 12px rgba(0, 212, 255, 0.15)"
3031
+ },
3032
+ children: hasPublished ? "Re-publish" : "Publish"
3033
+ }
3034
+ )
3035
+ ]
3036
+ }
3037
+ );
3038
+ };
3039
+
3040
+ // src/overrides/ComponentListSearch.tsx
3041
+ var import_react5 = require("react");
3042
+ var import_jsx_runtime38 = require("react/jsx-runtime");
3043
+ var ComponentSearchContext = (0, import_react5.createContext)({
3044
+ search: "",
3045
+ setSearch: () => {
3046
+ }
3047
+ });
3048
+ var ComponentSearchProvider = ({ children }) => {
3049
+ const [search, setSearch] = (0, import_react5.useState)("");
3050
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ComponentSearchContext.Provider, { value: { search, setSearch }, children });
3051
+ };
3052
+ var ComponentsPanel = ({ children }) => {
3053
+ const { search, setSearch } = (0, import_react5.useContext)(ComponentSearchContext);
3054
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
3055
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("style", { children: `[data-puck-dnd] > div:has([data-hidden-component]) { display: none !important; }` }),
3056
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3057
+ "div",
3058
+ {
3059
+ style: {
3060
+ flexShrink: 0,
3061
+ padding: "0",
3062
+ margin: "12px 0",
3063
+ background: "var(--puck-color-white, #fff)",
3064
+ position: "sticky",
3065
+ top: 0,
3066
+ zIndex: 1
3067
+ },
3068
+ children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3069
+ "input",
3070
+ {
3071
+ type: "search",
3072
+ placeholder: "Search components\u2026",
3073
+ value: search,
3074
+ onChange: (e) => setSearch(e.target.value),
3075
+ style: {
3076
+ width: "100%",
3077
+ boxSizing: "border-box",
3078
+ padding: "6px 10px",
3079
+ borderRadius: "4px",
3080
+ border: "1px solid var(--puck-color-grey-08, #d1d5db)",
3081
+ background: "var(--puck-color-white, #fff)",
3082
+ fontSize: "13px",
3083
+ outline: "none",
3084
+ color: "inherit"
3085
+ }
3086
+ }
3087
+ )
3088
+ }
3089
+ ),
3090
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { style: { flex: 1, overflowY: "auto" }, children })
3091
+ ] });
3092
+ };
3093
+ var ComponentItemFilter = ({
3094
+ children,
3095
+ name
3096
+ }) => {
3097
+ const { search } = (0, import_react5.useContext)(ComponentSearchContext);
3098
+ const isHidden = search.trim() !== "" && !name.toLowerCase().includes(search.toLowerCase());
3099
+ if (isHidden) {
3100
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { "data-hidden-component": true });
3101
+ }
3102
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_jsx_runtime38.Fragment, { children });
3103
+ };
3104
+
3105
+ // src/PuckEditor.tsx
3106
+ var import_jsx_runtime39 = require("react/jsx-runtime");
3107
+ var PuckEditorInner = ({
3108
+ pageKey,
3109
+ config,
3110
+ onPublish,
3111
+ onSave,
3112
+ onError,
3113
+ showPublishButton,
3114
+ autoSaveDebounceMs: _autoSaveDebounceMs
3115
+ }) => {
3116
+ const {
3117
+ page,
3118
+ states,
3119
+ saving,
3120
+ loading,
3121
+ error,
3122
+ saveDraft,
3123
+ publish,
3124
+ revertToPublished
3125
+ } = (0, import_puck_api8.usePuckPage)(pageKey);
3126
+ const latestDataRef = (0, import_react6.useRef)(null);
3127
+ const [hasUnsavedChanges, setHasUnsavedChanges] = (0, import_react6.useState)(false);
3128
+ const handleChange = (0, import_react6.useCallback)((data) => {
3129
+ latestDataRef.current = data;
3130
+ setHasUnsavedChanges(true);
3131
+ }, []);
3132
+ const handleSave = (0, import_react6.useCallback)(async () => {
3133
+ const data = latestDataRef.current;
3134
+ if (!data) return;
3135
+ try {
3136
+ await saveDraft(data);
3137
+ setHasUnsavedChanges(false);
3138
+ onSave?.(data);
3139
+ } catch (err) {
3140
+ onError?.(err);
3141
+ }
3142
+ }, [saveDraft, onSave, onError]);
3143
+ const handlePublish = (0, import_react6.useCallback)(
3144
+ async (data) => {
3145
+ try {
3146
+ await saveDraft(data);
3147
+ setHasUnsavedChanges(false);
3148
+ await publish(false);
3149
+ onPublish?.(data);
3150
+ } catch (err) {
3151
+ onError?.(err);
3152
+ }
3153
+ },
3154
+ [saveDraft, publish, onPublish, onError]
3155
+ );
3156
+ const handleRevert = (0, import_react6.useCallback)(async () => {
3157
+ try {
3158
+ await revertToPublished();
3159
+ setHasUnsavedChanges(false);
3160
+ } catch (err) {
3161
+ onError?.(err);
3162
+ }
3163
+ }, [revertToPublished, onError]);
3164
+ if (loading) {
3165
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3166
+ "div",
3167
+ {
3168
+ style: {
3169
+ display: "flex",
3170
+ alignItems: "center",
3171
+ justifyContent: "center",
3172
+ height: "100vh",
3173
+ fontSize: "16px",
3174
+ color: "var(--text-muted)",
3175
+ background: "var(--bg-void)"
3176
+ },
3177
+ children: "Loading editor\u2026"
3178
+ }
3179
+ );
3180
+ }
3181
+ if (error) {
3182
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
3183
+ "div",
3184
+ {
3185
+ style: {
3186
+ padding: "32px",
3187
+ color: "var(--status-error)",
3188
+ background: "rgba(248, 113, 113, 0.08)",
3189
+ border: "1px solid rgba(248, 113, 113, 0.25)",
3190
+ borderRadius: "8px",
3191
+ margin: "16px"
3192
+ },
3193
+ children: [
3194
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("strong", { children: "Error loading page:" }),
3195
+ " ",
3196
+ error
3197
+ ]
3198
+ }
3199
+ );
3200
+ }
3201
+ const activeData = states.draft?.puckData ?? page?.puckData ?? {
3202
+ content: [],
3203
+ root: { props: {} }
3204
+ };
3205
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ComponentSearchProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3206
+ import_puck2.Puck,
3207
+ {
3208
+ config,
3209
+ data: activeData,
3210
+ onChange: handleChange,
3211
+ onPublish: handlePublish,
3212
+ overrides: {
3213
+ headerActions: () => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3214
+ EditorToolbar,
3215
+ {
3216
+ saving,
3217
+ isDirty: hasUnsavedChanges,
3218
+ states,
3219
+ onSave: () => void handleSave(),
3220
+ onPublish: () => void handlePublish(activeData),
3221
+ onRevert: () => void handleRevert(),
3222
+ showPublishButton
3223
+ }
3224
+ ),
3225
+ components: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ComponentsPanel, { children }),
3226
+ componentItem: ({ children, name }) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ComponentItemFilter, { name, children })
3227
+ }
3228
+ }
3229
+ ) });
3230
+ };
3231
+ var PuckEditor = ({
3232
+ baseURL,
3233
+ projectKey,
3234
+ businessUnitKey,
3235
+ jwtToken,
3236
+ pageKey,
3237
+ config = defaultPuckConfig,
3238
+ onPublish,
3239
+ onSave,
3240
+ onError,
3241
+ showPublishButton = true,
3242
+ autoSaveDebounceMs = 1500
3243
+ }) => {
3244
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3245
+ import_puck_api7.PuckApiProvider,
3246
+ {
3247
+ baseURL,
3248
+ projectKey,
3249
+ businessUnitKey,
3250
+ jwtToken,
3251
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3252
+ PuckEditorInner,
3253
+ {
3254
+ pageKey,
3255
+ config,
3256
+ onPublish,
3257
+ onSave,
3258
+ onError,
3259
+ showPublishButton,
3260
+ autoSaveDebounceMs
3261
+ }
3262
+ )
3263
+ }
3264
+ );
3265
+ };
3266
+ // Annotate the CommonJS export names for ESM import in node:
3267
+ 0 && (module.exports = {
3268
+ Button,
3269
+ Card,
3270
+ CategoryGrid,
3271
+ CategoryHero,
3272
+ CheckoutPromoBanner,
3273
+ Columns,
3274
+ ComponentItemFilter,
3275
+ ComponentSearchProvider,
3276
+ ComponentsPanel,
3277
+ CountdownBanner,
3278
+ CrossSellBlock,
3279
+ DatasourceField,
3280
+ DeliveryMessage,
3281
+ Divider,
3282
+ EditorToolbar,
3283
+ EmptyState,
3284
+ FAQAccordion,
3285
+ FooterBlock,
3286
+ Hero,
3287
+ HeroBanner,
3288
+ Image,
3289
+ ImageBlock,
3290
+ ImagePickerField,
3291
+ NewsletterSignup,
3292
+ ProductBanner,
3293
+ ProductGridHeader,
3294
+ ProductSlider,
3295
+ ProductTeaser,
3296
+ PromotionalBanner,
3297
+ PuckEditor,
3298
+ RelatedProductsSlider,
3299
+ RichText,
3300
+ SocialLinks,
3301
+ Spacer,
3302
+ TabContent,
3303
+ TestimonialsSlider,
3304
+ TextBlock,
3305
+ ThankYouContent,
3306
+ TrustBadges,
3307
+ VideoBlock,
3308
+ WebsiteLogo,
3309
+ defaultPuckConfig
3310
+ });
3311
+ //# sourceMappingURL=index.js.map