@bookinglab/booking-ui-react 1.13.0 → 1.15.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/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +34 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +34 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -810,6 +810,15 @@ interface QuestionSettings {
|
|
|
810
810
|
max?: number;
|
|
811
811
|
placeholder?: string;
|
|
812
812
|
}
|
|
813
|
+
interface DateLimiter {
|
|
814
|
+
enabled: boolean;
|
|
815
|
+
/** ISO date string (e.g. "2025-01-01" or full ISO 8601). Only the date portion is used. */
|
|
816
|
+
minimumDate?: string;
|
|
817
|
+
/** ISO date string (e.g. "2025-12-31" or full ISO 8601). Only the date portion is used. */
|
|
818
|
+
maximumDate?: string;
|
|
819
|
+
/** Custom error message shown when the entered date falls outside the configured range. */
|
|
820
|
+
errorText?: string;
|
|
821
|
+
}
|
|
813
822
|
interface Question {
|
|
814
823
|
id: number;
|
|
815
824
|
name: string;
|
|
@@ -828,6 +837,8 @@ interface Question {
|
|
|
828
837
|
hide_on_customer_journey?: boolean;
|
|
829
838
|
/** Whether the question field is disabled */
|
|
830
839
|
disabled?: boolean;
|
|
840
|
+
/** Optional date validation config. Only applies when detail_type is 'date'. */
|
|
841
|
+
dateLimiter?: DateLimiter;
|
|
831
842
|
}
|
|
832
843
|
type FormValues = Record<number, string | number | boolean>;
|
|
833
844
|
type FormErrors = Record<number, string>;
|
|
@@ -869,8 +880,14 @@ interface BookingFormClassNames {
|
|
|
869
880
|
dateInputItem?: string;
|
|
870
881
|
/** Small "Day"/"Month"/"Year" label */
|
|
871
882
|
dateInputLabel?: string;
|
|
872
|
-
/** Date sub-input element (falls back to `input` / `inputError`) */
|
|
883
|
+
/** Date sub-input element (falls back to `input` / `inputError`). Applies to all 3 inputs unless overridden by dateInputDay/Month/Year. */
|
|
873
884
|
dateInput?: string;
|
|
885
|
+
/** Day input specifically (falls back to `dateInput`) */
|
|
886
|
+
dateInputDay?: string;
|
|
887
|
+
/** Month input specifically (falls back to `dateInput`) */
|
|
888
|
+
dateInputMonth?: string;
|
|
889
|
+
/** Year input specifically (falls back to `dateInput`) */
|
|
890
|
+
dateInputYear?: string;
|
|
874
891
|
}
|
|
875
892
|
interface BookingFormProps {
|
|
876
893
|
questions: Question[];
|
|
@@ -1017,4 +1034,4 @@ declare function minLen(min: number): (value: string) => string | null;
|
|
|
1017
1034
|
*/
|
|
1018
1035
|
declare function compose(...validators: Array<(value: string) => string | null>): (value: string) => string | null;
|
|
1019
1036
|
|
|
1020
|
-
export { type AppConfig, type AwsLookupConfig, type AwsLookupMatchEntry, type AwsLookupSetPayload, BookingForm, type BookingFormClassNames, type BookingFormProps, type BookingUIConfig, type ConditionClause, type ContactDetailsAnswerEntry, type ContactDetailsFieldSettings, ContactDetailsForm, type ContactDetailsFormClassNames, type ContactDetailsFormProps, type ContactDetailsFormRef, type ContactDetailsInitialValues, type ContactDetailsQuestionEntry, type ContactDetailsValues, type ContactFieldSettings, type CopyDataConfig, type DropdownOption, type ExtraItemEntry, type FieldConfig, type FieldError, type FieldOption, type FormErrors, type FormReadyPayload, type FormSchemaStatus, type FormValues, type Question, type QuestionOption, type QuestionSettings, type RadioOption, type RawSchemaField, type RegistrationFieldSettings, RegistrationForm, type RegistrationFormClassNames, type RegistrationFormErrors, type RegistrationFormProps, type RegistrationFormRef, type RegistrationFormValues, ResetPasswordForm, type ResetPasswordFormClassNames, type ResetPasswordFormProps, type ResetPasswordFormRef, type ResetPasswordFormValues, type SchemaField, SchemaFormBuilder, type SchemaFormBuilderProps, type ShowRules, type UpdateDatastorePayload, type ValidationMaxDate, type ValidationMaxLength, type ValidationMinDate, type ValidationMinLength, type ValidationRule, type ValidationShorthand, type VenueSetPayload, compose, email, hydrateField, minLen, phone, required, ukPostcode };
|
|
1037
|
+
export { type AppConfig, type AwsLookupConfig, type AwsLookupMatchEntry, type AwsLookupSetPayload, BookingForm, type BookingFormClassNames, type BookingFormProps, type BookingUIConfig, type ConditionClause, type ContactDetailsAnswerEntry, type ContactDetailsFieldSettings, ContactDetailsForm, type ContactDetailsFormClassNames, type ContactDetailsFormProps, type ContactDetailsFormRef, type ContactDetailsInitialValues, type ContactDetailsQuestionEntry, type ContactDetailsValues, type ContactFieldSettings, type CopyDataConfig, type DateLimiter, type DropdownOption, type ExtraItemEntry, type FieldConfig, type FieldError, type FieldOption, type FormErrors, type FormReadyPayload, type FormSchemaStatus, type FormValues, type Question, type QuestionOption, type QuestionSettings, type RadioOption, type RawSchemaField, type RegistrationFieldSettings, RegistrationForm, type RegistrationFormClassNames, type RegistrationFormErrors, type RegistrationFormProps, type RegistrationFormRef, type RegistrationFormValues, ResetPasswordForm, type ResetPasswordFormClassNames, type ResetPasswordFormProps, type ResetPasswordFormRef, type ResetPasswordFormValues, type SchemaField, SchemaFormBuilder, type SchemaFormBuilderProps, type ShowRules, type UpdateDatastorePayload, type ValidationMaxDate, type ValidationMaxLength, type ValidationMinDate, type ValidationMinLength, type ValidationRule, type ValidationShorthand, type VenueSetPayload, compose, email, hydrateField, minLen, phone, required, ukPostcode };
|
package/dist/index.d.ts
CHANGED
|
@@ -810,6 +810,15 @@ interface QuestionSettings {
|
|
|
810
810
|
max?: number;
|
|
811
811
|
placeholder?: string;
|
|
812
812
|
}
|
|
813
|
+
interface DateLimiter {
|
|
814
|
+
enabled: boolean;
|
|
815
|
+
/** ISO date string (e.g. "2025-01-01" or full ISO 8601). Only the date portion is used. */
|
|
816
|
+
minimumDate?: string;
|
|
817
|
+
/** ISO date string (e.g. "2025-12-31" or full ISO 8601). Only the date portion is used. */
|
|
818
|
+
maximumDate?: string;
|
|
819
|
+
/** Custom error message shown when the entered date falls outside the configured range. */
|
|
820
|
+
errorText?: string;
|
|
821
|
+
}
|
|
813
822
|
interface Question {
|
|
814
823
|
id: number;
|
|
815
824
|
name: string;
|
|
@@ -828,6 +837,8 @@ interface Question {
|
|
|
828
837
|
hide_on_customer_journey?: boolean;
|
|
829
838
|
/** Whether the question field is disabled */
|
|
830
839
|
disabled?: boolean;
|
|
840
|
+
/** Optional date validation config. Only applies when detail_type is 'date'. */
|
|
841
|
+
dateLimiter?: DateLimiter;
|
|
831
842
|
}
|
|
832
843
|
type FormValues = Record<number, string | number | boolean>;
|
|
833
844
|
type FormErrors = Record<number, string>;
|
|
@@ -869,8 +880,14 @@ interface BookingFormClassNames {
|
|
|
869
880
|
dateInputItem?: string;
|
|
870
881
|
/** Small "Day"/"Month"/"Year" label */
|
|
871
882
|
dateInputLabel?: string;
|
|
872
|
-
/** Date sub-input element (falls back to `input` / `inputError`) */
|
|
883
|
+
/** Date sub-input element (falls back to `input` / `inputError`). Applies to all 3 inputs unless overridden by dateInputDay/Month/Year. */
|
|
873
884
|
dateInput?: string;
|
|
885
|
+
/** Day input specifically (falls back to `dateInput`) */
|
|
886
|
+
dateInputDay?: string;
|
|
887
|
+
/** Month input specifically (falls back to `dateInput`) */
|
|
888
|
+
dateInputMonth?: string;
|
|
889
|
+
/** Year input specifically (falls back to `dateInput`) */
|
|
890
|
+
dateInputYear?: string;
|
|
874
891
|
}
|
|
875
892
|
interface BookingFormProps {
|
|
876
893
|
questions: Question[];
|
|
@@ -1017,4 +1034,4 @@ declare function minLen(min: number): (value: string) => string | null;
|
|
|
1017
1034
|
*/
|
|
1018
1035
|
declare function compose(...validators: Array<(value: string) => string | null>): (value: string) => string | null;
|
|
1019
1036
|
|
|
1020
|
-
export { type AppConfig, type AwsLookupConfig, type AwsLookupMatchEntry, type AwsLookupSetPayload, BookingForm, type BookingFormClassNames, type BookingFormProps, type BookingUIConfig, type ConditionClause, type ContactDetailsAnswerEntry, type ContactDetailsFieldSettings, ContactDetailsForm, type ContactDetailsFormClassNames, type ContactDetailsFormProps, type ContactDetailsFormRef, type ContactDetailsInitialValues, type ContactDetailsQuestionEntry, type ContactDetailsValues, type ContactFieldSettings, type CopyDataConfig, type DropdownOption, type ExtraItemEntry, type FieldConfig, type FieldError, type FieldOption, type FormErrors, type FormReadyPayload, type FormSchemaStatus, type FormValues, type Question, type QuestionOption, type QuestionSettings, type RadioOption, type RawSchemaField, type RegistrationFieldSettings, RegistrationForm, type RegistrationFormClassNames, type RegistrationFormErrors, type RegistrationFormProps, type RegistrationFormRef, type RegistrationFormValues, ResetPasswordForm, type ResetPasswordFormClassNames, type ResetPasswordFormProps, type ResetPasswordFormRef, type ResetPasswordFormValues, type SchemaField, SchemaFormBuilder, type SchemaFormBuilderProps, type ShowRules, type UpdateDatastorePayload, type ValidationMaxDate, type ValidationMaxLength, type ValidationMinDate, type ValidationMinLength, type ValidationRule, type ValidationShorthand, type VenueSetPayload, compose, email, hydrateField, minLen, phone, required, ukPostcode };
|
|
1037
|
+
export { type AppConfig, type AwsLookupConfig, type AwsLookupMatchEntry, type AwsLookupSetPayload, BookingForm, type BookingFormClassNames, type BookingFormProps, type BookingUIConfig, type ConditionClause, type ContactDetailsAnswerEntry, type ContactDetailsFieldSettings, ContactDetailsForm, type ContactDetailsFormClassNames, type ContactDetailsFormProps, type ContactDetailsFormRef, type ContactDetailsInitialValues, type ContactDetailsQuestionEntry, type ContactDetailsValues, type ContactFieldSettings, type CopyDataConfig, type DateLimiter, type DropdownOption, type ExtraItemEntry, type FieldConfig, type FieldError, type FieldOption, type FormErrors, type FormReadyPayload, type FormSchemaStatus, type FormValues, type Question, type QuestionOption, type QuestionSettings, type RadioOption, type RawSchemaField, type RegistrationFieldSettings, RegistrationForm, type RegistrationFormClassNames, type RegistrationFormErrors, type RegistrationFormProps, type RegistrationFormRef, type RegistrationFormValues, ResetPasswordForm, type ResetPasswordFormClassNames, type ResetPasswordFormProps, type ResetPasswordFormRef, type ResetPasswordFormValues, type SchemaField, SchemaFormBuilder, type SchemaFormBuilderProps, type ShowRules, type UpdateDatastorePayload, type ValidationMaxDate, type ValidationMaxLength, type ValidationMinDate, type ValidationMinLength, type ValidationRule, type ValidationShorthand, type VenueSetPayload, compose, email, hydrateField, minLen, phone, required, ukPostcode };
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,9 @@ function DateInputGroup({
|
|
|
24
24
|
itemCls,
|
|
25
25
|
sublabelCls,
|
|
26
26
|
dateInputCls,
|
|
27
|
+
dayInputCls,
|
|
28
|
+
monthInputCls,
|
|
29
|
+
yearInputCls,
|
|
27
30
|
helpTextAbove,
|
|
28
31
|
helpTextBelow,
|
|
29
32
|
renderError
|
|
@@ -63,7 +66,7 @@ function DateInputGroup({
|
|
|
63
66
|
return /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className: fieldsetCls, "aria-describedby": hasError ? errorId : void 0, children: [
|
|
64
67
|
/* @__PURE__ */ jsxRuntime.jsxs("legend", { className: legendCls, children: [
|
|
65
68
|
question.name,
|
|
66
|
-
question.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
69
|
+
question.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", style: { color: "#DD2D1D" }, "aria-hidden": "true", children: "*" })
|
|
67
70
|
] }),
|
|
68
71
|
helpTextAbove,
|
|
69
72
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: groupCls, role: "group", children: [
|
|
@@ -79,7 +82,7 @@ function DateInputGroup({
|
|
|
79
82
|
maxLength: 2,
|
|
80
83
|
value: parts.day,
|
|
81
84
|
onChange: (e) => handleSubChange("day", e.target.value),
|
|
82
|
-
className: cx(dateInputCls, "w-16"),
|
|
85
|
+
className: cx(dayInputCls ?? dateInputCls, "w-16"),
|
|
83
86
|
"aria-invalid": hasError ? true : void 0,
|
|
84
87
|
"aria-required": question.required || void 0
|
|
85
88
|
}
|
|
@@ -97,7 +100,7 @@ function DateInputGroup({
|
|
|
97
100
|
maxLength: 2,
|
|
98
101
|
value: parts.month,
|
|
99
102
|
onChange: (e) => handleSubChange("month", e.target.value),
|
|
100
|
-
className: cx(dateInputCls, "w-16"),
|
|
103
|
+
className: cx(monthInputCls ?? dateInputCls, "w-16"),
|
|
101
104
|
"aria-invalid": hasError ? true : void 0,
|
|
102
105
|
"aria-required": question.required || void 0
|
|
103
106
|
}
|
|
@@ -115,7 +118,7 @@ function DateInputGroup({
|
|
|
115
118
|
maxLength: 4,
|
|
116
119
|
value: parts.year,
|
|
117
120
|
onChange: (e) => handleSubChange("year", e.target.value),
|
|
118
|
-
className: cx(dateInputCls, "w-24"),
|
|
121
|
+
className: cx(yearInputCls ?? dateInputCls, "w-24"),
|
|
119
122
|
"aria-invalid": hasError ? true : void 0,
|
|
120
123
|
"aria-required": question.required || void 0
|
|
121
124
|
}
|
|
@@ -152,7 +155,7 @@ function FormField({
|
|
|
152
155
|
if (question.detail_type === "heading") return null;
|
|
153
156
|
return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: labelClasses, children: [
|
|
154
157
|
question.name,
|
|
155
|
-
question.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
158
|
+
question.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", style: { color: "#DD2D1D" }, "aria-hidden": "true", children: "*" })
|
|
156
159
|
] });
|
|
157
160
|
};
|
|
158
161
|
const renderHelpText = () => {
|
|
@@ -283,6 +286,10 @@ function FormField({
|
|
|
283
286
|
const groupCls = classNames?.dateInputGroup ?? "flex flex-row gap-3 items-end";
|
|
284
287
|
const legendCls = classNames?.dateLegend ?? labelClasses;
|
|
285
288
|
const fieldsetCls = classNames?.dateFieldset ?? (classNames?.fieldWrapper ?? defaultFieldWrapper);
|
|
289
|
+
const wrapPerInput = (cls) => cls === void 0 ? void 0 : hasError ? cx(cls, classNames?.inputError ?? defaultInputError) : cls;
|
|
290
|
+
const dayInputCls = wrapPerInput(classNames?.dateInputDay);
|
|
291
|
+
const monthInputCls = wrapPerInput(classNames?.dateInputMonth);
|
|
292
|
+
const yearInputCls = wrapPerInput(classNames?.dateInputYear);
|
|
286
293
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
287
294
|
DateInputGroup,
|
|
288
295
|
{
|
|
@@ -298,6 +305,9 @@ function FormField({
|
|
|
298
305
|
itemCls,
|
|
299
306
|
sublabelCls,
|
|
300
307
|
dateInputCls,
|
|
308
|
+
dayInputCls,
|
|
309
|
+
monthInputCls,
|
|
310
|
+
yearInputCls,
|
|
301
311
|
helpTextAbove,
|
|
302
312
|
helpTextBelow,
|
|
303
313
|
renderError
|
|
@@ -342,7 +352,7 @@ function FormField({
|
|
|
342
352
|
),
|
|
343
353
|
/* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: checkboxLabelClasses, children: [
|
|
344
354
|
question.name,
|
|
345
|
-
question.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
355
|
+
question.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", style: { color: "#DD2D1D" }, "aria-hidden": "true", children: "*" })
|
|
346
356
|
] })
|
|
347
357
|
] }),
|
|
348
358
|
helpTextBelow,
|
|
@@ -481,6 +491,24 @@ function BookingForm({
|
|
|
481
491
|
return `Maximum value is ${question.settings.max}`;
|
|
482
492
|
}
|
|
483
493
|
}
|
|
494
|
+
if (question.detail_type === "date" && question.dateLimiter?.enabled && typeof value === "string" && value !== "") {
|
|
495
|
+
const toDatePart = (iso) => {
|
|
496
|
+
if (!iso || typeof iso !== "string") return null;
|
|
497
|
+
const m = iso.match(/^(\d{4}-\d{2}-\d{2})/);
|
|
498
|
+
return m ? m[1] : null;
|
|
499
|
+
};
|
|
500
|
+
const min = toDatePart(question.dateLimiter.minimumDate);
|
|
501
|
+
const max = toDatePart(question.dateLimiter.maximumDate);
|
|
502
|
+
const v = value;
|
|
503
|
+
const outOfRange = min && v < min || max && v > max;
|
|
504
|
+
if (outOfRange) {
|
|
505
|
+
if (question.dateLimiter.errorText) return question.dateLimiter.errorText;
|
|
506
|
+
if (min && max) return `Date must be between ${min} and ${max}`;
|
|
507
|
+
if (min) return `Date must be on or after ${min}`;
|
|
508
|
+
if (max) return `Date must be on or before ${max}`;
|
|
509
|
+
return "Date is outside the allowed range";
|
|
510
|
+
}
|
|
511
|
+
}
|
|
484
512
|
return null;
|
|
485
513
|
}, []);
|
|
486
514
|
const validateAll = React.useCallback(() => {
|