@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.
- package/dist/forms/index.d.mts +14 -1
- package/dist/forms/index.d.ts +14 -1
- package/dist/forms/index.js +260 -5
- package/dist/forms/index.js.map +1 -1
- package/dist/forms/index.mjs +261 -7
- package/dist/forms/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/forms/index.d.mts
CHANGED
|
@@ -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
|
-
|
|
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 };
|
package/dist/forms/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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 };
|
package/dist/forms/index.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
1068
|
-
|
|
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;
|