@flamingo-stack/openframe-frontend-core 0.0.596-2034.5677.1 → 0.0.596-2034.5678.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.
@@ -28,20 +28,6 @@ export interface BookingFormConsent {
28
28
  /** Shown under the row when Continue is pressed unticked. */
29
29
  errorMessage?: string;
30
30
  }
31
- /**
32
- * BookingForm — attendee details + the link's declared custom questions +
33
- * verbatim legal-consent copy. ContactForm's scaffolding (react-hook-form +
34
- * zodResolver + lib field primitives); a sibling rather than a `<ContactForm>`
35
- * configuration because of the dynamic HubSpot `formFields`, the per-checkbox
36
- * consent model, and the first/last-name field model — none expressible via
37
- * `hideFields`/`extraTopField`.
38
- *
39
- * Bot protection is LOAD-BEARING: without the humanity signals in the body,
40
- * the host's `verifyHuman` degrades to first-party-only BotID (fails open for
41
- * external embedders). Honeypot + elapsed-ms are merged into the POST at
42
- * submit; the parent calls `resetSignals()` after a SLOT_TAKEN refetch so a
43
- * legitimate retry isn't flagged too-fast.
44
- */
45
31
  export interface BookingFormProps {
46
32
  availability: MeetingAvailability;
47
33
  meetingId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"booking-form.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/booking-form.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAa,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EAGL,KAAK,mBAAmB,EAGzB,MAAM,sCAAsC,CAAC;AAqB9C;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACtB;AAED,MAAM,MAAM,eAAe,GAAG,gBAAgB,EAAE,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAcD;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,mBAAmB,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;qEACiE;IACjE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B,uFAAuF;IACvF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,mFAAmF;IACnF,kBAAkB,EAAE;QAAE,GAAG,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CACnD;AAED,wBAAgB,WAAW,CAAC,EAC1B,YAAY,EACZ,SAAS,EACT,WAAW,EACX,UAAU,EACV,QAAQ,EACR,SAAiB,EACjB,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,kBAAkB,EAClB,UAAU,GACX,EAAE,gBAAgB,+BAkalB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,gCAelC"}
1
+ {"version":3,"file":"booking-form.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/booking-form.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAa,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAGvD,OAAO,EAKL,KAAK,mBAAmB,EAIzB,MAAM,sCAAsC,CAAC;AAqB9C;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACtB;AAED,MAAM,MAAM,eAAe,GAAG,gBAAgB,EAAE,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqJD,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,mBAAmB,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;qEACiE;IACjE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B,uFAAuF;IACvF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,mFAAmF;IACnF,kBAAkB,EAAE;QAAE,GAAG,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CACnD;AAED,wBAAgB,WAAW,CAAC,EAC1B,YAAY,EACZ,SAAS,EACT,WAAW,EACX,UAAU,EACV,QAAQ,EACR,SAAiB,EACjB,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,kBAAkB,EAClB,UAAU,GACX,EAAE,gBAAgB,+BAqTlB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,gCAelC"}
@@ -93,10 +93,63 @@ var MEETING_BOOKING_ERROR_CODES = [
93
93
  "TEMPORARILY_UNAVAILABLE",
94
94
  "MEETING_UNAVAILABLE"
95
95
  ];
96
- var SUPPORTED_FORM_FIELD_TYPES = ["text", "textarea", "select", "radio", "checkbox", "number"];
96
+ var optionValidator = (field) => _zod.z.string().refine((v) => !v || (_nullishCoalesce(field.options, () => ( []))).includes(v), {
97
+ message: `Please choose a valid option for ${field.label}`
98
+ });
99
+ var FORM_FIELD_TYPES = {
100
+ text: {
101
+ kind: "string",
102
+ hasOptions: false,
103
+ validator: (field) => _zod.z.string().max(1e3, { message: `${field.label} is too long` })
104
+ },
105
+ textarea: {
106
+ kind: "string",
107
+ hasOptions: false,
108
+ validator: (field) => _zod.z.string().max(5e3, { message: `${field.label} is too long` })
109
+ },
110
+ number: {
111
+ kind: "string",
112
+ hasOptions: false,
113
+ validator: (field) => _zod.z.string().max(32, { message: `${field.label} is too long` }).regex(/^-?\d+(\.\d+)?$/, { message: `${field.label} must be a number` })
114
+ },
115
+ select: { kind: "string", hasOptions: true, validator: optionValidator },
116
+ radio: { kind: "string", hasOptions: true, validator: optionValidator },
117
+ checkbox: { kind: "boolean", hasOptions: false, validator: () => _zod.z.boolean() }
118
+ };
119
+ var SUPPORTED_FORM_FIELD_TYPES = Object.keys(FORM_FIELD_TYPES);
120
+ var FORM_FIELD_TYPES_WITH_OPTIONS = SUPPORTED_FORM_FIELD_TYPES.filter(
121
+ (type) => FORM_FIELD_TYPES[type].hasOptions
122
+ );
97
123
  function isSupportedFormField(field) {
98
- return SUPPORTED_FORM_FIELD_TYPES.includes(field.type);
124
+ return Object.prototype.hasOwnProperty.call(FORM_FIELD_TYPES, field.type);
99
125
  }
126
+ var BUILT_IN_BOOKING_FIELDS = [
127
+ {
128
+ name: "firstName",
129
+ label: "First Name",
130
+ type: "text",
131
+ required: true,
132
+ autoComplete: "given-name",
133
+ placeholder: "Enter First Name"
134
+ },
135
+ {
136
+ name: "lastName",
137
+ label: "Last Name",
138
+ type: "text",
139
+ required: true,
140
+ autoComplete: "family-name",
141
+ placeholder: "Enter Last Name"
142
+ },
143
+ {
144
+ name: "email",
145
+ label: "Email",
146
+ type: "text",
147
+ required: true,
148
+ inputType: "email",
149
+ autoComplete: "email",
150
+ placeholder: "username@mail.com"
151
+ }
152
+ ];
100
153
  var IANA_TZ_RE = /^(?:UTC|[A-Za-z_]+(?:\/[A-Za-z0-9_+-]+)+)$/;
101
154
  function isValidIanaTimezone(tz) {
102
155
  if (!IANA_TZ_RE.test(tz)) return false;
@@ -118,34 +171,12 @@ function buildBookingSchema(formFields, legalConsent, slot) {
118
171
  const answers = {};
119
172
  for (const field of formFields) {
120
173
  if (!isSupportedFormField(field)) continue;
121
- let validator;
122
- switch (field.type) {
123
- case "checkbox":
124
- validator = _zod.z.boolean();
125
- break;
126
- case "select":
127
- case "radio":
128
- validator = _zod.z.string().refine((v) => !v || (_nullishCoalesce(field.options, () => ( []))).includes(v), {
129
- message: `Please choose a valid option for ${field.label}`
130
- });
131
- break;
132
- case "textarea":
133
- validator = _zod.z.string().max(5e3, { message: `${field.label} is too long` });
134
- break;
135
- case "number":
136
- validator = _zod.z.string().max(32, { message: `${field.label} is too long` }).regex(/^-?\d+(\.\d+)?$/, { message: `${field.label} must be a number` });
137
- break;
138
- case "text":
139
- default:
140
- validator = _zod.z.string().max(1e3, { message: `${field.label} is too long` });
141
- break;
142
- }
143
- if (field.required) {
144
- validator = field.type === "checkbox" ? _zod.z.literal(true, { message: `${field.label} is required` }) : validator.min(1, { message: `${field.label} is required` });
145
- } else if (field.type !== "checkbox") {
146
- validator = validator.optional().or(_zod.z.literal(""));
174
+ const spec = FORM_FIELD_TYPES[field.type];
175
+ let validator = spec.validator(field);
176
+ if (spec.kind === "boolean") {
177
+ validator = field.required ? _zod.z.literal(true, { message: `${field.label} is required` }) : _zod.z.boolean().optional();
147
178
  } else {
148
- validator = _zod.z.boolean().optional();
179
+ validator = field.required ? validator.min(1, { message: `${field.label} is required` }) : validator.optional().or(_zod.z.literal(""));
149
180
  }
150
181
  answers[field.name] = validator;
151
182
  }
@@ -289,6 +320,80 @@ var SPAN_CLASS = {
289
320
  4: "md:col-span-4"
290
321
  };
291
322
  var evenSpan = (count) => Math.min(4, Math.max(1, Math.floor(4 / Math.max(1, count))));
323
+ var INPUT_CLASS = "bg-ods-card border-ods-border text-ods-text-primary placeholder-ods-text-secondary px-3 h-11 md:h-12";
324
+ var TEXTAREA_CLASS = "border-ods-border bg-ods-card px-3 text-ods-text-primary placeholder-ods-text-secondary";
325
+ var placeholderFor = (field) => _nullishCoalesce(field.placeholder, () => ( (field.type === "text" ? `Enter ${field.label}` : field.type === "textarea" ? `Enter text${field.required ? "" : " (optional)"}` : void 0)));
326
+ var FIELD_CONTROLS = {
327
+ text: ({ field, id, registerName, register }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
328
+ _chunkUKT2FAPZcjs.Input,
329
+ {
330
+ id,
331
+ type: _nullishCoalesce(field.inputType, () => ( "text")),
332
+ required: field.required,
333
+ autoComplete: field.autoComplete,
334
+ placeholder: placeholderFor(field),
335
+ className: INPUT_CLASS,
336
+ ...register(registerName)
337
+ }
338
+ ),
339
+ textarea: ({ field, id, registerName, register }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
340
+ _chunkJFP4Q54Dcjs.Textarea,
341
+ {
342
+ id,
343
+ placeholder: placeholderFor(field),
344
+ className: TEXTAREA_CLASS,
345
+ ...register(registerName)
346
+ }
347
+ ),
348
+ number: ({ field, id, registerName, register }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
349
+ _chunkUKT2FAPZcjs.Input,
350
+ {
351
+ id,
352
+ type: "number",
353
+ inputMode: "numeric",
354
+ step: "any",
355
+ required: field.required,
356
+ className: INPUT_CLASS,
357
+ ...register(registerName)
358
+ }
359
+ ),
360
+ select: ({ field, id, registerName, control }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
361
+ _reacthookform.Controller,
362
+ {
363
+ control,
364
+ name: registerName,
365
+ render: ({ field: rhf }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkJFP4Q54Dcjs.Select, { value: _nullishCoalesce(rhf.value, () => ( "")), onValueChange: rhf.onChange, children: [
366
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.SelectTrigger, { id, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.SelectValue, { placeholder: "Select\u2026" }) }),
367
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.SelectContent, { children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.SelectItem, { value: opt, children: opt }, opt)) })
368
+ ] })
369
+ }
370
+ ),
371
+ radio: ({ field, id, registerName, control }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
372
+ _reacthookform.Controller,
373
+ {
374
+ control,
375
+ name: registerName,
376
+ render: ({ field: rhf }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.RadioGroup, { value: _nullishCoalesce(rhf.value, () => ( "")), onValueChange: rhf.onChange, children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-[var(--spacing-system-xs)]", children: [
377
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.RadioGroupItem, { id: `${id}-${opt}`, value: opt }),
378
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCHIHYC7Qcjs.Label, { htmlFor: `${id}-${opt}`, children: opt })
379
+ ] }, opt)) })
380
+ }
381
+ ),
382
+ checkbox: ({ id, registerName, control }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
383
+ _reacthookform.Controller,
384
+ {
385
+ control,
386
+ name: registerName,
387
+ render: ({ field: rhf }) => (
388
+ // The question's Label above already carries the text and binds to
389
+ // this id — a second inline label would double the visible text AND
390
+ // the accessible name.
391
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center gap-[var(--spacing-system-xs)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUKT2FAPZcjs.Checkbox, { id, checked: Boolean(rhf.value), onCheckedChange: (v) => rhf.onChange(v === true) }) })
392
+ )
393
+ }
394
+ )
395
+ };
396
+ var builtInId = (name) => `ms-${name.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}`;
292
397
  function BookingForm({
293
398
  availability,
294
399
  meetingId,
@@ -373,120 +478,19 @@ function BookingForm({
373
478
  const err = _optionalChain([errors, 'access', _12 => _12.formFields, 'optionalAccess', _13 => _13[name]]);
374
479
  return _optionalChain([err, 'optionalAccess', _14 => _14.message]);
375
480
  };
376
- const inputClass = "bg-ods-card border-ods-border text-ods-text-primary placeholder-ods-text-secondary px-3 h-11 md:h-12";
377
481
  const FORM_STACK = "flex flex-col gap-[var(--spacing-system-l)]";
378
- const builtInFields = {
379
- email: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUKT2FAPZcjs.FieldWrapper, { label: "Email", htmlFor: "ms-email", required: true, error: _optionalChain([errors, 'access', _15 => _15.email, 'optionalAccess', _16 => _16.message]), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
380
- _chunkUKT2FAPZcjs.Input,
381
- {
382
- id: "ms-email",
383
- type: "email",
384
- required: true,
385
- autoComplete: "email",
386
- placeholder: "jane@company.com",
387
- "aria-invalid": !!errors.email,
388
- className: inputClass,
389
- ...register("email")
390
- }
391
- ) }),
392
- firstName: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUKT2FAPZcjs.FieldWrapper, { label: "First Name", htmlFor: "ms-first-name", required: true, error: _optionalChain([errors, 'access', _17 => _17.firstName, 'optionalAccess', _18 => _18.message]), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
393
- _chunkUKT2FAPZcjs.Input,
394
- {
395
- id: "ms-first-name",
396
- required: true,
397
- autoComplete: "given-name",
398
- placeholder: "Jane",
399
- "aria-invalid": !!errors.firstName,
400
- className: inputClass,
401
- ...register("firstName")
402
- }
403
- ) }),
404
- lastName: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUKT2FAPZcjs.FieldWrapper, { label: "Last Name", htmlFor: "ms-last-name", required: true, error: _optionalChain([errors, 'access', _19 => _19.lastName, 'optionalAccess', _20 => _20.message]), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
405
- _chunkUKT2FAPZcjs.Input,
406
- {
407
- id: "ms-last-name",
408
- required: true,
409
- autoComplete: "family-name",
410
- placeholder: "Doe",
411
- "aria-invalid": !!errors.lastName,
412
- className: inputClass,
413
- ...register("lastName")
414
- }
415
- ) })
416
- };
417
- const renderDeclaredField = (field) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
418
- _chunkUKT2FAPZcjs.FieldWrapper,
419
- {
420
- label: field.label,
421
- htmlFor: `ms-q-${field.name}`,
422
- required: field.required,
423
- error: fieldError(field.name),
424
- children: [
425
- field.type === "textarea" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
426
- _chunkJFP4Q54Dcjs.Textarea,
427
- {
428
- id: `ms-q-${field.name}`,
429
- className: "border-ods-border bg-ods-card px-3 text-ods-text-primary placeholder-ods-text-secondary",
430
- ...register(`formFields.${field.name}`)
431
- }
432
- ),
433
- field.type === "text" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
434
- _chunkUKT2FAPZcjs.Input,
435
- {
436
- id: `ms-q-${field.name}`,
437
- className: "h-11 border-ods-border bg-ods-card px-3 text-ods-text-primary placeholder-ods-text-secondary md:h-12",
438
- ...register(`formFields.${field.name}`)
439
- }
440
- ),
441
- field.type === "number" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
442
- _chunkUKT2FAPZcjs.Input,
443
- {
444
- id: `ms-q-${field.name}`,
445
- type: "number",
446
- inputMode: "numeric",
447
- step: "any",
448
- className: "h-11 border-ods-border bg-ods-card px-3 text-ods-text-primary placeholder-ods-text-secondary md:h-12",
449
- ...register(`formFields.${field.name}`)
450
- }
451
- ),
452
- (field.type === "select" || field.type === "radio") && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
453
- _reacthookform.Controller,
454
- {
455
- control,
456
- name: `formFields.${field.name}`,
457
- render: ({ field: rhf }) => field.type === "select" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkJFP4Q54Dcjs.Select, { value: _nullishCoalesce(rhf.value, () => ( "")), onValueChange: rhf.onChange, children: [
458
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.SelectTrigger, { id: `ms-q-${field.name}`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.SelectValue, { placeholder: "Select\u2026" }) }),
459
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.SelectContent, { children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.SelectItem, { value: opt, children: opt }, opt)) })
460
- ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.RadioGroup, { value: _nullishCoalesce(rhf.value, () => ( "")), onValueChange: rhf.onChange, children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-[var(--spacing-system-xs)]", children: [
461
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJFP4Q54Dcjs.RadioGroupItem, { id: `ms-q-${field.name}-${opt}`, value: opt }),
462
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCHIHYC7Qcjs.Label, { htmlFor: `ms-q-${field.name}-${opt}`, children: opt })
463
- ] }, opt)) })
464
- }
465
- ),
466
- field.type === "checkbox" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
467
- _reacthookform.Controller,
468
- {
469
- control,
470
- name: `formFields.${field.name}`,
471
- render: ({ field: rhf }) => (
472
- // The question's Label above already carries the text and
473
- // binds to this id — a second inline label would double the
474
- // visible text AND the accessible name.
475
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center gap-[var(--spacing-system-xs)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
476
- _chunkUKT2FAPZcjs.Checkbox,
477
- {
478
- id: `ms-q-${field.name}`,
479
- checked: Boolean(rhf.value),
480
- onCheckedChange: (v) => rhf.onChange(v === true)
481
- }
482
- ) })
483
- )
484
- }
485
- )
486
- ]
487
- },
488
- field.name
482
+ const renderField = (field, where) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUKT2FAPZcjs.FieldWrapper, { label: field.label, htmlFor: where.id, required: field.required, error: where.error, children: FIELD_CONTROLS[field.type]({ field, id: where.id, registerName: where.registerName, register, control }) }, field.name);
483
+ const builtInFields = Object.fromEntries(
484
+ BUILT_IN_BOOKING_FIELDS.map((field) => [
485
+ field.name,
486
+ renderField(field, { id: builtInId(field.name), registerName: field.name, error: _optionalChain([errors, 'access', _15 => _15[field.name], 'optionalAccess', _16 => _16.message]) })
487
+ ])
489
488
  );
489
+ const renderDeclaredField = (field) => renderField(field, {
490
+ id: `ms-q-${field.name}`,
491
+ registerName: `formFields.${field.name}`,
492
+ error: fieldError(field.name)
493
+ });
490
494
  const declaredByName = new Map(supportedFields.map((f) => [f.name, f]));
491
495
  const slotResolves = (name) => Boolean(builtInFields[name] || declaredByName.has(name));
492
496
  const slotNode = (name) => {
@@ -560,7 +564,7 @@ function BookingForm({
560
564
  // box doesn't shove the submit button down the card. With no error the
561
565
  // wrapper is `display:contents` and the panel below is the flex item,
562
566
  // exactly as it was.
563
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUKT2FAPZcjs.FieldWrapper, { error: _optionalChain([errors, 'access', _21 => _21.legalConsentResponses, 'optionalAccess', _22 => _22.message]), children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-[var(--spacing-system-xs)]", children: [
567
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUKT2FAPZcjs.FieldWrapper, { error: _optionalChain([errors, 'access', _17 => _17.legalConsentResponses, 'optionalAccess', _18 => _18.message]), children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-[var(--spacing-system-xs)]", children: [
564
568
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
565
569
  _reacthookform.Controller,
566
570
  {
@@ -580,7 +584,7 @@ function BookingForm({
580
584
  _chunkJFP4Q54Dcjs.CheckboxBlock,
581
585
  {
582
586
  id: `ms-consent-${box.communicationTypeId}`,
583
- checked: _nullishCoalesce(_optionalChain([current, 'optionalAccess', _23 => _23.consented]), () => ( false)),
587
+ checked: _nullishCoalesce(_optionalChain([current, 'optionalAccess', _19 => _19.consented]), () => ( false)),
584
588
  onCheckedChange: (v) => rhf.onChange(
585
589
  responses.map(
586
590
  (r) => r.communicationTypeId === box.communicationTypeId ? { ...r, consented: v } : r
@@ -658,7 +662,7 @@ function zoneLabel(tz) {
658
662
  timeZone: tz,
659
663
  timeZoneName: "shortOffset"
660
664
  }).formatToParts(/* @__PURE__ */ new Date());
661
- const offset = _nullishCoalesce(_optionalChain([parts, 'access', _24 => _24.find, 'call', _25 => _25((p) => p.type === "timeZoneName"), 'optionalAccess', _26 => _26.value]), () => ( ""));
665
+ const offset = _nullishCoalesce(_optionalChain([parts, 'access', _20 => _20.find, 'call', _21 => _21((p) => p.type === "timeZoneName"), 'optionalAccess', _22 => _22.value]), () => ( ""));
662
666
  return offset ? `${tz.replace(/_/g, " ")} (${offset})` : tz.replace(/_/g, " ");
663
667
  } catch (e4) {
664
668
  return tz.replace(/_/g, " ");
@@ -782,7 +786,7 @@ function SchedulerContextPanel({
782
786
  {
783
787
  value: timezone,
784
788
  onChange: (tz) => {
785
- if (tz) _optionalChain([onTimezoneChange, 'optionalCall', _27 => _27(tz)]);
789
+ if (tz) _optionalChain([onTimezoneChange, 'optionalCall', _23 => _23(tz)]);
786
790
  },
787
791
  options: zoneOptions,
788
792
  placeholder: "Search timezone\u2026",
@@ -866,7 +870,7 @@ function DayCalendar({ monthOffset, onMonthOffsetChange, selectedDay, onSelectDa
866
870
  const startMonth = new Date(now.getFullYear(), now.getMonth(), 1);
867
871
  const endMonth = new Date(now.getFullYear(), now.getMonth() + _chunkJFP4Q54Dcjs.MAX_MONTH_OFFSET + 1, 0);
868
872
  const visibleMonth = new Date(now.getFullYear(), now.getMonth() + monthOffset, 1);
869
- const dayHasNoSlots = _react.useCallback.call(void 0, (day) => !_optionalChain([slotsByDay, 'optionalAccess', _28 => _28.has, 'call', _29 => _29(calendarDayKey(day))]), [slotsByDay]);
873
+ const dayHasNoSlots = _react.useCallback.call(void 0, (day) => !_optionalChain([slotsByDay, 'optionalAccess', _24 => _24.has, 'call', _25 => _25(calendarDayKey(day))]), [slotsByDay]);
870
874
  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,
871
875
  _chunkJFP4Q54Dcjs.DatePickerCalendar,
872
876
  {
@@ -884,7 +888,7 @@ function DayCalendar({ monthOffset, onMonthOffsetChange, selectedDay, onSelectDa
884
888
  const day = value;
885
889
  if (!day) return;
886
890
  const key = calendarDayKey(day);
887
- if (_optionalChain([slotsByDay, 'optionalAccess', _30 => _30.has, 'call', _31 => _31(key)])) onSelectDay(key);
891
+ if (_optionalChain([slotsByDay, 'optionalAccess', _26 => _26.has, 'call', _27 => _27(key)])) onSelectDay(key);
888
892
  },
889
893
  disabledDays: slotsByDay === null ? DISABLE_EVERY_DAY : dayHasNoSlots
890
894
  }
@@ -1122,7 +1126,7 @@ function MeetingSchedulerDirectory({
1122
1126
  };
1123
1127
  }, [initialData, includeAll, apiBaseUrl]);
1124
1128
  const rows = _react.useMemo.call(void 0, () => {
1125
- const purposes = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _32 => _32.purposes]), () => ( []));
1129
+ const purposes = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _28 => _28.purposes]), () => ( []));
1126
1130
  return purposes.flatMap((p) => p.links.map((link) => ({ link, audienceLabel: p.label })));
1127
1131
  }, [data]);
1128
1132
  const totalPages = _chunkH64ZHSYRcjs.pageCount.call(void 0, rows.length, pageSize);
@@ -1269,8 +1273,8 @@ function HubSpotMeetingScheduler({
1269
1273
  _react.useEffect.call(void 0, () => {
1270
1274
  autoAdvanceCount.current = 0;
1271
1275
  }, [meetingId]);
1272
- const durations = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([availability, 'optionalAccess', _33 => _33.durationsMs]), () => ( [])), [_optionalChain([availability, 'optionalAccess', _34 => _34.durationsMs])]);
1273
- const shownHosts = _nullishCoalesce(_nullishCoalesce(hosts, () => ( _optionalChain([availability, 'optionalAccess', _35 => _35.hosts]))), () => ( []));
1276
+ const durations = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([availability, 'optionalAccess', _29 => _29.durationsMs]), () => ( [])), [_optionalChain([availability, 'optionalAccess', _30 => _30.durationsMs])]);
1277
+ const shownHosts = _nullishCoalesce(_nullishCoalesce(hosts, () => ( _optionalChain([availability, 'optionalAccess', _31 => _31.hosts]))), () => ( []));
1274
1278
  const durationMs = _nullishCoalesce(_nullishCoalesce(pickedDurationMs, () => ( durations[0])), () => ( null));
1275
1279
  const slots = _react.useMemo.call(void 0, () => {
1276
1280
  if (!availability || durationMs == null) return [];
@@ -1326,7 +1330,7 @@ function HubSpotMeetingScheduler({
1326
1330
  if (result.ok && result.confirmation) {
1327
1331
  setConfirmation(result.confirmation);
1328
1332
  setStep("confirmed");
1329
- _optionalChain([onBooked, 'optionalCall', _36 => _36(result.confirmation)]);
1333
+ _optionalChain([onBooked, 'optionalCall', _32 => _32(result.confirmation)]);
1330
1334
  return;
1331
1335
  }
1332
1336
  const code = _nullishCoalesce(result.code, () => ( "TEMPORARILY_UNAVAILABLE"));
@@ -1423,7 +1427,7 @@ function HubSpotMeetingScheduler({
1423
1427
  deferSlot: detailsFirst,
1424
1428
  submitLabel: detailsFirst ? "Continue" : void 0,
1425
1429
  footerNote: detailsFirst ? "Next step: pick a slot that works. Calendar invite lands right after." : void 0,
1426
- initialValues: detailsFirst ? _optionalChain([stash, 'optionalAccess', _37 => _37.payload]) : void 0,
1430
+ initialValues: detailsFirst ? _optionalChain([stash, 'optionalAccess', _33 => _33.payload]) : void 0,
1427
1431
  isSubmitting,
1428
1432
  onSubmit: detailsFirst ? stashDetails : handleSubmit,
1429
1433
  honeypotInputProps,