@flamingo-stack/openframe-frontend-core 0.0.595 → 0.0.596-2034.5670.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.
Files changed (156) hide show
  1. package/dist/{chunk-U4QRK4MX.js → chunk-27U3NNFR.js} +4 -4
  2. package/dist/{chunk-OGE4GSLZ.cjs → chunk-2EPDTX4M.cjs} +84 -84
  3. package/dist/{chunk-OGE4GSLZ.cjs.map → chunk-2EPDTX4M.cjs.map} +1 -1
  4. package/dist/{chunk-BKMSI2AW.js → chunk-2KQO7OMB.js} +2 -2
  5. package/dist/{chunk-A57HKYLY.js → chunk-2NZKBKO6.js} +6 -6
  6. package/dist/{chunk-CPWX46TL.cjs → chunk-53HSPYKM.cjs} +6 -6
  7. package/dist/{chunk-CPWX46TL.cjs.map → chunk-53HSPYKM.cjs.map} +1 -1
  8. package/dist/{chunk-FHEN27GM.cjs → chunk-5K6GZANU.cjs} +11 -11
  9. package/dist/{chunk-FHEN27GM.cjs.map → chunk-5K6GZANU.cjs.map} +1 -1
  10. package/dist/{chunk-23UJ4EBJ.cjs → chunk-7CKSLZT6.cjs} +12 -12
  11. package/dist/{chunk-23UJ4EBJ.cjs.map → chunk-7CKSLZT6.cjs.map} +1 -1
  12. package/dist/{chunk-T2JAJ7MR.js → chunk-7YUFH47E.js} +26 -13
  13. package/dist/chunk-7YUFH47E.js.map +1 -0
  14. package/dist/{chunk-OWWICTQR.cjs → chunk-AN4CB7U3.cjs} +24 -24
  15. package/dist/{chunk-OWWICTQR.cjs.map → chunk-AN4CB7U3.cjs.map} +1 -1
  16. package/dist/{chunk-3WZLPCJ7.js → chunk-BDLFPDAW.js} +4 -4
  17. package/dist/{chunk-QLJMXCB5.js → chunk-BHIJ5OGK.js} +5 -5
  18. package/dist/{chunk-AQ65NLGJ.js → chunk-E7MTTLKC.js} +3 -3
  19. package/dist/{chunk-MUNVPRT2.js → chunk-EVMHJB6X.js} +2 -2
  20. package/dist/{chunk-MOHSA65M.js → chunk-EZM5DNII.js} +2 -2
  21. package/dist/{chunk-7N2NJPUK.js → chunk-FPG4S3X4.js} +4 -4
  22. package/dist/{chunk-HGWC7ABT.cjs → chunk-FUHYCQLO.cjs} +63 -63
  23. package/dist/{chunk-HGWC7ABT.cjs.map → chunk-FUHYCQLO.cjs.map} +1 -1
  24. package/dist/{chunk-MHORK6KM.cjs → chunk-IIWB7VEC.cjs} +3 -3
  25. package/dist/{chunk-MHORK6KM.cjs.map → chunk-IIWB7VEC.cjs.map} +1 -1
  26. package/dist/{chunk-ZY3Z3F4X.cjs → chunk-IJY6E2YO.cjs} +49 -49
  27. package/dist/{chunk-ZY3Z3F4X.cjs.map → chunk-IJY6E2YO.cjs.map} +1 -1
  28. package/dist/{chunk-5EM6NGBK.cjs → chunk-KOQCA5X5.cjs} +17 -27
  29. package/dist/chunk-KOQCA5X5.cjs.map +1 -0
  30. package/dist/{chunk-YYHYCQD6.cjs → chunk-L7GNBUXF.cjs} +168 -168
  31. package/dist/{chunk-YYHYCQD6.cjs.map → chunk-L7GNBUXF.cjs.map} +1 -1
  32. package/dist/{chunk-A5AKGC4S.js → chunk-LPMDCQLL.js} +17 -27
  33. package/dist/chunk-LPMDCQLL.js.map +1 -0
  34. package/dist/{chunk-4ZY5MP46.cjs → chunk-LPWTGNNP.cjs} +15 -15
  35. package/dist/{chunk-4ZY5MP46.cjs.map → chunk-LPWTGNNP.cjs.map} +1 -1
  36. package/dist/{chunk-FKXDDJEQ.cjs → chunk-M4YQUHOR.cjs} +5 -5
  37. package/dist/{chunk-FKXDDJEQ.cjs.map → chunk-M4YQUHOR.cjs.map} +1 -1
  38. package/dist/{chunk-PYEJL2UG.js → chunk-MOKMFLKB.js} +3 -3
  39. package/dist/{chunk-ZRXJX3JK.js → chunk-NRGBR3SN.js} +6 -6
  40. package/dist/{chunk-DYXVQ24Q.js → chunk-ONZCED5F.js} +3 -3
  41. package/dist/{chunk-UPKN5CYH.js → chunk-P367JZLK.js} +8 -8
  42. package/dist/{chunk-63PXZXCT.js → chunk-PPY2IRJP.js} +4 -4
  43. package/dist/{chunk-CZM2H5F5.cjs → chunk-QBXD4KOR.cjs} +5 -5
  44. package/dist/{chunk-CZM2H5F5.cjs.map → chunk-QBXD4KOR.cjs.map} +1 -1
  45. package/dist/{chunk-JGDDPNSC.cjs → chunk-QW663C35.cjs} +298 -285
  46. package/dist/chunk-QW663C35.cjs.map +1 -0
  47. package/dist/{chunk-6PEFK4UH.cjs → chunk-QX6GS6Y3.cjs} +9 -9
  48. package/dist/{chunk-6PEFK4UH.cjs.map → chunk-QX6GS6Y3.cjs.map} +1 -1
  49. package/dist/{chunk-SEVD4AST.js → chunk-RY2MDY6G.js} +7 -7
  50. package/dist/{chunk-4R6AZFNU.cjs → chunk-SAEJGTCI.cjs} +30 -30
  51. package/dist/{chunk-4R6AZFNU.cjs.map → chunk-SAEJGTCI.cjs.map} +1 -1
  52. package/dist/{chunk-TDEQ26A2.js → chunk-UAAXUFK6.js} +1 -1
  53. package/dist/chunk-UAAXUFK6.js.map +1 -0
  54. package/dist/{chunk-EO5GYWIX.cjs → chunk-V7SYWH7D.cjs} +40 -40
  55. package/dist/{chunk-EO5GYWIX.cjs.map → chunk-V7SYWH7D.cjs.map} +1 -1
  56. package/dist/{chunk-MX7DNV7X.cjs → chunk-VZMA3IUV.cjs} +33 -33
  57. package/dist/{chunk-MX7DNV7X.cjs.map → chunk-VZMA3IUV.cjs.map} +1 -1
  58. package/dist/{chunk-NNMAMTA5.js → chunk-WC3M4XJ2.js} +3 -3
  59. package/dist/{chunk-SK4IVCSI.cjs → chunk-WCBRZCU4.cjs} +1 -1
  60. package/dist/chunk-WCBRZCU4.cjs.map +1 -0
  61. package/dist/{chunk-2WLW5HDU.js → chunk-WE4OW4XP.js} +8 -8
  62. package/dist/{chunk-MDUAU74C.cjs → chunk-WKZ3JYMP.cjs} +28 -28
  63. package/dist/{chunk-MDUAU74C.cjs.map → chunk-WKZ3JYMP.cjs.map} +1 -1
  64. package/dist/components/case-studies/index.cjs +16 -16
  65. package/dist/components/case-studies/index.js +6 -6
  66. package/dist/components/chat/index.cjs +4 -4
  67. package/dist/components/chat/index.js +3 -3
  68. package/dist/components/contact/index.cjs +7 -7
  69. package/dist/components/contact/index.js +6 -6
  70. package/dist/components/docs/index.cjs +10 -10
  71. package/dist/components/docs/index.js +9 -9
  72. package/dist/components/embeds/index.cjs +7 -7
  73. package/dist/components/embeds/index.js +6 -6
  74. package/dist/components/faq/index.cjs +7 -7
  75. package/dist/components/faq/index.js +6 -6
  76. package/dist/components/features/index.cjs +6 -6
  77. package/dist/components/features/index.js +5 -5
  78. package/dist/components/help-center-pages/index.cjs +26 -26
  79. package/dist/components/help-center-pages/index.js +17 -17
  80. package/dist/components/icons/index.cjs +2 -2
  81. package/dist/components/icons/index.js +1 -1
  82. package/dist/components/icons/mlg-logo.d.ts.map +1 -1
  83. package/dist/components/index.cjs +56 -56
  84. package/dist/components/index.js +17 -17
  85. package/dist/components/meeting-scheduler/booking-form.d.ts +70 -6
  86. package/dist/components/meeting-scheduler/booking-form.d.ts.map +1 -1
  87. package/dist/components/meeting-scheduler/context-panel.d.ts +9 -1
  88. package/dist/components/meeting-scheduler/context-panel.d.ts.map +1 -1
  89. package/dist/components/meeting-scheduler/index.cjs +395 -188
  90. package/dist/components/meeting-scheduler/index.cjs.map +1 -1
  91. package/dist/components/meeting-scheduler/index.d.ts +55 -1
  92. package/dist/components/meeting-scheduler/index.d.ts.map +1 -1
  93. package/dist/components/meeting-scheduler/index.js +381 -174
  94. package/dist/components/meeting-scheduler/index.js.map +1 -1
  95. package/dist/components/meeting-scheduler/slot-picker.d.ts +8 -1
  96. package/dist/components/meeting-scheduler/slot-picker.d.ts.map +1 -1
  97. package/dist/components/navigation/index.cjs +9 -9
  98. package/dist/components/navigation/index.js +8 -8
  99. package/dist/components/onboarding-guides/index.cjs +9 -9
  100. package/dist/components/onboarding-guides/index.js +8 -8
  101. package/dist/components/related-content/index.cjs +3 -3
  102. package/dist/components/related-content/index.js +2 -2
  103. package/dist/components/tickets/index.cjs +10 -10
  104. package/dist/components/tickets/index.js +9 -9
  105. package/dist/components/ui/benefit-card.d.ts.map +1 -1
  106. package/dist/components/ui/index.cjs +6 -6
  107. package/dist/components/ui/index.js +5 -5
  108. package/dist/hooks/index.cjs +3 -3
  109. package/dist/hooks/index.js +2 -2
  110. package/dist/index.cjs +10 -10
  111. package/dist/index.js +9 -9
  112. package/dist/schemas/meeting-booking-schema.cjs +19 -4
  113. package/dist/schemas/meeting-booking-schema.cjs.map +1 -1
  114. package/dist/schemas/meeting-booking-schema.d.ts +41 -16
  115. package/dist/schemas/meeting-booking-schema.d.ts.map +1 -1
  116. package/dist/schemas/meeting-booking-schema.js +19 -5
  117. package/dist/schemas/meeting-booking-schema.js.map +1 -1
  118. package/dist/types/index.cjs.map +1 -1
  119. package/dist/types/index.js.map +1 -1
  120. package/dist/utils/index.cjs +16 -26
  121. package/dist/utils/index.cjs.map +1 -1
  122. package/dist/utils/index.js +16 -26
  123. package/dist/utils/index.js.map +1 -1
  124. package/package.json +1 -1
  125. package/src/components/icons/mlg-logo.tsx +1 -7
  126. package/src/components/meeting-scheduler/booking-form.tsx +425 -154
  127. package/src/components/meeting-scheduler/context-panel.tsx +13 -3
  128. package/src/components/meeting-scheduler/index.tsx +317 -69
  129. package/src/components/meeting-scheduler/slot-picker.tsx +17 -1
  130. package/src/components/ui/benefit-card.tsx +30 -9
  131. package/src/schemas/meeting-booking-schema.ts +58 -4
  132. package/src/types/tmcg.ts +0 -2
  133. package/src/utils/format.ts +1 -1
  134. package/dist/chunk-5EM6NGBK.cjs.map +0 -1
  135. package/dist/chunk-A5AKGC4S.js.map +0 -1
  136. package/dist/chunk-JGDDPNSC.cjs.map +0 -1
  137. package/dist/chunk-SK4IVCSI.cjs.map +0 -1
  138. package/dist/chunk-T2JAJ7MR.js.map +0 -1
  139. package/dist/chunk-TDEQ26A2.js.map +0 -1
  140. /package/dist/{chunk-U4QRK4MX.js.map → chunk-27U3NNFR.js.map} +0 -0
  141. /package/dist/{chunk-BKMSI2AW.js.map → chunk-2KQO7OMB.js.map} +0 -0
  142. /package/dist/{chunk-A57HKYLY.js.map → chunk-2NZKBKO6.js.map} +0 -0
  143. /package/dist/{chunk-3WZLPCJ7.js.map → chunk-BDLFPDAW.js.map} +0 -0
  144. /package/dist/{chunk-QLJMXCB5.js.map → chunk-BHIJ5OGK.js.map} +0 -0
  145. /package/dist/{chunk-AQ65NLGJ.js.map → chunk-E7MTTLKC.js.map} +0 -0
  146. /package/dist/{chunk-MUNVPRT2.js.map → chunk-EVMHJB6X.js.map} +0 -0
  147. /package/dist/{chunk-MOHSA65M.js.map → chunk-EZM5DNII.js.map} +0 -0
  148. /package/dist/{chunk-7N2NJPUK.js.map → chunk-FPG4S3X4.js.map} +0 -0
  149. /package/dist/{chunk-PYEJL2UG.js.map → chunk-MOKMFLKB.js.map} +0 -0
  150. /package/dist/{chunk-ZRXJX3JK.js.map → chunk-NRGBR3SN.js.map} +0 -0
  151. /package/dist/{chunk-DYXVQ24Q.js.map → chunk-ONZCED5F.js.map} +0 -0
  152. /package/dist/{chunk-UPKN5CYH.js.map → chunk-P367JZLK.js.map} +0 -0
  153. /package/dist/{chunk-63PXZXCT.js.map → chunk-PPY2IRJP.js.map} +0 -0
  154. /package/dist/{chunk-SEVD4AST.js.map → chunk-RY2MDY6G.js.map} +0 -0
  155. /package/dist/{chunk-NNMAMTA5.js.map → chunk-WC3M4XJ2.js.map} +0 -0
  156. /package/dist/{chunk-2WLW5HDU.js.map → chunk-WE4OW4XP.js.map} +0 -0
@@ -18,24 +18,24 @@ export const BenefitCard: React.FC<BenefitCardProps> = ({
18
18
  variant = 'default',
19
19
  className = '',
20
20
  }) => {
21
- const getBaseStyles = (cardVariant: string) => {
22
- const gap = cardVariant === 'auth-figma' ? 'gap-4' : 'gap-2';
23
- return `flex ${gap} items-start justify-start relative`;
24
- };
21
+ // Direction and cross-axis alignment only — every other per-variant value
22
+ // (including `gap`, which used to hide in a ternary here) lives in
23
+ // `variantStyles` so one variant is one place.
24
+ const baseStyles = 'flex items-start justify-start relative';
25
25
 
26
26
  const variantStyles = {
27
27
  default: {
28
- container: 'bg-ods-bg p-2 md:p-4',
28
+ container: 'gap-2 bg-ods-bg p-2 md:p-4',
29
29
  title: 'font-body font-bold text-body-md md:text-body-lg text-ods-text-primary',
30
30
  description: 'font-body font-medium text-body-sm md:text-body-md text-ods-text-secondary',
31
31
  },
32
32
  dark: {
33
- container: 'bg-transparent p-0 shadow-[0px_48px_80px_0px_rgba(0,0,0,0.24)]',
33
+ container: 'gap-2 bg-transparent p-0 shadow-[0px_48px_80px_0px_rgba(0,0,0,0.24)]',
34
34
  title: 'font-mono font-semibold text-heading-4 leading-[40px] text-ods-text-primary tracking-[-0.64px]',
35
35
  description: 'font-body font-medium text-body-lg leading-6 text-ods-text-tertiary',
36
36
  },
37
37
  'auth-figma': {
38
- container: 'bg-transparent p-6',
38
+ container: 'gap-4 bg-transparent p-6',
39
39
  title: 'text-h3 text-ods-text-primary tracking-[-0.36px]',
40
40
  description: 'text-h4 text-ods-text-secondary',
41
41
  },
@@ -44,7 +44,7 @@ export const BenefitCard: React.FC<BenefitCardProps> = ({
44
44
  const styles = variantStyles[variant];
45
45
 
46
46
  return (
47
- <div className={cn(getBaseStyles(variant), styles.container, className)}>
47
+ <div className={cn(baseStyles, styles.container, className)}>
48
48
  {icon && <div>{icon}</div>}
49
49
  <div className="flex min-w-0 flex-1 flex-col gap-1">
50
50
  <h3 className={cn(styles.title)}>{title}</h3>
@@ -93,8 +93,29 @@ export const BenefitCardGrid: React.FC<BenefitCardGridProps> = ({ children, clas
93
93
  !isInLastRow && 'border-b md:border-b lg:border-b-0',
94
94
  index < 2 && 'lg:border-b-0',
95
95
  );
96
+ } else if (columns === 3) {
97
+ // 3 columns lay out 1-up / 2-up / 3-up, so the row a card sits in
98
+ // differs per breakpoint and a single rule cannot describe it. The
99
+ // old shared 2-3 branch assumed one row and, at `md` (grid-cols-2),
100
+ // gave card 1 a trailing `md:border-r` while suppressing the divider
101
+ // between the two rows.
102
+ const isLastInMdRow = (index + 1) % 2 === 0;
103
+ const isInLastMdRow = index >= totalItems - (totalItems % 2 === 0 ? 2 : 1);
104
+ const isLastInLgRow = (index + 1) % 3 === 0;
105
+ const isInLastLgRow = index >= totalItems - (totalItems % 3 === 0 ? 3 : totalItems % 3);
106
+ borderClass = cn(
107
+ 'border-ods-border',
108
+ !isLastItem && 'border-b',
109
+ isInLastMdRow && 'md:border-b-0',
110
+ !isLastInMdRow && !isLastItem && 'md:border-r',
111
+ isLastInMdRow && 'md:border-r-0',
112
+ isInLastLgRow && 'lg:border-b-0',
113
+ !isInLastMdRow && !isInLastLgRow && 'lg:border-b',
114
+ !isLastInLgRow && !isLastItem && 'lg:border-r',
115
+ isLastInLgRow && 'lg:border-r-0',
116
+ );
96
117
  } else {
97
- // Original 2-3 column logic
118
+ // 2 columns: a flex row, so one rule genuinely does describe it.
98
119
  borderClass = isLastItem ? 'border-b-0' : 'border-b md:border-b-0 md:border-r border-ods-border';
99
120
  }
100
121
 
@@ -225,7 +225,15 @@ export function isValidBcp47Locale(locale: string): boolean {
225
225
  * in the visitor's local time) — this schema is the ONLY place a
226
226
  * client-supplied zone is accepted; the availability path is UTC-pinned.
227
227
  */
228
- export function makeBookingSchema(formFields: MeetingFormField[], legalConsent: MeetingLegalConsent | null) {
228
+ function buildBookingSchema<TStart extends z.ZodTypeAny, TDuration extends z.ZodTypeAny, TZone extends z.ZodTypeAny>(
229
+ formFields: MeetingFormField[],
230
+ legalConsent: MeetingLegalConsent | null,
231
+ // Passed IN rather than switched on a boolean: a `deferSlot: boolean`
232
+ // parameter cannot be narrowed at type level, so every ternary inside would
233
+ // infer a union and widen `startTimeMs`/`durationMs` to `number | null |
234
+ // undefined` for BOTH schemas — including the server's wire type.
235
+ slot: { startTimeMs: TStart; durationMs: TDuration; timezone: TZone },
236
+ ) {
229
237
  const answers: Record<string, z.ZodTypeAny> = {};
230
238
  for (const field of formFields) {
231
239
  if (!isSupportedFormField(field)) continue; // unsupported types are fail-closed at render time
@@ -276,12 +284,12 @@ export function makeBookingSchema(formFields: MeetingFormField[], legalConsent:
276
284
  z
277
285
  .object({
278
286
  meetingId: z.string().min(1),
279
- startTimeMs: z.number().int().positive(),
280
- durationMs: z.number().int().positive(),
287
+ startTimeMs: slot.startTimeMs,
288
+ durationMs: slot.durationMs,
281
289
  firstName: z.string().min(1, { message: 'First name is required' }).max(255),
282
290
  lastName: z.string().min(1, { message: 'Last name is required' }).max(255),
283
291
  email: z.string().email({ message: 'Please enter a valid email address' }).max(255),
284
- timezone: z.string().refine(isValidIanaTimezone, { message: 'Invalid timezone' }),
292
+ timezone: slot.timezone,
285
293
  locale: z.string().refine(isValidBcp47Locale, { message: 'Invalid locale' }).optional(),
286
294
  // Plain `.optional()` (no `.default()`) so zod's input and output types
287
295
  // match — react-hook-form's zodResolver needs them identical, and the
@@ -311,4 +319,50 @@ export function makeBookingSchema(formFields: MeetingFormField[], legalConsent:
311
319
  );
312
320
  }
313
321
 
322
+ /**
323
+ * The STRICT schema — the wire contract. The server rebuilds it from the link's
324
+ * own fetched metadata and validates every booking against it; a slot and a
325
+ * duration are not optional on anything that reaches HubSpot.
326
+ */
327
+ export function makeBookingSchema(formFields: MeetingFormField[], legalConsent: MeetingLegalConsent | null) {
328
+ return buildBookingSchema(formFields, legalConsent, {
329
+ startTimeMs: z.number().int().positive(),
330
+ durationMs: z.number().int().positive(),
331
+ timezone: z.string().refine(isValidIanaTimezone, { message: 'Invalid timezone' }),
332
+ });
333
+ }
334
+
335
+ /**
336
+ * The DEFERRED schema — same fields, with the slot/duration/timezone triple
337
+ * relaxed. `flow="details-first"` collects answers BEFORE a slot exists, so the
338
+ * form validates against this and the parent re-attaches the authoritative
339
+ * values at POST time.
340
+ *
341
+ * Two named exports over one private builder rather than an overload or an
342
+ * options flag: `MeetingBookingPayload` is `z.infer<ReturnType<...>>`, and
343
+ * either of those alternatives would widen `startTimeMs`/`durationMs` to
344
+ * `number | undefined` for EVERY consumer — including the server's
345
+ * `durationsMs.includes(data.durationMs)`.
346
+ */
347
+ export function makeDeferredBookingSchema(formFields: MeetingFormField[], legalConsent: MeetingLegalConsent | null) {
348
+ // `.nullish()`, not `.optional()`: the widget passes these straight into
349
+ // `defaultValues`, and details-first has `timezone === null` on the server
350
+ // render and the first client render (zone resolution is post-hydration).
351
+ // Accepting only `undefined` would reject a field with no rendered control
352
+ // and no FieldWrapper — the submit button silently dead, type-check clean.
353
+ return buildBookingSchema(formFields, legalConsent, {
354
+ startTimeMs: z.number().int().positive().nullish(),
355
+ durationMs: z.number().int().positive().nullish(),
356
+ timezone: z.string().refine(isValidIanaTimezone, { message: 'Invalid timezone' }).nullish(),
357
+ });
358
+ }
359
+
360
+ /** The wire payload. Pinned to the STRICT builder — see above. */
314
361
  export type MeetingBookingPayload = z.infer<ReturnType<typeof makeBookingSchema>>;
362
+
363
+ /**
364
+ * The form's value type, used as the `useForm` generic in BOTH flows: a relaxed
365
+ * resolver is not assignable to `Resolver<MeetingBookingPayload>`, and mixing
366
+ * the two survives only on TS's bivariant method-parameter check.
367
+ */
368
+ export type BookingFormValues = z.infer<ReturnType<typeof makeDeferredBookingSchema>>;
package/src/types/tmcg.ts CHANGED
@@ -106,5 +106,3 @@ export const TMCG_ROLE_DISPLAY_NAMES: Record<string, string> = {
106
106
  [TMCG_ROLES.SPEAKER]: 'Speaker',
107
107
  [TMCG_ROLES.MENTOR]: 'Mentor',
108
108
  };
109
-
110
-
@@ -184,7 +184,7 @@ export interface NameInitialsOptions {
184
184
  export function nameInitials(
185
185
  name: string | null | undefined,
186
186
  fallback: string = 'E',
187
- options: NameInitialsOptions = {}
187
+ options: NameInitialsOptions = {},
188
188
  ): string {
189
189
  const { maxLetters = 2, pick: mode = 'all' } = options;
190
190
  const source = typeof name === 'string' ? name.trim() : '';