@planetaexo/design-system 0.4.7 → 0.4.9
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.cjs +38 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +38 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -571,6 +571,15 @@ interface RegistrationFormProps {
|
|
|
571
571
|
defaultValues?: RegistrationFormValues;
|
|
572
572
|
onChange?: (values: RegistrationFormValues) => void;
|
|
573
573
|
onSubmit?: (values: RegistrationFormValues) => void;
|
|
574
|
+
/**
|
|
575
|
+
* Synchronous format/business validator called inside handleSubmit.
|
|
576
|
+
* Return a record of fieldId → error message to block submit and show inline errors.
|
|
577
|
+
* Called after the required-empty check, so values are guaranteed non-empty for required fields.
|
|
578
|
+
* For validating optional fields or additional format checks, use this instead of onSubmit.
|
|
579
|
+
*/
|
|
580
|
+
onValidate?: (values: RegistrationFormValues) => Record<string, string>;
|
|
581
|
+
/** @deprecated Use onValidate instead. Per-field errors injected by the parent. */
|
|
582
|
+
externalErrors?: Record<string, string>;
|
|
574
583
|
terms?: RegistrationTerms;
|
|
575
584
|
includeTerms?: boolean;
|
|
576
585
|
loading?: boolean;
|
|
@@ -580,7 +589,7 @@ interface RegistrationFormProps {
|
|
|
580
589
|
labels?: RegistrationFormLabels;
|
|
581
590
|
className?: string;
|
|
582
591
|
}
|
|
583
|
-
declare function RegistrationForm({ logo, logoAlt, heroImage, heroImageAlt, title, subtitle, adventure, booking, traveller, fields, values, defaultValues, onChange, onSubmit, terms, includeTerms, loading, error, defaultPhoneCountry, dateFormatter, labels, className, }: RegistrationFormProps): react_jsx_runtime.JSX.Element;
|
|
592
|
+
declare function RegistrationForm({ logo, logoAlt, heroImage, heroImageAlt, title, subtitle, adventure, booking, traveller, fields, values, defaultValues, onChange, onSubmit, onValidate, externalErrors, terms, includeTerms, loading, error, defaultPhoneCountry, dateFormatter, labels, className, }: RegistrationFormProps): react_jsx_runtime.JSX.Element;
|
|
584
593
|
interface RegistrationSuccessCardProps {
|
|
585
594
|
title?: string;
|
|
586
595
|
message?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -571,6 +571,15 @@ interface RegistrationFormProps {
|
|
|
571
571
|
defaultValues?: RegistrationFormValues;
|
|
572
572
|
onChange?: (values: RegistrationFormValues) => void;
|
|
573
573
|
onSubmit?: (values: RegistrationFormValues) => void;
|
|
574
|
+
/**
|
|
575
|
+
* Synchronous format/business validator called inside handleSubmit.
|
|
576
|
+
* Return a record of fieldId → error message to block submit and show inline errors.
|
|
577
|
+
* Called after the required-empty check, so values are guaranteed non-empty for required fields.
|
|
578
|
+
* For validating optional fields or additional format checks, use this instead of onSubmit.
|
|
579
|
+
*/
|
|
580
|
+
onValidate?: (values: RegistrationFormValues) => Record<string, string>;
|
|
581
|
+
/** @deprecated Use onValidate instead. Per-field errors injected by the parent. */
|
|
582
|
+
externalErrors?: Record<string, string>;
|
|
574
583
|
terms?: RegistrationTerms;
|
|
575
584
|
includeTerms?: boolean;
|
|
576
585
|
loading?: boolean;
|
|
@@ -580,7 +589,7 @@ interface RegistrationFormProps {
|
|
|
580
589
|
labels?: RegistrationFormLabels;
|
|
581
590
|
className?: string;
|
|
582
591
|
}
|
|
583
|
-
declare function RegistrationForm({ logo, logoAlt, heroImage, heroImageAlt, title, subtitle, adventure, booking, traveller, fields, values, defaultValues, onChange, onSubmit, terms, includeTerms, loading, error, defaultPhoneCountry, dateFormatter, labels, className, }: RegistrationFormProps): react_jsx_runtime.JSX.Element;
|
|
592
|
+
declare function RegistrationForm({ logo, logoAlt, heroImage, heroImageAlt, title, subtitle, adventure, booking, traveller, fields, values, defaultValues, onChange, onSubmit, onValidate, externalErrors, terms, includeTerms, loading, error, defaultPhoneCountry, dateFormatter, labels, className, }: RegistrationFormProps): react_jsx_runtime.JSX.Element;
|
|
584
593
|
interface RegistrationSuccessCardProps {
|
|
585
594
|
title?: string;
|
|
586
595
|
message?: string;
|
package/dist/index.js
CHANGED
|
@@ -4500,6 +4500,8 @@ function RegistrationForm({
|
|
|
4500
4500
|
defaultValues,
|
|
4501
4501
|
onChange,
|
|
4502
4502
|
onSubmit,
|
|
4503
|
+
onValidate,
|
|
4504
|
+
externalErrors,
|
|
4503
4505
|
terms,
|
|
4504
4506
|
includeTerms = false,
|
|
4505
4507
|
loading = false,
|
|
@@ -4531,6 +4533,7 @@ function RegistrationForm({
|
|
|
4531
4533
|
)
|
|
4532
4534
|
);
|
|
4533
4535
|
const [submitAttempted, setSubmitAttempted] = React21.useState(false);
|
|
4536
|
+
const [validationErrors, setValidationErrors] = React21.useState({});
|
|
4534
4537
|
React21.useEffect(() => {
|
|
4535
4538
|
if (isControlled) return;
|
|
4536
4539
|
setInternal((prev) => {
|
|
@@ -4556,12 +4559,15 @@ function RegistrationForm({
|
|
|
4556
4559
|
const termsEnabled = includeTerms && !!terms;
|
|
4557
4560
|
const acceptControl = (_a = terms == null ? void 0 : terms.acceptControl) != null ? _a : "checkbox";
|
|
4558
4561
|
const handleSubmit = (e) => {
|
|
4562
|
+
var _a2;
|
|
4559
4563
|
e.preventDefault();
|
|
4560
4564
|
setSubmitAttempted(true);
|
|
4561
4565
|
const hasRequiredEmpty = sortedFields.some(
|
|
4562
4566
|
(f) => f.required && isFieldEmpty(f, current[f.id])
|
|
4563
4567
|
);
|
|
4564
|
-
|
|
4568
|
+
const extraErrors = (_a2 = onValidate == null ? void 0 : onValidate(current)) != null ? _a2 : {};
|
|
4569
|
+
setValidationErrors(extraErrors);
|
|
4570
|
+
if (hasRequiredEmpty || Object.keys(extraErrors).length > 0 || termsEnabled && !termsAccepted) return;
|
|
4565
4571
|
onSubmit == null ? void 0 : onSubmit(current);
|
|
4566
4572
|
};
|
|
4567
4573
|
const dateRange = formatDateRange(adventure, dateFormatter);
|
|
@@ -4573,7 +4579,24 @@ function RegistrationForm({
|
|
|
4573
4579
|
fieldErrors[field.id] = L.requiredFieldError;
|
|
4574
4580
|
}
|
|
4575
4581
|
}
|
|
4582
|
+
for (const [id, msg] of Object.entries(validationErrors)) {
|
|
4583
|
+
if (!fieldErrors[id]) fieldErrors[id] = msg;
|
|
4584
|
+
}
|
|
4585
|
+
if (externalErrors) {
|
|
4586
|
+
for (const [id, msg] of Object.entries(externalErrors)) {
|
|
4587
|
+
if (!fieldErrors[id]) fieldErrors[id] = msg;
|
|
4588
|
+
}
|
|
4589
|
+
}
|
|
4576
4590
|
}
|
|
4591
|
+
const firstErrorFieldId = Object.keys(fieldErrors)[0];
|
|
4592
|
+
React21.useEffect(() => {
|
|
4593
|
+
if (!submitAttempted || !firstErrorFieldId) return;
|
|
4594
|
+
const timer = setTimeout(() => {
|
|
4595
|
+
const elem = document.getElementById(`rf-${firstErrorFieldId}`);
|
|
4596
|
+
if (elem) elem.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
4597
|
+
}, 50);
|
|
4598
|
+
return () => clearTimeout(timer);
|
|
4599
|
+
}, [submitAttempted, firstErrorFieldId, validationErrors]);
|
|
4577
4600
|
return /* @__PURE__ */ jsxs(
|
|
4578
4601
|
"form",
|
|
4579
4602
|
{
|
|
@@ -4625,31 +4648,31 @@ function RegistrationForm({
|
|
|
4625
4648
|
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-black uppercase tracking-wide text-foreground font-heading leading-tight", children: title }),
|
|
4626
4649
|
/* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm text-muted-foreground font-ui", children: subtitle != null ? subtitle : L.formSubtitle })
|
|
4627
4650
|
] }),
|
|
4628
|
-
hasTripInfo && /* @__PURE__ */ jsx(FormSection2, { title: L.tripInfoSectionTitle, children: /* @__PURE__ */ jsxs("dl", { className: "
|
|
4629
|
-
adventure && /* @__PURE__ */ jsxs(
|
|
4651
|
+
hasTripInfo && /* @__PURE__ */ jsx(FormSection2, { title: L.tripInfoSectionTitle, children: /* @__PURE__ */ jsxs("dl", { className: "flex flex-col gap-y-3 text-sm font-ui", children: [
|
|
4652
|
+
adventure && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-x-4", children: [
|
|
4630
4653
|
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: L.adventureLabel }),
|
|
4631
|
-
/* @__PURE__ */ jsx("dd", { className: "text-foreground font-medium", children: adventure.name })
|
|
4654
|
+
/* @__PURE__ */ jsx("dd", { className: "text-foreground font-medium text-right min-w-0 break-words", children: adventure.name })
|
|
4632
4655
|
] }),
|
|
4633
|
-
dateRange && /* @__PURE__ */ jsxs(
|
|
4656
|
+
dateRange && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-x-4", children: [
|
|
4634
4657
|
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: (adventure == null ? void 0 : adventure.startDate) && (adventure == null ? void 0 : adventure.endDate) ? "Dates" : "Date" }),
|
|
4635
|
-
/* @__PURE__ */ jsx("dd", { className: "text-foreground", children: dateRange })
|
|
4658
|
+
/* @__PURE__ */ jsx("dd", { className: "text-foreground text-right min-w-0", children: dateRange })
|
|
4636
4659
|
] }),
|
|
4637
|
-
(adventure == null ? void 0 : adventure.partnerName) && /* @__PURE__ */ jsxs(
|
|
4660
|
+
(adventure == null ? void 0 : adventure.partnerName) && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-x-4", children: [
|
|
4638
4661
|
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: L.partnerLabel }),
|
|
4639
|
-
/* @__PURE__ */ jsx("dd", { className: "text-foreground", children: adventure.partnerName })
|
|
4662
|
+
/* @__PURE__ */ jsx("dd", { className: "text-foreground text-right min-w-0", children: adventure.partnerName })
|
|
4640
4663
|
] }),
|
|
4641
|
-
booking && /* @__PURE__ */ jsxs(
|
|
4664
|
+
booking && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-x-4", children: [
|
|
4642
4665
|
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: L.bookingLabel }),
|
|
4643
|
-
/* @__PURE__ */ jsx("dd", { className: "text-foreground font-mono tabular-nums", children: booking.id })
|
|
4666
|
+
/* @__PURE__ */ jsx("dd", { className: "text-foreground font-mono tabular-nums text-right min-w-0", children: booking.id })
|
|
4644
4667
|
] }),
|
|
4645
|
-
traveller && /* @__PURE__ */ jsxs(
|
|
4668
|
+
traveller && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-x-4", children: [
|
|
4646
4669
|
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: L.travellerLabel }),
|
|
4647
|
-
/* @__PURE__ */ jsx("dd", { className: "text-foreground font-medium", children: traveller.fullName })
|
|
4670
|
+
/* @__PURE__ */ jsx("dd", { className: "text-foreground font-medium text-right min-w-0 break-words", children: traveller.fullName })
|
|
4648
4671
|
] })
|
|
4649
4672
|
] }) }),
|
|
4650
4673
|
/* @__PURE__ */ jsx(FormSection2, { title: L.detailsSectionTitle, children: sortedFields.map((field) => {
|
|
4651
4674
|
var _a2;
|
|
4652
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
4675
|
+
return /* @__PURE__ */ jsxs("div", { id: `rf-${field.id}`, className: "flex flex-col gap-1.5", children: [
|
|
4653
4676
|
/* @__PURE__ */ jsx(
|
|
4654
4677
|
FieldRenderer,
|
|
4655
4678
|
{
|
|
@@ -4837,9 +4860,9 @@ function RegistrationSuccessCard({
|
|
|
4837
4860
|
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-black uppercase tracking-wide text-foreground font-heading leading-tight", children: title }),
|
|
4838
4861
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground font-ui", children: message })
|
|
4839
4862
|
] }),
|
|
4840
|
-
sorted.length > 0 && /* @__PURE__ */ jsx(FormSection2, { title: answersTitle, children: /* @__PURE__ */ jsx("dl", { className: "
|
|
4863
|
+
sorted.length > 0 && /* @__PURE__ */ jsx(FormSection2, { title: answersTitle, children: /* @__PURE__ */ jsx("dl", { className: "flex flex-col gap-y-3 text-sm font-ui", children: sorted.map((f) => /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-x-4", children: [
|
|
4841
4864
|
/* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: f.label }),
|
|
4842
|
-
/* @__PURE__ */ jsx("dd", { className: "text-foreground", children: (formatAnswer != null ? formatAnswer : ((field, v) => defaultFormatAnswer(field, v, dateFormatter)))(
|
|
4865
|
+
/* @__PURE__ */ jsx("dd", { className: "text-foreground text-right min-w-0 break-words", children: (formatAnswer != null ? formatAnswer : ((field, v) => defaultFormatAnswer(field, v, dateFormatter)))(
|
|
4843
4866
|
f,
|
|
4844
4867
|
answers[f.id]
|
|
4845
4868
|
) })
|