@sonordev/site-kit 2.2.2 → 2.2.3

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.
@@ -439,4 +439,17 @@ declare function useFormTracking({ formId, totalSteps, enabled, debug, }: UseFor
439
439
  /** Shown when the API omits or returns an empty `success_message`. */
440
440
  declare const DEFAULT_FORM_SUCCESS_MESSAGE = "Thank you for your submission! We will be in touch soon.";
441
441
 
442
- export { type CreateFormInput, DEFAULT_FORM_SUCCESS_MESSAGE, type FieldType, type Form, FormClient, type FormDefinition, type FormField$1 as FormField, FormField as FormFieldComponent, FormField$2 as FormFieldConfig, type FormStep, FormSubmission, type FormType, type FormsListOptions, ManagedForm, ManagedFormConfig, type UpdateFormInput, type UseFormOptions, type UseFormReturn, configureFormsApi, defineForm, field, formsApi, initializeForms, useForm, useFormTracking };
442
+ interface DatePickerProps {
443
+ value: string;
444
+ onChange: (value: string) => void;
445
+ id?: string;
446
+ name?: string;
447
+ required?: boolean;
448
+ minDate?: string;
449
+ placeholder?: string;
450
+ className?: string;
451
+ style?: React__default.CSSProperties;
452
+ }
453
+ declare function DatePicker({ value, onChange, id, name, required, minDate, placeholder, className, style, }: DatePickerProps): react_jsx_runtime.JSX.Element;
454
+
455
+ export { type CreateFormInput, DEFAULT_FORM_SUCCESS_MESSAGE, DatePicker, type FieldType, type Form, FormClient, type FormDefinition, type FormField$1 as FormField, FormField as FormFieldComponent, FormField$2 as FormFieldConfig, type FormStep, FormSubmission, type FormType, type FormsListOptions, ManagedForm, ManagedFormConfig, type UpdateFormInput, type UseFormOptions, type UseFormReturn, configureFormsApi, defineForm, field, formsApi, initializeForms, useForm, useFormTracking };
@@ -439,4 +439,17 @@ declare function useFormTracking({ formId, totalSteps, enabled, debug, }: UseFor
439
439
  /** Shown when the API omits or returns an empty `success_message`. */
440
440
  declare const DEFAULT_FORM_SUCCESS_MESSAGE = "Thank you for your submission! We will be in touch soon.";
441
441
 
442
- export { type CreateFormInput, DEFAULT_FORM_SUCCESS_MESSAGE, type FieldType, type Form, FormClient, type FormDefinition, type FormField$1 as FormField, FormField as FormFieldComponent, FormField$2 as FormFieldConfig, type FormStep, FormSubmission, type FormType, type FormsListOptions, ManagedForm, ManagedFormConfig, type UpdateFormInput, type UseFormOptions, type UseFormReturn, configureFormsApi, defineForm, field, formsApi, initializeForms, useForm, useFormTracking };
442
+ interface DatePickerProps {
443
+ value: string;
444
+ onChange: (value: string) => void;
445
+ id?: string;
446
+ name?: string;
447
+ required?: boolean;
448
+ minDate?: string;
449
+ placeholder?: string;
450
+ className?: string;
451
+ style?: React__default.CSSProperties;
452
+ }
453
+ declare function DatePicker({ value, onChange, id, name, required, minDate, placeholder, className, style, }: DatePickerProps): react_jsx_runtime.JSX.Element;
454
+
455
+ export { type CreateFormInput, DEFAULT_FORM_SUCCESS_MESSAGE, DatePicker, type FieldType, type Form, FormClient, type FormDefinition, type FormField$1 as FormField, FormField as FormFieldComponent, FormField$2 as FormFieldConfig, type FormStep, FormSubmission, type FormType, type FormsListOptions, ManagedForm, ManagedFormConfig, type UpdateFormInput, type UseFormOptions, type UseFormReturn, configureFormsApi, defineForm, field, formsApi, initializeForms, useForm, useFormTracking };
@@ -885,6 +885,261 @@ function useForm(formIdOrSlug, options = {}) {
885
885
  reset
886
886
  };
887
887
  }
888
+ var DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
889
+ var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
890
+ function pad(n) {
891
+ return n < 10 ? `0${n}` : `${n}`;
892
+ }
893
+ function toDateStr(y, m, d) {
894
+ return `${y}-${pad(m + 1)}-${pad(d)}`;
895
+ }
896
+ function parseDate(str) {
897
+ if (!str) return null;
898
+ const [y, m, d] = str.split("-").map(Number);
899
+ if (!y || !m || !d) return null;
900
+ return { year: y, month: m - 1, day: d };
901
+ }
902
+ function getDaysInMonth(year, month) {
903
+ return new Date(year, month + 1, 0).getDate();
904
+ }
905
+ function getFirstDayOfMonth(year, month) {
906
+ return new Date(year, month, 1).getDay();
907
+ }
908
+ function formatDisplay(dateStr) {
909
+ const parsed = parseDate(dateStr);
910
+ if (!parsed) return "";
911
+ return `${MONTHS[parsed.month]} ${parsed.day}, ${parsed.year}`;
912
+ }
913
+ function DatePicker({
914
+ value,
915
+ onChange,
916
+ id,
917
+ name,
918
+ required,
919
+ minDate,
920
+ placeholder = "Select a date",
921
+ className = "",
922
+ style
923
+ }) {
924
+ const today = /* @__PURE__ */ new Date();
925
+ const todayStr = toDateStr(today.getFullYear(), today.getMonth(), today.getDate());
926
+ const effectiveMin = minDate || todayStr;
927
+ const parsed = parseDate(value);
928
+ const [viewYear, setViewYear] = react.useState(parsed?.year || today.getFullYear());
929
+ const [viewMonth, setViewMonth] = react.useState(parsed?.month ?? today.getMonth());
930
+ const [open, setOpen] = react.useState(false);
931
+ const containerRef = react.useRef(null);
932
+ react.useEffect(() => {
933
+ if (!open) return;
934
+ const handler = (e) => {
935
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
936
+ setOpen(false);
937
+ }
938
+ };
939
+ document.addEventListener("mousedown", handler);
940
+ return () => document.removeEventListener("mousedown", handler);
941
+ }, [open]);
942
+ react.useEffect(() => {
943
+ if (!open) return;
944
+ const handler = (e) => {
945
+ if (e.key === "Escape") setOpen(false);
946
+ };
947
+ window.addEventListener("keydown", handler);
948
+ return () => window.removeEventListener("keydown", handler);
949
+ }, [open]);
950
+ const prevMonth = react.useCallback(() => {
951
+ if (viewMonth === 0) {
952
+ setViewMonth(11);
953
+ setViewYear((y) => y - 1);
954
+ } else setViewMonth((m) => m - 1);
955
+ }, [viewMonth]);
956
+ const nextMonth = react.useCallback(() => {
957
+ if (viewMonth === 11) {
958
+ setViewMonth(0);
959
+ setViewYear((y) => y + 1);
960
+ } else setViewMonth((m) => m + 1);
961
+ }, [viewMonth]);
962
+ const selectDay = react.useCallback((day) => {
963
+ const dateStr = toDateStr(viewYear, viewMonth, day);
964
+ onChange(dateStr);
965
+ setOpen(false);
966
+ }, [viewYear, viewMonth, onChange]);
967
+ const isDisabled = react.useCallback((day) => {
968
+ const dateStr = toDateStr(viewYear, viewMonth, day);
969
+ return dateStr < effectiveMin;
970
+ }, [viewYear, viewMonth, effectiveMin]);
971
+ const isSelected = react.useCallback((day) => {
972
+ if (!value) return false;
973
+ return toDateStr(viewYear, viewMonth, day) === value;
974
+ }, [viewYear, viewMonth, value]);
975
+ const isToday = react.useCallback((day) => {
976
+ return toDateStr(viewYear, viewMonth, day) === todayStr;
977
+ }, [viewYear, viewMonth, todayStr]);
978
+ const daysInMonth = getDaysInMonth(viewYear, viewMonth);
979
+ const firstDay = getFirstDayOfMonth(viewYear, viewMonth);
980
+ const weeks = [];
981
+ let week = Array(firstDay).fill(null);
982
+ for (let d = 1; d <= daysInMonth; d++) {
983
+ week.push(d);
984
+ if (week.length === 7) {
985
+ weeks.push(week);
986
+ week = [];
987
+ }
988
+ }
989
+ if (week.length > 0) {
990
+ while (week.length < 7) week.push(null);
991
+ weeks.push(week);
992
+ }
993
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: `sk-datepicker ${className}`, style: { position: "relative", ...style }, children: [
994
+ /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: value || "" }),
995
+ /* @__PURE__ */ jsxRuntime.jsxs(
996
+ "button",
997
+ {
998
+ type: "button",
999
+ id,
1000
+ onClick: () => setOpen(!open),
1001
+ "aria-required": required,
1002
+ "aria-expanded": open,
1003
+ style: {
1004
+ display: "flex",
1005
+ alignItems: "center",
1006
+ justifyContent: "space-between",
1007
+ width: "100%",
1008
+ padding: "var(--sk-input-padding, 10px 12px)",
1009
+ backgroundColor: "var(--sk-input-bg, #fff)",
1010
+ border: `1px solid ${open ? "var(--sk-input-border-focus, #3b82f6)" : "var(--sk-input-border, #d1d5db)"}`,
1011
+ borderRadius: "var(--sk-input-radius, 0.375rem)",
1012
+ fontSize: "var(--sk-font-size, 14px)",
1013
+ color: value ? "var(--sk-form-success-text, #111)" : "var(--sk-text-tertiary, #9ca3af)",
1014
+ cursor: "pointer",
1015
+ outline: "none",
1016
+ textAlign: "left"
1017
+ },
1018
+ children: [
1019
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: value ? formatDisplay(value) : placeholder }),
1020
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { opacity: 0.5, flexShrink: 0 }, children: [
1021
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
1022
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
1023
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
1024
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
1025
+ ] })
1026
+ ]
1027
+ }
1028
+ ),
1029
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
1030
+ "div",
1031
+ {
1032
+ style: {
1033
+ position: "absolute",
1034
+ top: "100%",
1035
+ left: 0,
1036
+ right: 0,
1037
+ marginTop: "4px",
1038
+ backgroundColor: "var(--sk-input-bg, #fff)",
1039
+ border: "1px solid var(--sk-input-border, #d1d5db)",
1040
+ borderRadius: "var(--sk-input-radius, 0.375rem)",
1041
+ boxShadow: "0 10px 25px rgba(0,0,0,0.3)",
1042
+ zIndex: 50,
1043
+ padding: "12px",
1044
+ minWidth: "280px"
1045
+ },
1046
+ children: [
1047
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "12px" }, children: [
1048
+ /* @__PURE__ */ jsxRuntime.jsx(
1049
+ "button",
1050
+ {
1051
+ type: "button",
1052
+ onClick: prevMonth,
1053
+ style: { background: "none", border: "none", cursor: "pointer", padding: "4px 8px", color: "var(--sk-label-color, #6b7280)", fontSize: "18px", lineHeight: 1 },
1054
+ "aria-label": "Previous month",
1055
+ children: "\u2039"
1056
+ }
1057
+ ),
1058
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontWeight: 600, fontSize: "14px", color: "var(--sk-form-success-text, #111)" }, children: [
1059
+ MONTHS[viewMonth],
1060
+ " ",
1061
+ viewYear
1062
+ ] }),
1063
+ /* @__PURE__ */ jsxRuntime.jsx(
1064
+ "button",
1065
+ {
1066
+ type: "button",
1067
+ onClick: nextMonth,
1068
+ style: { background: "none", border: "none", cursor: "pointer", padding: "4px 8px", color: "var(--sk-label-color, #6b7280)", fontSize: "18px", lineHeight: 1 },
1069
+ "aria-label": "Next month",
1070
+ children: "\u203A"
1071
+ }
1072
+ )
1073
+ ] }),
1074
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: "2px", marginBottom: "4px" }, children: DAYS.map((d) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", fontSize: "11px", fontWeight: 600, color: "var(--sk-text-tertiary, #9ca3af)", padding: "4px 0", textTransform: "uppercase", letterSpacing: "0.05em" }, children: d }, d)) }),
1075
+ weeks.map((week2, wi) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: "2px" }, children: week2.map((day, di) => {
1076
+ if (day === null) {
1077
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px" } }, di);
1078
+ }
1079
+ const disabled = isDisabled(day);
1080
+ const selected = isSelected(day);
1081
+ const todayMark = isToday(day);
1082
+ return /* @__PURE__ */ jsxRuntime.jsx(
1083
+ "button",
1084
+ {
1085
+ type: "button",
1086
+ disabled,
1087
+ onClick: () => selectDay(day),
1088
+ style: {
1089
+ padding: "6px",
1090
+ textAlign: "center",
1091
+ fontSize: "13px",
1092
+ fontWeight: selected ? 700 : todayMark ? 600 : 400,
1093
+ borderRadius: "6px",
1094
+ border: todayMark && !selected ? "1px solid var(--sk-primary, #3b82f6)" : "1px solid transparent",
1095
+ background: selected ? "var(--sk-primary, #3b82f6)" : "transparent",
1096
+ color: disabled ? "var(--sk-text-tertiary, #9ca3af)" : selected ? "#fff" : "var(--sk-form-success-text, #111)",
1097
+ cursor: disabled ? "not-allowed" : "pointer",
1098
+ opacity: disabled ? 0.4 : 1,
1099
+ transition: "background 0.15s, color 0.15s"
1100
+ },
1101
+ onMouseEnter: (e) => {
1102
+ if (!disabled && !selected) {
1103
+ e.target.style.background = "var(--sk-input-border, #e5e7eb)";
1104
+ }
1105
+ },
1106
+ onMouseLeave: (e) => {
1107
+ if (!disabled && !selected) {
1108
+ e.target.style.background = "transparent";
1109
+ }
1110
+ },
1111
+ "aria-label": `${MONTHS[viewMonth]} ${day}, ${viewYear}`,
1112
+ "aria-selected": selected,
1113
+ children: day
1114
+ },
1115
+ di
1116
+ );
1117
+ }) }, wi)),
1118
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "8px", textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1119
+ "button",
1120
+ {
1121
+ type: "button",
1122
+ onClick: () => {
1123
+ onChange(todayStr);
1124
+ setOpen(false);
1125
+ },
1126
+ style: {
1127
+ background: "none",
1128
+ border: "none",
1129
+ cursor: "pointer",
1130
+ fontSize: "12px",
1131
+ fontWeight: 600,
1132
+ color: "var(--sk-primary, #3b82f6)",
1133
+ padding: "4px 8px"
1134
+ },
1135
+ children: "Today"
1136
+ }
1137
+ ) })
1138
+ ]
1139
+ }
1140
+ )
1141
+ ] });
1142
+ }
888
1143
  function normalizeOptions(options) {
889
1144
  if (!options) return [];
890
1145
  if (Array.isArray(options)) {
@@ -1056,16 +1311,15 @@ function FormField({ field: field2, value, error, onChange, classPrefix = "sk-fo
1056
1311
  ] }, option.value);
1057
1312
  }) }),
1058
1313
  field2.field_type === "date" && /* @__PURE__ */ jsxRuntime.jsx(
1059
- "input",
1314
+ DatePicker,
1060
1315
  {
1061
1316
  id: inputId,
1062
- className: `${classPrefix}__input ${classPrefix}__input--date`,
1063
- type: "date",
1064
1317
  name: field2.slug,
1065
1318
  value: String(value || ""),
1319
+ onChange,
1066
1320
  required: field2.is_required,
1067
- onChange: (e) => onChange(e.target.value),
1068
- style: baseInputStyle
1321
+ placeholder: field2.placeholder || "Select a date",
1322
+ className: `${classPrefix}__input ${classPrefix}__input--date`
1069
1323
  }
1070
1324
  ),
1071
1325
  field2.field_type === "time" && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1505,6 +1759,7 @@ function ManagedForm({
1505
1759
  }
1506
1760
 
1507
1761
  exports.DEFAULT_FORM_SUCCESS_MESSAGE = DEFAULT_FORM_SUCCESS_MESSAGE;
1762
+ exports.DatePicker = DatePicker;
1508
1763
  exports.FormClient = FormClient;
1509
1764
  exports.FormFieldComponent = FormField;
1510
1765
  exports.ManagedForm = ManagedForm;