@reblu/site-blocks 0.17.1 → 0.19.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/CHANGELOG.md +23 -0
- package/README.md +151 -0
- package/dist/_heading-BsNbc1wc.d.cts +4 -0
- package/dist/_heading-BsNbc1wc.d.ts +4 -0
- package/dist/client.cjs +256 -49
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +60 -2
- package/dist/client.d.ts +60 -2
- package/dist/client.js +255 -50
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +381 -308
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -8
- package/dist/index.d.ts +40 -8
- package/dist/index.js +380 -308
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/client.cjs
CHANGED
|
@@ -37,7 +37,9 @@ __export(client_exports, {
|
|
|
37
37
|
DATA_REQUEST_FIELD_LIMITS: () => DATA_REQUEST_FIELD_LIMITS,
|
|
38
38
|
DATA_REQUEST_TYPES: () => import_site_contracts.DATA_REQUEST_TYPES,
|
|
39
39
|
DEFAULT_DATA_REQUEST_FORM_LABELS: () => DEFAULT_DATA_REQUEST_FORM_LABELS,
|
|
40
|
+
DEFAULT_PRODUCT_CAROUSEL_LABELS: () => DEFAULT_PRODUCT_CAROUSEL_LABELS,
|
|
40
41
|
DataRequestForm: () => DataRequestForm,
|
|
42
|
+
ProductCarousel: () => ProductCarousel,
|
|
41
43
|
ShareButtons: () => ShareButtons,
|
|
42
44
|
useCollection: () => useCollection
|
|
43
45
|
});
|
|
@@ -226,7 +228,7 @@ function Collection({
|
|
|
226
228
|
] })
|
|
227
229
|
] });
|
|
228
230
|
}
|
|
229
|
-
var PAGE_BTN_CLASS = "inline-flex h-9 items-center rounded-md border border-border px-4 text-sm font-medium transition-colors hover:bg-muted disabled:pointer-events-none disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
231
|
+
var PAGE_BTN_CLASS = "inline-flex h-9 cursor-pointer items-center rounded-md border border-border px-4 text-sm font-medium transition-colors hover:bg-muted disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
230
232
|
function FacetChip({ label, pressed, color, onClick }) {
|
|
231
233
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
232
234
|
"button",
|
|
@@ -236,7 +238,7 @@ function FacetChip({ label, pressed, color, onClick }) {
|
|
|
236
238
|
onClick,
|
|
237
239
|
style: color ? { "--facet-color": color } : void 0,
|
|
238
240
|
className: (0, import_utils.cn)(
|
|
239
|
-
"inline-flex items-center rounded-full border px-3 py-1 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
241
|
+
"inline-flex cursor-pointer items-center rounded-full border px-3 py-1 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
240
242
|
pressed ? color ? "border-transparent bg-[var(--facet-color)] text-white" : "border-transparent bg-primary text-primary-foreground" : "border-border text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
241
243
|
),
|
|
242
244
|
children: label
|
|
@@ -321,7 +323,7 @@ function ShareButtons({ url, title, className, labels }) {
|
|
|
321
323
|
{
|
|
322
324
|
type: "button",
|
|
323
325
|
onClick: handleCopy,
|
|
324
|
-
className: (0, import_utils2.cn)(LINK_CLASS, "w-auto gap-2 px-3", copied && "border-primary text-primary"),
|
|
326
|
+
className: (0, import_utils2.cn)(LINK_CLASS, "w-auto cursor-pointer gap-2 px-3", copied && "border-primary text-primary"),
|
|
325
327
|
"aria-label": t.copy,
|
|
326
328
|
children: [
|
|
327
329
|
copied ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CheckIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CopyIcon, {}),
|
|
@@ -442,7 +444,7 @@ function AddToCartButton({
|
|
|
442
444
|
"data-slot": "add-to-cart-button",
|
|
443
445
|
"data-status": status,
|
|
444
446
|
className: (0, import_utils3.cn)(
|
|
445
|
-
"inline-flex items-center justify-center gap-2 rounded-xl px-4 py-2.5 text-sm font-semibold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
447
|
+
"inline-flex cursor-pointer items-center justify-center gap-2 rounded-xl px-4 py-2.5 text-sm font-semibold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
446
448
|
isDisabled ? "cursor-not-allowed bg-muted text-muted-foreground" : "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
447
449
|
status === "error" && "bg-destructive text-destructive-foreground",
|
|
448
450
|
className
|
|
@@ -527,11 +529,214 @@ function CartIcon({ itemCount, href, hydrated, bumpOnAdd, labels, className }) {
|
|
|
527
529
|
);
|
|
528
530
|
}
|
|
529
531
|
|
|
530
|
-
// src/components/
|
|
532
|
+
// src/components/product-carousel.tsx
|
|
531
533
|
var import_react4 = require("react");
|
|
534
|
+
var import_button_variants = require("@reblu/site-ui/button-variants");
|
|
535
|
+
var import_utils6 = require("@reblu/site-ui/utils");
|
|
536
|
+
|
|
537
|
+
// src/components/_heading.tsx
|
|
538
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
539
|
+
function Heading({
|
|
540
|
+
level,
|
|
541
|
+
className,
|
|
542
|
+
children
|
|
543
|
+
}) {
|
|
544
|
+
const Tag = `h${level}`;
|
|
545
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Tag, { className, children });
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// src/components/product-card.tsx
|
|
532
549
|
var import_utils5 = require("@reblu/site-ui/utils");
|
|
550
|
+
|
|
551
|
+
// src/lib/format-price.ts
|
|
552
|
+
function formatPrice(cents, currency = "EUR", locale = "es-ES") {
|
|
553
|
+
return new Intl.NumberFormat(locale, {
|
|
554
|
+
style: "currency",
|
|
555
|
+
currency
|
|
556
|
+
}).format(cents / 100);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// src/components/product-card.tsx
|
|
560
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
561
|
+
function ProductCard({ product, href, currencyCode = "EUR", locale, className }) {
|
|
562
|
+
const image = product.images.find((i) => i.isPrimary) ?? product.images[0];
|
|
563
|
+
const hasDiscount = product.comparePrice != null && product.comparePrice > product.price;
|
|
564
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
565
|
+
"article",
|
|
566
|
+
{
|
|
567
|
+
className: (0, import_utils5.cn)(
|
|
568
|
+
"group flex flex-col overflow-hidden rounded-lg border bg-card transition-shadow hover:shadow-lg",
|
|
569
|
+
className
|
|
570
|
+
),
|
|
571
|
+
"data-slot": "product-card",
|
|
572
|
+
children: [
|
|
573
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "relative aspect-square overflow-hidden bg-muted", children: image ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
574
|
+
"img",
|
|
575
|
+
{
|
|
576
|
+
src: image.url,
|
|
577
|
+
alt: image.alt ?? product.name,
|
|
578
|
+
loading: "lazy",
|
|
579
|
+
className: "h-full w-full object-cover transition-transform group-hover:scale-105"
|
|
580
|
+
}
|
|
581
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex h-full items-center justify-center text-4xl text-muted-foreground/30", "aria-hidden": "true", children: "\u{1F6CD}\uFE0F" }) }),
|
|
582
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-1 flex-col gap-2 p-4", children: [
|
|
583
|
+
product.category && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "inline-flex w-fit items-center rounded-full bg-secondary px-2.5 py-0.5 text-xs font-medium text-secondary-foreground", children: product.category.name }),
|
|
584
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: "text-base font-semibold leading-tight", children: href ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href, className: "transition-colors hover:text-primary", children: product.name }) : product.name }),
|
|
585
|
+
product.shortDescription && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "line-clamp-2 text-sm text-muted-foreground", children: product.shortDescription }),
|
|
586
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mt-auto flex items-baseline gap-2 pt-2", children: [
|
|
587
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-lg font-bold text-foreground", children: formatPrice(product.price, currencyCode, locale) }),
|
|
588
|
+
hasDiscount && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm text-muted-foreground line-through", children: formatPrice(product.comparePrice, currencyCode, locale) })
|
|
589
|
+
] })
|
|
590
|
+
] })
|
|
591
|
+
]
|
|
592
|
+
}
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// src/components/product-carousel.tsx
|
|
597
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
598
|
+
var DEFAULT_PRODUCT_CAROUSEL_LABELS = {
|
|
599
|
+
region: "Productos relacionados",
|
|
600
|
+
roleDescription: "carrusel",
|
|
601
|
+
previous: "Anterior",
|
|
602
|
+
next: "Siguiente"
|
|
603
|
+
};
|
|
604
|
+
var EDGE_EPSILON = 1;
|
|
605
|
+
function prefersReducedMotion() {
|
|
606
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)").matches : false;
|
|
607
|
+
}
|
|
608
|
+
function ChevronIcon({ direction }) {
|
|
609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
610
|
+
"svg",
|
|
611
|
+
{
|
|
612
|
+
"aria-hidden": "true",
|
|
613
|
+
viewBox: "0 0 24 24",
|
|
614
|
+
fill: "none",
|
|
615
|
+
stroke: "currentColor",
|
|
616
|
+
strokeWidth: 2,
|
|
617
|
+
strokeLinecap: "round",
|
|
618
|
+
strokeLinejoin: "round",
|
|
619
|
+
className: "rtl:-scale-x-100",
|
|
620
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: direction === "left" ? "m15 18-6-6 6-6" : "m9 18 6-6-6-6" })
|
|
621
|
+
}
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
function ProductCarousel(props) {
|
|
625
|
+
const { products, heading, headingLevel = 2, headingClassName, labels, className, itemClassName } = props;
|
|
626
|
+
const t = { ...DEFAULT_PRODUCT_CAROUSEL_LABELS, ...labels };
|
|
627
|
+
const trackId = (0, import_react4.useId)();
|
|
628
|
+
const headingId = (0, import_react4.useId)();
|
|
629
|
+
const trackRef = (0, import_react4.useRef)(null);
|
|
630
|
+
const [canPrev, setCanPrev] = (0, import_react4.useState)(false);
|
|
631
|
+
const [canNext, setCanNext] = (0, import_react4.useState)(false);
|
|
632
|
+
const update = (0, import_react4.useCallback)(() => {
|
|
633
|
+
const el = trackRef.current;
|
|
634
|
+
if (!el) return;
|
|
635
|
+
const max = el.scrollWidth - el.clientWidth;
|
|
636
|
+
const pos = Math.abs(el.scrollLeft);
|
|
637
|
+
setCanPrev(pos > EDGE_EPSILON);
|
|
638
|
+
setCanNext(pos < max - EDGE_EPSILON);
|
|
639
|
+
}, []);
|
|
640
|
+
(0, import_react4.useEffect)(() => {
|
|
641
|
+
const el = trackRef.current;
|
|
642
|
+
if (!el) return;
|
|
643
|
+
update();
|
|
644
|
+
el.addEventListener("scroll", update, { passive: true });
|
|
645
|
+
let observer;
|
|
646
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
647
|
+
observer = new ResizeObserver(update);
|
|
648
|
+
observer.observe(el);
|
|
649
|
+
} else {
|
|
650
|
+
window.addEventListener("resize", update);
|
|
651
|
+
}
|
|
652
|
+
return () => {
|
|
653
|
+
el.removeEventListener("scroll", update);
|
|
654
|
+
if (observer) observer.disconnect();
|
|
655
|
+
else window.removeEventListener("resize", update);
|
|
656
|
+
};
|
|
657
|
+
}, [update, products.length]);
|
|
658
|
+
const scrollByPage = (direction) => {
|
|
659
|
+
const el = trackRef.current;
|
|
660
|
+
if (!el) return;
|
|
661
|
+
const rtl = typeof getComputedStyle === "function" && getComputedStyle(el).direction === "rtl";
|
|
662
|
+
el.scrollBy({
|
|
663
|
+
left: direction * el.clientWidth * (rtl ? -1 : 1),
|
|
664
|
+
behavior: prefersReducedMotion() ? "auto" : "smooth"
|
|
665
|
+
});
|
|
666
|
+
};
|
|
667
|
+
if (products.length === 0) return null;
|
|
668
|
+
const scrollable = canPrev || canNext;
|
|
669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { "data-slot": "product-carousel", className: (0, import_utils6.cn)("flex flex-col gap-4", className), children: [
|
|
670
|
+
(heading || scrollable) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between gap-4", children: [
|
|
671
|
+
heading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { id: headingId, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Heading, { level: headingLevel, className: headingClassName ?? "text-xl font-semibold", children: heading }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", {}),
|
|
672
|
+
scrollable && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hidden gap-2 sm:flex", "data-slot": "product-carousel-controls", children: [
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
674
|
+
"button",
|
|
675
|
+
{
|
|
676
|
+
type: "button",
|
|
677
|
+
className: (0, import_utils6.cn)((0, import_button_variants.buttonVariants)({ variant: "outline", size: "icon" }), "rounded-full"),
|
|
678
|
+
"aria-label": t.previous,
|
|
679
|
+
"aria-controls": trackId,
|
|
680
|
+
disabled: !canPrev,
|
|
681
|
+
onClick: () => scrollByPage(-1),
|
|
682
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronIcon, { direction: "left" })
|
|
683
|
+
}
|
|
684
|
+
),
|
|
685
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
686
|
+
"button",
|
|
687
|
+
{
|
|
688
|
+
type: "button",
|
|
689
|
+
className: (0, import_utils6.cn)((0, import_button_variants.buttonVariants)({ variant: "outline", size: "icon" }), "rounded-full"),
|
|
690
|
+
"aria-label": t.next,
|
|
691
|
+
"aria-controls": trackId,
|
|
692
|
+
disabled: !canNext,
|
|
693
|
+
onClick: () => scrollByPage(1),
|
|
694
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronIcon, { direction: "right" })
|
|
695
|
+
}
|
|
696
|
+
)
|
|
697
|
+
] })
|
|
698
|
+
] }),
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
700
|
+
"div",
|
|
701
|
+
{
|
|
702
|
+
ref: trackRef,
|
|
703
|
+
id: trackId,
|
|
704
|
+
role: "region",
|
|
705
|
+
"aria-roledescription": t.roleDescription,
|
|
706
|
+
...heading ? { "aria-labelledby": headingId } : { "aria-label": t.region },
|
|
707
|
+
tabIndex: 0,
|
|
708
|
+
"data-slot": "product-carousel-track",
|
|
709
|
+
className: "snap-x snap-mandatory overflow-x-auto overscroll-x-contain scroll-smooth rounded-lg pb-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:scroll-auto",
|
|
710
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { role: "list", className: "m-0 flex list-none gap-4 p-0", children: products.map((product, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
711
|
+
"li",
|
|
712
|
+
{
|
|
713
|
+
className: (0, import_utils6.cn)(
|
|
714
|
+
"shrink-0 snap-start basis-[calc((100%-1rem)/1.5)] sm:basis-[calc((100%-2rem)/3)] lg:basis-[calc((100%-3rem)/4)]",
|
|
715
|
+
itemClassName
|
|
716
|
+
),
|
|
717
|
+
children: props.renderProduct ? props.renderProduct(product, index) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
718
|
+
ProductCard,
|
|
719
|
+
{
|
|
720
|
+
product,
|
|
721
|
+
href: props.productHref?.(product),
|
|
722
|
+
currencyCode: props.currencyCode,
|
|
723
|
+
locale: props.locale,
|
|
724
|
+
className: "h-full"
|
|
725
|
+
}
|
|
726
|
+
)
|
|
727
|
+
},
|
|
728
|
+
product.id
|
|
729
|
+
)) })
|
|
730
|
+
}
|
|
731
|
+
)
|
|
732
|
+
] });
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// src/components/data-request-form.tsx
|
|
736
|
+
var import_react5 = require("react");
|
|
737
|
+
var import_utils7 = require("@reblu/site-ui/utils");
|
|
533
738
|
var import_site_contracts = require("@reblu/site-contracts");
|
|
534
|
-
var
|
|
739
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
535
740
|
var DATA_REQUEST_FIELD_LIMITS = Object.freeze({ name: 200, email: 320, details: 5e3 });
|
|
536
741
|
var DEFAULT_DATA_REQUEST_FORM_LABELS = {
|
|
537
742
|
requestTypeLabel: "Derecho que quieres ejercer",
|
|
@@ -557,7 +762,7 @@ var DEFAULT_DATA_REQUEST_FORM_LABELS = {
|
|
|
557
762
|
nameRequired: "Indica tu nombre.",
|
|
558
763
|
emailInvalid: "Introduce un email v\xE1lido.",
|
|
559
764
|
consentRequired: "Debes aceptar el tratamiento de tus datos para gestionar la solicitud.",
|
|
560
|
-
success: (deadline) => /* @__PURE__ */ (0,
|
|
765
|
+
success: (deadline) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
561
766
|
"Hemos recibido tu solicitud. Te responderemos como m\xE1ximo el ",
|
|
562
767
|
deadline,
|
|
563
768
|
"."
|
|
@@ -606,18 +811,18 @@ function DataRequestForm({
|
|
|
606
811
|
...labels,
|
|
607
812
|
requestTypes: { ...DEFAULT_DATA_REQUEST_FORM_LABELS.requestTypes, ...labels?.requestTypes }
|
|
608
813
|
};
|
|
609
|
-
const id = (0,
|
|
610
|
-
const [requestType, setRequestType] = (0,
|
|
611
|
-
const [name, setName] = (0,
|
|
612
|
-
const [email, setEmail] = (0,
|
|
613
|
-
const [details, setDetails] = (0,
|
|
614
|
-
const [consent, setConsent] = (0,
|
|
615
|
-
const [errors, setErrors] = (0,
|
|
616
|
-
const [formError, setFormError] = (0,
|
|
617
|
-
const [submitting, setSubmitting] = (0,
|
|
618
|
-
const [ack, setAck] = (0,
|
|
619
|
-
const statusRef = (0,
|
|
620
|
-
(0,
|
|
814
|
+
const id = (0, import_react5.useId)();
|
|
815
|
+
const [requestType, setRequestType] = (0, import_react5.useState)("");
|
|
816
|
+
const [name, setName] = (0, import_react5.useState)("");
|
|
817
|
+
const [email, setEmail] = (0, import_react5.useState)("");
|
|
818
|
+
const [details, setDetails] = (0, import_react5.useState)("");
|
|
819
|
+
const [consent, setConsent] = (0, import_react5.useState)(false);
|
|
820
|
+
const [errors, setErrors] = (0, import_react5.useState)({});
|
|
821
|
+
const [formError, setFormError] = (0, import_react5.useState)(null);
|
|
822
|
+
const [submitting, setSubmitting] = (0, import_react5.useState)(false);
|
|
823
|
+
const [ack, setAck] = (0, import_react5.useState)(null);
|
|
824
|
+
const statusRef = (0, import_react5.useRef)(null);
|
|
825
|
+
(0, import_react5.useEffect)(() => {
|
|
621
826
|
if (ack) statusRef.current?.focus();
|
|
622
827
|
}, [ack]);
|
|
623
828
|
async function handleSubmit(event) {
|
|
@@ -668,21 +873,21 @@ function DataRequestForm({
|
|
|
668
873
|
dateStyle: "long",
|
|
669
874
|
timeStyle: "short"
|
|
670
875
|
}).format(new Date(ack.slaDueAt));
|
|
671
|
-
return /* @__PURE__ */ (0,
|
|
876
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
672
877
|
"div",
|
|
673
878
|
{
|
|
674
879
|
ref: statusRef,
|
|
675
880
|
tabIndex: -1,
|
|
676
881
|
role: "status",
|
|
677
882
|
"data-slot": "data-request-form-success",
|
|
678
|
-
className: (0,
|
|
883
|
+
className: (0, import_utils7.cn)("rounded-lg border border-border p-6 text-sm", className),
|
|
679
884
|
children: t.success(deadline)
|
|
680
885
|
}
|
|
681
886
|
);
|
|
682
887
|
}
|
|
683
888
|
const errorId = (field) => errors[field] ? `${id}-${field}-error` : void 0;
|
|
684
|
-
const fieldError = (field) => errors[field] ? /* @__PURE__ */ (0,
|
|
685
|
-
return /* @__PURE__ */ (0,
|
|
889
|
+
const fieldError = (field) => errors[field] ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { id: `${id}-${field}-error`, className: "text-xs text-destructive", children: errors[field] }) : null;
|
|
890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
686
891
|
"form",
|
|
687
892
|
{
|
|
688
893
|
noValidate: true,
|
|
@@ -690,11 +895,11 @@ function DataRequestForm({
|
|
|
690
895
|
onFocusCapture: onInteract,
|
|
691
896
|
onPointerDown: onInteract,
|
|
692
897
|
"data-slot": "data-request-form",
|
|
693
|
-
className: (0,
|
|
898
|
+
className: (0, import_utils7.cn)("space-y-4", className),
|
|
694
899
|
children: [
|
|
695
|
-
/* @__PURE__ */ (0,
|
|
696
|
-
/* @__PURE__ */ (0,
|
|
697
|
-
/* @__PURE__ */ (0,
|
|
900
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", children: [
|
|
901
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { htmlFor: `${id}-type`, className: "text-sm font-medium", children: t.requestTypeLabel }),
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
698
903
|
"select",
|
|
699
904
|
{
|
|
700
905
|
id: `${id}-type`,
|
|
@@ -702,18 +907,18 @@ function DataRequestForm({
|
|
|
702
907
|
onChange: (e) => setRequestType(e.target.value),
|
|
703
908
|
"aria-invalid": errors.requestType ? true : void 0,
|
|
704
909
|
"aria-describedby": errorId("requestType"),
|
|
705
|
-
className: (0,
|
|
910
|
+
className: (0, import_utils7.cn)(FIELD_CLASS, errors.requestType ? "border-destructive" : "border-border"),
|
|
706
911
|
children: [
|
|
707
|
-
/* @__PURE__ */ (0,
|
|
708
|
-
requestTypes.map((type) => /* @__PURE__ */ (0,
|
|
912
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: t.requestTypePlaceholder }),
|
|
913
|
+
requestTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: type, children: t.requestTypes[type] }, type))
|
|
709
914
|
]
|
|
710
915
|
}
|
|
711
916
|
),
|
|
712
917
|
fieldError("requestType")
|
|
713
918
|
] }),
|
|
714
|
-
/* @__PURE__ */ (0,
|
|
715
|
-
/* @__PURE__ */ (0,
|
|
716
|
-
/* @__PURE__ */ (0,
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", children: [
|
|
920
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { htmlFor: `${id}-name`, className: "text-sm font-medium", children: t.nameLabel }),
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
717
922
|
"input",
|
|
718
923
|
{
|
|
719
924
|
id: `${id}-name`,
|
|
@@ -724,14 +929,14 @@ function DataRequestForm({
|
|
|
724
929
|
onChange: (e) => setName(e.target.value),
|
|
725
930
|
"aria-invalid": errors.name ? true : void 0,
|
|
726
931
|
"aria-describedby": errorId("name"),
|
|
727
|
-
className: (0,
|
|
932
|
+
className: (0, import_utils7.cn)(FIELD_CLASS, errors.name ? "border-destructive" : "border-border")
|
|
728
933
|
}
|
|
729
934
|
),
|
|
730
935
|
fieldError("name")
|
|
731
936
|
] }),
|
|
732
|
-
/* @__PURE__ */ (0,
|
|
733
|
-
/* @__PURE__ */ (0,
|
|
734
|
-
/* @__PURE__ */ (0,
|
|
937
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", children: [
|
|
938
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { htmlFor: `${id}-email`, className: "text-sm font-medium", children: t.emailLabel }),
|
|
939
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
735
940
|
"input",
|
|
736
941
|
{
|
|
737
942
|
id: `${id}-email`,
|
|
@@ -742,14 +947,14 @@ function DataRequestForm({
|
|
|
742
947
|
onChange: (e) => setEmail(e.target.value),
|
|
743
948
|
"aria-invalid": errors.email ? true : void 0,
|
|
744
949
|
"aria-describedby": errorId("email"),
|
|
745
|
-
className: (0,
|
|
950
|
+
className: (0, import_utils7.cn)(FIELD_CLASS, errors.email ? "border-destructive" : "border-border")
|
|
746
951
|
}
|
|
747
952
|
),
|
|
748
953
|
fieldError("email")
|
|
749
954
|
] }),
|
|
750
|
-
/* @__PURE__ */ (0,
|
|
751
|
-
/* @__PURE__ */ (0,
|
|
752
|
-
/* @__PURE__ */ (0,
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", children: [
|
|
956
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { htmlFor: `${id}-details`, className: "text-sm font-medium", children: t.detailsLabel }),
|
|
957
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
753
958
|
"textarea",
|
|
754
959
|
{
|
|
755
960
|
id: `${id}-details`,
|
|
@@ -758,13 +963,13 @@ function DataRequestForm({
|
|
|
758
963
|
value: details,
|
|
759
964
|
onChange: (e) => setDetails(e.target.value),
|
|
760
965
|
placeholder: t.detailsPlaceholder,
|
|
761
|
-
className: (0,
|
|
966
|
+
className: (0, import_utils7.cn)(FIELD_CLASS, "border-border")
|
|
762
967
|
}
|
|
763
968
|
)
|
|
764
969
|
] }),
|
|
765
|
-
/* @__PURE__ */ (0,
|
|
766
|
-
/* @__PURE__ */ (0,
|
|
767
|
-
/* @__PURE__ */ (0,
|
|
970
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", children: [
|
|
971
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-start gap-2", children: [
|
|
972
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
768
973
|
"input",
|
|
769
974
|
{
|
|
770
975
|
id: `${id}-consent`,
|
|
@@ -776,17 +981,17 @@ function DataRequestForm({
|
|
|
776
981
|
className: "mt-1"
|
|
777
982
|
}
|
|
778
983
|
),
|
|
779
|
-
/* @__PURE__ */ (0,
|
|
984
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { htmlFor: `${id}-consent`, className: "text-sm text-foreground/80", children: t.consent })
|
|
780
985
|
] }),
|
|
781
986
|
fieldError("consent")
|
|
782
987
|
] }),
|
|
783
|
-
formError && /* @__PURE__ */ (0,
|
|
784
|
-
/* @__PURE__ */ (0,
|
|
988
|
+
formError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { role: "alert", className: "text-sm text-destructive", children: formError }),
|
|
989
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
785
990
|
"button",
|
|
786
991
|
{
|
|
787
992
|
type: "submit",
|
|
788
993
|
disabled: submitting,
|
|
789
|
-
className: "rounded-lg bg-primary px-6 py-2 text-sm font-semibold text-primary-foreground disabled:opacity-60",
|
|
994
|
+
className: "cursor-pointer rounded-lg bg-primary px-6 py-2 text-sm font-semibold text-primary-foreground disabled:cursor-not-allowed disabled:opacity-60",
|
|
790
995
|
children: submitting ? t.submitting : t.submit
|
|
791
996
|
}
|
|
792
997
|
)
|
|
@@ -802,7 +1007,9 @@ function DataRequestForm({
|
|
|
802
1007
|
DATA_REQUEST_FIELD_LIMITS,
|
|
803
1008
|
DATA_REQUEST_TYPES,
|
|
804
1009
|
DEFAULT_DATA_REQUEST_FORM_LABELS,
|
|
1010
|
+
DEFAULT_PRODUCT_CAROUSEL_LABELS,
|
|
805
1011
|
DataRequestForm,
|
|
1012
|
+
ProductCarousel,
|
|
806
1013
|
ShareButtons,
|
|
807
1014
|
useCollection
|
|
808
1015
|
});
|