@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.
- package/dist/components/meeting-scheduler/booking-form.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/index.cjs +177 -38
- package/dist/components/meeting-scheduler/index.cjs.map +1 -1
- package/dist/components/meeting-scheduler/index.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/index.js +151 -12
- package/dist/components/meeting-scheduler/index.js.map +1 -1
- package/dist/schemas/meeting-booking-schema.cjs +103 -11
- package/dist/schemas/meeting-booking-schema.cjs.map +1 -1
- package/dist/schemas/meeting-booking-schema.d.ts +96 -20
- package/dist/schemas/meeting-booking-schema.d.ts.map +1 -1
- package/dist/schemas/meeting-booking-schema.js +95 -10
- package/dist/schemas/meeting-booking-schema.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/meeting-booking-schema.test.ts +2 -2
- package/src/__tests__/meeting-form-field-types.test.tsx +178 -0
- package/src/components/meeting-scheduler/booking-form.tsx +67 -4
- package/src/components/meeting-scheduler/index.tsx +9 -6
- package/src/schemas/meeting-booking-schema.ts +217 -28
- package/src/utils/__tests__/hubspot-meetings-convention.test.ts +15 -6
|
@@ -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;AAGvD,OAAO,EAEL,KAAK,uBAAuB,
|
|
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,EAEL,KAAK,uBAAuB,EAQ5B,KAAK,mBAAmB,EAKzB,MAAM,sCAAsC,CAAC;AAsB9C;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yFAAyF;IACzF,IAAI,EAAE,uBAAuB,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,gFAAgF;IAChF,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,+EAA+E;AAC/E,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,UAAU,CAAC;AAEvD,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;AAiBD;6CAC6C;AAC7C,QAAA,MAAM,UAAU;;;;;CAKN,CAAC;AAOX,0GAA0G;AAC1G,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AAYtD;iFACiF;AACjF,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,KAAG,gBAIvD,CAAC;AA+MF,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;;;;;;;;;;;;;GAaG;AACH,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,+BAuTlB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,OAAO,EACP,UAAU,GACX,EAAE;IACD,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B;;qDAEiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,+BA2BA"}
|
|
@@ -101,6 +101,18 @@ var optionValidator = (field, base) => base.refine((v) => !v || (_nullishCoalesc
|
|
|
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) => (_nullishCoalesce(field.options, () => ( []))).includes(part)), {
|
|
156
|
+
message: `Please choose valid options for ${field.label}`
|
|
157
|
+
})
|
|
158
|
+
},
|
|
126
159
|
checkbox: { kind: "boolean", hasOptions: false, validator: () => _zod.z.boolean() }
|
|
127
160
|
};
|
|
128
161
|
var SUPPORTED_FORM_FIELD_TYPES = Object.keys(FORM_FIELD_TYPES);
|
|
129
|
-
var
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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) => (_nullishCoalesce(_optionalChain([field, 'access', _2 => _2.options, 'optionalAccess', _3 => _3.length]), () => ( 0))) > 0;
|
|
184
|
+
function resolveFormFieldControl(field) {
|
|
185
|
+
const fieldType = (_nullishCoalesce(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 _nullishCoalesce(_nullishCoalesce(usable(_nullishCoalesce(FIELD_TYPE_CONTROLS[fieldType], () => ( asControl))), () => ( usable(DATA_TYPE_CONTROLS[(_nullishCoalesce(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: _nullishCoalesce(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) => _nullishCoalesce(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
|
-
|
|
192
|
-
|
|
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") {
|
|
@@ -201,8 +282,8 @@ function buildBookingSchema(formFields, legalConsent, slot) {
|
|
|
201
282
|
}
|
|
202
283
|
answers[field.name] = validator;
|
|
203
284
|
}
|
|
204
|
-
const requiredConsentIds = (_nullishCoalesce(_optionalChain([legalConsent, 'optionalAccess',
|
|
205
|
-
const hasRequiredAnswers =
|
|
285
|
+
const requiredConsentIds = (_nullishCoalesce(_optionalChain([legalConsent, 'optionalAccess', _4 => _4.communicationConsentCheckboxes]), () => ( []))).filter((c) => c.required).map((c) => c.communicationTypeId);
|
|
286
|
+
const hasRequiredAnswers = drawn.some((f) => f.required);
|
|
206
287
|
const answersObject = _zod.z.object(answers);
|
|
207
288
|
return _zod.z.object({
|
|
208
289
|
meetingId: _zod.z.string().min(1),
|
|
@@ -254,7 +335,7 @@ var BOOKING_IN_FLIGHT_MESSAGE = "Already submitting";
|
|
|
254
335
|
function useMeetingBooking(options) {
|
|
255
336
|
const { meetingId, apiBaseUrl = "", initialAvailability } = options;
|
|
256
337
|
const queryClient = _reactquery.useQueryClient.call(void 0, );
|
|
257
|
-
const seededOffset = _optionalChain([initialAvailability, 'optionalAccess',
|
|
338
|
+
const seededOffset = _optionalChain([initialAvailability, 'optionalAccess', _5 => _5.meetingId]) === meetingId ? initialAvailability.monthOffset : void 0;
|
|
258
339
|
const [monthOffset, setMonthOffsetState] = _react.useState.call(void 0, _nullishCoalesce(seededOffset, () => ( 0)));
|
|
259
340
|
const setMonthOffset = _react.useCallback.call(void 0, (offset) => {
|
|
260
341
|
setMonthOffsetState(Math.max(0, Math.min(_chunk6FD7ZEBYcjs.MAX_MONTH_OFFSET, offset)));
|
|
@@ -265,7 +346,7 @@ function useMeetingBooking(options) {
|
|
|
265
346
|
prevMeetingIdRef.current = meetingId;
|
|
266
347
|
setMonthOffsetState(0);
|
|
267
348
|
}, [meetingId]);
|
|
268
|
-
const seed = _optionalChain([initialAvailability, 'optionalAccess',
|
|
349
|
+
const seed = _optionalChain([initialAvailability, 'optionalAccess', _6 => _6.meetingId]) === meetingId && initialAvailability.monthOffset === monthOffset ? initialAvailability : void 0;
|
|
269
350
|
const availabilityQuery = _reactquery.useQuery.call(void 0, {
|
|
270
351
|
queryKey: meetingAvailabilityKey(apiBaseUrl, meetingId, monthOffset),
|
|
271
352
|
queryFn: async ({ signal }) => {
|
|
@@ -361,7 +442,9 @@ var evenSpan = (count, index) => {
|
|
|
361
442
|
return Math.min(GRID_COLUMNS, Math.max(1, index < extra ? base + 1 : base));
|
|
362
443
|
};
|
|
363
444
|
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)))]);
|
|
364
|
-
var placeholderFor = (field) => _nullishCoalesce(field.placeholder, () => ( _optionalChain([fieldTypeSpec, 'call',
|
|
445
|
+
var placeholderFor = (field) => _nullishCoalesce(field.placeholder, () => ( _optionalChain([fieldTypeSpec, 'call', _7 => _7(field.type), 'access', _8 => _8.placeholder, 'optionalCall', _9 => _9(field)])));
|
|
446
|
+
var optionLabel = (field, value) => _nullishCoalesce(_optionalChain([field, 'access', _10 => _10.optionLabels, 'optionalAccess', _11 => _11[value]]), () => ( value));
|
|
447
|
+
var trimmed = (v) => String(_nullishCoalesce(v, () => ( ""))).trim();
|
|
365
448
|
var canonicalNumber = (v) => {
|
|
366
449
|
const s = String(_nullishCoalesce(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__ */ _jsxruntime.jsx.call(void 0,
|
|
492
|
+
_chunkQVSVRG7Icjs.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__ */ _jsxruntime.jsx.call(void 0,
|
|
507
|
+
_chunkQVSVRG7Icjs.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__ */ _jsxruntime.jsx.call(void 0,
|
|
409
518
|
_reacthookform.Controller,
|
|
410
519
|
{
|
|
@@ -412,7 +521,7 @@ var FIELD_CONTROLS = {
|
|
|
412
521
|
name: registerName,
|
|
413
522
|
render: ({ field: rhf }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk6FD7ZEBYcjs.Select, { value: _nullishCoalesce(rhf.value, () => ( "")), onValueChange: rhf.onChange, children: [
|
|
414
523
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6FD7ZEBYcjs.SelectTrigger, { id, "aria-required": field.required || void 0, "aria-invalid": Boolean(error), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6FD7ZEBYcjs.SelectValue, { placeholder: "Select\u2026" }) }),
|
|
415
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6FD7ZEBYcjs.SelectContent, { children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6FD7ZEBYcjs.SelectItem, { value: opt, children: opt }, opt)) })
|
|
524
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6FD7ZEBYcjs.SelectContent, { children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6FD7ZEBYcjs.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: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-[var(--spacing-system-xs)]", children: [
|
|
432
541
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk6FD7ZEBYcjs.RadioGroupItem, { id: `${id}-${opt}`, value: opt }),
|
|
433
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkGSD62VAYcjs.Label, { htmlFor: `${id}-${opt}`, children: opt })
|
|
542
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkGSD62VAYcjs.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__ */ _jsxruntime.jsx.call(void 0,
|
|
552
|
+
_reacthookform.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 = (_nullishCoalesce(field.options, () => ( []))).filter((o) => o === opt ? on : selected.includes(o));
|
|
560
|
+
rhf.onChange(next.join(MULTI_VALUE_SEPARATOR));
|
|
561
|
+
};
|
|
562
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { id, role: "group", className: "flex flex-col gap-[var(--spacing-system-xs)]", children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-[var(--spacing-system-xs)]", children: [
|
|
563
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
564
|
+
_chunkQVSVRG7Icjs.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__ */ _jsxruntime.jsx.call(void 0, _chunkGSD62VAYcjs.Label, { htmlFor: `${id}-${opt}`, children: optionLabel(field, opt) })
|
|
573
|
+
] }, opt)) });
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
)
|
|
577
|
+
),
|
|
439
578
|
checkbox: ({ field, id, registerName, error, control }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
440
579
|
_reacthookform.Controller,
|
|
441
580
|
{
|
|
@@ -478,13 +617,13 @@ function BookingForm({
|
|
|
478
617
|
getSignals
|
|
479
618
|
}) {
|
|
480
619
|
const { formFields, legalConsent } = availability;
|
|
481
|
-
const supportedFields = _react.useMemo.call(void 0, () => formFields
|
|
620
|
+
const supportedFields = _react.useMemo.call(void 0, () => normalizeFormFields(formFields), [formFields]);
|
|
482
621
|
const schema = _react.useMemo.call(void 0,
|
|
483
622
|
() => makeDeferredBookingSchema(supportedFields, legalConsent),
|
|
484
623
|
[supportedFields, legalConsent]
|
|
485
624
|
);
|
|
486
625
|
const consentDefaults = _react.useMemo.call(void 0,
|
|
487
|
-
() => (_nullishCoalesce(_optionalChain([legalConsent, 'optionalAccess',
|
|
626
|
+
() => (_nullishCoalesce(_optionalChain([legalConsent, 'optionalAccess', _12 => _12.communicationConsentCheckboxes]), () => ( []))).map((c) => ({
|
|
488
627
|
communicationTypeId: c.communicationTypeId,
|
|
489
628
|
consented: false
|
|
490
629
|
})),
|
|
@@ -515,8 +654,8 @@ function BookingForm({
|
|
|
515
654
|
..._nullishCoalesce(initialValues, () => ( {}))
|
|
516
655
|
}
|
|
517
656
|
});
|
|
518
|
-
const priorConsents = _optionalChain([initialValues, 'optionalAccess',
|
|
519
|
-
const [consented, setConsented] = _react.useState.call(void 0, _optionalChain([initialValues, 'optionalAccess',
|
|
657
|
+
const priorConsents = _optionalChain([initialValues, 'optionalAccess', _13 => _13.legalConsentResponses]);
|
|
658
|
+
const [consented, setConsented] = _react.useState.call(void 0, _optionalChain([initialValues, 'optionalAccess', _14 => _14[HOST_CONSENT_KEY]]) === true);
|
|
520
659
|
const [consentError, setConsentError] = _react.useState.call(void 0, null);
|
|
521
660
|
const consentMissing = Boolean(consent) && !consented;
|
|
522
661
|
_react.useEffect.call(void 0, () => {
|
|
@@ -525,7 +664,7 @@ function BookingForm({
|
|
|
525
664
|
"legalConsentResponses",
|
|
526
665
|
consentDefaults.map((next) => ({
|
|
527
666
|
...next,
|
|
528
|
-
consented: _nullishCoalesce(_optionalChain([current, 'access',
|
|
667
|
+
consented: _nullishCoalesce(_optionalChain([current, 'access', _15 => _15.find, 'call', _16 => _16((r) => r.communicationTypeId === next.communicationTypeId), 'optionalAccess', _17 => _17.consented]), () => ( false))
|
|
529
668
|
})),
|
|
530
669
|
{ shouldDirty: false }
|
|
531
670
|
);
|
|
@@ -547,12 +686,12 @@ function BookingForm({
|
|
|
547
686
|
});
|
|
548
687
|
});
|
|
549
688
|
const submit = (event) => {
|
|
550
|
-
if (consentMissing) setConsentError(_nullishCoalesce(_optionalChain([consent, 'optionalAccess',
|
|
689
|
+
if (consentMissing) setConsentError(_nullishCoalesce(_optionalChain([consent, 'optionalAccess', _18 => _18.errorMessage]), () => ( "Please agree to continue.")));
|
|
551
690
|
return submitValid(event);
|
|
552
691
|
};
|
|
553
692
|
const fieldError = (name) => {
|
|
554
|
-
const err = _optionalChain([errors, 'access',
|
|
555
|
-
return _optionalChain([err, 'optionalAccess',
|
|
693
|
+
const err = _optionalChain([errors, 'access', _19 => _19.formFields, 'optionalAccess', _20 => _20[name]]);
|
|
694
|
+
return _optionalChain([err, 'optionalAccess', _21 => _21.message]);
|
|
556
695
|
};
|
|
557
696
|
const renderField = (field, where) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQVSVRG7Icjs.FieldWrapper, { label: field.label, htmlFor: where.id, required: field.required, error: where.error, children: FIELD_CONTROLS[field.type]({
|
|
558
697
|
field,
|
|
@@ -565,7 +704,7 @@ function BookingForm({
|
|
|
565
704
|
const builtInFields = Object.fromEntries(
|
|
566
705
|
BUILT_IN_BOOKING_FIELDS.map((field) => [
|
|
567
706
|
field.name,
|
|
568
|
-
renderField(field, { id: builtInId(field.name), registerName: field.name, error: _optionalChain([errors, 'access',
|
|
707
|
+
renderField(field, { id: builtInId(field.name), registerName: field.name, error: _optionalChain([errors, 'access', _22 => _22[field.name], 'optionalAccess', _23 => _23.message]) })
|
|
569
708
|
])
|
|
570
709
|
);
|
|
571
710
|
const renderDeclaredField = (field) => renderField(field, {
|
|
@@ -626,7 +765,7 @@ function BookingForm({
|
|
|
626
765
|
// box doesn't shove the submit button down the card. With no error the
|
|
627
766
|
// wrapper is `display:contents` and the panel below is the flex item,
|
|
628
767
|
// exactly as it was.
|
|
629
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQVSVRG7Icjs.FieldWrapper, { error: _optionalChain([errors, 'access',
|
|
768
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQVSVRG7Icjs.FieldWrapper, { error: _optionalChain([errors, 'access', _24 => _24.legalConsentResponses, 'optionalAccess', _25 => _25.message]), children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-[var(--spacing-system-xs)]", children: [
|
|
630
769
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary text-h6", children: legalConsent.processingConsentText }),
|
|
631
770
|
legalConsent.communicationConsentText && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary text-h6", children: legalConsent.communicationConsentText }),
|
|
632
771
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
@@ -645,7 +784,7 @@ function BookingForm({
|
|
|
645
784
|
_chunk6FD7ZEBYcjs.CheckboxBlock,
|
|
646
785
|
{
|
|
647
786
|
id: `ms-consent-${box.communicationTypeId}`,
|
|
648
|
-
checked: _nullishCoalesce(_optionalChain([current, 'optionalAccess',
|
|
787
|
+
checked: _nullishCoalesce(_optionalChain([current, 'optionalAccess', _26 => _26.consented]), () => ( false)),
|
|
649
788
|
onCheckedChange: (v) => rhf.onChange(
|
|
650
789
|
responses.map(
|
|
651
790
|
(r) => r.communicationTypeId === box.communicationTypeId ? { ...r, consented: v } : r
|
|
@@ -740,7 +879,7 @@ function zoneLabel(tz) {
|
|
|
740
879
|
timeZone: tz,
|
|
741
880
|
timeZoneName: "shortOffset"
|
|
742
881
|
}).formatToParts(/* @__PURE__ */ new Date());
|
|
743
|
-
const offset = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
882
|
+
const offset = _nullishCoalesce(_optionalChain([parts, 'access', _27 => _27.find, 'call', _28 => _28((p) => p.type === "timeZoneName"), 'optionalAccess', _29 => _29.value]), () => ( ""));
|
|
744
883
|
return offset ? `${tz.replace(/_/g, " ")} (${offset})` : tz.replace(/_/g, " ");
|
|
745
884
|
} catch (e4) {
|
|
746
885
|
return tz.replace(/_/g, " ");
|
|
@@ -867,7 +1006,7 @@ function SchedulerContextPanel({
|
|
|
867
1006
|
value: timezone,
|
|
868
1007
|
disabled,
|
|
869
1008
|
onChange: (tz) => {
|
|
870
|
-
if (tz) _optionalChain([onTimezoneChange, 'optionalCall',
|
|
1009
|
+
if (tz) _optionalChain([onTimezoneChange, 'optionalCall', _30 => _30(tz)]);
|
|
871
1010
|
},
|
|
872
1011
|
options: zoneOptions,
|
|
873
1012
|
placeholder: "Search timezone\u2026",
|
|
@@ -951,7 +1090,7 @@ function DayCalendar({ monthOffset, onMonthOffsetChange, selectedDay, onSelectDa
|
|
|
951
1090
|
const startMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
952
1091
|
const endMonth = new Date(now.getFullYear(), now.getMonth() + _chunk6FD7ZEBYcjs.MAX_MONTH_OFFSET + 1, 0);
|
|
953
1092
|
const visibleMonth = new Date(now.getFullYear(), now.getMonth() + monthOffset, 1);
|
|
954
|
-
const dayHasNoSlots = _react.useCallback.call(void 0, (day) => !_optionalChain([slotsByDay, 'optionalAccess',
|
|
1093
|
+
const dayHasNoSlots = _react.useCallback.call(void 0, (day) => !_optionalChain([slotsByDay, 'optionalAccess', _31 => _31.has, 'call', _32 => _32(calendarDayKey(day))]), [slotsByDay]);
|
|
955
1094
|
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,
|
|
956
1095
|
_chunk6FD7ZEBYcjs.DatePickerCalendar,
|
|
957
1096
|
{
|
|
@@ -969,7 +1108,7 @@ function DayCalendar({ monthOffset, onMonthOffsetChange, selectedDay, onSelectDa
|
|
|
969
1108
|
const day = value;
|
|
970
1109
|
if (!day) return;
|
|
971
1110
|
const key = calendarDayKey(day);
|
|
972
|
-
if (_optionalChain([slotsByDay, 'optionalAccess',
|
|
1111
|
+
if (_optionalChain([slotsByDay, 'optionalAccess', _33 => _33.has, 'call', _34 => _34(key)])) onSelectDay(key);
|
|
973
1112
|
},
|
|
974
1113
|
disabledDays: slotsByDay === null ? DISABLE_EVERY_DAY : dayHasNoSlots
|
|
975
1114
|
}
|
|
@@ -1193,7 +1332,7 @@ function MeetingSchedulerDirectory({
|
|
|
1193
1332
|
};
|
|
1194
1333
|
}, [initialData, includeAll, apiBaseUrl]);
|
|
1195
1334
|
const rows = _react.useMemo.call(void 0, () => {
|
|
1196
|
-
const purposes = _nullishCoalesce(_optionalChain([data, 'optionalAccess',
|
|
1335
|
+
const purposes = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _35 => _35.purposes]), () => ( []));
|
|
1197
1336
|
return purposes.flatMap((p) => p.links.map((link) => ({ link, audienceLabel: p.label })));
|
|
1198
1337
|
}, [data]);
|
|
1199
1338
|
const totalPages = _chunkVTYP25OWcjs.pageCount.call(void 0, rows.length, pageSize);
|
|
@@ -1293,7 +1432,7 @@ function SchedulerDegradedCard({
|
|
|
1293
1432
|
] });
|
|
1294
1433
|
}
|
|
1295
1434
|
function isNativelyBookable(availability) {
|
|
1296
|
-
if (
|
|
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;
|
|
@@ -1349,7 +1488,7 @@ function HubSpotMeetingScheduler({
|
|
|
1349
1488
|
onStageChangeRef.current = onStageChange;
|
|
1350
1489
|
});
|
|
1351
1490
|
_react.useEffect.call(void 0, () => {
|
|
1352
|
-
_optionalChain([onStageChangeRef, 'access',
|
|
1491
|
+
_optionalChain([onStageChangeRef, 'access', _36 => _36.current, 'optionalCall', _37 => _37(stage)]);
|
|
1353
1492
|
}, [stage]);
|
|
1354
1493
|
const [stash, setStash] = _react.useState.call(void 0, null);
|
|
1355
1494
|
const inFlightRef = _react.useRef.call(void 0, false);
|
|
@@ -1380,8 +1519,8 @@ function HubSpotMeetingScheduler({
|
|
|
1380
1519
|
_react.useEffect.call(void 0, () => {
|
|
1381
1520
|
autoAdvanceCount.current = 0;
|
|
1382
1521
|
}, [meetingId]);
|
|
1383
|
-
const durations = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([availability, 'optionalAccess',
|
|
1384
|
-
const shownHosts = _nullishCoalesce(_nullishCoalesce(hosts, () => ( _optionalChain([availability, 'optionalAccess',
|
|
1522
|
+
const durations = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([availability, 'optionalAccess', _38 => _38.durationsMs]), () => ( [])), [_optionalChain([availability, 'optionalAccess', _39 => _39.durationsMs])]);
|
|
1523
|
+
const shownHosts = _nullishCoalesce(_nullishCoalesce(hosts, () => ( _optionalChain([availability, 'optionalAccess', _40 => _40.hosts]))), () => ( []));
|
|
1385
1524
|
const durationMs = _nullishCoalesce(_nullishCoalesce(pickedDurationMs, () => ( durations[0])), () => ( null));
|
|
1386
1525
|
const slots = _react.useMemo.call(void 0, () => {
|
|
1387
1526
|
if (!availability || durationMs == null) return [];
|
|
@@ -1440,7 +1579,7 @@ function HubSpotMeetingScheduler({
|
|
|
1440
1579
|
if (result.ok && result.confirmation) {
|
|
1441
1580
|
setConfirmation(result.confirmation);
|
|
1442
1581
|
setStep("confirmed");
|
|
1443
|
-
_optionalChain([onBooked, 'optionalCall',
|
|
1582
|
+
_optionalChain([onBooked, 'optionalCall', _41 => _41(result.confirmation)]);
|
|
1444
1583
|
return;
|
|
1445
1584
|
}
|
|
1446
1585
|
const code = _nullishCoalesce(result.code, () => ( "TEMPORARILY_UNAVAILABLE"));
|
|
@@ -1488,8 +1627,8 @@ function HubSpotMeetingScheduler({
|
|
|
1488
1627
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: stepPanelClass, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1489
1628
|
BookingFormSkeleton,
|
|
1490
1629
|
{
|
|
1491
|
-
fieldRows: _optionalChain([detailsFormProps, 'optionalAccess',
|
|
1492
|
-
consent: Boolean(_optionalChain([detailsFormProps, 'optionalAccess',
|
|
1630
|
+
fieldRows: _optionalChain([detailsFormProps, 'optionalAccess', _42 => _42.fieldRows]),
|
|
1631
|
+
consent: Boolean(_optionalChain([detailsFormProps, 'optionalAccess', _43 => _43.consent])),
|
|
1493
1632
|
footerNote: preset.footerNote
|
|
1494
1633
|
}
|
|
1495
1634
|
) })
|
|
@@ -1550,7 +1689,7 @@ function HubSpotMeetingScheduler({
|
|
|
1550
1689
|
deferSlot: detailsFirst,
|
|
1551
1690
|
submitLabel: preset.submitLabel,
|
|
1552
1691
|
footerNote: preset.footerNote,
|
|
1553
|
-
initialValues: detailsFirst ? _optionalChain([stash, 'optionalAccess',
|
|
1692
|
+
initialValues: detailsFirst ? _optionalChain([stash, 'optionalAccess', _44 => _44.payload]) : void 0,
|
|
1554
1693
|
isSubmitting,
|
|
1555
1694
|
onSubmit: detailsFirst ? stashDetails : handleSubmit,
|
|
1556
1695
|
honeypotInputProps,
|