@flamingo-stack/openframe-frontend-core 0.0.573 → 0.0.574-snapshot.20260827223923

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.
Files changed (108) hide show
  1. package/dist/{chunk-TIX2SHZX.js → chunk-2EPUD2VR.js} +2 -2
  2. package/dist/{chunk-2EB5273T.js → chunk-2IK6SB6F.js} +2 -2
  3. package/dist/{chunk-OUMRHNZW.cjs → chunk-3IUQLB47.cjs} +3 -3
  4. package/dist/{chunk-OUMRHNZW.cjs.map → chunk-3IUQLB47.cjs.map} +1 -1
  5. package/dist/{chunk-BWHLWS32.cjs → chunk-3U2P63NQ.cjs} +10 -10
  6. package/dist/{chunk-BWHLWS32.cjs.map → chunk-3U2P63NQ.cjs.map} +1 -1
  7. package/dist/{chunk-EC44ZXBH.js → chunk-5QDGP3RI.js} +2 -2
  8. package/dist/{chunk-YS64Y5MP.cjs → chunk-7G23ANVM.cjs} +49 -49
  9. package/dist/{chunk-YS64Y5MP.cjs.map → chunk-7G23ANVM.cjs.map} +1 -1
  10. package/dist/{chunk-R3I2XI33.js → chunk-BGE7CKXC.js} +4 -4
  11. package/dist/{chunk-6SMQCAPO.cjs → chunk-BGZCZ2JS.cjs} +3 -3
  12. package/dist/{chunk-6SMQCAPO.cjs.map → chunk-BGZCZ2JS.cjs.map} +1 -1
  13. package/dist/{chunk-B7S7ETML.cjs → chunk-BKXL7OYT.cjs} +3 -3
  14. package/dist/{chunk-B7S7ETML.cjs.map → chunk-BKXL7OYT.cjs.map} +1 -1
  15. package/dist/{chunk-4WCTY326.js → chunk-BTZF3JRS.js} +2 -2
  16. package/dist/{chunk-J5OC2KYU.js → chunk-DTSRMQIY.js} +5 -5
  17. package/dist/{chunk-4TGUWWMY.cjs → chunk-GFSJXRX7.cjs} +16 -16
  18. package/dist/{chunk-4TGUWWMY.cjs.map → chunk-GFSJXRX7.cjs.map} +1 -1
  19. package/dist/{chunk-P625NSEA.cjs → chunk-IRJQH7RJ.cjs} +17 -17
  20. package/dist/{chunk-P625NSEA.cjs.map → chunk-IRJQH7RJ.cjs.map} +1 -1
  21. package/dist/{chunk-DSU7LQMU.js → chunk-ISULYCGY.js} +2 -2
  22. package/dist/{chunk-SB67TZQU.js → chunk-IWISKP3F.js} +2 -2
  23. package/dist/{chunk-JLIXPN37.cjs → chunk-K3XONUML.cjs} +4 -4
  24. package/dist/{chunk-JLIXPN37.cjs.map → chunk-K3XONUML.cjs.map} +1 -1
  25. package/dist/{chunk-IBZBGRO2.js → chunk-KG7D35RU.js} +5 -5
  26. package/dist/{chunk-3ENV3IEP.js → chunk-KSKCQ3ZN.js} +2 -2
  27. package/dist/{chunk-NGXP4EAQ.js → chunk-OE7NV7H3.js} +2 -2
  28. package/dist/{chunk-66LZDE7U.js → chunk-PBS4F534.js} +3 -2
  29. package/dist/chunk-PBS4F534.js.map +1 -0
  30. package/dist/{chunk-AQBWGEL3.cjs → chunk-PUL6X6HY.cjs} +32 -32
  31. package/dist/{chunk-AQBWGEL3.cjs.map → chunk-PUL6X6HY.cjs.map} +1 -1
  32. package/dist/{chunk-YK7M7RBF.cjs → chunk-QDOBY3TP.cjs} +3 -2
  33. package/dist/chunk-QDOBY3TP.cjs.map +1 -0
  34. package/dist/{chunk-OYWAPTEF.cjs → chunk-QF5B6V4L.cjs} +17 -17
  35. package/dist/{chunk-OYWAPTEF.cjs.map → chunk-QF5B6V4L.cjs.map} +1 -1
  36. package/dist/{chunk-NCCWS6YE.cjs → chunk-QTVW5XBL.cjs} +4 -4
  37. package/dist/{chunk-NCCWS6YE.cjs.map → chunk-QTVW5XBL.cjs.map} +1 -1
  38. package/dist/{chunk-PDQ7F5AB.cjs → chunk-RXJZXMDZ.cjs} +13 -13
  39. package/dist/{chunk-PDQ7F5AB.cjs.map → chunk-RXJZXMDZ.cjs.map} +1 -1
  40. package/dist/{chunk-EIK6KDAE.cjs → chunk-SVUZUFT4.cjs} +34 -34
  41. package/dist/{chunk-EIK6KDAE.cjs.map → chunk-SVUZUFT4.cjs.map} +1 -1
  42. package/dist/{chunk-GSSJFXIW.cjs → chunk-UILNZL6J.cjs} +3 -3
  43. package/dist/{chunk-GSSJFXIW.cjs.map → chunk-UILNZL6J.cjs.map} +1 -1
  44. package/dist/{chunk-4IAZOAS7.js → chunk-UPEIX7VG.js} +4 -4
  45. package/dist/{chunk-SY7M6VAJ.js → chunk-WAWMZSCP.js} +3 -3
  46. package/dist/{chunk-JTDYVW2B.js → chunk-WVKRSC65.js} +2 -2
  47. package/dist/components/case-studies/index.cjs +8 -8
  48. package/dist/components/case-studies/index.js +2 -2
  49. package/dist/components/contact/index.cjs +3 -3
  50. package/dist/components/contact/index.js +2 -2
  51. package/dist/components/docs/index.cjs +6 -6
  52. package/dist/components/docs/index.js +5 -5
  53. package/dist/components/embeds/index.cjs +3 -3
  54. package/dist/components/embeds/index.js +2 -2
  55. package/dist/components/faq/index.cjs +3 -3
  56. package/dist/components/faq/index.js +2 -2
  57. package/dist/components/features/index.cjs +2 -2
  58. package/dist/components/features/index.js +1 -1
  59. package/dist/components/help-center-pages/index.cjs +22 -22
  60. package/dist/components/help-center-pages/index.js +13 -13
  61. package/dist/components/index.cjs +114 -114
  62. package/dist/components/index.js +12 -12
  63. package/dist/components/meeting-scheduler/index.cjs +130 -111
  64. package/dist/components/meeting-scheduler/index.cjs.map +1 -1
  65. package/dist/components/meeting-scheduler/index.d.ts.map +1 -1
  66. package/dist/components/meeting-scheduler/index.js +113 -94
  67. package/dist/components/meeting-scheduler/index.js.map +1 -1
  68. package/dist/components/navigation/index.cjs +5 -5
  69. package/dist/components/navigation/index.js +4 -4
  70. package/dist/components/onboarding-guides/index.cjs +5 -5
  71. package/dist/components/onboarding-guides/index.js +4 -4
  72. package/dist/components/tickets/index.cjs +6 -6
  73. package/dist/components/tickets/index.js +5 -5
  74. package/dist/components/ui/alert.d.ts +1 -1
  75. package/dist/components/ui/alert.d.ts.map +1 -1
  76. package/dist/components/ui/index.cjs +2 -2
  77. package/dist/components/ui/index.js +1 -1
  78. package/dist/hooks/use-meeting-booking.d.ts +1 -1
  79. package/dist/hooks/use-meeting-booking.d.ts.map +1 -1
  80. package/dist/index.cjs +6 -6
  81. package/dist/index.js +5 -5
  82. package/dist/schemas/meeting-booking-schema.cjs +9 -0
  83. package/dist/schemas/meeting-booking-schema.cjs.map +1 -1
  84. package/dist/schemas/meeting-booking-schema.d.ts +15 -2
  85. package/dist/schemas/meeting-booking-schema.d.ts.map +1 -1
  86. package/dist/schemas/meeting-booking-schema.js +9 -1
  87. package/dist/schemas/meeting-booking-schema.js.map +1 -1
  88. package/package.json +1 -1
  89. package/src/components/meeting-scheduler/index.tsx +34 -16
  90. package/src/components/ui/alert.tsx +1 -0
  91. package/src/hooks/use-meeting-booking.ts +6 -13
  92. package/src/schemas/meeting-booking-schema.ts +23 -3
  93. package/dist/chunk-66LZDE7U.js.map +0 -1
  94. package/dist/chunk-YK7M7RBF.cjs.map +0 -1
  95. /package/dist/{chunk-TIX2SHZX.js.map → chunk-2EPUD2VR.js.map} +0 -0
  96. /package/dist/{chunk-2EB5273T.js.map → chunk-2IK6SB6F.js.map} +0 -0
  97. /package/dist/{chunk-EC44ZXBH.js.map → chunk-5QDGP3RI.js.map} +0 -0
  98. /package/dist/{chunk-R3I2XI33.js.map → chunk-BGE7CKXC.js.map} +0 -0
  99. /package/dist/{chunk-4WCTY326.js.map → chunk-BTZF3JRS.js.map} +0 -0
  100. /package/dist/{chunk-J5OC2KYU.js.map → chunk-DTSRMQIY.js.map} +0 -0
  101. /package/dist/{chunk-DSU7LQMU.js.map → chunk-ISULYCGY.js.map} +0 -0
  102. /package/dist/{chunk-SB67TZQU.js.map → chunk-IWISKP3F.js.map} +0 -0
  103. /package/dist/{chunk-IBZBGRO2.js.map → chunk-KG7D35RU.js.map} +0 -0
  104. /package/dist/{chunk-3ENV3IEP.js.map → chunk-KSKCQ3ZN.js.map} +0 -0
  105. /package/dist/{chunk-NGXP4EAQ.js.map → chunk-OE7NV7H3.js.map} +0 -0
  106. /package/dist/{chunk-4IAZOAS7.js.map → chunk-UPEIX7VG.js.map} +0 -0
  107. /package/dist/{chunk-SY7M6VAJ.js.map → chunk-WAWMZSCP.js.map} +0 -0
  108. /package/dist/{chunk-JTDYVW2B.js.map → chunk-WVKRSC65.js.map} +0 -0
@@ -15,7 +15,7 @@ import {
15
15
  SoftwareInfo,
16
16
  SoftwareSourceBadge,
17
17
  ToolBadge
18
- } from "../chunk-EC44ZXBH.js";
18
+ } from "../chunk-5QDGP3RI.js";
19
19
  import {
20
20
  AppHeader,
21
21
  AppLayout,
@@ -34,7 +34,7 @@ import {
34
34
  SlidingSidebar,
35
35
  TicketAlertsButton,
36
36
  TopNavigation
37
- } from "../chunk-SY7M6VAJ.js";
37
+ } from "../chunk-WAWMZSCP.js";
38
38
  import {
39
39
  DeliveryLists,
40
40
  DeliveryTable,
@@ -48,7 +48,7 @@ import {
48
48
  RoadmapView,
49
49
  useLegalDocs,
50
50
  useRoadmapVoting
51
- } from "../chunk-R3I2XI33.js";
51
+ } from "../chunk-BGE7CKXC.js";
52
52
  import {
53
53
  AnnouncementBarSkeleton,
54
54
  ArticleLayoutSkeleton,
@@ -81,12 +81,12 @@ import {
81
81
  useDocNavigation,
82
82
  useDocumentTree,
83
83
  useScrollSpy
84
- } from "../chunk-IBZBGRO2.js";
84
+ } from "../chunk-KG7D35RU.js";
85
85
  import {
86
86
  FileDownloadCard,
87
87
  GoogleSheetsViewer,
88
88
  PdfViewer
89
- } from "../chunk-DSU7LQMU.js";
89
+ } from "../chunk-ISULYCGY.js";
90
90
  import {
91
91
  PersistentPagination,
92
92
  PersistentPaginationWrapper,
@@ -96,13 +96,13 @@ import {
96
96
  FaqAccordion,
97
97
  FaqDocumentPage,
98
98
  FaqSection
99
- } from "../chunk-NGXP4EAQ.js";
99
+ } from "../chunk-OE7NV7H3.js";
100
100
  import {
101
101
  MobileNavigationDropdown,
102
102
  MultiLevelNavigation,
103
103
  StickySectionNav,
104
104
  useSectionNavigation
105
- } from "../chunk-3ENV3IEP.js";
105
+ } from "../chunk-KSKCQ3ZN.js";
106
106
  import {
107
107
  DeliveryRow,
108
108
  DevCardRowContent,
@@ -110,16 +110,16 @@ import {
110
110
  DevCardRowSkeletonList,
111
111
  DevSectionPage,
112
112
  DevSectionView
113
- } from "../chunk-JTDYVW2B.js";
113
+ } from "../chunk-WVKRSC65.js";
114
114
  import {
115
115
  EmptyState,
116
116
  UnifiedPagination
117
117
  } from "../chunk-QQ5ZVCD4.js";
118
- import "../chunk-SB67TZQU.js";
118
+ import "../chunk-IWISKP3F.js";
119
119
  import {
120
120
  ArticleAuthorByline,
121
121
  DetailPageSkeleton
122
- } from "../chunk-TIX2SHZX.js";
122
+ } from "../chunk-2EPUD2VR.js";
123
123
  import {
124
124
  DocSearchBar,
125
125
  DocSearchResultRow,
@@ -127,7 +127,7 @@ import {
127
127
  mapDocSearchResults,
128
128
  resolveSearchResultAction,
129
129
  useDocSearch
130
- } from "../chunk-4WCTY326.js";
130
+ } from "../chunk-BTZF3JRS.js";
131
131
  import {
132
132
  useSelfFetch
133
133
  } from "../chunk-UC5RXT3O.js";
@@ -576,7 +576,7 @@ import {
576
576
  useTimeTracker,
577
577
  useTrackerClock,
578
578
  useWalkthroughVideo
579
- } from "../chunk-66LZDE7U.js";
579
+ } from "../chunk-PBS4F534.js";
580
580
  import "../chunk-L2SLFCXP.js";
581
581
  import "../chunk-BJXDHKUX.js";
582
582
  import {
@@ -20,7 +20,9 @@ var _chunkVIAZWBZ2cjs = require('../../chunk-VIAZWBZ2.cjs');
20
20
 
21
21
 
22
22
 
23
- var _chunkYK7M7RBFcjs = require('../../chunk-YK7M7RBF.cjs');
23
+
24
+
25
+ var _chunkQDOBY3TPcjs = require('../../chunk-QDOBY3TP.cjs');
24
26
  require('../../chunk-GQWM3ECA.cjs');
25
27
  require('../../chunk-TON3YCCW.cjs');
26
28
 
@@ -77,102 +79,17 @@ var _react = require('react');
77
79
  // src/hooks/use-meeting-booking.ts
78
80
  var _reactquery = require('@tanstack/react-query');
79
81
 
80
- var KNOWN_CODES = [
82
+
83
+ // src/schemas/meeting-booking-schema.ts
84
+ var _zod = require('zod');
85
+ var MEETING_BOOKING_ERROR_CODES = [
81
86
  "SLOT_TAKEN",
82
87
  "VALIDATION",
88
+ "INVALID_EMAIL",
83
89
  "LINK_GONE",
84
90
  "TEMPORARILY_UNAVAILABLE",
85
91
  "MEETING_UNAVAILABLE"
86
92
  ];
87
- var AVAILABILITY_STALE_MS = 0;
88
- function meetingAvailabilityKey(apiBaseUrl, meetingId, monthOffset) {
89
- return ["meeting-availability", apiBaseUrl, meetingId, monthOffset];
90
- }
91
- function useMeetingBooking(options) {
92
- const { meetingId, apiBaseUrl = "", initialAvailability } = options;
93
- const queryClient = _reactquery.useQueryClient.call(void 0, );
94
- const seededOffset = _optionalChain([initialAvailability, 'optionalAccess', _2 => _2.meetingId]) === meetingId ? initialAvailability.monthOffset : void 0;
95
- const [monthOffset, setMonthOffsetState] = _react.useState.call(void 0, _nullishCoalesce(seededOffset, () => ( 0)));
96
- const setMonthOffset = _react.useCallback.call(void 0, (offset) => {
97
- setMonthOffsetState(Math.max(0, Math.min(_chunkYK7M7RBFcjs.MAX_MONTH_OFFSET, offset)));
98
- }, []);
99
- const prevMeetingIdRef = _react.useRef.call(void 0, meetingId);
100
- _react.useLayoutEffect.call(void 0, () => {
101
- if (prevMeetingIdRef.current === meetingId) return;
102
- prevMeetingIdRef.current = meetingId;
103
- setMonthOffsetState(0);
104
- }, [meetingId]);
105
- const seed = _optionalChain([initialAvailability, 'optionalAccess', _3 => _3.meetingId]) === meetingId && initialAvailability.monthOffset === monthOffset ? initialAvailability : void 0;
106
- const availabilityQuery = _reactquery.useQuery.call(void 0, {
107
- queryKey: meetingAvailabilityKey(apiBaseUrl, meetingId, monthOffset),
108
- queryFn: async ({ signal }) => {
109
- const params = new URLSearchParams({ meeting: meetingId, monthOffset: String(monthOffset) });
110
- const res = await _chunkTRC37VRCcjs.contentFetch.call(void 0, `${apiBaseUrl}/api/meetings/availability?${params}`, { signal });
111
- if (!res.ok) throw new Error(`availability ${res.status}`);
112
- return await res.json();
113
- },
114
- staleTime: AVAILABILITY_STALE_MS,
115
- initialData: seed,
116
- // Stamped as infinitely old on purpose: the seed is first-paint
117
- // scaffolding for a 60-second-volatile resource, not truth, so it paints
118
- // immediately AND is refetched immediately.
119
- initialDataUpdatedAt: seed ? 0 : void 0
120
- });
121
- const refetchAvailability = _react.useCallback.call(void 0, async () => {
122
- await queryClient.invalidateQueries({ queryKey: meetingAvailabilityKey(apiBaseUrl, meetingId, monthOffset) }).catch(() => void 0);
123
- }, [queryClient, apiBaseUrl, meetingId, monthOffset]);
124
- const bookMutation = _reactquery.useMutation.call(void 0, {
125
- mutationFn: async (payload) => {
126
- try {
127
- const res = await _chunkTRC37VRCcjs.contentFetch.call(void 0, `${apiBaseUrl}/api/meetings/book`, {
128
- method: "POST",
129
- headers: { "Content-Type": "application/json" },
130
- body: JSON.stringify(payload)
131
- });
132
- const data = await res.json().catch(() => ({}));
133
- if (res.ok) return { ok: true, confirmation: data };
134
- const rawCode = typeof data.code === "string" ? data.code : "";
135
- const code = KNOWN_CODES.includes(rawCode) ? rawCode : "TEMPORARILY_UNAVAILABLE";
136
- return { ok: false, code, message: typeof data.error === "string" ? data.error : void 0 };
137
- } catch (e) {
138
- return { ok: false, code: "TEMPORARILY_UNAVAILABLE" };
139
- }
140
- },
141
- // A booking is not a read — never retried, at any layer.
142
- retry: false
143
- });
144
- const submittingRef = _react.useRef.call(void 0, null);
145
- const { mutateAsync } = bookMutation;
146
- const book = _react.useCallback.call(void 0,
147
- async (payload) => {
148
- if (submittingRef.current !== null) return { ok: false, code: "VALIDATION", message: "Already submitting" };
149
- const submitToken = {};
150
- submittingRef.current = submitToken;
151
- try {
152
- return await mutateAsync(payload);
153
- } finally {
154
- if (submittingRef.current === submitToken) submittingRef.current = null;
155
- }
156
- },
157
- [mutateAsync]
158
- );
159
- return {
160
- availability: _nullishCoalesce(availabilityQuery.data, () => ( null)),
161
- /** No availability for this month yet — the times column has nothing to show. */
162
- isLoadingAvailability: availabilityQuery.isPending,
163
- /** ANY request in flight, including a silent revalidation of cached data. */
164
- isFetchingAvailability: availabilityQuery.isFetching,
165
- availabilityError: availabilityQuery.error ? availabilityQuery.error.message : null,
166
- monthOffset,
167
- setMonthOffset,
168
- refetchAvailability,
169
- book,
170
- isSubmitting: bookMutation.isPending
171
- };
172
- }
173
-
174
- // src/schemas/meeting-booking-schema.ts
175
- var _zod = require('zod');
176
93
  var SUPPORTED_FORM_FIELD_TYPES = ["text", "textarea", "select", "radio", "checkbox"];
177
94
  function isSupportedFormField(field) {
178
95
  return SUPPORTED_FORM_FIELD_TYPES.includes(field.type);
@@ -183,14 +100,14 @@ function isValidIanaTimezone(tz) {
183
100
  try {
184
101
  new Intl.DateTimeFormat("en-US", { timeZone: tz });
185
102
  return true;
186
- } catch (e2) {
103
+ } catch (e) {
187
104
  return false;
188
105
  }
189
106
  }
190
107
  function isValidBcp47Locale(locale) {
191
108
  try {
192
109
  return Intl.getCanonicalLocales(locale).length > 0;
193
- } catch (e3) {
110
+ } catch (e2) {
194
111
  return false;
195
112
  }
196
113
  }
@@ -226,7 +143,7 @@ function makeBookingSchema(formFields, legalConsent) {
226
143
  }
227
144
  answers[field.name] = validator;
228
145
  }
229
- const requiredConsentIds = (_nullishCoalesce(_optionalChain([legalConsent, 'optionalAccess', _4 => _4.communicationConsentCheckboxes]), () => ( []))).filter((c) => c.required).map((c) => c.communicationTypeId);
146
+ const requiredConsentIds = (_nullishCoalesce(_optionalChain([legalConsent, 'optionalAccess', _2 => _2.communicationConsentCheckboxes]), () => ( []))).filter((c) => c.required).map((c) => c.communicationTypeId);
230
147
  const hasRequiredAnswers = formFields.some((f) => isSupportedFormField(f) && f.required);
231
148
  const answersObject = _zod.z.object(answers);
232
149
  return _zod.z.object({
@@ -259,6 +176,94 @@ function makeBookingSchema(formFields, legalConsent) {
259
176
  });
260
177
  }
261
178
 
179
+ // src/hooks/use-meeting-booking.ts
180
+ var AVAILABILITY_STALE_MS = 0;
181
+ function meetingAvailabilityKey(apiBaseUrl, meetingId, monthOffset) {
182
+ return ["meeting-availability", apiBaseUrl, meetingId, monthOffset];
183
+ }
184
+ function useMeetingBooking(options) {
185
+ const { meetingId, apiBaseUrl = "", initialAvailability } = options;
186
+ const queryClient = _reactquery.useQueryClient.call(void 0, );
187
+ const seededOffset = _optionalChain([initialAvailability, 'optionalAccess', _3 => _3.meetingId]) === meetingId ? initialAvailability.monthOffset : void 0;
188
+ const [monthOffset, setMonthOffsetState] = _react.useState.call(void 0, _nullishCoalesce(seededOffset, () => ( 0)));
189
+ const setMonthOffset = _react.useCallback.call(void 0, (offset) => {
190
+ setMonthOffsetState(Math.max(0, Math.min(_chunkQDOBY3TPcjs.MAX_MONTH_OFFSET, offset)));
191
+ }, []);
192
+ const prevMeetingIdRef = _react.useRef.call(void 0, meetingId);
193
+ _react.useLayoutEffect.call(void 0, () => {
194
+ if (prevMeetingIdRef.current === meetingId) return;
195
+ prevMeetingIdRef.current = meetingId;
196
+ setMonthOffsetState(0);
197
+ }, [meetingId]);
198
+ const seed = _optionalChain([initialAvailability, 'optionalAccess', _4 => _4.meetingId]) === meetingId && initialAvailability.monthOffset === monthOffset ? initialAvailability : void 0;
199
+ const availabilityQuery = _reactquery.useQuery.call(void 0, {
200
+ queryKey: meetingAvailabilityKey(apiBaseUrl, meetingId, monthOffset),
201
+ queryFn: async ({ signal }) => {
202
+ const params = new URLSearchParams({ meeting: meetingId, monthOffset: String(monthOffset) });
203
+ const res = await _chunkTRC37VRCcjs.contentFetch.call(void 0, `${apiBaseUrl}/api/meetings/availability?${params}`, { signal });
204
+ if (!res.ok) throw new Error(`availability ${res.status}`);
205
+ return await res.json();
206
+ },
207
+ staleTime: AVAILABILITY_STALE_MS,
208
+ initialData: seed,
209
+ // Stamped as infinitely old on purpose: the seed is first-paint
210
+ // scaffolding for a 60-second-volatile resource, not truth, so it paints
211
+ // immediately AND is refetched immediately.
212
+ initialDataUpdatedAt: seed ? 0 : void 0
213
+ });
214
+ const refetchAvailability = _react.useCallback.call(void 0, async () => {
215
+ await queryClient.invalidateQueries({ queryKey: meetingAvailabilityKey(apiBaseUrl, meetingId, monthOffset) }).catch(() => void 0);
216
+ }, [queryClient, apiBaseUrl, meetingId, monthOffset]);
217
+ const bookMutation = _reactquery.useMutation.call(void 0, {
218
+ mutationFn: async (payload) => {
219
+ try {
220
+ const res = await _chunkTRC37VRCcjs.contentFetch.call(void 0, `${apiBaseUrl}/api/meetings/book`, {
221
+ method: "POST",
222
+ headers: { "Content-Type": "application/json" },
223
+ body: JSON.stringify(payload)
224
+ });
225
+ const data = await res.json().catch(() => ({}));
226
+ if (res.ok) return { ok: true, confirmation: data };
227
+ const rawCode = typeof data.code === "string" ? data.code : "";
228
+ const code = MEETING_BOOKING_ERROR_CODES.includes(rawCode) ? rawCode : "TEMPORARILY_UNAVAILABLE";
229
+ return { ok: false, code, message: typeof data.error === "string" ? data.error : void 0 };
230
+ } catch (e3) {
231
+ return { ok: false, code: "TEMPORARILY_UNAVAILABLE" };
232
+ }
233
+ },
234
+ // A booking is not a read — never retried, at any layer.
235
+ retry: false
236
+ });
237
+ const submittingRef = _react.useRef.call(void 0, null);
238
+ const { mutateAsync } = bookMutation;
239
+ const book = _react.useCallback.call(void 0,
240
+ async (payload) => {
241
+ if (submittingRef.current !== null) return { ok: false, code: "VALIDATION", message: "Already submitting" };
242
+ const submitToken = {};
243
+ submittingRef.current = submitToken;
244
+ try {
245
+ return await mutateAsync(payload);
246
+ } finally {
247
+ if (submittingRef.current === submitToken) submittingRef.current = null;
248
+ }
249
+ },
250
+ [mutateAsync]
251
+ );
252
+ return {
253
+ availability: _nullishCoalesce(availabilityQuery.data, () => ( null)),
254
+ /** No availability for this month yet — the times column has nothing to show. */
255
+ isLoadingAvailability: availabilityQuery.isPending,
256
+ /** ANY request in flight, including a silent revalidation of cached data. */
257
+ isFetchingAvailability: availabilityQuery.isFetching,
258
+ availabilityError: availabilityQuery.error ? availabilityQuery.error.message : null,
259
+ monthOffset,
260
+ setMonthOffset,
261
+ refetchAvailability,
262
+ book,
263
+ isSubmitting: bookMutation.isPending
264
+ };
265
+ }
266
+
262
267
  // src/components/meeting-scheduler/booking-form.tsx
263
268
  var _zod3 = require('@hookform/resolvers/zod');
264
269
 
@@ -311,7 +316,7 @@ function BookingForm({
311
316
  const inputClass = "bg-ods-card border-ods-border text-ods-text-primary placeholder-ods-text-secondary px-3 h-11 md:h-12";
312
317
  const FORM_STACK = "flex flex-col gap-[var(--spacing-system-l)]";
313
318
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit: submit, className: FORM_STACK, noValidate: true, children: [
314
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.HoneypotField, { ...honeypotInputProps }),
319
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.HoneypotField, { ...honeypotInputProps }),
315
320
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQYQXAXVRcjs.FieldWrapper, { label: "Email", htmlFor: "ms-email", error: _optionalChain([errors, 'access', _9 => _9.email, 'optionalAccess', _10 => _10.message]), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
316
321
  _chunkQYQXAXVRcjs.Input,
317
322
  {
@@ -359,7 +364,7 @@ function BookingForm({
359
364
  error: fieldError(field.name),
360
365
  children: [
361
366
  field.type === "textarea" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
362
- _chunkYK7M7RBFcjs.Textarea,
367
+ _chunkQDOBY3TPcjs.Textarea,
363
368
  {
364
369
  id: `ms-q-${field.name}`,
365
370
  className: "border-ods-border bg-ods-card px-3 text-ods-text-primary placeholder-ods-text-secondary",
@@ -379,11 +384,11 @@ function BookingForm({
379
384
  {
380
385
  control,
381
386
  name: `formFields.${field.name}`,
382
- render: ({ field: rhf }) => field.type === "select" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkYK7M7RBFcjs.Select, { value: _nullishCoalesce(rhf.value, () => ( "")), onValueChange: rhf.onChange, children: [
383
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.SelectTrigger, { id: `ms-q-${field.name}`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.SelectValue, { placeholder: "Select\u2026" }) }),
384
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.SelectContent, { children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.SelectItem, { value: opt, children: opt }, opt)) })
385
- ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.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: [
386
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.RadioGroupItem, { id: `ms-q-${field.name}-${opt}`, value: opt }),
387
+ render: ({ field: rhf }) => field.type === "select" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkQDOBY3TPcjs.Select, { value: _nullishCoalesce(rhf.value, () => ( "")), onValueChange: rhf.onChange, children: [
388
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.SelectTrigger, { id: `ms-q-${field.name}`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.SelectValue, { placeholder: "Select\u2026" }) }),
389
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.SelectContent, { children: (_nullishCoalesce(field.options, () => ( []))).map((opt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.SelectItem, { value: opt, children: opt }, opt)) })
390
+ ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.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: [
391
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.RadioGroupItem, { id: `ms-q-${field.name}-${opt}`, value: opt }),
387
392
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3QDJLLD2cjs.Label, { htmlFor: `ms-q-${field.name}-${opt}`, children: opt })
388
393
  ] }, opt)) })
389
394
  }
@@ -504,7 +509,7 @@ function ContextPanelSkeleton({
504
509
  backLabel = "Back"
505
510
  }) {
506
511
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkPRPZBXWZcjs.cn.call(void 0, PANEL_STACK, className), children: [
507
- onBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.BackButton, { label: backLabel, onClick: onBack, className: BACK_BUTTON_CLASS }),
512
+ onBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.BackButton, { label: backLabel, onClick: onBack, className: BACK_BUTTON_CLASS }),
508
513
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: STRIP_BODY, children: [
509
514
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: STRIP_MAIN, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: IDENTITY_ROW, children: [
510
515
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-w-0 flex-1 items-center gap-[var(--spacing-system-xs)] lg:flex-none", children: [
@@ -551,7 +556,7 @@ function SchedulerContextPanel({
551
556
  return zones.map((tz) => ({ value: tz, label: zoneLabel(tz) }));
552
557
  }, [timezone]);
553
558
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkPRPZBXWZcjs.cn.call(void 0, PANEL_STACK, className), children: [
554
- onBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYK7M7RBFcjs.BackButton, { label: backLabel, onClick: onBack, className: BACK_BUTTON_CLASS }),
559
+ onBack && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.BackButton, { label: backLabel, onClick: onBack, className: BACK_BUTTON_CLASS }),
555
560
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: STRIP_BODY, children: [
556
561
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: STRIP_MAIN, children: [
557
562
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: IDENTITY_ROW, children: [
@@ -612,7 +617,7 @@ function SchedulerContextPanel({
612
617
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkPRPZBXWZcjs.cn.call(void 0, STRIP_ASIDE, locked && "max-lg:hidden"), children: [
613
618
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: FIELD_LABEL_CLASS, children: "Timezone" }),
614
619
  timezone ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
615
- _chunkYK7M7RBFcjs.Autocomplete,
620
+ _chunkQDOBY3TPcjs.Autocomplete,
616
621
  {
617
622
  value: timezone,
618
623
  onChange: (tz) => {
@@ -698,18 +703,18 @@ var NOOP = () => void 0;
698
703
  function DayCalendar({ monthOffset, onMonthOffsetChange, selectedDay, onSelectDay, slotsByDay }) {
699
704
  const now = /* @__PURE__ */ new Date();
700
705
  const startMonth = new Date(now.getFullYear(), now.getMonth(), 1);
701
- const endMonth = new Date(now.getFullYear(), now.getMonth() + _chunkYK7M7RBFcjs.MAX_MONTH_OFFSET + 1, 0);
706
+ const endMonth = new Date(now.getFullYear(), now.getMonth() + _chunkQDOBY3TPcjs.MAX_MONTH_OFFSET + 1, 0);
702
707
  const visibleMonth = new Date(now.getFullYear(), now.getMonth() + monthOffset, 1);
703
708
  const dayHasNoSlots = _react.useCallback.call(void 0, (day) => !_optionalChain([slotsByDay, 'optionalAccess', _22 => _22.has, 'call', _23 => _23(calendarDayKey(day))]), [slotsByDay]);
704
709
  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,
705
- _chunkYK7M7RBFcjs.DatePickerCalendar,
710
+ _chunkQDOBY3TPcjs.DatePickerCalendar,
706
711
  {
707
712
  mode: "single",
708
713
  bare: true,
709
714
  month: visibleMonth,
710
715
  onMonthChange: (month) => {
711
716
  const offset = (month.getFullYear() - now.getFullYear()) * 12 + (month.getMonth() - now.getMonth());
712
- onMonthOffsetChange(Math.max(0, Math.min(_chunkYK7M7RBFcjs.MAX_MONTH_OFFSET, offset)));
717
+ onMonthOffsetChange(Math.max(0, Math.min(_chunkQDOBY3TPcjs.MAX_MONTH_OFFSET, offset)));
713
718
  },
714
719
  fromDate: startMonth,
715
720
  toDate: endMonth,
@@ -823,7 +828,7 @@ function SlotPicker({
823
828
  monthLabelFor(monthOffset),
824
829
  "."
825
830
  ] }),
826
- monthOffset < _chunkYK7M7RBFcjs.MAX_MONTH_OFFSET && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
831
+ monthOffset < _chunkQDOBY3TPcjs.MAX_MONTH_OFFSET && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
827
832
  _chunkS6LZN66Dcjs.Button,
828
833
  {
829
834
  variant: "outline",
@@ -1001,6 +1006,13 @@ function MeetingSchedulerDirectory({
1001
1006
 
1002
1007
  // src/components/meeting-scheduler/index.tsx
1003
1008
 
1009
+ var BOOKING_ERROR_COPY = {
1010
+ INVALID_EMAIL: "That email address was rejected by our scheduling system \u2014 please use a real, reachable address (work email works best).",
1011
+ VALIDATION: "Please double-check your details \u2014 especially that the email address is real and reachable \u2014 and try again.",
1012
+ TEMPORARILY_UNAVAILABLE: "Scheduling is briefly unavailable \u2014 please try again in a minute.",
1013
+ MEETING_UNAVAILABLE: "This meeting type has reached its booking limit for today \u2014 try another time or contact us.",
1014
+ LINK_GONE: "This meeting type is no longer available."
1015
+ };
1004
1016
  var CONTEXT_PANEL_CLASS = "p-[var(--spacing-system-l)] shrink-0 lg:w-[280px] border-b lg:border-b-0 lg:border-r border-ods-border lg:min-h-0 lg:overflow-y-auto";
1005
1017
  var ACTION_PANEL_CLASS = "flex-1 min-w-0 flex flex-col md:min-h-0 lg:p-[var(--spacing-system-l)]";
1006
1018
  var PANEL_STEP_CLASS = "p-[var(--spacing-system-l)] md:min-h-0 md:overflow-y-auto lg:p-0";
@@ -1189,8 +1201,8 @@ function HubSpotMeetingScheduler({
1189
1201
  "\xB7 ",
1190
1202
  _chunkSPAAKHQAcjs.formatDurationCompact.call(void 0, durationMs / 1e3)
1191
1203
  ] }),
1192
- bookingError && bookingError !== "SLOT_TAKEN" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-start gap-[var(--spacing-system-xs)]", children: [
1193
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-error text-h6", children: bookingError === "TEMPORARILY_UNAVAILABLE" ? "Scheduling is briefly unavailable \u2014 please try again in a minute." : bookingError === "MEETING_UNAVAILABLE" ? "This meeting type has reached its booking limit for today \u2014 try another time or contact us." : bookingError === "LINK_GONE" ? "This meeting type is no longer available." : "Please double-check your details and try again." }),
1204
+ bookingError && bookingError !== "SLOT_TAKEN" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkQDOBY3TPcjs.Alert, { variant: "error", className: "flex flex-col items-start gap-[var(--spacing-system-xs)]", children: [
1205
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.AlertDescription, { children: _nullishCoalesce(BOOKING_ERROR_COPY[bookingError], () => ( BOOKING_ERROR_COPY.VALIDATION)) }),
1194
1206
  escapeHatch
1195
1207
  ] }),
1196
1208
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -1208,7 +1220,14 @@ function HubSpotMeetingScheduler({
1208
1220
  }
1209
1221
  )
1210
1222
  ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-[var(--spacing-system-m)] md:min-h-0 md:flex-1", children: [
1211
- bookingError === "SLOT_TAKEN" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "px-[var(--spacing-system-l)] pt-[var(--spacing-system-l)] text-ods-error text-h6 lg:p-0", children: "That time is no longer available \u2014 if you just submitted, check your email for a confirmation before rebooking." }),
1223
+ bookingError === "SLOT_TAKEN" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1224
+ _chunkQDOBY3TPcjs.Alert,
1225
+ {
1226
+ variant: "warning",
1227
+ className: "mx-[var(--spacing-system-l)] mt-[var(--spacing-system-l)] w-auto lg:m-0 lg:w-full",
1228
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQDOBY3TPcjs.AlertDescription, { children: "That time was just taken \u2014 pick another slot below. (If you already submitted, check your email for a confirmation before rebooking.)" })
1229
+ }
1230
+ ),
1212
1231
  timezone && durationMs != null ? (
1213
1232
  // The picker owns BOTH the loading and the empty month now —
1214
1233
  // it keeps the calendar up either way, so there is no branch