@reblu/site-blocks 0.19.0 → 0.21.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 +29 -0
- package/README.md +126 -2
- package/dist/client.cjs +372 -45
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +78 -2
- package/dist/client.d.ts +78 -2
- package/dist/client.js +369 -44
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +440 -305
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -4
- package/dist/index.d.ts +68 -4
- package/dist/index.js +438 -305
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/client.cjs
CHANGED
|
@@ -34,8 +34,10 @@ __export(client_exports, {
|
|
|
34
34
|
AddToCartButton: () => AddToCartButton,
|
|
35
35
|
CartIcon: () => CartIcon,
|
|
36
36
|
Collection: () => Collection,
|
|
37
|
+
CourseSyllabus: () => CourseSyllabus,
|
|
37
38
|
DATA_REQUEST_FIELD_LIMITS: () => DATA_REQUEST_FIELD_LIMITS,
|
|
38
39
|
DATA_REQUEST_TYPES: () => import_site_contracts.DATA_REQUEST_TYPES,
|
|
40
|
+
DEFAULT_COURSE_SYLLABUS_LABELS: () => DEFAULT_COURSE_SYLLABUS_LABELS,
|
|
39
41
|
DEFAULT_DATA_REQUEST_FORM_LABELS: () => DEFAULT_DATA_REQUEST_FORM_LABELS,
|
|
40
42
|
DEFAULT_PRODUCT_CAROUSEL_LABELS: () => DEFAULT_PRODUCT_CAROUSEL_LABELS,
|
|
41
43
|
DataRequestForm: () => DataRequestForm,
|
|
@@ -460,7 +462,7 @@ var import_utils4 = require("@reblu/site-ui/utils");
|
|
|
460
462
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
461
463
|
var DEFAULT_LABELS4 = {
|
|
462
464
|
cart: "Carrito",
|
|
463
|
-
itemsSuffix: (
|
|
465
|
+
itemsSuffix: (count2) => `${count2} art\xEDculo${count2 === 1 ? "" : "s"}`
|
|
464
466
|
};
|
|
465
467
|
var BUMP_DURATION_MS = 400;
|
|
466
468
|
function CartIcon({ itemCount, href, hydrated, bumpOnAdd, labels, className }) {
|
|
@@ -732,11 +734,334 @@ function ProductCarousel(props) {
|
|
|
732
734
|
] });
|
|
733
735
|
}
|
|
734
736
|
|
|
735
|
-
// src/components/
|
|
737
|
+
// src/components/course-syllabus.tsx
|
|
736
738
|
var import_react5 = require("react");
|
|
739
|
+
var import_utils8 = require("@reblu/site-ui/utils");
|
|
740
|
+
|
|
741
|
+
// src/lib/slot-class-name.ts
|
|
737
742
|
var import_utils7 = require("@reblu/site-ui/utils");
|
|
738
|
-
var
|
|
743
|
+
var MERGE_SAFE_TEXT = /(?:^|:)!?text-(?:left|center|right|justify|start|end|wrap|nowrap|balance|pretty|ellipsis|clip)$/;
|
|
744
|
+
var TEXT_UTILITY = /(?:^|:)!?-?text-/;
|
|
745
|
+
function bypassesMerge(token) {
|
|
746
|
+
return TEXT_UTILITY.test(token) && !MERGE_SAFE_TEXT.test(token);
|
|
747
|
+
}
|
|
748
|
+
function slotClassName(structural, defaults, consumer) {
|
|
749
|
+
if (consumer === void 0 || consumer.trim() === "") return (0, import_utils7.cn)(structural, defaults);
|
|
750
|
+
const tokens = consumer.split(/\s+/).filter(Boolean);
|
|
751
|
+
const verbatim = tokens.filter(bypassesMerge);
|
|
752
|
+
const merged = (0, import_utils7.cn)(structural, tokens.filter((token) => !bypassesMerge(token)));
|
|
753
|
+
return [merged, ...verbatim].filter(Boolean).join(" ");
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// src/components/course-syllabus.tsx
|
|
739
757
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
758
|
+
var DEFAULT_COURSE_SYLLABUS_LABELS = {
|
|
759
|
+
heading: "Programa",
|
|
760
|
+
moduleSingular: "m\xF3dulo",
|
|
761
|
+
modulePlural: "m\xF3dulos",
|
|
762
|
+
lessonSingular: "lecci\xF3n",
|
|
763
|
+
lessonPlural: "lecciones",
|
|
764
|
+
freePreview: "Vista previa gratuita",
|
|
765
|
+
hours: "h",
|
|
766
|
+
minutes: "min",
|
|
767
|
+
expandAll: "Expandir todo",
|
|
768
|
+
collapseAll: "Contraer todo",
|
|
769
|
+
videoLesson: "V\xEDdeo",
|
|
770
|
+
textLesson: "Lectura"
|
|
771
|
+
};
|
|
772
|
+
var SEPARATOR = " \xB7 ";
|
|
773
|
+
function count(n, singular, plural) {
|
|
774
|
+
return `${n} ${n === 1 ? singular : plural}`;
|
|
775
|
+
}
|
|
776
|
+
function formatTotal(seconds, labels) {
|
|
777
|
+
const totalMinutes = Math.max(1, Math.round(seconds / 60));
|
|
778
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
779
|
+
const minutes = totalMinutes % 60;
|
|
780
|
+
if (hours === 0) return `${minutes} ${labels.minutes}`;
|
|
781
|
+
return minutes === 0 ? `${hours} ${labels.hours}` : `${hours} ${labels.hours} ${minutes} ${labels.minutes}`;
|
|
782
|
+
}
|
|
783
|
+
function splitSeconds(seconds) {
|
|
784
|
+
const whole = Math.round(seconds);
|
|
785
|
+
return [Math.floor(whole / 3600), Math.floor(whole % 3600 / 60), whole % 60];
|
|
786
|
+
}
|
|
787
|
+
function formatClock(seconds) {
|
|
788
|
+
const [h, m, s] = splitSeconds(seconds);
|
|
789
|
+
const ss = String(s).padStart(2, "0");
|
|
790
|
+
return h > 0 ? `${h}:${String(m).padStart(2, "0")}:${ss}` : `${m}:${ss}`;
|
|
791
|
+
}
|
|
792
|
+
function isoDuration(seconds) {
|
|
793
|
+
const [h, m, s] = splitSeconds(seconds);
|
|
794
|
+
return `PT${h > 0 ? `${h}H` : ""}${m}M${s}S`;
|
|
795
|
+
}
|
|
796
|
+
function hasDuration(lesson) {
|
|
797
|
+
return typeof lesson.durationSeconds === "number" && lesson.durationSeconds > 0;
|
|
798
|
+
}
|
|
799
|
+
function totalSeconds(lessons) {
|
|
800
|
+
if (lessons.length === 0) return null;
|
|
801
|
+
let total = 0;
|
|
802
|
+
for (const l of lessons) {
|
|
803
|
+
if (!hasDuration(l)) return null;
|
|
804
|
+
total += l.durationSeconds;
|
|
805
|
+
}
|
|
806
|
+
return total;
|
|
807
|
+
}
|
|
808
|
+
function fillTemplate(template, lesson) {
|
|
809
|
+
return template.replaceAll("{lessonSlug}", encodeURIComponent(lesson.slug)).replaceAll("{lessonId}", encodeURIComponent(lesson.id));
|
|
810
|
+
}
|
|
811
|
+
var ICON_PROPS = {
|
|
812
|
+
"aria-hidden": true,
|
|
813
|
+
viewBox: "0 0 24 24",
|
|
814
|
+
fill: "none",
|
|
815
|
+
stroke: "currentColor",
|
|
816
|
+
strokeWidth: 2,
|
|
817
|
+
strokeLinecap: "round",
|
|
818
|
+
strokeLinejoin: "round"
|
|
819
|
+
};
|
|
820
|
+
function LessonIcon({ type }) {
|
|
821
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
822
|
+
"svg",
|
|
823
|
+
{
|
|
824
|
+
...ICON_PROPS,
|
|
825
|
+
"data-slot": "course-syllabus-lesson-icon",
|
|
826
|
+
"data-type": type,
|
|
827
|
+
className: "size-4 shrink-0 text-muted-foreground",
|
|
828
|
+
children: type === "video" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "12", r: "9" }),
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "m10 8.5 5 3.5-5 3.5z" })
|
|
831
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z" }),
|
|
833
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M14 3v5h5M9 13h6M9 17h4" })
|
|
834
|
+
] })
|
|
835
|
+
}
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
function PlayIcon() {
|
|
839
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { ...ICON_PROPS, className: "size-3.5 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "m7 4 13 8-13 8z", fill: "currentColor" }) });
|
|
840
|
+
}
|
|
841
|
+
var PREVIEW_CTA = "inline-flex items-center gap-1.5 rounded-full border border-primary/40 bg-primary/10 px-3 py-1 text-xs font-semibold text-primary transition-colors hover:bg-primary hover:text-primary-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring motion-reduce:transition-none";
|
|
842
|
+
function CourseSyllabus({
|
|
843
|
+
modules,
|
|
844
|
+
labels: labelOverrides,
|
|
845
|
+
headingLevel = 2,
|
|
846
|
+
headingClassName,
|
|
847
|
+
className,
|
|
848
|
+
getPreviewHref,
|
|
849
|
+
previewHrefTemplate,
|
|
850
|
+
onPreview
|
|
851
|
+
}) {
|
|
852
|
+
const labels = { ...DEFAULT_COURSE_SYLLABUS_LABELS, ...labelOverrides };
|
|
853
|
+
const baseId = (0, import_react5.useId)();
|
|
854
|
+
const [open, setOpen] = (0, import_react5.useState)(() => /* @__PURE__ */ new Set());
|
|
855
|
+
if (modules.length === 0) return null;
|
|
856
|
+
const expandable = modules.filter((m) => (m.lessons?.length ?? 0) > 0).map((m) => m.id);
|
|
857
|
+
const allLessons = modules.flatMap((m) => m.lessons ?? []);
|
|
858
|
+
const courseSeconds = totalSeconds(allLessons);
|
|
859
|
+
const summary = [count(modules.length, labels.moduleSingular, labels.modulePlural)];
|
|
860
|
+
if (allLessons.length > 0)
|
|
861
|
+
summary.push(count(allLessons.length, labels.lessonSingular, labels.lessonPlural));
|
|
862
|
+
if (courseSeconds !== null) summary.push(formatTotal(courseSeconds, labels));
|
|
863
|
+
const allOpen = expandable.length > 0 && expandable.every((id) => open.has(id));
|
|
864
|
+
const headingId = `${baseId}-heading`;
|
|
865
|
+
const Tag = `h${headingLevel}`;
|
|
866
|
+
function toggle(id) {
|
|
867
|
+
setOpen((prev) => {
|
|
868
|
+
const next = new Set(prev);
|
|
869
|
+
if (next.has(id)) next.delete(id);
|
|
870
|
+
else next.add(id);
|
|
871
|
+
return next;
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
function previewHref(lesson) {
|
|
875
|
+
if (getPreviewHref) return getPreviewHref(lesson);
|
|
876
|
+
return previewHrefTemplate ? fillTemplate(previewHrefTemplate, lesson) : void 0;
|
|
877
|
+
}
|
|
878
|
+
function renderPreview(lesson) {
|
|
879
|
+
const name = `${labels.freePreview}: ${lesson.title}`;
|
|
880
|
+
const href = previewHref(lesson);
|
|
881
|
+
if (href) {
|
|
882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("a", { href, "aria-label": name, "data-slot": "course-syllabus-preview", className: PREVIEW_CTA, children: [
|
|
883
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PlayIcon, {}),
|
|
884
|
+
labels.freePreview
|
|
885
|
+
] });
|
|
886
|
+
}
|
|
887
|
+
if (onPreview) {
|
|
888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
889
|
+
"button",
|
|
890
|
+
{
|
|
891
|
+
type: "button",
|
|
892
|
+
"aria-label": name,
|
|
893
|
+
"data-slot": "course-syllabus-preview",
|
|
894
|
+
onClick: () => onPreview(lesson),
|
|
895
|
+
className: (0, import_utils8.cn)(PREVIEW_CTA, "cursor-pointer"),
|
|
896
|
+
children: [
|
|
897
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PlayIcon, {}),
|
|
898
|
+
labels.freePreview
|
|
899
|
+
]
|
|
900
|
+
}
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
904
|
+
"span",
|
|
905
|
+
{
|
|
906
|
+
"data-slot": "course-syllabus-preview",
|
|
907
|
+
className: "rounded-full bg-muted px-2.5 py-0.5 text-xs font-medium text-muted-foreground",
|
|
908
|
+
children: labels.freePreview
|
|
909
|
+
}
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
913
|
+
"section",
|
|
914
|
+
{
|
|
915
|
+
"data-slot": "course-syllabus",
|
|
916
|
+
"aria-labelledby": headingId,
|
|
917
|
+
className: (0, import_utils8.cn)("space-y-4", className),
|
|
918
|
+
children: [
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
920
|
+
"div",
|
|
921
|
+
{
|
|
922
|
+
"data-slot": "course-syllabus-header",
|
|
923
|
+
className: "flex flex-wrap items-end justify-between gap-x-4 gap-y-2",
|
|
924
|
+
children: [
|
|
925
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", children: [
|
|
926
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
927
|
+
Tag,
|
|
928
|
+
{
|
|
929
|
+
id: headingId,
|
|
930
|
+
className: slotClassName("", "text-xl font-semibold", headingClassName),
|
|
931
|
+
children: labels.heading
|
|
932
|
+
}
|
|
933
|
+
),
|
|
934
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { "data-slot": "course-syllabus-summary", className: "text-sm text-muted-foreground", children: summary.join(SEPARATOR) })
|
|
935
|
+
] }),
|
|
936
|
+
expandable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
937
|
+
"button",
|
|
938
|
+
{
|
|
939
|
+
type: "button",
|
|
940
|
+
"data-slot": "course-syllabus-toggle-all",
|
|
941
|
+
onClick: () => setOpen(allOpen ? /* @__PURE__ */ new Set() : new Set(expandable)),
|
|
942
|
+
className: "cursor-pointer rounded-md px-2 py-1 text-sm font-semibold text-primary underline-offset-4 hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
|
|
943
|
+
children: allOpen ? labels.collapseAll : labels.expandAll
|
|
944
|
+
}
|
|
945
|
+
)
|
|
946
|
+
]
|
|
947
|
+
}
|
|
948
|
+
),
|
|
949
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ol", { className: "list-none divide-y divide-border overflow-hidden rounded-xl border border-border bg-card p-0", children: modules.map((module2, index) => {
|
|
950
|
+
const lessons = module2.lessons ?? [];
|
|
951
|
+
const number = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
952
|
+
"span",
|
|
953
|
+
{
|
|
954
|
+
"aria-hidden": "true",
|
|
955
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-full bg-primary/10 text-sm font-semibold text-primary tabular-nums",
|
|
956
|
+
children: index + 1
|
|
957
|
+
}
|
|
958
|
+
);
|
|
959
|
+
if (lessons.length === 0) {
|
|
960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
961
|
+
"li",
|
|
962
|
+
{
|
|
963
|
+
"data-slot": "course-syllabus-module",
|
|
964
|
+
className: "flex items-center gap-4 px-4 py-4 sm:px-5",
|
|
965
|
+
children: [
|
|
966
|
+
number,
|
|
967
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "font-semibold leading-snug", children: module2.title })
|
|
968
|
+
]
|
|
969
|
+
},
|
|
970
|
+
module2.id
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
const isOpen = open.has(module2.id);
|
|
974
|
+
const panelId = `${baseId}-module-${index}`;
|
|
975
|
+
const seconds = totalSeconds(lessons);
|
|
976
|
+
const meta = [count(lessons.length, labels.lessonSingular, labels.lessonPlural)];
|
|
977
|
+
if (seconds !== null) meta.push(formatTotal(seconds, labels));
|
|
978
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { "data-slot": "course-syllabus-module", children: [
|
|
979
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
980
|
+
"button",
|
|
981
|
+
{
|
|
982
|
+
type: "button",
|
|
983
|
+
"aria-expanded": isOpen,
|
|
984
|
+
"aria-controls": panelId,
|
|
985
|
+
onClick: () => toggle(module2.id),
|
|
986
|
+
className: (0, import_utils8.cn)(
|
|
987
|
+
"flex w-full cursor-pointer items-center gap-4 px-4 py-4 text-left transition-colors hover:bg-muted/60 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring motion-reduce:transition-none sm:px-5",
|
|
988
|
+
isOpen && "bg-muted/40"
|
|
989
|
+
),
|
|
990
|
+
children: [
|
|
991
|
+
number,
|
|
992
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "font-semibold leading-snug", children: module2.title }),
|
|
994
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm text-muted-foreground", children: meta.join(SEPARATOR) })
|
|
995
|
+
] }),
|
|
996
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
997
|
+
"svg",
|
|
998
|
+
{
|
|
999
|
+
...ICON_PROPS,
|
|
1000
|
+
"data-slot": "course-syllabus-chevron",
|
|
1001
|
+
className: (0, import_utils8.cn)(
|
|
1002
|
+
"size-5 shrink-0 text-muted-foreground transition-transform duration-200 motion-reduce:transition-none",
|
|
1003
|
+
isOpen && "rotate-180"
|
|
1004
|
+
),
|
|
1005
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "m6 9 6 6 6-6" })
|
|
1006
|
+
}
|
|
1007
|
+
)
|
|
1008
|
+
]
|
|
1009
|
+
}
|
|
1010
|
+
),
|
|
1011
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1012
|
+
"ol",
|
|
1013
|
+
{
|
|
1014
|
+
id: panelId,
|
|
1015
|
+
hidden: !isOpen,
|
|
1016
|
+
"data-slot": "course-syllabus-lessons",
|
|
1017
|
+
className: "list-none border-t border-border p-0 py-1",
|
|
1018
|
+
children: lessons.map((lesson) => {
|
|
1019
|
+
const type = lesson.hasVideo ? "video" : "text";
|
|
1020
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1021
|
+
"li",
|
|
1022
|
+
{
|
|
1023
|
+
"data-slot": "course-syllabus-lesson",
|
|
1024
|
+
className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 px-4 py-2.5 text-sm sm:pl-[4.25rem] sm:pr-5",
|
|
1025
|
+
children: [
|
|
1026
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LessonIcon, { type }),
|
|
1027
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "sr-only", children: type === "video" ? labels.videoLesson : labels.textLesson }),
|
|
1028
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1029
|
+
"span",
|
|
1030
|
+
{
|
|
1031
|
+
"data-slot": "course-syllabus-lesson-title",
|
|
1032
|
+
className: "min-w-0 flex-1 leading-snug",
|
|
1033
|
+
children: lesson.title
|
|
1034
|
+
}
|
|
1035
|
+
),
|
|
1036
|
+
lesson.isFreePreview && renderPreview(lesson),
|
|
1037
|
+
hasDuration(lesson) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1038
|
+
"time",
|
|
1039
|
+
{
|
|
1040
|
+
"data-slot": "course-syllabus-lesson-duration",
|
|
1041
|
+
dateTime: isoDuration(lesson.durationSeconds),
|
|
1042
|
+
className: "ml-auto shrink-0 text-muted-foreground tabular-nums",
|
|
1043
|
+
children: formatClock(lesson.durationSeconds)
|
|
1044
|
+
}
|
|
1045
|
+
)
|
|
1046
|
+
]
|
|
1047
|
+
},
|
|
1048
|
+
lesson.id
|
|
1049
|
+
);
|
|
1050
|
+
})
|
|
1051
|
+
}
|
|
1052
|
+
)
|
|
1053
|
+
] }, module2.id);
|
|
1054
|
+
}) })
|
|
1055
|
+
]
|
|
1056
|
+
}
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
// src/components/data-request-form.tsx
|
|
1061
|
+
var import_react6 = require("react");
|
|
1062
|
+
var import_utils9 = require("@reblu/site-ui/utils");
|
|
1063
|
+
var import_site_contracts = require("@reblu/site-contracts");
|
|
1064
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
740
1065
|
var DATA_REQUEST_FIELD_LIMITS = Object.freeze({ name: 200, email: 320, details: 5e3 });
|
|
741
1066
|
var DEFAULT_DATA_REQUEST_FORM_LABELS = {
|
|
742
1067
|
requestTypeLabel: "Derecho que quieres ejercer",
|
|
@@ -762,7 +1087,7 @@ var DEFAULT_DATA_REQUEST_FORM_LABELS = {
|
|
|
762
1087
|
nameRequired: "Indica tu nombre.",
|
|
763
1088
|
emailInvalid: "Introduce un email v\xE1lido.",
|
|
764
1089
|
consentRequired: "Debes aceptar el tratamiento de tus datos para gestionar la solicitud.",
|
|
765
|
-
success: (deadline) => /* @__PURE__ */ (0,
|
|
1090
|
+
success: (deadline) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
766
1091
|
"Hemos recibido tu solicitud. Te responderemos como m\xE1ximo el ",
|
|
767
1092
|
deadline,
|
|
768
1093
|
"."
|
|
@@ -811,18 +1136,18 @@ function DataRequestForm({
|
|
|
811
1136
|
...labels,
|
|
812
1137
|
requestTypes: { ...DEFAULT_DATA_REQUEST_FORM_LABELS.requestTypes, ...labels?.requestTypes }
|
|
813
1138
|
};
|
|
814
|
-
const id = (0,
|
|
815
|
-
const [requestType, setRequestType] = (0,
|
|
816
|
-
const [name, setName] = (0,
|
|
817
|
-
const [email, setEmail] = (0,
|
|
818
|
-
const [details, setDetails] = (0,
|
|
819
|
-
const [consent, setConsent] = (0,
|
|
820
|
-
const [errors, setErrors] = (0,
|
|
821
|
-
const [formError, setFormError] = (0,
|
|
822
|
-
const [submitting, setSubmitting] = (0,
|
|
823
|
-
const [ack, setAck] = (0,
|
|
824
|
-
const statusRef = (0,
|
|
825
|
-
(0,
|
|
1139
|
+
const id = (0, import_react6.useId)();
|
|
1140
|
+
const [requestType, setRequestType] = (0, import_react6.useState)("");
|
|
1141
|
+
const [name, setName] = (0, import_react6.useState)("");
|
|
1142
|
+
const [email, setEmail] = (0, import_react6.useState)("");
|
|
1143
|
+
const [details, setDetails] = (0, import_react6.useState)("");
|
|
1144
|
+
const [consent, setConsent] = (0, import_react6.useState)(false);
|
|
1145
|
+
const [errors, setErrors] = (0, import_react6.useState)({});
|
|
1146
|
+
const [formError, setFormError] = (0, import_react6.useState)(null);
|
|
1147
|
+
const [submitting, setSubmitting] = (0, import_react6.useState)(false);
|
|
1148
|
+
const [ack, setAck] = (0, import_react6.useState)(null);
|
|
1149
|
+
const statusRef = (0, import_react6.useRef)(null);
|
|
1150
|
+
(0, import_react6.useEffect)(() => {
|
|
826
1151
|
if (ack) statusRef.current?.focus();
|
|
827
1152
|
}, [ack]);
|
|
828
1153
|
async function handleSubmit(event) {
|
|
@@ -873,21 +1198,21 @@ function DataRequestForm({
|
|
|
873
1198
|
dateStyle: "long",
|
|
874
1199
|
timeStyle: "short"
|
|
875
1200
|
}).format(new Date(ack.slaDueAt));
|
|
876
|
-
return /* @__PURE__ */ (0,
|
|
1201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
877
1202
|
"div",
|
|
878
1203
|
{
|
|
879
1204
|
ref: statusRef,
|
|
880
1205
|
tabIndex: -1,
|
|
881
1206
|
role: "status",
|
|
882
1207
|
"data-slot": "data-request-form-success",
|
|
883
|
-
className: (0,
|
|
1208
|
+
className: (0, import_utils9.cn)("rounded-lg border border-border p-6 text-sm", className),
|
|
884
1209
|
children: t.success(deadline)
|
|
885
1210
|
}
|
|
886
1211
|
);
|
|
887
1212
|
}
|
|
888
1213
|
const errorId = (field) => errors[field] ? `${id}-${field}-error` : void 0;
|
|
889
|
-
const fieldError = (field) => errors[field] ? /* @__PURE__ */ (0,
|
|
890
|
-
return /* @__PURE__ */ (0,
|
|
1214
|
+
const fieldError = (field) => errors[field] ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { id: `${id}-${field}-error`, className: "text-xs text-destructive", children: errors[field] }) : null;
|
|
1215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
891
1216
|
"form",
|
|
892
1217
|
{
|
|
893
1218
|
noValidate: true,
|
|
@@ -895,11 +1220,11 @@ function DataRequestForm({
|
|
|
895
1220
|
onFocusCapture: onInteract,
|
|
896
1221
|
onPointerDown: onInteract,
|
|
897
1222
|
"data-slot": "data-request-form",
|
|
898
|
-
className: (0,
|
|
1223
|
+
className: (0, import_utils9.cn)("space-y-4", className),
|
|
899
1224
|
children: [
|
|
900
|
-
/* @__PURE__ */ (0,
|
|
901
|
-
/* @__PURE__ */ (0,
|
|
902
|
-
/* @__PURE__ */ (0,
|
|
1225
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1", children: [
|
|
1226
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { htmlFor: `${id}-type`, className: "text-sm font-medium", children: t.requestTypeLabel }),
|
|
1227
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
903
1228
|
"select",
|
|
904
1229
|
{
|
|
905
1230
|
id: `${id}-type`,
|
|
@@ -907,18 +1232,18 @@ function DataRequestForm({
|
|
|
907
1232
|
onChange: (e) => setRequestType(e.target.value),
|
|
908
1233
|
"aria-invalid": errors.requestType ? true : void 0,
|
|
909
1234
|
"aria-describedby": errorId("requestType"),
|
|
910
|
-
className: (0,
|
|
1235
|
+
className: (0, import_utils9.cn)(FIELD_CLASS, errors.requestType ? "border-destructive" : "border-border"),
|
|
911
1236
|
children: [
|
|
912
|
-
/* @__PURE__ */ (0,
|
|
913
|
-
requestTypes.map((type) => /* @__PURE__ */ (0,
|
|
1237
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "", children: t.requestTypePlaceholder }),
|
|
1238
|
+
requestTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: type, children: t.requestTypes[type] }, type))
|
|
914
1239
|
]
|
|
915
1240
|
}
|
|
916
1241
|
),
|
|
917
1242
|
fieldError("requestType")
|
|
918
1243
|
] }),
|
|
919
|
-
/* @__PURE__ */ (0,
|
|
920
|
-
/* @__PURE__ */ (0,
|
|
921
|
-
/* @__PURE__ */ (0,
|
|
1244
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1", children: [
|
|
1245
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { htmlFor: `${id}-name`, className: "text-sm font-medium", children: t.nameLabel }),
|
|
1246
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
922
1247
|
"input",
|
|
923
1248
|
{
|
|
924
1249
|
id: `${id}-name`,
|
|
@@ -929,14 +1254,14 @@ function DataRequestForm({
|
|
|
929
1254
|
onChange: (e) => setName(e.target.value),
|
|
930
1255
|
"aria-invalid": errors.name ? true : void 0,
|
|
931
1256
|
"aria-describedby": errorId("name"),
|
|
932
|
-
className: (0,
|
|
1257
|
+
className: (0, import_utils9.cn)(FIELD_CLASS, errors.name ? "border-destructive" : "border-border")
|
|
933
1258
|
}
|
|
934
1259
|
),
|
|
935
1260
|
fieldError("name")
|
|
936
1261
|
] }),
|
|
937
|
-
/* @__PURE__ */ (0,
|
|
938
|
-
/* @__PURE__ */ (0,
|
|
939
|
-
/* @__PURE__ */ (0,
|
|
1262
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1", children: [
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { htmlFor: `${id}-email`, className: "text-sm font-medium", children: t.emailLabel }),
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
940
1265
|
"input",
|
|
941
1266
|
{
|
|
942
1267
|
id: `${id}-email`,
|
|
@@ -947,14 +1272,14 @@ function DataRequestForm({
|
|
|
947
1272
|
onChange: (e) => setEmail(e.target.value),
|
|
948
1273
|
"aria-invalid": errors.email ? true : void 0,
|
|
949
1274
|
"aria-describedby": errorId("email"),
|
|
950
|
-
className: (0,
|
|
1275
|
+
className: (0, import_utils9.cn)(FIELD_CLASS, errors.email ? "border-destructive" : "border-border")
|
|
951
1276
|
}
|
|
952
1277
|
),
|
|
953
1278
|
fieldError("email")
|
|
954
1279
|
] }),
|
|
955
|
-
/* @__PURE__ */ (0,
|
|
956
|
-
/* @__PURE__ */ (0,
|
|
957
|
-
/* @__PURE__ */ (0,
|
|
1280
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1", children: [
|
|
1281
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { htmlFor: `${id}-details`, className: "text-sm font-medium", children: t.detailsLabel }),
|
|
1282
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
958
1283
|
"textarea",
|
|
959
1284
|
{
|
|
960
1285
|
id: `${id}-details`,
|
|
@@ -963,13 +1288,13 @@ function DataRequestForm({
|
|
|
963
1288
|
value: details,
|
|
964
1289
|
onChange: (e) => setDetails(e.target.value),
|
|
965
1290
|
placeholder: t.detailsPlaceholder,
|
|
966
|
-
className: (0,
|
|
1291
|
+
className: (0, import_utils9.cn)(FIELD_CLASS, "border-border")
|
|
967
1292
|
}
|
|
968
1293
|
)
|
|
969
1294
|
] }),
|
|
970
|
-
/* @__PURE__ */ (0,
|
|
971
|
-
/* @__PURE__ */ (0,
|
|
972
|
-
/* @__PURE__ */ (0,
|
|
1295
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1", children: [
|
|
1296
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-start gap-2", children: [
|
|
1297
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
973
1298
|
"input",
|
|
974
1299
|
{
|
|
975
1300
|
id: `${id}-consent`,
|
|
@@ -981,12 +1306,12 @@ function DataRequestForm({
|
|
|
981
1306
|
className: "mt-1"
|
|
982
1307
|
}
|
|
983
1308
|
),
|
|
984
|
-
/* @__PURE__ */ (0,
|
|
1309
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { htmlFor: `${id}-consent`, className: "text-sm text-foreground/80", children: t.consent })
|
|
985
1310
|
] }),
|
|
986
1311
|
fieldError("consent")
|
|
987
1312
|
] }),
|
|
988
|
-
formError && /* @__PURE__ */ (0,
|
|
989
|
-
/* @__PURE__ */ (0,
|
|
1313
|
+
formError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { role: "alert", className: "text-sm text-destructive", children: formError }),
|
|
1314
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
990
1315
|
"button",
|
|
991
1316
|
{
|
|
992
1317
|
type: "submit",
|
|
@@ -1004,8 +1329,10 @@ function DataRequestForm({
|
|
|
1004
1329
|
AddToCartButton,
|
|
1005
1330
|
CartIcon,
|
|
1006
1331
|
Collection,
|
|
1332
|
+
CourseSyllabus,
|
|
1007
1333
|
DATA_REQUEST_FIELD_LIMITS,
|
|
1008
1334
|
DATA_REQUEST_TYPES,
|
|
1335
|
+
DEFAULT_COURSE_SYLLABUS_LABELS,
|
|
1009
1336
|
DEFAULT_DATA_REQUEST_FORM_LABELS,
|
|
1010
1337
|
DEFAULT_PRODUCT_CAROUSEL_LABELS,
|
|
1011
1338
|
DataRequestForm,
|