@alfadocs/ui-kit 1.46.0 → 1.47.0

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 (91) hide show
  1. package/dist/_chunks/booking-C4MwImkS.js +3362 -0
  2. package/dist/_chunks/calendar-workspace-DDnQmiIL.js +12427 -0
  3. package/dist/_chunks/{freemium-paywall-Cz-O9lQD.js → freemium-paywall-BaW5ODc9.js} +2 -2
  4. package/dist/_chunks/{patient-details-DUj1htsH.js → patient-details-yrgkSeEY.js} +2 -2
  5. package/dist/_chunks/{patient-field-row-CO0WR7yA.js → patient-field-row-DCMkFGqI.js} +2 -2
  6. package/dist/_chunks/{patient-summary-card-DNzdYjxE.js → patient-summary-card-CmEFflGS.js} +2 -2
  7. package/dist/_chunks/payment-form-DqJFiplX.js +881 -0
  8. package/dist/_chunks/{phone-input-BsZIoE36.js → phone-input-IWrGOCwm.js} +40 -39
  9. package/dist/_chunks/{stepper-accordion-DmVykr5F.js → stepper-accordion-jMR8NaOB.js} +2 -1
  10. package/dist/agent-catalog.json +5 -4
  11. package/dist/agent-i18n/en.json +2 -2
  12. package/dist/components/booking/booking-types.d.ts +60 -1
  13. package/dist/components/booking/booking.d.ts +1 -1
  14. package/dist/components/booking/details-form.d.ts +5 -1
  15. package/dist/components/booking/index.d.ts +1 -1
  16. package/dist/components/booking/index.js +1 -1
  17. package/dist/components/booking/payment.d.ts +9 -0
  18. package/dist/components/booking/use-booking-payment.d.ts +14 -0
  19. package/dist/components/freemium-paywall/index.js +1 -1
  20. package/dist/components/patient-details/index.js +1 -1
  21. package/dist/components/patient-summary-card/index.js +1 -1
  22. package/dist/components/payment-form/index.d.ts +1 -1
  23. package/dist/components/payment-form/index.js +1 -1
  24. package/dist/components/payment-form/payment-form.d.ts +35 -3
  25. package/dist/components/phone-input/index.js +1 -1
  26. package/dist/components/stepper-accordion/index.js +1 -1
  27. package/dist/i18n/locales/ar.d.ts +36 -1
  28. package/dist/i18n/locales/ar.js +36 -1
  29. package/dist/i18n/locales/de.d.ts +36 -1
  30. package/dist/i18n/locales/de.js +36 -1
  31. package/dist/i18n/locales/el.d.ts +36 -1
  32. package/dist/i18n/locales/el.js +36 -1
  33. package/dist/i18n/locales/en.d.ts +36 -1
  34. package/dist/i18n/locales/en.js +36 -1
  35. package/dist/i18n/locales/es.d.ts +36 -1
  36. package/dist/i18n/locales/es.js +36 -1
  37. package/dist/i18n/locales/fr.d.ts +36 -1
  38. package/dist/i18n/locales/fr.js +36 -1
  39. package/dist/i18n/locales/hi.d.ts +36 -1
  40. package/dist/i18n/locales/hi.js +36 -1
  41. package/dist/i18n/locales/it.d.ts +36 -1
  42. package/dist/i18n/locales/it.js +36 -1
  43. package/dist/i18n/locales/ja.d.ts +36 -1
  44. package/dist/i18n/locales/ja.js +36 -1
  45. package/dist/i18n/locales/nl.d.ts +36 -1
  46. package/dist/i18n/locales/nl.js +36 -1
  47. package/dist/i18n/locales/pl.d.ts +36 -1
  48. package/dist/i18n/locales/pl.js +36 -1
  49. package/dist/i18n/locales/pt.d.ts +36 -1
  50. package/dist/i18n/locales/pt.js +36 -1
  51. package/dist/i18n/locales/ro.d.ts +36 -1
  52. package/dist/i18n/locales/ro.js +36 -1
  53. package/dist/i18n/locales/ru.d.ts +36 -1
  54. package/dist/i18n/locales/ru.js +36 -1
  55. package/dist/i18n/locales/sq.d.ts +36 -1
  56. package/dist/i18n/locales/sq.js +36 -1
  57. package/dist/i18n/locales/sv.d.ts +36 -1
  58. package/dist/i18n/locales/sv.js +36 -1
  59. package/dist/i18n/locales/tr.d.ts +36 -1
  60. package/dist/i18n/locales/tr.js +36 -1
  61. package/dist/i18n/locales/zh.d.ts +36 -1
  62. package/dist/i18n/locales/zh.js +36 -1
  63. package/dist/index.js +8 -8
  64. package/dist/locales/ar.json +36 -1
  65. package/dist/locales/de.json +36 -1
  66. package/dist/locales/el.json +36 -1
  67. package/dist/locales/en.json +36 -1
  68. package/dist/locales/es.json +36 -1
  69. package/dist/locales/fr.json +36 -1
  70. package/dist/locales/hi.json +36 -1
  71. package/dist/locales/it.json +36 -1
  72. package/dist/locales/ja.json +36 -1
  73. package/dist/locales/nl.json +36 -1
  74. package/dist/locales/pl.json +36 -1
  75. package/dist/locales/pt.json +36 -1
  76. package/dist/locales/ro.json +36 -1
  77. package/dist/locales/ru.json +36 -1
  78. package/dist/locales/sq.json +36 -1
  79. package/dist/locales/sv.json +36 -1
  80. package/dist/locales/tr.json +36 -1
  81. package/dist/locales/zh.json +36 -1
  82. package/dist/patterns/calendar/calendar-editor-fields.d.ts +33 -0
  83. package/dist/patterns/calendar/calendar-sticky-offset.d.ts +20 -0
  84. package/dist/patterns/calendar/calendar.data.d.ts +17 -0
  85. package/dist/patterns/calendar/calendar.types.d.ts +24 -10
  86. package/dist/patterns/calendar/index.js +1 -1
  87. package/dist/tokens.css +1 -1
  88. package/package.json +1 -1
  89. package/dist/_chunks/booking-B7gA9gFB.js +0 -3017
  90. package/dist/_chunks/calendar-workspace-BB-BZT7W.js +0 -12251
  91. package/dist/_chunks/payment-form-BHMDqW9C.js +0 -767
@@ -1,12 +1,12 @@
1
1
  import { jsxs as m, jsx as r } from "react/jsx-runtime";
2
- import { forwardRef as Te, useContext as Ae, useMemo as b, useState as $, useRef as B, useEffect as ue, useCallback as ce } from "react";
2
+ import { forwardRef as Te, useContext as Ae, useMemo as b, useState as B, useRef as K, useEffect as ue, useCallback as ce } from "react";
3
3
  import { u as $e } from "./registry-DvAUVLHh.js";
4
4
  import { u as Be } from "./use-isomorphic-layout-effect-BGfaCOP1.js";
5
- import * as K from "@radix-ui/react-popover";
5
+ import * as L from "@radix-ui/react-popover";
6
6
  import { R as Ke, _ as N } from "./index-4xgbg-sn.js";
7
7
  import { c as ee } from "./index-D2ZczOXr.js";
8
8
  import { useTranslation as Le } from "react-i18next";
9
- import { getCountries as qe, parsePhoneNumberFromString as L, AsYouType as q, getCountryCallingCode as Me } from "libphonenumber-js/min";
9
+ import { getCountries as qe, parsePhoneNumberFromString as q, AsYouType as M, getCountryCallingCode as Me } from "libphonenumber-js/min";
10
10
  import { u as He, F as _e } from "./form-field-context-B3APVHKx.js";
11
11
  import { c as Ge } from "./compose-refs-C0k0tdqF.js";
12
12
  import { n as J } from "./normalize-diacritics-BNGbFNlJ.js";
@@ -253,7 +253,7 @@ const rt = Te(
253
253
  popularCountries: V,
254
254
  allowedCountries: F,
255
255
  className: ge,
256
- id: M,
256
+ id: H,
257
257
  name: be,
258
258
  required: ye,
259
259
  "aria-label": ve
@@ -265,7 +265,7 @@ const rt = Te(
265
265
  if (!F || F.length === 0) return null;
266
266
  const e = /* @__PURE__ */ new Set(), t = F.filter((n) => !h.has(n) || e.has(n) ? !1 : (e.add(n), !0));
267
267
  return t.length > 0 ? t : null;
268
- }, [F, h]), xe = c !== null && c.length === 1, H = b(() => {
268
+ }, [F, h]), xe = c !== null && c.length === 1, _ = b(() => {
269
269
  const e = me(
270
270
  o,
271
271
  h,
@@ -274,23 +274,23 @@ const rt = Te(
274
274
  c
275
275
  ), t = a ?? l;
276
276
  if (t) {
277
- const n = L(t);
277
+ const n = q(t);
278
278
  return n != null && n.country ? !c || c.includes(n.country) ? {
279
279
  country: n.country,
280
280
  display: n.formatNational(),
281
281
  pinned: !0
282
282
  } : {
283
283
  country: e,
284
- display: new q(e).input(
284
+ display: new M(e).input(
285
285
  n.nationalNumber
286
286
  ),
287
287
  pinned: !0
288
288
  } : { country: e, display: t, pinned: !1 };
289
289
  }
290
290
  return { country: e, display: "", pinned: !1 };
291
- }, []), [u, E] = $(H.country), [te, g] = $(
292
- H.display
293
- ), [_, G] = $(!1), [Ne, ne] = $(""), se = a !== void 0, O = B(""), j = B(null), D = B(H.pinned), T = B(null), we = Ge(Ce, T);
291
+ }, []), [u, E] = B(_.country), [te, g] = B(
292
+ _.display
293
+ ), [G, O] = B(!1), [Ne, ne] = B(""), se = a !== void 0, U = K(""), j = K(null), D = K(_.pinned), T = K(null), we = Ge(Ce, T);
294
294
  ue(() => {
295
295
  if (D.current) return;
296
296
  const e = me(
@@ -310,12 +310,12 @@ const rt = Te(
310
310
  ]), ue(() => {
311
311
  if (!se) return;
312
312
  const e = a ?? "";
313
- if (e === O.current) return;
313
+ if (e === U.current) return;
314
314
  if (e === "") {
315
315
  g("");
316
316
  return;
317
317
  }
318
- const t = L(e);
318
+ const t = q(e);
319
319
  t != null && t.country && (!c || c.includes(t.country)) ? (D.current = !0, E(t.country), g(t.formatNational())) : g(t ? t.formatNational() : e);
320
320
  }, [a, se, c]), Be(() => {
321
321
  if (j.current == null) return;
@@ -326,8 +326,8 @@ const rt = Te(
326
326
  });
327
327
  const C = ce(
328
328
  (e, t) => {
329
- const n = L(e, t), p = (n == null ? void 0 : n.number) ?? "";
330
- O.current = p, i == null || i(p, {
329
+ const n = q(e, t), p = (n == null ? void 0 : n.number) ?? "";
330
+ U.current = p, i == null || i(p, {
331
331
  country: t,
332
332
  isValid: (n == null ? void 0 : n.isValid()) ?? !1,
333
333
  isPossible: (n == null ? void 0 : n.isPossible()) ?? !1,
@@ -335,11 +335,11 @@ const rt = Te(
335
335
  });
336
336
  },
337
337
  [i]
338
- ), ze = M ?? (k ? z.id : void 0), oe = (k ? z.disabled : !1) || !!y, Ie = (k ? z.required : !1) || !!ye, re = k ? z.invalid : !1, Se = re ? "error" : v, Re = k && z.describedBy ? z.describedBy : void 0, ke = he ?? w("inputs.phone.placeholder", "Phone number"), Pe = (e) => {
338
+ ), ze = H ?? (k ? z.id : void 0), oe = (k ? z.disabled : !1) || !!y, Ie = (k ? z.required : !1) || !!ye, re = k ? z.invalid : !1, Se = re ? "error" : v, Re = k && z.describedBy ? z.describedBy : void 0, ke = he ?? w("inputs.phone.placeholder", "Phone number"), Pe = (e) => {
339
339
  if (S) return;
340
- const t = e.target, n = t.value, p = t.selectionStart ?? n.length, I = nt(n, p), Z = new q(u).input(n);
340
+ const t = e.target, n = t.value, p = t.selectionStart ?? n.length, I = nt(n, p), Z = new M(u).input(n);
341
341
  j.current = st(Z, I), g(Z), C(Z, u);
342
- }, ae = O, Ve = b(
342
+ }, ae = U, Ve = b(
343
343
  () => ({
344
344
  getValue: () => ae.current,
345
345
  setValue: (e) => {
@@ -347,11 +347,11 @@ const rt = Te(
347
347
  g(""), C("", u);
348
348
  return;
349
349
  }
350
- const t = L(e);
350
+ const t = q(e);
351
351
  if (t != null && t.country)
352
352
  D.current = !0, E(t.country), g(t.formatNational()), C(t.formatNational(), t.country);
353
353
  else {
354
- const p = new q(u).input(e);
354
+ const p = new M(u).input(e);
355
355
  g(p), C(p, u);
356
356
  }
357
357
  },
@@ -365,14 +365,14 @@ const rt = Te(
365
365
  }),
366
366
  [u, C, ae]
367
367
  );
368
- $e(Ue, Ve, M);
368
+ $e(Ue, Ve, H);
369
369
  const Fe = (e) => {
370
370
  if (e === u) {
371
- G(!1);
371
+ O(!1);
372
372
  return;
373
373
  }
374
- const t = te.replace(/\D/g, ""), n = new q(e), p = t ? n.input(t) : "";
375
- D.current = !0, E(e), g(p), G(!1), ne(""), C(p, e), requestAnimationFrame(() => {
374
+ const t = te.replace(/\D/g, ""), n = new M(e), p = t ? n.input(t) : "";
375
+ D.current = !0, E(e), g(p), O(!1), ne(""), C(p, e), requestAnimationFrame(() => {
376
376
  var I;
377
377
  (I = T.current) == null || I.focus();
378
378
  });
@@ -386,16 +386,16 @@ const rt = Te(
386
386
  if (!V || V.length === 0) return [];
387
387
  const e = new Map(x.map((t) => [t.code, t]));
388
388
  return V.filter((t) => h.has(t)).map((t) => e.get(t)).filter((t) => !!t);
389
- }, [V, x, h]), U = b(
389
+ }, [V, x, h]), W = b(
390
390
  () => new Set(P.map((e) => e.code)),
391
391
  [P]
392
392
  ), Ee = b(
393
- () => U.size > 0 ? x.filter((e) => !U.has(e.code)) : x,
394
- [x, U]
393
+ () => W.size > 0 ? x.filter((e) => !W.has(e.code)) : x,
394
+ [x, W]
395
395
  ), A = b(
396
396
  () => x.find((e) => e.code === u),
397
397
  [x, u]
398
- ), W = A ? A.dialCode : "", ie = A ? A.name : u, Y = w("inputs.phone.countryPickerLabel", "Country"), je = `${Y}: ${ie}, +${W}`, De = ce(
398
+ ), Y = A ? A.dialCode : "", ie = A ? A.name : u, $ = w("inputs.phone.countryPickerLabel", "Country"), je = `${$}: ${ie}, +${Y}`, De = ce(
399
399
  (e, t, n) => {
400
400
  const p = J(e), I = J(t), le = n == null ? void 0 : n.map(J);
401
401
  return Ke(
@@ -431,7 +431,7 @@ const rt = Te(
431
431
  "div",
432
432
  {
433
433
  "data-component": "phone-input",
434
- "data-component-id": M,
434
+ "data-component-id": H,
435
435
  "data-slot": "phone-input",
436
436
  className: We({
437
437
  size: d,
@@ -445,29 +445,29 @@ const rt = Te(
445
445
  "data-slot": "phone-country-fixed",
446
446
  className: `${pe({ size: d })} ds:cursor-default ds:hover:bg-transparent`,
447
447
  children: [
448
- /* @__PURE__ */ r("span", { className: "ds:sr-only", children: `${Y}: ${ie}` }),
448
+ /* @__PURE__ */ r("span", { className: "ds:sr-only", children: `${$}: ${ie}` }),
449
449
  /* @__PURE__ */ r(Q, { country: u, size: X[d] }),
450
450
  /* @__PURE__ */ m("bdi", { dir: "ltr", className: "ds:tabular-nums", children: [
451
451
  "+",
452
- W
452
+ Y
453
453
  ] })
454
454
  ]
455
455
  }
456
- ) : /* @__PURE__ */ m(K.Root, { open: _, onOpenChange: G, children: [
457
- /* @__PURE__ */ r(K.Trigger, { asChild: !0, children: /* @__PURE__ */ m(
456
+ ) : /* @__PURE__ */ m(L.Root, { open: G, onOpenChange: O, children: [
457
+ /* @__PURE__ */ r(L.Trigger, { asChild: !0, children: /* @__PURE__ */ m(
458
458
  "button",
459
459
  {
460
460
  type: "button",
461
461
  disabled: oe,
462
462
  "aria-haspopup": "listbox",
463
- "aria-expanded": _,
463
+ "aria-expanded": G,
464
464
  "aria-label": je,
465
465
  className: pe({ size: d }),
466
466
  children: [
467
467
  /* @__PURE__ */ r(Q, { country: u, size: X[d] }),
468
468
  /* @__PURE__ */ m("bdi", { dir: "ltr", className: "ds:tabular-nums", children: [
469
469
  "+",
470
- W
470
+ Y
471
471
  ] }),
472
472
  /* @__PURE__ */ r(
473
473
  Oe,
@@ -477,18 +477,19 @@ const rt = Te(
477
477
  tt[d],
478
478
  "ds:shrink-0 ds:text-muted-foreground",
479
479
  "ds:transition-transform ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none",
480
- _ ? "ds:rotate-180" : ""
480
+ G ? "ds:rotate-180" : ""
481
481
  ].join(" ")
482
482
  }
483
483
  )
484
484
  ]
485
485
  }
486
486
  ) }),
487
- /* @__PURE__ */ r(K.Portal, { children: /* @__PURE__ */ r(
488
- K.Content,
487
+ /* @__PURE__ */ r(L.Portal, { children: /* @__PURE__ */ r(
488
+ L.Content,
489
489
  {
490
490
  sideOffset: 6,
491
491
  align: "start",
492
+ "aria-label": $,
492
493
  className: Ze,
493
494
  children: /* @__PURE__ */ m(
494
495
  N,
@@ -496,7 +497,7 @@ const rt = Te(
496
497
  filter: De,
497
498
  shouldFilter: !0,
498
499
  loop: !0,
499
- label: Y,
500
+ label: $,
500
501
  children: [
501
502
  /* @__PURE__ */ r(
502
503
  N.Input,
@@ -577,4 +578,4 @@ export {
577
578
  pe as c,
578
579
  We as p
579
580
  };
580
- //# sourceMappingURL=phone-input-BsZIoE36.js.map
581
+ //# sourceMappingURL=phone-input-IWrGOCwm.js.map
@@ -176,6 +176,7 @@ const K = [
176
176
  value: w(n),
177
177
  onValueChange: I,
178
178
  collapsible: !1,
179
+ role: "group",
179
180
  "aria-label": V,
180
181
  id: x,
181
182
  "data-component": "stepper-accordion",
@@ -247,4 +248,4 @@ oe.displayName = "StepperAccordion";
247
248
  export {
248
249
  oe as S
249
250
  };
250
- //# sourceMappingURL=stepper-accordion-DmVykr5F.js.map
251
+ //# sourceMappingURL=stepper-accordion-jMR8NaOB.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "1.46.0",
3
+ "packageVersion": "1.47.0",
4
4
  "components": [
5
5
  {
6
6
  "kind": "component",
@@ -1295,7 +1295,8 @@
1295
1295
  "safety": "destructive",
1296
1296
  "idempotent": true,
1297
1297
  "errors": [
1298
- "Resetting after submit has no effect — the flow is on step 8."
1298
+ "Resetting after submit has no effect — the flow is on step 8.",
1299
+ "Refused while a payment session is open (step 7): the consumer must cancel the hold first."
1299
1300
  ],
1300
1301
  "description": "Clear the booking value back to an empty state. Use to abandon an in-progress flow.",
1301
1302
  "descriptionKey": "ui.agent.booking.actions.reset"
@@ -8931,7 +8932,7 @@
8931
8932
  {
8932
8933
  "name": "complete",
8933
8934
  "type": "boolean",
8934
- "description": "True when Stripe reports the payment fields as complete. Read this before `submit` — outside preview mode the submit control is disabled while it is false, so the call will not be accepted.",
8935
+ "description": "True when Stripe reports the payment fields, and any required billing address, as complete. Read this before `submit` — outside preview mode the submit control is disabled while it is false, so the call will not be accepted.",
8935
8936
  "descriptionKey": "ui.agent.paymentForm.state.complete"
8936
8937
  },
8937
8938
  {
@@ -8966,7 +8967,7 @@
8966
8967
  "name": "reset",
8967
8968
  "safety": "destructive",
8968
8969
  "idempotent": true,
8969
- "description": "Reset the form to its initial state. Loses any in-progress input, and discards the previous attempt — `status` returns to \"idle\" and `errorKey` / `paymentIntentId` to null.",
8970
+ "description": "Clear recoverable errors and return their status to \"idle\". Stripe fields remain unchanged. Pending or paid attempts cannot be reset and require a new session.",
8970
8971
  "descriptionKey": "ui.agent.paymentForm.actions.reset"
8971
8972
  }
8972
8973
  ],
@@ -942,13 +942,13 @@
942
942
  "paymentForm": {
943
943
  "state": {
944
944
  "status": "Lifecycle of the current payment attempt. `succeeded` is only reached once Stripe confirmed the PaymentIntent; `failed` covers validation, decline and processor errors alike. Still `idle` after `submit` means the attempt never fired — Stripe had not mounted.",
945
- "complete": "True when Stripe reports the payment fields as complete. Read this before `submit` — outside preview mode the submit control is disabled while it is false, so the call will not be accepted.",
945
+ "complete": "True when Stripe reports the payment fields, and any required billing address, as complete. Read this before `submit` — outside preview mode the submit control is disabled while it is false, so the call will not be accepted.",
946
946
  "errorKey": "i18n key of the current error (e.g. `payment.error.cardDeclined`), or null. The key is the structural datum — the translated message is free text and is never exposed.",
947
947
  "paymentIntentId": "Opaque Stripe PaymentIntent id once a charge succeeded, else null. The receipt — the attribution handle for the money that moved. Never the client secret."
948
948
  },
949
949
  "actions": {
950
950
  "submit": "Submit the payment. Charges the configured payment method — irreversible. Resolves once the attempt has settled; the outcome is never in the resolved value, so read `status`, then `errorKey` on failure or `paymentIntentId` on success.",
951
- "reset": "Reset the form to its initial state. Loses any in-progress input, and discards the previous attempt — `status` returns to \"idle\" and `errorKey` / `paymentIntentId` to null."
951
+ "reset": "Clear recoverable errors and return their status to \"idle\". Stripe fields remain unchanged. Pending or paid attempts cannot be reset and require a new session."
952
952
  }
953
953
  },
954
954
  "pdfViewer": {
@@ -13,6 +13,48 @@ export interface BookingSpecialty {
13
13
  /** Restrict to operators-on-page when lockedOperatorId is set. */
14
14
  operatorIds?: string[];
15
15
  }
16
+ /**
17
+ * One appointment payment, in currency minor units. Set it only when the
18
+ * platform AppointmentBookingReason.requireAdvancePayment is true.
19
+ */
20
+ export interface BookingServicePayment {
21
+ /** No platform field: the consumer derives it, e.g. deposit when advanceAmount < price. */
22
+ kind: 'full' | 'deposit';
23
+ /** Platform advanceAmount (euros) x 100. NOT price, which only feeds priceLabel. */
24
+ amountCents: number;
25
+ /** Defaults to EUR, the only currency production charges. */
26
+ currencyCode?: string;
27
+ }
28
+ export interface BookingResolvedPayment extends BookingServicePayment {
29
+ serviceId: string;
30
+ currencyCode: string;
31
+ }
32
+ export interface BookingPaymentSession {
33
+ /** Opaque hold identity. Keep Stripe credentials in the consumer, keyed by this id. */
34
+ id: string;
35
+ payment: BookingResolvedPayment;
36
+ }
37
+ export interface BookingSubmitResult {
38
+ paymentSession: BookingPaymentSession;
39
+ }
40
+ export type BookingPaymentState = {
41
+ sessionId: string;
42
+ status: 'ready' | 'cancelled' | 'paid';
43
+ } | {
44
+ sessionId: string;
45
+ status: 'processing';
46
+ phase: 'payment' | 'completion';
47
+ } | {
48
+ sessionId: string;
49
+ status: 'failed';
50
+ phase: 'payment' | 'completion';
51
+ error?: ReactNode;
52
+ };
53
+ export interface BookingPaymentRenderContext {
54
+ session: BookingPaymentSession;
55
+ payment: BookingResolvedPayment;
56
+ state: BookingPaymentState;
57
+ }
16
58
  export interface BookingService {
17
59
  id: string;
18
60
  label: string;
@@ -27,6 +69,8 @@ export interface BookingService {
27
69
  * string verbatim. Added in 1.6.0.
28
70
  */
29
71
  priceLabel?: string;
72
+ /** Mandatory online payment for this service only. Never inferred from priceLabel. */
73
+ payment?: BookingServicePayment;
30
74
  /** Required when useSpecialties is true. */
31
75
  specialtyId?: string;
32
76
  /** Operators who can perform this service. */
@@ -50,6 +94,8 @@ export interface BookingOperator {
50
94
  export interface BookingSlot {
51
95
  /** Opaque unique key within `availableSlots[date]`. */
52
96
  key: string;
97
+ /** Actual service booked when serviceIds contains several search alternatives. */
98
+ serviceId?: string;
53
99
  /** HH:mm 24h — used for display. */
54
100
  time: string;
55
101
  available: boolean;
@@ -70,6 +116,8 @@ export interface BookingDetails {
70
116
  * only when the service carries that text; omitted otherwise.
71
117
  */
72
118
  criticalInformationAccepted?: boolean;
119
+ /** Included only when the patient accepts this service's payment quote. */
120
+ paymentAccepted?: boolean;
73
121
  codiceFiscale?: string;
74
122
  dateOfBirth?: string;
75
123
  insuranceNumber?: string;
@@ -122,6 +170,7 @@ export interface BookingSubmitPayload {
122
170
  value: BookingValue;
123
171
  /** Fully populated + validated (privacy + terms ticked, required fields filled). */
124
172
  details: BookingDetails;
173
+ payment?: BookingResolvedPayment;
125
174
  }
126
175
  export interface BookingValidationResult {
127
176
  valid: boolean;
@@ -179,6 +228,16 @@ export interface BookingProps extends Omit<ComponentPropsWithoutRef<'div'>, 'ari
179
228
  showReturningPatientFlag?: boolean;
180
229
  privacyPolicyUrl?: string;
181
230
  termsUrl?: string;
231
+ paymentTermsUrl?: string;
232
+ /** Publish paid only after the server verifies payment AND saves the appointment. */
233
+ paymentState?: BookingPaymentState;
234
+ /** Render PaymentForm here. The consumer owns Stripe credentials and completion calls. */
235
+ renderPayment?: (context: BookingPaymentRenderContext) => ReactNode;
236
+ /**
237
+ * Completion retry only: never render card entry or start another payment here.
238
+ * Supply it with renderPayment; without it a failed completion shows only the error.
239
+ */
240
+ renderPaymentCompletion?: (context: BookingPaymentRenderContext) => ReactNode;
182
241
  validateCodiceFiscale?: BookingValidator;
183
242
  validateInsuranceNumber?: BookingValidator;
184
243
  /** Default: false. Specialty auto-select on length=1 is always on. */
@@ -198,7 +257,7 @@ export interface BookingProps extends Omit<ComponentPropsWithoutRef<'div'>, 'ari
198
257
  defaultConfirmationChannels?: ConfirmationChannel[];
199
258
  value: BookingValue;
200
259
  onChange: (next: BookingValue) => void;
201
- onSubmit: (payload: BookingSubmitPayload) => void | Promise<void>;
260
+ onSubmit: (payload: BookingSubmitPayload) => void | BookingSubmitResult | Promise<void | BookingSubmitResult>;
202
261
  /**
203
262
  * Calendar/date-strip shimmer — set true while `availableDates` is being
204
263
  * fetched. When omitted, the kit falls back to `loadingSlots` for the
@@ -1,5 +1,5 @@
1
1
  import type { BookingProps } from './booking-types';
2
- export type { BookingDetails, BookingHandle, BookingOperator, BookingProps, BookingService, BookingSlot, BookingSpecialty, BookingSubmitPayload, BookingValidationResult, BookingValidator, BookingValue, BookingVariant, ConfirmationChannel, InsuranceType, } from './booking-types';
2
+ export type { BookingPaymentSession, BookingPaymentState, BookingPaymentRenderContext, BookingSubmitResult, BookingServicePayment, BookingResolvedPayment, BookingDetails, BookingHandle, BookingOperator, BookingProps, BookingService, BookingSlot, BookingSpecialty, BookingSubmitPayload, BookingValidationResult, BookingValidator, BookingValue, BookingVariant, ConfirmationChannel, InsuranceType, } from './booking-types';
3
3
  export { CONFIRMATION_CHANNEL_ORDER } from './booking-types';
4
4
  export { OPERATORS_ALL } from './cascade';
5
5
  export declare const Booking: import("react").ForwardRefExoticComponent<BookingProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
- import type { BookingDetails, BookingValidator, ConfirmationChannel } from './booking-types';
2
+ import type { BookingDetails, BookingResolvedPayment, BookingValidator, ConfirmationChannel } from './booking-types';
3
3
  export interface BookingDetailsFormProps {
4
4
  value: Partial<BookingDetails>;
5
5
  onChange: (next: Partial<BookingDetails>) => void;
@@ -13,6 +13,10 @@ export interface BookingDetailsFormProps {
13
13
  showReturningPatientFlag?: boolean;
14
14
  privacyPolicyUrl?: string;
15
15
  termsUrl?: string;
16
+ payment?: BookingResolvedPayment;
17
+ paymentTermsUrl?: string;
18
+ /** Prevent submit when the selected service's payment cannot be resolved. */
19
+ paymentBlocked?: boolean;
16
20
  /**
17
21
  * The selected service's `criticalInformationToAccept`. When set (and not
18
22
  * blank), a "Before you book" block renders above the consents and the
@@ -1,5 +1,5 @@
1
1
  export { Booking } from './booking';
2
- export type { BookingProps, BookingHandle, BookingVariant, BookingValue, BookingService, BookingSpecialty, BookingSlot, BookingOperator, BookingDetails, BookingSubmitPayload, BookingValidator, BookingValidationResult, ConfirmationChannel, InsuranceType, } from './booking';
2
+ export type { BookingPaymentSession, BookingPaymentState, BookingPaymentRenderContext, BookingSubmitResult, BookingServicePayment, BookingResolvedPayment, BookingProps, BookingHandle, BookingVariant, BookingValue, BookingService, BookingSpecialty, BookingSlot, BookingOperator, BookingDetails, BookingSubmitPayload, BookingValidator, BookingValidationResult, ConfirmationChannel, InsuranceType, } from './booking';
3
3
  export { CONFIRMATION_CHANNEL_ORDER, OPERATORS_ALL } from './booking';
4
4
  export { bookingAgent } from './booking.agent';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,4 @@
1
- import { B as A, C as R, O as a, b as s } from "../../_chunks/booking-B7gA9gFB.js";
1
+ import { B as A, C as R, O as a, b as s } from "../../_chunks/booking-C4MwImkS.js";
2
2
  export {
3
3
  A as Booking,
4
4
  R as CONFIRMATION_CHANNEL_ORDER,
@@ -0,0 +1,9 @@
1
+ import type { BookingResolvedPayment, BookingService, BookingSlot } from './booking-types';
2
+ export declare function resolveServicePayment(service: BookingService): BookingResolvedPayment | undefined;
3
+ /** Selected services are search alternatives, never a shopping basket. */
4
+ export declare function resolveBookingPayment(services: BookingService[], serviceIds: string[], slot?: BookingSlot): {
5
+ payment?: BookingResolvedPayment;
6
+ blocked: boolean;
7
+ };
8
+ export declare function paymentIdentity(payment?: BookingResolvedPayment): string;
9
+ //# sourceMappingURL=payment.d.ts.map
@@ -0,0 +1,14 @@
1
+ import type { BookingDetails, BookingPaymentSession, BookingProps, BookingSubmitPayload } from './booking-types';
2
+ export declare function useBookingPayment({ services, value, availableSlots, onSubmit, onChange, paymentState, submitting, paymentTermsUrl, renderPayment, }: Pick<BookingProps, 'services' | 'value' | 'availableSlots' | 'onSubmit' | 'onChange' | 'paymentState' | 'submitting' | 'paymentTermsUrl' | 'renderPayment'>): {
3
+ payment: import("./booking-types").BookingResolvedPayment | undefined;
4
+ blocked: boolean;
5
+ state: import("./booking-types").BookingPaymentState | undefined;
6
+ activeSession: BookingPaymentSession | undefined;
7
+ submit: (details: BookingDetails) => Promise<void>;
8
+ reset: () => void;
9
+ status: "idle" | "submitting" | "payment" | "success" | "error";
10
+ snapshot?: BookingSubmitPayload;
11
+ session?: BookingPaymentSession;
12
+ cancelled?: boolean;
13
+ };
14
+ //# sourceMappingURL=use-booking-payment.d.ts.map
@@ -1,4 +1,4 @@
1
- import { F as m, f as l } from "../../_chunks/freemium-paywall-Cz-O9lQD.js";
1
+ import { F as m, f as l } from "../../_chunks/freemium-paywall-BaW5ODc9.js";
2
2
  export {
3
3
  m as FreemiumPaywall,
4
4
  l as freemiumPaywallAgent
@@ -1,4 +1,4 @@
1
- import { P as e, p as i } from "../../_chunks/patient-details-DUj1htsH.js";
1
+ import { P as e, p as i } from "../../_chunks/patient-details-yrgkSeEY.js";
2
2
  export {
3
3
  e as PatientDetails,
4
4
  i as patientDetailsAgent
@@ -1,4 +1,4 @@
1
- import { P as t, p as m } from "../../_chunks/patient-summary-card-DNzdYjxE.js";
1
+ import { P as t, p as m } from "../../_chunks/patient-summary-card-CmEFflGS.js";
2
2
  export {
3
3
  t as PatientSummaryCard,
4
4
  m as patientSummaryCardAgent
@@ -1,4 +1,4 @@
1
1
  export { PaymentForm, formatPaymentAmount, stripCardLikeDigits, stripeErrorCodeToI18nKey, paymentFormVariants, paymentSubmitButtonVariants, } from './payment-form';
2
- export type { PaymentFormProps, PaymentFormHandle, PaymentFormStatus, PaymentCurrency, } from './payment-form';
2
+ export type { PaymentFormProps, PaymentFormHandle, PaymentFormStatus, PaymentFormIntentStatus, PaymentFormBillingDetails, PaymentCurrency, } from './payment-form';
3
3
  export { paymentFormAgent } from './payment-form.agent';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,4 @@
1
- import { P as r, f as s, p as m, a as e, s as n, b as o, c as i } from "../../_chunks/payment-form-BHMDqW9C.js";
1
+ import { P as r, f as s, p as m, a as e, s as n, b as o, c as i } from "../../_chunks/payment-form-DqJFiplX.js";
2
2
  export {
3
3
  r as PaymentForm,
4
4
  s as formatPaymentAmount,
@@ -1,5 +1,19 @@
1
- import { type Stripe } from '@stripe/stripe-js';
1
+ import type { Stripe } from '@stripe/stripe-js';
2
2
  export type PaymentCurrency = string;
3
+ /** Stripe's known PaymentIntent states. Only `succeeded` means paid. */
4
+ export type PaymentFormIntentStatus = 'requires_payment_method' | 'requires_confirmation' | 'requires_action' | 'processing' | 'requires_capture' | 'canceled' | 'succeeded';
5
+ /** Complete invoicing address only. Never contains card details. */
6
+ export interface PaymentFormBillingDetails {
7
+ name: string;
8
+ address: {
9
+ line1: string;
10
+ line2: string | null;
11
+ city: string;
12
+ state: string;
13
+ postalCode: string;
14
+ country: string;
15
+ };
16
+ }
3
17
  export interface PaymentFormProps {
4
18
  /** Opaque instance id — emitted as `data-component-id` for the agent registry. */
5
19
  id?: string;
@@ -18,6 +32,8 @@ export interface PaymentFormProps {
18
32
  * own intent type wins). Defaults to `'payment'`.
19
33
  */
20
34
  mode?: 'payment' | 'setup';
35
+ /** Restrict deferred Elements to cards. With a client secret, the server intent controls methods. */
36
+ cardOnly?: boolean;
21
37
  /**
22
38
  * Deferred-confirm callback. Called at submit time (after client-side
23
39
  * field validation succeeds) so your server can mint a PaymentIntent and
@@ -27,14 +43,20 @@ export interface PaymentFormProps {
27
43
  * charge is attempted.
28
44
  */
29
45
  onCreatePaymentIntent?: () => Promise<string>;
46
+ /** Preview-only validation completed. Awaited without creating or confirming a payment. */
47
+ onPreviewValidated?: () => void | Promise<void>;
30
48
  /** Stripe publishable key (`pk_test_…` / `pk_live_…`). */
31
49
  publishableKey: string;
50
+ /** Connected account used to create the intent. Ignored by an injected Stripe instance. */
51
+ stripeAccount?: string;
32
52
  /** ISO-4217 currency code (e.g. 'EUR', 'USD', 'JPY'). */
33
53
  currency: PaymentCurrency;
34
54
  /** Amount in the currency's smallest unit (cents for EUR/USD, yen for JPY). */
35
55
  amount: number;
36
56
  /** Called with the PaymentIntent id on successful confirmation. */
37
57
  onSuccess?: (paymentIntentId: string) => void;
58
+ /** Observes confirmed intent states, including payments still awaiting completion. */
59
+ onPaymentStatusChange?: (status: PaymentFormIntentStatus, paymentIntentId: string) => void;
38
60
  /** Called with a sanitised error (no PAN digits, no Stripe English strings). */
39
61
  onError?: (error: {
40
62
  code: string;
@@ -42,6 +64,16 @@ export interface PaymentFormProps {
42
64
  }) => void;
43
65
  /** Show the billing-address collector below the payment fields. */
44
66
  billingAddress?: boolean;
67
+ /** Show and require a complete billing address before confirming payment. */
68
+ requireBillingAddress?: boolean;
69
+ /** Initial name/address for each Elements session. Does not enable or validate the collector. */
70
+ defaultBillingDetails?: PaymentFormBillingDetails;
71
+ /**
72
+ * Save complete billing details before confirmation or any redirect. Enables
73
+ * the address collector; rejection blocks payment and permits a retry.
74
+ * Not called in validation-only preview mode. Never logs or stores details.
75
+ */
76
+ onBillingDetails?: (details: PaymentFormBillingDetails) => void | Promise<void>;
45
77
  /** Locale override — defaults to the active i18next locale. */
46
78
  locale?: string;
47
79
  /** Accessible label for the form. */
@@ -72,12 +104,12 @@ export interface PaymentFormHandle {
72
104
  * `getStatus()` / `getErrorKey()` afterwards for the outcome.
73
105
  */
74
106
  submit: () => Promise<void>;
75
- /** Reset the form to its initial state. */
107
+ /** Clear recoverable errors. A pending or paid attempt requires a new session. */
76
108
  reset: () => void;
77
109
  /** Lifecycle of the current attempt. */
78
110
  getStatus: () => PaymentFormStatus;
79
111
  /**
80
- * True when Stripe reports the payment fields as complete. `submit`
112
+ * True when Stripe reports the payment fields, and any required billing address, as complete. `submit`
81
113
  * is refused (the button is disabled) while this is false outside
82
114
  * preview mode.
83
115
  */
@@ -1,4 +1,4 @@
1
- import { P as n, c as p, p as t, a as e } from "../../_chunks/phone-input-BsZIoE36.js";
1
+ import { P as n, c as p, p as t, a as e } from "../../_chunks/phone-input-IWrGOCwm.js";
2
2
  export {
3
3
  n as PhoneInput,
4
4
  p as countryTriggerVariants,
@@ -1,4 +1,4 @@
1
- import { S as e } from "../../_chunks/stepper-accordion-DmVykr5F.js";
1
+ import { S as e } from "../../_chunks/stepper-accordion-jMR8NaOB.js";
2
2
  import { s as t } from "../../_chunks/stepper-accordion.agent-cmEguIdx.js";
3
3
  export {
4
4
  e as StepperAccordion,