@alfadocs/ui-kit-debug 1.12.6 → 1.13.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.
- package/dist/_chunks/{actions-cell-renderer-DnSLrgQD.js → actions-cell-renderer-ReurEy5i.js} +2 -2
- package/dist/_chunks/{actions-cell-renderer-DnSLrgQD.js.map → actions-cell-renderer-ReurEy5i.js.map} +1 -1
- package/dist/_chunks/{address-fields-CZP4Wncx.js → address-fields-CZ0pEdEI.js} +4 -4
- package/dist/_chunks/{address-fields-CZP4Wncx.js.map → address-fields-CZ0pEdEI.js.map} +1 -1
- package/dist/_chunks/{ai-prompt-input-DnbfEJnr.js → ai-prompt-input-CrHr-5H8.js} +2 -2
- package/dist/_chunks/{ai-prompt-input-DnbfEJnr.js.map → ai-prompt-input-CrHr-5H8.js.map} +1 -1
- package/dist/_chunks/{anamnesis-summary-rows-BfhxWPO3.js → anamnesis-summary-rows-CRWO8x8g.js} +4 -4
- package/dist/_chunks/{anamnesis-summary-rows-BfhxWPO3.js.map → anamnesis-summary-rows-CRWO8x8g.js.map} +1 -1
- package/dist/_chunks/{audio-recorder-EWBCNIsd.js → audio-recorder-DXG6LTtO.js} +2 -2
- package/dist/_chunks/{audio-recorder-EWBCNIsd.js.map → audio-recorder-DXG6LTtO.js.map} +1 -1
- package/dist/_chunks/{autocomplete-BrONKN8l.js → autocomplete-MpBhz-fG.js} +86 -74
- package/dist/_chunks/{autocomplete-BrONKN8l.js.map → autocomplete-MpBhz-fG.js.map} +1 -1
- package/dist/_chunks/{balance-badge-cell-7L6nzB29.js → balance-badge-cell--iQ_gtmi.js} +4 -4
- package/dist/_chunks/{balance-badge-cell-7L6nzB29.js.map → balance-badge-cell--iQ_gtmi.js.map} +1 -1
- package/dist/_chunks/{bishop-score-Cnu0xs-z.js → bishop-score-CJUVBfAu.js} +2 -2
- package/dist/_chunks/{bishop-score-Cnu0xs-z.js.map → bishop-score-CJUVBfAu.js.map} +1 -1
- package/dist/_chunks/{booking-CBHKdsZl.js → booking-DQbo6mQF.js} +609 -591
- package/dist/_chunks/booking-DQbo6mQF.js.map +1 -0
- package/dist/_chunks/{care-plan-card-aDN4oem9.js → care-plan-card-D-FMfDKH.js} +2 -2
- package/dist/_chunks/{care-plan-card-aDN4oem9.js.map → care-plan-card-D-FMfDKH.js.map} +1 -1
- package/dist/_chunks/{care-plan-entry-card-BEhANdBE.js → care-plan-entry-card-Bvw_9T-d.js} +2 -2
- package/dist/_chunks/{care-plan-entry-card-BEhANdBE.js.map → care-plan-entry-card-Bvw_9T-d.js.map} +1 -1
- package/dist/_chunks/{care-plan-header-CkpPyQqG.js → care-plan-header-B5CBE0zu.js} +2 -2
- package/dist/_chunks/{care-plan-header-CkpPyQqG.js.map → care-plan-header-B5CBE0zu.js.map} +1 -1
- package/dist/_chunks/{city-input-towzBenY.js → city-input-DaQc-Hbj.js} +2 -2
- package/dist/_chunks/{city-input-towzBenY.js.map → city-input-DaQc-Hbj.js.map} +1 -1
- package/dist/_chunks/{combobox-DiMLItyu.js → combobox-D7_NLE2Z.js} +89 -81
- package/dist/_chunks/{combobox-DiMLItyu.js.map → combobox-D7_NLE2Z.js.map} +1 -1
- package/dist/_chunks/{contact-profile-card-BMIBr5s9.js → contact-profile-card-BZqi8Hck.js} +38 -36
- package/dist/_chunks/{contact-profile-card-BMIBr5s9.js.map → contact-profile-card-BZqi8Hck.js.map} +1 -1
- package/dist/_chunks/{country-select-UEF9BEeQ.js → country-select-DzbPFktV.js} +2 -2
- package/dist/_chunks/{country-select-UEF9BEeQ.js.map → country-select-DzbPFktV.js.map} +1 -1
- package/dist/_chunks/{document-preview-oyx9RhCo.js → document-preview-CDb-n_W7.js} +2 -2
- package/dist/_chunks/{document-preview-oyx9RhCo.js.map → document-preview-CDb-n_W7.js.map} +1 -1
- package/dist/_chunks/{face-scheme-CZaKm6fG.js → face-scheme-DA2vjqaM.js} +2 -2
- package/dist/_chunks/{face-scheme-CZaKm6fG.js.map → face-scheme-DA2vjqaM.js.map} +1 -1
- package/dist/_chunks/{file-manager-C0y7HBAN.js → file-manager-UsD8e_AB.js} +2 -2
- package/dist/_chunks/{file-manager-C0y7HBAN.js.map → file-manager-UsD8e_AB.js.map} +1 -1
- package/dist/_chunks/{gestational-age-calculator-CxZelpu2.js → gestational-age-calculator-CiOQjzgx.js} +2 -2
- package/dist/_chunks/{gestational-age-calculator-CxZelpu2.js.map → gestational-age-calculator-CiOQjzgx.js.map} +1 -1
- package/dist/_chunks/key-value-pair-BIBdZBLg.js +188 -0
- package/dist/_chunks/key-value-pair-BIBdZBLg.js.map +1 -0
- package/dist/_chunks/{link-cell-renderer-CenJx-_7.js → link-cell-renderer-CIASXsVM.js} +4 -4
- package/dist/_chunks/{link-cell-renderer-CenJx-_7.js.map → link-cell-renderer-CIASXsVM.js.map} +1 -1
- package/dist/_chunks/{multi-select-DqL4o0qV.js → multi-select-DYOvx2SJ.js} +56 -48
- package/dist/_chunks/{multi-select-DqL4o0qV.js.map → multi-select-DYOvx2SJ.js.map} +1 -1
- package/dist/_chunks/{muscle-scheme-yfzP_xoJ.js → muscle-scheme-BSJsI4-I.js} +2 -2
- package/dist/_chunks/{muscle-scheme-yfzP_xoJ.js.map → muscle-scheme-BSJsI4-I.js.map} +1 -1
- package/dist/_chunks/{optical-prescription-Dj3Eh5Ok.js → optical-prescription-BvwuqTpl.js} +2 -2
- package/dist/_chunks/{optical-prescription-Dj3Eh5Ok.js.map → optical-prescription-BvwuqTpl.js.map} +1 -1
- package/dist/_chunks/{patient-details-xrqe13az.js → patient-details-BQaUzPqp.js} +5 -5
- package/dist/_chunks/{patient-details-xrqe13az.js.map → patient-details-BQaUzPqp.js.map} +1 -1
- package/dist/_chunks/{patient-search-D5ufYoRc.js → patient-search-HeEUB-_X.js} +2 -2
- package/dist/_chunks/{patient-search-D5ufYoRc.js.map → patient-search-HeEUB-_X.js.map} +1 -1
- package/dist/_chunks/{patient-summary-card-CBfuDvJ5.js → patient-summary-card-CvDxhbBR.js} +2 -2
- package/dist/_chunks/{patient-summary-card-CBfuDvJ5.js.map → patient-summary-card-CvDxhbBR.js.map} +1 -1
- package/dist/_chunks/{payment-request-card-YVCcCZ25.js → payment-request-card-lmKLwsDs.js} +2 -2
- package/dist/_chunks/{payment-request-card-YVCcCZ25.js.map → payment-request-card-lmKLwsDs.js.map} +1 -1
- package/dist/_chunks/{periodontal-chart-BatZEFar.js → periodontal-chart-B9fphroR.js} +2 -2
- package/dist/_chunks/{periodontal-chart-BatZEFar.js.map → periodontal-chart-B9fphroR.js.map} +1 -1
- package/dist/_chunks/{periodontal-chart-card-BBpY_rBc.js → periodontal-chart-card-qEZPXj83.js} +2 -2
- package/dist/_chunks/{periodontal-chart-card-BBpY_rBc.js.map → periodontal-chart-card-qEZPXj83.js.map} +1 -1
- package/dist/_chunks/{pregnancy-dating-DtToyMyc.js → pregnancy-dating-D2wchD11.js} +2 -2
- package/dist/_chunks/{pregnancy-dating-DtToyMyc.js.map → pregnancy-dating-D2wchD11.js.map} +1 -1
- package/dist/_chunks/{province-select-BDywtmL-.js → province-select-BBc7s7vR.js} +2 -2
- package/dist/_chunks/{province-select-BDywtmL-.js.map → province-select-BBc7s7vR.js.map} +1 -1
- package/dist/_chunks/{select-BW5ecXlX.js → select-Bi8zril7.js} +165 -136
- package/dist/_chunks/select-Bi8zril7.js.map +1 -0
- package/dist/_chunks/{signature-request-DVDTKLjM.js → signature-request-CUe903hj.js} +2 -2
- package/dist/_chunks/{signature-request-DVDTKLjM.js.map → signature-request-CUe903hj.js.map} +1 -1
- package/dist/_chunks/{tabs-CBb2AidH.js → tabs-DqKtTIjZ.js} +2 -2
- package/dist/_chunks/{tabs-CBb2AidH.js.map → tabs-DqKtTIjZ.js.map} +1 -1
- package/dist/_chunks/{tasks-panel-Do5SFp-j.js → tasks-panel-DPCNaRko.js} +2 -2
- package/dist/_chunks/{tasks-panel-Do5SFp-j.js.map → tasks-panel-DPCNaRko.js.map} +1 -1
- package/dist/_chunks/{tooth-scheme-WdyVymQ1.js → tooth-scheme-2IsmbE6w.js} +2 -2
- package/dist/_chunks/{tooth-scheme-WdyVymQ1.js.map → tooth-scheme-2IsmbE6w.js.map} +1 -1
- package/dist/_chunks/{unit-converter-BPumXMA6.js → unit-converter-C6jMjqL9.js} +2 -2
- package/dist/_chunks/{unit-converter-BPumXMA6.js.map → unit-converter-C6jMjqL9.js.map} +1 -1
- package/dist/_chunks/{workflow-map-DE_ribRM.js → workflow-map-wcw3t6g4.js} +2 -2
- package/dist/_chunks/{workflow-map-DE_ribRM.js.map → workflow-map-wcw3t6g4.js.map} +1 -1
- package/dist/agent-catalog.json +1 -1
- package/dist/components/_shared/option.d.ts +1 -0
- package/dist/components/_shared/option.d.ts.map +1 -1
- package/dist/components/address-fields/index.js +1 -1
- package/dist/components/ai-prompt-input/index.js +1 -1
- package/dist/components/audio-recorder/index.js +1 -1
- package/dist/components/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/components/autocomplete/index.js +1 -1
- package/dist/components/bishop-score/index.js +1 -1
- package/dist/components/booking/booking.d.ts.map +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/care-plan-card/index.js +1 -1
- package/dist/components/care-plan-entry-card/index.js +1 -1
- package/dist/components/care-plan-header/index.js +1 -1
- package/dist/components/city-input/index.js +1 -1
- package/dist/components/combobox/combobox.d.ts.map +1 -1
- package/dist/components/combobox/index.js +1 -1
- package/dist/components/contact-profile-card/contact-profile-card.d.ts.map +1 -1
- package/dist/components/contact-profile-card/index.js +1 -1
- package/dist/components/country-select/index.js +1 -1
- package/dist/components/data-table/index.js +2 -2
- package/dist/components/document-preview/index.js +1 -1
- package/dist/components/face-scheme/index.js +1 -1
- package/dist/components/file-manager/index.js +1 -1
- package/dist/components/gestational-age-calculator/index.js +1 -1
- package/dist/components/key-value-pair/index.js +1 -1
- package/dist/components/key-value-pair/key-value-pair.d.ts +16 -0
- package/dist/components/key-value-pair/key-value-pair.d.ts.map +1 -1
- package/dist/components/multi-select/index.js +1 -1
- package/dist/components/multi-select/multi-select.d.ts.map +1 -1
- package/dist/components/muscle-scheme/index.js +1 -1
- package/dist/components/optical-prescription/index.js +1 -1
- package/dist/components/patient-details/index.js +1 -1
- package/dist/components/patient-search/index.js +1 -1
- package/dist/components/patient-summary-card/index.js +1 -1
- package/dist/components/patient-table/index.js +1 -1
- package/dist/components/payment-card/index.js +1 -1
- package/dist/components/periodontal-chart/index.js +1 -1
- package/dist/components/periodontal-chart-card/index.js +1 -1
- package/dist/components/pregnancy-dating/index.js +1 -1
- package/dist/components/province-select/index.js +1 -1
- package/dist/components/select/index.js +1 -1
- package/dist/components/select/select.d.ts +24 -0
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/skeleton-scheme/index.js +1 -1
- package/dist/components/tabs/index.js +1 -1
- package/dist/components/tasks-panel/index.js +1 -1
- package/dist/components/tooth-scheme/index.js +1 -1
- package/dist/components/unit-converter/index.js +1 -1
- package/dist/components/workflow/index.js +1 -1
- package/dist/index.js +40 -40
- package/dist/patterns/anamnesis/index.js +1 -1
- package/dist/patterns/signature-request/index.js +1 -1
- package/package.json +1 -1
- package/dist/_chunks/booking-CBHKdsZl.js.map +0 -1
- package/dist/_chunks/key-value-pair-BubG4fUa.js +0 -144
- package/dist/_chunks/key-value-pair-BubG4fUa.js.map +0 -1
- package/dist/_chunks/select-BW5ecXlX.js.map +0 -1
package/dist/_chunks/{periodontal-chart-card-BBpY_rBc.js → periodontal-chart-card-qEZPXj83.js}
RENAMED
|
@@ -4,7 +4,7 @@ import { c as R } from "./index-D2ZczOXr.js";
|
|
|
4
4
|
import { useTranslation as ae } from "react-i18next";
|
|
5
5
|
import { B as re } from "./badge-sTusUqZD.js";
|
|
6
6
|
import { C as S } from "./card-DPmk26CL.js";
|
|
7
|
-
import { K as ne, a as se } from "./key-value-pair-
|
|
7
|
+
import { K as ne, a as se } from "./key-value-pair-BIBdZBLg.js";
|
|
8
8
|
import { u as oe } from "./registry-DvAUVLHh.js";
|
|
9
9
|
const de = {
|
|
10
10
|
id: "periodontal-chart-card",
|
|
@@ -452,4 +452,4 @@ export {
|
|
|
452
452
|
he as a,
|
|
453
453
|
de as p
|
|
454
454
|
};
|
|
455
|
-
//# sourceMappingURL=periodontal-chart-card-
|
|
455
|
+
//# sourceMappingURL=periodontal-chart-card-qEZPXj83.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"periodontal-chart-card-BBpY_rBc.js","sources":["../../src/components/periodontal-chart-card/periodontal-chart-card.agent.ts","../../src/components/periodontal-chart-card/periodontal-chart-card.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { PeriodontalChartCardHandle } from './periodontal-chart-card';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalChartCard — agent adapter */\n/* */\n/* Read-only clinical chart. The handle returns STRUCTURAL state only — */\n/* the set of charted FDI tooth ids, how many probing sites breach the */\n/* 4mm / 6mm thresholds, and the chart date. NEVER patient identity, */\n/* names, or any free-text PHI — the chart never holds those. */\n/* -------------------------------------------------------------------- */\n\nexport const periodontalChartCardAgent: AgentAdapter<PeriodontalChartCardHandle> =\n {\n id: 'periodontal-chart-card',\n capabilities: [],\n state: {\n toothIds: {\n type: 'string[]',\n descriptionKey: 'ui.agent.periodontalChartCard.state.toothIds',\n description:\n 'FDI ids of the teeth currently charted. Tooth identifiers only — no patient identity.',\n read: (handle) => handle.getToothIds(),\n },\n siteCount: {\n type: 'number',\n descriptionKey: 'ui.agent.periodontalChartCard.state.siteCount',\n description: 'Total number of probing sites rendered.',\n read: (handle) => handle.getSiteCount(),\n },\n deepPocketCount: {\n type: 'number',\n descriptionKey: 'ui.agent.periodontalChartCard.state.deepPocketCount',\n description:\n 'Number of sites with a probing depth at or above the 6mm severe threshold.',\n read: (handle) => handle.getDeepPocketCount(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'periodontal-chart-card',\n description: 'Marks the PeriodontalChartCard root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n };\n","import {\n forwardRef,\n useId,\n useMemo,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '../badge/badge';\nimport { Card } from '../card/card';\nimport { KeyValueList, KeyValuePair } from '../key-value-pair/key-value-pair';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { periodontalChartCardAgent } from './periodontal-chart-card.agent';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalChartCard */\n/* */\n/* A DISPLAY-ONLY periodontal (gum) chart. There is no kit equivalent — */\n/* the dental ToothScheme charts caries/restorations per tooth, whereas */\n/* a perio chart records probing measurements per SITE (6 sites/tooth): */\n/* pocket depth (PD), gingival recession (REC), bleeding on probing */\n/* (BoP), suppuration, and tooth mobility. */\n/* */\n/* It renders a compact per-quadrant TABLE (real <table>/<th> semantics */\n/* + scope + caption — NOT a colour-only grid) of teeth x sites. Pocket */\n/* depths >= 4mm are flagged with the warning token, >= 6mm with the */\n/* destructive token, and EACH flag also carries a non-colour cue */\n/* (bold weight + an asterisk / double-asterisk) so the severity is */\n/* legible without colour. Bleeding and suppuration render as small */\n/* glyphs WITH an accessible per-cell label. */\n/* */\n/* The component owns no editing affordance — it is a passive read */\n/* surface for a chart captured elsewhere. */\n/* */\n/* All visible text flows through `useTranslation('ui')` against the */\n/* `periodontalChartCard.*` namespace. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n // Matches the kit's other `surface` props. `elevated` wraps in\n // `<Card variant=\"elevated\">`; `flat` drops the chrome for use\n // inside an existing Card / Sheet.\n surface: {\n flat: '',\n elevated: '',\n },\n },\n defaultVariants: { surface: 'elevated' },\n});\n\n// Per-measurement-cell severity. The colour is paired with a weight bump\n// so the flag survives greyscale / forced-colors — colour is never the\n// sole cue (the asterisk in the cell content carries the same signal).\nconst measureVariants = cva(\n 'ds:[font-variant-numeric:var(--font-feature-tabular)] ds:tabular-nums',\n {\n variants: {\n severity: {\n normal: 'ds:text-[color:var(--foreground)]',\n moderate: 'ds:font-semibold ds:text-[color:var(--warning-foreground)]',\n severe: 'ds:font-bold ds:text-[color:var(--destructive)]',\n },\n },\n defaultVariants: { severity: 'normal' },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* Constants */\n/* -------------------------------------------------------------------- */\n\n/** Probing depth (mm) at/above which a site is flagged moderate. */\nconst MODERATE_POCKET_MM = 4;\n/** Probing depth (mm) at/above which a site is flagged severe. */\nconst SEVERE_POCKET_MM = 6;\n\n/** The six standard probing sites, in buccal-then-lingual display order. */\nexport const PERIODONTAL_SITE_ORDER = [\n 'db',\n 'b',\n 'mb',\n 'dl',\n 'l',\n 'ml',\n] as const;\n\nexport type PeriodontalSiteId = (typeof PERIODONTAL_SITE_ORDER)[number];\n\n/** English fallback labels for the six probing sites (belt-and-braces). */\nconst SITE_DEFAULT: Record<PeriodontalSiteId, string> = {\n db: 'Disto-buccal',\n b: 'Buccal',\n mb: 'Mesio-buccal',\n dl: 'Disto-lingual',\n l: 'Lingual',\n ml: 'Mesio-lingual',\n};\n\n/** FDI quadrant ids (first digit of the FDI tooth number). */\nconst QUADRANT_ORDER = ['1', '2', '3', '4'] as const;\ntype QuadrantId = (typeof QUADRANT_ORDER)[number];\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** One probing-site reading. */\nexport interface PeriodontalSite {\n /** FDI tooth number, e.g. `'11'`, `'46'`. */\n tooth: string;\n /** Probing site: mesio-/disto- buccal/lingual, mid buccal/lingual. */\n site: PeriodontalSiteId;\n /** Pocket depth in millimetres. */\n pocketDepthMm?: number;\n /** Gingival recession in millimetres. */\n recessionMm?: number;\n /** Bleeding on probing at this site. */\n bleeding?: boolean;\n /** Suppuration (pus) at this site. */\n suppuration?: boolean;\n}\n\n/** Aggregate chart summary, consumer-supplied. */\nexport interface PeriodontalChartSummary {\n /** Whole-mouth mean probing depth in millimetres. */\n meanPocketDepthMm?: number;\n /** Bleeding-on-probing as a percentage of sites (0–100). */\n bleedingOnProbingPercent?: number;\n}\n\n/** Tooth-mobility grade (Miller 0–3). */\nexport type PeriodontalMobility = 0 | 1 | 2 | 3;\n\n/** Imperative handle — structural state only, never PHI. */\nexport interface PeriodontalChartCardHandle {\n /** FDI ids of the charted teeth, in display order. */\n getToothIds: () => string[];\n /** Total probing sites rendered. */\n getSiteCount: () => number;\n /** Count of sites at/above the 6mm severe threshold. */\n getDeepPocketCount: () => number;\n}\n\nexport interface PeriodontalChartCardProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children'\n> {\n /** Probing-site readings. Sites are grouped per tooth automatically. */\n sites: PeriodontalSite[];\n /**\n * ISO-8601 date the chart was captured. Rendered as a localised date in\n * the header and exposed as the table caption context. Optional.\n */\n dateIso?: string;\n /**\n * Dentition the chart covers. Drives only the localised header label —\n * tooth grouping is derived from the FDI numbers in `sites`.\n */\n dentition?: 'permanent' | 'primary' | 'mixed';\n /** Per-tooth Miller mobility grade, keyed by FDI tooth number. */\n mobility?: Record<string, PeriodontalMobility>;\n /** Aggregate summary stats rendered above the per-quadrant tables. */\n summary?: PeriodontalChartSummary;\n\n /* ----- i18n / formatting ----- */\n\n /** Locale for date + number formatting. Falls back to `i18n.language`. */\n locale?: string;\n\n /* ----- Styling ----- */\n\n /**\n * `'elevated'` (default) wraps in `<Card variant=\"elevated\">`. `'flat'`\n * drops the Card — use inside another card / sheet.\n */\n surface?: 'flat' | 'elevated';\n\n /* ----- a11y ----- */\n\n /** Override the default region aria-label. */\n 'aria-label'?: string;\n /** Agent-readiness consumer id, surfaced as `data-component-id`. */\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\n/** Classify a pocket depth into a severity band. */\nfunction pocketSeverity(\n depth: number | undefined,\n): 'normal' | 'moderate' | 'severe' {\n if (depth == null || !Number.isFinite(depth)) return 'normal';\n if (depth >= SEVERE_POCKET_MM) return 'severe';\n if (depth >= MODERATE_POCKET_MM) return 'moderate';\n return 'normal';\n}\n\n/** Non-colour severity cue appended to the measurement (`''`/`*`/`**`). */\nfunction severityMarker(severity: 'normal' | 'moderate' | 'severe'): string {\n if (severity === 'severe') return '∗∗';\n if (severity === 'moderate') return '∗';\n return '';\n}\n\n/** FDI quadrant (first digit) of a tooth number, or null if unparseable. */\nfunction quadrantOf(tooth: string): QuadrantId | null {\n const first = tooth.trim().charAt(0);\n return (QUADRANT_ORDER as readonly string[]).includes(first)\n ? (first as QuadrantId)\n : null;\n}\n\ninterface ToothRow {\n tooth: string;\n sites: Partial<Record<PeriodontalSiteId, PeriodontalSite>>;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const PeriodontalChartCard = forwardRef<\n HTMLDivElement,\n PeriodontalChartCardProps\n>(\n (\n {\n sites,\n dateIso,\n dentition = 'permanent',\n mobility,\n summary,\n locale,\n surface = 'elevated',\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const headingId = useId();\n const resolvedLocale = locale ?? i18n.language ?? 'en';\n\n // Group sites by tooth, then bucket teeth into FDI quadrants. The\n // grouping is derived purely from the FDI numbers — the consumer\n // passes a flat site list and the kit owns the layout.\n const { quadrants, toothIds, siteCount, deepPocketCount } = useMemo(() => {\n const byTooth = new Map<string, ToothRow>();\n let sCount = 0;\n let deep = 0;\n for (const site of sites) {\n sCount += 1;\n if ((site.pocketDepthMm ?? 0) >= SEVERE_POCKET_MM) deep += 1;\n let row = byTooth.get(site.tooth);\n if (!row) {\n row = { tooth: site.tooth, sites: {} };\n byTooth.set(site.tooth, row);\n }\n row.sites[site.site] = site;\n }\n\n // Sort teeth within a quadrant by their FDI position digit (2nd\n // char) ascending; keep insertion order as a stable fallback.\n const rows = Array.from(byTooth.values());\n const grouped: Array<{\n quadrant: QuadrantId | null;\n teeth: ToothRow[];\n }> = QUADRANT_ORDER.map((q) => ({\n quadrant: q as QuadrantId | null,\n teeth: rows\n .filter((r) => quadrantOf(r.tooth) === q)\n .sort((a, b) => a.tooth.localeCompare(b.tooth, 'en')),\n })).filter((g) => g.teeth.length > 0);\n\n // Teeth with an unparseable FDI quadrant render in their own group\n // so nothing is silently dropped.\n const unassigned = rows.filter((r) => quadrantOf(r.tooth) === null);\n if (unassigned.length > 0) {\n grouped.push({ quadrant: null, teeth: unassigned });\n }\n\n const ids = grouped.flatMap((g) => g.teeth.map((tt) => tt.tooth));\n return {\n quadrants: grouped,\n toothIds: ids,\n siteCount: sCount,\n deepPocketCount: deep,\n };\n }, [sites]);\n\n useAgentRegistration(\n periodontalChartCardAgent,\n {\n getToothIds: () => toothIds,\n getSiteCount: () => siteCount,\n getDeepPocketCount: () => deepPocketCount,\n },\n id,\n );\n\n const formattedDate = useMemo(() => {\n if (!dateIso) return undefined;\n const parsed = new Date(dateIso);\n if (Number.isNaN(parsed.getTime())) return undefined;\n try {\n return new Intl.DateTimeFormat(resolvedLocale, {\n dateStyle: 'medium',\n }).format(parsed);\n } catch {\n return parsed.toISOString().slice(0, 10);\n }\n }, [dateIso, resolvedLocale]);\n\n const resolvedHeading = t(\n 'periodontalChartCard.heading',\n 'Periodontal chart',\n );\n const resolvedAriaLabel = ariaLabel ?? resolvedHeading;\n\n const DENTITION_DEFAULT: Record<typeof dentition, string> = {\n permanent: 'Permanent dentition',\n primary: 'Primary dentition',\n mixed: 'Mixed dentition',\n };\n const dentitionLabel = t(`periodontalChartCard.dentition.${dentition}`, {\n defaultValue: DENTITION_DEFAULT[dentition],\n });\n\n const formatNumber = (n: number): string => {\n try {\n return new Intl.NumberFormat(resolvedLocale, {\n maximumFractionDigits: 1,\n }).format(n);\n } catch {\n return String(n);\n }\n };\n\n /* ------------------------------------------------------------ */\n /* Summary rows */\n /* ------------------------------------------------------------ */\n\n const summaryRows: Array<{ key: string; label: string; value: ReactNode }> =\n [];\n if (summary?.meanPocketDepthMm != null) {\n summaryRows.push({\n key: 'meanPocketDepth',\n label: t(\n 'periodontalChartCard.summary.meanPocketDepth',\n 'Mean probing depth',\n ),\n value: t('periodontalChartCard.unit.mm', {\n value: formatNumber(summary.meanPocketDepthMm),\n defaultValue: '{{value}} mm',\n }),\n });\n }\n if (summary?.bleedingOnProbingPercent != null) {\n summaryRows.push({\n key: 'bleedingOnProbing',\n label: t(\n 'periodontalChartCard.summary.bleedingOnProbing',\n 'Bleeding on probing',\n ),\n value: t('periodontalChartCard.unit.percent', {\n value: formatNumber(summary.bleedingOnProbingPercent),\n defaultValue: '{{value}}%',\n }),\n });\n }\n\n /* ------------------------------------------------------------ */\n /* Render a single measurement cell */\n /* ------------------------------------------------------------ */\n\n const renderMeasure = (\n depth: number | undefined,\n kind: 'pocket' | 'recession',\n ): ReactNode => {\n if (depth == null || !Number.isFinite(depth)) {\n return (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n );\n }\n const severity = kind === 'pocket' ? pocketSeverity(depth) : 'normal';\n const marker = kind === 'pocket' ? severityMarker(severity) : '';\n const numeric = formatNumber(depth);\n // The flag is announced as a worded suffix for SR users; sighted\n // users get the colour + bold + asterisk. The asterisk itself is\n // aria-hidden so it isn't read as punctuation.\n const srSuffix =\n severity === 'severe'\n ? ` ${t('periodontalChartCard.flag.severe', 'severe pocket')}`\n : severity === 'moderate'\n ? ` ${t('periodontalChartCard.flag.moderate', 'moderate pocket')}`\n : '';\n return (\n <span className={measureVariants({ severity })}>\n <span>{numeric}</span>\n {marker ? <span aria-hidden=\"true\">{marker}</span> : null}\n {srSuffix ? <span className=\"ds:sr-only\">{srSuffix}</span> : null}\n </span>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* Render bleeding / suppuration indicator cell */\n /* ------------------------------------------------------------ */\n\n const renderSigns = (site: PeriodontalSite | undefined): ReactNode => {\n if (!site || (!site.bleeding && !site.suppuration)) {\n return (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n );\n }\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n {site.bleeding ? (\n <span\n role=\"img\"\n aria-label={t(\n 'periodontalChartCard.sign.bleeding',\n 'Bleeding on probing',\n )}\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--destructive)]\"\n />\n ) : null}\n {site.suppuration ? (\n <span\n role=\"img\"\n aria-label={t(\n 'periodontalChartCard.sign.suppuration',\n 'Suppuration',\n )}\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--warning)]\"\n />\n ) : null}\n </span>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* One quadrant table */\n /* ------------------------------------------------------------ */\n\n const renderQuadrant = (group: {\n quadrant: QuadrantId | null;\n teeth: ToothRow[];\n }): ReactNode => {\n const QUADRANT_DEFAULT: Record<QuadrantId, string> = {\n '1': 'Upper right (Q1)',\n '2': 'Upper left (Q2)',\n '3': 'Lower left (Q3)',\n '4': 'Lower right (Q4)',\n };\n const captionText =\n group.quadrant != null\n ? t(`periodontalChartCard.quadrant.${group.quadrant}`, {\n defaultValue: QUADRANT_DEFAULT[group.quadrant],\n })\n : t('periodontalChartCard.quadrant.other', 'Other teeth');\n const cellClass =\n 'ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-center ds:border-b ds:border-[color:var(--border)]';\n const rowHeaderClass =\n 'ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-start ds:font-medium ds:border-b ds:border-[color:var(--border)] ds:whitespace-nowrap';\n return (\n <div\n key={group.quadrant ?? 'other'}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:overflow-x-auto\"\n >\n <table className=\"type-body-sm ds:w-full ds:border-collapse\">\n <caption className=\"type-label ds:text-start ds:mb-[var(--spacing-2xs)] ds:text-[color:var(--muted-foreground)]\">\n {captionText}\n </caption>\n <thead>\n <tr>\n <th\n scope=\"col\"\n className=\"ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-start ds:border-b ds:border-[color:var(--border)]\"\n >\n {t('periodontalChartCard.column.measure', 'Measurement')}\n </th>\n {group.teeth.map((row) => (\n <th\n key={row.tooth}\n scope=\"col\"\n data-tooth-id={row.tooth}\n className=\"ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-center ds:border-b ds:border-[color:var(--border)] ds:[font-variant-numeric:var(--font-feature-tabular)] ds:tabular-nums\"\n >\n <span className=\"ds:sr-only\">\n {t('periodontalChartCard.toothHeader', {\n tooth: row.tooth,\n defaultValue: 'Tooth {{tooth}}',\n })}\n </span>\n <span aria-hidden=\"true\">{row.tooth}</span>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {/* Pocket depth row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t(\n 'periodontalChartCard.row.pocketDepth',\n 'Pocket depth (PD)',\n )}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:items-center ds:justify-center ds:gap-[var(--spacing-2xs)]\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId} className=\"ds:sr-only\">\n {t(`periodontalChartCard.site.${siteId}`, {\n defaultValue: SITE_DEFAULT[siteId],\n })}\n </span>\n ))}\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)]\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderMeasure(\n row.sites[siteId]?.pocketDepthMm,\n 'pocket',\n )}\n </span>\n ))}\n </span>\n </span>\n </td>\n ))}\n </tr>\n {/* Recession row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t('periodontalChartCard.row.recession', 'Recession (REC)')}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)] ds:justify-center\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderMeasure(\n row.sites[siteId]?.recessionMm,\n 'recession',\n )}\n </span>\n ))}\n </span>\n </td>\n ))}\n </tr>\n {/* Bleeding / suppuration row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t(\n 'periodontalChartCard.row.signs',\n 'Bleeding / suppuration',\n )}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)] ds:justify-center\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderSigns(row.sites[siteId])}\n </span>\n ))}\n </span>\n </td>\n ))}\n </tr>\n {/* Mobility row — only when any tooth in the quadrant has a grade */}\n {mobility &&\n group.teeth.some((row) => mobility[row.tooth] != null) ? (\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t('periodontalChartCard.row.mobility', 'Mobility')}\n </th>\n {group.teeth.map((row) => {\n const grade = mobility[row.tooth];\n return (\n <td key={row.tooth} className={cellClass}>\n {grade != null ? (\n <Badge\n variant={grade >= 2 ? 'warning' : 'neutral'}\n size=\"sm\"\n aria-label={t(\n 'periodontalChartCard.mobility.label',\n {\n grade,\n defaultValue: 'Mobility grade {{grade}}',\n },\n )}\n >\n {grade}\n </Badge>\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n )}\n </td>\n );\n })}\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* Legend — explains the non-colour cues */\n /* ------------------------------------------------------------ */\n\n const legend = (\n <div\n role=\"group\"\n className=\"type-meta ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)] ds:text-[color:var(--muted-foreground)]\"\n aria-label={t('periodontalChartCard.legend.label', 'Chart legend')}\n >\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:font-semibold ds:text-[color:var(--warning-foreground)]\"\n >\n {'∗'}\n </span>\n {t('periodontalChartCard.legend.moderate', {\n threshold: MODERATE_POCKET_MM,\n defaultValue: 'PD ≥ {{threshold}} mm',\n })}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:font-bold ds:text-[color:var(--destructive)]\"\n >\n {'∗∗'}\n </span>\n {t('periodontalChartCard.legend.severe', {\n threshold: SEVERE_POCKET_MM,\n defaultValue: 'PD ≥ {{threshold}} mm',\n })}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--destructive)]\"\n />\n {t('periodontalChartCard.sign.bleeding', 'Bleeding on probing')}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--warning)]\"\n />\n {t('periodontalChartCard.sign.suppuration', 'Suppuration')}\n </span>\n </div>\n );\n\n const isEmpty = quadrants.length === 0;\n\n const inner = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <h2\n id={headingId}\n className=\"type-title-card ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {resolvedHeading}\n </h2>\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {formattedDate\n ? t('periodontalChartCard.subtitle.dated', {\n dentition: dentitionLabel,\n date: formattedDate,\n defaultValue: '{{dentition}} · {{date}}',\n })\n : dentitionLabel}\n </p>\n </div>\n\n {summaryRows.length > 0 ? (\n <KeyValueList rowGap=\"sm\">\n {summaryRows.map((row) => (\n <KeyValuePair key={row.key} label={row.label} value={row.value} />\n ))}\n </KeyValueList>\n ) : null}\n\n {isEmpty ? (\n <p\n role=\"status\"\n className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\"\n >\n {t(\n 'periodontalChartCard.empty',\n 'No periodontal readings recorded.',\n )}\n </p>\n ) : (\n <>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {quadrants.map((group) => renderQuadrant(group))}\n </div>\n {legend}\n </>\n )}\n </div>\n );\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-labelledby={headingId}\n data-component=\"periodontal-chart-card\"\n data-component-id={id}\n id={id}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {surface === 'elevated' ? (\n <Card variant=\"elevated\">\n <Card.Body>{inner}</Card.Body>\n </Card>\n ) : (\n inner\n )}\n </div>\n );\n },\n);\n\nPeriodontalChartCard.displayName = 'PeriodontalChartCard';\n\nexport type PeriodontalChartCardSurface = NonNullable<\n VariantProps<typeof rootVariants>['surface']\n>;\n"],"names":["periodontalChartCardAgent","handle","rootVariants","cva","measureVariants","MODERATE_POCKET_MM","SEVERE_POCKET_MM","PERIODONTAL_SITE_ORDER","SITE_DEFAULT","QUADRANT_ORDER","pocketSeverity","depth","severityMarker","severity","quadrantOf","tooth","first","PeriodontalChartCard","forwardRef","sites","dateIso","dentition","mobility","summary","locale","surface","ariaLabel","id","className","rest","ref","t","i18n","useTranslation","headingId","useId","resolvedLocale","quadrants","toothIds","siteCount","deepPocketCount","useMemo","byTooth","sCount","deep","site","row","rows","grouped","q","r","a","b","g","unassigned","ids","tt","useAgentRegistration","formattedDate","parsed","resolvedHeading","resolvedAriaLabel","DENTITION_DEFAULT","dentitionLabel","formatNumber","n","summaryRows","renderMeasure","kind","jsx","marker","numeric","srSuffix","renderSigns","jsxs","renderQuadrant","group","QUADRANT_DEFAULT","captionText","cellClass","rowHeaderClass","siteId","_a","grade","Badge","legend","isEmpty","inner","KeyValueList","KeyValuePair","Fragment","Card"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"periodontal-chart-card-qEZPXj83.js","sources":["../../src/components/periodontal-chart-card/periodontal-chart-card.agent.ts","../../src/components/periodontal-chart-card/periodontal-chart-card.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { PeriodontalChartCardHandle } from './periodontal-chart-card';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalChartCard — agent adapter */\n/* */\n/* Read-only clinical chart. The handle returns STRUCTURAL state only — */\n/* the set of charted FDI tooth ids, how many probing sites breach the */\n/* 4mm / 6mm thresholds, and the chart date. NEVER patient identity, */\n/* names, or any free-text PHI — the chart never holds those. */\n/* -------------------------------------------------------------------- */\n\nexport const periodontalChartCardAgent: AgentAdapter<PeriodontalChartCardHandle> =\n {\n id: 'periodontal-chart-card',\n capabilities: [],\n state: {\n toothIds: {\n type: 'string[]',\n descriptionKey: 'ui.agent.periodontalChartCard.state.toothIds',\n description:\n 'FDI ids of the teeth currently charted. Tooth identifiers only — no patient identity.',\n read: (handle) => handle.getToothIds(),\n },\n siteCount: {\n type: 'number',\n descriptionKey: 'ui.agent.periodontalChartCard.state.siteCount',\n description: 'Total number of probing sites rendered.',\n read: (handle) => handle.getSiteCount(),\n },\n deepPocketCount: {\n type: 'number',\n descriptionKey: 'ui.agent.periodontalChartCard.state.deepPocketCount',\n description:\n 'Number of sites with a probing depth at or above the 6mm severe threshold.',\n read: (handle) => handle.getDeepPocketCount(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'periodontal-chart-card',\n description: 'Marks the PeriodontalChartCard root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n };\n","import {\n forwardRef,\n useId,\n useMemo,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '../badge/badge';\nimport { Card } from '../card/card';\nimport { KeyValueList, KeyValuePair } from '../key-value-pair/key-value-pair';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { periodontalChartCardAgent } from './periodontal-chart-card.agent';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalChartCard */\n/* */\n/* A DISPLAY-ONLY periodontal (gum) chart. There is no kit equivalent — */\n/* the dental ToothScheme charts caries/restorations per tooth, whereas */\n/* a perio chart records probing measurements per SITE (6 sites/tooth): */\n/* pocket depth (PD), gingival recession (REC), bleeding on probing */\n/* (BoP), suppuration, and tooth mobility. */\n/* */\n/* It renders a compact per-quadrant TABLE (real <table>/<th> semantics */\n/* + scope + caption — NOT a colour-only grid) of teeth x sites. Pocket */\n/* depths >= 4mm are flagged with the warning token, >= 6mm with the */\n/* destructive token, and EACH flag also carries a non-colour cue */\n/* (bold weight + an asterisk / double-asterisk) so the severity is */\n/* legible without colour. Bleeding and suppuration render as small */\n/* glyphs WITH an accessible per-cell label. */\n/* */\n/* The component owns no editing affordance — it is a passive read */\n/* surface for a chart captured elsewhere. */\n/* */\n/* All visible text flows through `useTranslation('ui')` against the */\n/* `periodontalChartCard.*` namespace. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n // Matches the kit's other `surface` props. `elevated` wraps in\n // `<Card variant=\"elevated\">`; `flat` drops the chrome for use\n // inside an existing Card / Sheet.\n surface: {\n flat: '',\n elevated: '',\n },\n },\n defaultVariants: { surface: 'elevated' },\n});\n\n// Per-measurement-cell severity. The colour is paired with a weight bump\n// so the flag survives greyscale / forced-colors — colour is never the\n// sole cue (the asterisk in the cell content carries the same signal).\nconst measureVariants = cva(\n 'ds:[font-variant-numeric:var(--font-feature-tabular)] ds:tabular-nums',\n {\n variants: {\n severity: {\n normal: 'ds:text-[color:var(--foreground)]',\n moderate: 'ds:font-semibold ds:text-[color:var(--warning-foreground)]',\n severe: 'ds:font-bold ds:text-[color:var(--destructive)]',\n },\n },\n defaultVariants: { severity: 'normal' },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* Constants */\n/* -------------------------------------------------------------------- */\n\n/** Probing depth (mm) at/above which a site is flagged moderate. */\nconst MODERATE_POCKET_MM = 4;\n/** Probing depth (mm) at/above which a site is flagged severe. */\nconst SEVERE_POCKET_MM = 6;\n\n/** The six standard probing sites, in buccal-then-lingual display order. */\nexport const PERIODONTAL_SITE_ORDER = [\n 'db',\n 'b',\n 'mb',\n 'dl',\n 'l',\n 'ml',\n] as const;\n\nexport type PeriodontalSiteId = (typeof PERIODONTAL_SITE_ORDER)[number];\n\n/** English fallback labels for the six probing sites (belt-and-braces). */\nconst SITE_DEFAULT: Record<PeriodontalSiteId, string> = {\n db: 'Disto-buccal',\n b: 'Buccal',\n mb: 'Mesio-buccal',\n dl: 'Disto-lingual',\n l: 'Lingual',\n ml: 'Mesio-lingual',\n};\n\n/** FDI quadrant ids (first digit of the FDI tooth number). */\nconst QUADRANT_ORDER = ['1', '2', '3', '4'] as const;\ntype QuadrantId = (typeof QUADRANT_ORDER)[number];\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** One probing-site reading. */\nexport interface PeriodontalSite {\n /** FDI tooth number, e.g. `'11'`, `'46'`. */\n tooth: string;\n /** Probing site: mesio-/disto- buccal/lingual, mid buccal/lingual. */\n site: PeriodontalSiteId;\n /** Pocket depth in millimetres. */\n pocketDepthMm?: number;\n /** Gingival recession in millimetres. */\n recessionMm?: number;\n /** Bleeding on probing at this site. */\n bleeding?: boolean;\n /** Suppuration (pus) at this site. */\n suppuration?: boolean;\n}\n\n/** Aggregate chart summary, consumer-supplied. */\nexport interface PeriodontalChartSummary {\n /** Whole-mouth mean probing depth in millimetres. */\n meanPocketDepthMm?: number;\n /** Bleeding-on-probing as a percentage of sites (0–100). */\n bleedingOnProbingPercent?: number;\n}\n\n/** Tooth-mobility grade (Miller 0–3). */\nexport type PeriodontalMobility = 0 | 1 | 2 | 3;\n\n/** Imperative handle — structural state only, never PHI. */\nexport interface PeriodontalChartCardHandle {\n /** FDI ids of the charted teeth, in display order. */\n getToothIds: () => string[];\n /** Total probing sites rendered. */\n getSiteCount: () => number;\n /** Count of sites at/above the 6mm severe threshold. */\n getDeepPocketCount: () => number;\n}\n\nexport interface PeriodontalChartCardProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children'\n> {\n /** Probing-site readings. Sites are grouped per tooth automatically. */\n sites: PeriodontalSite[];\n /**\n * ISO-8601 date the chart was captured. Rendered as a localised date in\n * the header and exposed as the table caption context. Optional.\n */\n dateIso?: string;\n /**\n * Dentition the chart covers. Drives only the localised header label —\n * tooth grouping is derived from the FDI numbers in `sites`.\n */\n dentition?: 'permanent' | 'primary' | 'mixed';\n /** Per-tooth Miller mobility grade, keyed by FDI tooth number. */\n mobility?: Record<string, PeriodontalMobility>;\n /** Aggregate summary stats rendered above the per-quadrant tables. */\n summary?: PeriodontalChartSummary;\n\n /* ----- i18n / formatting ----- */\n\n /** Locale for date + number formatting. Falls back to `i18n.language`. */\n locale?: string;\n\n /* ----- Styling ----- */\n\n /**\n * `'elevated'` (default) wraps in `<Card variant=\"elevated\">`. `'flat'`\n * drops the Card — use inside another card / sheet.\n */\n surface?: 'flat' | 'elevated';\n\n /* ----- a11y ----- */\n\n /** Override the default region aria-label. */\n 'aria-label'?: string;\n /** Agent-readiness consumer id, surfaced as `data-component-id`. */\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\n/** Classify a pocket depth into a severity band. */\nfunction pocketSeverity(\n depth: number | undefined,\n): 'normal' | 'moderate' | 'severe' {\n if (depth == null || !Number.isFinite(depth)) return 'normal';\n if (depth >= SEVERE_POCKET_MM) return 'severe';\n if (depth >= MODERATE_POCKET_MM) return 'moderate';\n return 'normal';\n}\n\n/** Non-colour severity cue appended to the measurement (`''`/`*`/`**`). */\nfunction severityMarker(severity: 'normal' | 'moderate' | 'severe'): string {\n if (severity === 'severe') return '∗∗';\n if (severity === 'moderate') return '∗';\n return '';\n}\n\n/** FDI quadrant (first digit) of a tooth number, or null if unparseable. */\nfunction quadrantOf(tooth: string): QuadrantId | null {\n const first = tooth.trim().charAt(0);\n return (QUADRANT_ORDER as readonly string[]).includes(first)\n ? (first as QuadrantId)\n : null;\n}\n\ninterface ToothRow {\n tooth: string;\n sites: Partial<Record<PeriodontalSiteId, PeriodontalSite>>;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const PeriodontalChartCard = forwardRef<\n HTMLDivElement,\n PeriodontalChartCardProps\n>(\n (\n {\n sites,\n dateIso,\n dentition = 'permanent',\n mobility,\n summary,\n locale,\n surface = 'elevated',\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const headingId = useId();\n const resolvedLocale = locale ?? i18n.language ?? 'en';\n\n // Group sites by tooth, then bucket teeth into FDI quadrants. The\n // grouping is derived purely from the FDI numbers — the consumer\n // passes a flat site list and the kit owns the layout.\n const { quadrants, toothIds, siteCount, deepPocketCount } = useMemo(() => {\n const byTooth = new Map<string, ToothRow>();\n let sCount = 0;\n let deep = 0;\n for (const site of sites) {\n sCount += 1;\n if ((site.pocketDepthMm ?? 0) >= SEVERE_POCKET_MM) deep += 1;\n let row = byTooth.get(site.tooth);\n if (!row) {\n row = { tooth: site.tooth, sites: {} };\n byTooth.set(site.tooth, row);\n }\n row.sites[site.site] = site;\n }\n\n // Sort teeth within a quadrant by their FDI position digit (2nd\n // char) ascending; keep insertion order as a stable fallback.\n const rows = Array.from(byTooth.values());\n const grouped: Array<{\n quadrant: QuadrantId | null;\n teeth: ToothRow[];\n }> = QUADRANT_ORDER.map((q) => ({\n quadrant: q as QuadrantId | null,\n teeth: rows\n .filter((r) => quadrantOf(r.tooth) === q)\n .sort((a, b) => a.tooth.localeCompare(b.tooth, 'en')),\n })).filter((g) => g.teeth.length > 0);\n\n // Teeth with an unparseable FDI quadrant render in their own group\n // so nothing is silently dropped.\n const unassigned = rows.filter((r) => quadrantOf(r.tooth) === null);\n if (unassigned.length > 0) {\n grouped.push({ quadrant: null, teeth: unassigned });\n }\n\n const ids = grouped.flatMap((g) => g.teeth.map((tt) => tt.tooth));\n return {\n quadrants: grouped,\n toothIds: ids,\n siteCount: sCount,\n deepPocketCount: deep,\n };\n }, [sites]);\n\n useAgentRegistration(\n periodontalChartCardAgent,\n {\n getToothIds: () => toothIds,\n getSiteCount: () => siteCount,\n getDeepPocketCount: () => deepPocketCount,\n },\n id,\n );\n\n const formattedDate = useMemo(() => {\n if (!dateIso) return undefined;\n const parsed = new Date(dateIso);\n if (Number.isNaN(parsed.getTime())) return undefined;\n try {\n return new Intl.DateTimeFormat(resolvedLocale, {\n dateStyle: 'medium',\n }).format(parsed);\n } catch {\n return parsed.toISOString().slice(0, 10);\n }\n }, [dateIso, resolvedLocale]);\n\n const resolvedHeading = t(\n 'periodontalChartCard.heading',\n 'Periodontal chart',\n );\n const resolvedAriaLabel = ariaLabel ?? resolvedHeading;\n\n const DENTITION_DEFAULT: Record<typeof dentition, string> = {\n permanent: 'Permanent dentition',\n primary: 'Primary dentition',\n mixed: 'Mixed dentition',\n };\n const dentitionLabel = t(`periodontalChartCard.dentition.${dentition}`, {\n defaultValue: DENTITION_DEFAULT[dentition],\n });\n\n const formatNumber = (n: number): string => {\n try {\n return new Intl.NumberFormat(resolvedLocale, {\n maximumFractionDigits: 1,\n }).format(n);\n } catch {\n return String(n);\n }\n };\n\n /* ------------------------------------------------------------ */\n /* Summary rows */\n /* ------------------------------------------------------------ */\n\n const summaryRows: Array<{ key: string; label: string; value: ReactNode }> =\n [];\n if (summary?.meanPocketDepthMm != null) {\n summaryRows.push({\n key: 'meanPocketDepth',\n label: t(\n 'periodontalChartCard.summary.meanPocketDepth',\n 'Mean probing depth',\n ),\n value: t('periodontalChartCard.unit.mm', {\n value: formatNumber(summary.meanPocketDepthMm),\n defaultValue: '{{value}} mm',\n }),\n });\n }\n if (summary?.bleedingOnProbingPercent != null) {\n summaryRows.push({\n key: 'bleedingOnProbing',\n label: t(\n 'periodontalChartCard.summary.bleedingOnProbing',\n 'Bleeding on probing',\n ),\n value: t('periodontalChartCard.unit.percent', {\n value: formatNumber(summary.bleedingOnProbingPercent),\n defaultValue: '{{value}}%',\n }),\n });\n }\n\n /* ------------------------------------------------------------ */\n /* Render a single measurement cell */\n /* ------------------------------------------------------------ */\n\n const renderMeasure = (\n depth: number | undefined,\n kind: 'pocket' | 'recession',\n ): ReactNode => {\n if (depth == null || !Number.isFinite(depth)) {\n return (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n );\n }\n const severity = kind === 'pocket' ? pocketSeverity(depth) : 'normal';\n const marker = kind === 'pocket' ? severityMarker(severity) : '';\n const numeric = formatNumber(depth);\n // The flag is announced as a worded suffix for SR users; sighted\n // users get the colour + bold + asterisk. The asterisk itself is\n // aria-hidden so it isn't read as punctuation.\n const srSuffix =\n severity === 'severe'\n ? ` ${t('periodontalChartCard.flag.severe', 'severe pocket')}`\n : severity === 'moderate'\n ? ` ${t('periodontalChartCard.flag.moderate', 'moderate pocket')}`\n : '';\n return (\n <span className={measureVariants({ severity })}>\n <span>{numeric}</span>\n {marker ? <span aria-hidden=\"true\">{marker}</span> : null}\n {srSuffix ? <span className=\"ds:sr-only\">{srSuffix}</span> : null}\n </span>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* Render bleeding / suppuration indicator cell */\n /* ------------------------------------------------------------ */\n\n const renderSigns = (site: PeriodontalSite | undefined): ReactNode => {\n if (!site || (!site.bleeding && !site.suppuration)) {\n return (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n );\n }\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n {site.bleeding ? (\n <span\n role=\"img\"\n aria-label={t(\n 'periodontalChartCard.sign.bleeding',\n 'Bleeding on probing',\n )}\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--destructive)]\"\n />\n ) : null}\n {site.suppuration ? (\n <span\n role=\"img\"\n aria-label={t(\n 'periodontalChartCard.sign.suppuration',\n 'Suppuration',\n )}\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--warning)]\"\n />\n ) : null}\n </span>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* One quadrant table */\n /* ------------------------------------------------------------ */\n\n const renderQuadrant = (group: {\n quadrant: QuadrantId | null;\n teeth: ToothRow[];\n }): ReactNode => {\n const QUADRANT_DEFAULT: Record<QuadrantId, string> = {\n '1': 'Upper right (Q1)',\n '2': 'Upper left (Q2)',\n '3': 'Lower left (Q3)',\n '4': 'Lower right (Q4)',\n };\n const captionText =\n group.quadrant != null\n ? t(`periodontalChartCard.quadrant.${group.quadrant}`, {\n defaultValue: QUADRANT_DEFAULT[group.quadrant],\n })\n : t('periodontalChartCard.quadrant.other', 'Other teeth');\n const cellClass =\n 'ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-center ds:border-b ds:border-[color:var(--border)]';\n const rowHeaderClass =\n 'ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-start ds:font-medium ds:border-b ds:border-[color:var(--border)] ds:whitespace-nowrap';\n return (\n <div\n key={group.quadrant ?? 'other'}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:overflow-x-auto\"\n >\n <table className=\"type-body-sm ds:w-full ds:border-collapse\">\n <caption className=\"type-label ds:text-start ds:mb-[var(--spacing-2xs)] ds:text-[color:var(--muted-foreground)]\">\n {captionText}\n </caption>\n <thead>\n <tr>\n <th\n scope=\"col\"\n className=\"ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-start ds:border-b ds:border-[color:var(--border)]\"\n >\n {t('periodontalChartCard.column.measure', 'Measurement')}\n </th>\n {group.teeth.map((row) => (\n <th\n key={row.tooth}\n scope=\"col\"\n data-tooth-id={row.tooth}\n className=\"ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-center ds:border-b ds:border-[color:var(--border)] ds:[font-variant-numeric:var(--font-feature-tabular)] ds:tabular-nums\"\n >\n <span className=\"ds:sr-only\">\n {t('periodontalChartCard.toothHeader', {\n tooth: row.tooth,\n defaultValue: 'Tooth {{tooth}}',\n })}\n </span>\n <span aria-hidden=\"true\">{row.tooth}</span>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {/* Pocket depth row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t(\n 'periodontalChartCard.row.pocketDepth',\n 'Pocket depth (PD)',\n )}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:items-center ds:justify-center ds:gap-[var(--spacing-2xs)]\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId} className=\"ds:sr-only\">\n {t(`periodontalChartCard.site.${siteId}`, {\n defaultValue: SITE_DEFAULT[siteId],\n })}\n </span>\n ))}\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)]\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderMeasure(\n row.sites[siteId]?.pocketDepthMm,\n 'pocket',\n )}\n </span>\n ))}\n </span>\n </span>\n </td>\n ))}\n </tr>\n {/* Recession row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t('periodontalChartCard.row.recession', 'Recession (REC)')}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)] ds:justify-center\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderMeasure(\n row.sites[siteId]?.recessionMm,\n 'recession',\n )}\n </span>\n ))}\n </span>\n </td>\n ))}\n </tr>\n {/* Bleeding / suppuration row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t(\n 'periodontalChartCard.row.signs',\n 'Bleeding / suppuration',\n )}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)] ds:justify-center\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderSigns(row.sites[siteId])}\n </span>\n ))}\n </span>\n </td>\n ))}\n </tr>\n {/* Mobility row — only when any tooth in the quadrant has a grade */}\n {mobility &&\n group.teeth.some((row) => mobility[row.tooth] != null) ? (\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t('periodontalChartCard.row.mobility', 'Mobility')}\n </th>\n {group.teeth.map((row) => {\n const grade = mobility[row.tooth];\n return (\n <td key={row.tooth} className={cellClass}>\n {grade != null ? (\n <Badge\n variant={grade >= 2 ? 'warning' : 'neutral'}\n size=\"sm\"\n aria-label={t(\n 'periodontalChartCard.mobility.label',\n {\n grade,\n defaultValue: 'Mobility grade {{grade}}',\n },\n )}\n >\n {grade}\n </Badge>\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n )}\n </td>\n );\n })}\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* Legend — explains the non-colour cues */\n /* ------------------------------------------------------------ */\n\n const legend = (\n <div\n role=\"group\"\n className=\"type-meta ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)] ds:text-[color:var(--muted-foreground)]\"\n aria-label={t('periodontalChartCard.legend.label', 'Chart legend')}\n >\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:font-semibold ds:text-[color:var(--warning-foreground)]\"\n >\n {'∗'}\n </span>\n {t('periodontalChartCard.legend.moderate', {\n threshold: MODERATE_POCKET_MM,\n defaultValue: 'PD ≥ {{threshold}} mm',\n })}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:font-bold ds:text-[color:var(--destructive)]\"\n >\n {'∗∗'}\n </span>\n {t('periodontalChartCard.legend.severe', {\n threshold: SEVERE_POCKET_MM,\n defaultValue: 'PD ≥ {{threshold}} mm',\n })}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--destructive)]\"\n />\n {t('periodontalChartCard.sign.bleeding', 'Bleeding on probing')}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--warning)]\"\n />\n {t('periodontalChartCard.sign.suppuration', 'Suppuration')}\n </span>\n </div>\n );\n\n const isEmpty = quadrants.length === 0;\n\n const inner = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <h2\n id={headingId}\n className=\"type-title-card ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {resolvedHeading}\n </h2>\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {formattedDate\n ? t('periodontalChartCard.subtitle.dated', {\n dentition: dentitionLabel,\n date: formattedDate,\n defaultValue: '{{dentition}} · {{date}}',\n })\n : dentitionLabel}\n </p>\n </div>\n\n {summaryRows.length > 0 ? (\n <KeyValueList rowGap=\"sm\">\n {summaryRows.map((row) => (\n <KeyValuePair key={row.key} label={row.label} value={row.value} />\n ))}\n </KeyValueList>\n ) : null}\n\n {isEmpty ? (\n <p\n role=\"status\"\n className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\"\n >\n {t(\n 'periodontalChartCard.empty',\n 'No periodontal readings recorded.',\n )}\n </p>\n ) : (\n <>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {quadrants.map((group) => renderQuadrant(group))}\n </div>\n {legend}\n </>\n )}\n </div>\n );\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-labelledby={headingId}\n data-component=\"periodontal-chart-card\"\n data-component-id={id}\n id={id}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {surface === 'elevated' ? (\n <Card variant=\"elevated\">\n <Card.Body>{inner}</Card.Body>\n </Card>\n ) : (\n inner\n )}\n </div>\n );\n },\n);\n\nPeriodontalChartCard.displayName = 'PeriodontalChartCard';\n\nexport type PeriodontalChartCardSurface = NonNullable<\n VariantProps<typeof rootVariants>['surface']\n>;\n"],"names":["periodontalChartCardAgent","handle","rootVariants","cva","measureVariants","MODERATE_POCKET_MM","SEVERE_POCKET_MM","PERIODONTAL_SITE_ORDER","SITE_DEFAULT","QUADRANT_ORDER","pocketSeverity","depth","severityMarker","severity","quadrantOf","tooth","first","PeriodontalChartCard","forwardRef","sites","dateIso","dentition","mobility","summary","locale","surface","ariaLabel","id","className","rest","ref","t","i18n","useTranslation","headingId","useId","resolvedLocale","quadrants","toothIds","siteCount","deepPocketCount","useMemo","byTooth","sCount","deep","site","row","rows","grouped","q","r","a","b","g","unassigned","ids","tt","useAgentRegistration","formattedDate","parsed","resolvedHeading","resolvedAriaLabel","DENTITION_DEFAULT","dentitionLabel","formatNumber","n","summaryRows","renderMeasure","kind","jsx","marker","numeric","srSuffix","renderSigns","jsxs","renderQuadrant","group","QUADRANT_DEFAULT","captionText","cellClass","rowHeaderClass","siteId","_a","grade","Badge","legend","isEmpty","inner","KeyValueList","KeyValuePair","Fragment","Card"],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ import { R as j } from "./radio-group-rXDJADzW.js";
|
|
|
8
8
|
import { F as f } from "./form-field-CahJzTxp.js";
|
|
9
9
|
import { D as V } from "./date-picker-CepI_oI2.js";
|
|
10
10
|
import { N as H } from "./number-input-Cgu2TtA8.js";
|
|
11
|
-
import { S as Ce } from "./select-
|
|
11
|
+
import { S as Ce } from "./select-Bi8zril7.js";
|
|
12
12
|
import { S as je } from "./switch-OILsBLWo.js";
|
|
13
13
|
import { C as ie } from "./card-DPmk26CL.js";
|
|
14
14
|
import { B as $ } from "./badge-sTusUqZD.js";
|
|
@@ -767,4 +767,4 @@ Ue.displayName = "PregnancyDating";
|
|
|
767
767
|
export {
|
|
768
768
|
Ue as P
|
|
769
769
|
};
|
|
770
|
-
//# sourceMappingURL=pregnancy-dating-
|
|
770
|
+
//# sourceMappingURL=pregnancy-dating-D2wchD11.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pregnancy-dating-DtToyMyc.js","sources":["../../src/components/pregnancy-dating/pregnancy-dating.agent.ts","../../src/components/pregnancy-dating/pregnancy-dating.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — PregnancyDating. */\n/* */\n/* Unified obstetric dating widget: takes any known anchor (LMP / */\n/* conception / IVF transfer / known EDD) and shows both the estimated */\n/* due date and the current gestational age, trimester and milestones, */\n/* with optional CRL re-dating and a ±days nudge. This is the adapter to */\n/* prefer — DueDateCalculator and GestationalAgeCalculator are deprecated */\n/* in favour of it. */\n/* */\n/* The agent surface is the dating inputs plus the computed EDD / GA; the */\n/* handle is the curated `PregnancyDatingHandle` (the public `ref` stays */\n/* the root <div>, exactly as `slider.tsx` and `bmi-calculator.tsx` keep */\n/* 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/* Host-delegated, deliberately WITHOUT actions: the optional antenatal- */\n/* schedule inputs (plurality, chorionicity, Rh status, GDM risk) only */\n/* appear under `showSchedule` and steer the appended exam timeline, not */\n/* the dating result. An agent reaches them through the DOM — the */\n/* Select / Switch controls inside `data-component=\"pregnancy-dating\"`. */\n/* */\n/* PHI (§7): never exposes patient identity — the slots return the */\n/* operator's own structural dating inputs and the dates derived from */\n/* them. See `src/docs/26-agent-readiness.mdx`. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { PregnancyDatingHandle } from './pregnancy-dating';\n\n/** Shared JSON Schema fragment for a local calendar date. */\nconst isoDate = {\n type: 'string',\n pattern: '^\\\\d{4}-\\\\d{2}-\\\\d{2}$',\n} as const;\n\nexport const pregnancyDatingAgent: AgentAdapter<PregnancyDatingHandle> = {\n id: 'pregnancy-dating',\n // set_value → the seven `set_*` actions + the `inputs` state slot.\n capabilities: ['set_value'],\n state: {\n inputs: {\n type: '{ method: string, referenceDate: string | null, cycleLength: number | null, embryoAge: 3 | 5, crlMm: number | null, scanDate: string | null, datingAdjustment: number | null, asOfDate: string }',\n descriptionKey: 'ui.agent.pregnancyDating.state.inputs',\n description:\n 'The dating inputs as entered — anchor method, its reference date, cycle length (LMP), embryo age (IVF), the optional CRL + scan date, the manual ±days nudge, and the evaluation date. Dates are `yyyy-MM-dd`. Read this to see which method a reference date will be interpreted under.',\n read: (handle) => handle.getInputs(),\n },\n result: {\n type: '{ dueDate: string, gestationalStart: string, gestationalAge: { weeks: number, days: number, totalDays: number } | null, trimester: string } | null',\n descriptionKey: 'ui.agent.pregnancyDating.state.result',\n description:\n 'Computed estimated delivery date, the GA day-0 anchor after any re-dating or adjustment, the gestational age in completed weeks + days as of the evaluation date, and the trimester band (preconception / first / second / third / postterm). Null until a reference date is set.',\n read: (handle) => handle.getResult(),\n },\n },\n actions: {\n set_method: {\n // Drives the same local input state a user picks; nothing is persisted\n // to a record, and the choice is reversible in the same UI.\n safety: 'write',\n argsType: \"{ method: 'lmp' | 'conception' | 'ivf' | 'edd' }\",\n argsSchema: {\n type: 'object',\n properties: {\n method: {\n enum: ['lmp', 'conception', 'ivf', 'edd'],\n description:\n 'Which anchor to date from — last menstrual period, conception, IVF transfer, or a known estimated delivery date.',\n },\n },\n required: ['method'],\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the method was applied.',\n },\n errors: [\n 'Returns false for a method outside the four supported anchors.',\n ],\n examples: [\n { args: { method: 'edd' }, note: 'Date backwards from a known EDD.' },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setMethod',\n description:\n 'Choose which anchor the pregnancy is dated from. The reference date is kept and re-interpreted under the new method, so set the method first — only a known EDD may be in the future.',\n invoke: (\n handle,\n args: { method: 'lmp' | 'conception' | 'ivf' | 'edd' },\n ) => handle.setMethod(args.method),\n },\n set_reference_date: {\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 'The date the active method anchors on — LMP, conception, transfer, or known EDD — or null to clear it. Only a known EDD may 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 for a future date under any method but `edd` — the on-screen DatePicker caps those at today.',\n ],\n examples: [\n {\n args: { date: '2026-01-12' },\n note: 'Under the default LMP method, a last period starting 12 January.',\n },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setReferenceDate',\n description:\n 'Set the reference date for the active method. This is the only required input — the result stays null without it.',\n invoke: (handle, args: { date: string | null }) =>\n handle.setReferenceDate(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 'Applies but changes nothing unless the method is `lmp`, and is ignored once a CRL re-dating is confirmed.',\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setCycleLength',\n description:\n 'LMP method only — set the average cycle length, which shifts Naegele dating off the 28-day assumption.',\n invoke: (handle, args: { days: number | null }) =>\n handle.setCycleLength(args.days),\n },\n set_embryo_age: {\n safety: 'write',\n argsType: '{ days: 3 | 5 }',\n argsSchema: {\n type: 'object',\n properties: {\n days: {\n enum: [3, 5],\n description:\n 'Embryo age at transfer in days — 3 (cleavage) or 5 (blastocyst).',\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 for any value other than 3 or 5.',\n 'Applies but changes nothing unless the method is `ivf`.',\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setEmbryoAge',\n description:\n 'IVF method only — set the embryo age at transfer, which offsets the transfer date back to a notional LMP.',\n invoke: (handle, args: { days: 3 | 5 }) => handle.setEmbryoAge(args.days),\n },\n set_crl: {\n safety: 'write',\n argsType: '{ crlMm?: number | null, scanDate?: string | null }',\n argsSchema: {\n type: 'object',\n properties: {\n crlMm: {\n oneOf: [{ type: 'number', exclusiveMinimum: 0 }, { type: 'null' }],\n description:\n 'Crown-rump length in millimetres, or null to clear it.',\n },\n scanDate: {\n oneOf: [{ ...isoDate }, { type: 'null' }],\n description:\n 'Date of the CRL scan (`yyyy-MM-dd`, not in the future), or null to clear it.',\n },\n },\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the measurement was applied.',\n },\n errors: [\n 'Returns false and writes nothing when the length is not positive or the scan date is unparseable or in the future — the payload applies all-or-nothing.',\n 'Re-dating only happens under the `lmp` method, and only when both the length and the scan date are set.',\n ],\n examples: [\n {\n args: { crlMm: 42, scanDate: '2026-02-20' },\n note: 'A first-trimester CRL that may re-date the pregnancy per ACOG CO 700.',\n },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setCrl',\n description:\n 'LMP method only — set the first-trimester crown-rump length and its scan date. A confirmed re-dating wins over both the cycle length and the manual adjustment.',\n invoke: (\n handle,\n args: { crlMm?: number | null; scanDate?: string | null },\n ) => handle.setCrl(args),\n },\n set_dating_adjustment: {\n safety: 'write',\n argsType: '{ days: number | null }',\n argsSchema: {\n type: 'object',\n properties: {\n days: {\n oneOf: [{ type: 'integer' }, { type: 'null' }],\n description:\n 'Whole days to nudge the dating by — positive moves the pregnancy further along — or null for no adjustment.',\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 for a non-integer number of days.',\n 'Applies but changes nothing while a CRL re-dating is confirmed — the measurement wins.',\n ],\n examples: [\n {\n args: { days: 3 },\n note: 'An uncertain LMP judged three days earlier than entered.',\n },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setDatingAdjustment',\n description:\n 'Nudge the dating by whole days for an uncertain anchor. Positive moves the pregnancy further along (earlier effective LMP, earlier due date).',\n invoke: (handle, args: { days: number | null }) =>\n handle.setDatingAdjustment(args.days),\n },\n set_as_of_date: {\n safety: 'write',\n argsType: '{ date: string }',\n argsSchema: {\n type: 'object',\n properties: {\n date: {\n ...isoDate,\n description:\n 'Date to evaluate gestational age and trimester against, `yyyy-MM-dd`. May be in the future to project forward.',\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: ['Returns false for an unparseable date.'],\n examples: [\n {\n args: { date: '2026-09-15' },\n note: 'Project gestational age forward to an upcoming appointment.',\n },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setAsOfDate',\n description:\n 'Set the date gestational age, trimester and the antenatal schedule are evaluated against. Defaults to today; the estimated delivery date itself does not depend on it.',\n invoke: (handle, args: { date: string }) => handle.setAsOfDate(args.date),\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'pregnancy-dating',\n description: 'Marks the PregnancyDating 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 the handle-driven actions/state are unreachable.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* PregnancyDating — the unified obstetric dating widget. */\n/* */\n/* Supersedes DueDateCalculator + GestationalAgeCalculator: takes any */\n/* known anchor (LMP / conception / IVF transfer / known EDD) and shows */\n/* BOTH the estimated due date AND the current gestational age, */\n/* trimester and milestones. Two dating refinements: a precise CRL + */\n/* scan-date ACOG CO 700 re-dating (LMP), and a quick manual ±days */\n/* adjustment for an uncertain LMP/conception. `showSchedule` appends */\n/* the antenatal exam schedule with plurality / chorionicity / risk */\n/* inputs. All maths lives in `_shared/obstetrics` + `_shared/antenatal- */\n/* schedule` (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, subDays } from 'date-fns';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { pregnancyDatingAgent } from './pregnancy-dating.agent';\nimport { RadioGroup, Radio } from '../radio-group';\nimport { FormField } from '../form-field';\nimport { DatePicker } from '../date-picker';\nimport { NumberInput } from '../number-input';\nimport { Select } from '../select';\nimport { Switch } from '../switch';\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 EmbryoAge,\n type GestationalAge,\n type DueDateResult,\n type Plurality,\n type Chorionicity,\n computeDueDate,\n redateByCrl,\n gestationalMilestones,\n GESTATION_DAYS,\n CONCEPTION_OFFSET_DAYS,\n DEFAULT_CYCLE_LENGTH,\n TRIMESTER_BADGE_VARIANT,\n trimesterHighlightToken,\n} from '../_shared/obstetrics';\nimport {\n computeAntenatalSchedule,\n type AntenatalScheduleOptions,\n type GdmRisk,\n} from '../_shared/antenatal-schedule';\nimport {\n AntenatalScheduleTimeline,\n buildScheduleInsertFields,\n} from '../_shared/antenatal-schedule-timeline';\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/** Any known anchor the pregnancy can be dated from. */\nexport type DatingMethod = 'lmp' | 'conception' | 'ivf' | 'edd';\n\n/** i18n key for each method's reference-date field. */\nconst DATE_LABEL_KEY: Record<DatingMethod, string> = {\n lmp: 'pregnancyDating.lmpDate',\n conception: 'pregnancyDating.conceptionDate',\n ivf: 'pregnancyDating.transferDate',\n edd: 'pregnancyDating.eddDate',\n};\n\nexport interface PregnancyDatingResult {\n /** Estimated date of delivery. */\n dueDate: Date;\n /** GA day-0 anchor (effective LMP) after any re-dating / adjustment. */\n gestationalStart: Date;\n /** Gestational age as of the evaluation date; `null` before conception. */\n gestationalAge: GestationalAge | null;\n trimester: DueDateResult['trimester'];\n}\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;\n\n/** The dating inputs as entered. */\nexport interface PregnancyDatingInputsSnapshot {\n /** Which anchor the pregnancy is dated from. */\n method: DatingMethod;\n /** The method's reference date (`yyyy-MM-dd`), or null when unset. */\n referenceDate: string | null;\n /** LMP only — average cycle length in days, or null for the 28-day default. */\n cycleLength: number | null;\n /** IVF only — embryo age at transfer, in days. */\n embryoAge: EmbryoAge;\n /** LMP only — crown-rump length in millimetres, or null. */\n crlMm: number | null;\n /** LMP only — date of the CRL scan (`yyyy-MM-dd`), or null. */\n scanDate: string | null;\n /** Manual ±days nudge applied to the dating, or null. */\n datingAdjustment: number | null;\n /** The date gestational age and trimester are evaluated against. */\n asOfDate: string;\n}\n\n/** `PregnancyDatingResult` projected onto the agent boundary — ISO dates. */\nexport interface PregnancyDatingSnapshot {\n /** Estimated date of delivery, `yyyy-MM-dd`. */\n dueDate: string;\n /** GA day-0 anchor after any re-dating / adjustment, `yyyy-MM-dd`. */\n gestationalStart: string;\n /** Gestational age as of the evaluation date; null before conception. */\n gestationalAge: { weeks: number; days: number; totalDays: number } | null;\n /** Trimester band as of the evaluation date. */\n trimester: DueDateResult['trimester'];\n}\n\n/**\n * Curated imperative handle for agent / external automation. Reads the dating\n * inputs and the computed EDD + gestational age, and drives the inputs the way\n * a user would. Never exposes patient identity — only structural dates and\n * numbers. Consumed by `pregnancy-dating.agent.ts`; the public `ref` stays the\n * root DOM element.\n */\nexport interface PregnancyDatingHandle {\n /** The dating inputs as entered. */\n getInputs: () => PregnancyDatingInputsSnapshot;\n /** Computed due date, gestational age and trimester, or null until a reference date is set. */\n getResult: () => PregnancyDatingSnapshot | null;\n /** Switch the dating anchor. Keeps the reference date, which is re-interpreted. */\n setMethod: (method: DatingMethod) => boolean;\n /** Set the method's reference date (`yyyy-MM-dd`); only a known EDD may be in the future. */\n setReferenceDate: (isoDate: string | null) => boolean;\n /** LMP only — set the average cycle length in days (20–45). */\n setCycleLength: (days: number | null) => boolean;\n /** IVF only — set the embryo age at transfer (3 or 5 days). */\n setEmbryoAge: (days: EmbryoAge) => boolean;\n /** LMP only — set the CRL measurement and/or its scan date for ACOG re-dating. */\n setCrl: (next: {\n crlMm?: number | null;\n scanDate?: string | null;\n }) => boolean;\n /** Set the manual ±days dating nudge (positive = further along). */\n setDatingAdjustment: (days: number | null) => boolean;\n /** Set the date gestational age and trimester are evaluated against. */\n setAsOfDate: (isoDate: string) => boolean;\n}\n\nexport interface PregnancyDatingProps extends VariantProps<\n typeof rootVariants\n> {\n /** Initial dating method. Defaults to `'lmp'`. */\n defaultMethod?: DatingMethod;\n /** Pre-fill the reference date (e.g. a known LMP from the patient record). */\n defaultReferenceDate?: Date;\n /** Fires whenever a result can be computed (and `null` when it can't). */\n onResultChange?: (result: PregnancyDatingResult | null) => void;\n /** When provided, shows the result-action buttons that emit / copy the result. */\n onInsert?: (payload: InsertPayload) => void;\n /** Which verb the result button performs. Defaults to `'insert'`. */\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 /** Brand wordmark printed in the inserted/copied result-card footer. */\n insertBrand?: string | false;\n /** Append the antenatal exam schedule + reveal the plurality / risk inputs. */\n showSchedule?: boolean;\n /** `showSchedule` only — initial number of babies. Defaults to `'singleton'`. */\n defaultPlurality?: Plurality;\n /** `showSchedule` only — initial chorionicity for multiples. Defaults to `'unknown'`. */\n defaultChorionicity?: Chorionicity;\n /** `showSchedule` only — initial Rh-negative state (surfaces anti-D). */\n defaultRhNegative?: boolean;\n /** `showSchedule` only — initial gestational-diabetes risk tier (surfaces OGTT). */\n defaultGdmRisk?: GdmRisk;\n /**\n * Passthrough options for the appended schedule (national `schedule`,\n * `includeOnIndication`, `birthGuideline`). `today`, `plurality`,\n * `chorionicity`, `rhNegative` and `gdmRisk` come from the component's own\n * inputs. Ignored unless `showSchedule` is set.\n */\n scheduleOptions?: Omit<\n AntenatalScheduleOptions,\n 'today' | 'plurality' | 'chorionicity' | 'rhNegative' | 'gdmRisk'\n >;\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 PregnancyDating = forwardRef<HTMLDivElement, PregnancyDatingProps>(\n (\n {\n defaultMethod = 'lmp',\n defaultReferenceDate,\n onResultChange,\n onInsert,\n insertVariant = 'insert',\n onCopy,\n onError,\n insertBrand,\n showSchedule = false,\n defaultPlurality = 'singleton',\n defaultChorionicity = 'unknown',\n defaultRhNegative = false,\n defaultGdmRisk,\n scheduleOptions,\n id,\n width,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const [method, setMethod] = useState<DatingMethod>(defaultMethod);\n const [refDate, setRefDate] = useState<Date | undefined>(\n defaultReferenceDate,\n );\n const [cycleLength, setCycleLength] = useState<number | null>(\n DEFAULT_CYCLE_LENGTH,\n );\n const [embryoAge, setEmbryoAge] = useState<EmbryoAge>(5);\n // Precise re-dating (LMP method) and the quick ±days nudge.\n const [crlMm, setCrlMm] = useState<number | null>(null);\n const [scanDate, setScanDate] = useState<Date | undefined>(undefined);\n const [datingAdjustment, setDatingAdjustment] = useState<number | null>(\n null,\n );\n // Evaluation date (\"as of\") + multiple-pregnancy / risk inputs.\n const [asOfDate, setAsOfDate] = useState<Date>(() => new Date());\n const [plurality, setPlurality] = useState<Plurality>(defaultPlurality);\n const [chorionicity, setChorionicity] =\n useState<Chorionicity>(defaultChorionicity);\n const [rhNegative, setRhNegative] = useState<boolean>(defaultRhNegative);\n const [gdmRisk, setGdmRisk] = useState<GdmRisk | 'none'>(\n defaultGdmRisk ?? 'none',\n );\n\n // Real today caps the past-only date inputs (LMP, conception, transfer, scan).\n const today = useMemo(() => new Date(), []);\n\n // CRL re-dating (LMP method only) — the measurement-based path.\n const redating = useMemo(() => {\n if (method !== 'lmp' || !refDate || crlMm === null || !scanDate) {\n return null;\n }\n return redateByCrl({ lmp: refDate, scanDate, crlMm });\n }, [method, refDate, crlMm, scanDate]);\n\n const data = useMemo(() => {\n if (!refDate) return null;\n\n // Resolve the method's anchor to an effective LMP (GA day 0).\n let effectiveLmp: Date;\n let cycleForEdd = DEFAULT_CYCLE_LENGTH;\n if (method === 'lmp') {\n effectiveLmp = refDate;\n cycleForEdd = cycleLength ?? DEFAULT_CYCLE_LENGTH;\n } else if (method === 'conception') {\n effectiveLmp = subDays(refDate, CONCEPTION_OFFSET_DAYS);\n } else if (method === 'ivf') {\n effectiveLmp = subDays(refDate, embryoAge + CONCEPTION_OFFSET_DAYS);\n } else {\n effectiveLmp = subDays(refDate, GESTATION_DAYS);\n }\n\n // A confirmed CRL re-dating wins over everything (measurement-based); else\n // apply the quick ±days nudge (+ = pregnancy further along → earlier LMP).\n if (method === 'lmp' && redating?.redated) {\n effectiveLmp = redating.gestationalStart;\n cycleForEdd = DEFAULT_CYCLE_LENGTH;\n } else if (datingAdjustment) {\n effectiveLmp = subDays(effectiveLmp, datingAdjustment);\n }\n\n const r = computeDueDate(\n { method: 'lmp', date: effectiveLmp, cycleLength: cycleForEdd },\n asOfDate,\n );\n return {\n result: {\n dueDate: r.dueDate,\n gestationalStart: r.gestationalStart,\n gestationalAge: r.gestationalAge,\n trimester: r.trimester,\n } satisfies PregnancyDatingResult,\n milestones: gestationalMilestones(r.gestationalStart),\n };\n }, [\n method,\n refDate,\n cycleLength,\n embryoAge,\n redating,\n datingAdjustment,\n asOfDate,\n ]);\n\n const result = data?.result ?? null;\n\n const schedule = useMemo(() => {\n if (!showSchedule || !result) return null;\n return computeAntenatalSchedule(result.gestationalStart, {\n ...scheduleOptions,\n today: asOfDate,\n plurality,\n chorionicity,\n rhNegative,\n gdmRisk: gdmRisk === 'none' ? undefined : gdmRisk,\n });\n }, [\n showSchedule,\n result,\n asOfDate,\n scheduleOptions,\n plurality,\n chorionicity,\n rhNegative,\n gdmRisk,\n ]);\n\n const longDate = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'long' }),\n [i18n.language],\n );\n const medDate = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }),\n [i18n.language],\n );\n\n useEffect(() => {\n onResultChange?.(result);\n }, [result, onResultChange]);\n\n /* ── Agent handle ────────────────────────────────────────────────── */\n const liveRef = useRef({\n method,\n refDate,\n cycleLength,\n embryoAge,\n crlMm,\n scanDate,\n datingAdjustment,\n asOfDate,\n result,\n });\n liveRef.current = {\n method,\n refDate,\n cycleLength,\n embryoAge,\n crlMm,\n scanDate,\n datingAdjustment,\n asOfDate,\n result,\n };\n\n const agentHandle = useMemo<PregnancyDatingHandle>(\n () => ({\n getInputs: () => {\n const live = liveRef.current;\n return {\n method: live.method,\n referenceDate: live.refDate ? toIsoDate(live.refDate) : null,\n cycleLength: live.cycleLength,\n embryoAge: live.embryoAge,\n crlMm: live.crlMm,\n scanDate: live.scanDate ? toIsoDate(live.scanDate) : null,\n datingAdjustment: live.datingAdjustment,\n asOfDate: toIsoDate(live.asOfDate),\n };\n },\n getResult: () => {\n const r = liveRef.current.result;\n if (!r) return null;\n return {\n dueDate: toIsoDate(r.dueDate),\n gestationalStart: toIsoDate(r.gestationalStart),\n gestationalAge: r.gestationalAge ? { ...r.gestationalAge } : null,\n trimester: r.trimester,\n };\n },\n setMethod: (next) => {\n if (\n next !== 'lmp' &&\n next !== 'conception' &&\n next !== 'ivf' &&\n next !== 'edd'\n ) {\n return false;\n }\n setMethod(next);\n return true;\n },\n setReferenceDate: (isoDate) => {\n if (isoDate === null) {\n setRefDate(undefined);\n return true;\n }\n const parsed = fromIsoDate(isoDate);\n if (!parsed) return false;\n // The DatePicker caps every anchor but a known EDD at today.\n if (liveRef.current.method !== 'edd' && isAfter(parsed, new Date())) {\n return false;\n }\n setRefDate(parsed);\n return true;\n },\n setCycleLength: (days) => {\n if (\n days !== null &&\n !(\n Number.isFinite(days) &&\n days >= CYCLE_LENGTH_RANGE.min &&\n days <= CYCLE_LENGTH_RANGE.max\n )\n ) {\n return false;\n }\n setCycleLength(days);\n return true;\n },\n setEmbryoAge: (days) => {\n if (days !== 3 && days !== 5) return false;\n setEmbryoAge(days);\n return true;\n },\n setCrl: (next) => {\n const now = new Date();\n let parsedScan: Date | undefined;\n // Validate the whole payload before writing any of it, so a bad\n // value can't leave the form half-updated.\n if ('crlMm' in next) {\n const mm = next.crlMm;\n if (\n mm !== null &&\n mm !== undefined &&\n !(Number.isFinite(mm) && mm > 0)\n ) {\n return false;\n }\n }\n if ('scanDate' in next && next.scanDate != null) {\n const d = fromIsoDate(next.scanDate);\n if (!d || isAfter(d, now)) return false;\n parsedScan = d;\n }\n if ('crlMm' in next) setCrlMm(next.crlMm ?? null);\n if ('scanDate' in next) setScanDate(parsedScan);\n return true;\n },\n setDatingAdjustment: (days) => {\n if (days !== null && !Number.isInteger(days)) return false;\n setDatingAdjustment(days);\n return true;\n },\n setAsOfDate: (isoDate) => {\n const parsed = fromIsoDate(isoDate);\n if (!parsed) return false;\n setAsOfDate(parsed);\n return true;\n },\n }),\n [],\n );\n useAgentRegistration(pregnancyDatingAgent, agentHandle, id);\n\n const chorionicityOptions = useMemo(\n () =>\n (\n [\n 'unknown',\n 'dichorionic-diamniotic',\n 'monochorionic-diamniotic',\n 'monochorionic-monoamniotic',\n ] as const\n ).map((c) => ({\n value: c,\n label: t(`antenatalSchedule.chorionicity.${c}`),\n })),\n [t],\n );\n\n const gaText = (ga: GestationalAge | null): string =>\n ga\n ? t('pregnancyDating.result.gestation', {\n weeks: ga.weeks,\n days: ga.days,\n })\n : '—';\n\n return (\n <div\n ref={ref}\n data-component=\"pregnancy-dating\"\n data-component-id={id}\n className={rootVariants({ width, className })}\n >\n <RadioGroup\n label={t('pregnancyDating.method.label')}\n variant=\"horizontal\"\n value={method}\n onValueChange={(next) => setMethod(next as DatingMethod)}\n >\n <Radio label={t('pregnancyDating.method.lmp')} value=\"lmp\" />\n <Radio\n label={t('pregnancyDating.method.conception')}\n value=\"conception\"\n />\n <Radio label={t('pregnancyDating.method.ivf')} value=\"ivf\" />\n <Radio label={t('pregnancyDating.method.edd')} value=\"edd\" />\n </RadioGroup>\n\n <div className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-2\">\n <FormField label={t(DATE_LABEL_KEY[method])}>\n <DatePicker\n value={refDate}\n onChange={setRefDate}\n maxDate={method === 'edd' ? undefined : today}\n />\n </FormField>\n\n {method === 'lmp' && (\n <FormField\n label={t('pregnancyDating.cycleLength')}\n description={t('pregnancyDating.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 )}\n\n {method === 'ivf' && (\n <RadioGroup\n label={t('pregnancyDating.embryoAge')}\n variant=\"horizontal\"\n value={String(embryoAge)}\n onValueChange={(next) => setEmbryoAge(Number(next) as EmbryoAge)}\n >\n <Radio label={t('pregnancyDating.day3')} value=\"3\" />\n <Radio label={t('pregnancyDating.day5')} value=\"5\" />\n </RadioGroup>\n )}\n\n <FormField\n label={t('pregnancyDating.datingAdjustment')}\n description={t('pregnancyDating.datingAdjustmentHint')}\n >\n <NumberInput\n mode=\"integer\"\n value={datingAdjustment}\n onChange={setDatingAdjustment}\n />\n </FormField>\n\n <FormField\n label={t('pregnancyDating.asOfDate')}\n description={t('pregnancyDating.asOfDateHint')}\n >\n <DatePicker\n value={asOfDate}\n onChange={(d) => d && setAsOfDate(d)}\n />\n </FormField>\n </div>\n\n {method === 'lmp' ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-2\">\n <FormField\n label={t('pregnancyDating.crl')}\n description={t('pregnancyDating.crlHint')}\n >\n <NumberInput\n mode=\"decimal\"\n min={0}\n step={0.1}\n value={crlMm}\n onChange={setCrlMm}\n />\n </FormField>\n <FormField label={t('pregnancyDating.scanDate')}>\n <DatePicker\n value={scanDate}\n onChange={setScanDate}\n maxDate={today}\n />\n </FormField>\n </div>\n {redating ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Badge variant={redating.redated ? 'warning' : 'success'}>\n {redating.redated\n ? t('pregnancyDating.redated', {\n days: redating.discrepancyDays,\n })\n : t('pregnancyDating.datesAgree')}\n </Badge>\n {!redating.crlInRange ? (\n <span className=\"type-meta ds:text-muted-foreground\">\n {t('pregnancyDating.crlOutOfRange')}\n </span>\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null}\n\n {showSchedule ? (\n <>\n <RadioGroup\n label={t('antenatalSchedule.plurality.label')}\n variant=\"horizontal\"\n value={plurality}\n onValueChange={(next) => setPlurality(next as Plurality)}\n >\n <Radio\n label={t('antenatalSchedule.plurality.singleton')}\n value=\"singleton\"\n />\n <Radio\n label={t('antenatalSchedule.plurality.twin')}\n value=\"twin\"\n />\n <Radio\n label={t('antenatalSchedule.plurality.triplet')}\n value=\"triplet\"\n />\n </RadioGroup>\n\n {plurality !== 'singleton' ? (\n <FormField label={t('antenatalSchedule.chorionicity.label')}>\n <Select\n options={chorionicityOptions}\n value={chorionicity}\n onValueChange={(next) =>\n setChorionicity(next as Chorionicity)\n }\n />\n </FormField>\n ) : null}\n\n <Switch\n label={t('antenatalSchedule.rhNegative')}\n checked={rhNegative}\n onCheckedChange={setRhNegative}\n />\n\n <RadioGroup\n label={t('antenatalSchedule.gdmRisk.label')}\n variant=\"horizontal\"\n value={gdmRisk}\n onValueChange={(next) => setGdmRisk(next as GdmRisk | 'none')}\n >\n <Radio label={t('antenatalSchedule.gdmRisk.none')} value=\"none\" />\n <Radio\n label={t('antenatalSchedule.gdmRisk.medium')}\n value=\"medium\"\n />\n <Radio label={t('antenatalSchedule.gdmRisk.high')} value=\"high\" />\n </RadioGroup>\n </>\n ) : null}\n\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {result\n ? `${t('pregnancyDating.result.dueDateLabel')}: ${longDate.format(\n result.dueDate,\n )}. ${t('pregnancyDating.result.gestationLabel')}: ${gaText(\n result.gestationalAge,\n )}.`\n : ''}\n </p>\n\n {data && result ? (\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {/* EDD is the headline — full width so a long localized date\n never wraps; gestational age + trimester flow beneath it,\n packed to the start so they don't strand a gap at narrow /\n modal widths. */}\n <dl className=\"ds:flex ds:flex-wrap ds:items-start ds:gap-x-[var(--spacing-xl)] ds:gap-y-[var(--spacing-md)]\">\n <div className=\"ds:basis-full ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('pregnancyDating.result.dueDateLabel')}\n </dt>\n <dd className=\"type-metric ds:text-foreground\">\n {longDate.format(result.dueDate)}\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('pregnancyDating.result.gestationLabel')}\n </dt>\n <dd className=\"type-body ds:text-foreground\">\n {gaText(result.gestationalAge)}\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('pregnancyDating.result.trimesterLabel')}\n </dt>\n <dd>\n <Badge\n variant={TRIMESTER_BADGE_VARIANT[result.trimester]}\n size=\"lg\"\n >\n {t(`pregnancyDating.trimester.${result.trimester}`)}\n </Badge>\n </dd>\n </div>\n </dl>\n\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('pregnancyDating.milestonesLabel')}\n </span>\n <ul className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n {data.milestones.map((m) => {\n const reached = isAfter(asOfDate, m.date);\n return (\n <li\n key={m.key}\n className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-md)]\"\n >\n <span className=\"type-body ds:text-foreground\">\n {t(`pregnancyDating.milestone.${m.key}`)}\n </span>\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span className=\"type-body ds:text-muted-foreground\">\n {medDate.format(m.date)}\n </span>\n {reached ? (\n <Badge variant=\"success\">\n {t('pregnancyDating.reached')}\n </Badge>\n ) : null}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n </Card.Body>\n </Card>\n ) : (\n <p className=\"type-body ds:text-muted-foreground\">\n {t('pregnancyDating.empty')}\n </p>\n )}\n\n {schedule ? <AntenatalScheduleTimeline events={schedule} /> : null}\n\n {result && (insertVariant === 'copy' || onInsert) ? (\n <InsertButton\n onInsert={onInsert}\n variant={insertVariant}\n onCopy={onCopy}\n onError={onError}\n card={{\n title: t('insert.title.pregnancyDating'),\n icon: 'calendar-heart',\n highlight: longDate.format(result.dueDate),\n highlightToken: trimesterHighlightToken(result.trimester),\n brand: insertBrand,\n fields: [\n {\n icon: 'calendar',\n label: t('pregnancyDating.result.dueDateLabel'),\n value: longDate.format(result.dueDate),\n },\n {\n icon: 'clock',\n label: t('pregnancyDating.result.gestationLabel'),\n value: gaText(result.gestationalAge),\n },\n {\n icon: 'tag',\n label: t('pregnancyDating.result.trimesterLabel'),\n value: t(`pregnancyDating.trimester.${result.trimester}`),\n },\n ...(schedule\n ? buildScheduleInsertFields(schedule, t, (d) =>\n medDate.format(d),\n )\n : []),\n ],\n }}\n />\n ) : null}\n </div>\n );\n },\n);\n\nPregnancyDating.displayName = 'PregnancyDating';\n"],"names":["isoDate","pregnancyDatingAgent","handle","args","rootVariants","cva","DATE_LABEL_KEY","toIsoDate","d","format","fromIsoDate","iso","parseISO","CYCLE_LENGTH_RANGE","PregnancyDating","forwardRef","defaultMethod","defaultReferenceDate","onResultChange","onInsert","insertVariant","onCopy","onError","insertBrand","showSchedule","defaultPlurality","defaultChorionicity","defaultRhNegative","defaultGdmRisk","scheduleOptions","id","width","className","ref","i18n","useTranslation","method","setMethod","useState","refDate","setRefDate","cycleLength","setCycleLength","DEFAULT_CYCLE_LENGTH","embryoAge","setEmbryoAge","crlMm","setCrlMm","scanDate","setScanDate","datingAdjustment","setDatingAdjustment","asOfDate","setAsOfDate","plurality","setPlurality","chorionicity","setChorionicity","rhNegative","setRhNegative","gdmRisk","setGdmRisk","today","useMemo","redating","redateByCrl","data","effectiveLmp","cycleForEdd","subDays","CONCEPTION_OFFSET_DAYS","GESTATION_DAYS","r","computeDueDate","gestationalMilestones","result","schedule","computeAntenatalSchedule","longDate","medDate","useEffect","liveRef","useRef","agentHandle","live","next","parsed","isAfter","days","now","parsedScan","mm","useAgentRegistration","chorionicityOptions","c","gaText","ga","jsxs","RadioGroup","jsx","Radio","FormField","DatePicker","NumberInput","Badge","Fragment","Select","Switch","Card","TRIMESTER_BADGE_VARIANT","m","reached","AntenatalScheduleTimeline","InsertButton","trimesterHighlightToken","buildScheduleInsertFields"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pregnancy-dating-D2wchD11.js","sources":["../../src/components/pregnancy-dating/pregnancy-dating.agent.ts","../../src/components/pregnancy-dating/pregnancy-dating.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — PregnancyDating. */\n/* */\n/* Unified obstetric dating widget: takes any known anchor (LMP / */\n/* conception / IVF transfer / known EDD) and shows both the estimated */\n/* due date and the current gestational age, trimester and milestones, */\n/* with optional CRL re-dating and a ±days nudge. This is the adapter to */\n/* prefer — DueDateCalculator and GestationalAgeCalculator are deprecated */\n/* in favour of it. */\n/* */\n/* The agent surface is the dating inputs plus the computed EDD / GA; the */\n/* handle is the curated `PregnancyDatingHandle` (the public `ref` stays */\n/* the root <div>, exactly as `slider.tsx` and `bmi-calculator.tsx` keep */\n/* 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/* Host-delegated, deliberately WITHOUT actions: the optional antenatal- */\n/* schedule inputs (plurality, chorionicity, Rh status, GDM risk) only */\n/* appear under `showSchedule` and steer the appended exam timeline, not */\n/* the dating result. An agent reaches them through the DOM — the */\n/* Select / Switch controls inside `data-component=\"pregnancy-dating\"`. */\n/* */\n/* PHI (§7): never exposes patient identity — the slots return the */\n/* operator's own structural dating inputs and the dates derived from */\n/* them. See `src/docs/26-agent-readiness.mdx`. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { PregnancyDatingHandle } from './pregnancy-dating';\n\n/** Shared JSON Schema fragment for a local calendar date. */\nconst isoDate = {\n type: 'string',\n pattern: '^\\\\d{4}-\\\\d{2}-\\\\d{2}$',\n} as const;\n\nexport const pregnancyDatingAgent: AgentAdapter<PregnancyDatingHandle> = {\n id: 'pregnancy-dating',\n // set_value → the seven `set_*` actions + the `inputs` state slot.\n capabilities: ['set_value'],\n state: {\n inputs: {\n type: '{ method: string, referenceDate: string | null, cycleLength: number | null, embryoAge: 3 | 5, crlMm: number | null, scanDate: string | null, datingAdjustment: number | null, asOfDate: string }',\n descriptionKey: 'ui.agent.pregnancyDating.state.inputs',\n description:\n 'The dating inputs as entered — anchor method, its reference date, cycle length (LMP), embryo age (IVF), the optional CRL + scan date, the manual ±days nudge, and the evaluation date. Dates are `yyyy-MM-dd`. Read this to see which method a reference date will be interpreted under.',\n read: (handle) => handle.getInputs(),\n },\n result: {\n type: '{ dueDate: string, gestationalStart: string, gestationalAge: { weeks: number, days: number, totalDays: number } | null, trimester: string } | null',\n descriptionKey: 'ui.agent.pregnancyDating.state.result',\n description:\n 'Computed estimated delivery date, the GA day-0 anchor after any re-dating or adjustment, the gestational age in completed weeks + days as of the evaluation date, and the trimester band (preconception / first / second / third / postterm). Null until a reference date is set.',\n read: (handle) => handle.getResult(),\n },\n },\n actions: {\n set_method: {\n // Drives the same local input state a user picks; nothing is persisted\n // to a record, and the choice is reversible in the same UI.\n safety: 'write',\n argsType: \"{ method: 'lmp' | 'conception' | 'ivf' | 'edd' }\",\n argsSchema: {\n type: 'object',\n properties: {\n method: {\n enum: ['lmp', 'conception', 'ivf', 'edd'],\n description:\n 'Which anchor to date from — last menstrual period, conception, IVF transfer, or a known estimated delivery date.',\n },\n },\n required: ['method'],\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the method was applied.',\n },\n errors: [\n 'Returns false for a method outside the four supported anchors.',\n ],\n examples: [\n { args: { method: 'edd' }, note: 'Date backwards from a known EDD.' },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setMethod',\n description:\n 'Choose which anchor the pregnancy is dated from. The reference date is kept and re-interpreted under the new method, so set the method first — only a known EDD may be in the future.',\n invoke: (\n handle,\n args: { method: 'lmp' | 'conception' | 'ivf' | 'edd' },\n ) => handle.setMethod(args.method),\n },\n set_reference_date: {\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 'The date the active method anchors on — LMP, conception, transfer, or known EDD — or null to clear it. Only a known EDD may 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 for a future date under any method but `edd` — the on-screen DatePicker caps those at today.',\n ],\n examples: [\n {\n args: { date: '2026-01-12' },\n note: 'Under the default LMP method, a last period starting 12 January.',\n },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setReferenceDate',\n description:\n 'Set the reference date for the active method. This is the only required input — the result stays null without it.',\n invoke: (handle, args: { date: string | null }) =>\n handle.setReferenceDate(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 'Applies but changes nothing unless the method is `lmp`, and is ignored once a CRL re-dating is confirmed.',\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setCycleLength',\n description:\n 'LMP method only — set the average cycle length, which shifts Naegele dating off the 28-day assumption.',\n invoke: (handle, args: { days: number | null }) =>\n handle.setCycleLength(args.days),\n },\n set_embryo_age: {\n safety: 'write',\n argsType: '{ days: 3 | 5 }',\n argsSchema: {\n type: 'object',\n properties: {\n days: {\n enum: [3, 5],\n description:\n 'Embryo age at transfer in days — 3 (cleavage) or 5 (blastocyst).',\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 for any value other than 3 or 5.',\n 'Applies but changes nothing unless the method is `ivf`.',\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setEmbryoAge',\n description:\n 'IVF method only — set the embryo age at transfer, which offsets the transfer date back to a notional LMP.',\n invoke: (handle, args: { days: 3 | 5 }) => handle.setEmbryoAge(args.days),\n },\n set_crl: {\n safety: 'write',\n argsType: '{ crlMm?: number | null, scanDate?: string | null }',\n argsSchema: {\n type: 'object',\n properties: {\n crlMm: {\n oneOf: [{ type: 'number', exclusiveMinimum: 0 }, { type: 'null' }],\n description:\n 'Crown-rump length in millimetres, or null to clear it.',\n },\n scanDate: {\n oneOf: [{ ...isoDate }, { type: 'null' }],\n description:\n 'Date of the CRL scan (`yyyy-MM-dd`, not in the future), or null to clear it.',\n },\n },\n additionalProperties: false,\n },\n idempotent: true,\n returns: 'boolean',\n returnsSchema: {\n type: 'boolean',\n description: 'True when the measurement was applied.',\n },\n errors: [\n 'Returns false and writes nothing when the length is not positive or the scan date is unparseable or in the future — the payload applies all-or-nothing.',\n 'Re-dating only happens under the `lmp` method, and only when both the length and the scan date are set.',\n ],\n examples: [\n {\n args: { crlMm: 42, scanDate: '2026-02-20' },\n note: 'A first-trimester CRL that may re-date the pregnancy per ACOG CO 700.',\n },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setCrl',\n description:\n 'LMP method only — set the first-trimester crown-rump length and its scan date. A confirmed re-dating wins over both the cycle length and the manual adjustment.',\n invoke: (\n handle,\n args: { crlMm?: number | null; scanDate?: string | null },\n ) => handle.setCrl(args),\n },\n set_dating_adjustment: {\n safety: 'write',\n argsType: '{ days: number | null }',\n argsSchema: {\n type: 'object',\n properties: {\n days: {\n oneOf: [{ type: 'integer' }, { type: 'null' }],\n description:\n 'Whole days to nudge the dating by — positive moves the pregnancy further along — or null for no adjustment.',\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 for a non-integer number of days.',\n 'Applies but changes nothing while a CRL re-dating is confirmed — the measurement wins.',\n ],\n examples: [\n {\n args: { days: 3 },\n note: 'An uncertain LMP judged three days earlier than entered.',\n },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setDatingAdjustment',\n description:\n 'Nudge the dating by whole days for an uncertain anchor. Positive moves the pregnancy further along (earlier effective LMP, earlier due date).',\n invoke: (handle, args: { days: number | null }) =>\n handle.setDatingAdjustment(args.days),\n },\n set_as_of_date: {\n safety: 'write',\n argsType: '{ date: string }',\n argsSchema: {\n type: 'object',\n properties: {\n date: {\n ...isoDate,\n description:\n 'Date to evaluate gestational age and trimester against, `yyyy-MM-dd`. May be in the future to project forward.',\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: ['Returns false for an unparseable date.'],\n examples: [\n {\n args: { date: '2026-09-15' },\n note: 'Project gestational age forward to an upcoming appointment.',\n },\n ],\n descriptionKey: 'ui.agent.pregnancyDating.actions.setAsOfDate',\n description:\n 'Set the date gestational age, trimester and the antenatal schedule are evaluated against. Defaults to today; the estimated delivery date itself does not depend on it.',\n invoke: (handle, args: { date: string }) => handle.setAsOfDate(args.date),\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'pregnancy-dating',\n description: 'Marks the PregnancyDating 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 the handle-driven actions/state are unreachable.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* PregnancyDating — the unified obstetric dating widget. */\n/* */\n/* Supersedes DueDateCalculator + GestationalAgeCalculator: takes any */\n/* known anchor (LMP / conception / IVF transfer / known EDD) and shows */\n/* BOTH the estimated due date AND the current gestational age, */\n/* trimester and milestones. Two dating refinements: a precise CRL + */\n/* scan-date ACOG CO 700 re-dating (LMP), and a quick manual ±days */\n/* adjustment for an uncertain LMP/conception. `showSchedule` appends */\n/* the antenatal exam schedule with plurality / chorionicity / risk */\n/* inputs. All maths lives in `_shared/obstetrics` + `_shared/antenatal- */\n/* schedule` (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, subDays } from 'date-fns';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { pregnancyDatingAgent } from './pregnancy-dating.agent';\nimport { RadioGroup, Radio } from '../radio-group';\nimport { FormField } from '../form-field';\nimport { DatePicker } from '../date-picker';\nimport { NumberInput } from '../number-input';\nimport { Select } from '../select';\nimport { Switch } from '../switch';\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 EmbryoAge,\n type GestationalAge,\n type DueDateResult,\n type Plurality,\n type Chorionicity,\n computeDueDate,\n redateByCrl,\n gestationalMilestones,\n GESTATION_DAYS,\n CONCEPTION_OFFSET_DAYS,\n DEFAULT_CYCLE_LENGTH,\n TRIMESTER_BADGE_VARIANT,\n trimesterHighlightToken,\n} from '../_shared/obstetrics';\nimport {\n computeAntenatalSchedule,\n type AntenatalScheduleOptions,\n type GdmRisk,\n} from '../_shared/antenatal-schedule';\nimport {\n AntenatalScheduleTimeline,\n buildScheduleInsertFields,\n} from '../_shared/antenatal-schedule-timeline';\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/** Any known anchor the pregnancy can be dated from. */\nexport type DatingMethod = 'lmp' | 'conception' | 'ivf' | 'edd';\n\n/** i18n key for each method's reference-date field. */\nconst DATE_LABEL_KEY: Record<DatingMethod, string> = {\n lmp: 'pregnancyDating.lmpDate',\n conception: 'pregnancyDating.conceptionDate',\n ivf: 'pregnancyDating.transferDate',\n edd: 'pregnancyDating.eddDate',\n};\n\nexport interface PregnancyDatingResult {\n /** Estimated date of delivery. */\n dueDate: Date;\n /** GA day-0 anchor (effective LMP) after any re-dating / adjustment. */\n gestationalStart: Date;\n /** Gestational age as of the evaluation date; `null` before conception. */\n gestationalAge: GestationalAge | null;\n trimester: DueDateResult['trimester'];\n}\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;\n\n/** The dating inputs as entered. */\nexport interface PregnancyDatingInputsSnapshot {\n /** Which anchor the pregnancy is dated from. */\n method: DatingMethod;\n /** The method's reference date (`yyyy-MM-dd`), or null when unset. */\n referenceDate: string | null;\n /** LMP only — average cycle length in days, or null for the 28-day default. */\n cycleLength: number | null;\n /** IVF only — embryo age at transfer, in days. */\n embryoAge: EmbryoAge;\n /** LMP only — crown-rump length in millimetres, or null. */\n crlMm: number | null;\n /** LMP only — date of the CRL scan (`yyyy-MM-dd`), or null. */\n scanDate: string | null;\n /** Manual ±days nudge applied to the dating, or null. */\n datingAdjustment: number | null;\n /** The date gestational age and trimester are evaluated against. */\n asOfDate: string;\n}\n\n/** `PregnancyDatingResult` projected onto the agent boundary — ISO dates. */\nexport interface PregnancyDatingSnapshot {\n /** Estimated date of delivery, `yyyy-MM-dd`. */\n dueDate: string;\n /** GA day-0 anchor after any re-dating / adjustment, `yyyy-MM-dd`. */\n gestationalStart: string;\n /** Gestational age as of the evaluation date; null before conception. */\n gestationalAge: { weeks: number; days: number; totalDays: number } | null;\n /** Trimester band as of the evaluation date. */\n trimester: DueDateResult['trimester'];\n}\n\n/**\n * Curated imperative handle for agent / external automation. Reads the dating\n * inputs and the computed EDD + gestational age, and drives the inputs the way\n * a user would. Never exposes patient identity — only structural dates and\n * numbers. Consumed by `pregnancy-dating.agent.ts`; the public `ref` stays the\n * root DOM element.\n */\nexport interface PregnancyDatingHandle {\n /** The dating inputs as entered. */\n getInputs: () => PregnancyDatingInputsSnapshot;\n /** Computed due date, gestational age and trimester, or null until a reference date is set. */\n getResult: () => PregnancyDatingSnapshot | null;\n /** Switch the dating anchor. Keeps the reference date, which is re-interpreted. */\n setMethod: (method: DatingMethod) => boolean;\n /** Set the method's reference date (`yyyy-MM-dd`); only a known EDD may be in the future. */\n setReferenceDate: (isoDate: string | null) => boolean;\n /** LMP only — set the average cycle length in days (20–45). */\n setCycleLength: (days: number | null) => boolean;\n /** IVF only — set the embryo age at transfer (3 or 5 days). */\n setEmbryoAge: (days: EmbryoAge) => boolean;\n /** LMP only — set the CRL measurement and/or its scan date for ACOG re-dating. */\n setCrl: (next: {\n crlMm?: number | null;\n scanDate?: string | null;\n }) => boolean;\n /** Set the manual ±days dating nudge (positive = further along). */\n setDatingAdjustment: (days: number | null) => boolean;\n /** Set the date gestational age and trimester are evaluated against. */\n setAsOfDate: (isoDate: string) => boolean;\n}\n\nexport interface PregnancyDatingProps extends VariantProps<\n typeof rootVariants\n> {\n /** Initial dating method. Defaults to `'lmp'`. */\n defaultMethod?: DatingMethod;\n /** Pre-fill the reference date (e.g. a known LMP from the patient record). */\n defaultReferenceDate?: Date;\n /** Fires whenever a result can be computed (and `null` when it can't). */\n onResultChange?: (result: PregnancyDatingResult | null) => void;\n /** When provided, shows the result-action buttons that emit / copy the result. */\n onInsert?: (payload: InsertPayload) => void;\n /** Which verb the result button performs. Defaults to `'insert'`. */\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 /** Brand wordmark printed in the inserted/copied result-card footer. */\n insertBrand?: string | false;\n /** Append the antenatal exam schedule + reveal the plurality / risk inputs. */\n showSchedule?: boolean;\n /** `showSchedule` only — initial number of babies. Defaults to `'singleton'`. */\n defaultPlurality?: Plurality;\n /** `showSchedule` only — initial chorionicity for multiples. Defaults to `'unknown'`. */\n defaultChorionicity?: Chorionicity;\n /** `showSchedule` only — initial Rh-negative state (surfaces anti-D). */\n defaultRhNegative?: boolean;\n /** `showSchedule` only — initial gestational-diabetes risk tier (surfaces OGTT). */\n defaultGdmRisk?: GdmRisk;\n /**\n * Passthrough options for the appended schedule (national `schedule`,\n * `includeOnIndication`, `birthGuideline`). `today`, `plurality`,\n * `chorionicity`, `rhNegative` and `gdmRisk` come from the component's own\n * inputs. Ignored unless `showSchedule` is set.\n */\n scheduleOptions?: Omit<\n AntenatalScheduleOptions,\n 'today' | 'plurality' | 'chorionicity' | 'rhNegative' | 'gdmRisk'\n >;\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 PregnancyDating = forwardRef<HTMLDivElement, PregnancyDatingProps>(\n (\n {\n defaultMethod = 'lmp',\n defaultReferenceDate,\n onResultChange,\n onInsert,\n insertVariant = 'insert',\n onCopy,\n onError,\n insertBrand,\n showSchedule = false,\n defaultPlurality = 'singleton',\n defaultChorionicity = 'unknown',\n defaultRhNegative = false,\n defaultGdmRisk,\n scheduleOptions,\n id,\n width,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const [method, setMethod] = useState<DatingMethod>(defaultMethod);\n const [refDate, setRefDate] = useState<Date | undefined>(\n defaultReferenceDate,\n );\n const [cycleLength, setCycleLength] = useState<number | null>(\n DEFAULT_CYCLE_LENGTH,\n );\n const [embryoAge, setEmbryoAge] = useState<EmbryoAge>(5);\n // Precise re-dating (LMP method) and the quick ±days nudge.\n const [crlMm, setCrlMm] = useState<number | null>(null);\n const [scanDate, setScanDate] = useState<Date | undefined>(undefined);\n const [datingAdjustment, setDatingAdjustment] = useState<number | null>(\n null,\n );\n // Evaluation date (\"as of\") + multiple-pregnancy / risk inputs.\n const [asOfDate, setAsOfDate] = useState<Date>(() => new Date());\n const [plurality, setPlurality] = useState<Plurality>(defaultPlurality);\n const [chorionicity, setChorionicity] =\n useState<Chorionicity>(defaultChorionicity);\n const [rhNegative, setRhNegative] = useState<boolean>(defaultRhNegative);\n const [gdmRisk, setGdmRisk] = useState<GdmRisk | 'none'>(\n defaultGdmRisk ?? 'none',\n );\n\n // Real today caps the past-only date inputs (LMP, conception, transfer, scan).\n const today = useMemo(() => new Date(), []);\n\n // CRL re-dating (LMP method only) — the measurement-based path.\n const redating = useMemo(() => {\n if (method !== 'lmp' || !refDate || crlMm === null || !scanDate) {\n return null;\n }\n return redateByCrl({ lmp: refDate, scanDate, crlMm });\n }, [method, refDate, crlMm, scanDate]);\n\n const data = useMemo(() => {\n if (!refDate) return null;\n\n // Resolve the method's anchor to an effective LMP (GA day 0).\n let effectiveLmp: Date;\n let cycleForEdd = DEFAULT_CYCLE_LENGTH;\n if (method === 'lmp') {\n effectiveLmp = refDate;\n cycleForEdd = cycleLength ?? DEFAULT_CYCLE_LENGTH;\n } else if (method === 'conception') {\n effectiveLmp = subDays(refDate, CONCEPTION_OFFSET_DAYS);\n } else if (method === 'ivf') {\n effectiveLmp = subDays(refDate, embryoAge + CONCEPTION_OFFSET_DAYS);\n } else {\n effectiveLmp = subDays(refDate, GESTATION_DAYS);\n }\n\n // A confirmed CRL re-dating wins over everything (measurement-based); else\n // apply the quick ±days nudge (+ = pregnancy further along → earlier LMP).\n if (method === 'lmp' && redating?.redated) {\n effectiveLmp = redating.gestationalStart;\n cycleForEdd = DEFAULT_CYCLE_LENGTH;\n } else if (datingAdjustment) {\n effectiveLmp = subDays(effectiveLmp, datingAdjustment);\n }\n\n const r = computeDueDate(\n { method: 'lmp', date: effectiveLmp, cycleLength: cycleForEdd },\n asOfDate,\n );\n return {\n result: {\n dueDate: r.dueDate,\n gestationalStart: r.gestationalStart,\n gestationalAge: r.gestationalAge,\n trimester: r.trimester,\n } satisfies PregnancyDatingResult,\n milestones: gestationalMilestones(r.gestationalStart),\n };\n }, [\n method,\n refDate,\n cycleLength,\n embryoAge,\n redating,\n datingAdjustment,\n asOfDate,\n ]);\n\n const result = data?.result ?? null;\n\n const schedule = useMemo(() => {\n if (!showSchedule || !result) return null;\n return computeAntenatalSchedule(result.gestationalStart, {\n ...scheduleOptions,\n today: asOfDate,\n plurality,\n chorionicity,\n rhNegative,\n gdmRisk: gdmRisk === 'none' ? undefined : gdmRisk,\n });\n }, [\n showSchedule,\n result,\n asOfDate,\n scheduleOptions,\n plurality,\n chorionicity,\n rhNegative,\n gdmRisk,\n ]);\n\n const longDate = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'long' }),\n [i18n.language],\n );\n const medDate = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }),\n [i18n.language],\n );\n\n useEffect(() => {\n onResultChange?.(result);\n }, [result, onResultChange]);\n\n /* ── Agent handle ────────────────────────────────────────────────── */\n const liveRef = useRef({\n method,\n refDate,\n cycleLength,\n embryoAge,\n crlMm,\n scanDate,\n datingAdjustment,\n asOfDate,\n result,\n });\n liveRef.current = {\n method,\n refDate,\n cycleLength,\n embryoAge,\n crlMm,\n scanDate,\n datingAdjustment,\n asOfDate,\n result,\n };\n\n const agentHandle = useMemo<PregnancyDatingHandle>(\n () => ({\n getInputs: () => {\n const live = liveRef.current;\n return {\n method: live.method,\n referenceDate: live.refDate ? toIsoDate(live.refDate) : null,\n cycleLength: live.cycleLength,\n embryoAge: live.embryoAge,\n crlMm: live.crlMm,\n scanDate: live.scanDate ? toIsoDate(live.scanDate) : null,\n datingAdjustment: live.datingAdjustment,\n asOfDate: toIsoDate(live.asOfDate),\n };\n },\n getResult: () => {\n const r = liveRef.current.result;\n if (!r) return null;\n return {\n dueDate: toIsoDate(r.dueDate),\n gestationalStart: toIsoDate(r.gestationalStart),\n gestationalAge: r.gestationalAge ? { ...r.gestationalAge } : null,\n trimester: r.trimester,\n };\n },\n setMethod: (next) => {\n if (\n next !== 'lmp' &&\n next !== 'conception' &&\n next !== 'ivf' &&\n next !== 'edd'\n ) {\n return false;\n }\n setMethod(next);\n return true;\n },\n setReferenceDate: (isoDate) => {\n if (isoDate === null) {\n setRefDate(undefined);\n return true;\n }\n const parsed = fromIsoDate(isoDate);\n if (!parsed) return false;\n // The DatePicker caps every anchor but a known EDD at today.\n if (liveRef.current.method !== 'edd' && isAfter(parsed, new Date())) {\n return false;\n }\n setRefDate(parsed);\n return true;\n },\n setCycleLength: (days) => {\n if (\n days !== null &&\n !(\n Number.isFinite(days) &&\n days >= CYCLE_LENGTH_RANGE.min &&\n days <= CYCLE_LENGTH_RANGE.max\n )\n ) {\n return false;\n }\n setCycleLength(days);\n return true;\n },\n setEmbryoAge: (days) => {\n if (days !== 3 && days !== 5) return false;\n setEmbryoAge(days);\n return true;\n },\n setCrl: (next) => {\n const now = new Date();\n let parsedScan: Date | undefined;\n // Validate the whole payload before writing any of it, so a bad\n // value can't leave the form half-updated.\n if ('crlMm' in next) {\n const mm = next.crlMm;\n if (\n mm !== null &&\n mm !== undefined &&\n !(Number.isFinite(mm) && mm > 0)\n ) {\n return false;\n }\n }\n if ('scanDate' in next && next.scanDate != null) {\n const d = fromIsoDate(next.scanDate);\n if (!d || isAfter(d, now)) return false;\n parsedScan = d;\n }\n if ('crlMm' in next) setCrlMm(next.crlMm ?? null);\n if ('scanDate' in next) setScanDate(parsedScan);\n return true;\n },\n setDatingAdjustment: (days) => {\n if (days !== null && !Number.isInteger(days)) return false;\n setDatingAdjustment(days);\n return true;\n },\n setAsOfDate: (isoDate) => {\n const parsed = fromIsoDate(isoDate);\n if (!parsed) return false;\n setAsOfDate(parsed);\n return true;\n },\n }),\n [],\n );\n useAgentRegistration(pregnancyDatingAgent, agentHandle, id);\n\n const chorionicityOptions = useMemo(\n () =>\n (\n [\n 'unknown',\n 'dichorionic-diamniotic',\n 'monochorionic-diamniotic',\n 'monochorionic-monoamniotic',\n ] as const\n ).map((c) => ({\n value: c,\n label: t(`antenatalSchedule.chorionicity.${c}`),\n })),\n [t],\n );\n\n const gaText = (ga: GestationalAge | null): string =>\n ga\n ? t('pregnancyDating.result.gestation', {\n weeks: ga.weeks,\n days: ga.days,\n })\n : '—';\n\n return (\n <div\n ref={ref}\n data-component=\"pregnancy-dating\"\n data-component-id={id}\n className={rootVariants({ width, className })}\n >\n <RadioGroup\n label={t('pregnancyDating.method.label')}\n variant=\"horizontal\"\n value={method}\n onValueChange={(next) => setMethod(next as DatingMethod)}\n >\n <Radio label={t('pregnancyDating.method.lmp')} value=\"lmp\" />\n <Radio\n label={t('pregnancyDating.method.conception')}\n value=\"conception\"\n />\n <Radio label={t('pregnancyDating.method.ivf')} value=\"ivf\" />\n <Radio label={t('pregnancyDating.method.edd')} value=\"edd\" />\n </RadioGroup>\n\n <div className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-2\">\n <FormField label={t(DATE_LABEL_KEY[method])}>\n <DatePicker\n value={refDate}\n onChange={setRefDate}\n maxDate={method === 'edd' ? undefined : today}\n />\n </FormField>\n\n {method === 'lmp' && (\n <FormField\n label={t('pregnancyDating.cycleLength')}\n description={t('pregnancyDating.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 )}\n\n {method === 'ivf' && (\n <RadioGroup\n label={t('pregnancyDating.embryoAge')}\n variant=\"horizontal\"\n value={String(embryoAge)}\n onValueChange={(next) => setEmbryoAge(Number(next) as EmbryoAge)}\n >\n <Radio label={t('pregnancyDating.day3')} value=\"3\" />\n <Radio label={t('pregnancyDating.day5')} value=\"5\" />\n </RadioGroup>\n )}\n\n <FormField\n label={t('pregnancyDating.datingAdjustment')}\n description={t('pregnancyDating.datingAdjustmentHint')}\n >\n <NumberInput\n mode=\"integer\"\n value={datingAdjustment}\n onChange={setDatingAdjustment}\n />\n </FormField>\n\n <FormField\n label={t('pregnancyDating.asOfDate')}\n description={t('pregnancyDating.asOfDateHint')}\n >\n <DatePicker\n value={asOfDate}\n onChange={(d) => d && setAsOfDate(d)}\n />\n </FormField>\n </div>\n\n {method === 'lmp' ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-2\">\n <FormField\n label={t('pregnancyDating.crl')}\n description={t('pregnancyDating.crlHint')}\n >\n <NumberInput\n mode=\"decimal\"\n min={0}\n step={0.1}\n value={crlMm}\n onChange={setCrlMm}\n />\n </FormField>\n <FormField label={t('pregnancyDating.scanDate')}>\n <DatePicker\n value={scanDate}\n onChange={setScanDate}\n maxDate={today}\n />\n </FormField>\n </div>\n {redating ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Badge variant={redating.redated ? 'warning' : 'success'}>\n {redating.redated\n ? t('pregnancyDating.redated', {\n days: redating.discrepancyDays,\n })\n : t('pregnancyDating.datesAgree')}\n </Badge>\n {!redating.crlInRange ? (\n <span className=\"type-meta ds:text-muted-foreground\">\n {t('pregnancyDating.crlOutOfRange')}\n </span>\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null}\n\n {showSchedule ? (\n <>\n <RadioGroup\n label={t('antenatalSchedule.plurality.label')}\n variant=\"horizontal\"\n value={plurality}\n onValueChange={(next) => setPlurality(next as Plurality)}\n >\n <Radio\n label={t('antenatalSchedule.plurality.singleton')}\n value=\"singleton\"\n />\n <Radio\n label={t('antenatalSchedule.plurality.twin')}\n value=\"twin\"\n />\n <Radio\n label={t('antenatalSchedule.plurality.triplet')}\n value=\"triplet\"\n />\n </RadioGroup>\n\n {plurality !== 'singleton' ? (\n <FormField label={t('antenatalSchedule.chorionicity.label')}>\n <Select\n options={chorionicityOptions}\n value={chorionicity}\n onValueChange={(next) =>\n setChorionicity(next as Chorionicity)\n }\n />\n </FormField>\n ) : null}\n\n <Switch\n label={t('antenatalSchedule.rhNegative')}\n checked={rhNegative}\n onCheckedChange={setRhNegative}\n />\n\n <RadioGroup\n label={t('antenatalSchedule.gdmRisk.label')}\n variant=\"horizontal\"\n value={gdmRisk}\n onValueChange={(next) => setGdmRisk(next as GdmRisk | 'none')}\n >\n <Radio label={t('antenatalSchedule.gdmRisk.none')} value=\"none\" />\n <Radio\n label={t('antenatalSchedule.gdmRisk.medium')}\n value=\"medium\"\n />\n <Radio label={t('antenatalSchedule.gdmRisk.high')} value=\"high\" />\n </RadioGroup>\n </>\n ) : null}\n\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {result\n ? `${t('pregnancyDating.result.dueDateLabel')}: ${longDate.format(\n result.dueDate,\n )}. ${t('pregnancyDating.result.gestationLabel')}: ${gaText(\n result.gestationalAge,\n )}.`\n : ''}\n </p>\n\n {data && result ? (\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {/* EDD is the headline — full width so a long localized date\n never wraps; gestational age + trimester flow beneath it,\n packed to the start so they don't strand a gap at narrow /\n modal widths. */}\n <dl className=\"ds:flex ds:flex-wrap ds:items-start ds:gap-x-[var(--spacing-xl)] ds:gap-y-[var(--spacing-md)]\">\n <div className=\"ds:basis-full ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('pregnancyDating.result.dueDateLabel')}\n </dt>\n <dd className=\"type-metric ds:text-foreground\">\n {longDate.format(result.dueDate)}\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('pregnancyDating.result.gestationLabel')}\n </dt>\n <dd className=\"type-body ds:text-foreground\">\n {gaText(result.gestationalAge)}\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('pregnancyDating.result.trimesterLabel')}\n </dt>\n <dd>\n <Badge\n variant={TRIMESTER_BADGE_VARIANT[result.trimester]}\n size=\"lg\"\n >\n {t(`pregnancyDating.trimester.${result.trimester}`)}\n </Badge>\n </dd>\n </div>\n </dl>\n\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('pregnancyDating.milestonesLabel')}\n </span>\n <ul className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n {data.milestones.map((m) => {\n const reached = isAfter(asOfDate, m.date);\n return (\n <li\n key={m.key}\n className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-md)]\"\n >\n <span className=\"type-body ds:text-foreground\">\n {t(`pregnancyDating.milestone.${m.key}`)}\n </span>\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span className=\"type-body ds:text-muted-foreground\">\n {medDate.format(m.date)}\n </span>\n {reached ? (\n <Badge variant=\"success\">\n {t('pregnancyDating.reached')}\n </Badge>\n ) : null}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n </Card.Body>\n </Card>\n ) : (\n <p className=\"type-body ds:text-muted-foreground\">\n {t('pregnancyDating.empty')}\n </p>\n )}\n\n {schedule ? <AntenatalScheduleTimeline events={schedule} /> : null}\n\n {result && (insertVariant === 'copy' || onInsert) ? (\n <InsertButton\n onInsert={onInsert}\n variant={insertVariant}\n onCopy={onCopy}\n onError={onError}\n card={{\n title: t('insert.title.pregnancyDating'),\n icon: 'calendar-heart',\n highlight: longDate.format(result.dueDate),\n highlightToken: trimesterHighlightToken(result.trimester),\n brand: insertBrand,\n fields: [\n {\n icon: 'calendar',\n label: t('pregnancyDating.result.dueDateLabel'),\n value: longDate.format(result.dueDate),\n },\n {\n icon: 'clock',\n label: t('pregnancyDating.result.gestationLabel'),\n value: gaText(result.gestationalAge),\n },\n {\n icon: 'tag',\n label: t('pregnancyDating.result.trimesterLabel'),\n value: t(`pregnancyDating.trimester.${result.trimester}`),\n },\n ...(schedule\n ? buildScheduleInsertFields(schedule, t, (d) =>\n medDate.format(d),\n )\n : []),\n ],\n }}\n />\n ) : null}\n </div>\n );\n },\n);\n\nPregnancyDating.displayName = 'PregnancyDating';\n"],"names":["isoDate","pregnancyDatingAgent","handle","args","rootVariants","cva","DATE_LABEL_KEY","toIsoDate","d","format","fromIsoDate","iso","parseISO","CYCLE_LENGTH_RANGE","PregnancyDating","forwardRef","defaultMethod","defaultReferenceDate","onResultChange","onInsert","insertVariant","onCopy","onError","insertBrand","showSchedule","defaultPlurality","defaultChorionicity","defaultRhNegative","defaultGdmRisk","scheduleOptions","id","width","className","ref","i18n","useTranslation","method","setMethod","useState","refDate","setRefDate","cycleLength","setCycleLength","DEFAULT_CYCLE_LENGTH","embryoAge","setEmbryoAge","crlMm","setCrlMm","scanDate","setScanDate","datingAdjustment","setDatingAdjustment","asOfDate","setAsOfDate","plurality","setPlurality","chorionicity","setChorionicity","rhNegative","setRhNegative","gdmRisk","setGdmRisk","today","useMemo","redating","redateByCrl","data","effectiveLmp","cycleForEdd","subDays","CONCEPTION_OFFSET_DAYS","GESTATION_DAYS","r","computeDueDate","gestationalMilestones","result","schedule","computeAntenatalSchedule","longDate","medDate","useEffect","liveRef","useRef","agentHandle","live","next","parsed","isAfter","days","now","parsedScan","mm","useAgentRegistration","chorionicityOptions","c","gaText","ga","jsxs","RadioGroup","jsx","Radio","FormField","DatePicker","NumberInput","Badge","Fragment","Select","Switch","Card","TRIMESTER_BADGE_VARIANT","m","reached","AntenatalScheduleTimeline","InsertButton","trimesterHighlightToken","buildScheduleInsertFields"],"mappings":"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"}
|