@alfadocs/ui-kit-debug 1.19.0 → 1.21.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 (123) hide show
  1. package/dist/_chunks/{anamnesis-summary-rows-CRWO8x8g.js → anamnesis-summary-rows-DwjqZgR5.js} +3 -3
  2. package/dist/_chunks/{anamnesis-summary-rows-CRWO8x8g.js.map → anamnesis-summary-rows-DwjqZgR5.js.map} +1 -1
  3. package/dist/_chunks/{antenatal-schedule-timeline-B1k8QkA6.js → antenatal-schedule-timeline-sXfIp5lp.js} +3 -3
  4. package/dist/_chunks/{antenatal-schedule-timeline-B1k8QkA6.js.map → antenatal-schedule-timeline-sXfIp5lp.js.map} +1 -1
  5. package/dist/_chunks/{appointment-timeline-DCn0Jx55.js → appointment-timeline-DhHwmHo1.js} +2 -2
  6. package/dist/_chunks/{appointment-timeline-DCn0Jx55.js.map → appointment-timeline-DhHwmHo1.js.map} +1 -1
  7. package/dist/_chunks/{balance-badge-cell-DNjHODfP.js → balance-badge-cell-Bh2QbxsZ.js} +47 -46
  8. package/dist/_chunks/balance-badge-cell-Bh2QbxsZ.js.map +1 -0
  9. package/dist/_chunks/{booking-DQbo6mQF.js → booking-WXKbA69C.js} +4 -4
  10. package/dist/_chunks/{booking-DQbo6mQF.js.map → booking-WXKbA69C.js.map} +1 -1
  11. package/dist/_chunks/{calendar-workspace-BAouFiA5.js → calendar-workspace-CB6KLoF6.js} +87 -73
  12. package/dist/_chunks/{calendar-workspace-BAouFiA5.js.map → calendar-workspace-CB6KLoF6.js.map} +1 -1
  13. package/dist/_chunks/{care-plan-card-D-FMfDKH.js → care-plan-card-CQVboTn1.js} +2 -2
  14. package/dist/_chunks/{care-plan-card-D-FMfDKH.js.map → care-plan-card-CQVboTn1.js.map} +1 -1
  15. package/dist/_chunks/{care-plan-entry-card-Bvw_9T-d.js → care-plan-entry-card-jxHkzez5.js} +2 -2
  16. package/dist/_chunks/{care-plan-entry-card-Bvw_9T-d.js.map → care-plan-entry-card-jxHkzez5.js.map} +1 -1
  17. package/dist/_chunks/{cycle-calculator-DmtYGhqq.js → cycle-calculator-DVgxBfP0.js} +3 -3
  18. package/dist/_chunks/{cycle-calculator-DmtYGhqq.js.map → cycle-calculator-DVgxBfP0.js.map} +1 -1
  19. package/dist/_chunks/{data-table-DC5rO3Ty.js → data-table-Bw3i0753.js} +253 -249
  20. package/dist/_chunks/{data-table-DC5rO3Ty.js.map → data-table-Bw3i0753.js.map} +1 -1
  21. package/dist/_chunks/{data-table-tabs-D24qj89A.js → data-table-tabs-DVIFkqx_.js} +2 -2
  22. package/dist/_chunks/{data-table-tabs-D24qj89A.js.map → data-table-tabs-DVIFkqx_.js.map} +1 -1
  23. package/dist/_chunks/{date-picker-CepI_oI2.js → date-picker-B6NW_PS5.js} +3 -3
  24. package/dist/_chunks/{date-picker-CepI_oI2.js.map → date-picker-B6NW_PS5.js.map} +1 -1
  25. package/dist/_chunks/{date-picker-variants-DfuooXEK.js → date-picker-variants-B9NLAfUK.js} +5 -2
  26. package/dist/_chunks/{date-picker-variants-DfuooXEK.js.map → date-picker-variants-B9NLAfUK.js.map} +1 -1
  27. package/dist/_chunks/{date-range-picker-BD8P_rJq.js → date-range-picker-TpmECKRh.js} +197 -196
  28. package/dist/_chunks/date-range-picker-TpmECKRh.js.map +1 -0
  29. package/dist/_chunks/{date-time-picker-3I2vVKGV.js → date-time-picker-DijEae25.js} +2 -2
  30. package/dist/_chunks/{date-time-picker-3I2vVKGV.js.map → date-time-picker-DijEae25.js.map} +1 -1
  31. package/dist/_chunks/{due-date-calculator-BF_Ikofx.js → due-date-calculator-BtgWeFqp.js} +4 -4
  32. package/dist/_chunks/{due-date-calculator-BF_Ikofx.js.map → due-date-calculator-BtgWeFqp.js.map} +1 -1
  33. package/dist/_chunks/{field-value-D-vkX9uL.js → field-value-BetdWMA2.js} +2 -2
  34. package/dist/_chunks/{field-value-D-vkX9uL.js.map → field-value-BetdWMA2.js.map} +1 -1
  35. package/dist/_chunks/{file-manager-spc3_khe.js → file-manager-BdXjZNIc.js} +2 -2
  36. package/dist/_chunks/{file-manager-spc3_khe.js.map → file-manager-BdXjZNIc.js.map} +1 -1
  37. package/dist/_chunks/{gestational-age-calculator-CiOQjzgx.js → gestational-age-calculator-KdMg9z9H.js} +5 -5
  38. package/dist/_chunks/{gestational-age-calculator-CiOQjzgx.js.map → gestational-age-calculator-KdMg9z9H.js.map} +1 -1
  39. package/dist/_chunks/{hcg-doubling-CpU7H5rQ.js → hcg-doubling-C2fQxfXd.js} +3 -3
  40. package/dist/_chunks/{hcg-doubling-CpU7H5rQ.js.map → hcg-doubling-C2fQxfXd.js.map} +1 -1
  41. package/dist/_chunks/{header-settings-J-ZCAfir.js → header-settings-DvjZNMhD.js} +2 -2
  42. package/dist/_chunks/{header-settings-J-ZCAfir.js.map → header-settings-DvjZNMhD.js.map} +1 -1
  43. package/dist/_chunks/{icon-picker-ChzpCnZ-.js → icon-picker-DOa89vn3.js} +2 -2
  44. package/dist/_chunks/{icon-picker-ChzpCnZ-.js.map → icon-picker-DOa89vn3.js.map} +1 -1
  45. package/dist/_chunks/{info-tip-C119cwQl.js → info-tip-CADik6WN.js} +2 -2
  46. package/dist/_chunks/{info-tip-C119cwQl.js.map → info-tip-CADik6WN.js.map} +1 -1
  47. package/dist/_chunks/{link-cell-renderer-B-xrUPew.js → link-cell-renderer-tWEOv3Sc.js} +6 -4
  48. package/dist/_chunks/link-cell-renderer-tWEOv3Sc.js.map +1 -0
  49. package/dist/_chunks/{locale-picker-BvbVjDQ-.js → locale-picker-CwFtqSkt.js} +2 -2
  50. package/dist/_chunks/{locale-picker-BvbVjDQ-.js.map → locale-picker-CwFtqSkt.js.map} +1 -1
  51. package/dist/_chunks/{marketplace-app-shell-DDQXQ8hX.js → marketplace-app-shell-C4AjQmvz.js} +2 -2
  52. package/dist/_chunks/{marketplace-app-shell-DDQXQ8hX.js.map → marketplace-app-shell-C4AjQmvz.js.map} +1 -1
  53. package/dist/_chunks/{notes-panel-DYAtlq_i.js → notes-panel-CTNpsByN.js} +2 -2
  54. package/dist/_chunks/{notes-panel-DYAtlq_i.js.map → notes-panel-CTNpsByN.js.map} +1 -1
  55. package/dist/_chunks/{parse-MN9bGkrY.js → parse-DPqj4JtD.js} +2 -2
  56. package/dist/_chunks/{parse-MN9bGkrY.js.map → parse-DPqj4JtD.js.map} +1 -1
  57. package/dist/_chunks/{patient-details-BfzvFnxQ.js → patient-details-DYAmq76G.js} +3 -3
  58. package/dist/_chunks/{patient-details-BfzvFnxQ.js.map → patient-details-DYAmq76G.js.map} +1 -1
  59. package/dist/_chunks/{patient-summary-card-D5Vfa321.js → patient-summary-card-C9WBwct-.js} +2 -2
  60. package/dist/_chunks/{patient-summary-card-D5Vfa321.js.map → patient-summary-card-C9WBwct-.js.map} +1 -1
  61. package/dist/_chunks/{popover-Cqcjx-Ny.js → popover-DP6WCVwm.js} +2 -2
  62. package/dist/_chunks/{popover-Cqcjx-Ny.js.map → popover-DP6WCVwm.js.map} +1 -1
  63. package/dist/_chunks/{pregnancy-dating-D2wchD11.js → pregnancy-dating-m-c05DOI.js} +5 -5
  64. package/dist/_chunks/{pregnancy-dating-D2wchD11.js.map → pregnancy-dating-m-c05DOI.js.map} +1 -1
  65. package/dist/_chunks/{radiograph-panel.agent-C3trfWqB.js → radiograph-panel.agent-ByM9M3qm.js} +3 -3
  66. package/dist/_chunks/{radiograph-panel.agent-C3trfWqB.js.map → radiograph-panel.agent-ByM9M3qm.js.map} +1 -1
  67. package/dist/_chunks/{rich-text-editor-DtbcA6s1.js → rich-text-editor-lSCiE0Zz.js} +2 -2
  68. package/dist/_chunks/{rich-text-editor-DtbcA6s1.js.map → rich-text-editor-lSCiE0Zz.js.map} +1 -1
  69. package/dist/_chunks/{signature-request-CUe903hj.js → signature-request-CwlAmVLw.js} +2 -2
  70. package/dist/_chunks/{signature-request-CUe903hj.js.map → signature-request-CwlAmVLw.js.map} +1 -1
  71. package/dist/_chunks/subDays-HPvBuvq3.js +8 -0
  72. package/dist/_chunks/{subDays-BLl3y3pd.js.map → subDays-HPvBuvq3.js.map} +1 -1
  73. package/dist/_chunks/{tooth-scheme-2IsmbE6w.js → tooth-scheme-C9jssOmy.js} +2 -2
  74. package/dist/_chunks/{tooth-scheme-2IsmbE6w.js.map → tooth-scheme-C9jssOmy.js.map} +1 -1
  75. package/dist/agent-catalog.json +1 -1
  76. package/dist/components/_shared/calendar-class-names.d.ts.map +1 -1
  77. package/dist/components/appointment-timeline/index.js +1 -1
  78. package/dist/components/booking/index.js +1 -1
  79. package/dist/components/care-plan-card/index.js +1 -1
  80. package/dist/components/care-plan-entry-card/index.js +1 -1
  81. package/dist/components/cycle-calculator/index.js +1 -1
  82. package/dist/components/data-table/data-table.d.ts.map +1 -1
  83. package/dist/components/data-table/filters/date-range-filter.d.ts.map +1 -1
  84. package/dist/components/data-table/index.js +2 -2
  85. package/dist/components/data-table/toolbar.d.ts.map +1 -1
  86. package/dist/components/data-table-tabs/index.js +1 -1
  87. package/dist/components/date-picker/index.js +1 -1
  88. package/dist/components/date-range-picker/date-range-picker.d.ts +6 -0
  89. package/dist/components/date-range-picker/date-range-picker.d.ts.map +1 -1
  90. package/dist/components/date-range-picker/index.js +1 -1
  91. package/dist/components/date-time-picker/index.js +1 -1
  92. package/dist/components/due-date-calculator/index.js +2 -2
  93. package/dist/components/file-manager/index.js +1 -1
  94. package/dist/components/gestational-age-calculator/index.js +1 -1
  95. package/dist/components/hcg-doubling/index.js +1 -1
  96. package/dist/components/header-settings/index.js +1 -1
  97. package/dist/components/icon-picker/index.js +1 -1
  98. package/dist/components/info-tip/index.js +1 -1
  99. package/dist/components/locale-picker/index.js +1 -1
  100. package/dist/components/notes-panel/index.js +1 -1
  101. package/dist/components/patient-details/index.js +1 -1
  102. package/dist/components/patient-summary-card/index.js +1 -1
  103. package/dist/components/patient-table/columns.d.ts +10 -3
  104. package/dist/components/patient-table/columns.d.ts.map +1 -1
  105. package/dist/components/patient-table/index.js +1 -1
  106. package/dist/components/popover/index.js +1 -1
  107. package/dist/components/popover/popover.d.ts +1 -1
  108. package/dist/components/popover/popover.d.ts.map +1 -1
  109. package/dist/components/pregnancy-dating/index.js +1 -1
  110. package/dist/components/radiograph-panel/index.js +1 -1
  111. package/dist/components/rich-text-editor/index.js +1 -1
  112. package/dist/components/tooth-scheme/index.js +1 -1
  113. package/dist/index.js +31 -31
  114. package/dist/patterns/anamnesis/index.js +1 -1
  115. package/dist/patterns/calendar/calendar.surface.d.ts.map +1 -1
  116. package/dist/patterns/calendar/index.js +1 -1
  117. package/dist/patterns/marketplace-app-shell/index.js +1 -1
  118. package/dist/patterns/signature-request/index.js +1 -1
  119. package/package.json +1 -1
  120. package/dist/_chunks/balance-badge-cell-DNjHODfP.js.map +0 -1
  121. package/dist/_chunks/date-range-picker-BD8P_rJq.js.map +0 -1
  122. package/dist/_chunks/link-cell-renderer-B-xrUPew.js.map +0 -1
  123. package/dist/_chunks/subDays-BLl3y3pd.js +0 -8
@@ -7,7 +7,7 @@ import { P as A } from "./progress-CK8otcQ-.js";
7
7
  import { T as C } from "./timestamp-BV2lC-wV.js";
8
8
  import { T as L } from "./transaction-chip-DJCstquX.js";
9
9
  import { A as O, b as G, c as Y, a as $ } from "./accordion-C11v9ouP.js";
10
- import { C as q } from "./care-plan-entry-card-Bvw_9T-d.js";
10
+ import { C as q } from "./care-plan-entry-card-jxHkzez5.js";
11
11
  import { u as J } from "./registry-DvAUVLHh.js";
12
12
  import { C as Q, e as W } from "./entity-card-DmrgYSEX.js";
13
13
  import { i as X } from "./is-safe-url-DkETxeHz.js";
@@ -253,4 +253,4 @@ export {
253
253
  de as C,
254
254
  Z as c
255
255
  };
256
- //# sourceMappingURL=care-plan-card-D-FMfDKH.js.map
256
+ //# sourceMappingURL=care-plan-card-CQVboTn1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"care-plan-card-D-FMfDKH.js","sources":["../../src/components/care-plan-card/care-plan-card.agent.ts","../../src/components/care-plan-card/care-plan-card.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — CarePlanCard. */\n/* */\n/* Read-only surface: expose the plan's lifecycle state and line-progress */\n/* counts so an agent can introspect a care plan's status. State enum + */\n/* counts only — never the plan name, operator, treatment names, or any */\n/* patient identity. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { CarePlanCardHandle } from './care-plan-card';\n\nexport const carePlanCardAgent: AgentAdapter<CarePlanCardHandle> = {\n id: 'care-plan-card',\n // `expand` is host-delegated: the treatment-line list is an in-component\n // Accordion the user (or a host) drives directly — there is no handle\n // method for it, so no backing action is registered. `view_change` was\n // dropped: the card has no view modes to switch between.\n capabilities: ['expand'],\n state: {\n state: {\n type: \"'estimate' | 'accepted' | 'discarded' | 'closed'\",\n descriptionKey: 'ui.agent.carePlanCard.state.state',\n description:\n 'The plan lifecycle state. Enum value only — never the localised label or any PHI.',\n read: (handle) => handle.getState(),\n },\n progress: {\n type: '{ done: number; total: number }',\n descriptionKey: 'ui.agent.carePlanCard.state.progress',\n description:\n 'Line progress as done / total counts. Counts only — never treatment names or operator identity.',\n read: (handle) => handle.getProgress(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'care-plan-card',\n description: 'Marks the CarePlanCard root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop. Addresses a specific plan.',\n },\n },\n};\n","import { forwardRef, useId, type HTMLAttributes } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '../badge/badge';\nimport { Link } from '../link/link';\nimport { Progress } from '../progress/progress';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { TransactionChip } from '../transaction-chip/transaction-chip';\nimport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n} from '../accordion/accordion';\nimport {\n CarePlanEntryCard,\n type CarePlanEntryCardProps,\n} from '../care-plan-entry-card';\nimport {\n entitySurfaceVariants,\n CARE_PLAN_STATE_BADGE,\n isSafeEntityUrl,\n type CarePlanState,\n} from '../_shared/entity-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { carePlanCardAgent } from './care-plan-card.agent';\n\n/* -------------------------------------------------------------------- */\n/* CarePlanCard */\n/* */\n/* The summary card for a whole care plan / estimate (\"preventivo\"). */\n/* Replaces the hand-rolled platform care-plan header that interleaves */\n/* the plan number + name, a lifecycle badge, the financial figures */\n/* (billed / due / overdue), an acceptance/closure date, a phase- */\n/* progress bar, an optional deep link, and an expandable list of the */\n/* plan's treatment lines. */\n/* */\n/* Composes: entitySurfaceVariants (shared card surface) + Badge */\n/* (lifecycle state) + TransactionChip (money) + Progress (done/total) */\n/* + Timestamp (dates) + Link (deep link) + Accordion (entries rendered */\n/* as <CarePlanEntryCard> rows). */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `carePlanCard.*` namespace — the lifecycle state is ALWAYS shown as a */\n/* localised label, never the raw server string. Identifiers + structural */\n/* state only reach the agent layer — never patient identity. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/**\n * A single treatment line within the plan. Each ref is forwarded straight\n * to a `<CarePlanEntryCard>` rendered inside the Accordion. `entryId` keys\n * the row and surfaces as the line's `data-component-id`.\n */\nexport interface CarePlanEntryRef extends Omit<\n CarePlanEntryCardProps,\n 'id' | 'surface'\n> {\n /** Stable line id — identifier only, never PHI. */\n entryId: string;\n}\n\n/** Financial figures for the plan, all amounts in integer cents. */\nexport interface CarePlanAmounts {\n /** Full list price in cents (non-negative). */\n priceCents?: number;\n /** Discounted / agreed price in cents (non-negative). */\n discountedPriceCents?: number;\n /** Amount already invoiced in cents (non-negative). */\n billedAmountCents?: number;\n /** Outstanding amount still due in cents (non-negative). */\n dueCents?: number;\n /** How many days the due amount is overdue (non-negative). */\n overdueDays?: number;\n}\n\n/** Phase / line progress for the plan. */\nexport interface CarePlanProgress {\n /** Number of executed / completed lines. */\n done: number;\n /** Total number of lines. */\n total: number;\n}\n\n/** Lifecycle dates for the plan, all ISO-8601 strings. */\nexport interface CarePlanDates {\n /** When the plan was accepted. */\n acceptedIso?: string;\n /** When the plan was closed. */\n closedIso?: string;\n /** When the plan was discarded / rejected. */\n discardedIso?: string;\n}\n\n/** Curated read-only handle exposed to the agent registry. */\nexport interface CarePlanCardHandle {\n /** The plan's lifecycle state. */\n getState: () => CarePlanState;\n /** Line progress as `{ done, total }` — counts only, no PHI. */\n getProgress: () => { done: number; total: number };\n}\n\nexport interface CarePlanCardProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'aria-label' | 'title' | 'children'\n> {\n /**\n * Stable instance id — surfaced as `data-component-id` for the agent\n * registry and mirrored to the DOM `id`; also wires the heading ↔ region\n * relationship.\n */\n id?: string;\n /** Plan number (e.g. estimate number). Rendered beside the name. */\n number: string | number;\n /** Plan name / title. Rendered as the card heading. */\n name?: string;\n /** Lifecycle state — drives a localised Badge label. */\n state: CarePlanState;\n /** Optional deep link to the full plan. Guarded by `isSafeEntityUrl`. */\n url?: string;\n /** Financial figures (billed / due / overdue …). */\n amounts?: CarePlanAmounts;\n /** Line progress (done / total). */\n progress?: CarePlanProgress;\n /** Lifecycle dates (accepted / closed / discarded). */\n dates?: CarePlanDates;\n /** Reason the plan was discarded — shown only when `state === 'discarded'`. */\n discardReason?: string;\n /**\n * Dentition the plan applies to — forwarded to each entry card's tooth\n * display where relevant. Structural only.\n */\n dentitionMode?: 'permanent' | 'deciduous';\n /** Treatment lines — rendered as `<CarePlanEntryCard>` rows in an Accordion. */\n entries?: CarePlanEntryRef[];\n /** BCP 47 locale override for dates / currency. Defaults to i18n.language. */\n locale?: string;\n /** ISO 4217 currency code for the money chips. Defaults to `EUR`. */\n currency?: string;\n /**\n * `elevated` (default) paints the kit card chrome; `flat` drops it for use\n * inside an existing Card / Sheet.\n */\n surface?: 'flat' | 'elevated';\n /** Fires when the plan deep link / heading is activated. */\n onActivate?: () => void;\n /** Accessible label override for the plan region. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nconst DEFAULT_CURRENCY = 'EUR';\n\n/**\n * English fallbacks for the lifecycle-state labels. The canonical strings\n * live in the `ui.carePlanCard.state.*` bundle; these inline defaults guard\n * against a stale / not-yet-wired bundle so a raw key never reaches the UI.\n */\nconst STATE_LABEL_FALLBACK: Record<CarePlanState, string> = {\n estimate: 'Estimate',\n accepted: 'Accepted',\n discarded: 'Discarded',\n closed: 'Closed',\n};\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const CarePlanCard = forwardRef<HTMLDivElement, CarePlanCardProps>(\n (\n {\n id,\n number,\n name,\n state,\n url,\n amounts,\n progress,\n dates,\n discardReason,\n dentitionMode: _dentitionMode,\n entries,\n locale,\n currency = DEFAULT_CURRENCY,\n surface = 'elevated',\n onActivate,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const headingId = useId();\n const progressLabelId = useId();\n const activeLocale = locale ?? i18n.language ?? 'en';\n\n useAgentRegistration(\n carePlanCardAgent,\n {\n getState: () => state,\n getProgress: () => ({\n done: progress?.done ?? 0,\n total: progress?.total ?? 0,\n }),\n },\n id,\n );\n\n const stateLabel = t(`carePlanCard.state.${state}`, {\n defaultValue: STATE_LABEL_FALLBACK[state],\n });\n const stateBadgeVariant = CARE_PLAN_STATE_BADGE[state];\n const hasSafeUrl = !!url && isSafeEntityUrl(url);\n const hasEntries = !!entries && entries.length > 0;\n\n // Money: prefer the outstanding \"due\" chip; mark it overdue when it has\n // run past its term. Anything billed shows a settled chip alongside.\n const dueCents = amounts?.dueCents;\n const billedCents = amounts?.billedAmountCents;\n const overdueDays = amounts?.overdueDays;\n const isOverdue =\n typeof overdueDays === 'number' &&\n overdueDays > 0 &&\n typeof dueCents === 'number' &&\n dueCents > 0;\n\n const headingNode = (\n <h3\n id={headingId}\n className=\"type-title-card ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {name ?? t('carePlanCard.untitled', 'Untitled plan')}\n </h3>\n );\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabel ? undefined : headingId}\n data-component=\"care-plan-card\"\n data-component-id={id}\n data-state={state}\n id={id}\n className={entitySurfaceVariants({ surface, className })}\n {...rest}\n >\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {/* Heading row: number + name + lifecycle badge */}\n <div className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)] ds:tabular-nums\">\n {t('carePlanCard.number', {\n number,\n defaultValue: 'Plan #{{number}}',\n })}\n </span>\n {hasSafeUrl ? (\n <Link\n href={url as string}\n weight=\"strong\"\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n onActivate?.();\n }}\n >\n {headingNode}\n </Link>\n ) : (\n headingNode\n )}\n </div>\n\n <Badge\n variant={stateBadgeVariant}\n size=\"sm\"\n withDot\n className=\"ds:shrink-0\"\n >\n {stateLabel}\n </Badge>\n </div>\n\n {/* Discard reason — only when discarded */}\n {state === 'discarded' && discardReason ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n <span className=\"ds:font-medium ds:text-[color:var(--foreground)]\">\n {t('carePlanCard.discardReasonLabel', 'Discard reason:')}\n </span>{' '}\n {discardReason}\n </p>\n ) : null}\n\n {/* Lifecycle date line */}\n {dates ? (\n <div className=\"type-body-sm ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-md)] ds:text-[color:var(--muted-foreground)]\">\n {dates.acceptedIso ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span>{t('carePlanCard.date.accepted', 'Accepted')}</span>\n <Timestamp\n value={dates.acceptedIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n </span>\n ) : null}\n {dates.closedIso ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span>{t('carePlanCard.date.closed', 'Closed')}</span>\n <Timestamp\n value={dates.closedIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n </span>\n ) : null}\n {dates.discardedIso ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span>{t('carePlanCard.date.discarded', 'Discarded')}</span>\n <Timestamp\n value={dates.discardedIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n </span>\n ) : null}\n </div>\n ) : null}\n\n {/* Money: due / overdue / billed chips */}\n {typeof dueCents === 'number' || typeof billedCents === 'number' ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {typeof dueCents === 'number' && dueCents > 0 ? (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <TransactionChip\n state=\"debt\"\n amount={dueCents / 100}\n currency={currency}\n locale={activeLocale}\n showLabel\n size=\"md\"\n />\n {isOverdue ? (\n <Badge variant=\"error\" size=\"sm\" withDot>\n {t('carePlanCard.overdue', {\n count: overdueDays,\n defaultValue: 'Overdue {{count}}d',\n })}\n </Badge>\n ) : null}\n </div>\n ) : null}\n {typeof billedCents === 'number' && billedCents > 0 ? (\n <TransactionChip\n state=\"settled\"\n amount={billedCents / 100}\n currency={currency}\n locale={activeLocale}\n showLabel\n size=\"md\"\n />\n ) : null}\n </div>\n ) : null}\n\n {/* Line / phase progress */}\n {progress && progress.total > 0 ? (\n <Progress\n value={progress.done}\n max={progress.total}\n size=\"sm\"\n aria-label={t('carePlanCard.progressLabel', {\n done: progress.done,\n total: progress.total,\n defaultValue: 'Progress: {{done}} of {{total}} completed',\n })}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <Progress.Label id={progressLabelId}>\n {t('carePlanCard.progressHeading', 'Progress')}\n </Progress.Label>\n <span className=\"type-body-sm ds:tabular-nums ds:text-[color:var(--muted-foreground)]\">\n {t('carePlanCard.progressCount', {\n done: progress.done,\n total: progress.total,\n defaultValue: '{{done}} / {{total}}',\n })}\n </span>\n </div>\n </Progress>\n ) : null}\n\n {/* Entries — expandable list of treatment lines */}\n {hasEntries ? (\n <Accordion type=\"single\" collapsible variant=\"separated\">\n <AccordionItem value=\"entries\">\n <AccordionTrigger>\n {t('carePlanCard.entries.toggle', {\n count: entries.length,\n defaultValue: 'Treatment lines ({{count}})',\n })}\n </AccordionTrigger>\n <AccordionContent>\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-0\">\n {entries.map(({ entryId, ...entry }) => (\n <li key={entryId}>\n <CarePlanEntryCard\n id={entryId}\n surface=\"flat\"\n locale={activeLocale}\n currency={currency}\n {...entry}\n />\n </li>\n ))}\n </ul>\n </AccordionContent>\n </AccordionItem>\n </Accordion>\n ) : null}\n </div>\n </div>\n );\n },\n);\n\nCarePlanCard.displayName = 'CarePlanCard';\n\nexport type CarePlanCardSurface = NonNullable<\n VariantProps<typeof entitySurfaceVariants>['surface']\n>;\n\n/** The dentition the plan applies to. */\nexport type CarePlanCardDentition = NonNullable<\n CarePlanCardProps['dentitionMode']\n>;\n\n/* Re-export the shared lifecycle-state type for downstream typing. */\nexport type { CarePlanState } from '../_shared/entity-card';\n"],"names":["carePlanCardAgent","handle","DEFAULT_CURRENCY","STATE_LABEL_FALLBACK","CarePlanCard","forwardRef","id","number","name","state","url","amounts","progress","dates","discardReason","_dentitionMode","entries","locale","currency","surface","onActivate","ariaLabel","className","rest","ref","t","i18n","useTranslation","headingId","useId","progressLabelId","activeLocale","useAgentRegistration","stateLabel","stateBadgeVariant","CARE_PLAN_STATE_BADGE","hasSafeUrl","isSafeEntityUrl","hasEntries","dueCents","billedCents","overdueDays","isOverdue","headingNode","jsx","entitySurfaceVariants","jsxs","Link","event","Badge","Timestamp","TransactionChip","Progress","Accordion","AccordionItem","AccordionTrigger","AccordionContent","entryId","entry","CarePlanEntryCard"],"mappings":"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"}
1
+ {"version":3,"file":"care-plan-card-CQVboTn1.js","sources":["../../src/components/care-plan-card/care-plan-card.agent.ts","../../src/components/care-plan-card/care-plan-card.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — CarePlanCard. */\n/* */\n/* Read-only surface: expose the plan's lifecycle state and line-progress */\n/* counts so an agent can introspect a care plan's status. State enum + */\n/* counts only — never the plan name, operator, treatment names, or any */\n/* patient identity. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { CarePlanCardHandle } from './care-plan-card';\n\nexport const carePlanCardAgent: AgentAdapter<CarePlanCardHandle> = {\n id: 'care-plan-card',\n // `expand` is host-delegated: the treatment-line list is an in-component\n // Accordion the user (or a host) drives directly — there is no handle\n // method for it, so no backing action is registered. `view_change` was\n // dropped: the card has no view modes to switch between.\n capabilities: ['expand'],\n state: {\n state: {\n type: \"'estimate' | 'accepted' | 'discarded' | 'closed'\",\n descriptionKey: 'ui.agent.carePlanCard.state.state',\n description:\n 'The plan lifecycle state. Enum value only — never the localised label or any PHI.',\n read: (handle) => handle.getState(),\n },\n progress: {\n type: '{ done: number; total: number }',\n descriptionKey: 'ui.agent.carePlanCard.state.progress',\n description:\n 'Line progress as done / total counts. Counts only — never treatment names or operator identity.',\n read: (handle) => handle.getProgress(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'care-plan-card',\n description: 'Marks the CarePlanCard root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop. Addresses a specific plan.',\n },\n },\n};\n","import { forwardRef, useId, type HTMLAttributes } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '../badge/badge';\nimport { Link } from '../link/link';\nimport { Progress } from '../progress/progress';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { TransactionChip } from '../transaction-chip/transaction-chip';\nimport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n} from '../accordion/accordion';\nimport {\n CarePlanEntryCard,\n type CarePlanEntryCardProps,\n} from '../care-plan-entry-card';\nimport {\n entitySurfaceVariants,\n CARE_PLAN_STATE_BADGE,\n isSafeEntityUrl,\n type CarePlanState,\n} from '../_shared/entity-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { carePlanCardAgent } from './care-plan-card.agent';\n\n/* -------------------------------------------------------------------- */\n/* CarePlanCard */\n/* */\n/* The summary card for a whole care plan / estimate (\"preventivo\"). */\n/* Replaces the hand-rolled platform care-plan header that interleaves */\n/* the plan number + name, a lifecycle badge, the financial figures */\n/* (billed / due / overdue), an acceptance/closure date, a phase- */\n/* progress bar, an optional deep link, and an expandable list of the */\n/* plan's treatment lines. */\n/* */\n/* Composes: entitySurfaceVariants (shared card surface) + Badge */\n/* (lifecycle state) + TransactionChip (money) + Progress (done/total) */\n/* + Timestamp (dates) + Link (deep link) + Accordion (entries rendered */\n/* as <CarePlanEntryCard> rows). */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `carePlanCard.*` namespace — the lifecycle state is ALWAYS shown as a */\n/* localised label, never the raw server string. Identifiers + structural */\n/* state only reach the agent layer — never patient identity. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/**\n * A single treatment line within the plan. Each ref is forwarded straight\n * to a `<CarePlanEntryCard>` rendered inside the Accordion. `entryId` keys\n * the row and surfaces as the line's `data-component-id`.\n */\nexport interface CarePlanEntryRef extends Omit<\n CarePlanEntryCardProps,\n 'id' | 'surface'\n> {\n /** Stable line id — identifier only, never PHI. */\n entryId: string;\n}\n\n/** Financial figures for the plan, all amounts in integer cents. */\nexport interface CarePlanAmounts {\n /** Full list price in cents (non-negative). */\n priceCents?: number;\n /** Discounted / agreed price in cents (non-negative). */\n discountedPriceCents?: number;\n /** Amount already invoiced in cents (non-negative). */\n billedAmountCents?: number;\n /** Outstanding amount still due in cents (non-negative). */\n dueCents?: number;\n /** How many days the due amount is overdue (non-negative). */\n overdueDays?: number;\n}\n\n/** Phase / line progress for the plan. */\nexport interface CarePlanProgress {\n /** Number of executed / completed lines. */\n done: number;\n /** Total number of lines. */\n total: number;\n}\n\n/** Lifecycle dates for the plan, all ISO-8601 strings. */\nexport interface CarePlanDates {\n /** When the plan was accepted. */\n acceptedIso?: string;\n /** When the plan was closed. */\n closedIso?: string;\n /** When the plan was discarded / rejected. */\n discardedIso?: string;\n}\n\n/** Curated read-only handle exposed to the agent registry. */\nexport interface CarePlanCardHandle {\n /** The plan's lifecycle state. */\n getState: () => CarePlanState;\n /** Line progress as `{ done, total }` — counts only, no PHI. */\n getProgress: () => { done: number; total: number };\n}\n\nexport interface CarePlanCardProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'aria-label' | 'title' | 'children'\n> {\n /**\n * Stable instance id — surfaced as `data-component-id` for the agent\n * registry and mirrored to the DOM `id`; also wires the heading ↔ region\n * relationship.\n */\n id?: string;\n /** Plan number (e.g. estimate number). Rendered beside the name. */\n number: string | number;\n /** Plan name / title. Rendered as the card heading. */\n name?: string;\n /** Lifecycle state — drives a localised Badge label. */\n state: CarePlanState;\n /** Optional deep link to the full plan. Guarded by `isSafeEntityUrl`. */\n url?: string;\n /** Financial figures (billed / due / overdue …). */\n amounts?: CarePlanAmounts;\n /** Line progress (done / total). */\n progress?: CarePlanProgress;\n /** Lifecycle dates (accepted / closed / discarded). */\n dates?: CarePlanDates;\n /** Reason the plan was discarded — shown only when `state === 'discarded'`. */\n discardReason?: string;\n /**\n * Dentition the plan applies to — forwarded to each entry card's tooth\n * display where relevant. Structural only.\n */\n dentitionMode?: 'permanent' | 'deciduous';\n /** Treatment lines — rendered as `<CarePlanEntryCard>` rows in an Accordion. */\n entries?: CarePlanEntryRef[];\n /** BCP 47 locale override for dates / currency. Defaults to i18n.language. */\n locale?: string;\n /** ISO 4217 currency code for the money chips. Defaults to `EUR`. */\n currency?: string;\n /**\n * `elevated` (default) paints the kit card chrome; `flat` drops it for use\n * inside an existing Card / Sheet.\n */\n surface?: 'flat' | 'elevated';\n /** Fires when the plan deep link / heading is activated. */\n onActivate?: () => void;\n /** Accessible label override for the plan region. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nconst DEFAULT_CURRENCY = 'EUR';\n\n/**\n * English fallbacks for the lifecycle-state labels. The canonical strings\n * live in the `ui.carePlanCard.state.*` bundle; these inline defaults guard\n * against a stale / not-yet-wired bundle so a raw key never reaches the UI.\n */\nconst STATE_LABEL_FALLBACK: Record<CarePlanState, string> = {\n estimate: 'Estimate',\n accepted: 'Accepted',\n discarded: 'Discarded',\n closed: 'Closed',\n};\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const CarePlanCard = forwardRef<HTMLDivElement, CarePlanCardProps>(\n (\n {\n id,\n number,\n name,\n state,\n url,\n amounts,\n progress,\n dates,\n discardReason,\n dentitionMode: _dentitionMode,\n entries,\n locale,\n currency = DEFAULT_CURRENCY,\n surface = 'elevated',\n onActivate,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const headingId = useId();\n const progressLabelId = useId();\n const activeLocale = locale ?? i18n.language ?? 'en';\n\n useAgentRegistration(\n carePlanCardAgent,\n {\n getState: () => state,\n getProgress: () => ({\n done: progress?.done ?? 0,\n total: progress?.total ?? 0,\n }),\n },\n id,\n );\n\n const stateLabel = t(`carePlanCard.state.${state}`, {\n defaultValue: STATE_LABEL_FALLBACK[state],\n });\n const stateBadgeVariant = CARE_PLAN_STATE_BADGE[state];\n const hasSafeUrl = !!url && isSafeEntityUrl(url);\n const hasEntries = !!entries && entries.length > 0;\n\n // Money: prefer the outstanding \"due\" chip; mark it overdue when it has\n // run past its term. Anything billed shows a settled chip alongside.\n const dueCents = amounts?.dueCents;\n const billedCents = amounts?.billedAmountCents;\n const overdueDays = amounts?.overdueDays;\n const isOverdue =\n typeof overdueDays === 'number' &&\n overdueDays > 0 &&\n typeof dueCents === 'number' &&\n dueCents > 0;\n\n const headingNode = (\n <h3\n id={headingId}\n className=\"type-title-card ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {name ?? t('carePlanCard.untitled', 'Untitled plan')}\n </h3>\n );\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabel ? undefined : headingId}\n data-component=\"care-plan-card\"\n data-component-id={id}\n data-state={state}\n id={id}\n className={entitySurfaceVariants({ surface, className })}\n {...rest}\n >\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {/* Heading row: number + name + lifecycle badge */}\n <div className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)] ds:tabular-nums\">\n {t('carePlanCard.number', {\n number,\n defaultValue: 'Plan #{{number}}',\n })}\n </span>\n {hasSafeUrl ? (\n <Link\n href={url as string}\n weight=\"strong\"\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n onActivate?.();\n }}\n >\n {headingNode}\n </Link>\n ) : (\n headingNode\n )}\n </div>\n\n <Badge\n variant={stateBadgeVariant}\n size=\"sm\"\n withDot\n className=\"ds:shrink-0\"\n >\n {stateLabel}\n </Badge>\n </div>\n\n {/* Discard reason — only when discarded */}\n {state === 'discarded' && discardReason ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n <span className=\"ds:font-medium ds:text-[color:var(--foreground)]\">\n {t('carePlanCard.discardReasonLabel', 'Discard reason:')}\n </span>{' '}\n {discardReason}\n </p>\n ) : null}\n\n {/* Lifecycle date line */}\n {dates ? (\n <div className=\"type-body-sm ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-md)] ds:text-[color:var(--muted-foreground)]\">\n {dates.acceptedIso ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span>{t('carePlanCard.date.accepted', 'Accepted')}</span>\n <Timestamp\n value={dates.acceptedIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n </span>\n ) : null}\n {dates.closedIso ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span>{t('carePlanCard.date.closed', 'Closed')}</span>\n <Timestamp\n value={dates.closedIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n </span>\n ) : null}\n {dates.discardedIso ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span>{t('carePlanCard.date.discarded', 'Discarded')}</span>\n <Timestamp\n value={dates.discardedIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n </span>\n ) : null}\n </div>\n ) : null}\n\n {/* Money: due / overdue / billed chips */}\n {typeof dueCents === 'number' || typeof billedCents === 'number' ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {typeof dueCents === 'number' && dueCents > 0 ? (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <TransactionChip\n state=\"debt\"\n amount={dueCents / 100}\n currency={currency}\n locale={activeLocale}\n showLabel\n size=\"md\"\n />\n {isOverdue ? (\n <Badge variant=\"error\" size=\"sm\" withDot>\n {t('carePlanCard.overdue', {\n count: overdueDays,\n defaultValue: 'Overdue {{count}}d',\n })}\n </Badge>\n ) : null}\n </div>\n ) : null}\n {typeof billedCents === 'number' && billedCents > 0 ? (\n <TransactionChip\n state=\"settled\"\n amount={billedCents / 100}\n currency={currency}\n locale={activeLocale}\n showLabel\n size=\"md\"\n />\n ) : null}\n </div>\n ) : null}\n\n {/* Line / phase progress */}\n {progress && progress.total > 0 ? (\n <Progress\n value={progress.done}\n max={progress.total}\n size=\"sm\"\n aria-label={t('carePlanCard.progressLabel', {\n done: progress.done,\n total: progress.total,\n defaultValue: 'Progress: {{done}} of {{total}} completed',\n })}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <Progress.Label id={progressLabelId}>\n {t('carePlanCard.progressHeading', 'Progress')}\n </Progress.Label>\n <span className=\"type-body-sm ds:tabular-nums ds:text-[color:var(--muted-foreground)]\">\n {t('carePlanCard.progressCount', {\n done: progress.done,\n total: progress.total,\n defaultValue: '{{done}} / {{total}}',\n })}\n </span>\n </div>\n </Progress>\n ) : null}\n\n {/* Entries — expandable list of treatment lines */}\n {hasEntries ? (\n <Accordion type=\"single\" collapsible variant=\"separated\">\n <AccordionItem value=\"entries\">\n <AccordionTrigger>\n {t('carePlanCard.entries.toggle', {\n count: entries.length,\n defaultValue: 'Treatment lines ({{count}})',\n })}\n </AccordionTrigger>\n <AccordionContent>\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-0\">\n {entries.map(({ entryId, ...entry }) => (\n <li key={entryId}>\n <CarePlanEntryCard\n id={entryId}\n surface=\"flat\"\n locale={activeLocale}\n currency={currency}\n {...entry}\n />\n </li>\n ))}\n </ul>\n </AccordionContent>\n </AccordionItem>\n </Accordion>\n ) : null}\n </div>\n </div>\n );\n },\n);\n\nCarePlanCard.displayName = 'CarePlanCard';\n\nexport type CarePlanCardSurface = NonNullable<\n VariantProps<typeof entitySurfaceVariants>['surface']\n>;\n\n/** The dentition the plan applies to. */\nexport type CarePlanCardDentition = NonNullable<\n CarePlanCardProps['dentitionMode']\n>;\n\n/* Re-export the shared lifecycle-state type for downstream typing. */\nexport type { CarePlanState } from '../_shared/entity-card';\n"],"names":["carePlanCardAgent","handle","DEFAULT_CURRENCY","STATE_LABEL_FALLBACK","CarePlanCard","forwardRef","id","number","name","state","url","amounts","progress","dates","discardReason","_dentitionMode","entries","locale","currency","surface","onActivate","ariaLabel","className","rest","ref","t","i18n","useTranslation","headingId","useId","progressLabelId","activeLocale","useAgentRegistration","stateLabel","stateBadgeVariant","CARE_PLAN_STATE_BADGE","hasSafeUrl","isSafeEntityUrl","hasEntries","dueCents","billedCents","overdueDays","isOverdue","headingNode","jsx","entitySurfaceVariants","jsxs","Link","event","Badge","Timestamp","TransactionChip","Progress","Accordion","AccordionItem","AccordionTrigger","AccordionContent","entryId","entry","CarePlanEntryCard"],"mappings":"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"}
@@ -6,7 +6,7 @@ import { P as O } from "./progress-CK8otcQ-.js";
6
6
  import { T as q } from "./tag-3wgkwwDB.js";
7
7
  import { T as b } from "./timestamp-BV2lC-wV.js";
8
8
  import { T as G } from "./transaction-chip-DJCstquX.js";
9
- import { T as J } from "./tooth-scheme-2IsmbE6w.js";
9
+ import { T as J } from "./tooth-scheme-C9jssOmy.js";
10
10
  import { C as Q, b as X, a as Z } from "./collapsible-CTjxzGuF.js";
11
11
  import { u as ee } from "./registry-DvAUVLHh.js";
12
12
  import { C as ae } from "./chevron-down-DWE7GSq9.js";
@@ -319,4 +319,4 @@ export {
319
319
  le as C,
320
320
  re as c
321
321
  };
322
- //# sourceMappingURL=care-plan-entry-card-Bvw_9T-d.js.map
322
+ //# sourceMappingURL=care-plan-entry-card-jxHkzez5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"care-plan-entry-card-Bvw_9T-d.js","sources":["../../src/components/care-plan-entry-card/care-plan-entry-card.agent.ts","../../src/components/care-plan-entry-card/care-plan-entry-card.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — CarePlanEntryCard. */\n/* */\n/* Read-only surface: expose the execution flag and phase-progress */\n/* counts so an agent can introspect a treatment line's status. Counts + */\n/* booleans only — never the treatment name, operator, or any patient */\n/* identity. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { CarePlanEntryCardHandle } from './care-plan-entry-card';\n\nexport const carePlanEntryCardAgent: AgentAdapter<CarePlanEntryCardHandle> = {\n id: 'care-plan-entry-card',\n // `expand` is host-delegated: the per-phase breakdown is an in-component\n // Collapsible the user (or a host) drives directly — there is no handle\n // method for it, so no backing action is registered. `view_change` was\n // dropped: the card has no view modes to switch between.\n capabilities: ['expand'],\n state: {\n done: {\n type: 'boolean',\n descriptionKey: 'ui.agent.carePlanEntryCard.state.done',\n description: 'Whether the treatment line is marked executed.',\n read: (handle) => handle.isDone(),\n },\n phaseProgress: {\n type: '{ executed: number; total: number }',\n descriptionKey: 'ui.agent.carePlanEntryCard.state.phaseProgress',\n description:\n 'Phase progress as executed / total counts. Counts only — never phase labels or operator identity.',\n read: (handle) => handle.getPhaseProgress(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'care-plan-entry-card',\n description: 'Marks the CarePlanEntryCard root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop. Addresses a specific line.',\n },\n },\n};\n","import { forwardRef, useId, type HTMLAttributes, type ReactNode } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ChevronDown } from 'lucide-react';\nimport { Badge } from '../badge/badge';\nimport { Progress } from '../progress/progress';\nimport { Tag } from '../tag/tag';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { TransactionChip } from '../transaction-chip/transaction-chip';\nimport { ToothScheme } from '../tooth-scheme/tooth-scheme';\nimport type { FdiId, ToothCondition } from '../tooth-scheme/tooth-data';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from '../collapsible/collapsible';\nimport { entitySurfaceVariants } from '../_shared/entity-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { carePlanEntryCardAgent } from './care-plan-entry-card.agent';\n\n/* -------------------------------------------------------------------- */\n/* CarePlanEntryCard */\n/* */\n/* A single granular treatment line within a care plan / estimate */\n/* (\"voce di preventivo\"). Replaces the hand-rolled platform treatment */\n/* row that interleaves the treatment label, FDI tooth codes, an */\n/* execution badge, a phase-progress bar, a price chip, and an */\n/* expandable per-phase breakdown. */\n/* */\n/* Composes: entitySurfaceVariants (shared card surface) + Tag / ToothScheme*/\n/* (elements) + Badge (lifecycle flags) + Timestamp (execution / planned) */\n/* + Progress (phases) + TransactionChip (price) + Collapsible (per-phase */\n/* detail). */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `carePlanEntryCard.*` namespace. Identifiers + structural state only */\n/* reach the agent layer — never patient identity. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** A planned (not-yet-executed) appointment the line is scheduled into. */\nexport interface CarePlanEntryPlannedAppointment {\n /** ISO-8601 date / datetime string. */\n dateIso: string;\n /** Stable appointment id (identifier only — never PHI). */\n appointmentId: string;\n /** Optional deep link to the appointment. */\n url?: string;\n}\n\n/** Price breakdown for the line, all amounts in integer cents. */\nexport interface CarePlanEntryPrice {\n /** List price in cents (non-negative). */\n priceCents?: number;\n /** Discounted price in cents (non-negative), when a discount applies. */\n discountedPriceCents?: number;\n /** Discount percentage (0–100), for the discount label. */\n discountPercentage?: number;\n}\n\n/** One row of the per-phase execution breakdown. */\nexport interface CarePlanEntryPhaseDetail {\n /** Short localised phase label (consumer-localised). */\n label: string;\n /** Whether this phase has been executed. */\n executed: boolean;\n /** ISO-8601 execution date, when executed. */\n executionDateIso?: string;\n /** Operator display name for the phase. */\n operator?: string;\n /** Unique Device Identifier / lot string for traceable materials. */\n udi?: string;\n}\n\n/** Phase progress summary + optional drill-down detail. */\nexport interface CarePlanEntryPhases {\n /** Number of executed phases. */\n executed: number;\n /** Total number of phases. */\n total: number;\n /** Optional per-phase breakdown rendered inside the Collapsible. */\n detail?: CarePlanEntryPhaseDetail[];\n}\n\n/** Operator the line is assigned to. */\nexport interface CarePlanEntryOperator {\n /** Operator display name (consumer-localised). */\n name: string;\n}\n\n/** Curated read-only handle exposed to the agent registry. */\nexport interface CarePlanEntryCardHandle {\n /** Whether the line is marked executed. */\n isDone: () => boolean;\n /** Phase progress as `{ executed, total }` — counts only, no PHI. */\n getPhaseProgress: () => { executed: number; total: number };\n}\n\nexport interface CarePlanEntryCardProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'aria-label' | 'title' | 'children'\n> {\n /**\n * Stable instance id — surfaced as `data-component-id` for the agent\n * registry and used to wire up the heading ↔ region relationship.\n */\n id?: string;\n /** Treatment / service name. Rendered as the line heading. */\n careName: string;\n /** Optional treatment code (e.g. tariff code) shown beside the name. */\n code?: string;\n /** Optional secondary label (e.g. category) under the name. */\n label?: string;\n /** FDI tooth codes the line applies to (e.g. `['16', '36']`). */\n elements?: string[];\n /** Whether the line has been executed / completed. */\n done?: boolean;\n /** ISO-8601 execution date — rendered next to the \"done\" badge. */\n executionDateIso?: string;\n /** A planned appointment the line is scheduled into, when not yet done. */\n plannedAppointment?: CarePlanEntryPlannedAppointment;\n /** Operator the line is assigned to. */\n operator?: CarePlanEntryOperator;\n /** Price breakdown (list / discounted). */\n price?: CarePlanEntryPrice;\n /** Phase progress + optional drill-down detail. */\n phases?: CarePlanEntryPhases;\n /** Whether the line has been billed / invoiced. */\n billed?: boolean;\n /** Whether the line falls outside the accepted estimate. */\n outsideOfEstimate?: boolean;\n /** Count of attached notes — rendered as a neutral count badge when > 0. */\n notesCount?: number;\n /**\n * How to render `elements`: `'chips'` (default) lists each FDI code as a\n * Tag; `'scheme'` renders a read-only `ToothScheme` highlighting them.\n */\n toothDisplay?: 'scheme' | 'chips';\n /** BCP 47 locale override for dates / currency. Defaults to i18n.language. */\n locale?: string;\n /** ISO 4217 currency code for the price chip. Defaults to `EUR`. */\n currency?: string;\n /**\n * `elevated` (default) paints the kit card chrome; `flat` drops it for use\n * inside an existing Card / Sheet.\n */\n surface?: 'flat' | 'elevated';\n /** Accessible label override for the line region. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nconst DEFAULT_CURRENCY = 'EUR';\n\n/**\n * Map the FDI element codes to a `ToothScheme` conditions shortcut. Codes\n * outside the FDI vocabulary are dropped (the scheme ignores unknown ids).\n * Every applied tooth is flagged `filled` so the display-mode chart marks\n * them with both colour and pattern — colour-not-alone.\n */\nfunction elementsToConditions(\n elements: string[],\n): Partial<Record<FdiId, ToothCondition[]>> {\n const conditions: Partial<Record<FdiId, ToothCondition[]>> = {};\n for (const code of elements) {\n conditions[code as FdiId] = ['filled'];\n }\n return conditions;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const CarePlanEntryCard = forwardRef<\n HTMLDivElement,\n CarePlanEntryCardProps\n>(\n (\n {\n id,\n careName,\n code,\n label,\n elements,\n done = false,\n executionDateIso,\n plannedAppointment,\n operator,\n price,\n phases,\n billed = false,\n outsideOfEstimate = false,\n notesCount,\n toothDisplay = 'chips',\n locale,\n currency = DEFAULT_CURRENCY,\n surface = 'elevated',\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const headingId = useId();\n const phasesLabelId = useId();\n const detailTriggerId = useId();\n const detailContentId = useId();\n const activeLocale = locale ?? i18n.language ?? 'en';\n\n useAgentRegistration(\n carePlanEntryCardAgent,\n {\n isDone: () => done,\n getPhaseProgress: () => ({\n executed: phases?.executed ?? 0,\n total: phases?.total ?? 0,\n }),\n },\n id,\n );\n\n const hasElements = !!elements && elements.length > 0;\n const hasPhaseDetail = !!phases?.detail && phases.detail.length > 0;\n\n // Price: prefer the discounted amount when present; show the list price\n // struck through beside it. Both are \"to-invoice\" until billed, then\n // settled.\n const priceState = billed ? 'settled' : 'to-invoice';\n const listCents = price?.priceCents;\n const discountedCents = price?.discountedPriceCents;\n const hasDiscount =\n discountedCents !== undefined &&\n listCents !== undefined &&\n discountedCents < listCents;\n const payableCents = discountedCents ?? listCents;\n\n const formatMoney = (cents: number): string =>\n new Intl.NumberFormat(activeLocale, {\n style: 'currency',\n currency,\n }).format(cents / 100);\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabel ? undefined : headingId}\n data-component=\"care-plan-entry-card\"\n data-component-id={id}\n data-done={done ? 'true' : 'false'}\n id={id}\n className={entitySurfaceVariants({ surface, className })}\n {...rest}\n >\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {/* Heading row: name + code + trailing status flags */}\n <div className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-baseline ds:gap-[var(--spacing-xs)]\">\n <h3\n id={headingId}\n className=\"type-title-item ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {careName}\n </h3>\n {code ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)] ds:tabular-nums\">\n {code}\n </span>\n ) : null}\n </div>\n {label ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {label}\n </span>\n ) : null}\n </div>\n\n <div className=\"ds:flex ds:shrink-0 ds:flex-wrap ds:items-center ds:justify-end ds:gap-[var(--spacing-2xs)]\">\n {done ? (\n <Badge variant=\"success\" size=\"sm\" withDot>\n {t('carePlanEntryCard.flag.done', 'Done')}\n </Badge>\n ) : null}\n {outsideOfEstimate ? (\n <Badge variant=\"warning\" size=\"sm\" withDot>\n {t(\n 'carePlanEntryCard.flag.outsideOfEstimate',\n 'Outside estimate',\n )}\n </Badge>\n ) : null}\n {billed ? (\n <Badge variant=\"neutral\" size=\"sm\">\n {t('carePlanEntryCard.flag.billed', 'Billed')}\n </Badge>\n ) : null}\n {typeof notesCount === 'number' && notesCount > 0 ? (\n <Badge\n variant=\"neutral\"\n size=\"sm\"\n aria-label={t('carePlanEntryCard.notesLabel', {\n count: notesCount,\n defaultValue: '{{count}} notes',\n })}\n >\n {notesCount}\n </Badge>\n ) : null}\n </div>\n </div>\n\n {/* Elements: tooth scheme (display mode) or FDI tag chips */}\n {hasElements ? (\n toothDisplay === 'scheme' ? (\n <ToothScheme\n mode=\"display\"\n conditions={elementsToConditions(elements)}\n ariaLabel={t('carePlanEntryCard.toothSchemeLabel', {\n count: elements.length,\n defaultValue: 'Teeth involved: {{count}}',\n })}\n />\n ) : (\n <div\n role=\"list\"\n aria-label={t(\n 'carePlanEntryCard.elementsLabel',\n 'Teeth involved',\n )}\n className=\"ds:flex ds:flex-wrap ds:gap-[var(--spacing-2xs)]\"\n >\n {elements.map((element) => (\n <div role=\"listitem\" key={element}>\n <Tag label={element} variant=\"info\" size=\"sm\" />\n </div>\n ))}\n </div>\n )\n ) : null}\n\n {/* Schedule / execution line */}\n {done && executionDateIso ? (\n <p className=\"type-body-sm ds:m-0 ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n <span>{t('carePlanEntryCard.executedOn', 'Executed on')}</span>\n <Timestamp\n value={executionDateIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n {operator ? (\n <span>\n {t('carePlanEntryCard.byOperator', {\n operator: operator.name,\n defaultValue: 'by {{operator}}',\n })}\n </span>\n ) : null}\n </p>\n ) : plannedAppointment ? (\n <p className=\"type-body-sm ds:m-0 ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n <span>{t('carePlanEntryCard.plannedFor', 'Planned for')}</span>\n <Timestamp\n value={plannedAppointment.dateIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n {operator ? (\n <span>\n {t('carePlanEntryCard.byOperator', {\n operator: operator.name,\n defaultValue: 'by {{operator}}',\n })}\n </span>\n ) : null}\n </p>\n ) : operator ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t('carePlanEntryCard.assignedTo', {\n operator: operator.name,\n defaultValue: 'Assigned to {{operator}}',\n })}\n </p>\n ) : null}\n\n {/* Phase progress */}\n {phases && phases.total > 0 ? (\n <Progress\n value={phases.executed}\n max={phases.total}\n size=\"sm\"\n aria-label={t('carePlanEntryCard.phasesLabel', {\n executed: phases.executed,\n total: phases.total,\n defaultValue: 'Phases: {{executed}} of {{total}} executed',\n })}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <Progress.Label id={phasesLabelId}>\n {t('carePlanEntryCard.phasesHeading', 'Phases')}\n </Progress.Label>\n <span className=\"type-body-sm ds:tabular-nums ds:text-[color:var(--muted-foreground)]\">\n {t('carePlanEntryCard.phasesCount', {\n executed: phases.executed,\n total: phases.total,\n defaultValue: '{{executed}} / {{total}}',\n })}\n </span>\n </div>\n </Progress>\n ) : null}\n\n {/* Footer: price + (optional) phase-detail disclosure */}\n {payableCents !== undefined || hasPhaseDetail ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {payableCents !== undefined ? (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <TransactionChip\n state={priceState}\n amount={payableCents / 100}\n currency={currency}\n locale={activeLocale}\n size=\"md\"\n />\n {hasDiscount && listCents !== undefined ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)] ds:line-through ds:tabular-nums\">\n {formatMoney(listCents)}\n </span>\n ) : null}\n {hasDiscount && price?.discountPercentage !== undefined ? (\n <Badge variant=\"success\" size=\"sm\">\n {t('carePlanEntryCard.discountLabel', {\n percentage: price.discountPercentage,\n defaultValue: '-{{percentage}}%',\n })}\n </Badge>\n ) : null}\n </div>\n ) : null}\n\n {hasPhaseDetail ? (\n <Collapsible\n variant=\"default\"\n className=\"ds:ms-auto ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n id={detailTriggerId}\n aria-controls={detailContentId}\n className=\"ds:group ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)] ds:rounded-[var(--radius-sm)] ds:border-0 ds:bg-transparent type-body-sm ds:text-[color:var(--foreground)] ds:cursor-pointer ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]\"\n >\n <span>\n {t(\n 'carePlanEntryCard.phaseDetail.toggle',\n 'Phase detail',\n )}\n </span>\n <ChevronDown\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--muted-foreground)] ds:transition-transform ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none ds:group-data-[state=open]:rotate-180\"\n />\n </button>\n </CollapsibleTrigger>\n <CollapsibleContent\n id={detailContentId}\n aria-labelledby={detailTriggerId}\n >\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-xs)] ds:p-0\">\n {phases?.detail?.map((phase, index) => (\n <PhaseDetailRow\n key={`${phase.label}-${index}`}\n phase={phase}\n locale={activeLocale}\n />\n ))}\n </ul>\n </CollapsibleContent>\n </Collapsible>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n );\n },\n);\n\nCarePlanEntryCard.displayName = 'CarePlanEntryCard';\n\n/* -------------------------------------------------------------------- */\n/* PhaseDetailRow — one row inside the per-phase Collapsible */\n/* -------------------------------------------------------------------- */\n\nfunction PhaseDetailRow({\n phase,\n locale,\n}: {\n phase: CarePlanEntryPhaseDetail;\n locale: string;\n}): ReactNode {\n const { t } = useTranslation();\n return (\n <li className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n <Badge variant={phase.executed ? 'success' : 'neutral'} size=\"sm\" withDot>\n {phase.executed\n ? t('carePlanEntryCard.phaseDetail.executed', 'Executed')\n : t('carePlanEntryCard.phaseDetail.pending', 'Pending')}\n </Badge>\n <span className=\"type-body-sm ds:text-[color:var(--foreground)]\">\n {phase.label}\n </span>\n {phase.executed && phase.executionDateIso ? (\n <Timestamp\n value={phase.executionDateIso}\n format=\"absolute\"\n locale={locale}\n />\n ) : null}\n {phase.operator ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t('carePlanEntryCard.byOperator', {\n operator: phase.operator,\n defaultValue: 'by {{operator}}',\n })}\n </span>\n ) : null}\n {phase.udi ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)] ds:tabular-nums\">\n {t('carePlanEntryCard.phaseDetail.udi', {\n udi: phase.udi,\n defaultValue: 'UDI {{udi}}',\n })}\n </span>\n ) : null}\n </li>\n );\n}\n\nexport type CarePlanEntryCardSurface = NonNullable<\n VariantProps<typeof entitySurfaceVariants>['surface']\n>;\n"],"names":["carePlanEntryCardAgent","handle","DEFAULT_CURRENCY","elementsToConditions","elements","conditions","code","CarePlanEntryCard","forwardRef","id","careName","label","done","executionDateIso","plannedAppointment","operator","price","phases","billed","outsideOfEstimate","notesCount","toothDisplay","locale","currency","surface","ariaLabel","className","rest","ref","t","i18n","useTranslation","headingId","useId","phasesLabelId","detailTriggerId","detailContentId","activeLocale","useAgentRegistration","hasElements","hasPhaseDetail","priceState","listCents","discountedCents","hasDiscount","payableCents","formatMoney","cents","jsx","entitySurfaceVariants","jsxs","Badge","ToothScheme","element","Tag","Timestamp","Progress","TransactionChip","Collapsible","CollapsibleTrigger","ChevronDown","CollapsibleContent","phase","index","PhaseDetailRow"],"mappings":"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"}
1
+ {"version":3,"file":"care-plan-entry-card-jxHkzez5.js","sources":["../../src/components/care-plan-entry-card/care-plan-entry-card.agent.ts","../../src/components/care-plan-entry-card/care-plan-entry-card.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — CarePlanEntryCard. */\n/* */\n/* Read-only surface: expose the execution flag and phase-progress */\n/* counts so an agent can introspect a treatment line's status. Counts + */\n/* booleans only — never the treatment name, operator, or any patient */\n/* identity. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { CarePlanEntryCardHandle } from './care-plan-entry-card';\n\nexport const carePlanEntryCardAgent: AgentAdapter<CarePlanEntryCardHandle> = {\n id: 'care-plan-entry-card',\n // `expand` is host-delegated: the per-phase breakdown is an in-component\n // Collapsible the user (or a host) drives directly — there is no handle\n // method for it, so no backing action is registered. `view_change` was\n // dropped: the card has no view modes to switch between.\n capabilities: ['expand'],\n state: {\n done: {\n type: 'boolean',\n descriptionKey: 'ui.agent.carePlanEntryCard.state.done',\n description: 'Whether the treatment line is marked executed.',\n read: (handle) => handle.isDone(),\n },\n phaseProgress: {\n type: '{ executed: number; total: number }',\n descriptionKey: 'ui.agent.carePlanEntryCard.state.phaseProgress',\n description:\n 'Phase progress as executed / total counts. Counts only — never phase labels or operator identity.',\n read: (handle) => handle.getPhaseProgress(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'care-plan-entry-card',\n description: 'Marks the CarePlanEntryCard root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop. Addresses a specific line.',\n },\n },\n};\n","import { forwardRef, useId, type HTMLAttributes, type ReactNode } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ChevronDown } from 'lucide-react';\nimport { Badge } from '../badge/badge';\nimport { Progress } from '../progress/progress';\nimport { Tag } from '../tag/tag';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { TransactionChip } from '../transaction-chip/transaction-chip';\nimport { ToothScheme } from '../tooth-scheme/tooth-scheme';\nimport type { FdiId, ToothCondition } from '../tooth-scheme/tooth-data';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from '../collapsible/collapsible';\nimport { entitySurfaceVariants } from '../_shared/entity-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { carePlanEntryCardAgent } from './care-plan-entry-card.agent';\n\n/* -------------------------------------------------------------------- */\n/* CarePlanEntryCard */\n/* */\n/* A single granular treatment line within a care plan / estimate */\n/* (\"voce di preventivo\"). Replaces the hand-rolled platform treatment */\n/* row that interleaves the treatment label, FDI tooth codes, an */\n/* execution badge, a phase-progress bar, a price chip, and an */\n/* expandable per-phase breakdown. */\n/* */\n/* Composes: entitySurfaceVariants (shared card surface) + Tag / ToothScheme*/\n/* (elements) + Badge (lifecycle flags) + Timestamp (execution / planned) */\n/* + Progress (phases) + TransactionChip (price) + Collapsible (per-phase */\n/* detail). */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `carePlanEntryCard.*` namespace. Identifiers + structural state only */\n/* reach the agent layer — never patient identity. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** A planned (not-yet-executed) appointment the line is scheduled into. */\nexport interface CarePlanEntryPlannedAppointment {\n /** ISO-8601 date / datetime string. */\n dateIso: string;\n /** Stable appointment id (identifier only — never PHI). */\n appointmentId: string;\n /** Optional deep link to the appointment. */\n url?: string;\n}\n\n/** Price breakdown for the line, all amounts in integer cents. */\nexport interface CarePlanEntryPrice {\n /** List price in cents (non-negative). */\n priceCents?: number;\n /** Discounted price in cents (non-negative), when a discount applies. */\n discountedPriceCents?: number;\n /** Discount percentage (0–100), for the discount label. */\n discountPercentage?: number;\n}\n\n/** One row of the per-phase execution breakdown. */\nexport interface CarePlanEntryPhaseDetail {\n /** Short localised phase label (consumer-localised). */\n label: string;\n /** Whether this phase has been executed. */\n executed: boolean;\n /** ISO-8601 execution date, when executed. */\n executionDateIso?: string;\n /** Operator display name for the phase. */\n operator?: string;\n /** Unique Device Identifier / lot string for traceable materials. */\n udi?: string;\n}\n\n/** Phase progress summary + optional drill-down detail. */\nexport interface CarePlanEntryPhases {\n /** Number of executed phases. */\n executed: number;\n /** Total number of phases. */\n total: number;\n /** Optional per-phase breakdown rendered inside the Collapsible. */\n detail?: CarePlanEntryPhaseDetail[];\n}\n\n/** Operator the line is assigned to. */\nexport interface CarePlanEntryOperator {\n /** Operator display name (consumer-localised). */\n name: string;\n}\n\n/** Curated read-only handle exposed to the agent registry. */\nexport interface CarePlanEntryCardHandle {\n /** Whether the line is marked executed. */\n isDone: () => boolean;\n /** Phase progress as `{ executed, total }` — counts only, no PHI. */\n getPhaseProgress: () => { executed: number; total: number };\n}\n\nexport interface CarePlanEntryCardProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'aria-label' | 'title' | 'children'\n> {\n /**\n * Stable instance id — surfaced as `data-component-id` for the agent\n * registry and used to wire up the heading ↔ region relationship.\n */\n id?: string;\n /** Treatment / service name. Rendered as the line heading. */\n careName: string;\n /** Optional treatment code (e.g. tariff code) shown beside the name. */\n code?: string;\n /** Optional secondary label (e.g. category) under the name. */\n label?: string;\n /** FDI tooth codes the line applies to (e.g. `['16', '36']`). */\n elements?: string[];\n /** Whether the line has been executed / completed. */\n done?: boolean;\n /** ISO-8601 execution date — rendered next to the \"done\" badge. */\n executionDateIso?: string;\n /** A planned appointment the line is scheduled into, when not yet done. */\n plannedAppointment?: CarePlanEntryPlannedAppointment;\n /** Operator the line is assigned to. */\n operator?: CarePlanEntryOperator;\n /** Price breakdown (list / discounted). */\n price?: CarePlanEntryPrice;\n /** Phase progress + optional drill-down detail. */\n phases?: CarePlanEntryPhases;\n /** Whether the line has been billed / invoiced. */\n billed?: boolean;\n /** Whether the line falls outside the accepted estimate. */\n outsideOfEstimate?: boolean;\n /** Count of attached notes — rendered as a neutral count badge when > 0. */\n notesCount?: number;\n /**\n * How to render `elements`: `'chips'` (default) lists each FDI code as a\n * Tag; `'scheme'` renders a read-only `ToothScheme` highlighting them.\n */\n toothDisplay?: 'scheme' | 'chips';\n /** BCP 47 locale override for dates / currency. Defaults to i18n.language. */\n locale?: string;\n /** ISO 4217 currency code for the price chip. Defaults to `EUR`. */\n currency?: string;\n /**\n * `elevated` (default) paints the kit card chrome; `flat` drops it for use\n * inside an existing Card / Sheet.\n */\n surface?: 'flat' | 'elevated';\n /** Accessible label override for the line region. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nconst DEFAULT_CURRENCY = 'EUR';\n\n/**\n * Map the FDI element codes to a `ToothScheme` conditions shortcut. Codes\n * outside the FDI vocabulary are dropped (the scheme ignores unknown ids).\n * Every applied tooth is flagged `filled` so the display-mode chart marks\n * them with both colour and pattern — colour-not-alone.\n */\nfunction elementsToConditions(\n elements: string[],\n): Partial<Record<FdiId, ToothCondition[]>> {\n const conditions: Partial<Record<FdiId, ToothCondition[]>> = {};\n for (const code of elements) {\n conditions[code as FdiId] = ['filled'];\n }\n return conditions;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const CarePlanEntryCard = forwardRef<\n HTMLDivElement,\n CarePlanEntryCardProps\n>(\n (\n {\n id,\n careName,\n code,\n label,\n elements,\n done = false,\n executionDateIso,\n plannedAppointment,\n operator,\n price,\n phases,\n billed = false,\n outsideOfEstimate = false,\n notesCount,\n toothDisplay = 'chips',\n locale,\n currency = DEFAULT_CURRENCY,\n surface = 'elevated',\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const headingId = useId();\n const phasesLabelId = useId();\n const detailTriggerId = useId();\n const detailContentId = useId();\n const activeLocale = locale ?? i18n.language ?? 'en';\n\n useAgentRegistration(\n carePlanEntryCardAgent,\n {\n isDone: () => done,\n getPhaseProgress: () => ({\n executed: phases?.executed ?? 0,\n total: phases?.total ?? 0,\n }),\n },\n id,\n );\n\n const hasElements = !!elements && elements.length > 0;\n const hasPhaseDetail = !!phases?.detail && phases.detail.length > 0;\n\n // Price: prefer the discounted amount when present; show the list price\n // struck through beside it. Both are \"to-invoice\" until billed, then\n // settled.\n const priceState = billed ? 'settled' : 'to-invoice';\n const listCents = price?.priceCents;\n const discountedCents = price?.discountedPriceCents;\n const hasDiscount =\n discountedCents !== undefined &&\n listCents !== undefined &&\n discountedCents < listCents;\n const payableCents = discountedCents ?? listCents;\n\n const formatMoney = (cents: number): string =>\n new Intl.NumberFormat(activeLocale, {\n style: 'currency',\n currency,\n }).format(cents / 100);\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabel ? undefined : headingId}\n data-component=\"care-plan-entry-card\"\n data-component-id={id}\n data-done={done ? 'true' : 'false'}\n id={id}\n className={entitySurfaceVariants({ surface, className })}\n {...rest}\n >\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {/* Heading row: name + code + trailing status flags */}\n <div className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-baseline ds:gap-[var(--spacing-xs)]\">\n <h3\n id={headingId}\n className=\"type-title-item ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {careName}\n </h3>\n {code ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)] ds:tabular-nums\">\n {code}\n </span>\n ) : null}\n </div>\n {label ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {label}\n </span>\n ) : null}\n </div>\n\n <div className=\"ds:flex ds:shrink-0 ds:flex-wrap ds:items-center ds:justify-end ds:gap-[var(--spacing-2xs)]\">\n {done ? (\n <Badge variant=\"success\" size=\"sm\" withDot>\n {t('carePlanEntryCard.flag.done', 'Done')}\n </Badge>\n ) : null}\n {outsideOfEstimate ? (\n <Badge variant=\"warning\" size=\"sm\" withDot>\n {t(\n 'carePlanEntryCard.flag.outsideOfEstimate',\n 'Outside estimate',\n )}\n </Badge>\n ) : null}\n {billed ? (\n <Badge variant=\"neutral\" size=\"sm\">\n {t('carePlanEntryCard.flag.billed', 'Billed')}\n </Badge>\n ) : null}\n {typeof notesCount === 'number' && notesCount > 0 ? (\n <Badge\n variant=\"neutral\"\n size=\"sm\"\n aria-label={t('carePlanEntryCard.notesLabel', {\n count: notesCount,\n defaultValue: '{{count}} notes',\n })}\n >\n {notesCount}\n </Badge>\n ) : null}\n </div>\n </div>\n\n {/* Elements: tooth scheme (display mode) or FDI tag chips */}\n {hasElements ? (\n toothDisplay === 'scheme' ? (\n <ToothScheme\n mode=\"display\"\n conditions={elementsToConditions(elements)}\n ariaLabel={t('carePlanEntryCard.toothSchemeLabel', {\n count: elements.length,\n defaultValue: 'Teeth involved: {{count}}',\n })}\n />\n ) : (\n <div\n role=\"list\"\n aria-label={t(\n 'carePlanEntryCard.elementsLabel',\n 'Teeth involved',\n )}\n className=\"ds:flex ds:flex-wrap ds:gap-[var(--spacing-2xs)]\"\n >\n {elements.map((element) => (\n <div role=\"listitem\" key={element}>\n <Tag label={element} variant=\"info\" size=\"sm\" />\n </div>\n ))}\n </div>\n )\n ) : null}\n\n {/* Schedule / execution line */}\n {done && executionDateIso ? (\n <p className=\"type-body-sm ds:m-0 ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n <span>{t('carePlanEntryCard.executedOn', 'Executed on')}</span>\n <Timestamp\n value={executionDateIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n {operator ? (\n <span>\n {t('carePlanEntryCard.byOperator', {\n operator: operator.name,\n defaultValue: 'by {{operator}}',\n })}\n </span>\n ) : null}\n </p>\n ) : plannedAppointment ? (\n <p className=\"type-body-sm ds:m-0 ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n <span>{t('carePlanEntryCard.plannedFor', 'Planned for')}</span>\n <Timestamp\n value={plannedAppointment.dateIso}\n format=\"absolute\"\n locale={activeLocale}\n />\n {operator ? (\n <span>\n {t('carePlanEntryCard.byOperator', {\n operator: operator.name,\n defaultValue: 'by {{operator}}',\n })}\n </span>\n ) : null}\n </p>\n ) : operator ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t('carePlanEntryCard.assignedTo', {\n operator: operator.name,\n defaultValue: 'Assigned to {{operator}}',\n })}\n </p>\n ) : null}\n\n {/* Phase progress */}\n {phases && phases.total > 0 ? (\n <Progress\n value={phases.executed}\n max={phases.total}\n size=\"sm\"\n aria-label={t('carePlanEntryCard.phasesLabel', {\n executed: phases.executed,\n total: phases.total,\n defaultValue: 'Phases: {{executed}} of {{total}} executed',\n })}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]\">\n <Progress.Label id={phasesLabelId}>\n {t('carePlanEntryCard.phasesHeading', 'Phases')}\n </Progress.Label>\n <span className=\"type-body-sm ds:tabular-nums ds:text-[color:var(--muted-foreground)]\">\n {t('carePlanEntryCard.phasesCount', {\n executed: phases.executed,\n total: phases.total,\n defaultValue: '{{executed}} / {{total}}',\n })}\n </span>\n </div>\n </Progress>\n ) : null}\n\n {/* Footer: price + (optional) phase-detail disclosure */}\n {payableCents !== undefined || hasPhaseDetail ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {payableCents !== undefined ? (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <TransactionChip\n state={priceState}\n amount={payableCents / 100}\n currency={currency}\n locale={activeLocale}\n size=\"md\"\n />\n {hasDiscount && listCents !== undefined ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)] ds:line-through ds:tabular-nums\">\n {formatMoney(listCents)}\n </span>\n ) : null}\n {hasDiscount && price?.discountPercentage !== undefined ? (\n <Badge variant=\"success\" size=\"sm\">\n {t('carePlanEntryCard.discountLabel', {\n percentage: price.discountPercentage,\n defaultValue: '-{{percentage}}%',\n })}\n </Badge>\n ) : null}\n </div>\n ) : null}\n\n {hasPhaseDetail ? (\n <Collapsible\n variant=\"default\"\n className=\"ds:ms-auto ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n id={detailTriggerId}\n aria-controls={detailContentId}\n className=\"ds:group ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)] ds:rounded-[var(--radius-sm)] ds:border-0 ds:bg-transparent type-body-sm ds:text-[color:var(--foreground)] ds:cursor-pointer ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]\"\n >\n <span>\n {t(\n 'carePlanEntryCard.phaseDetail.toggle',\n 'Phase detail',\n )}\n </span>\n <ChevronDown\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--muted-foreground)] ds:transition-transform ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none ds:group-data-[state=open]:rotate-180\"\n />\n </button>\n </CollapsibleTrigger>\n <CollapsibleContent\n id={detailContentId}\n aria-labelledby={detailTriggerId}\n >\n <ul className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-xs)] ds:p-0\">\n {phases?.detail?.map((phase, index) => (\n <PhaseDetailRow\n key={`${phase.label}-${index}`}\n phase={phase}\n locale={activeLocale}\n />\n ))}\n </ul>\n </CollapsibleContent>\n </Collapsible>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n );\n },\n);\n\nCarePlanEntryCard.displayName = 'CarePlanEntryCard';\n\n/* -------------------------------------------------------------------- */\n/* PhaseDetailRow — one row inside the per-phase Collapsible */\n/* -------------------------------------------------------------------- */\n\nfunction PhaseDetailRow({\n phase,\n locale,\n}: {\n phase: CarePlanEntryPhaseDetail;\n locale: string;\n}): ReactNode {\n const { t } = useTranslation();\n return (\n <li className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n <Badge variant={phase.executed ? 'success' : 'neutral'} size=\"sm\" withDot>\n {phase.executed\n ? t('carePlanEntryCard.phaseDetail.executed', 'Executed')\n : t('carePlanEntryCard.phaseDetail.pending', 'Pending')}\n </Badge>\n <span className=\"type-body-sm ds:text-[color:var(--foreground)]\">\n {phase.label}\n </span>\n {phase.executed && phase.executionDateIso ? (\n <Timestamp\n value={phase.executionDateIso}\n format=\"absolute\"\n locale={locale}\n />\n ) : null}\n {phase.operator ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t('carePlanEntryCard.byOperator', {\n operator: phase.operator,\n defaultValue: 'by {{operator}}',\n })}\n </span>\n ) : null}\n {phase.udi ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)] ds:tabular-nums\">\n {t('carePlanEntryCard.phaseDetail.udi', {\n udi: phase.udi,\n defaultValue: 'UDI {{udi}}',\n })}\n </span>\n ) : null}\n </li>\n );\n}\n\nexport type CarePlanEntryCardSurface = NonNullable<\n VariantProps<typeof entitySurfaceVariants>['surface']\n>;\n"],"names":["carePlanEntryCardAgent","handle","DEFAULT_CURRENCY","elementsToConditions","elements","conditions","code","CarePlanEntryCard","forwardRef","id","careName","label","done","executionDateIso","plannedAppointment","operator","price","phases","billed","outsideOfEstimate","notesCount","toothDisplay","locale","currency","surface","ariaLabel","className","rest","ref","t","i18n","useTranslation","headingId","useId","phasesLabelId","detailTriggerId","detailContentId","activeLocale","useAgentRegistration","hasElements","hasPhaseDetail","priceState","listCents","discountedCents","hasDiscount","payableCents","formatMoney","cents","jsx","entitySurfaceVariants","jsxs","Badge","ToothScheme","element","Tag","Timestamp","Progress","TransactionChip","Collapsible","CollapsibleTrigger","ChevronDown","CollapsibleContent","phase","index","PhaseDetailRow"],"mappings":";;;;;;;;;;;;;AAYO,MAAMA,KAAgE;AAAA,EAC3E,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAKJ,cAAc,CAAC,QAAQ;AAAA,EACvB,OAAO;AAAA,IACL,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACC,MAAWA,EAAO,OAAA;AAAA,IAAO;AAAA,IAElC,eAAe;AAAA,MACb,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWA,EAAO,iBAAA;AAAA,IAAiB;AAAA,EAC5C;AAAA,EAEF,SAAS,CAAA;AAAA,EACT,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,aAAa;AAAA,IAAA;AAAA,EACf;AAEJ,GC+GMC,KAAmB;AAQzB,SAASC,GACPC,GAC0C;AAC1C,QAAMC,IAAuD,CAAA;AAC7D,aAAWC,KAAQF;AACjB,IAAAC,EAAWC,CAAa,IAAI,CAAC,QAAQ;AAEvC,SAAOD;AACT;AAMO,MAAME,KAAoBC;AAAA,EAI/B,CACE;AAAA,IACE,IAAAC;AAAA,IACA,UAAAC;AAAA,IACA,MAAAJ;AAAA,IACA,OAAAK;AAAA,IACA,UAAAP;AAAA,IACA,MAAAQ,IAAO;AAAA,IACP,kBAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,QAAAC;AAAA,IACA,QAAAC,IAAS;AAAA,IACT,mBAAAC,IAAoB;AAAA,IACpB,YAAAC;AAAA,IACA,cAAAC,IAAe;AAAA,IACf,QAAAC;AAAA,IACA,UAAAC,IAAWrB;AAAA,IACX,SAAAsB,IAAU;AAAA,IACV,cAAcC;AAAA,IACd,WAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,MACG;;AACH,UAAM,EAAE,GAAAC,GAAG,MAAAC,EAAA,IAASC,EAAA,GACdC,IAAYC,EAAA,GACZC,IAAgBD,EAAA,GAChBE,IAAkBF,EAAA,GAClBG,IAAkBH,EAAA,GAClBI,IAAef,KAAUQ,EAAK,YAAY;AAEhD,IAAAQ;AAAA,MACEtC;AAAA,MACA;AAAA,QACE,QAAQ,MAAMY;AAAA,QACd,kBAAkB,OAAO;AAAA,UACvB,WAAUK,KAAA,gBAAAA,EAAQ,aAAY;AAAA,UAC9B,QAAOA,KAAA,gBAAAA,EAAQ,UAAS;AAAA,QAAA;AAAA,MAC1B;AAAA,MAEFR;AAAA,IAAA;AAGF,UAAM8B,IAAc,CAAC,CAACnC,KAAYA,EAAS,SAAS,GAC9CoC,IAAiB,CAAC,EAACvB,KAAA,QAAAA,EAAQ,WAAUA,EAAO,OAAO,SAAS,GAK5DwB,IAAavB,IAAS,YAAY,cAClCwB,IAAY1B,KAAA,gBAAAA,EAAO,YACnB2B,IAAkB3B,KAAA,gBAAAA,EAAO,sBACzB4B,IACJD,MAAoB,UACpBD,MAAc,UACdC,IAAkBD,GACdG,IAAeF,KAAmBD,GAElCI,IAAc,CAACC,MACnB,IAAI,KAAK,aAAaV,GAAc;AAAA,MAClC,OAAO;AAAA,MACP,UAAAd;AAAA,IAAA,CACD,EAAE,OAAOwB,IAAQ,GAAG;AAEvB,WACE,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAApB;AAAA,QACA,MAAK;AAAA,QACL,cAAYH;AAAA,QACZ,mBAAiBA,IAAY,SAAYO;AAAA,QACzC,kBAAe;AAAA,QACf,qBAAmBvB;AAAA,QACnB,aAAWG,IAAO,SAAS;AAAA,QAC3B,IAAAH;AAAA,QACA,WAAWwC,GAAsB,EAAE,SAAAzB,GAAS,WAAAE,GAAW;AAAA,QACtD,GAAGC;AAAA,QAEJ,UAAA,gBAAAuB,EAAC,OAAA,EAAI,WAAU,kDAEb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qDACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,wEACb,UAAA;AAAA,cAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qEACb,UAAA;AAAA,gBAAA,gBAAAF;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,IAAIhB;AAAA,oBACJ,WAAU;AAAA,oBAET,UAAAtB;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEFJ,IACC,gBAAA0C,EAAC,QAAA,EAAK,WAAU,qEACb,aACH,IACE;AAAA,cAAA,GACN;AAAA,cACCrC,IACC,gBAAAqC,EAAC,QAAA,EAAK,WAAU,wDACb,aACH,IACE;AAAA,YAAA,GACN;AAAA,YAEA,gBAAAE,EAAC,OAAA,EAAI,WAAU,+FACZ,UAAA;AAAA,cAAAtC,IACC,gBAAAoC,EAACG,GAAA,EAAM,SAAQ,WAAU,MAAK,MAAK,SAAO,IACvC,UAAAtB,EAAE,+BAA+B,MAAM,EAAA,CAC1C,IACE;AAAA,cACHV,sBACEgC,GAAA,EAAM,SAAQ,WAAU,MAAK,MAAK,SAAO,IACvC,UAAAtB;AAAA,gBACC;AAAA,gBACA;AAAA,cAAA,GAEJ,IACE;AAAA,cACHX,IACC,gBAAA8B,EAACG,GAAA,EAAM,SAAQ,WAAU,MAAK,MAC3B,UAAAtB,EAAE,iCAAiC,QAAQ,EAAA,CAC9C,IACE;AAAA,cACH,OAAOT,KAAe,YAAYA,IAAa,IAC9C,gBAAA4B;AAAA,gBAACG;AAAA,gBAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,cAAYtB,EAAE,gCAAgC;AAAA,oBAC5C,OAAOT;AAAA,oBACP,cAAc;AAAA,kBAAA,CACf;AAAA,kBAEA,UAAAA;AAAA,gBAAA;AAAA,cAAA,IAED;AAAA,YAAA,EAAA,CACN;AAAA,UAAA,GACF;AAAA,UAGCmB,IACClB,MAAiB,WACf,gBAAA2B;AAAA,YAACI;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,YAAYjD,GAAqBC,CAAQ;AAAA,cACzC,WAAWyB,EAAE,sCAAsC;AAAA,gBACjD,OAAOzB,EAAS;AAAA,gBAChB,cAAc;AAAA,cAAA,CACf;AAAA,YAAA;AAAA,UAAA,IAGH,gBAAA4C;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAYnB;AAAA,gBACV;AAAA,gBACA;AAAA,cAAA;AAAA,cAEF,WAAU;AAAA,cAET,YAAS,IAAI,CAACwB,MACb,gBAAAL,EAAC,OAAA,EAAI,MAAK,YACR,UAAA,gBAAAA,EAACM,GAAA,EAAI,OAAOD,GAAS,SAAQ,QAAO,MAAK,KAAA,CAAK,EAAA,GADtBA,CAE1B,CACD;AAAA,YAAA;AAAA,UAAA,IAGH;AAAA,UAGHzC,KAAQC,IACP,gBAAAqC,EAAC,KAAA,EAAE,WAAU,+HACX,UAAA;AAAA,YAAA,gBAAAF,EAAC,QAAA,EAAM,UAAAnB,EAAE,gCAAgC,aAAa,GAAE;AAAA,YACxD,gBAAAmB;AAAA,cAACO;AAAA,cAAA;AAAA,gBACC,OAAO1C;AAAA,gBACP,QAAO;AAAA,gBACP,QAAQwB;AAAA,cAAA;AAAA,YAAA;AAAA,YAETtB,IACC,gBAAAiC,EAAC,QAAA,EACE,UAAAnB,EAAE,gCAAgC;AAAA,cACjC,UAAUd,EAAS;AAAA,cACnB,cAAc;AAAA,YAAA,CACf,GACH,IACE;AAAA,UAAA,EAAA,CACN,IACED,IACF,gBAAAoC,EAAC,KAAA,EAAE,WAAU,+HACX,UAAA;AAAA,YAAA,gBAAAF,EAAC,QAAA,EAAM,UAAAnB,EAAE,gCAAgC,aAAa,GAAE;AAAA,YACxD,gBAAAmB;AAAA,cAACO;AAAA,cAAA;AAAA,gBACC,OAAOzC,EAAmB;AAAA,gBAC1B,QAAO;AAAA,gBACP,QAAQuB;AAAA,cAAA;AAAA,YAAA;AAAA,YAETtB,IACC,gBAAAiC,EAAC,QAAA,EACE,UAAAnB,EAAE,gCAAgC;AAAA,cACjC,UAAUd,EAAS;AAAA,cACnB,cAAc;AAAA,YAAA,CACf,GACH,IACE;AAAA,UAAA,GACN,IACEA,IACF,gBAAAiC,EAAC,OAAE,WAAU,+DACV,YAAE,gCAAgC;AAAA,YACjC,UAAUjC,EAAS;AAAA,YACnB,cAAc;AAAA,UAAA,CACf,GACH,IACE;AAAA,UAGHE,KAAUA,EAAO,QAAQ,IACxB,gBAAA+B;AAAA,YAACQ;AAAA,YAAA;AAAA,cACC,OAAOvC,EAAO;AAAA,cACd,KAAKA,EAAO;AAAA,cACZ,MAAK;AAAA,cACL,cAAYY,EAAE,iCAAiC;AAAA,gBAC7C,UAAUZ,EAAO;AAAA,gBACjB,OAAOA,EAAO;AAAA,gBACd,cAAc;AAAA,cAAA,CACf;AAAA,cAED,UAAA,gBAAAiC,EAAC,OAAA,EAAI,WAAU,yEACb,UAAA;AAAA,gBAAA,gBAAAF,EAACQ,EAAS,OAAT,EAAe,IAAItB,GACjB,UAAAL,EAAE,mCAAmC,QAAQ,GAChD;AAAA,gBACA,gBAAAmB,EAAC,QAAA,EAAK,WAAU,wEACb,YAAE,iCAAiC;AAAA,kBAClC,UAAU/B,EAAO;AAAA,kBACjB,OAAOA,EAAO;AAAA,kBACd,cAAc;AAAA,gBAAA,CACf,EAAA,CACH;AAAA,cAAA,EAAA,CACF;AAAA,YAAA;AAAA,UAAA,IAEA;AAAA,UAGH4B,MAAiB,UAAaL,IAC7B,gBAAAU,EAAC,OAAA,EAAI,WAAU,mEACZ,UAAA;AAAA,YAAAL,MAAiB,SAChB,gBAAAK,EAAC,OAAA,EAAI,WAAU,sDACb,UAAA;AAAA,cAAA,gBAAAF;AAAA,gBAACS;AAAA,gBAAA;AAAA,kBACC,OAAOhB;AAAA,kBACP,QAAQI,IAAe;AAAA,kBACvB,UAAAtB;AAAA,kBACA,QAAQc;AAAA,kBACR,MAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,cAENO,KAAeF,MAAc,SAC5B,gBAAAM,EAAC,QAAA,EAAK,WAAU,qFACb,UAAAF,EAAYJ,CAAS,EAAA,CACxB,IACE;AAAA,cACHE,MAAe5B,KAAA,gBAAAA,EAAO,wBAAuB,SAC5C,gBAAAgC,EAACG,GAAA,EAAM,SAAQ,WAAU,MAAK,MAC3B,UAAAtB,EAAE,mCAAmC;AAAA,gBACpC,YAAYb,EAAM;AAAA,gBAClB,cAAc;AAAA,cAAA,CACf,GACH,IACE;AAAA,YAAA,EAAA,CACN,IACE;AAAA,YAEHwB,IACC,gBAAAU;AAAA,cAACQ;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,WAAU;AAAA,gBAEV,UAAA;AAAA,kBAAA,gBAAAV,EAACW,GAAA,EAAmB,SAAO,IACzB,UAAA,gBAAAT;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,IAAIf;AAAA,sBACJ,iBAAeC;AAAA,sBACf,WAAU;AAAA,sBAEV,UAAA;AAAA,wBAAA,gBAAAY,EAAC,QAAA,EACE,UAAAnB;AAAA,0BACC;AAAA,0BACA;AAAA,wBAAA,GAEJ;AAAA,wBACA,gBAAAmB;AAAA,0BAACY;AAAA,0BAAA;AAAA,4BACC,eAAY;AAAA,4BACZ,WAAU;AAAA,0BAAA;AAAA,wBAAA;AAAA,sBACZ;AAAA,oBAAA;AAAA,kBAAA,GAEJ;AAAA,kBACA,gBAAAZ;AAAA,oBAACa;AAAA,oBAAA;AAAA,sBACC,IAAIzB;AAAA,sBACJ,mBAAiBD;AAAA,sBAEjB,UAAA,gBAAAa,EAAC,QAAG,WAAU,6EACX,sCAAQ,6BAAQ,IAAI,CAACc,GAAOC,MAC3B,gBAAAf;AAAA,wBAACgB;AAAA,wBAAA;AAAA,0BAEC,OAAAF;AAAA,0BACA,QAAQzB;AAAA,wBAAA;AAAA,wBAFH,GAAGyB,EAAM,KAAK,IAAIC,CAAK;AAAA,sBAAA,GAI/B,CACH;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACF;AAAA,cAAA;AAAA,YAAA,IAEA;AAAA,UAAA,EAAA,CACN,IACE;AAAA,QAAA,EAAA,CACN;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEAxD,GAAkB,cAAc;AAMhC,SAASyD,GAAe;AAAA,EACtB,OAAAF;AAAA,EACA,QAAAxC;AACF,GAGc;AACZ,QAAM,EAAE,GAAAO,EAAA,IAAME,EAAA;AACd,SACE,gBAAAmB,EAAC,MAAA,EAAG,WAAU,mEACZ,UAAA;AAAA,IAAA,gBAAAF,EAACG,KAAM,SAASW,EAAM,WAAW,YAAY,WAAW,MAAK,MAAK,SAAO,IACtE,UAAAA,EAAM,WACHjC,EAAE,0CAA0C,UAAU,IACtDA,EAAE,yCAAyC,SAAS,GAC1D;AAAA,IACA,gBAAAmB,EAAC,QAAA,EAAK,WAAU,kDACb,YAAM,OACT;AAAA,IACCc,EAAM,YAAYA,EAAM,mBACvB,gBAAAd;AAAA,MAACO;AAAA,MAAA;AAAA,QACC,OAAOO,EAAM;AAAA,QACb,QAAO;AAAA,QACP,QAAAxC;AAAA,MAAA;AAAA,IAAA,IAEA;AAAA,IACHwC,EAAM,WACL,gBAAAd,EAAC,UAAK,WAAU,qDACb,YAAE,gCAAgC;AAAA,MACjC,UAAUc,EAAM;AAAA,MAChB,cAAc;AAAA,IAAA,CACf,GACH,IACE;AAAA,IACHA,EAAM,MACL,gBAAAd,EAAC,UAAK,WAAU,qEACb,YAAE,qCAAqC;AAAA,MACtC,KAAKc,EAAM;AAAA,MACX,cAAc;AAAA,IAAA,CACf,GACH,IACE;AAAA,EAAA,GACN;AAEJ;"}
@@ -4,12 +4,12 @@ import { c as q } from "./index-D2ZczOXr.js";
4
4
  import { useTranslation as z } from "react-i18next";
5
5
  import { u as B } from "./registry-DvAUVLHh.js";
6
6
  import { F as S } from "./form-field-CahJzTxp.js";
7
- import { D as Y } from "./date-picker-CepI_oI2.js";
7
+ import { D as Y } from "./date-picker-B6NW_PS5.js";
8
8
  import { N as H } from "./number-input-Cgu2TtA8.js";
9
9
  import { C as M } from "./card-DPmk26CL.js";
10
10
  import { B as T } from "./badge-sTusUqZD.js";
11
11
  import { I as U } from "./insert-result-LCNTskNJ.js";
12
- import { a as m, c as V } from "./date-picker-variants-DfuooXEK.js";
12
+ import { a as m, c as V } from "./date-picker-variants-B9NLAfUK.js";
13
13
  import { C as J } from "./check-DrFSN__t.js";
14
14
  import { H as Q } from "./heart--qCA4ffe.js";
15
15
  import { c as X } from "./createLucideIcon-DhHxpK9K.js";
@@ -422,4 +422,4 @@ export {
422
422
  ie as L,
423
423
  se as p
424
424
  };
425
- //# sourceMappingURL=cycle-calculator-DmtYGhqq.js.map
425
+ //# sourceMappingURL=cycle-calculator-DVgxBfP0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cycle-calculator-DmtYGhqq.js","sources":["../../node_modules/lucide-react/dist/esm/icons/droplet.mjs","../../src/components/cycle-calculator/cycle-calculator.agent.ts","../../src/components/cycle-calculator/cycle.ts","../../src/components/cycle-calculator/cycle-calculator.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z\",\n key: \"c7niix\"\n }\n ]\n];\nconst Droplet = createLucideIcon(\"droplet\", __iconNode);\n\nexport { __iconNode, Droplet as default };\n//# sourceMappingURL=droplet.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — CycleCalculator. */\n/* */\n/* Menstrual-cycle predictor: takes a last-period date (+ optional cycle */\n/* and period lengths) and computes ovulation, fertile window and the */\n/* next few periods. The agent surface is the three inputs plus the */\n/* computed prediction; the handle is the curated `CycleCalculatorHandle` */\n/* (the public `ref` stays the root <div>, exactly as `slider.tsx` and */\n/* `bmi-calculator.tsx` keep theirs). */\n/* */\n/* Dates cross the boundary as local-time `yyyy-MM-dd` strings, never */\n/* `Date` objects, so nothing shifts a day under JSON/UTC serialisation. */\n/* */\n/* PHI (§7): never exposes patient identity — the slots return the */\n/* operator's own structural inputs (a date, two day counts) and the */\n/* dates derived from them, the same \"filter model\" precedent §7 sets. */\n/* See `src/docs/26-agent-readiness.mdx`. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { CycleCalculatorHandle } from './cycle-calculator';\n\n/** Shared JSON Schema fragment for a local-time calendar date. */\nconst isoDate = {\n type: 'string',\n pattern: '^\\\\d{4}-\\\\d{2}-\\\\d{2}$',\n} as const;\n\nexport const cycleCalculatorAgent: AgentAdapter<CycleCalculatorHandle> = {\n id: 'cycle-calculator',\n // set_value → the three `set_*` actions + the `inputs` state slot.\n capabilities: ['set_value'],\n state: {\n inputs: {\n type: '{ lastPeriodStart: string | null, cycleLength: number | null, periodLength: number | null }',\n descriptionKey: 'ui.agent.cycleCalculator.state.inputs',\n description:\n 'The three cycle inputs as entered — last-period start date (`yyyy-MM-dd`), average cycle length in days, and period (bleed) length in days. Null where unset.',\n read: (handle) => handle.getInputs(),\n },\n result: {\n type: '{ ovulation: string, fertileWindow: { start: string, end: string }, nextPeriod: string, periodRange: { start: string, end: string } | null, upcomingPeriods: string[] } | null',\n descriptionKey: 'ui.agent.cycleCalculator.state.result',\n description:\n 'Computed prediction — ovulation date, fertile window, next period, current bleed range and the next few period starts, all `yyyy-MM-dd`. Null until a last-period date is set.',\n read: (handle) => handle.getResult(),\n },\n },\n actions: {\n set_last_period: {\n // Drives the same local input state a user types into; nothing is\n // persisted to a record, and the value is reversible in the same UI.\n safety: 'write',\n argsType: '{ date: string | null }',\n argsSchema: {\n type: 'object',\n properties: {\n date: {\n oneOf: [\n { ...isoDate, description: 'Local calendar date, `yyyy-MM-dd`.' },\n { type: 'null' },\n ],\n description:\n 'Start date of the last period, or null to clear it. Must not be in the future.',\n },\n },\n required: ['date'],\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the date was applied.',\n },\n errors: [\n 'Returns false for an unparseable date or a date in the future — the on-screen DatePicker caps at today.',\n ],\n examples: [\n { args: { date: '2026-08-01' }, note: 'Last period started 1 August.' },\n ],\n descriptionKey: 'ui.agent.cycleCalculator.actions.setLastPeriod',\n description:\n 'Set the start date of the last period. This is the only required input — the prediction stays null without it.',\n invoke: (handle, args: { date: string | null }) =>\n handle.setLastPeriod(args.date),\n },\n set_cycle_length: {\n safety: 'write',\n argsType: '{ days: number | null }',\n argsSchema: {\n type: 'object',\n properties: {\n days: {\n oneOf: [\n { type: 'integer', minimum: 20, maximum: 45 },\n { type: 'null' },\n ],\n description:\n 'Average cycle length in days (20–45), or null to fall back to the 28-day default.',\n },\n },\n required: ['days'],\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the value was applied.',\n },\n errors: [\n 'Returns false outside 20–45 days — the same bounds the on-screen NumberInput enforces.',\n ],\n descriptionKey: 'ui.agent.cycleCalculator.actions.setCycleLength',\n description:\n 'Set the average cycle length in days. Shifts ovulation, the fertile window and every upcoming period.',\n invoke: (handle, args: { days: number | null }) =>\n handle.setCycleLength(args.days),\n },\n set_period_length: {\n safety: 'write',\n argsType: '{ days: number | null }',\n argsSchema: {\n type: 'object',\n properties: {\n days: {\n oneOf: [\n { type: 'integer', minimum: 1, maximum: 14 },\n { type: 'null' },\n ],\n description:\n 'Period (bleed) length in days (1–14), or null to omit the bleed range.',\n },\n },\n required: ['days'],\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the value was applied.',\n },\n errors: [\n 'Returns false outside 1–14 days — the same bounds the on-screen NumberInput enforces.',\n ],\n descriptionKey: 'ui.agent.cycleCalculator.actions.setPeriodLength',\n description:\n 'Set the period (bleed) length in days. Optional — it only adds the current bleed range to the result.',\n invoke: (handle, args: { days: number | null }) =>\n handle.setPeriodLength(args.days),\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'cycle-calculator',\n description: 'Marks the CycleCalculator wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Also the registry key — without an `id` the instance does not register and only the DOM channel works.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* Menstrual-cycle prediction — pure, framework-free, unit-testable. */\n/* */\n/* Uses the standard fixed-luteal-phase model: ovulation falls ~14 days */\n/* before the next period, so on a cycle of length L ovulation is day */\n/* (L − 14). The fertile window spans the 5 days before ovulation */\n/* (sperm survival) through 1 day after (oocyte viability). */\n/* ------------------------------------------------------------------ */\n\nimport { addDays } from 'date-fns';\n\n/** Standard menstrual-cycle length. */\nexport const DEFAULT_CYCLE_LENGTH = 28;\n/** Luteal phase is biologically near-constant at ~14 days. */\nexport const LUTEAL_PHASE_DAYS = 14;\n/** Sperm survive up to ~5 days before ovulation. */\nexport const FERTILE_DAYS_BEFORE = 5;\n/** The oocyte is viable ~1 day after ovulation. */\nexport const FERTILE_DAYS_AFTER = 1;\n\nexport interface CycleInput {\n /** First day of the most recent period. */\n lastPeriodStart: Date;\n /** Average cycle length in days. Defaults to 28. */\n cycleLength?: number;\n /** Period (bleed) length in days. Optional — used for the period range. */\n periodLength?: number;\n}\n\nexport interface DateRange {\n start: Date;\n end: Date;\n}\n\nexport interface CyclePrediction {\n /** Start date of the next period. */\n nextPeriod: Date;\n /** Estimated ovulation date. */\n ovulation: Date;\n /** Fertile window (5 days before ovulation → 1 day after). */\n fertileWindow: DateRange;\n /** Start dates of the next few periods (length = `occurrences`). */\n upcomingPeriods: Date[];\n /**\n * The current period's bleed range (first day → last day), or `null` when no\n * `periodLength` was given.\n */\n periodRange: DateRange | null;\n}\n\n/**\n * Predict ovulation, the fertile window and upcoming periods from the last\n * period's start date. `occurrences` controls how many future periods to\n * list (default 3).\n */\nexport function predictCycle(\n input: CycleInput,\n occurrences = 3,\n): CyclePrediction {\n const cycle = input.cycleLength ?? DEFAULT_CYCLE_LENGTH;\n const { lastPeriodStart } = input;\n\n const ovulation = addDays(lastPeriodStart, cycle - LUTEAL_PHASE_DAYS);\n const fertileWindow: DateRange = {\n start: addDays(ovulation, -FERTILE_DAYS_BEFORE),\n end: addDays(ovulation, FERTILE_DAYS_AFTER),\n };\n const nextPeriod = addDays(lastPeriodStart, cycle);\n const upcomingPeriods = Array.from({ length: occurrences }, (_, i) =>\n addDays(lastPeriodStart, cycle * (i + 1)),\n );\n const periodRange: DateRange | null =\n input.periodLength && input.periodLength > 0\n ? {\n start: lastPeriodStart,\n end: addDays(lastPeriodStart, input.periodLength - 1),\n }\n : null;\n\n return { nextPeriod, ovulation, fertileWindow, upcomingPeriods, periodRange };\n}\n","/* ------------------------------------------------------------------ */\n/* CycleCalculator — predict ovulation, fertile window and upcoming */\n/* periods from the last period's start date. */\n/* */\n/* Maths lives in `./cycle` (pure, separately tested). */\n/* ------------------------------------------------------------------ */\n\nimport { forwardRef, useEffect, useMemo, useRef, useState } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { format, isAfter, parseISO } from 'date-fns';\nimport { Heart, Check, Droplet } from 'lucide-react';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { cycleCalculatorAgent } from './cycle-calculator.agent';\nimport { FormField } from '../form-field';\nimport { DatePicker } from '../date-picker';\nimport { NumberInput } from '../number-input';\nimport { Card } from '../card';\nimport { Badge } from '../badge';\nimport {\n InsertButton,\n type InsertPayload,\n type InsertVariant,\n type InsertMode,\n} from '../_shared/insert-result';\nimport {\n type CyclePrediction,\n predictCycle,\n DEFAULT_CYCLE_LENGTH,\n} from './cycle';\n\nconst rootVariants = cva('ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]', {\n variants: {\n width: { full: 'ds:w-full', auto: 'ds:inline-flex' },\n },\n defaultVariants: { width: 'full' },\n});\n\n/**\n * DS token NAME backing the result-card chip — the fertile window is the\n * headline fertility datum, shown on screen with the `accent` Badge variant\n * (which fills `--accent`). The card chip reuses that token so the inserted\n * PNG chip matches the on-screen fertile-window badge.\n */\nconst HIGHLIGHT_TOKEN = '--accent';\n\n/* ------------------------------------------------------------------ */\n/* Agent boundary */\n/* */\n/* Dates cross the agent boundary as local-time `yyyy-MM-dd` strings, */\n/* never `Date` objects — a Date JSON-serialises to UTC and silently */\n/* shifts the day for anyone east or west of Greenwich. */\n/* ------------------------------------------------------------------ */\n\nconst toIsoDate = (d: Date): string => format(d, 'yyyy-MM-dd');\n\nconst fromIsoDate = (iso: string): Date | null => {\n const d = parseISO(iso);\n return Number.isNaN(d.getTime()) ? null : d;\n};\n\n/** UI input bounds, mirrored by the agent handle so it can't out-type a user. */\nconst CYCLE_LENGTH_RANGE = { min: 20, max: 45 } as const;\nconst PERIOD_LENGTH_RANGE = { min: 1, max: 14 } as const;\n\nconst inRange = (\n n: number | null,\n { min, max }: { min: number; max: number },\n): boolean => n === null || (Number.isFinite(n) && n >= min && n <= max);\n\n/** `CyclePrediction` projected onto the agent boundary — ISO dates, no Dates. */\nexport interface CyclePredictionSnapshot {\n /** Estimated ovulation date, `yyyy-MM-dd`. */\n ovulation: string;\n /** Fertile window, `yyyy-MM-dd` endpoints. */\n fertileWindow: { start: string; end: string };\n /** Start of the next period, `yyyy-MM-dd`. */\n nextPeriod: string;\n /** Current period's bleed range, or null when no period length was given. */\n periodRange: { start: string; end: string } | null;\n /** Start dates of the next few periods, `yyyy-MM-dd`. */\n upcomingPeriods: string[];\n}\n\n/**\n * Curated imperative handle for agent / external automation. Reads the three\n * cycle inputs and the computed prediction, and drives the inputs the way a\n * user would. Never exposes patient identity — only structural dates and day\n * counts. Consumed by `cycle-calculator.agent.ts`; the public `ref` stays the\n * root DOM element.\n */\nexport interface CycleCalculatorHandle {\n /** Current inputs — ISO date + day counts, or null when unset. */\n getInputs: () => {\n lastPeriodStart: string | null;\n cycleLength: number | null;\n periodLength: number | null;\n };\n /** Computed prediction, or null until a last-period date is set. */\n getResult: () => CyclePredictionSnapshot | null;\n /** Set the last period's start date (`yyyy-MM-dd`, not in the future). */\n setLastPeriod: (isoDate: string | null) => boolean;\n /** Set the average cycle length in days (20–45). */\n setCycleLength: (days: number | null) => boolean;\n /** Set the period (bleed) length in days (1–14). */\n setPeriodLength: (days: number | null) => boolean;\n}\n\nexport interface CycleCalculatorProps extends VariantProps<\n typeof rootVariants\n> {\n /** Initial cycle length in days. Defaults to 28. */\n defaultCycleLength?: number;\n /** Fires whenever a prediction can be computed (and `null` when it can't). */\n onResultChange?: (result: CyclePrediction | null) => void;\n /** When provided, shows the result-action buttons that emit / copy the result. */\n onInsert?: (payload: InsertPayload) => void;\n /**\n * Which verb the result button performs. Defaults to `'insert'`.\n * Use `'copy'` in an app-shell surface (no editor to insert into) — the\n * button writes the result to the clipboard as a multi-format `ClipboardItem`.\n */\n insertVariant?: InsertVariant;\n /** `copy` variant only — fired after a successful clipboard write. */\n onCopy?: (mode: InsertMode) => void;\n /** `copy` variant only — fired if the clipboard write can't proceed. */\n onError?: (error: unknown) => void;\n /**\n * Brand wordmark printed in the inserted/copied result-card footer.\n * Omitted → no brand line (and no footer hairline); a string → that custom\n * brand; `false` → no brand line. Brand is opt-in.\n */\n insertBrand?: string | false;\n /** Opaque instance id, emitted as `data-component-id`. */\n id?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n}\n\nexport const CycleCalculator = forwardRef<HTMLDivElement, CycleCalculatorProps>(\n (\n {\n defaultCycleLength = DEFAULT_CYCLE_LENGTH,\n onResultChange,\n onInsert,\n insertVariant = 'insert',\n onCopy,\n onError,\n insertBrand,\n id,\n width,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const [lastPeriod, setLastPeriod] = useState<Date | undefined>(undefined);\n const [cycleLength, setCycleLength] = useState<number | null>(\n defaultCycleLength,\n );\n const [periodLength, setPeriodLength] = useState<number | null>(null);\n\n const result = useMemo<CyclePrediction | null>(() => {\n if (!lastPeriod) return null;\n return predictCycle({\n lastPeriodStart: lastPeriod,\n cycleLength: cycleLength ?? DEFAULT_CYCLE_LENGTH,\n periodLength: periodLength ?? undefined,\n });\n }, [lastPeriod, cycleLength, periodLength]);\n\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }),\n [i18n.language],\n );\n\n useEffect(() => {\n onResultChange?.(result);\n }, [result, onResultChange]);\n\n const today = useMemo(() => new Date(), []);\n\n /* ── Agent handle ────────────────────────────────────────────────── */\n const liveRef = useRef({ lastPeriod, cycleLength, periodLength, result });\n liveRef.current = { lastPeriod, cycleLength, periodLength, result };\n\n const agentHandle = useMemo<CycleCalculatorHandle>(\n () => ({\n getInputs: () => ({\n lastPeriodStart: liveRef.current.lastPeriod\n ? toIsoDate(liveRef.current.lastPeriod)\n : null,\n cycleLength: liveRef.current.cycleLength,\n periodLength: liveRef.current.periodLength,\n }),\n getResult: () => {\n const r = liveRef.current.result;\n if (!r) return null;\n return {\n ovulation: toIsoDate(r.ovulation),\n fertileWindow: {\n start: toIsoDate(r.fertileWindow.start),\n end: toIsoDate(r.fertileWindow.end),\n },\n nextPeriod: toIsoDate(r.nextPeriod),\n periodRange: r.periodRange\n ? {\n start: toIsoDate(r.periodRange.start),\n end: toIsoDate(r.periodRange.end),\n }\n : null,\n upcomingPeriods: r.upcomingPeriods.map(toIsoDate),\n };\n },\n setLastPeriod: (isoDate) => {\n if (isoDate === null) {\n setLastPeriod(undefined);\n return true;\n }\n const parsed = fromIsoDate(isoDate);\n // The DatePicker caps at today; the handle honours the same bound.\n if (!parsed || isAfter(parsed, new Date())) return false;\n setLastPeriod(parsed);\n return true;\n },\n setCycleLength: (days) => {\n if (!inRange(days, CYCLE_LENGTH_RANGE)) return false;\n setCycleLength(days);\n return true;\n },\n setPeriodLength: (days) => {\n if (!inRange(days, PERIOD_LENGTH_RANGE)) return false;\n setPeriodLength(days);\n return true;\n },\n }),\n [],\n );\n useAgentRegistration(cycleCalculatorAgent, agentHandle, id);\n\n const fmt = (d: Date): string => dateFormatter.format(d);\n\n return (\n <div\n ref={ref}\n data-component=\"cycle-calculator\"\n data-component-id={id}\n className={rootVariants({ width, className })}\n >\n <div className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-2\">\n <FormField label={t('cycleCalculator.lastPeriod')}>\n <DatePicker\n value={lastPeriod}\n onChange={setLastPeriod}\n maxDate={today}\n />\n </FormField>\n <FormField\n label={t('cycleCalculator.cycleLength')}\n description={t('cycleCalculator.cycleLengthHint')}\n >\n <NumberInput\n mode=\"integer\"\n min={CYCLE_LENGTH_RANGE.min}\n max={CYCLE_LENGTH_RANGE.max}\n value={cycleLength}\n onChange={setCycleLength}\n />\n </FormField>\n <FormField\n label={t('cycleCalculator.periodLength')}\n description={t('cycleCalculator.periodLengthHint')}\n >\n <NumberInput\n mode=\"integer\"\n min={PERIOD_LENGTH_RANGE.min}\n max={PERIOD_LENGTH_RANGE.max}\n value={periodLength}\n onChange={setPeriodLength}\n />\n </FormField>\n </div>\n\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {result\n ? `${t('cycleCalculator.ovulation')}: ${fmt(result.ovulation)}. ${t(\n 'cycleCalculator.nextPeriod',\n )}: ${fmt(result.nextPeriod)}.`\n : ''}\n </p>\n\n {result ? (\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <dl className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-3\">\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)] ds:text-center\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.ovulation')}\n </dt>\n <dd>\n <Badge\n variant=\"success\"\n size=\"lg\"\n leading={<Check aria-hidden />}\n >\n {fmt(result.ovulation)}\n </Badge>\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)] ds:text-center\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.fertileWindow')}\n </dt>\n <dd>\n <Badge\n variant=\"accent\"\n size=\"lg\"\n leading={<Heart aria-hidden />}\n >\n {fmt(result.fertileWindow.start)} –{' '}\n {fmt(result.fertileWindow.end)}\n </Badge>\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)] ds:text-center\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.nextPeriod')}\n </dt>\n <dd>\n <Badge\n variant=\"error\"\n size=\"lg\"\n leading={<Droplet aria-hidden />}\n >\n {fmt(result.nextPeriod)}\n </Badge>\n </dd>\n </div>\n </dl>\n\n {result.periodRange ? (\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.periodRange')}\n </span>\n <span className=\"type-body ds:text-foreground\">\n {fmt(result.periodRange.start)} –{' '}\n {fmt(result.periodRange.end)}\n </span>\n </div>\n ) : null}\n\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.upcomingPeriods')}\n </span>\n <ul className=\"ds:flex ds:flex-wrap ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-2xs)]\">\n {result.upcomingPeriods.map((d) => (\n <li\n key={d.getTime()}\n className=\"type-body ds:text-foreground\"\n >\n {fmt(d)}\n </li>\n ))}\n </ul>\n </div>\n\n {insertVariant === 'copy' || onInsert ? (\n <InsertButton\n onInsert={onInsert}\n variant={insertVariant}\n onCopy={onCopy}\n onError={onError}\n card={{\n title: t('insert.title.cycle'),\n icon: 'heart',\n highlight: `${fmt(result.fertileWindow.start)} – ${fmt(\n result.fertileWindow.end,\n )}`,\n // Chip reuses the on-screen fertile-window badge's accent\n // token so the inserted PNG chip matches the screen.\n highlightToken: HIGHLIGHT_TOKEN,\n brand: insertBrand,\n fields: [\n {\n // Ovulation is a predicted date → calendar glyph (the\n // on-screen badge uses a Check tick, which ICON_GEOMETRY\n // does not carry, so the calendar reads the date meaning).\n icon: 'calendar',\n label: t('cycleCalculator.ovulation'),\n value: fmt(result.ovulation),\n },\n {\n // Fertile window → heart glyph, matching the on-screen\n // fertile-window badge's Heart icon.\n icon: 'heart',\n label: t('cycleCalculator.fertileWindow'),\n value: `${fmt(result.fertileWindow.start)} – ${fmt(\n result.fertileWindow.end,\n )}`,\n },\n {\n // Next period → droplets glyph, matching the on-screen\n // next-period badge's Droplet icon.\n icon: 'droplets',\n label: t('cycleCalculator.nextPeriod'),\n value: fmt(result.nextPeriod),\n },\n ],\n }}\n />\n ) : null}\n </Card.Body>\n </Card>\n ) : (\n <p className=\"type-body ds:text-muted-foreground\">\n {t('cycleCalculator.empty')}\n </p>\n )}\n </div>\n );\n },\n);\n\nCycleCalculator.displayName = 'CycleCalculator';\n"],"names":["__iconNode","Droplet","createLucideIcon","isoDate","cycleCalculatorAgent","handle","args","DEFAULT_CYCLE_LENGTH","LUTEAL_PHASE_DAYS","FERTILE_DAYS_AFTER","predictCycle","input","occurrences","cycle","lastPeriodStart","ovulation","addDays","fertileWindow","nextPeriod","upcomingPeriods","_","i","periodRange","rootVariants","cva","HIGHLIGHT_TOKEN","toIsoDate","d","format","fromIsoDate","iso","parseISO","CYCLE_LENGTH_RANGE","PERIOD_LENGTH_RANGE","inRange","n","min","max","CycleCalculator","forwardRef","defaultCycleLength","onResultChange","onInsert","insertVariant","onCopy","onError","insertBrand","id","width","className","ref","t","i18n","useTranslation","lastPeriod","setLastPeriod","useState","cycleLength","setCycleLength","periodLength","setPeriodLength","result","useMemo","dateFormatter","useEffect","today","liveRef","useRef","agentHandle","parsed","isAfter","days","useAgentRegistration","fmt","jsxs","jsx","FormField","DatePicker","NumberInput","Card","Badge","Check","Heart","InsertButton"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"cycle-calculator-DVgxBfP0.js","sources":["../../node_modules/lucide-react/dist/esm/icons/droplet.mjs","../../src/components/cycle-calculator/cycle-calculator.agent.ts","../../src/components/cycle-calculator/cycle.ts","../../src/components/cycle-calculator/cycle-calculator.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z\",\n key: \"c7niix\"\n }\n ]\n];\nconst Droplet = createLucideIcon(\"droplet\", __iconNode);\n\nexport { __iconNode, Droplet as default };\n//# sourceMappingURL=droplet.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — CycleCalculator. */\n/* */\n/* Menstrual-cycle predictor: takes a last-period date (+ optional cycle */\n/* and period lengths) and computes ovulation, fertile window and the */\n/* next few periods. The agent surface is the three inputs plus the */\n/* computed prediction; the handle is the curated `CycleCalculatorHandle` */\n/* (the public `ref` stays the root <div>, exactly as `slider.tsx` and */\n/* `bmi-calculator.tsx` keep theirs). */\n/* */\n/* Dates cross the boundary as local-time `yyyy-MM-dd` strings, never */\n/* `Date` objects, so nothing shifts a day under JSON/UTC serialisation. */\n/* */\n/* PHI (§7): never exposes patient identity — the slots return the */\n/* operator's own structural inputs (a date, two day counts) and the */\n/* dates derived from them, the same \"filter model\" precedent §7 sets. */\n/* See `src/docs/26-agent-readiness.mdx`. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { CycleCalculatorHandle } from './cycle-calculator';\n\n/** Shared JSON Schema fragment for a local-time calendar date. */\nconst isoDate = {\n type: 'string',\n pattern: '^\\\\d{4}-\\\\d{2}-\\\\d{2}$',\n} as const;\n\nexport const cycleCalculatorAgent: AgentAdapter<CycleCalculatorHandle> = {\n id: 'cycle-calculator',\n // set_value → the three `set_*` actions + the `inputs` state slot.\n capabilities: ['set_value'],\n state: {\n inputs: {\n type: '{ lastPeriodStart: string | null, cycleLength: number | null, periodLength: number | null }',\n descriptionKey: 'ui.agent.cycleCalculator.state.inputs',\n description:\n 'The three cycle inputs as entered — last-period start date (`yyyy-MM-dd`), average cycle length in days, and period (bleed) length in days. Null where unset.',\n read: (handle) => handle.getInputs(),\n },\n result: {\n type: '{ ovulation: string, fertileWindow: { start: string, end: string }, nextPeriod: string, periodRange: { start: string, end: string } | null, upcomingPeriods: string[] } | null',\n descriptionKey: 'ui.agent.cycleCalculator.state.result',\n description:\n 'Computed prediction — ovulation date, fertile window, next period, current bleed range and the next few period starts, all `yyyy-MM-dd`. Null until a last-period date is set.',\n read: (handle) => handle.getResult(),\n },\n },\n actions: {\n set_last_period: {\n // Drives the same local input state a user types into; nothing is\n // persisted to a record, and the value is reversible in the same UI.\n safety: 'write',\n argsType: '{ date: string | null }',\n argsSchema: {\n type: 'object',\n properties: {\n date: {\n oneOf: [\n { ...isoDate, description: 'Local calendar date, `yyyy-MM-dd`.' },\n { type: 'null' },\n ],\n description:\n 'Start date of the last period, or null to clear it. Must not be in the future.',\n },\n },\n required: ['date'],\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the date was applied.',\n },\n errors: [\n 'Returns false for an unparseable date or a date in the future — the on-screen DatePicker caps at today.',\n ],\n examples: [\n { args: { date: '2026-08-01' }, note: 'Last period started 1 August.' },\n ],\n descriptionKey: 'ui.agent.cycleCalculator.actions.setLastPeriod',\n description:\n 'Set the start date of the last period. This is the only required input — the prediction stays null without it.',\n invoke: (handle, args: { date: string | null }) =>\n handle.setLastPeriod(args.date),\n },\n set_cycle_length: {\n safety: 'write',\n argsType: '{ days: number | null }',\n argsSchema: {\n type: 'object',\n properties: {\n days: {\n oneOf: [\n { type: 'integer', minimum: 20, maximum: 45 },\n { type: 'null' },\n ],\n description:\n 'Average cycle length in days (20–45), or null to fall back to the 28-day default.',\n },\n },\n required: ['days'],\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the value was applied.',\n },\n errors: [\n 'Returns false outside 20–45 days — the same bounds the on-screen NumberInput enforces.',\n ],\n descriptionKey: 'ui.agent.cycleCalculator.actions.setCycleLength',\n description:\n 'Set the average cycle length in days. Shifts ovulation, the fertile window and every upcoming period.',\n invoke: (handle, args: { days: number | null }) =>\n handle.setCycleLength(args.days),\n },\n set_period_length: {\n safety: 'write',\n argsType: '{ days: number | null }',\n argsSchema: {\n type: 'object',\n properties: {\n days: {\n oneOf: [\n { type: 'integer', minimum: 1, maximum: 14 },\n { type: 'null' },\n ],\n description:\n 'Period (bleed) length in days (1–14), or null to omit the bleed range.',\n },\n },\n required: ['days'],\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the value was applied.',\n },\n errors: [\n 'Returns false outside 1–14 days — the same bounds the on-screen NumberInput enforces.',\n ],\n descriptionKey: 'ui.agent.cycleCalculator.actions.setPeriodLength',\n description:\n 'Set the period (bleed) length in days. Optional — it only adds the current bleed range to the result.',\n invoke: (handle, args: { days: number | null }) =>\n handle.setPeriodLength(args.days),\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'cycle-calculator',\n description: 'Marks the CycleCalculator wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Also the registry key — without an `id` the instance does not register and only the DOM channel works.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* Menstrual-cycle prediction — pure, framework-free, unit-testable. */\n/* */\n/* Uses the standard fixed-luteal-phase model: ovulation falls ~14 days */\n/* before the next period, so on a cycle of length L ovulation is day */\n/* (L − 14). The fertile window spans the 5 days before ovulation */\n/* (sperm survival) through 1 day after (oocyte viability). */\n/* ------------------------------------------------------------------ */\n\nimport { addDays } from 'date-fns';\n\n/** Standard menstrual-cycle length. */\nexport const DEFAULT_CYCLE_LENGTH = 28;\n/** Luteal phase is biologically near-constant at ~14 days. */\nexport const LUTEAL_PHASE_DAYS = 14;\n/** Sperm survive up to ~5 days before ovulation. */\nexport const FERTILE_DAYS_BEFORE = 5;\n/** The oocyte is viable ~1 day after ovulation. */\nexport const FERTILE_DAYS_AFTER = 1;\n\nexport interface CycleInput {\n /** First day of the most recent period. */\n lastPeriodStart: Date;\n /** Average cycle length in days. Defaults to 28. */\n cycleLength?: number;\n /** Period (bleed) length in days. Optional — used for the period range. */\n periodLength?: number;\n}\n\nexport interface DateRange {\n start: Date;\n end: Date;\n}\n\nexport interface CyclePrediction {\n /** Start date of the next period. */\n nextPeriod: Date;\n /** Estimated ovulation date. */\n ovulation: Date;\n /** Fertile window (5 days before ovulation → 1 day after). */\n fertileWindow: DateRange;\n /** Start dates of the next few periods (length = `occurrences`). */\n upcomingPeriods: Date[];\n /**\n * The current period's bleed range (first day → last day), or `null` when no\n * `periodLength` was given.\n */\n periodRange: DateRange | null;\n}\n\n/**\n * Predict ovulation, the fertile window and upcoming periods from the last\n * period's start date. `occurrences` controls how many future periods to\n * list (default 3).\n */\nexport function predictCycle(\n input: CycleInput,\n occurrences = 3,\n): CyclePrediction {\n const cycle = input.cycleLength ?? DEFAULT_CYCLE_LENGTH;\n const { lastPeriodStart } = input;\n\n const ovulation = addDays(lastPeriodStart, cycle - LUTEAL_PHASE_DAYS);\n const fertileWindow: DateRange = {\n start: addDays(ovulation, -FERTILE_DAYS_BEFORE),\n end: addDays(ovulation, FERTILE_DAYS_AFTER),\n };\n const nextPeriod = addDays(lastPeriodStart, cycle);\n const upcomingPeriods = Array.from({ length: occurrences }, (_, i) =>\n addDays(lastPeriodStart, cycle * (i + 1)),\n );\n const periodRange: DateRange | null =\n input.periodLength && input.periodLength > 0\n ? {\n start: lastPeriodStart,\n end: addDays(lastPeriodStart, input.periodLength - 1),\n }\n : null;\n\n return { nextPeriod, ovulation, fertileWindow, upcomingPeriods, periodRange };\n}\n","/* ------------------------------------------------------------------ */\n/* CycleCalculator — predict ovulation, fertile window and upcoming */\n/* periods from the last period's start date. */\n/* */\n/* Maths lives in `./cycle` (pure, separately tested). */\n/* ------------------------------------------------------------------ */\n\nimport { forwardRef, useEffect, useMemo, useRef, useState } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { format, isAfter, parseISO } from 'date-fns';\nimport { Heart, Check, Droplet } from 'lucide-react';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { cycleCalculatorAgent } from './cycle-calculator.agent';\nimport { FormField } from '../form-field';\nimport { DatePicker } from '../date-picker';\nimport { NumberInput } from '../number-input';\nimport { Card } from '../card';\nimport { Badge } from '../badge';\nimport {\n InsertButton,\n type InsertPayload,\n type InsertVariant,\n type InsertMode,\n} from '../_shared/insert-result';\nimport {\n type CyclePrediction,\n predictCycle,\n DEFAULT_CYCLE_LENGTH,\n} from './cycle';\n\nconst rootVariants = cva('ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]', {\n variants: {\n width: { full: 'ds:w-full', auto: 'ds:inline-flex' },\n },\n defaultVariants: { width: 'full' },\n});\n\n/**\n * DS token NAME backing the result-card chip — the fertile window is the\n * headline fertility datum, shown on screen with the `accent` Badge variant\n * (which fills `--accent`). The card chip reuses that token so the inserted\n * PNG chip matches the on-screen fertile-window badge.\n */\nconst HIGHLIGHT_TOKEN = '--accent';\n\n/* ------------------------------------------------------------------ */\n/* Agent boundary */\n/* */\n/* Dates cross the agent boundary as local-time `yyyy-MM-dd` strings, */\n/* never `Date` objects — a Date JSON-serialises to UTC and silently */\n/* shifts the day for anyone east or west of Greenwich. */\n/* ------------------------------------------------------------------ */\n\nconst toIsoDate = (d: Date): string => format(d, 'yyyy-MM-dd');\n\nconst fromIsoDate = (iso: string): Date | null => {\n const d = parseISO(iso);\n return Number.isNaN(d.getTime()) ? null : d;\n};\n\n/** UI input bounds, mirrored by the agent handle so it can't out-type a user. */\nconst CYCLE_LENGTH_RANGE = { min: 20, max: 45 } as const;\nconst PERIOD_LENGTH_RANGE = { min: 1, max: 14 } as const;\n\nconst inRange = (\n n: number | null,\n { min, max }: { min: number; max: number },\n): boolean => n === null || (Number.isFinite(n) && n >= min && n <= max);\n\n/** `CyclePrediction` projected onto the agent boundary — ISO dates, no Dates. */\nexport interface CyclePredictionSnapshot {\n /** Estimated ovulation date, `yyyy-MM-dd`. */\n ovulation: string;\n /** Fertile window, `yyyy-MM-dd` endpoints. */\n fertileWindow: { start: string; end: string };\n /** Start of the next period, `yyyy-MM-dd`. */\n nextPeriod: string;\n /** Current period's bleed range, or null when no period length was given. */\n periodRange: { start: string; end: string } | null;\n /** Start dates of the next few periods, `yyyy-MM-dd`. */\n upcomingPeriods: string[];\n}\n\n/**\n * Curated imperative handle for agent / external automation. Reads the three\n * cycle inputs and the computed prediction, and drives the inputs the way a\n * user would. Never exposes patient identity — only structural dates and day\n * counts. Consumed by `cycle-calculator.agent.ts`; the public `ref` stays the\n * root DOM element.\n */\nexport interface CycleCalculatorHandle {\n /** Current inputs — ISO date + day counts, or null when unset. */\n getInputs: () => {\n lastPeriodStart: string | null;\n cycleLength: number | null;\n periodLength: number | null;\n };\n /** Computed prediction, or null until a last-period date is set. */\n getResult: () => CyclePredictionSnapshot | null;\n /** Set the last period's start date (`yyyy-MM-dd`, not in the future). */\n setLastPeriod: (isoDate: string | null) => boolean;\n /** Set the average cycle length in days (20–45). */\n setCycleLength: (days: number | null) => boolean;\n /** Set the period (bleed) length in days (1–14). */\n setPeriodLength: (days: number | null) => boolean;\n}\n\nexport interface CycleCalculatorProps extends VariantProps<\n typeof rootVariants\n> {\n /** Initial cycle length in days. Defaults to 28. */\n defaultCycleLength?: number;\n /** Fires whenever a prediction can be computed (and `null` when it can't). */\n onResultChange?: (result: CyclePrediction | null) => void;\n /** When provided, shows the result-action buttons that emit / copy the result. */\n onInsert?: (payload: InsertPayload) => void;\n /**\n * Which verb the result button performs. Defaults to `'insert'`.\n * Use `'copy'` in an app-shell surface (no editor to insert into) — the\n * button writes the result to the clipboard as a multi-format `ClipboardItem`.\n */\n insertVariant?: InsertVariant;\n /** `copy` variant only — fired after a successful clipboard write. */\n onCopy?: (mode: InsertMode) => void;\n /** `copy` variant only — fired if the clipboard write can't proceed. */\n onError?: (error: unknown) => void;\n /**\n * Brand wordmark printed in the inserted/copied result-card footer.\n * Omitted → no brand line (and no footer hairline); a string → that custom\n * brand; `false` → no brand line. Brand is opt-in.\n */\n insertBrand?: string | false;\n /** Opaque instance id, emitted as `data-component-id`. */\n id?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n}\n\nexport const CycleCalculator = forwardRef<HTMLDivElement, CycleCalculatorProps>(\n (\n {\n defaultCycleLength = DEFAULT_CYCLE_LENGTH,\n onResultChange,\n onInsert,\n insertVariant = 'insert',\n onCopy,\n onError,\n insertBrand,\n id,\n width,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const [lastPeriod, setLastPeriod] = useState<Date | undefined>(undefined);\n const [cycleLength, setCycleLength] = useState<number | null>(\n defaultCycleLength,\n );\n const [periodLength, setPeriodLength] = useState<number | null>(null);\n\n const result = useMemo<CyclePrediction | null>(() => {\n if (!lastPeriod) return null;\n return predictCycle({\n lastPeriodStart: lastPeriod,\n cycleLength: cycleLength ?? DEFAULT_CYCLE_LENGTH,\n periodLength: periodLength ?? undefined,\n });\n }, [lastPeriod, cycleLength, periodLength]);\n\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }),\n [i18n.language],\n );\n\n useEffect(() => {\n onResultChange?.(result);\n }, [result, onResultChange]);\n\n const today = useMemo(() => new Date(), []);\n\n /* ── Agent handle ────────────────────────────────────────────────── */\n const liveRef = useRef({ lastPeriod, cycleLength, periodLength, result });\n liveRef.current = { lastPeriod, cycleLength, periodLength, result };\n\n const agentHandle = useMemo<CycleCalculatorHandle>(\n () => ({\n getInputs: () => ({\n lastPeriodStart: liveRef.current.lastPeriod\n ? toIsoDate(liveRef.current.lastPeriod)\n : null,\n cycleLength: liveRef.current.cycleLength,\n periodLength: liveRef.current.periodLength,\n }),\n getResult: () => {\n const r = liveRef.current.result;\n if (!r) return null;\n return {\n ovulation: toIsoDate(r.ovulation),\n fertileWindow: {\n start: toIsoDate(r.fertileWindow.start),\n end: toIsoDate(r.fertileWindow.end),\n },\n nextPeriod: toIsoDate(r.nextPeriod),\n periodRange: r.periodRange\n ? {\n start: toIsoDate(r.periodRange.start),\n end: toIsoDate(r.periodRange.end),\n }\n : null,\n upcomingPeriods: r.upcomingPeriods.map(toIsoDate),\n };\n },\n setLastPeriod: (isoDate) => {\n if (isoDate === null) {\n setLastPeriod(undefined);\n return true;\n }\n const parsed = fromIsoDate(isoDate);\n // The DatePicker caps at today; the handle honours the same bound.\n if (!parsed || isAfter(parsed, new Date())) return false;\n setLastPeriod(parsed);\n return true;\n },\n setCycleLength: (days) => {\n if (!inRange(days, CYCLE_LENGTH_RANGE)) return false;\n setCycleLength(days);\n return true;\n },\n setPeriodLength: (days) => {\n if (!inRange(days, PERIOD_LENGTH_RANGE)) return false;\n setPeriodLength(days);\n return true;\n },\n }),\n [],\n );\n useAgentRegistration(cycleCalculatorAgent, agentHandle, id);\n\n const fmt = (d: Date): string => dateFormatter.format(d);\n\n return (\n <div\n ref={ref}\n data-component=\"cycle-calculator\"\n data-component-id={id}\n className={rootVariants({ width, className })}\n >\n <div className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-2\">\n <FormField label={t('cycleCalculator.lastPeriod')}>\n <DatePicker\n value={lastPeriod}\n onChange={setLastPeriod}\n maxDate={today}\n />\n </FormField>\n <FormField\n label={t('cycleCalculator.cycleLength')}\n description={t('cycleCalculator.cycleLengthHint')}\n >\n <NumberInput\n mode=\"integer\"\n min={CYCLE_LENGTH_RANGE.min}\n max={CYCLE_LENGTH_RANGE.max}\n value={cycleLength}\n onChange={setCycleLength}\n />\n </FormField>\n <FormField\n label={t('cycleCalculator.periodLength')}\n description={t('cycleCalculator.periodLengthHint')}\n >\n <NumberInput\n mode=\"integer\"\n min={PERIOD_LENGTH_RANGE.min}\n max={PERIOD_LENGTH_RANGE.max}\n value={periodLength}\n onChange={setPeriodLength}\n />\n </FormField>\n </div>\n\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {result\n ? `${t('cycleCalculator.ovulation')}: ${fmt(result.ovulation)}. ${t(\n 'cycleCalculator.nextPeriod',\n )}: ${fmt(result.nextPeriod)}.`\n : ''}\n </p>\n\n {result ? (\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <dl className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-3\">\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)] ds:text-center\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.ovulation')}\n </dt>\n <dd>\n <Badge\n variant=\"success\"\n size=\"lg\"\n leading={<Check aria-hidden />}\n >\n {fmt(result.ovulation)}\n </Badge>\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)] ds:text-center\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.fertileWindow')}\n </dt>\n <dd>\n <Badge\n variant=\"accent\"\n size=\"lg\"\n leading={<Heart aria-hidden />}\n >\n {fmt(result.fertileWindow.start)} –{' '}\n {fmt(result.fertileWindow.end)}\n </Badge>\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-xs)] ds:text-center\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.nextPeriod')}\n </dt>\n <dd>\n <Badge\n variant=\"error\"\n size=\"lg\"\n leading={<Droplet aria-hidden />}\n >\n {fmt(result.nextPeriod)}\n </Badge>\n </dd>\n </div>\n </dl>\n\n {result.periodRange ? (\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.periodRange')}\n </span>\n <span className=\"type-body ds:text-foreground\">\n {fmt(result.periodRange.start)} –{' '}\n {fmt(result.periodRange.end)}\n </span>\n </div>\n ) : null}\n\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('cycleCalculator.upcomingPeriods')}\n </span>\n <ul className=\"ds:flex ds:flex-wrap ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-2xs)]\">\n {result.upcomingPeriods.map((d) => (\n <li\n key={d.getTime()}\n className=\"type-body ds:text-foreground\"\n >\n {fmt(d)}\n </li>\n ))}\n </ul>\n </div>\n\n {insertVariant === 'copy' || onInsert ? (\n <InsertButton\n onInsert={onInsert}\n variant={insertVariant}\n onCopy={onCopy}\n onError={onError}\n card={{\n title: t('insert.title.cycle'),\n icon: 'heart',\n highlight: `${fmt(result.fertileWindow.start)} – ${fmt(\n result.fertileWindow.end,\n )}`,\n // Chip reuses the on-screen fertile-window badge's accent\n // token so the inserted PNG chip matches the screen.\n highlightToken: HIGHLIGHT_TOKEN,\n brand: insertBrand,\n fields: [\n {\n // Ovulation is a predicted date → calendar glyph (the\n // on-screen badge uses a Check tick, which ICON_GEOMETRY\n // does not carry, so the calendar reads the date meaning).\n icon: 'calendar',\n label: t('cycleCalculator.ovulation'),\n value: fmt(result.ovulation),\n },\n {\n // Fertile window → heart glyph, matching the on-screen\n // fertile-window badge's Heart icon.\n icon: 'heart',\n label: t('cycleCalculator.fertileWindow'),\n value: `${fmt(result.fertileWindow.start)} – ${fmt(\n result.fertileWindow.end,\n )}`,\n },\n {\n // Next period → droplets glyph, matching the on-screen\n // next-period badge's Droplet icon.\n icon: 'droplets',\n label: t('cycleCalculator.nextPeriod'),\n value: fmt(result.nextPeriod),\n },\n ],\n }}\n />\n ) : null}\n </Card.Body>\n </Card>\n ) : (\n <p className=\"type-body ds:text-muted-foreground\">\n {t('cycleCalculator.empty')}\n </p>\n )}\n </div>\n );\n },\n);\n\nCycleCalculator.displayName = 'CycleCalculator';\n"],"names":["__iconNode","Droplet","createLucideIcon","isoDate","cycleCalculatorAgent","handle","args","DEFAULT_CYCLE_LENGTH","LUTEAL_PHASE_DAYS","FERTILE_DAYS_AFTER","predictCycle","input","occurrences","cycle","lastPeriodStart","ovulation","addDays","fertileWindow","nextPeriod","upcomingPeriods","_","i","periodRange","rootVariants","cva","HIGHLIGHT_TOKEN","toIsoDate","d","format","fromIsoDate","iso","parseISO","CYCLE_LENGTH_RANGE","PERIOD_LENGTH_RANGE","inRange","n","min","max","CycleCalculator","forwardRef","defaultCycleLength","onResultChange","onInsert","insertVariant","onCopy","onError","insertBrand","id","width","className","ref","t","i18n","useTranslation","lastPeriod","setLastPeriod","useState","cycleLength","setCycleLength","periodLength","setPeriodLength","result","useMemo","dateFormatter","useEffect","today","liveRef","useRef","agentHandle","parsed","isAfter","days","useAgentRegistration","fmt","jsxs","jsx","FormField","DatePicker","NumberInput","Card","Badge","Check","Heart","InsertButton"],"mappings":"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","x_google_ignoreList":[0]}