@flamingo-stack/openframe-frontend-core 0.0.664 → 0.0.665-2372.7061.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 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/index.tsx"],"names":[],"mappings":"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"}
@@ -101,6 +101,18 @@ var optionValidator = (field, base) => base.refine((v) => !v || (field.options ?
101
101
  message: `Please choose a valid option for ${field.label}`
102
102
  });
103
103
  var DECIMAL_LITERAL_RE = /^-?\d+(\.\d+)?$/;
104
+ var MULTI_VALUE_SEPARATOR = ";";
105
+ var splitMultiValue = (value) => typeof value === "string" && value ? value.split(MULTI_VALUE_SEPARATOR) : [];
106
+ var PHONE_RE = /^\+?[\d\s().\-/]+(?:\s*(?:x|ext\.?)\s*\d+)?$/i;
107
+ var PHONE_MIN_DIGITS = 5;
108
+ var PHONE_MAX_DIGITS = 20;
109
+ var phoneDigits = (v) => v.replace(/\D/g, "").length;
110
+ var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
111
+ var isRealIsoDate = (v) => {
112
+ if (!ISO_DATE_RE.test(v)) return false;
113
+ const d = /* @__PURE__ */ new Date(`${v}T00:00:00Z`);
114
+ return !Number.isNaN(d.getTime()) && d.toISOString().slice(0, 10) === v;
115
+ };
104
116
  var FORM_FIELD_TYPES = {
105
117
  text: {
106
118
  kind: "string",
@@ -121,16 +133,85 @@ var FORM_FIELD_TYPES = {
121
133
  // accepts (`1e3`, `007`) to this before it is validated or sent.
122
134
  validator: (field, base) => base.max(32, { message: `${field.label} is too long` }).regex(DECIMAL_LITERAL_RE, { message: `${field.label} must be a number` })
123
135
  },
136
+ phone: {
137
+ kind: "string",
138
+ hasOptions: false,
139
+ validator: (field, base) => base.max(40, { message: `${field.label} is too long` }).refine(
140
+ (v) => !v || PHONE_RE.test(v) && phoneDigits(v) >= PHONE_MIN_DIGITS && phoneDigits(v) <= PHONE_MAX_DIGITS,
141
+ { message: `Please enter a valid phone number for ${field.label}` }
142
+ ),
143
+ placeholder: (field) => `Enter ${field.label}`
144
+ },
145
+ date: {
146
+ kind: "string",
147
+ hasOptions: false,
148
+ validator: (field, base) => base.refine((v) => !v || isRealIsoDate(v), { message: `${field.label} must be a date` })
149
+ },
124
150
  select: { kind: "string", hasOptions: true, validator: optionValidator },
125
151
  radio: { kind: "string", hasOptions: true, validator: optionValidator },
152
+ multiselect: {
153
+ kind: "string",
154
+ hasOptions: true,
155
+ validator: (field, base) => base.refine((v) => splitMultiValue(v).every((part) => (field.options ?? []).includes(part)), {
156
+ message: `Please choose valid options for ${field.label}`
157
+ })
158
+ },
126
159
  checkbox: { kind: "boolean", hasOptions: false, validator: () => z.boolean() }
127
160
  };
128
161
  var SUPPORTED_FORM_FIELD_TYPES = Object.keys(FORM_FIELD_TYPES);
129
- var FORM_FIELD_TYPES_WITH_OPTIONS = SUPPORTED_FORM_FIELD_TYPES.filter(
130
- (type) => FORM_FIELD_TYPES[type].hasOptions
131
- );
132
- function isSupportedFormField(field) {
133
- return Object.prototype.hasOwnProperty.call(FORM_FIELD_TYPES, field.type);
162
+ var FIELD_TYPE_CONTROLS = {
163
+ text: "text",
164
+ textarea: "textarea",
165
+ number: "number",
166
+ select: "select",
167
+ radio: "radio",
168
+ booleancheckbox: "checkbox",
169
+ phonenumber: "phone",
170
+ date: "date",
171
+ html: "display",
172
+ file: "unanswerable"
173
+ };
174
+ var DATA_TYPE_CONTROLS = {
175
+ string: "text",
176
+ number: "number",
177
+ enumeration: "select",
178
+ bool: "checkbox",
179
+ date: "date",
180
+ datetime: "date",
181
+ phone_number: "phone"
182
+ };
183
+ var hasDeclaredOptions = (field) => (field.options?.length ?? 0) > 0;
184
+ function resolveFormFieldControl(field) {
185
+ const fieldType = (field.type ?? "").toLowerCase();
186
+ const withOptions = hasDeclaredOptions(field);
187
+ const usable = (r) => {
188
+ if (!r || r === "display" || r === "unanswerable") return r;
189
+ return FORM_FIELD_TYPES[r].hasOptions && !withOptions ? "text" : r;
190
+ };
191
+ if (fieldType === "checkbox") return withOptions ? "multiselect" : "checkbox";
192
+ if (fieldType.startsWith("calculation")) return "display";
193
+ const asControl = Object.prototype.hasOwnProperty.call(FORM_FIELD_TYPES, fieldType) ? fieldType : void 0;
194
+ return usable(FIELD_TYPE_CONTROLS[fieldType] ?? asControl) ?? usable(DATA_TYPE_CONTROLS[(field.dataType ?? "").toLowerCase()]) ?? (withOptions ? "select" : "text");
195
+ }
196
+ function normalizeFormField(field) {
197
+ const control = resolveFormFieldControl(field);
198
+ if (control === "display" || control === "unanswerable") return null;
199
+ const normalized = {
200
+ ...field,
201
+ type: control,
202
+ hubspotType: field.hubspotType ?? field.type
203
+ };
204
+ if (!FORM_FIELD_TYPES[control].hasOptions) {
205
+ delete normalized.options;
206
+ delete normalized.optionLabels;
207
+ }
208
+ return normalized;
209
+ }
210
+ function normalizeFormFields(fields) {
211
+ return fields.flatMap((f) => normalizeFormField(f) ?? []);
212
+ }
213
+ function blocksNativeBooking(field) {
214
+ return field.required && resolveFormFieldControl(field) === "unanswerable";
134
215
  }
135
216
  var BUILT_IN_BOOKING_FIELDS = [
136
217
  {
@@ -188,8 +269,8 @@ function isValidBcp47Locale(locale) {
188
269
  }
189
270
  function buildBookingSchema(formFields, legalConsent, slot) {
190
271
  const answers = {};
191
- for (const field of formFields) {
192
- if (!isSupportedFormField(field)) continue;
272
+ const drawn = normalizeFormFields(formFields);
273
+ for (const field of drawn) {
193
274
  const spec = FORM_FIELD_TYPES[field.type];
194
275
  let validator;
195
276
  if (spec.kind === "boolean") {
@@ -202,7 +283,7 @@ function buildBookingSchema(formFields, legalConsent, slot) {
202
283
  answers[field.name] = validator;
203
284
  }
204
285
  const requiredConsentIds = (legalConsent?.communicationConsentCheckboxes ?? []).filter((c) => c.required).map((c) => c.communicationTypeId);
205
- const hasRequiredAnswers = formFields.some((f) => isSupportedFormField(f) && f.required);
286
+ const hasRequiredAnswers = drawn.some((f) => f.required);
206
287
  const answersObject = z.object(answers);
207
288
  return z.object({
208
289
  meetingId: z.string().min(1),
@@ -362,6 +443,8 @@ var evenSpan = (count, index) => {
362
443
  };
363
444
  var slotColumnClass = (row, slot, index) => cn(row.length === 2 ? "col-span-1" : "col-span-2", SPAN_CLASS[slot.span ?? evenSpan(row.length, index)]);
364
445
  var placeholderFor = (field) => field.placeholder ?? fieldTypeSpec(field.type).placeholder?.(field);
446
+ var optionLabel = (field, value) => field.optionLabels?.[value] ?? value;
447
+ var trimmed = (v) => String(v ?? "").trim();
365
448
  var canonicalNumber = (v) => {
366
449
  const s = String(v ?? "").trim();
367
450
  if (s === "" || DECIMAL_LITERAL_RE.test(s)) return s;
@@ -405,6 +488,32 @@ var FIELD_CONTROLS = {
405
488
  ...register(registerName, { setValueAs: canonicalNumber })
406
489
  }
407
490
  ),
491
+ phone: ({ field, id, registerName, error, register }) => /* @__PURE__ */ jsx(
492
+ Input,
493
+ {
494
+ id,
495
+ type: "tel",
496
+ inputMode: "tel",
497
+ autoComplete: "tel",
498
+ required: field.required,
499
+ "aria-invalid": Boolean(error),
500
+ placeholder: placeholderFor(field),
501
+ ...register(registerName, { setValueAs: trimmed })
502
+ }
503
+ ),
504
+ date: ({ field, id, registerName, error, register }) => (
505
+ // The native picker emits exactly the wire shape (`YYYY-MM-DD`).
506
+ /* @__PURE__ */ jsx(
507
+ Input,
508
+ {
509
+ id,
510
+ type: "date",
511
+ required: field.required,
512
+ "aria-invalid": Boolean(error),
513
+ ...register(registerName)
514
+ }
515
+ )
516
+ ),
408
517
  select: ({ field, id, registerName, error, control }) => /* @__PURE__ */ jsx(
409
518
  Controller,
410
519
  {
@@ -412,7 +521,7 @@ var FIELD_CONTROLS = {
412
521
  name: registerName,
413
522
  render: ({ field: rhf }) => /* @__PURE__ */ jsxs(Select, { value: rhf.value ?? "", onValueChange: rhf.onChange, children: [
414
523
  /* @__PURE__ */ jsx(SelectTrigger, { id, "aria-required": field.required || void 0, "aria-invalid": Boolean(error), children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select\u2026" }) }),
415
- /* @__PURE__ */ jsx(SelectContent, { children: (field.options ?? []).map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt, children: opt }, opt)) })
524
+ /* @__PURE__ */ jsx(SelectContent, { children: (field.options ?? []).map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt, children: optionLabel(field, opt) }, opt)) })
416
525
  ] })
417
526
  }
418
527
  ),
@@ -430,12 +539,42 @@ var FIELD_CONTROLS = {
430
539
  "aria-invalid": Boolean(error),
431
540
  children: (field.options ?? []).map((opt) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[var(--spacing-system-xs)]", children: [
432
541
  /* @__PURE__ */ jsx(RadioGroupItem, { id: `${id}-${opt}`, value: opt }),
433
- /* @__PURE__ */ jsx(Label, { htmlFor: `${id}-${opt}`, children: opt })
542
+ /* @__PURE__ */ jsx(Label, { htmlFor: `${id}-${opt}`, children: optionLabel(field, opt) })
434
543
  ] }, opt))
435
544
  }
436
545
  )
437
546
  }
438
547
  ),
548
+ multiselect: ({ field, id, registerName, error, control }) => (
549
+ // HubSpot's "multiple checkboxes": the answer is its `;`-joined value list,
550
+ // held in that wire shape so the validator and the POST see one string.
551
+ /* @__PURE__ */ jsx(
552
+ Controller,
553
+ {
554
+ control,
555
+ name: registerName,
556
+ render: ({ field: rhf }) => {
557
+ const selected = splitMultiValue(rhf.value);
558
+ const toggle = (opt, on) => {
559
+ const next = (field.options ?? []).filter((o) => o === opt ? on : selected.includes(o));
560
+ rhf.onChange(next.join(MULTI_VALUE_SEPARATOR));
561
+ };
562
+ return /* @__PURE__ */ jsx("div", { id, role: "group", className: "flex flex-col gap-[var(--spacing-system-xs)]", children: (field.options ?? []).map((opt) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[var(--spacing-system-xs)]", children: [
563
+ /* @__PURE__ */ jsx(
564
+ Checkbox,
565
+ {
566
+ id: `${id}-${opt}`,
567
+ checked: selected.includes(opt),
568
+ onCheckedChange: (v) => toggle(opt, v === true),
569
+ "aria-invalid": Boolean(error)
570
+ }
571
+ ),
572
+ /* @__PURE__ */ jsx(Label, { htmlFor: `${id}-${opt}`, children: optionLabel(field, opt) })
573
+ ] }, opt)) });
574
+ }
575
+ }
576
+ )
577
+ ),
439
578
  checkbox: ({ field, id, registerName, error, control }) => /* @__PURE__ */ jsx(
440
579
  Controller,
441
580
  {
@@ -478,7 +617,7 @@ function BookingForm({
478
617
  getSignals
479
618
  }) {
480
619
  const { formFields, legalConsent } = availability;
481
- const supportedFields = useMemo(() => formFields.filter(isSupportedFormField), [formFields]);
620
+ const supportedFields = useMemo(() => normalizeFormFields(formFields), [formFields]);
482
621
  const schema = useMemo(
483
622
  () => makeDeferredBookingSchema(supportedFields, legalConsent),
484
623
  [supportedFields, legalConsent]
@@ -1293,7 +1432,7 @@ function SchedulerDegradedCard({
1293
1432
  ] });
1294
1433
  }
1295
1434
  function isNativelyBookable(availability) {
1296
- if (!availability.formFields.every(isSupportedFormField)) return false;
1435
+ if (availability.formFields.some(blocksNativeBooking)) return false;
1297
1436
  const consent = availability.legalConsent;
1298
1437
  if (consent) {
1299
1438
  if (typeof consent.processingConsentText !== "string") return false;