@flamingo-stack/openframe-frontend-core 0.0.675 → 0.0.676-2437.7324.1
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/components/meeting-scheduler/booking-form.d.ts +21 -2
- package/dist/components/meeting-scheduler/booking-form.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/index.cjs +92 -38
- package/dist/components/meeting-scheduler/index.cjs.map +1 -1
- package/dist/components/meeting-scheduler/index.d.ts +7 -6
- package/dist/components/meeting-scheduler/index.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/index.js +66 -12
- package/dist/components/meeting-scheduler/index.js.map +1 -1
- package/dist/schemas/meeting-booking-schema.cjs +16 -0
- package/dist/schemas/meeting-booking-schema.cjs.map +1 -1
- package/dist/schemas/meeting-booking-schema.d.ts +34 -0
- package/dist/schemas/meeting-booking-schema.d.ts.map +1 -1
- package/dist/schemas/meeting-booking-schema.js +15 -1
- package/dist/schemas/meeting-booking-schema.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/meeting-scheduler-details-first.test.tsx +42 -1
- package/src/components/meeting-scheduler/booking-form.tsx +91 -17
- package/src/components/meeting-scheduler/index.tsx +7 -5
- package/src/schemas/meeting-booking-schema.ts +34 -0
|
@@ -68,11 +68,12 @@ export interface HubSpotMeetingSchedulerProps {
|
|
|
68
68
|
*/
|
|
69
69
|
detailsForm?: ComponentType<BookingFormProps>;
|
|
70
70
|
/**
|
|
71
|
-
* The DATA form of the same override: `fieldRows
|
|
72
|
-
* spread onto whichever form renders. Serialisable,
|
|
73
|
-
* can pass it across the RSC boundary where a component
|
|
71
|
+
* The DATA form of the same override: `fieldRows`, a host consent row and
|
|
72
|
+
* per-field display copy, spread onto whichever form renders. Serialisable,
|
|
73
|
+
* so a Server Component can pass it across the RSC boundary where a component
|
|
74
|
+
* cannot.
|
|
74
75
|
*/
|
|
75
|
-
detailsFormProps?: Pick<BookingFormProps, 'fieldRows' | 'consent'>;
|
|
76
|
+
detailsFormProps?: Pick<BookingFormProps, 'fieldRows' | 'consent' | 'fieldCopy' | 'deniedEmailDomains'>;
|
|
76
77
|
/** Form rescue for the details form (`RESCUE_FORMS.meetingBooking`). OPT-IN:
|
|
77
78
|
* omitted or `null` saves nothing. */
|
|
78
79
|
rescue?: FormRescueDefinition | null;
|
|
@@ -174,8 +175,8 @@ export declare function SchedulerDegradedCard({ flow, className, message, action
|
|
|
174
175
|
children?: ReactNode;
|
|
175
176
|
}): import("react").JSX.Element;
|
|
176
177
|
export declare function HubSpotMeetingScheduler({ meetingId, apiBaseUrl, initialAvailability, title, description, hosts, displayTimezone, fallbackUrl, onBack, onBooked, onStageChange, className, flow, detailsForm: DetailsForm, detailsFormProps, rescue, }: HubSpotMeetingSchedulerProps): import("react").JSX.Element;
|
|
177
|
-
export { BookingForm, BookingFormSkeleton, type BookingFormProps, type BookingFieldRow, type BookingFieldSlot, type BookingFormConsent, } from './booking-form';
|
|
178
|
+
export { BookingForm, BookingFormSkeleton, type BookingFormProps, type BookingFieldRow, type BookingFieldSlot, type BookingFieldCopy, type BookingFormConsent, } from './booking-form';
|
|
178
179
|
export { MeetingSchedulerDirectory, MeetingSchedulerDirectoryRowSkeleton, type MeetingSchedulerDirectoryProps, } from './directory';
|
|
179
180
|
export type { MeetingAvailability, BookingConfirmation, MeetingBookingErrorCode, MeetingHost };
|
|
180
|
-
export type { SchedulingLink, SchedulingLinksPayload } from '../../schemas/meeting-booking-schema';
|
|
181
|
+
export type { SchedulingLink, SchedulingLinksPayload, DeniedEmailDomains } from '../../schemas/meeting-booking-schema';
|
|
181
182
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/index.tsx"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMtD,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EACjB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAA6B,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/F,OAAO,EAA0D,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAwB/G,MAAM,WAAW,4BAA4B;IAC3C,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mEAAmE;IACnE,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,sFAAsF;IACtF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5C;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAC9C
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -331,6 +331,20 @@ function makeDeferredBookingSchema(formFields, legalConsent) {
|
|
|
331
331
|
timezone: TIMEZONE.nullish()
|
|
332
332
|
});
|
|
333
333
|
}
|
|
334
|
+
function emailDomainDenied(email, rule) {
|
|
335
|
+
if (typeof email !== "string") return false;
|
|
336
|
+
const domain = email.split("@")[1]?.trim().toLowerCase();
|
|
337
|
+
if (domain === void 0 || domain === "") return false;
|
|
338
|
+
return rule.domains.includes(domain);
|
|
339
|
+
}
|
|
340
|
+
function withDeniedEmailDomains(schema, rule) {
|
|
341
|
+
if (!rule) return schema;
|
|
342
|
+
return schema.superRefine((values, ctx) => {
|
|
343
|
+
if (emailDomainDenied(values.email, rule)) {
|
|
344
|
+
ctx.addIssue({ code: "custom", path: ["email"], message: rule.message });
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
334
348
|
|
|
335
349
|
// src/hooks/use-meeting-booking.ts
|
|
336
350
|
var AVAILABILITY_STALE_MS = 0;
|
|
@@ -467,6 +481,7 @@ var FIELD_CONTROLS = {
|
|
|
467
481
|
type: field.inputType ?? "text",
|
|
468
482
|
required: field.required,
|
|
469
483
|
"aria-invalid": Boolean(error),
|
|
484
|
+
invalid: Boolean(error),
|
|
470
485
|
autoComplete: field.autoComplete,
|
|
471
486
|
placeholder: placeholderFor(field),
|
|
472
487
|
...register(registerName)
|
|
@@ -478,6 +493,7 @@ var FIELD_CONTROLS = {
|
|
|
478
493
|
id,
|
|
479
494
|
required: field.required,
|
|
480
495
|
"aria-invalid": Boolean(error),
|
|
496
|
+
invalid: Boolean(error),
|
|
481
497
|
placeholder: placeholderFor(field),
|
|
482
498
|
...register(registerName)
|
|
483
499
|
}
|
|
@@ -491,6 +507,7 @@ var FIELD_CONTROLS = {
|
|
|
491
507
|
step: "any",
|
|
492
508
|
required: field.required,
|
|
493
509
|
"aria-invalid": Boolean(error),
|
|
510
|
+
invalid: Boolean(error),
|
|
494
511
|
...register(registerName, { setValueAs: canonicalNumber })
|
|
495
512
|
}
|
|
496
513
|
),
|
|
@@ -503,6 +520,7 @@ var FIELD_CONTROLS = {
|
|
|
503
520
|
autoComplete: "tel",
|
|
504
521
|
required: field.required,
|
|
505
522
|
"aria-invalid": Boolean(error),
|
|
523
|
+
invalid: Boolean(error),
|
|
506
524
|
placeholder: placeholderFor(field),
|
|
507
525
|
...register(registerName, { setValueAs: trimmed })
|
|
508
526
|
}
|
|
@@ -516,6 +534,7 @@ var FIELD_CONTROLS = {
|
|
|
516
534
|
type: "date",
|
|
517
535
|
required: field.required,
|
|
518
536
|
"aria-invalid": Boolean(error),
|
|
537
|
+
invalid: Boolean(error),
|
|
519
538
|
...register(registerName)
|
|
520
539
|
}
|
|
521
540
|
)
|
|
@@ -526,7 +545,16 @@ var FIELD_CONTROLS = {
|
|
|
526
545
|
control,
|
|
527
546
|
name: registerName,
|
|
528
547
|
render: ({ field: rhf }) => /* @__PURE__ */ jsxs(Select, { value: rhf.value ?? "", onValueChange: rhf.onChange, children: [
|
|
529
|
-
/* @__PURE__ */ jsx(
|
|
548
|
+
/* @__PURE__ */ jsx(
|
|
549
|
+
SelectTrigger,
|
|
550
|
+
{
|
|
551
|
+
id,
|
|
552
|
+
"aria-required": field.required || void 0,
|
|
553
|
+
"aria-invalid": Boolean(error),
|
|
554
|
+
invalid: Boolean(error),
|
|
555
|
+
children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select\u2026" })
|
|
556
|
+
}
|
|
557
|
+
),
|
|
530
558
|
/* @__PURE__ */ jsx(SelectContent, { children: (field.options ?? []).map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt, children: optionLabel(field, opt) }, opt)) })
|
|
531
559
|
] })
|
|
532
560
|
}
|
|
@@ -616,6 +644,8 @@ function BookingForm({
|
|
|
616
644
|
submitLabel,
|
|
617
645
|
footerNote,
|
|
618
646
|
fieldRows,
|
|
647
|
+
fieldCopy,
|
|
648
|
+
deniedEmailDomains,
|
|
619
649
|
consent,
|
|
620
650
|
isSubmitting,
|
|
621
651
|
onSubmit,
|
|
@@ -626,8 +656,8 @@ function BookingForm({
|
|
|
626
656
|
const { formFields, legalConsent } = availability;
|
|
627
657
|
const supportedFields = useMemo(() => normalizeFormFields(formFields), [formFields]);
|
|
628
658
|
const schema = useMemo(
|
|
629
|
-
() => makeDeferredBookingSchema(supportedFields, legalConsent),
|
|
630
|
-
[supportedFields, legalConsent]
|
|
659
|
+
() => withDeniedEmailDomains(makeDeferredBookingSchema(supportedFields, legalConsent), deniedEmailDomains),
|
|
660
|
+
[supportedFields, legalConsent, deniedEmailDomains]
|
|
631
661
|
);
|
|
632
662
|
const consentDefaults = useMemo(
|
|
633
663
|
() => (legalConsent?.communicationConsentCheckboxes ?? []).map((c) => ({
|
|
@@ -690,6 +720,16 @@ function BookingForm({
|
|
|
690
720
|
fieldPath: (name) => BUILT_IN_BOOKING_FIELDS.some((field) => field.name === name) ? name : `formFields.${name}`
|
|
691
721
|
}
|
|
692
722
|
);
|
|
723
|
+
const { toast } = useToast();
|
|
724
|
+
const onInvalid = () => {
|
|
725
|
+
if (deniedEmailDomains && emailDomainDenied(getValues("email"), deniedEmailDomains)) {
|
|
726
|
+
toast({
|
|
727
|
+
variant: "error",
|
|
728
|
+
title: "Check your email address",
|
|
729
|
+
description: deniedEmailDomains.message
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
};
|
|
693
733
|
const submitValid = handleSubmit(async (data) => {
|
|
694
734
|
if (consentMissing) return;
|
|
695
735
|
if (deferSlot) {
|
|
@@ -706,7 +746,7 @@ function BookingForm({
|
|
|
706
746
|
...getSignals(),
|
|
707
747
|
...formRescue.submitFields()
|
|
708
748
|
});
|
|
709
|
-
});
|
|
749
|
+
}, onInvalid);
|
|
710
750
|
const submit = (event) => {
|
|
711
751
|
if (consentMissing) setConsentError(consent?.errorMessage ?? "Please agree to continue.");
|
|
712
752
|
return submitValid(event);
|
|
@@ -715,14 +755,28 @@ function BookingForm({
|
|
|
715
755
|
const err = errors.formFields?.[name];
|
|
716
756
|
return err?.message;
|
|
717
757
|
};
|
|
718
|
-
const renderField = (field, where) =>
|
|
719
|
-
field
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
758
|
+
const renderField = (field, where) => {
|
|
759
|
+
const copy = fieldCopy?.[field.name];
|
|
760
|
+
const shown = copy ? { ...field, label: copy.label ?? field.label, placeholder: copy.placeholder ?? field.placeholder } : field;
|
|
761
|
+
return /* @__PURE__ */ jsx(
|
|
762
|
+
FieldWrapper,
|
|
763
|
+
{
|
|
764
|
+
label: shown.label,
|
|
765
|
+
htmlFor: where.id,
|
|
766
|
+
required: shown.required,
|
|
767
|
+
error: where.error,
|
|
768
|
+
children: FIELD_CONTROLS[shown.type]({
|
|
769
|
+
field: shown,
|
|
770
|
+
id: where.id,
|
|
771
|
+
registerName: where.registerName,
|
|
772
|
+
error: where.error,
|
|
773
|
+
register,
|
|
774
|
+
control
|
|
775
|
+
})
|
|
776
|
+
},
|
|
777
|
+
shown.name
|
|
778
|
+
);
|
|
779
|
+
};
|
|
726
780
|
const builtInFields = Object.fromEntries(
|
|
727
781
|
BUILT_IN_BOOKING_FIELDS.map((field) => [
|
|
728
782
|
field.name,
|