@mission-studio/puck 1.0.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.
@@ -0,0 +1,1799 @@
1
+ import {
2
+ cn,
3
+ getShadowCSS,
4
+ hexToRgba,
5
+ useEntries,
6
+ useTheme
7
+ } from "./chunk-TTKY3YGP.mjs";
8
+
9
+ // components/page/Heading.tsx
10
+ import { jsx } from "react/jsx-runtime";
11
+ var sizeMap = {
12
+ xs: "0.875rem",
13
+ sm: "1rem",
14
+ md: "1.25rem",
15
+ lg: "1.5rem",
16
+ xl: "2rem",
17
+ "2xl": "2.5rem",
18
+ "3xl": "3rem",
19
+ "4xl": "4rem"
20
+ };
21
+ var weightMap = {
22
+ normal: 400,
23
+ medium: 500,
24
+ semibold: 600,
25
+ bold: 700,
26
+ extrabold: 800
27
+ };
28
+ var letterSpacingMap = {
29
+ tight: "-0.025em",
30
+ normal: "0",
31
+ wide: "0.05em"
32
+ };
33
+ var lineHeightMap = {
34
+ tight: "1.1",
35
+ normal: "1.4",
36
+ relaxed: "1.6"
37
+ };
38
+ function isThemeableValue(value) {
39
+ return typeof value === "object" && value !== null && "useTheme" in value;
40
+ }
41
+ function isEntryBoundValue(value) {
42
+ return typeof value === "object" && value !== null && "useEntry" in value;
43
+ }
44
+ function Heading({
45
+ text,
46
+ level = "h2",
47
+ size = "2xl",
48
+ weight = "bold",
49
+ color,
50
+ align = "left",
51
+ letterSpacing = "normal",
52
+ lineHeight = "tight",
53
+ id
54
+ }) {
55
+ const { resolveColor: resolveColor2 } = useTheme();
56
+ const { getEntryValue } = useEntries();
57
+ const resolvedText = (() => {
58
+ if (!text) return "";
59
+ if (typeof text === "string") return text;
60
+ if (isEntryBoundValue(text)) {
61
+ if (text.useEntry) {
62
+ return String(getEntryValue(text.entryName, text.fieldKey) ?? "");
63
+ }
64
+ return text.value;
65
+ }
66
+ return "";
67
+ })();
68
+ const resolvedColor = (() => {
69
+ if (!color) return resolveColor2("foreground");
70
+ if (typeof color === "string") return { color, opacity: 100 };
71
+ if (isThemeableValue(color)) {
72
+ return color.useTheme ? resolveColor2(color.themeKey) : color.value;
73
+ }
74
+ if ("color" in color) return color;
75
+ return resolveColor2("foreground");
76
+ })();
77
+ const Tag = level;
78
+ const style = {
79
+ fontSize: sizeMap[size],
80
+ fontWeight: weightMap[weight],
81
+ color: hexToRgba(resolvedColor.color, resolvedColor.opacity),
82
+ textAlign: align,
83
+ letterSpacing: letterSpacingMap[letterSpacing],
84
+ lineHeight: lineHeightMap[lineHeight],
85
+ margin: 0
86
+ };
87
+ if (!resolvedText) return null;
88
+ return /* @__PURE__ */ jsx(Tag, { id, style, children: resolvedText });
89
+ }
90
+
91
+ // components/page/Paragraph.tsx
92
+ import { jsx as jsx2 } from "react/jsx-runtime";
93
+ var sizeMap2 = {
94
+ sm: "0.875rem",
95
+ base: "1rem",
96
+ lg: "1.125rem",
97
+ xl: "1.25rem"
98
+ };
99
+ var weightMap2 = {
100
+ normal: 400,
101
+ medium: 500,
102
+ semibold: 600
103
+ };
104
+ var lineHeightMap2 = {
105
+ tight: "1.4",
106
+ normal: "1.6",
107
+ relaxed: "1.75",
108
+ loose: "2"
109
+ };
110
+ function isThemeableValue2(value) {
111
+ return typeof value === "object" && value !== null && "useTheme" in value;
112
+ }
113
+ function isEntryBoundValue2(value) {
114
+ return typeof value === "object" && value !== null && "useEntry" in value;
115
+ }
116
+ function Paragraph({
117
+ text,
118
+ size = "base",
119
+ weight = "normal",
120
+ color,
121
+ align = "left",
122
+ lineHeight = "normal",
123
+ maxWidth,
124
+ id
125
+ }) {
126
+ const { resolveColor: resolveColor2 } = useTheme();
127
+ const { getEntryValue } = useEntries();
128
+ const resolvedText = (() => {
129
+ if (!text) return "";
130
+ if (typeof text === "string") return text;
131
+ if (isEntryBoundValue2(text)) {
132
+ if (text.useEntry) {
133
+ return String(getEntryValue(text.entryName, text.fieldKey) ?? "");
134
+ }
135
+ return text.value;
136
+ }
137
+ return "";
138
+ })();
139
+ const resolvedColor = (() => {
140
+ if (!color) return resolveColor2("foreground");
141
+ if (typeof color === "string") return { color, opacity: 100 };
142
+ if (isThemeableValue2(color)) {
143
+ return color.useTheme ? resolveColor2(color.themeKey) : color.value;
144
+ }
145
+ if ("color" in color) return color;
146
+ return resolveColor2("foreground");
147
+ })();
148
+ const style = {
149
+ fontSize: sizeMap2[size],
150
+ fontWeight: weightMap2[weight],
151
+ color: hexToRgba(resolvedColor.color, resolvedColor.opacity),
152
+ textAlign: align,
153
+ lineHeight: lineHeightMap2[lineHeight],
154
+ maxWidth: maxWidth || void 0,
155
+ margin: 0
156
+ };
157
+ if (!resolvedText) return null;
158
+ return /* @__PURE__ */ jsx2("p", { id, style, children: resolvedText });
159
+ }
160
+
161
+ // components/page/Button.tsx
162
+ import { jsx as jsx3 } from "react/jsx-runtime";
163
+ var sizeStyles = {
164
+ sm: { padding: "8px 16px", fontSize: "0.875rem" },
165
+ md: { padding: "12px 24px", fontSize: "1rem" },
166
+ lg: { padding: "16px 32px", fontSize: "1.125rem" },
167
+ xl: { padding: "20px 40px", fontSize: "1.25rem" }
168
+ };
169
+ var radiusMap = {
170
+ none: "0",
171
+ sm: "4px",
172
+ md: "8px",
173
+ lg: "16px",
174
+ full: "9999px"
175
+ };
176
+ function isThemeableValue3(value) {
177
+ return typeof value === "object" && value !== null && "useTheme" in value;
178
+ }
179
+ function isEntryBoundValue3(value) {
180
+ return typeof value === "object" && value !== null && "useEntry" in value;
181
+ }
182
+ function Button({
183
+ text,
184
+ href,
185
+ target = "_self",
186
+ variant = "solid",
187
+ size = "md",
188
+ color,
189
+ textColor,
190
+ borderRadius = "md",
191
+ fullWidth = false,
192
+ align = "center",
193
+ id
194
+ }) {
195
+ const { resolveColor: resolveColor2 } = useTheme();
196
+ const { getEntryValue } = useEntries();
197
+ const resolvedText = (() => {
198
+ if (!text) return "Button";
199
+ if (typeof text === "string") return text;
200
+ if (isEntryBoundValue3(text)) {
201
+ if (text.useEntry) {
202
+ return String(getEntryValue(text.entryName, text.fieldKey) ?? "Button");
203
+ }
204
+ return text.value;
205
+ }
206
+ return "Button";
207
+ })();
208
+ const resolvedColor = (() => {
209
+ if (!color) return resolveColor2("primary");
210
+ if (typeof color === "string") return { color, opacity: 100 };
211
+ if (isThemeableValue3(color)) {
212
+ return color.useTheme ? resolveColor2(color.themeKey) : color.value;
213
+ }
214
+ if ("color" in color) return color;
215
+ return resolveColor2("primary");
216
+ })();
217
+ const resolvedTextColor = (() => {
218
+ if (!textColor) {
219
+ if (variant === "solid") return { color: "#FFFFFF", opacity: 100 };
220
+ return resolvedColor;
221
+ }
222
+ if (typeof textColor === "string")
223
+ return { color: textColor, opacity: 100 };
224
+ if (isThemeableValue3(textColor)) {
225
+ return textColor.useTheme ? resolveColor2(textColor.themeKey) : textColor.value;
226
+ }
227
+ if ("color" in textColor) return textColor;
228
+ return { color: "#FFFFFF", opacity: 100 };
229
+ })();
230
+ const bgColor = hexToRgba(resolvedColor.color, resolvedColor.opacity);
231
+ const fgColor = hexToRgba(resolvedTextColor.color, resolvedTextColor.opacity);
232
+ const baseStyle = {
233
+ ...sizeStyles[size],
234
+ borderRadius: radiusMap[borderRadius],
235
+ fontWeight: 600,
236
+ cursor: "pointer",
237
+ display: "inline-flex",
238
+ alignItems: "center",
239
+ justifyContent: "center",
240
+ textDecoration: "none",
241
+ transition: "opacity 0.2s, transform 0.2s",
242
+ width: fullWidth ? "100%" : "auto",
243
+ border: "none"
244
+ };
245
+ const variantStyles = {
246
+ solid: {
247
+ backgroundColor: bgColor,
248
+ color: fgColor
249
+ },
250
+ outline: {
251
+ backgroundColor: "transparent",
252
+ color: bgColor,
253
+ border: `2px solid ${bgColor}`
254
+ },
255
+ ghost: {
256
+ backgroundColor: "transparent",
257
+ color: bgColor
258
+ },
259
+ link: {
260
+ backgroundColor: "transparent",
261
+ color: bgColor,
262
+ padding: "0",
263
+ textDecoration: "underline"
264
+ }
265
+ };
266
+ const style = { ...baseStyle, ...variantStyles[variant] };
267
+ const wrapperStyle = {
268
+ display: "flex",
269
+ justifyContent: align === "left" ? "flex-start" : align === "right" ? "flex-end" : "center"
270
+ };
271
+ const content = /* @__PURE__ */ jsx3("span", { style, children: resolvedText });
272
+ if (href) {
273
+ return /* @__PURE__ */ jsx3("div", { style: wrapperStyle, children: /* @__PURE__ */ jsx3(
274
+ "a",
275
+ {
276
+ id,
277
+ href,
278
+ target,
279
+ style,
280
+ rel: target === "_blank" ? "noopener noreferrer" : void 0,
281
+ children: resolvedText
282
+ }
283
+ ) });
284
+ }
285
+ return /* @__PURE__ */ jsx3("div", { style: wrapperStyle, children: /* @__PURE__ */ jsx3("button", { id, type: "button", style, children: resolvedText }) });
286
+ }
287
+
288
+ // components/page/Image.tsx
289
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
290
+ var widthMap = {
291
+ auto: "auto",
292
+ full: "100%",
293
+ sm: "300px",
294
+ md: "500px",
295
+ lg: "700px",
296
+ xl: "900px"
297
+ };
298
+ var aspectRatioMap = {
299
+ auto: void 0,
300
+ "1:1": "1 / 1",
301
+ "4:3": "4 / 3",
302
+ "16:9": "16 / 9",
303
+ "21:9": "21 / 9"
304
+ };
305
+ var radiusMap2 = {
306
+ none: "0",
307
+ sm: "4px",
308
+ md: "8px",
309
+ lg: "16px",
310
+ xl: "24px",
311
+ full: "9999px"
312
+ };
313
+ var shadowMap = {
314
+ none: "none",
315
+ sm: "0 1px 2px rgba(0,0,0,0.05)",
316
+ md: "0 4px 6px rgba(0,0,0,0.1)",
317
+ lg: "0 10px 15px rgba(0,0,0,0.1)",
318
+ xl: "0 20px 25px rgba(0,0,0,0.15)"
319
+ };
320
+ function isThemeableValue4(value) {
321
+ return typeof value === "object" && value !== null && "useTheme" in value;
322
+ }
323
+ function isEntryBoundValue4(value) {
324
+ return typeof value === "object" && value !== null && "useEntry" in value;
325
+ }
326
+ function Image({
327
+ src,
328
+ alt = "",
329
+ width = "full",
330
+ aspectRatio = "auto",
331
+ objectFit = "cover",
332
+ borderRadius = "none",
333
+ shadow = "none",
334
+ align = "center",
335
+ caption,
336
+ captionColor,
337
+ id
338
+ }) {
339
+ const { resolveColor: resolveColor2 } = useTheme();
340
+ const { getEntryValue } = useEntries();
341
+ const resolvedSrc = (() => {
342
+ if (!src) return "";
343
+ if (typeof src === "string") return src;
344
+ if (isEntryBoundValue4(src)) {
345
+ if (src.useEntry) {
346
+ return String(getEntryValue(src.entryName, src.fieldKey) ?? "");
347
+ }
348
+ return src.value;
349
+ }
350
+ return "";
351
+ })();
352
+ const resolvedCaption = (() => {
353
+ if (!caption) return "";
354
+ if (typeof caption === "string") return caption;
355
+ if (isEntryBoundValue4(caption)) {
356
+ if (caption.useEntry) {
357
+ return String(getEntryValue(caption.entryName, caption.fieldKey) ?? "");
358
+ }
359
+ return caption.value;
360
+ }
361
+ return "";
362
+ })();
363
+ const resolvedCaptionColor = (() => {
364
+ if (!captionColor) return resolveColor2("muted");
365
+ if (typeof captionColor === "string")
366
+ return { color: captionColor, opacity: 100 };
367
+ if (isThemeableValue4(captionColor)) {
368
+ return captionColor.useTheme ? resolveColor2(captionColor.themeKey) : captionColor.value;
369
+ }
370
+ if ("color" in captionColor) return captionColor;
371
+ return resolveColor2("muted");
372
+ })();
373
+ const wrapperStyle = {
374
+ display: "flex",
375
+ flexDirection: "column",
376
+ alignItems: align === "left" ? "flex-start" : align === "right" ? "flex-end" : "center",
377
+ gap: "8px"
378
+ };
379
+ const imageStyle = {
380
+ width: widthMap[width],
381
+ maxWidth: "100%",
382
+ aspectRatio: aspectRatioMap[aspectRatio],
383
+ objectFit,
384
+ borderRadius: radiusMap2[borderRadius],
385
+ boxShadow: shadowMap[shadow],
386
+ display: "block"
387
+ };
388
+ const captionStyle = {
389
+ fontSize: "0.875rem",
390
+ color: hexToRgba(resolvedCaptionColor.color, resolvedCaptionColor.opacity),
391
+ textAlign: align,
392
+ maxWidth: widthMap[width]
393
+ };
394
+ if (!resolvedSrc) {
395
+ return /* @__PURE__ */ jsx4("div", { style: wrapperStyle, children: /* @__PURE__ */ jsx4(
396
+ "div",
397
+ {
398
+ style: {
399
+ ...imageStyle,
400
+ backgroundColor: "#e5e7eb",
401
+ display: "flex",
402
+ alignItems: "center",
403
+ justifyContent: "center",
404
+ minHeight: "200px",
405
+ color: "#9ca3af"
406
+ },
407
+ children: "No image"
408
+ }
409
+ ) });
410
+ }
411
+ return /* @__PURE__ */ jsxs("figure", { id, style: { ...wrapperStyle, margin: 0 }, children: [
412
+ /* @__PURE__ */ jsx4("img", { src: resolvedSrc, alt, style: imageStyle, loading: "lazy" }),
413
+ resolvedCaption && /* @__PURE__ */ jsx4("figcaption", { style: captionStyle, children: resolvedCaption })
414
+ ] });
415
+ }
416
+
417
+ // components/page/ImageCarousel.tsx
418
+ import { useState } from "react";
419
+ import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
420
+ var aspectRatioMap2 = {
421
+ "16:9": "16 / 9",
422
+ "4:3": "4 / 3",
423
+ "1:1": "1 / 1",
424
+ "21:9": "21 / 9"
425
+ };
426
+ var radiusMap3 = {
427
+ none: "0",
428
+ sm: "4px",
429
+ md: "8px",
430
+ lg: "16px"
431
+ };
432
+ function isThemeableValue5(value) {
433
+ return typeof value === "object" && value !== null && "useTheme" in value;
434
+ }
435
+ function ImageCarousel({
436
+ images = [],
437
+ aspectRatio = "16:9",
438
+ borderRadius = "none",
439
+ showDots = true,
440
+ showArrows = true,
441
+ arrowColor,
442
+ dotColor,
443
+ id
444
+ }) {
445
+ const [currentIndex, setCurrentIndex] = useState(0);
446
+ const { resolveColor: resolveColor2 } = useTheme();
447
+ const resolvedArrowColor = (() => {
448
+ if (!arrowColor) return { color: "#FFFFFF", opacity: 100 };
449
+ if (typeof arrowColor === "string")
450
+ return { color: arrowColor, opacity: 100 };
451
+ if (isThemeableValue5(arrowColor)) {
452
+ return arrowColor.useTheme ? resolveColor2(arrowColor.themeKey) : arrowColor.value;
453
+ }
454
+ if ("color" in arrowColor) return arrowColor;
455
+ return { color: "#FFFFFF", opacity: 100 };
456
+ })();
457
+ const resolvedDotColor = (() => {
458
+ if (!dotColor) return resolveColor2("primary");
459
+ if (typeof dotColor === "string") return { color: dotColor, opacity: 100 };
460
+ if (isThemeableValue5(dotColor)) {
461
+ return dotColor.useTheme ? resolveColor2(dotColor.themeKey) : dotColor.value;
462
+ }
463
+ if ("color" in dotColor) return dotColor;
464
+ return resolveColor2("primary");
465
+ })();
466
+ const goToPrevious = () => {
467
+ setCurrentIndex((prev) => prev === 0 ? images.length - 1 : prev - 1);
468
+ };
469
+ const goToNext = () => {
470
+ setCurrentIndex((prev) => prev === images.length - 1 ? 0 : prev + 1);
471
+ };
472
+ const goToSlide = (index) => {
473
+ setCurrentIndex(index);
474
+ };
475
+ if (images.length === 0) {
476
+ return /* @__PURE__ */ jsx5(
477
+ "div",
478
+ {
479
+ style: {
480
+ aspectRatio: aspectRatioMap2[aspectRatio],
481
+ backgroundColor: "#e5e7eb",
482
+ borderRadius: radiusMap3[borderRadius],
483
+ display: "flex",
484
+ alignItems: "center",
485
+ justifyContent: "center",
486
+ color: "#9ca3af"
487
+ },
488
+ children: "No images"
489
+ }
490
+ );
491
+ }
492
+ const containerStyle = {
493
+ position: "relative",
494
+ aspectRatio: aspectRatioMap2[aspectRatio],
495
+ borderRadius: radiusMap3[borderRadius],
496
+ overflow: "hidden"
497
+ };
498
+ const slideContainerStyle = {
499
+ display: "flex",
500
+ transition: "transform 0.3s ease-in-out",
501
+ transform: `translateX(-${currentIndex * 100}%)`,
502
+ height: "100%"
503
+ };
504
+ const slideStyle = {
505
+ minWidth: "100%",
506
+ height: "100%"
507
+ };
508
+ const imageStyle = {
509
+ width: "100%",
510
+ height: "100%",
511
+ objectFit: "cover"
512
+ };
513
+ const arrowStyle = {
514
+ position: "absolute",
515
+ top: "50%",
516
+ transform: "translateY(-50%)",
517
+ backgroundColor: "rgba(0,0,0,0.5)",
518
+ color: hexToRgba(resolvedArrowColor.color, resolvedArrowColor.opacity),
519
+ border: "none",
520
+ borderRadius: "50%",
521
+ width: "40px",
522
+ height: "40px",
523
+ cursor: "pointer",
524
+ display: "flex",
525
+ alignItems: "center",
526
+ justifyContent: "center",
527
+ fontSize: "20px",
528
+ zIndex: 1
529
+ };
530
+ const dotsContainerStyle = {
531
+ position: "absolute",
532
+ bottom: "16px",
533
+ left: "50%",
534
+ transform: "translateX(-50%)",
535
+ display: "flex",
536
+ gap: "8px",
537
+ zIndex: 1
538
+ };
539
+ const dotStyle = (isActive) => ({
540
+ width: "10px",
541
+ height: "10px",
542
+ borderRadius: "50%",
543
+ border: "none",
544
+ cursor: "pointer",
545
+ backgroundColor: isActive ? hexToRgba(resolvedDotColor.color, resolvedDotColor.opacity) : "rgba(255,255,255,0.5)"
546
+ });
547
+ return /* @__PURE__ */ jsxs2("div", { id, style: containerStyle, children: [
548
+ /* @__PURE__ */ jsx5("div", { style: slideContainerStyle, children: images.map((image, index) => /* @__PURE__ */ jsx5("div", { style: slideStyle, children: /* @__PURE__ */ jsx5(
549
+ "img",
550
+ {
551
+ src: image.src,
552
+ alt: image.alt || "",
553
+ style: imageStyle,
554
+ loading: "lazy"
555
+ }
556
+ ) }, index)) }),
557
+ showArrows && images.length > 1 && /* @__PURE__ */ jsxs2(Fragment, { children: [
558
+ /* @__PURE__ */ jsx5(
559
+ "button",
560
+ {
561
+ type: "button",
562
+ onClick: goToPrevious,
563
+ style: { ...arrowStyle, left: "16px" },
564
+ "aria-label": "Previous slide",
565
+ children: "\u2039"
566
+ }
567
+ ),
568
+ /* @__PURE__ */ jsx5(
569
+ "button",
570
+ {
571
+ type: "button",
572
+ onClick: goToNext,
573
+ style: { ...arrowStyle, right: "16px" },
574
+ "aria-label": "Next slide",
575
+ children: "\u203A"
576
+ }
577
+ )
578
+ ] }),
579
+ showDots && images.length > 1 && /* @__PURE__ */ jsx5("div", { style: dotsContainerStyle, children: images.map((_, index) => /* @__PURE__ */ jsx5(
580
+ "button",
581
+ {
582
+ type: "button",
583
+ onClick: () => goToSlide(index),
584
+ style: dotStyle(index === currentIndex),
585
+ "aria-label": `Go to slide ${index + 1}`
586
+ },
587
+ index
588
+ )) })
589
+ ] });
590
+ }
591
+
592
+ // components/page/VideoEmbed.tsx
593
+ import { jsx as jsx6 } from "react/jsx-runtime";
594
+ var aspectRatioMap3 = {
595
+ "16:9": "56.25%",
596
+ // 9/16 * 100
597
+ "4:3": "75%",
598
+ "1:1": "100%",
599
+ "21:9": "42.86%"
600
+ };
601
+ var radiusMap4 = {
602
+ none: "0",
603
+ sm: "4px",
604
+ md: "8px",
605
+ lg: "16px"
606
+ };
607
+ var maxWidthMap = {
608
+ sm: "400px",
609
+ md: "600px",
610
+ lg: "800px",
611
+ xl: "1000px",
612
+ full: "100%"
613
+ };
614
+ function isEntryBoundValue5(value) {
615
+ return typeof value === "object" && value !== null && "useEntry" in value;
616
+ }
617
+ function parseVideoUrl(url) {
618
+ const ytMatch = url.match(
619
+ /(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/
620
+ );
621
+ if (ytMatch) {
622
+ return {
623
+ type: "youtube",
624
+ embedUrl: `https://www.youtube.com/embed/${ytMatch[1]}`
625
+ };
626
+ }
627
+ const vimeoMatch = url.match(/(?:vimeo\.com\/)(\d+)/);
628
+ if (vimeoMatch) {
629
+ return {
630
+ type: "vimeo",
631
+ embedUrl: `https://player.vimeo.com/video/${vimeoMatch[1]}`
632
+ };
633
+ }
634
+ return { type: "unknown", embedUrl: url };
635
+ }
636
+ function VideoEmbed({
637
+ url,
638
+ aspectRatio = "16:9",
639
+ borderRadius = "none",
640
+ autoplay = false,
641
+ muted = false,
642
+ loop = false,
643
+ align = "center",
644
+ maxWidth = "full",
645
+ id
646
+ }) {
647
+ const { getEntryValue } = useEntries();
648
+ const resolvedUrl = (() => {
649
+ if (!url) return "";
650
+ if (typeof url === "string") return url;
651
+ if (isEntryBoundValue5(url)) {
652
+ if (url.useEntry) {
653
+ return String(getEntryValue(url.entryName, url.fieldKey) ?? "");
654
+ }
655
+ return url.value;
656
+ }
657
+ return "";
658
+ })();
659
+ if (!resolvedUrl) {
660
+ return /* @__PURE__ */ jsx6(
661
+ "div",
662
+ {
663
+ style: {
664
+ backgroundColor: "#1f2937",
665
+ borderRadius: radiusMap4[borderRadius],
666
+ aspectRatio: aspectRatio.replace(":", " / "),
667
+ display: "flex",
668
+ alignItems: "center",
669
+ justifyContent: "center",
670
+ color: "#9ca3af",
671
+ maxWidth: maxWidthMap[maxWidth],
672
+ marginLeft: align === "center" ? "auto" : align === "right" ? "auto" : void 0,
673
+ marginRight: align === "center" ? "auto" : align === "left" ? "auto" : void 0
674
+ },
675
+ children: "No video URL"
676
+ }
677
+ );
678
+ }
679
+ const { embedUrl } = parseVideoUrl(resolvedUrl);
680
+ const params = new URLSearchParams();
681
+ if (autoplay) params.set("autoplay", "1");
682
+ if (muted) params.set("mute", "1");
683
+ if (loop) params.set("loop", "1");
684
+ const finalUrl = params.toString() ? `${embedUrl}?${params.toString()}` : embedUrl;
685
+ const wrapperStyle = {
686
+ display: "flex",
687
+ justifyContent: align === "left" ? "flex-start" : align === "right" ? "flex-end" : "center"
688
+ };
689
+ const containerStyle = {
690
+ position: "relative",
691
+ width: "100%",
692
+ maxWidth: maxWidthMap[maxWidth],
693
+ paddingBottom: aspectRatioMap3[aspectRatio],
694
+ borderRadius: radiusMap4[borderRadius],
695
+ overflow: "hidden"
696
+ };
697
+ const iframeStyle = {
698
+ position: "absolute",
699
+ top: 0,
700
+ left: 0,
701
+ width: "100%",
702
+ height: "100%",
703
+ border: "none"
704
+ };
705
+ return /* @__PURE__ */ jsx6("div", { id, style: wrapperStyle, children: /* @__PURE__ */ jsx6("div", { style: containerStyle, children: /* @__PURE__ */ jsx6(
706
+ "iframe",
707
+ {
708
+ src: finalUrl,
709
+ style: iframeStyle,
710
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
711
+ allowFullScreen: true,
712
+ loading: "lazy"
713
+ }
714
+ ) }) });
715
+ }
716
+
717
+ // components/page/Icon.tsx
718
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
719
+ var sizeMap3 = {
720
+ sm: { size: "16px", strokeWidth: 2 },
721
+ md: { size: "24px", strokeWidth: 2 },
722
+ lg: { size: "32px", strokeWidth: 1.5 },
723
+ xl: { size: "48px", strokeWidth: 1.5 },
724
+ "2xl": { size: "64px", strokeWidth: 1.5 }
725
+ };
726
+ var icons = {
727
+ check: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsx7(
728
+ "svg",
729
+ {
730
+ width: size,
731
+ height: size,
732
+ viewBox: "0 0 24 24",
733
+ fill: "none",
734
+ stroke: color,
735
+ strokeWidth,
736
+ strokeLinecap: "round",
737
+ strokeLinejoin: "round",
738
+ children: /* @__PURE__ */ jsx7("polyline", { points: "20 6 9 17 4 12" })
739
+ }
740
+ ),
741
+ x: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsxs3(
742
+ "svg",
743
+ {
744
+ width: size,
745
+ height: size,
746
+ viewBox: "0 0 24 24",
747
+ fill: "none",
748
+ stroke: color,
749
+ strokeWidth,
750
+ strokeLinecap: "round",
751
+ strokeLinejoin: "round",
752
+ children: [
753
+ /* @__PURE__ */ jsx7("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
754
+ /* @__PURE__ */ jsx7("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
755
+ ]
756
+ }
757
+ ),
758
+ star: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsx7(
759
+ "svg",
760
+ {
761
+ width: size,
762
+ height: size,
763
+ viewBox: "0 0 24 24",
764
+ fill: color,
765
+ stroke: color,
766
+ strokeWidth,
767
+ strokeLinecap: "round",
768
+ strokeLinejoin: "round",
769
+ children: /* @__PURE__ */ jsx7("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" })
770
+ }
771
+ ),
772
+ heart: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsx7(
773
+ "svg",
774
+ {
775
+ width: size,
776
+ height: size,
777
+ viewBox: "0 0 24 24",
778
+ fill: "none",
779
+ stroke: color,
780
+ strokeWidth,
781
+ strokeLinecap: "round",
782
+ strokeLinejoin: "round",
783
+ children: /* @__PURE__ */ jsx7("path", { d: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" })
784
+ }
785
+ ),
786
+ arrowRight: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsxs3(
787
+ "svg",
788
+ {
789
+ width: size,
790
+ height: size,
791
+ viewBox: "0 0 24 24",
792
+ fill: "none",
793
+ stroke: color,
794
+ strokeWidth,
795
+ strokeLinecap: "round",
796
+ strokeLinejoin: "round",
797
+ children: [
798
+ /* @__PURE__ */ jsx7("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
799
+ /* @__PURE__ */ jsx7("polyline", { points: "12 5 19 12 12 19" })
800
+ ]
801
+ }
802
+ ),
803
+ arrowLeft: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsxs3(
804
+ "svg",
805
+ {
806
+ width: size,
807
+ height: size,
808
+ viewBox: "0 0 24 24",
809
+ fill: "none",
810
+ stroke: color,
811
+ strokeWidth,
812
+ strokeLinecap: "round",
813
+ strokeLinejoin: "round",
814
+ children: [
815
+ /* @__PURE__ */ jsx7("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
816
+ /* @__PURE__ */ jsx7("polyline", { points: "12 19 5 12 12 5" })
817
+ ]
818
+ }
819
+ ),
820
+ mail: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsxs3(
821
+ "svg",
822
+ {
823
+ width: size,
824
+ height: size,
825
+ viewBox: "0 0 24 24",
826
+ fill: "none",
827
+ stroke: color,
828
+ strokeWidth,
829
+ strokeLinecap: "round",
830
+ strokeLinejoin: "round",
831
+ children: [
832
+ /* @__PURE__ */ jsx7("path", { d: "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" }),
833
+ /* @__PURE__ */ jsx7("polyline", { points: "22,6 12,13 2,6" })
834
+ ]
835
+ }
836
+ ),
837
+ phone: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsx7(
838
+ "svg",
839
+ {
840
+ width: size,
841
+ height: size,
842
+ viewBox: "0 0 24 24",
843
+ fill: "none",
844
+ stroke: color,
845
+ strokeWidth,
846
+ strokeLinecap: "round",
847
+ strokeLinejoin: "round",
848
+ children: /* @__PURE__ */ jsx7("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" })
849
+ }
850
+ ),
851
+ mapPin: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsxs3(
852
+ "svg",
853
+ {
854
+ width: size,
855
+ height: size,
856
+ viewBox: "0 0 24 24",
857
+ fill: "none",
858
+ stroke: color,
859
+ strokeWidth,
860
+ strokeLinecap: "round",
861
+ strokeLinejoin: "round",
862
+ children: [
863
+ /* @__PURE__ */ jsx7("path", { d: "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" }),
864
+ /* @__PURE__ */ jsx7("circle", { cx: "12", cy: "10", r: "3" })
865
+ ]
866
+ }
867
+ ),
868
+ zap: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsx7(
869
+ "svg",
870
+ {
871
+ width: size,
872
+ height: size,
873
+ viewBox: "0 0 24 24",
874
+ fill: "none",
875
+ stroke: color,
876
+ strokeWidth,
877
+ strokeLinecap: "round",
878
+ strokeLinejoin: "round",
879
+ children: /* @__PURE__ */ jsx7("polygon", { points: "13 2 3 14 12 14 11 22 21 10 12 10 13 2" })
880
+ }
881
+ ),
882
+ shield: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsx7(
883
+ "svg",
884
+ {
885
+ width: size,
886
+ height: size,
887
+ viewBox: "0 0 24 24",
888
+ fill: "none",
889
+ stroke: color,
890
+ strokeWidth,
891
+ strokeLinecap: "round",
892
+ strokeLinejoin: "round",
893
+ children: /* @__PURE__ */ jsx7("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" })
894
+ }
895
+ ),
896
+ users: ({ size, color, strokeWidth }) => /* @__PURE__ */ jsxs3(
897
+ "svg",
898
+ {
899
+ width: size,
900
+ height: size,
901
+ viewBox: "0 0 24 24",
902
+ fill: "none",
903
+ stroke: color,
904
+ strokeWidth,
905
+ strokeLinecap: "round",
906
+ strokeLinejoin: "round",
907
+ children: [
908
+ /* @__PURE__ */ jsx7("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }),
909
+ /* @__PURE__ */ jsx7("circle", { cx: "9", cy: "7", r: "4" }),
910
+ /* @__PURE__ */ jsx7("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87" }),
911
+ /* @__PURE__ */ jsx7("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })
912
+ ]
913
+ }
914
+ )
915
+ };
916
+ function isThemeableValue6(value) {
917
+ return typeof value === "object" && value !== null && "useTheme" in value;
918
+ }
919
+ function Icon({
920
+ name = "check",
921
+ size = "md",
922
+ color,
923
+ align = "center",
924
+ id
925
+ }) {
926
+ const { resolveColor: resolveColor2 } = useTheme();
927
+ const resolvedColor = (() => {
928
+ if (!color) return resolveColor2("primary");
929
+ if (typeof color === "string") return { color, opacity: 100 };
930
+ if (isThemeableValue6(color)) {
931
+ return color.useTheme ? resolveColor2(color.themeKey) : color.value;
932
+ }
933
+ if ("color" in color) return color;
934
+ return resolveColor2("primary");
935
+ })();
936
+ const IconComponent = icons[name.toLowerCase()] || icons.check;
937
+ const { size: iconSize, strokeWidth } = sizeMap3[size];
938
+ const colorValue = hexToRgba(resolvedColor.color, resolvedColor.opacity);
939
+ const wrapperStyle = {
940
+ display: "flex",
941
+ justifyContent: align === "left" ? "flex-start" : align === "right" ? "flex-end" : "center"
942
+ };
943
+ return /* @__PURE__ */ jsx7("div", { id, style: wrapperStyle, children: /* @__PURE__ */ jsx7(
944
+ IconComponent,
945
+ {
946
+ size: iconSize,
947
+ color: colorValue,
948
+ strokeWidth
949
+ }
950
+ ) });
951
+ }
952
+ var availableIcons = Object.keys(icons);
953
+
954
+ // components/page/Section.tsx
955
+ import { jsx as jsx8 } from "react/jsx-runtime";
956
+ function isThemeableValue7(value) {
957
+ return typeof value === "object" && value !== null && "useTheme" in value;
958
+ }
959
+ function resolveBackgroundColor(bg, resolveColor2) {
960
+ if (!bg) return void 0;
961
+ if (typeof bg === "string") return bg;
962
+ if (isThemeableValue7(bg)) {
963
+ if (bg.useTheme) {
964
+ const themeColor = resolveColor2(bg.themeKey);
965
+ return hexToRgba(themeColor.color, themeColor.opacity);
966
+ }
967
+ return hexToRgba(bg.value.color, bg.value.opacity);
968
+ }
969
+ if ("color" in bg && "opacity" in bg) {
970
+ return hexToRgba(bg.color, bg.opacity);
971
+ }
972
+ return void 0;
973
+ }
974
+ function getVisibilityClasses(visibility) {
975
+ if (!visibility) return "";
976
+ if (!visibility.mobile && !visibility.desktop) {
977
+ return "hidden";
978
+ }
979
+ if (!visibility.mobile && visibility.desktop) {
980
+ return "hidden md:block";
981
+ }
982
+ if (visibility.mobile && !visibility.desktop) {
983
+ return "md:hidden";
984
+ }
985
+ return "";
986
+ }
987
+ function Section({
988
+ children: _children,
989
+ verticalPadding = 48,
990
+ horizontalPadding = 32,
991
+ gap = 24,
992
+ backgroundColor,
993
+ backgroundImage,
994
+ shadow = "none",
995
+ borderRadius = 0,
996
+ contentMaxWidth = "1400px",
997
+ anchorLink,
998
+ visibility,
999
+ puck
1000
+ }) {
1001
+ const { resolveColor: resolveColor2 } = useTheme();
1002
+ const DropZone = puck?.renderDropZone;
1003
+ return /* @__PURE__ */ jsx8(
1004
+ "section",
1005
+ {
1006
+ id: anchorLink,
1007
+ className: cn("flex w-full flex-col", getVisibilityClasses(visibility)),
1008
+ style: {
1009
+ padding: `${verticalPadding}px ${horizontalPadding}px`,
1010
+ gap: `${gap}px`,
1011
+ backgroundColor: resolveBackgroundColor(backgroundColor, resolveColor2),
1012
+ backgroundImage: backgroundImage ? `url(${backgroundImage})` : void 0,
1013
+ backgroundSize: "cover",
1014
+ backgroundPosition: "center",
1015
+ boxShadow: getShadowCSS(shadow),
1016
+ borderRadius: `${borderRadius}px`
1017
+ },
1018
+ children: /* @__PURE__ */ jsx8("div", { className: "mx-auto w-full", style: { maxWidth: contentMaxWidth }, children: DropZone && /* @__PURE__ */ jsx8(DropZone, { zone: "content" }) })
1019
+ }
1020
+ );
1021
+ }
1022
+
1023
+ // components/page/Container.tsx
1024
+ import { jsx as jsx9 } from "react/jsx-runtime";
1025
+ var maxWidthMap2 = {
1026
+ sm: "640px",
1027
+ md: "768px",
1028
+ lg: "1024px",
1029
+ xl: "1280px",
1030
+ "2xl": "1536px",
1031
+ full: "100%"
1032
+ };
1033
+ var paddingMap = {
1034
+ none: "0",
1035
+ sm: "16px",
1036
+ md: "24px",
1037
+ lg: "32px",
1038
+ xl: "48px"
1039
+ };
1040
+ function isThemeableValue8(value) {
1041
+ return typeof value === "object" && value !== null && "useTheme" in value;
1042
+ }
1043
+ function Container({
1044
+ maxWidth = "lg",
1045
+ padding,
1046
+ paddingX = "md",
1047
+ paddingY = "none",
1048
+ backgroundColor,
1049
+ centered = true,
1050
+ id,
1051
+ puck
1052
+ }) {
1053
+ const { resolveColor: resolveColor2 } = useTheme();
1054
+ const DropZone = puck?.renderDropZone;
1055
+ const resolvedBgColor = (() => {
1056
+ if (!backgroundColor) return null;
1057
+ if (typeof backgroundColor === "string")
1058
+ return { color: backgroundColor, opacity: 100 };
1059
+ if (isThemeableValue8(backgroundColor)) {
1060
+ return backgroundColor.useTheme ? resolveColor2(backgroundColor.themeKey) : backgroundColor.value;
1061
+ }
1062
+ if ("color" in backgroundColor) return backgroundColor;
1063
+ return null;
1064
+ })();
1065
+ const effectivePaddingX = padding || paddingX;
1066
+ const effectivePaddingY = padding || paddingY;
1067
+ const style = {
1068
+ maxWidth: maxWidthMap2[maxWidth],
1069
+ marginLeft: centered ? "auto" : void 0,
1070
+ marginRight: centered ? "auto" : void 0,
1071
+ paddingLeft: paddingMap[effectivePaddingX],
1072
+ paddingRight: paddingMap[effectivePaddingX],
1073
+ paddingTop: paddingMap[effectivePaddingY],
1074
+ paddingBottom: paddingMap[effectivePaddingY],
1075
+ backgroundColor: resolvedBgColor ? hexToRgba(resolvedBgColor.color, resolvedBgColor.opacity) : void 0,
1076
+ width: "100%"
1077
+ };
1078
+ return /* @__PURE__ */ jsx9("div", { id, style, children: DropZone && /* @__PURE__ */ jsx9(DropZone, { zone: "container-content" }) });
1079
+ }
1080
+
1081
+ // components/page/Columns.tsx
1082
+ import { jsx as jsx10 } from "react/jsx-runtime";
1083
+ var gapMap = {
1084
+ none: "0",
1085
+ sm: "16px",
1086
+ md: "24px",
1087
+ lg: "32px",
1088
+ xl: "48px"
1089
+ };
1090
+ var alignMap = {
1091
+ top: "flex-start",
1092
+ center: "center",
1093
+ bottom: "flex-end",
1094
+ stretch: "stretch"
1095
+ };
1096
+ function Columns({
1097
+ columns = 2,
1098
+ gap = "md",
1099
+ verticalAlign = "top",
1100
+ stackOnMobile = true,
1101
+ id,
1102
+ puck
1103
+ }) {
1104
+ const DropZone = puck?.renderDropZone;
1105
+ const containerStyle = {
1106
+ display: "grid",
1107
+ gridTemplateColumns: `repeat(${columns}, 1fr)`,
1108
+ gap: gapMap[gap],
1109
+ alignItems: alignMap[verticalAlign]
1110
+ };
1111
+ return /* @__PURE__ */ jsx10("div", { id, style: containerStyle, children: Array.from({ length: columns }).map((_, index) => /* @__PURE__ */ jsx10("div", { style: { minWidth: 0 }, children: DropZone && /* @__PURE__ */ jsx10(DropZone, { zone: `column-${index}` }) }, index)) });
1112
+ }
1113
+
1114
+ // components/page/Card.tsx
1115
+ import { jsx as jsx11 } from "react/jsx-runtime";
1116
+ var borderWidthMap = {
1117
+ none: "0",
1118
+ thin: "1px",
1119
+ medium: "2px",
1120
+ thick: "4px"
1121
+ };
1122
+ var radiusMap5 = {
1123
+ none: "0",
1124
+ sm: "4px",
1125
+ md: "8px",
1126
+ lg: "16px",
1127
+ xl: "24px"
1128
+ };
1129
+ var shadowMap2 = {
1130
+ none: "none",
1131
+ sm: "0 1px 2px rgba(0,0,0,0.05)",
1132
+ md: "0 4px 6px rgba(0,0,0,0.1)",
1133
+ lg: "0 10px 15px rgba(0,0,0,0.1)",
1134
+ xl: "0 20px 25px rgba(0,0,0,0.15)"
1135
+ };
1136
+ var paddingMap2 = {
1137
+ none: "0",
1138
+ sm: "16px",
1139
+ md: "24px",
1140
+ lg: "32px",
1141
+ xl: "48px"
1142
+ };
1143
+ function isThemeableValue9(value) {
1144
+ return typeof value === "object" && value !== null && "useTheme" in value;
1145
+ }
1146
+ function Card({
1147
+ backgroundColor,
1148
+ borderColor,
1149
+ borderWidth = "thin",
1150
+ borderRadius = "md",
1151
+ shadow = "sm",
1152
+ padding = "md",
1153
+ id,
1154
+ puck
1155
+ }) {
1156
+ const { resolveColor: resolveColor2 } = useTheme();
1157
+ const DropZone = puck?.renderDropZone;
1158
+ const resolvedBgColor = (() => {
1159
+ if (!backgroundColor) return resolveColor2("background");
1160
+ if (typeof backgroundColor === "string")
1161
+ return { color: backgroundColor, opacity: 100 };
1162
+ if (isThemeableValue9(backgroundColor)) {
1163
+ return backgroundColor.useTheme ? resolveColor2(backgroundColor.themeKey) : backgroundColor.value;
1164
+ }
1165
+ if ("color" in backgroundColor) return backgroundColor;
1166
+ return resolveColor2("background");
1167
+ })();
1168
+ const resolvedBorderColor = (() => {
1169
+ if (!borderColor) return resolveColor2("muted");
1170
+ if (typeof borderColor === "string")
1171
+ return { color: borderColor, opacity: 100 };
1172
+ if (isThemeableValue9(borderColor)) {
1173
+ return borderColor.useTheme ? resolveColor2(borderColor.themeKey) : borderColor.value;
1174
+ }
1175
+ if ("color" in borderColor) return borderColor;
1176
+ return resolveColor2("muted");
1177
+ })();
1178
+ const style = {
1179
+ backgroundColor: hexToRgba(resolvedBgColor.color, resolvedBgColor.opacity),
1180
+ border: borderWidth !== "none" ? `${borderWidthMap[borderWidth]} solid ${hexToRgba(resolvedBorderColor.color, resolvedBorderColor.opacity)}` : "none",
1181
+ borderRadius: radiusMap5[borderRadius],
1182
+ boxShadow: shadowMap2[shadow],
1183
+ padding: paddingMap2[padding]
1184
+ };
1185
+ return /* @__PURE__ */ jsx11("div", { id, style, children: DropZone && /* @__PURE__ */ jsx11(DropZone, { zone: "card-content" }) });
1186
+ }
1187
+
1188
+ // components/page/Divider.tsx
1189
+ import { jsx as jsx12 } from "react/jsx-runtime";
1190
+ var thicknessMap = {
1191
+ thin: "1px",
1192
+ medium: "2px",
1193
+ thick: "4px"
1194
+ };
1195
+ var widthMap2 = {
1196
+ full: "100%",
1197
+ "3/4": "75%",
1198
+ "1/2": "50%",
1199
+ "1/4": "25%"
1200
+ };
1201
+ var spacingMap = {
1202
+ sm: "16px",
1203
+ md: "24px",
1204
+ lg: "32px",
1205
+ xl: "48px"
1206
+ };
1207
+ function isThemeableValue10(value) {
1208
+ return typeof value === "object" && value !== null && "useTheme" in value;
1209
+ }
1210
+ function Divider({
1211
+ style: lineStyle = "solid",
1212
+ thickness = "thin",
1213
+ color,
1214
+ width = "full",
1215
+ align = "center",
1216
+ spacing = "md",
1217
+ id
1218
+ }) {
1219
+ const { resolveColor: resolveColor2 } = useTheme();
1220
+ const resolvedColor = (() => {
1221
+ if (!color) return resolveColor2("muted");
1222
+ if (typeof color === "string") return { color, opacity: 100 };
1223
+ if (isThemeableValue10(color)) {
1224
+ return color.useTheme ? resolveColor2(color.themeKey) : color.value;
1225
+ }
1226
+ if ("color" in color) return color;
1227
+ return resolveColor2("muted");
1228
+ })();
1229
+ const wrapperStyle = {
1230
+ display: "flex",
1231
+ justifyContent: align === "left" ? "flex-start" : align === "right" ? "flex-end" : "center",
1232
+ padding: `${spacingMap[spacing]} 0`
1233
+ };
1234
+ const hrStyle = {
1235
+ width: widthMap2[width],
1236
+ border: "none",
1237
+ borderTop: `${thicknessMap[thickness]} ${lineStyle} ${hexToRgba(resolvedColor.color, resolvedColor.opacity)}`,
1238
+ margin: 0
1239
+ };
1240
+ return /* @__PURE__ */ jsx12("div", { id, style: wrapperStyle, children: /* @__PURE__ */ jsx12("hr", { style: hrStyle }) });
1241
+ }
1242
+
1243
+ // components/page/Spacer.tsx
1244
+ import { jsx as jsx13 } from "react/jsx-runtime";
1245
+ var sizeMap4 = {
1246
+ xs: "8px",
1247
+ sm: "16px",
1248
+ md: "24px",
1249
+ lg: "32px",
1250
+ xl: "48px",
1251
+ "2xl": "64px",
1252
+ "3xl": "96px"
1253
+ };
1254
+ function Spacer({ size = "md", id }) {
1255
+ const style = {
1256
+ height: sizeMap4[size],
1257
+ width: "100%"
1258
+ };
1259
+ return /* @__PURE__ */ jsx13("div", { id, style, "aria-hidden": "true" });
1260
+ }
1261
+
1262
+ // components/page/TextBlock.tsx
1263
+ import { jsx as jsx14, jsxs as jsxs4 } from "react/jsx-runtime";
1264
+ var alignmentMap = {
1265
+ left: "text-left",
1266
+ center: "text-center",
1267
+ right: "text-right"
1268
+ };
1269
+ var sizeMap5 = {
1270
+ small: "text-2xl",
1271
+ "medium-small": "text-3xl",
1272
+ medium: "text-4xl",
1273
+ large: "text-5xl",
1274
+ xlarge: "text-6xl"
1275
+ };
1276
+ function isThemeableValue11(value) {
1277
+ return typeof value === "object" && value !== null && "useTheme" in value;
1278
+ }
1279
+ function isEntryBoundValue6(value) {
1280
+ return typeof value === "object" && value !== null && "useEntry" in value;
1281
+ }
1282
+ function resolveColor(color, resolveThemeColor) {
1283
+ if (!color) return "#000000";
1284
+ if (typeof color === "string") return color;
1285
+ if (isThemeableValue11(color)) {
1286
+ if (color.useTheme) {
1287
+ const themeColor = resolveThemeColor(color.themeKey);
1288
+ return hexToRgba(themeColor.color, themeColor.opacity);
1289
+ }
1290
+ return hexToRgba(color.value.color, color.value.opacity);
1291
+ }
1292
+ if ("color" in color && "opacity" in color) {
1293
+ return hexToRgba(color.color, color.opacity);
1294
+ }
1295
+ return "#000000";
1296
+ }
1297
+ function resolveColorHex(color, resolveThemeColor) {
1298
+ if (!color) return "#000000";
1299
+ if (typeof color === "string") return color;
1300
+ if (isThemeableValue11(color)) {
1301
+ if (color.useTheme) {
1302
+ return resolveThemeColor(color.themeKey).color;
1303
+ }
1304
+ return color.value.color;
1305
+ }
1306
+ if ("color" in color) {
1307
+ return color.color;
1308
+ }
1309
+ return "#000000";
1310
+ }
1311
+ function TextBlock({
1312
+ title,
1313
+ subtitle,
1314
+ body,
1315
+ alignment = "left",
1316
+ textSize = "medium",
1317
+ textColor,
1318
+ subtitleBodyColor,
1319
+ useGradientText = false,
1320
+ gradientColor1,
1321
+ gradientColor2,
1322
+ anchorLink
1323
+ }) {
1324
+ const { resolveColor: resolveThemeColor } = useTheme();
1325
+ const { getEntryValue } = useEntries();
1326
+ const resolveText = (value) => {
1327
+ if (!value) return void 0;
1328
+ if (typeof value === "string") return value;
1329
+ if (isEntryBoundValue6(value)) {
1330
+ if (value.useEntry) {
1331
+ const entryVal = getEntryValue(value.entryName, value.fieldKey);
1332
+ return entryVal != null ? String(entryVal) : void 0;
1333
+ }
1334
+ return value.value;
1335
+ }
1336
+ return void 0;
1337
+ };
1338
+ const resolvedTitle = resolveText(title);
1339
+ const resolvedSubtitle = resolveText(subtitle);
1340
+ const resolvedBody = resolveText(body);
1341
+ const titleColorValue = resolveColor(textColor, resolveThemeColor);
1342
+ const subtitleColorValue = resolveColor(subtitleBodyColor, resolveThemeColor);
1343
+ const gradientStyle = useGradientText ? {
1344
+ backgroundImage: `linear-gradient(90deg, ${resolveColorHex(gradientColor1, resolveThemeColor)}, ${resolveColorHex(gradientColor2, resolveThemeColor)})`,
1345
+ WebkitBackgroundClip: "text",
1346
+ WebkitTextFillColor: "transparent",
1347
+ backgroundClip: "text"
1348
+ } : { color: titleColorValue };
1349
+ return /* @__PURE__ */ jsxs4(
1350
+ "div",
1351
+ {
1352
+ id: anchorLink,
1353
+ className: cn("flex flex-col gap-4", alignmentMap[alignment]),
1354
+ children: [
1355
+ resolvedTitle && /* @__PURE__ */ jsx14(
1356
+ "h2",
1357
+ {
1358
+ className: cn("font-bold", sizeMap5[textSize]),
1359
+ style: gradientStyle,
1360
+ children: resolvedTitle
1361
+ }
1362
+ ),
1363
+ resolvedSubtitle && /* @__PURE__ */ jsx14("p", { className: "text-xl", style: { color: subtitleColorValue }, children: resolvedSubtitle }),
1364
+ resolvedBody && /* @__PURE__ */ jsx14(
1365
+ "div",
1366
+ {
1367
+ className: "prose max-w-none",
1368
+ style: { color: subtitleColorValue },
1369
+ dangerouslySetInnerHTML: { __html: resolvedBody }
1370
+ }
1371
+ )
1372
+ ]
1373
+ }
1374
+ );
1375
+ }
1376
+
1377
+ // components/page/CustomImage.tsx
1378
+ import { jsx as jsx15 } from "react/jsx-runtime";
1379
+ var alignmentMap2 = {
1380
+ left: "mr-auto",
1381
+ center: "mx-auto",
1382
+ right: "ml-auto"
1383
+ };
1384
+ function CustomImage({
1385
+ image,
1386
+ alt = "",
1387
+ maxWidth,
1388
+ alignment = "center",
1389
+ fitContent = false
1390
+ }) {
1391
+ if (!image) {
1392
+ return /* @__PURE__ */ jsx15("div", { className: "flex h-48 w-full items-center justify-center bg-gray-200 text-gray-400", children: "No image" });
1393
+ }
1394
+ return /* @__PURE__ */ jsx15(
1395
+ "img",
1396
+ {
1397
+ src: image,
1398
+ alt,
1399
+ className: cn(
1400
+ "block",
1401
+ alignmentMap2[alignment],
1402
+ fitContent && "h-full w-full object-cover"
1403
+ ),
1404
+ style: { maxWidth: maxWidth ? `${maxWidth}px` : void 0 }
1405
+ }
1406
+ );
1407
+ }
1408
+
1409
+ // components/page/FeaturesList.tsx
1410
+ import { icons as icons2 } from "lucide-react";
1411
+ import { jsx as jsx16, jsxs as jsxs5 } from "react/jsx-runtime";
1412
+ var sizeMap6 = {
1413
+ small: { icon: 24, title: "text-base", desc: "text-sm" },
1414
+ medium: { icon: 32, title: "text-lg", desc: "text-base" },
1415
+ large: { icon: 48, title: "text-xl", desc: "text-lg" }
1416
+ };
1417
+ function FeaturesList({
1418
+ features = [],
1419
+ align = "left",
1420
+ size = "medium",
1421
+ iconColor = "#000000",
1422
+ anchorLink
1423
+ }) {
1424
+ const sizeConfig = sizeMap6[size];
1425
+ const getIcon = (iconName) => {
1426
+ const formatted = iconName.charAt(0).toUpperCase() + iconName.slice(1);
1427
+ return icons2[formatted] || null;
1428
+ };
1429
+ return /* @__PURE__ */ jsx16(
1430
+ "div",
1431
+ {
1432
+ id: anchorLink,
1433
+ className: cn(
1434
+ "flex flex-col gap-6",
1435
+ align === "center" && "items-center text-center",
1436
+ align === "right" && "items-end text-right"
1437
+ ),
1438
+ children: features.map((feature, index) => {
1439
+ const IconComponent = feature.icon ? getIcon(feature.icon) : null;
1440
+ return /* @__PURE__ */ jsxs5(
1441
+ "div",
1442
+ {
1443
+ className: cn(
1444
+ "flex gap-4",
1445
+ align === "center" && "flex-col items-center",
1446
+ align === "right" && "flex-row-reverse"
1447
+ ),
1448
+ children: [
1449
+ feature.image ? /* @__PURE__ */ jsx16(
1450
+ "img",
1451
+ {
1452
+ src: feature.image,
1453
+ alt: feature.title || "",
1454
+ className: "object-contain",
1455
+ style: { width: sizeConfig.icon, height: sizeConfig.icon }
1456
+ }
1457
+ ) : IconComponent ? /* @__PURE__ */ jsx16(
1458
+ IconComponent,
1459
+ {
1460
+ size: sizeConfig.icon,
1461
+ style: { color: iconColor },
1462
+ className: "flex-shrink-0"
1463
+ }
1464
+ ) : null,
1465
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-1", children: [
1466
+ feature.title && /* @__PURE__ */ jsx16("h3", { className: cn("font-semibold", sizeConfig.title), children: feature.title }),
1467
+ feature.description && /* @__PURE__ */ jsx16("p", { className: cn("text-gray-600", sizeConfig.desc), children: feature.description })
1468
+ ] })
1469
+ ]
1470
+ },
1471
+ index
1472
+ );
1473
+ })
1474
+ }
1475
+ );
1476
+ }
1477
+
1478
+ // components/page/FeatureGrid.tsx
1479
+ import { icons as icons3 } from "lucide-react";
1480
+ import { jsx as jsx17, jsxs as jsxs6 } from "react/jsx-runtime";
1481
+ var sizeMap7 = {
1482
+ small: { icon: 24, title: "text-base", desc: "text-sm" },
1483
+ medium: { icon: 32, title: "text-lg", desc: "text-base" },
1484
+ large: { icon: 48, title: "text-xl", desc: "text-lg" }
1485
+ };
1486
+ function FeatureGrid({
1487
+ heading,
1488
+ description,
1489
+ features = [],
1490
+ columns = 3,
1491
+ align = "left",
1492
+ size = "medium",
1493
+ iconColor = "#3B82F6",
1494
+ textColor = "#000000",
1495
+ anchorLink
1496
+ }) {
1497
+ const sizeConfig = sizeMap7[size];
1498
+ const getIcon = (iconName) => {
1499
+ const formatted = iconName.charAt(0).toUpperCase() + iconName.slice(1);
1500
+ return icons3[formatted] || null;
1501
+ };
1502
+ const columnClass = {
1503
+ 2: "grid-cols-1 md:grid-cols-2",
1504
+ 3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
1505
+ 4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4"
1506
+ };
1507
+ return /* @__PURE__ */ jsxs6("div", { id: anchorLink, className: "flex flex-col gap-8", children: [
1508
+ (heading || description) && /* @__PURE__ */ jsxs6(
1509
+ "div",
1510
+ {
1511
+ className: cn(
1512
+ "flex flex-col gap-2",
1513
+ align === "center" && "text-center",
1514
+ align === "right" && "text-right"
1515
+ ),
1516
+ children: [
1517
+ heading && /* @__PURE__ */ jsx17("h2", { className: "text-3xl font-bold", style: { color: textColor }, children: heading }),
1518
+ description && /* @__PURE__ */ jsx17("p", { className: "text-gray-600", children: description })
1519
+ ]
1520
+ }
1521
+ ),
1522
+ /* @__PURE__ */ jsx17("div", { className: cn("grid gap-6", columnClass[columns]), children: features.map((feature, index) => {
1523
+ const IconComponent = feature.icon ? getIcon(feature.icon) : null;
1524
+ return /* @__PURE__ */ jsxs6(
1525
+ "div",
1526
+ {
1527
+ className: cn(
1528
+ "flex flex-col gap-3 rounded-lg bg-gray-50 p-6",
1529
+ align === "center" && "items-center text-center"
1530
+ ),
1531
+ children: [
1532
+ feature.image ? /* @__PURE__ */ jsx17(
1533
+ "img",
1534
+ {
1535
+ src: feature.image,
1536
+ alt: feature.title || "",
1537
+ className: "object-contain",
1538
+ style: { width: sizeConfig.icon, height: sizeConfig.icon }
1539
+ }
1540
+ ) : IconComponent ? /* @__PURE__ */ jsx17(
1541
+ IconComponent,
1542
+ {
1543
+ size: sizeConfig.icon,
1544
+ style: { color: iconColor }
1545
+ }
1546
+ ) : null,
1547
+ feature.title && /* @__PURE__ */ jsx17(
1548
+ "h3",
1549
+ {
1550
+ className: cn("font-semibold", sizeConfig.title),
1551
+ style: { color: textColor },
1552
+ children: feature.title
1553
+ }
1554
+ ),
1555
+ feature.description && /* @__PURE__ */ jsx17("p", { className: cn("text-gray-600", sizeConfig.desc), children: feature.description })
1556
+ ]
1557
+ },
1558
+ index
1559
+ );
1560
+ }) })
1561
+ ] });
1562
+ }
1563
+
1564
+ // components/page/Footer.tsx
1565
+ import { Facebook, Instagram, Twitter } from "lucide-react";
1566
+ import { jsx as jsx18, jsxs as jsxs7 } from "react/jsx-runtime";
1567
+ function Footer({
1568
+ logo,
1569
+ copyright = "\xA9 2024 Company. All rights reserved.",
1570
+ backgroundColor = "#111827",
1571
+ textColor = "#ffffff",
1572
+ facebookUrl,
1573
+ instagramUrl,
1574
+ twitterUrl,
1575
+ puck
1576
+ }) {
1577
+ const DropZone = puck?.renderDropZone;
1578
+ const socialLinks = [
1579
+ { url: facebookUrl, Icon: Facebook },
1580
+ { url: instagramUrl, Icon: Instagram },
1581
+ { url: twitterUrl, Icon: Twitter }
1582
+ ].filter((link) => link.url);
1583
+ return /* @__PURE__ */ jsx18(
1584
+ "footer",
1585
+ {
1586
+ className: "w-full px-6 py-8",
1587
+ style: { backgroundColor, color: textColor },
1588
+ children: /* @__PURE__ */ jsxs7("div", { className: "mx-auto flex max-w-7xl flex-col items-center justify-between gap-6 md:flex-row", children: [
1589
+ /* @__PURE__ */ jsx18("div", { className: "flex items-center gap-4", children: logo && /* @__PURE__ */ jsx18("img", { src: logo, alt: "Logo", className: "h-8" }) }),
1590
+ DropZone && /* @__PURE__ */ jsx18(DropZone, { zone: "footer-content" }),
1591
+ /* @__PURE__ */ jsx18("div", { className: "flex items-center gap-4", children: socialLinks.map(({ url, Icon: Icon3 }, index) => /* @__PURE__ */ jsx18(
1592
+ "a",
1593
+ {
1594
+ href: url,
1595
+ target: "_blank",
1596
+ rel: "noopener noreferrer",
1597
+ className: "transition-opacity hover:opacity-80",
1598
+ children: /* @__PURE__ */ jsx18(Icon3, { size: 24, style: { color: textColor } })
1599
+ },
1600
+ index
1601
+ )) }),
1602
+ copyright && /* @__PURE__ */ jsx18("p", { className: "text-sm opacity-80", children: copyright })
1603
+ ] })
1604
+ }
1605
+ );
1606
+ }
1607
+
1608
+ // components/page/Topbar.tsx
1609
+ import { useState as useState2 } from "react";
1610
+ import Link from "next/link";
1611
+ import { Menu, X } from "lucide-react";
1612
+ import { jsx as jsx19, jsxs as jsxs8 } from "react/jsx-runtime";
1613
+ function Topbar({
1614
+ logo,
1615
+ logoUrl = "/",
1616
+ navItems = [],
1617
+ backgroundColor = "#ffffff",
1618
+ textColor = "#000000",
1619
+ maxWidth = "1400px",
1620
+ puck
1621
+ }) {
1622
+ const DropZone = puck?.renderDropZone;
1623
+ const [mobileMenuOpen, setMobileMenuOpen] = useState2(false);
1624
+ const renderLink = (item, index) => {
1625
+ const className = "hover:opacity-80 transition-opacity";
1626
+ if (item.linkType === "external") {
1627
+ return /* @__PURE__ */ jsx19(
1628
+ "a",
1629
+ {
1630
+ href: item.url,
1631
+ target: "_blank",
1632
+ rel: "noopener noreferrer",
1633
+ className,
1634
+ children: item.name
1635
+ },
1636
+ index
1637
+ );
1638
+ }
1639
+ if (item.linkType === "scrollTo") {
1640
+ return /* @__PURE__ */ jsx19("a", { href: item.url, className, children: item.name }, index);
1641
+ }
1642
+ return /* @__PURE__ */ jsx19(Link, { href: item.url, className, children: item.name }, index);
1643
+ };
1644
+ return /* @__PURE__ */ jsxs8(
1645
+ "nav",
1646
+ {
1647
+ className: "sticky top-0 z-50 w-full px-6 py-4",
1648
+ style: { backgroundColor, color: textColor },
1649
+ children: [
1650
+ /* @__PURE__ */ jsxs8(
1651
+ "div",
1652
+ {
1653
+ className: "mx-auto flex items-center justify-between",
1654
+ style: { maxWidth },
1655
+ children: [
1656
+ /* @__PURE__ */ jsx19(Link, { href: logoUrl, className: "flex-shrink-0", children: logo ? /* @__PURE__ */ jsx19("img", { src: logo, alt: "Logo", className: "h-8" }) : /* @__PURE__ */ jsx19("span", { className: "text-xl font-bold", children: "Logo" }) }),
1657
+ /* @__PURE__ */ jsxs8("div", { className: "hidden items-center gap-8 md:flex", children: [
1658
+ navItems.map(renderLink),
1659
+ DropZone && /* @__PURE__ */ jsx19(DropZone, { zone: "cta" })
1660
+ ] }),
1661
+ /* @__PURE__ */ jsx19(
1662
+ "button",
1663
+ {
1664
+ className: "md:hidden",
1665
+ onClick: () => setMobileMenuOpen(!mobileMenuOpen),
1666
+ children: mobileMenuOpen ? /* @__PURE__ */ jsx19(X, { size: 24 }) : /* @__PURE__ */ jsx19(Menu, { size: 24 })
1667
+ }
1668
+ )
1669
+ ]
1670
+ }
1671
+ ),
1672
+ mobileMenuOpen && /* @__PURE__ */ jsxs8(
1673
+ "div",
1674
+ {
1675
+ className: "absolute top-full right-0 left-0 flex flex-col gap-4 px-6 py-4 md:hidden",
1676
+ style: { backgroundColor },
1677
+ children: [
1678
+ navItems.map(renderLink),
1679
+ DropZone && /* @__PURE__ */ jsx19(DropZone, { zone: "cta" })
1680
+ ]
1681
+ }
1682
+ )
1683
+ ]
1684
+ }
1685
+ );
1686
+ }
1687
+
1688
+ // components/page/Popup.tsx
1689
+ import { useState as useState3 } from "react";
1690
+ import { icons as icons4, X as X2 } from "lucide-react";
1691
+ import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs9 } from "react/jsx-runtime";
1692
+ function Icon2({ name, ...props }) {
1693
+ const formatted = name.charAt(0).toUpperCase() + name.slice(1);
1694
+ const IconComponent = icons4[formatted];
1695
+ if (!IconComponent) return null;
1696
+ return /* @__PURE__ */ jsx20(IconComponent, { ...props });
1697
+ }
1698
+ var widthMap3 = {
1699
+ small: "max-w-sm",
1700
+ medium: "max-w-lg",
1701
+ large: "max-w-2xl"
1702
+ };
1703
+ var sizeMap8 = {
1704
+ small: "px-3 py-1.5 text-sm",
1705
+ medium: "px-4 py-2 text-base",
1706
+ large: "px-6 py-3 text-lg"
1707
+ };
1708
+ function Popup({
1709
+ ctaText = "Open",
1710
+ buttonColor = "#3B82F6",
1711
+ textColor = "#ffffff",
1712
+ icon,
1713
+ iconPosition = "left",
1714
+ size = "medium",
1715
+ width = "medium",
1716
+ textLink = false,
1717
+ puck
1718
+ }) {
1719
+ const [isOpen, setIsOpen] = useState3(false);
1720
+ const trigger = textLink ? /* @__PURE__ */ jsx20(
1721
+ "button",
1722
+ {
1723
+ onClick: () => setIsOpen(true),
1724
+ className: "underline hover:opacity-80",
1725
+ style: { color: buttonColor },
1726
+ children: ctaText
1727
+ }
1728
+ ) : /* @__PURE__ */ jsxs9(
1729
+ "button",
1730
+ {
1731
+ onClick: () => setIsOpen(true),
1732
+ className: cn(
1733
+ "flex items-center gap-2 rounded-full font-medium",
1734
+ sizeMap8[size]
1735
+ ),
1736
+ style: { backgroundColor: buttonColor, color: textColor },
1737
+ children: [
1738
+ icon && iconPosition === "left" && /* @__PURE__ */ jsx20(Icon2, { name: icon, size: 18 }),
1739
+ ctaText,
1740
+ icon && iconPosition === "right" && /* @__PURE__ */ jsx20(Icon2, { name: icon, size: 18 })
1741
+ ]
1742
+ }
1743
+ );
1744
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
1745
+ trigger,
1746
+ isOpen && /* @__PURE__ */ jsx20(
1747
+ "div",
1748
+ {
1749
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4",
1750
+ onClick: () => setIsOpen(false),
1751
+ children: /* @__PURE__ */ jsxs9(
1752
+ "div",
1753
+ {
1754
+ className: cn(
1755
+ "relative w-full rounded-lg bg-white p-6",
1756
+ widthMap3[width]
1757
+ ),
1758
+ onClick: (e) => e.stopPropagation(),
1759
+ children: [
1760
+ /* @__PURE__ */ jsx20(
1761
+ "button",
1762
+ {
1763
+ onClick: () => setIsOpen(false),
1764
+ className: "absolute top-4 right-4 text-gray-500 hover:text-gray-700",
1765
+ children: /* @__PURE__ */ jsx20(X2, { size: 24 })
1766
+ }
1767
+ ),
1768
+ puck && /* @__PURE__ */ jsx20(puck.renderDropZone, { zone: "popup-content" })
1769
+ ]
1770
+ }
1771
+ )
1772
+ }
1773
+ )
1774
+ ] });
1775
+ }
1776
+
1777
+ export {
1778
+ Heading,
1779
+ Paragraph,
1780
+ Button,
1781
+ Image,
1782
+ ImageCarousel,
1783
+ VideoEmbed,
1784
+ Icon,
1785
+ availableIcons,
1786
+ Section,
1787
+ Container,
1788
+ Columns,
1789
+ Card,
1790
+ Divider,
1791
+ Spacer,
1792
+ TextBlock,
1793
+ CustomImage,
1794
+ FeaturesList,
1795
+ FeatureGrid,
1796
+ Footer,
1797
+ Topbar,
1798
+ Popup
1799
+ };