@flamingo-stack/openframe-frontend-core 0.0.676-2437.7317.1 → 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.
@@ -1,5 +1,5 @@
1
1
  import type { ReactNode, Ref } from 'react';
2
- import { type BuiltInBookingFieldName, type MeetingAvailability } from '../../schemas/meeting-booking-schema';
2
+ import { type BuiltInBookingFieldName, type DeniedEmailDomains, type MeetingAvailability } from '../../schemas/meeting-booking-schema';
3
3
  import type { FormRescueDefinition } from '../../utils/form-rescue';
4
4
  /**
5
5
  * One field in a host-supplied row. `name` is a built-in (`email`, `firstName`,
@@ -92,6 +92,9 @@ export interface BookingFormProps {
92
92
  fieldRows?: BookingFieldRow[];
93
93
  /** Per-field display overrides, keyed by field name — see `BookingFieldCopy`. */
94
94
  fieldCopy?: Record<string, BookingFieldCopy>;
95
+ /** Email domains this form refuses, with the message it shows — see `DeniedEmailDomains`.
96
+ * MEMOIZE it: a new object every render rebuilds the resolver's schema. */
97
+ deniedEmailDomains?: DeniedEmailDomains;
95
98
  /** Host-supplied consent row, rendered after the fields — see `BookingFormConsent`. */
96
99
  consent?: BookingFormConsent;
97
100
  isSubmitting: boolean;
@@ -122,7 +125,7 @@ export interface BookingFormProps {
122
125
  * submit; the parent calls `resetSignals()` after a SLOT_TAKEN refetch so a
123
126
  * legitimate retry isn't flagged too-fast.
124
127
  */
125
- export declare function BookingForm({ availability, meetingId, startTimeMs, durationMs, timezone, deferSlot, initialValues, submitLabel, footerNote, fieldRows, fieldCopy, consent, isSubmitting, onSubmit, honeypotInputProps, getSignals, rescue, }: BookingFormProps): import("react").JSX.Element;
128
+ export declare function BookingForm({ availability, meetingId, startTimeMs, durationMs, timezone, deferSlot, initialValues, submitLabel, footerNote, fieldRows, fieldCopy, deniedEmailDomains, consent, isSubmitting, onSubmit, honeypotInputProps, getSignals, rescue, }: BookingFormProps): import("react").JSX.Element;
126
129
  /**
127
130
  * Cold-start placeholder for `flow="details-first"`, where the FORM is the
128
131
  * first thing in the action panel.
@@ -1 +1 @@
1
- {"version":3,"file":"booking-form.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/booking-form.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"booking-form.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/booking-form.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 = _optionalChain([email, 'access', _5 => _5.split, 'call', _6 => _6("@"), 'access', _7 => _7[1], 'optionalAccess', _8 => _8.trim, 'call', _9 => _9(), 'access', _10 => _10.toLowerCase, 'call', _11 => _11()]);
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;
@@ -341,7 +355,7 @@ var BOOKING_IN_FLIGHT_MESSAGE = "Already submitting";
341
355
  function useMeetingBooking(options) {
342
356
  const { meetingId, apiBaseUrl = "", initialAvailability } = options;
343
357
  const queryClient = _reactquery.useQueryClient.call(void 0, );
344
- const seededOffset = _optionalChain([initialAvailability, 'optionalAccess', _5 => _5.meetingId]) === meetingId ? initialAvailability.monthOffset : void 0;
358
+ const seededOffset = _optionalChain([initialAvailability, 'optionalAccess', _12 => _12.meetingId]) === meetingId ? initialAvailability.monthOffset : void 0;
345
359
  const [monthOffset, setMonthOffsetState] = _react.useState.call(void 0, _nullishCoalesce(seededOffset, () => ( 0)));
346
360
  const setMonthOffset = _react.useCallback.call(void 0, (offset) => {
347
361
  setMonthOffsetState(Math.max(0, Math.min(_chunkVZMST7BDcjs.MAX_MONTH_OFFSET, offset)));
@@ -352,7 +366,7 @@ function useMeetingBooking(options) {
352
366
  prevMeetingIdRef.current = meetingId;
353
367
  setMonthOffsetState(0);
354
368
  }, [meetingId]);
355
- const seed = _optionalChain([initialAvailability, 'optionalAccess', _6 => _6.meetingId]) === meetingId && initialAvailability.monthOffset === monthOffset ? initialAvailability : void 0;
369
+ const seed = _optionalChain([initialAvailability, 'optionalAccess', _13 => _13.meetingId]) === meetingId && initialAvailability.monthOffset === monthOffset ? initialAvailability : void 0;
356
370
  const availabilityQuery = _reactquery.useQuery.call(void 0, {
357
371
  queryKey: meetingAvailabilityKey(apiBaseUrl, meetingId, monthOffset),
358
372
  queryFn: async ({ signal }) => {
@@ -448,8 +462,8 @@ var evenSpan = (count, index) => {
448
462
  return Math.min(GRID_COLUMNS, Math.max(1, index < extra ? base + 1 : base));
449
463
  };
450
464
  var slotColumnClass = (row, slot, index) => _chunkX7CEWD6Vcjs.cn.call(void 0, row.length === 2 ? "col-span-1" : "col-span-2", SPAN_CLASS[_nullishCoalesce(slot.span, () => ( evenSpan(row.length, index)))]);
451
- var placeholderFor = (field) => _nullishCoalesce(field.placeholder, () => ( _optionalChain([fieldTypeSpec, 'call', _7 => _7(field.type), 'access', _8 => _8.placeholder, 'optionalCall', _9 => _9(field)])));
452
- var optionLabel = (field, value) => _nullishCoalesce(_optionalChain([field, 'access', _10 => _10.optionLabels, 'optionalAccess', _11 => _11[value]]), () => ( value));
465
+ var placeholderFor = (field) => _nullishCoalesce(field.placeholder, () => ( _optionalChain([fieldTypeSpec, 'call', _14 => _14(field.type), 'access', _15 => _15.placeholder, 'optionalCall', _16 => _16(field)])));
466
+ var optionLabel = (field, value) => _nullishCoalesce(_optionalChain([field, 'access', _17 => _17.optionLabels, 'optionalAccess', _18 => _18[value]]), () => ( value));
453
467
  var trimmed = (v) => String(_nullishCoalesce(v, () => ( ""))).trim();
454
468
  var canonicalNumber = (v) => {
455
469
  const s = String(_nullishCoalesce(v, () => ( ""))).trim();
@@ -467,6 +481,7 @@ var FIELD_CONTROLS = {
467
481
  type: _nullishCoalesce(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__ */ _jsxruntime.jsxs.call(void 0, _chunkVZMST7BDcjs.Select, { value: _nullishCoalesce(rhf.value, () => ( "")), onValueChange: rhf.onChange, children: [
529
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.SelectTrigger, { id, "aria-required": field.required || void 0, "aria-invalid": Boolean(error), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.SelectValue, { placeholder: "Select\u2026" }) }),
548
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
549
+ _chunkVZMST7BDcjs.SelectTrigger,
550
+ {
551
+ id,
552
+ "aria-required": field.required || void 0,
553
+ "aria-invalid": Boolean(error),
554
+ invalid: Boolean(error),
555
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.SelectValue, { placeholder: "Select\u2026" })
556
+ }
557
+ ),
530
558
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.SelectContent, { children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.SelectItem, { value: opt, children: optionLabel(field, opt) }, opt)) })
531
559
  ] })
532
560
  }
@@ -617,6 +645,7 @@ function BookingForm({
617
645
  footerNote,
618
646
  fieldRows,
619
647
  fieldCopy,
648
+ deniedEmailDomains,
620
649
  consent,
621
650
  isSubmitting,
622
651
  onSubmit,
@@ -627,11 +656,11 @@ function BookingForm({
627
656
  const { formFields, legalConsent } = availability;
628
657
  const supportedFields = _react.useMemo.call(void 0, () => normalizeFormFields(formFields), [formFields]);
629
658
  const schema = _react.useMemo.call(void 0,
630
- () => makeDeferredBookingSchema(supportedFields, legalConsent),
631
- [supportedFields, legalConsent]
659
+ () => withDeniedEmailDomains(makeDeferredBookingSchema(supportedFields, legalConsent), deniedEmailDomains),
660
+ [supportedFields, legalConsent, deniedEmailDomains]
632
661
  );
633
662
  const consentDefaults = _react.useMemo.call(void 0,
634
- () => (_nullishCoalesce(_optionalChain([legalConsent, 'optionalAccess', _12 => _12.communicationConsentCheckboxes]), () => ( []))).map((c) => ({
663
+ () => (_nullishCoalesce(_optionalChain([legalConsent, 'optionalAccess', _19 => _19.communicationConsentCheckboxes]), () => ( []))).map((c) => ({
635
664
  communicationTypeId: c.communicationTypeId,
636
665
  consented: false
637
666
  })),
@@ -663,8 +692,8 @@ function BookingForm({
663
692
  ..._nullishCoalesce(initialValues, () => ( {}))
664
693
  }
665
694
  });
666
- const priorConsents = _optionalChain([initialValues, 'optionalAccess', _13 => _13.legalConsentResponses]);
667
- const [consented, setConsented] = _react.useState.call(void 0, _optionalChain([initialValues, 'optionalAccess', _14 => _14[HOST_CONSENT_KEY]]) === true);
695
+ const priorConsents = _optionalChain([initialValues, 'optionalAccess', _20 => _20.legalConsentResponses]);
696
+ const [consented, setConsented] = _react.useState.call(void 0, _optionalChain([initialValues, 'optionalAccess', _21 => _21[HOST_CONSENT_KEY]]) === true);
668
697
  const [consentError, setConsentError] = _react.useState.call(void 0, null);
669
698
  const consentMissing = Boolean(consent) && !consented;
670
699
  _react.useEffect.call(void 0, () => {
@@ -673,7 +702,7 @@ function BookingForm({
673
702
  "legalConsentResponses",
674
703
  consentDefaults.map((next) => ({
675
704
  ...next,
676
- consented: _nullishCoalesce(_optionalChain([current, 'access', _15 => _15.find, 'call', _16 => _16((r) => r.communicationTypeId === next.communicationTypeId), 'optionalAccess', _17 => _17.consented]), () => ( false))
705
+ consented: _nullishCoalesce(_optionalChain([current, 'access', _22 => _22.find, 'call', _23 => _23((r) => r.communicationTypeId === next.communicationTypeId), 'optionalAccess', _24 => _24.consented]), () => ( false))
677
706
  })),
678
707
  { shouldDirty: false }
679
708
  );
@@ -691,6 +720,16 @@ function BookingForm({
691
720
  fieldPath: (name) => BUILT_IN_BOOKING_FIELDS.some((field) => field.name === name) ? name : `formFields.${name}`
692
721
  }
693
722
  );
723
+ const { toast } = _chunkRCLYHHB3cjs.useToast.call(void 0, );
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
+ };
694
733
  const submitValid = handleSubmit(async (data) => {
695
734
  if (consentMissing) return;
696
735
  if (deferSlot) {
@@ -707,17 +746,17 @@ function BookingForm({
707
746
  ...getSignals(),
708
747
  ...formRescue.submitFields()
709
748
  });
710
- });
749
+ }, onInvalid);
711
750
  const submit = (event) => {
712
- if (consentMissing) setConsentError(_nullishCoalesce(_optionalChain([consent, 'optionalAccess', _18 => _18.errorMessage]), () => ( "Please agree to continue.")));
751
+ if (consentMissing) setConsentError(_nullishCoalesce(_optionalChain([consent, 'optionalAccess', _25 => _25.errorMessage]), () => ( "Please agree to continue.")));
713
752
  return submitValid(event);
714
753
  };
715
754
  const fieldError = (name) => {
716
- const err = _optionalChain([errors, 'access', _19 => _19.formFields, 'optionalAccess', _20 => _20[name]]);
717
- return _optionalChain([err, 'optionalAccess', _21 => _21.message]);
755
+ const err = _optionalChain([errors, 'access', _26 => _26.formFields, 'optionalAccess', _27 => _27[name]]);
756
+ return _optionalChain([err, 'optionalAccess', _28 => _28.message]);
718
757
  };
719
758
  const renderField = (field, where) => {
720
- const copy = _optionalChain([fieldCopy, 'optionalAccess', _22 => _22[field.name]]);
759
+ const copy = _optionalChain([fieldCopy, 'optionalAccess', _29 => _29[field.name]]);
721
760
  const shown = copy ? { ...field, label: _nullishCoalesce(copy.label, () => ( field.label)), placeholder: _nullishCoalesce(copy.placeholder, () => ( field.placeholder)) } : field;
722
761
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
723
762
  _chunkQVSVRG7Icjs.FieldWrapper,
@@ -741,7 +780,7 @@ function BookingForm({
741
780
  const builtInFields = Object.fromEntries(
742
781
  BUILT_IN_BOOKING_FIELDS.map((field) => [
743
782
  field.name,
744
- renderField(field, { id: builtInId(field.name), registerName: field.name, error: _optionalChain([errors, 'access', _23 => _23[field.name], 'optionalAccess', _24 => _24.message]) })
783
+ renderField(field, { id: builtInId(field.name), registerName: field.name, error: _optionalChain([errors, 'access', _30 => _30[field.name], 'optionalAccess', _31 => _31.message]) })
745
784
  ])
746
785
  );
747
786
  const renderDeclaredField = (field) => renderField(field, {
@@ -802,7 +841,7 @@ function BookingForm({
802
841
  // box doesn't shove the submit button down the card. With no error the
803
842
  // wrapper is `display:contents` and the panel below is the flex item,
804
843
  // exactly as it was.
805
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQVSVRG7Icjs.FieldWrapper, { error: _optionalChain([errors, 'access', _25 => _25.legalConsentResponses, 'optionalAccess', _26 => _26.message]), children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-[var(--spacing-system-xs)]", children: [
844
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQVSVRG7Icjs.FieldWrapper, { error: _optionalChain([errors, 'access', _32 => _32.legalConsentResponses, 'optionalAccess', _33 => _33.message]), children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-[var(--spacing-system-xs)]", children: [
806
845
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary text-h6", children: legalConsent.processingConsentText }),
807
846
  legalConsent.communicationConsentText && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary text-h6", children: legalConsent.communicationConsentText }),
808
847
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -821,7 +860,7 @@ function BookingForm({
821
860
  _chunkVZMST7BDcjs.CheckboxBlock,
822
861
  {
823
862
  id: `ms-consent-${box.communicationTypeId}`,
824
- checked: _nullishCoalesce(_optionalChain([current, 'optionalAccess', _27 => _27.consented]), () => ( false)),
863
+ checked: _nullishCoalesce(_optionalChain([current, 'optionalAccess', _34 => _34.consented]), () => ( false)),
825
864
  onCheckedChange: (v) => rhf.onChange(
826
865
  responses.map(
827
866
  (r) => r.communicationTypeId === box.communicationTypeId ? { ...r, consented: v } : r
@@ -916,7 +955,7 @@ function zoneLabel(tz) {
916
955
  timeZone: tz,
917
956
  timeZoneName: "shortOffset"
918
957
  }).formatToParts(/* @__PURE__ */ new Date());
919
- const offset = _nullishCoalesce(_optionalChain([parts, 'access', _28 => _28.find, 'call', _29 => _29((p) => p.type === "timeZoneName"), 'optionalAccess', _30 => _30.value]), () => ( ""));
958
+ const offset = _nullishCoalesce(_optionalChain([parts, 'access', _35 => _35.find, 'call', _36 => _36((p) => p.type === "timeZoneName"), 'optionalAccess', _37 => _37.value]), () => ( ""));
920
959
  return offset ? `${tz.replace(/_/g, " ")} (${offset})` : tz.replace(/_/g, " ");
921
960
  } catch (e4) {
922
961
  return tz.replace(/_/g, " ");
@@ -1043,7 +1082,7 @@ function SchedulerContextPanel({
1043
1082
  value: timezone,
1044
1083
  disabled,
1045
1084
  onChange: (tz) => {
1046
- if (tz) _optionalChain([onTimezoneChange, 'optionalCall', _31 => _31(tz)]);
1085
+ if (tz) _optionalChain([onTimezoneChange, 'optionalCall', _38 => _38(tz)]);
1047
1086
  },
1048
1087
  options: zoneOptions,
1049
1088
  placeholder: "Search timezone\u2026",
@@ -1127,7 +1166,7 @@ function DayCalendar({ monthOffset, onMonthOffsetChange, selectedDay, onSelectDa
1127
1166
  const startMonth = new Date(now.getFullYear(), now.getMonth(), 1);
1128
1167
  const endMonth = new Date(now.getFullYear(), now.getMonth() + _chunkVZMST7BDcjs.MAX_MONTH_OFFSET + 1, 0);
1129
1168
  const visibleMonth = new Date(now.getFullYear(), now.getMonth() + monthOffset, 1);
1130
- const dayHasNoSlots = _react.useCallback.call(void 0, (day) => !_optionalChain([slotsByDay, 'optionalAccess', _32 => _32.has, 'call', _33 => _33(calendarDayKey(day))]), [slotsByDay]);
1169
+ const dayHasNoSlots = _react.useCallback.call(void 0, (day) => !_optionalChain([slotsByDay, 'optionalAccess', _39 => _39.has, 'call', _40 => _40(calendarDayKey(day))]), [slotsByDay]);
1131
1170
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex min-h-0 flex-1 flex-col", "aria-busy": slotsByDay === null, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1132
1171
  _chunkVZMST7BDcjs.DatePickerCalendar,
1133
1172
  {
@@ -1145,7 +1184,7 @@ function DayCalendar({ monthOffset, onMonthOffsetChange, selectedDay, onSelectDa
1145
1184
  const day = value;
1146
1185
  if (!day) return;
1147
1186
  const key = calendarDayKey(day);
1148
- if (_optionalChain([slotsByDay, 'optionalAccess', _34 => _34.has, 'call', _35 => _35(key)])) onSelectDay(key);
1187
+ if (_optionalChain([slotsByDay, 'optionalAccess', _41 => _41.has, 'call', _42 => _42(key)])) onSelectDay(key);
1149
1188
  },
1150
1189
  disabledDays: slotsByDay === null ? DISABLE_EVERY_DAY : dayHasNoSlots
1151
1190
  }
@@ -1369,7 +1408,7 @@ function MeetingSchedulerDirectory({
1369
1408
  };
1370
1409
  }, [initialData, includeAll, apiBaseUrl]);
1371
1410
  const rows = _react.useMemo.call(void 0, () => {
1372
- const purposes = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _36 => _36.purposes]), () => ( []));
1411
+ const purposes = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _43 => _43.purposes]), () => ( []));
1373
1412
  return purposes.flatMap((p) => p.links.map((link) => ({ link, audienceLabel: p.label })));
1374
1413
  }, [data]);
1375
1414
  const totalPages = _chunkVTYP25OWcjs.pageCount.call(void 0, rows.length, pageSize);
@@ -1526,7 +1565,7 @@ function HubSpotMeetingScheduler({
1526
1565
  onStageChangeRef.current = onStageChange;
1527
1566
  });
1528
1567
  _react.useEffect.call(void 0, () => {
1529
- _optionalChain([onStageChangeRef, 'access', _37 => _37.current, 'optionalCall', _38 => _38(stage)]);
1568
+ _optionalChain([onStageChangeRef, 'access', _44 => _44.current, 'optionalCall', _45 => _45(stage)]);
1530
1569
  }, [stage]);
1531
1570
  const [stash, setStash] = _react.useState.call(void 0, null);
1532
1571
  const inFlightRef = _react.useRef.call(void 0, false);
@@ -1557,8 +1596,8 @@ function HubSpotMeetingScheduler({
1557
1596
  _react.useEffect.call(void 0, () => {
1558
1597
  autoAdvanceCount.current = 0;
1559
1598
  }, [meetingId]);
1560
- const durations = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([availability, 'optionalAccess', _39 => _39.durationsMs]), () => ( [])), [_optionalChain([availability, 'optionalAccess', _40 => _40.durationsMs])]);
1561
- const shownHosts = _nullishCoalesce(_nullishCoalesce(hosts, () => ( _optionalChain([availability, 'optionalAccess', _41 => _41.hosts]))), () => ( []));
1599
+ const durations = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([availability, 'optionalAccess', _46 => _46.durationsMs]), () => ( [])), [_optionalChain([availability, 'optionalAccess', _47 => _47.durationsMs])]);
1600
+ const shownHosts = _nullishCoalesce(_nullishCoalesce(hosts, () => ( _optionalChain([availability, 'optionalAccess', _48 => _48.hosts]))), () => ( []));
1562
1601
  const durationMs = _nullishCoalesce(_nullishCoalesce(pickedDurationMs, () => ( durations[0])), () => ( null));
1563
1602
  const slots = _react.useMemo.call(void 0, () => {
1564
1603
  if (!availability || durationMs == null) return [];
@@ -1618,7 +1657,7 @@ function HubSpotMeetingScheduler({
1618
1657
  _chunkRCLYHHB3cjs.completeFormRescue.call(void 0, rescue, payload[_chunkRCLYHHB3cjs.FORM_RESCUE_ATTEMPT_FIELD]);
1619
1658
  setConfirmation(result.confirmation);
1620
1659
  setStep("confirmed");
1621
- _optionalChain([onBooked, 'optionalCall', _42 => _42(result.confirmation)]);
1660
+ _optionalChain([onBooked, 'optionalCall', _49 => _49(result.confirmation)]);
1622
1661
  return;
1623
1662
  }
1624
1663
  const code = _nullishCoalesce(result.code, () => ( "TEMPORARILY_UNAVAILABLE"));
@@ -1666,8 +1705,8 @@ function HubSpotMeetingScheduler({
1666
1705
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: stepPanelClass, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1667
1706
  BookingFormSkeleton,
1668
1707
  {
1669
- fieldRows: _optionalChain([detailsFormProps, 'optionalAccess', _43 => _43.fieldRows]),
1670
- consent: Boolean(_optionalChain([detailsFormProps, 'optionalAccess', _44 => _44.consent])),
1708
+ fieldRows: _optionalChain([detailsFormProps, 'optionalAccess', _50 => _50.fieldRows]),
1709
+ consent: Boolean(_optionalChain([detailsFormProps, 'optionalAccess', _51 => _51.consent])),
1671
1710
  footerNote: preset.footerNote
1672
1711
  }
1673
1712
  ) })
@@ -1728,7 +1767,7 @@ function HubSpotMeetingScheduler({
1728
1767
  deferSlot: detailsFirst,
1729
1768
  submitLabel: preset.submitLabel,
1730
1769
  footerNote: preset.footerNote,
1731
- initialValues: detailsFirst ? _optionalChain([stash, 'optionalAccess', _45 => _45.payload]) : void 0,
1770
+ initialValues: detailsFirst ? _optionalChain([stash, 'optionalAccess', _52 => _52.payload]) : void 0,
1732
1771
  isSubmitting,
1733
1772
  onSubmit: detailsFirst ? stashDetails : handleSubmit,
1734
1773
  honeypotInputProps,