@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/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: (count) => `${count} art\xEDculo${count === 1 ? "" : "s"}`
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/data-request-form.tsx
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 import_site_contracts = require("@reblu/site-contracts");
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, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
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, 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)(() => {
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, import_jsx_runtime8.jsx)(
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, import_utils7.cn)("rounded-lg border border-border p-6 text-sm", className),
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, 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)(
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, import_utils7.cn)("space-y-4", className),
1223
+ className: (0, import_utils9.cn)("space-y-4", className),
899
1224
  children: [
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)(
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, import_utils7.cn)(FIELD_CLASS, errors.requestType ? "border-destructive" : "border-border"),
1235
+ className: (0, import_utils9.cn)(FIELD_CLASS, errors.requestType ? "border-destructive" : "border-border"),
911
1236
  children: [
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))
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, 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)(
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, import_utils7.cn)(FIELD_CLASS, errors.name ? "border-destructive" : "border-border")
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, 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)(
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, import_utils7.cn)(FIELD_CLASS, errors.email ? "border-destructive" : "border-border")
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, 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)(
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, import_utils7.cn)(FIELD_CLASS, "border-border")
1291
+ className: (0, import_utils9.cn)(FIELD_CLASS, "border-border")
967
1292
  }
968
1293
  )
969
1294
  ] }),
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)(
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, import_jsx_runtime8.jsx)("label", { htmlFor: `${id}-consent`, className: "text-sm text-foreground/80", children: t.consent })
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, import_jsx_runtime8.jsx)("p", { role: "alert", className: "text-sm text-destructive", children: formError }),
989
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
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,