@flamingo-stack/openframe-frontend-core 0.0.596-2034.5669.1 → 0.0.596-2034.5671.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,7 +1,7 @@
1
1
  import type { ComponentType } from 'react';
2
2
  import { type BookingConfirmation, type MeetingAvailability, type MeetingBookingErrorCode, type MeetingHost } from '../../schemas/meeting-booking-schema';
3
3
  import { type BookingFormProps } from './booking-form';
4
- export { BookingForm, BookingFormSkeleton, type BookingFormProps, type BookingFieldRow, type BookingFieldSlot, } from './booking-form';
4
+ export { BookingForm, BookingFormSkeleton, type BookingFormProps, type BookingFieldRow, type BookingFieldSlot, type BookingFormConsent, } from './booking-form';
5
5
  export interface HubSpotMeetingSchedulerProps {
6
6
  /** Directory id of the meeting link (from the host's `/api/meetings` payload). */
7
7
  meetingId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/index.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAK3C,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EACjB,MAAM,sCAAsC,CAAC;AAI9C,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAKzF,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AAwBxB,MAAM,WAAW,4BAA4B;IAC3C,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mEAAmE;IACnE,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,sFAAsF;IACtF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,YAAY,GAAG,eAAe,CAAC;IACtC;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;CAC/C;AA4CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iCAAiC,qBAAqB,CAAC;AAqEpE,wBAAgB,uBAAuB,CAAC,EACtC,SAAS,EACT,UAAe,EACf,mBAAmB,EACnB,KAAK,EACL,WAAW,EACX,KAAK,EACL,eAAe,EACf,WAAW,EACX,MAAM,EACN,QAAQ,EACR,SAAS,EACT,IAAmB,EACnB,WAAW,EAAE,WAAyB,GACvC,EAAE,4BAA4B,+BAigB9B;AAED,OAAO,EACL,yBAAyB,EACzB,oCAAoC,EACpC,KAAK,8BAA8B,GACpC,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,WAAW,EAAE,CAAC;AAC/F,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/meeting-scheduler/index.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAK3C,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EACjB,MAAM,sCAAsC,CAAC;AAI9C,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAKzF,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAC;AAwBxB,MAAM,WAAW,4BAA4B;IAC3C,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mEAAmE;IACnE,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,sFAAsF;IACtF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,YAAY,GAAG,eAAe,CAAC;IACtC;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;CAC/C;AA4CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iCAAiC,qBAAqB,CAAC;AAqEpE,wBAAgB,uBAAuB,CAAC,EACtC,SAAS,EACT,UAAe,EACf,mBAAmB,EACnB,KAAK,EACL,WAAW,EACX,KAAK,EACL,eAAe,EACf,WAAW,EACX,MAAM,EACN,QAAQ,EACR,SAAS,EACT,IAAmB,EACnB,WAAW,EAAE,WAAyB,GACvC,EAAE,4BAA4B,+BA+f9B;AAED,OAAO,EACL,yBAAyB,EACzB,oCAAoC,EACpC,KAAK,8BAA8B,GACpC,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,WAAW,EAAE,CAAC;AAC/F,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC"}
@@ -77,7 +77,7 @@ import "../../chunk-3DTTSBDF.js";
77
77
  import "../../chunk-DCHYNTHI.js";
78
78
 
79
79
  // src/components/meeting-scheduler/index.tsx
80
- import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo5, useRef as useRef2, useState as useState3 } from "react";
80
+ import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo5, useRef as useRef2, useState as useState4 } from "react";
81
81
 
82
82
  // src/hooks/use-meeting-booking.ts
83
83
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
@@ -276,7 +276,7 @@ function useMeetingBooking(options) {
276
276
 
277
277
  // src/components/meeting-scheduler/booking-form.tsx
278
278
  import { zodResolver } from "@hookform/resolvers/zod";
279
- import { Fragment, useEffect, useMemo } from "react";
279
+ import { Fragment, useEffect, useMemo, useState as useState2 } from "react";
280
280
  import { useForm, Controller } from "react-hook-form";
281
281
  import { Fragment as Fragment2, jsx, jsxs } from "react/jsx-runtime";
282
282
  var SPAN_CLASS = {
@@ -297,6 +297,7 @@ function BookingForm({
297
297
  submitLabel,
298
298
  footerNote,
299
299
  fieldRows,
300
+ consent,
300
301
  isSubmitting,
301
302
  onSubmit,
302
303
  honeypotInputProps,
@@ -340,6 +341,9 @@ function BookingForm({
340
341
  }
341
342
  });
342
343
  const priorConsents = initialValues?.legalConsentResponses;
344
+ const [consented, setConsented] = useState2(initialValues?.hostConsent === true);
345
+ const [consentError, setConsentError] = useState2(null);
346
+ const consentMissing = Boolean(consent) && !consented;
343
347
  useEffect(() => {
344
348
  setValue(
345
349
  "legalConsentResponses",
@@ -350,13 +354,18 @@ function BookingForm({
350
354
  { shouldDirty: false }
351
355
  );
352
356
  }, [consentDefaults, priorConsents, setValue]);
353
- const submit = handleSubmit(async (data) => {
357
+ const submitValid = handleSubmit(async (data) => {
358
+ if (consentMissing) return;
354
359
  if (deferSlot) {
355
- await onSubmit({ ...data, meetingId });
360
+ await onSubmit({ ...data, meetingId, hostConsent: consented });
356
361
  return;
357
362
  }
358
- await onSubmit({ ...data, meetingId, startTimeMs, durationMs, timezone, ...getSignals() });
363
+ await onSubmit({ ...data, meetingId, hostConsent: consented, startTimeMs, durationMs, timezone, ...getSignals() });
359
364
  });
365
+ const submit = (event) => {
366
+ if (consentMissing) setConsentError(consent?.errorMessage ?? "Please agree to continue.");
367
+ return submitValid(event);
368
+ };
360
369
  const fieldError = (name) => {
361
370
  const err = errors.formFields?.[name];
362
371
  return err?.message;
@@ -508,6 +517,21 @@ function BookingForm({
508
517
  ] }),
509
518
  supportedFields.map((field) => /* @__PURE__ */ jsx(Fragment, { children: renderDeclaredField(field) }, field.name))
510
519
  ] }),
520
+ consent && /* @__PURE__ */ jsx(
521
+ CheckboxBlock,
522
+ {
523
+ id: "ms-host-consent",
524
+ checked: consented,
525
+ onCheckedChange: (v) => {
526
+ setConsented(v);
527
+ if (v) setConsentError(null);
528
+ },
529
+ disabled: isSubmitting,
530
+ error: consentError ?? void 0,
531
+ label: consent.label,
532
+ description: consent.description
533
+ }
534
+ ),
511
535
  legalConsent && // Same out-of-flow message as the fields above, so a missed consent
512
536
  // box doesn't shove the submit button down the card. With no error the
513
537
  // wrapper is `display:contents` and the panel below is the flex item,
@@ -653,7 +677,6 @@ function SchedulerContextPanel({
653
677
  onBack,
654
678
  backLabel = "Back",
655
679
  locked = false,
656
- fixedDuration = false,
657
680
  showTimezone = true,
658
681
  className
659
682
  }) {
@@ -697,9 +720,8 @@ function SchedulerContextPanel({
697
720
  " hosts on this calendar"
698
721
  ] })
699
722
  ] }),
700
- locked || fixedDuration || durationsMs.length <= 1 ? (
701
- // Post-selection, a fixed-length flow, or a link that offers one
702
- // length: a static line,
723
+ locked || durationsMs.length <= 1 ? (
724
+ // Post-selection, or a link that offers one length: a static line,
703
725
  // which is what sits beside the host on the header-strip layouts.
704
726
  selectedDurationMs != null && /* @__PURE__ */ jsxs3("p", { className: "shrink-0 text-ods-text-secondary text-h6", children: [
705
727
  formatDurationCompact(selectedDurationMs / 1e3),
@@ -709,7 +731,7 @@ function SchedulerContextPanel({
709
731
  ] }),
710
732
  title && /* @__PURE__ */ jsx3("p", { className: "text-ods-text-primary text-h3", children: title }),
711
733
  description && /* @__PURE__ */ jsx3("p", { className: "text-ods-text-secondary text-h6", children: description }),
712
- !locked && !fixedDuration && durationsMs.length > 1 && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-[var(--spacing-system-xxs)]", children: [
734
+ !locked && durationsMs.length > 1 && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-[var(--spacing-system-xxs)]", children: [
713
735
  /* @__PURE__ */ jsx3("p", { className: FIELD_LABEL_CLASS, children: "Duration" }),
714
736
  /* @__PURE__ */ jsx3("div", { className: "flex flex-wrap gap-[var(--spacing-system-xs)]", children: durationsMs.map((ms) => /* @__PURE__ */ jsx3(
715
737
  Button,
@@ -968,7 +990,7 @@ function SlotPicker({
968
990
 
969
991
  // src/components/meeting-scheduler/directory.tsx
970
992
  import { ChevronRight as ChevronRight2 } from "lucide-react";
971
- import { useEffect as useEffect2, useMemo as useMemo4, useState as useState2 } from "react";
993
+ import { useEffect as useEffect2, useMemo as useMemo4, useState as useState3 } from "react";
972
994
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
973
995
  function useNextAvailableLabel(ms) {
974
996
  const hydrated = useIsHydrated();
@@ -1045,10 +1067,10 @@ function MeetingSchedulerDirectory({
1045
1067
  contactHref,
1046
1068
  className
1047
1069
  }) {
1048
- const [data, setData] = useState2(initialData);
1049
- const [isLoading, setIsLoading] = useState2(initialData === null);
1050
- const [error, setError] = useState2(null);
1051
- const [page, setPage] = useState2(1);
1070
+ const [data, setData] = useState3(initialData);
1071
+ const [isLoading, setIsLoading] = useState3(initialData === null);
1072
+ const [error, setError] = useState3(null);
1073
+ const [page, setPage] = useState3(1);
1052
1074
  useEffect2(() => {
1053
1075
  if (initialData !== null) return void 0;
1054
1076
  const controller = new AbortController();
@@ -1188,7 +1210,7 @@ function HubSpotMeetingScheduler({
1188
1210
  } = useMeetingBooking({ meetingId, apiBaseUrl, initialAvailability });
1189
1211
  const detailsFirst = flow === "details-first";
1190
1212
  const hydrated = useIsHydrated();
1191
- const [pickedTimezone, setTimezone] = useState3(null);
1213
+ const [pickedTimezone, setTimezone] = useState4(null);
1192
1214
  const resolvedLocalTimezone = useMemo5(() => {
1193
1215
  if (!hydrated) return null;
1194
1216
  try {
@@ -1198,18 +1220,18 @@ function HubSpotMeetingScheduler({
1198
1220
  }
1199
1221
  }, [hydrated]);
1200
1222
  const timezone = pickedTimezone ?? displayTimezone ?? resolvedLocalTimezone;
1201
- const [step, setStep] = useState3(detailsFirst ? "details" : "slot");
1202
- const [stash, setStash] = useState3(null);
1223
+ const [step, setStep] = useState4(detailsFirst ? "details" : "slot");
1224
+ const [stash, setStash] = useState4(null);
1203
1225
  const formOnly = detailsFirst && step === "details";
1204
- const [pickedDurationMs, setDurationMs] = useState3(null);
1205
- const [pickedDay, setSelectedDay] = useState3(null);
1206
- const [selectedSlot, setSelectedSlot] = useState3(null);
1207
- const [confirmation, setConfirmation] = useState3(null);
1208
- const [bookingError, setBookingError] = useState3(null);
1226
+ const [pickedDurationMs, setDurationMs] = useState4(null);
1227
+ const [pickedDay, setSelectedDay] = useState4(null);
1228
+ const [selectedSlot, setSelectedSlot] = useState4(null);
1229
+ const [confirmation, setConfirmation] = useState4(null);
1230
+ const [bookingError, setBookingError] = useState4(null);
1209
1231
  const { honeypotInputProps, getSignals, resetSignals } = useHumanitySignals();
1210
1232
  const { toast } = useToast();
1211
1233
  const autoAdvanceCount = useRef2(0);
1212
- const [machineFor, setMachineFor] = useState3(meetingId);
1234
+ const [machineFor, setMachineFor] = useState4(meetingId);
1213
1235
  if (machineFor !== meetingId) {
1214
1236
  setMachineFor(meetingId);
1215
1237
  setStep(detailsFirst ? "details" : "slot");
@@ -1343,7 +1365,6 @@ function HubSpotMeetingScheduler({
1343
1365
  onBack: detailsFirst ? step === "slot" ? backToDetails : onBack : step === "details" ? backToSlot : onBack,
1344
1366
  locked: detailsFirst ? step === "confirmed" || isSubmitting : step !== "slot",
1345
1367
  showTimezone: step !== "confirmed",
1346
- fixedDuration: detailsFirst,
1347
1368
  className: CONTEXT_PANEL_CLASS
1348
1369
  }
1349
1370
  ),