@alfadocs/ui-kit-debug 0.49.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/_chunks/{antenatal-schedule-timeline-Dg0m0yFl.js → antenatal-schedule-timeline-CdiqkF05.js} +9 -8
  2. package/dist/_chunks/{antenatal-schedule-timeline-Dg0m0yFl.js.map → antenatal-schedule-timeline-CdiqkF05.js.map} +1 -1
  3. package/dist/_chunks/{due-date-calculator-tDqZXPWO.js → due-date-calculator-DykajWzh.js} +2 -2
  4. package/dist/_chunks/due-date-calculator-DykajWzh.js.map +1 -0
  5. package/dist/_chunks/{gestational-age-calculator-DbDfTJU2.js → gestational-age-calculator-Bc55hq6t.js} +2 -2
  6. package/dist/_chunks/gestational-age-calculator-Bc55hq6t.js.map +1 -0
  7. package/dist/_chunks/pregnancy-dating-48Gfvod1.js +421 -0
  8. package/dist/_chunks/pregnancy-dating-48Gfvod1.js.map +1 -0
  9. package/dist/agent-catalog.json +1 -1
  10. package/dist/components/due-date-calculator/due-date-calculator.d.ts +6 -0
  11. package/dist/components/due-date-calculator/due-date-calculator.d.ts.map +1 -1
  12. package/dist/components/due-date-calculator/index.js +2 -2
  13. package/dist/components/gestational-age-calculator/gestational-age-calculator.d.ts +7 -0
  14. package/dist/components/gestational-age-calculator/gestational-age-calculator.d.ts.map +1 -1
  15. package/dist/components/gestational-age-calculator/index.js +1 -1
  16. package/dist/components/index.d.ts +1 -0
  17. package/dist/components/index.d.ts.map +1 -1
  18. package/dist/components/pregnancy-dating/index.d.ts +3 -0
  19. package/dist/components/pregnancy-dating/index.d.ts.map +1 -0
  20. package/dist/components/pregnancy-dating/index.js +5 -0
  21. package/dist/components/pregnancy-dating/index.js.map +1 -0
  22. package/dist/components/pregnancy-dating/pregnancy-dating.d.ts +60 -0
  23. package/dist/components/pregnancy-dating/pregnancy-dating.d.ts.map +1 -0
  24. package/dist/i18n/locales/ar.d.ts +52 -0
  25. package/dist/i18n/locales/ar.d.ts.map +1 -1
  26. package/dist/i18n/locales/ar.js +52 -0
  27. package/dist/i18n/locales/ar.js.map +1 -1
  28. package/dist/i18n/locales/de.d.ts +52 -0
  29. package/dist/i18n/locales/de.d.ts.map +1 -1
  30. package/dist/i18n/locales/de.js +52 -0
  31. package/dist/i18n/locales/de.js.map +1 -1
  32. package/dist/i18n/locales/el.d.ts +52 -0
  33. package/dist/i18n/locales/el.d.ts.map +1 -1
  34. package/dist/i18n/locales/el.js +52 -0
  35. package/dist/i18n/locales/el.js.map +1 -1
  36. package/dist/i18n/locales/en.d.ts +52 -0
  37. package/dist/i18n/locales/en.d.ts.map +1 -1
  38. package/dist/i18n/locales/en.js +52 -0
  39. package/dist/i18n/locales/en.js.map +1 -1
  40. package/dist/i18n/locales/es.d.ts +52 -0
  41. package/dist/i18n/locales/es.d.ts.map +1 -1
  42. package/dist/i18n/locales/es.js +52 -0
  43. package/dist/i18n/locales/es.js.map +1 -1
  44. package/dist/i18n/locales/fr.d.ts +52 -0
  45. package/dist/i18n/locales/fr.d.ts.map +1 -1
  46. package/dist/i18n/locales/fr.js +52 -0
  47. package/dist/i18n/locales/fr.js.map +1 -1
  48. package/dist/i18n/locales/hi.d.ts +52 -0
  49. package/dist/i18n/locales/hi.d.ts.map +1 -1
  50. package/dist/i18n/locales/hi.js +52 -0
  51. package/dist/i18n/locales/hi.js.map +1 -1
  52. package/dist/i18n/locales/it.d.ts +52 -0
  53. package/dist/i18n/locales/it.d.ts.map +1 -1
  54. package/dist/i18n/locales/it.js +52 -0
  55. package/dist/i18n/locales/it.js.map +1 -1
  56. package/dist/i18n/locales/ja.d.ts +52 -0
  57. package/dist/i18n/locales/ja.d.ts.map +1 -1
  58. package/dist/i18n/locales/ja.js +52 -0
  59. package/dist/i18n/locales/ja.js.map +1 -1
  60. package/dist/i18n/locales/nl.d.ts +52 -0
  61. package/dist/i18n/locales/nl.d.ts.map +1 -1
  62. package/dist/i18n/locales/nl.js +52 -0
  63. package/dist/i18n/locales/nl.js.map +1 -1
  64. package/dist/i18n/locales/pl.d.ts +52 -0
  65. package/dist/i18n/locales/pl.d.ts.map +1 -1
  66. package/dist/i18n/locales/pl.js +52 -0
  67. package/dist/i18n/locales/pl.js.map +1 -1
  68. package/dist/i18n/locales/pt.d.ts +52 -0
  69. package/dist/i18n/locales/pt.d.ts.map +1 -1
  70. package/dist/i18n/locales/pt.js +52 -0
  71. package/dist/i18n/locales/pt.js.map +1 -1
  72. package/dist/i18n/locales/ro.d.ts +52 -0
  73. package/dist/i18n/locales/ro.d.ts.map +1 -1
  74. package/dist/i18n/locales/ro.js +52 -0
  75. package/dist/i18n/locales/ro.js.map +1 -1
  76. package/dist/i18n/locales/ru.d.ts +52 -0
  77. package/dist/i18n/locales/ru.d.ts.map +1 -1
  78. package/dist/i18n/locales/ru.js +52 -0
  79. package/dist/i18n/locales/ru.js.map +1 -1
  80. package/dist/i18n/locales/sq.d.ts +52 -0
  81. package/dist/i18n/locales/sq.d.ts.map +1 -1
  82. package/dist/i18n/locales/sq.js +52 -0
  83. package/dist/i18n/locales/sq.js.map +1 -1
  84. package/dist/i18n/locales/sv.d.ts +52 -0
  85. package/dist/i18n/locales/sv.d.ts.map +1 -1
  86. package/dist/i18n/locales/sv.js +52 -0
  87. package/dist/i18n/locales/sv.js.map +1 -1
  88. package/dist/i18n/locales/tr.d.ts +52 -0
  89. package/dist/i18n/locales/tr.d.ts.map +1 -1
  90. package/dist/i18n/locales/tr.js +52 -0
  91. package/dist/i18n/locales/tr.js.map +1 -1
  92. package/dist/i18n/locales/zh.d.ts +52 -0
  93. package/dist/i18n/locales/zh.d.ts.map +1 -1
  94. package/dist/i18n/locales/zh.js +52 -0
  95. package/dist/i18n/locales/zh.js.map +1 -1
  96. package/dist/index.js +632 -630
  97. package/dist/index.js.map +1 -1
  98. package/dist/locales/ar.json +52 -0
  99. package/dist/locales/de.json +52 -0
  100. package/dist/locales/el.json +52 -0
  101. package/dist/locales/en.json +52 -0
  102. package/dist/locales/es.json +52 -0
  103. package/dist/locales/fr.json +52 -0
  104. package/dist/locales/hi.json +52 -0
  105. package/dist/locales/it.json +52 -0
  106. package/dist/locales/ja.json +52 -0
  107. package/dist/locales/nl.json +52 -0
  108. package/dist/locales/pl.json +52 -0
  109. package/dist/locales/pt.json +52 -0
  110. package/dist/locales/ro.json +52 -0
  111. package/dist/locales/ru.json +52 -0
  112. package/dist/locales/sq.json +52 -0
  113. package/dist/locales/sv.json +52 -0
  114. package/dist/locales/tr.json +52 -0
  115. package/dist/locales/zh.json +52 -0
  116. package/package.json +5 -1
  117. package/dist/_chunks/due-date-calculator-tDqZXPWO.js.map +0 -1
  118. package/dist/_chunks/gestational-age-calculator-DbDfTJU2.js.map +0 -1
@@ -113,7 +113,7 @@ function ht(t) {
113
113
  crlInRange: t.crlMm >= L && t.crlMm <= B
114
114
  };
115
115
  }
116
- const n = (t, a = 0) => t * 7 + a, P = (t) => t === "uk" ? {
116
+ const n = (t, a = 0) => t * 7 + a, j = (t) => t === "uk" ? {
117
117
  key: "dating-nt",
118
118
  category: "screening",
119
119
  startDay: n(11, 2),
@@ -125,21 +125,21 @@ const n = (t, a = 0) => t * 7 + a, P = (t) => t === "uk" ? {
125
125
  startDay: n(11, 0),
126
126
  endDay: n(13, 6),
127
127
  source: "SIEOG-2021"
128
- }, W = {
128
+ }, P = {
129
129
  key: "nipt",
130
130
  category: "screening",
131
131
  startDay: n(10, 0),
132
132
  endDay: n(13, 6),
133
133
  condition: "on-indication",
134
134
  source: "ACOG-CO700"
135
- }, Y = {
135
+ }, W = {
136
136
  key: "cvs",
137
137
  category: "diagnostic",
138
138
  startDay: n(11, 0),
139
139
  endDay: n(13, 6),
140
140
  condition: "on-indication",
141
141
  source: "ISS"
142
- }, j = {
142
+ }, Y = {
143
143
  key: "amnio",
144
144
  category: "diagnostic",
145
145
  startDay: n(15, 0),
@@ -229,11 +229,11 @@ const n = (t, a = 0) => t * 7 + a, P = (t) => t === "uk" ? {
229
229
  };
230
230
  function tt(t) {
231
231
  return [
232
- P(t),
232
+ j(t),
233
+ P,
233
234
  W,
234
- Y,
235
235
  Z,
236
- j,
236
+ Y,
237
237
  K(t),
238
238
  q,
239
239
  V,
@@ -405,8 +405,9 @@ export {
405
405
  gt as g,
406
406
  Nt as h,
407
407
  ft as i,
408
+ S as j,
408
409
  F as p,
409
410
  ht as r,
410
411
  w as t
411
412
  };
412
- //# sourceMappingURL=antenatal-schedule-timeline-Dg0m0yFl.js.map
413
+ //# sourceMappingURL=antenatal-schedule-timeline-CdiqkF05.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"antenatal-schedule-timeline-Dg0m0yFl.js","sources":["../../src/components/_shared/obstetrics.ts","../../src/components/_shared/antenatal-schedule.ts","../../src/components/_shared/antenatal-schedule-timeline.tsx"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* Obstetric maths — pure, framework-free, unit-testable. */\n/* */\n/* Estimated-due-date dating, gestational age, trimester classification */\n/* and milestone projection, plus the trimester→presentation maps the */\n/* obstetric calculators share. All three dating methods are normalised */\n/* onto a single \"gestational start\" (the notional first day of the last */\n/* menstrual period, GA day 0) so gestational age and trimester are */\n/* computed identically regardless of how the pregnancy was dated. */\n/* */\n/* Home for cross-component obstetric logic: the due-date and */\n/* gestational-age calculators both consume this module, so it lives in */\n/* `_shared/` rather than inside a single component directory. */\n/* `due-date-calculator/gestation.ts` re-exports this file for */\n/* back-compatibility with the public package barrel. */\n/* ------------------------------------------------------------------ */\n\nimport { addDays, subDays, differenceInCalendarDays } from 'date-fns';\n\nexport type DueDateMethod = 'lmp' | 'conception' | 'ivf';\n\n/** Embryo age at transfer, in days (cleavage vs blastocyst). */\nexport type EmbryoAge = 3 | 5;\n\nexport type Trimester =\n | 'preconception'\n | 'first'\n | 'second'\n | 'third'\n | 'postterm';\n\n/** Number of fetuses. Drives surveillance schedule and planned-birth timing. */\nexport type Plurality = 'singleton' | 'twin' | 'triplet';\n\n/**\n * Placentation of a multiple pregnancy. `unknown` is the safe default — managed\n * as monochorionic (the higher-risk assumption) until proven otherwise, per\n * NICE QS46. Only meaningful when `plurality !== 'singleton'`.\n */\nexport type Chorionicity =\n | 'dichorionic-diamniotic'\n | 'monochorionic-diamniotic'\n | 'monochorionic-monoamniotic'\n | 'unknown';\n\n/** Naegele's rule: a term pregnancy is 280 days from the LMP. */\nexport const GESTATION_DAYS = 280;\n/** Ovulation/conception sits ~14 days after the LMP in a 28-day cycle. */\nexport const CONCEPTION_OFFSET_DAYS = 14;\n/** A term pregnancy is 266 days from conception. */\nexport const TERM_FROM_CONCEPTION_DAYS = 266;\n/** Standard menstrual-cycle length Naegele assumes. */\nexport const DEFAULT_CYCLE_LENGTH = 28;\n\nexport interface DueDateInput {\n method: DueDateMethod;\n /** The reference date for the chosen method (LMP / conception / transfer). */\n date: Date;\n /** LMP only — average cycle length in days. Defaults to 28. */\n cycleLength?: number;\n /** IVF only — embryo age at transfer in days. Defaults to 5 (blastocyst). */\n embryoAge?: EmbryoAge;\n}\n\nexport interface GestationalAge {\n weeks: number;\n days: number;\n totalDays: number;\n}\n\nexport interface DueDateResult {\n /** Estimated date of delivery. */\n dueDate: Date;\n /** GA day-0 anchor (notional LMP) the trimester maths counts from. */\n gestationalStart: Date;\n /** Gestational age as of `today`; `null` before conception. */\n gestationalAge: GestationalAge | null;\n trimester: Trimester;\n}\n\n/** Classify gestational age (in completed weeks) into a trimester. */\nexport function trimesterForWeeks(totalDays: number): Trimester {\n if (totalDays < 0) return 'preconception';\n const weeks = Math.floor(totalDays / 7);\n if (weeks < 14) return 'first';\n if (weeks < 28) return 'second';\n if (weeks < 42) return 'third';\n return 'postterm';\n}\n\n/**\n * Resolve the gestational start (notional LMP) and due date for a method.\n * `cycleLength` shifts a longer/shorter cycle's ovulation, moving the due\n * date while GA stays counted from the LMP — the standard convention.\n */\nexport function computeDueDate(\n input: DueDateInput,\n today: Date,\n): DueDateResult {\n const { method, date } = input;\n\n let gestationalStart: Date;\n let dueDate: Date;\n\n if (method === 'lmp') {\n const cycle = input.cycleLength ?? DEFAULT_CYCLE_LENGTH;\n gestationalStart = date;\n dueDate = addDays(date, GESTATION_DAYS + (cycle - DEFAULT_CYCLE_LENGTH));\n } else if (method === 'conception') {\n gestationalStart = subDays(date, CONCEPTION_OFFSET_DAYS);\n dueDate = addDays(date, TERM_FROM_CONCEPTION_DAYS);\n } else {\n // IVF: back out the conception (egg-retrieval) date from the transfer.\n const embryo = input.embryoAge ?? 5;\n const conceptionDate = subDays(date, embryo);\n gestationalStart = subDays(conceptionDate, CONCEPTION_OFFSET_DAYS);\n dueDate = addDays(conceptionDate, TERM_FROM_CONCEPTION_DAYS);\n }\n\n const totalDays = differenceInCalendarDays(today, gestationalStart);\n const gestationalAge: GestationalAge | null =\n totalDays < 0\n ? null\n : {\n weeks: Math.floor(totalDays / 7),\n days: totalDays % 7,\n totalDays,\n };\n\n return {\n dueDate,\n gestationalStart,\n gestationalAge,\n trimester: trimesterForWeeks(totalDays),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Milestones */\n/* ------------------------------------------------------------------ */\n\n/** Gestational weeks at which clinically notable milestones fall. */\nexport const MILESTONE_WEEKS = [12, 24, 28, 37, 40] as const;\n\nexport interface GestationalMilestone {\n /** Stable key (`w12`, `w24`, …) for i18n lookup. */\n key: string;\n /** Completed gestational weeks. */\n week: number;\n /** Calendar date the milestone is reached. */\n date: Date;\n}\n\n/**\n * Project the standard milestone dates from a gestational start (notional\n * LMP / GA day 0): end of first trimester (12w), viability (24w), third\n * trimester (28w), term (37w) and the 40-week due date.\n */\nexport function gestationalMilestones(\n gestationalStart: Date,\n): GestationalMilestone[] {\n return MILESTONE_WEEKS.map((week) => ({\n key: `w${week}`,\n week,\n date: addDays(gestationalStart, week * 7),\n }));\n}\n\n/* ------------------------------------------------------------------ */\n/* Trimester presentation */\n/* */\n/* Shared by DueDateCalculator and GestationalAgeCalculator so the */\n/* on-screen badge and the inserted result-card chip stay in lockstep. */\n/* These are plain string maps (no React/Badge import) — the same */\n/* pattern as `_shared/entity-card`'s state→badge maps. */\n/* ------------------------------------------------------------------ */\n\n/** Badge `variant` names used for trimesters (the Badge component's union). */\nexport type TrimesterBadgeVariant =\n | 'neutral'\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\n/** Trimester → on-screen Badge variant. */\nexport const TRIMESTER_BADGE_VARIANT: Record<Trimester, TrimesterBadgeVariant> =\n {\n preconception: 'neutral',\n first: 'info',\n second: 'success',\n third: 'warning',\n postterm: 'error',\n };\n\n/**\n * DS token NAME backing each trimester's result-card chip — the solid-fill\n * companion of `TRIMESTER_BADGE_VARIANT` (Badge `error` fills `--destructive`;\n * `neutral` fills `--muted`). Passed as the card's `highlightToken` so the\n * inserted PNG chip matches the on-screen trimester badge; `InsertButton`\n * resolves the name to a concrete colour at raster time.\n *\n * `third` resolves to `--warning-readable`, which the result card's colour\n * probe resolves in the live themed DOM: orange-600 in light, non-accessible\n * mode (where bare `--warning` yellow only reaches ~3.2:1 on the white card)\n * and `--warning` elsewhere, whose deepened ramp already clears contrast.\n * Resolving the token NAME at the card means the choice tracks the live theme\n * regardless of where the theme class lives.\n */\nexport const TRIMESTER_HIGHLIGHT_TOKEN: Record<Trimester, string> = {\n preconception: '--muted',\n first: '--info',\n second: '--success',\n third: '--warning-readable',\n postterm: '--destructive',\n};\n\n/** The DS token name for a trimester's result-card chip. */\nexport function trimesterHighlightToken(trimester: Trimester): string {\n return TRIMESTER_HIGHLIGHT_TOKEN[trimester];\n}\n\n/* ------------------------------------------------------------------ */\n/* Multiple pregnancy — planned-birth timing */\n/* */\n/* For multiples the \"due date\" is not a single 40-week point but a */\n/* recommended planned-birth window that depends on chorionicity. The */\n/* UK (NICE NG137) and US (ACOG PB231) bodies diverge by ~1 week for */\n/* diamniotic twins, so the guideline is selectable; Italian practice */\n/* aligns closer to the earlier NICE stance, so `nice` is the default. */\n/* ------------------------------------------------------------------ */\n\n/** Which body's planned-birth timing to use for multiples. */\nexport type BirthGuideline = 'nice' | 'acog';\n\n/** Planned-birth window as GA days (week*7 + day), inclusive, with source. */\nexport interface BirthWindow {\n startDay: number;\n endDay: number;\n source: string;\n}\n\nconst day = (week: number, d = 0): number => week * 7 + d;\n\n/**\n * Recommended planned-birth window for a multiple pregnancy, by chorionicity.\n * Singletons return `null` (use the 40-week EDD instead). `unknown`\n * chorionicity is managed as monochorionic-diamniotic — the higher-risk\n * default (NICE QS46).\n */\nexport function plannedBirthWindow(\n plurality: Plurality,\n chorionicity: Chorionicity = 'unknown',\n guideline: BirthGuideline = 'nice',\n): BirthWindow | null {\n if (plurality === 'singleton') return null;\n\n if (plurality === 'triplet') {\n // NICE/ACOG: offer planned birth for uncomplicated triplets at ~35 weeks.\n return { startDay: day(35, 0), endDay: day(35, 6), source: 'NICE-NG137' };\n }\n\n // Twins. `unknown` is managed as monochorionic-diamniotic.\n const effective: Chorionicity =\n chorionicity === 'unknown' ? 'monochorionic-diamniotic' : chorionicity;\n\n if (guideline === 'acog') {\n switch (effective) {\n case 'dichorionic-diamniotic':\n return {\n startDay: day(38, 0),\n endDay: day(38, 6),\n source: 'ACOG-PB231',\n };\n case 'monochorionic-diamniotic':\n return {\n startDay: day(36, 0),\n endDay: day(37, 6),\n source: 'ACOG-PB231',\n };\n case 'monochorionic-monoamniotic':\n return {\n startDay: day(32, 0),\n endDay: day(34, 0),\n source: 'ACOG-PB231',\n };\n }\n }\n\n // NICE NG137 (default).\n switch (effective) {\n case 'dichorionic-diamniotic':\n return { startDay: day(37, 0), endDay: day(37, 6), source: 'NICE-NG137' };\n case 'monochorionic-diamniotic':\n return { startDay: day(36, 0), endDay: day(36, 6), source: 'NICE-NG137' };\n case 'monochorionic-monoamniotic':\n return { startDay: day(32, 0), endDay: day(33, 6), source: 'NICE-NG137' };\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Ultrasound (CRL) redating — ACOG Committee Opinion 700 */\n/* */\n/* A first-trimester crown-rump length gives a gestational age via */\n/* Robinson–Fleming. When it disagrees with the LMP by more than the */\n/* ACOG CO 700 threshold (which widens with gestation), the ultrasound */\n/* estimate replaces the LMP dating. Below threshold, the LMP stands. */\n/* The returned `ecoDiffDays` mirrors the server-side `eco_diff_days` */\n/* offset so the kit and the editor-actions backend can be reconciled. */\n/* ------------------------------------------------------------------ */\n\n/** Robinson–Fleming dating is validated for CRL 45–84 mm. */\nexport const CRL_DATING_MIN_MM = 45;\nexport const CRL_DATING_MAX_MM = 84;\n\n/** Gestational age in days from a crown-rump length (mm), Robinson–Fleming. */\nexport function crlToGestationalAgeDays(crlMm: number): number {\n // GA(days) = 8.052·√(CRL·1.037) + 23.73\n return 8.052 * Math.sqrt(crlMm * 1.037) + 23.73;\n}\n\n/**\n * ACOG CO 700 redating threshold (in days) for a given GA-by-LMP: re-date the\n * EDD to the ultrasound estimate only when the discrepancy EXCEEDS this.\n */\nexport function redatingThresholdDays(gaByLmpDays: number): number {\n if (gaByLmpDays <= day(8, 6)) return 5; // ≤ 8+6\n if (gaByLmpDays <= day(15, 6)) return 7; // 9+0 – 15+6\n if (gaByLmpDays <= day(21, 6)) return 10; // 16+0 – 21+6\n if (gaByLmpDays <= day(27, 6)) return 14; // 22+0 – 27+6\n return 21; // ≥ 28+0 (with a growth-restriction caveat the UI should note)\n}\n\nexport interface CrlRedatingInput {\n /** Reported first day of the last menstrual period. */\n lmp: Date;\n /** Date the ultrasound CRL was measured. */\n scanDate: Date;\n /** Crown-rump length, mm. */\n crlMm: number;\n}\n\nexport interface CrlRedatingResult {\n /** Notional LMP (GA day 0) after the rule — the ultrasound's or the original. */\n gestationalStart: Date;\n /** Whether the ultrasound estimate replaced the LMP dating. */\n redated: boolean;\n /** |GA-by-LMP − GA-by-CRL| at the scan, in days. */\n discrepancyDays: number;\n /** The ACOG CO 700 threshold (days) that applied. */\n thresholdDays: number;\n /** CRL − LMP dating, in days (+ = fetus ahead of dates). Server `eco_diff_days`. */\n ecoDiffDays: number;\n /** Whether the CRL is within the 45–84 mm dating-validity window. */\n crlInRange: boolean;\n}\n\n/** Apply the ACOG CO 700 CRL-redating rule to an LMP. */\nexport function redateByCrl(input: CrlRedatingInput): CrlRedatingResult {\n const gaByLmpDays = differenceInCalendarDays(input.scanDate, input.lmp);\n const gaByCrlDays = Math.round(crlToGestationalAgeDays(input.crlMm));\n const discrepancyDays = Math.abs(gaByLmpDays - gaByCrlDays);\n const thresholdDays = redatingThresholdDays(gaByLmpDays);\n const redated = discrepancyDays > thresholdDays;\n return {\n gestationalStart: redated\n ? subDays(input.scanDate, gaByCrlDays)\n : input.lmp,\n redated,\n discrepancyDays,\n thresholdDays,\n ecoDiffDays: gaByCrlDays - gaByLmpDays,\n crlInRange:\n input.crlMm >= CRL_DATING_MIN_MM && input.crlMm <= CRL_DATING_MAX_MM,\n };\n}\n","/* ------------------------------------------------------------------ */\n/* Antenatal schedule — pure, framework-free, clinically cited. */\n/* */\n/* Given a gestational start (GA day 0 = notional LMP, from */\n/* `obstetrics.ts`), resolves the time-sensitive antenatal exams and */\n/* screenings to absolute date windows with a past / current / upcoming */\n/* status. The schedule is locale-configurable because guidelines */\n/* genuinely diverge (e.g. the anomaly scan is 19+0–21+6 in Italy but */\n/* 18+0–20+6 in the UK), and conditional items (anti-D, OGTT tier, */\n/* CVS/amnio) are opt-in so a patient is never shown every test. */\n/* */\n/* Every window carries a `source` citation key so the UI can show */\n/* provenance and a clinician can audit the data. Windows are NOT */\n/* ported from the original Metricare app — its constants carry a */\n/* documented 2-week-late dating shift (the first-trimester screening */\n/* rendered after its window had closed). These are the guideline */\n/* windows, anchored to the kit's correct `computeDueDate` maths. */\n/* */\n/* Sources (citation keys): */\n/* SIEOG-2021 — SIEOG ministerial ultrasound guidelines 2021 (IT) */\n/* ISS — ISS 'Gravidanza fisiologica' / LEA (IT) */\n/* SID-AMD — SID-AMD/ISS gestational-diabetes screening (IT) */\n/* ACOG-CO700 — ACOG Committee Opinion 700 (EDD methods) */\n/* NICE-NG201 — NICE NG201 routine antenatal care (UK) */\n/* NICE-NG137 — NICE NG137 twin & triplet pregnancy (UK) */\n/* ISUOG-2025 — ISUOG twin-pregnancy ultrasound guidelines 2025 */\n/* ------------------------------------------------------------------ */\n\nimport { addDays, differenceInCalendarDays } from 'date-fns';\nimport {\n plannedBirthWindow,\n type Plurality,\n type Chorionicity,\n type BirthGuideline,\n} from './obstetrics';\n\nexport type AntenatalCategory =\n | 'scan'\n | 'screening'\n | 'diagnostic'\n | 'lab'\n | 'prophylaxis'\n | 'milestone';\n\n/** Which national schedule to resolve. Italy is the default market. */\nexport type ScheduleLocale = 'it' | 'uk' | 'international';\n\n/** Status of a window relative to the reference date (keyed off its end). */\nexport type AntenatalStatus = 'past' | 'current' | 'upcoming';\n\n/** Gestational-diabetes risk tier (drives which OGTT window applies). */\nexport type GdmRisk = 'high' | 'medium';\n\n/** A clinical condition gating whether an event applies to a pregnancy. */\nexport type AntenatalCondition =\n | 'rh-negative'\n | 'gdm-high'\n | 'gdm-medium'\n | 'on-indication';\n\nexport interface AntenatalEvent {\n /** Stable key → i18n lookup `antenatalSchedule.event.<key>`. */\n key: string;\n category: AntenatalCategory;\n /** Window start as GA days from gestationalStart (week*7 + day). Inclusive. */\n startDay: number;\n /** Window end as GA days. Inclusive. Equals `startDay` for single dates. */\n endDay: number;\n /** Restrict to these pluralities (omit ⇒ applies to all). */\n plurality?: Plurality[];\n /** Restrict to these chorionicities (omit ⇒ any). */\n chorionicity?: Chorionicity[];\n /** Gate behind a clinical condition (omit ⇒ always applies). */\n condition?: AntenatalCondition;\n /** Citation key for provenance display. */\n source: string;\n /** Interpolation values for the event's i18n string (e.g. surveillance cadence). */\n meta?: Record<string, string | number>;\n}\n\nexport interface ResolvedAntenatalEvent extends AntenatalEvent {\n /** Absolute window start date. */\n start: Date;\n /** Absolute window end date (=== `start` for a single-date event). */\n end: Date;\n /** True when the event is a single calendar date, not a range. */\n single: boolean;\n /** Status relative to the reference date, keyed off the window end. */\n status: AntenatalStatus;\n /** Reference date is within `nearDays` before the window end. */\n near: boolean;\n}\n\nexport interface AntenatalScheduleOptions {\n /** Reference date for status. Defaults to the host's current date. */\n today?: Date;\n /** National schedule. Defaults to `'it'`. */\n schedule?: ScheduleLocale;\n /** Number of fetuses. Defaults to `'singleton'`. */\n plurality?: Plurality;\n /** Placentation, for multiples. Defaults to `'unknown'`. */\n chorionicity?: Chorionicity;\n /** Surface the anti-D prophylaxis event (Rh-negative, non-sensitised). */\n rhNegative?: boolean;\n /** Surface the matching OGTT window for the patient's GDM risk tier. */\n gdmRisk?: GdmRisk;\n /** Include `on-indication` diagnostics (CVS, amnio, NIPT). Default false. */\n includeOnIndication?: boolean;\n /** Planned-birth guideline for multiples. Defaults to `'nice'`. */\n birthGuideline?: BirthGuideline;\n /** Days before a window's end still counted as `current`. Default 14. */\n nearDays?: number;\n}\n\n/** Gestational-age days from a week + day pair (e.g. `ga(13, 6)` → 97). */\nconst ga = (week: number, day = 0): number => week * 7 + day;\n\n/* ------------------------------------------------------------------ */\n/* Schedule data — one table per locale. */\n/* Common events are defined once and reused; only the windows that */\n/* genuinely diverge between locales are overridden. */\n/* ------------------------------------------------------------------ */\n\n/**\n * First-trimester dating scan + nuchal translucency + combined/bi-test.\n * NT is only measurable at CRL 45–84 mm, which is the 11+0–13+6 window;\n * the combined-test bloods (PAPP-A, free β-hCG) share it. (UK opens it a\n * touch later, 11+2–14+1, anchored to NICE's CRL band.)\n */\nconst datingNt = (locale: ScheduleLocale): AntenatalEvent =>\n locale === 'uk'\n ? {\n key: 'dating-nt',\n category: 'screening',\n startDay: ga(11, 2),\n endDay: ga(14, 1),\n source: 'NICE-NG201',\n }\n : {\n key: 'dating-nt',\n category: 'screening',\n startDay: ga(11, 0),\n endDay: ga(13, 6),\n source: 'SIEOG-2021',\n };\n\n/** NIPT / cell-free DNA — earliest 10+0; co-timed with the combined test. */\nconst nipt: AntenatalEvent = {\n key: 'nipt',\n category: 'screening',\n startDay: ga(10, 0),\n endDay: ga(13, 6),\n condition: 'on-indication',\n source: 'ACOG-CO700',\n};\n\n/** Chorionic villus sampling — never before 10–11w (limb-reduction risk). */\nconst cvs: AntenatalEvent = {\n key: 'cvs',\n category: 'diagnostic',\n startDay: ga(11, 0),\n endDay: ga(13, 6),\n condition: 'on-indication',\n source: 'ISS',\n};\n\n/** Amniocentesis — from 15+0 (typically 15–18w). */\nconst amnio: AntenatalEvent = {\n key: 'amnio',\n category: 'diagnostic',\n startDay: ga(15, 0),\n endDay: ga(18, 0),\n condition: 'on-indication',\n source: 'ISS',\n};\n\n/** Second-trimester anomaly / morphology scan — the key locale divergence. */\nconst morphology = (locale: ScheduleLocale): AntenatalEvent => {\n if (locale === 'uk') {\n return {\n key: 'morphology',\n category: 'scan',\n startDay: ga(18, 0),\n endDay: ga(20, 6),\n source: 'NICE-NG201',\n };\n }\n if (locale === 'international') {\n return {\n key: 'morphology',\n category: 'scan',\n startDay: ga(18, 0),\n endDay: ga(22, 0),\n source: 'ACOG-CO700',\n };\n }\n return {\n key: 'morphology',\n category: 'scan',\n startDay: ga(19, 0),\n endDay: ga(21, 6),\n source: 'SIEOG-2021',\n };\n};\n\n/**\n * Third-trimester growth scan — `on-indication` everywhere: not routine in\n * the Italian low-risk pathway (ISS uses symphysis-fundal height from 24w);\n * NICE/ACOG also reserve late scans for indications in low-risk pregnancies.\n */\nconst growth: AntenatalEvent = {\n key: 'growth',\n category: 'scan',\n startDay: ga(30, 0),\n endDay: ga(33, 6),\n condition: 'on-indication',\n source: 'SIEOG-2021',\n};\n\n/** OGTT 75 g, high-risk tier (BMI ≥ 30 / prior GDM / fasting 100–125). */\nconst ogttHigh: AntenatalEvent = {\n key: 'ogtt-high',\n category: 'lab',\n startDay: ga(16, 0),\n endDay: ga(18, 6),\n condition: 'gdm-high',\n source: 'SID-AMD',\n};\n\n/** OGTT 75 g, medium-risk tier (≥ 1 of: family hx, BMI ≥ 25, age ≥ 35 …). */\nconst ogttMedium: AntenatalEvent = {\n key: 'ogtt-medium',\n category: 'lab',\n startDay: ga(24, 0),\n endDay: ga(28, 6),\n condition: 'gdm-medium',\n source: 'SID-AMD',\n};\n\n/** Group-B streptococcus vagino-rectal swab. */\nconst gbs = (locale: ScheduleLocale): AntenatalEvent =>\n locale === 'it'\n ? {\n key: 'gbs',\n category: 'lab',\n startDay: ga(36, 0),\n endDay: ga(37, 6),\n source: 'ISS',\n }\n : {\n // CDC / legacy international protocols open a week earlier.\n key: 'gbs',\n category: 'lab',\n startDay: ga(35, 0),\n endDay: ga(37, 6),\n source: 'NICE-NG201',\n };\n\n/** Routine antenatal anti-D prophylaxis for non-sensitised Rh(D)-neg women. */\nconst antiD: AntenatalEvent = {\n key: 'anti-d',\n category: 'prophylaxis',\n startDay: ga(28, 0),\n endDay: ga(28, 0),\n condition: 'rh-negative',\n source: 'ISS',\n};\n\n/**\n * Term threshold (37+0) — singletons only. Multiples are delivered earlier\n * (see `plannedBirthWindow`), so a 37-week \"term\" milestone would fall after\n * their recommended birth window and read as clinically contradictory.\n */\nconst term: AntenatalEvent = {\n key: 'term',\n category: 'milestone',\n startDay: ga(37, 0),\n endDay: ga(37, 0),\n plurality: ['singleton'],\n source: 'ACOG-CO700',\n};\n\n/** Estimated due date (40+0) — singleton only; twins use a birth window. */\nconst edd: AntenatalEvent = {\n key: 'edd',\n category: 'milestone',\n startDay: ga(40, 0),\n endDay: ga(40, 0),\n plurality: ['singleton'],\n source: 'ACOG-CO700',\n};\n\n/**\n * Chorionicity + amnionicity determination — twins/triplets only, at the\n * first-trimester scan (before 13+6 / CRL 45–84 mm). If presentation is\n * later, determine at the earliest opportunity.\n */\nconst chorionicityDetermination: AntenatalEvent = {\n key: 'chorionicity',\n category: 'scan',\n startDay: ga(11, 2),\n endDay: ga(14, 1),\n plurality: ['twin', 'triplet'],\n source: 'ISUOG-2025',\n};\n\n/** Build the ordered base event list for a locale (pre-filtering). */\nfunction baseEvents(locale: ScheduleLocale): AntenatalEvent[] {\n return [\n datingNt(locale),\n nipt,\n cvs,\n chorionicityDetermination,\n amnio,\n morphology(locale),\n ogttHigh,\n growth,\n ogttMedium,\n term,\n gbs(locale),\n antiD,\n edd,\n ];\n}\n\n/**\n * Extra events for a multiple pregnancy: increased ultrasound surveillance\n * (cadence by chorionicity) and the planned-birth window (which replaces the\n * singleton EDD). Monochorionic twins are scanned every 2 weeks from 16w to\n * catch TTTS; dichorionic every 4 weeks from 20w. `unknown` chorionicity is\n * managed as monochorionic (the higher-risk default).\n */\nfunction multipleEvents(\n plurality: Plurality,\n chorionicity: Chorionicity,\n guideline: BirthGuideline,\n): AntenatalEvent[] {\n if (plurality === 'singleton') return [];\n\n const isDichorionic = chorionicity === 'dichorionic-diamniotic';\n const everyWeeks = isDichorionic ? 4 : 2;\n const fromWeek = isDichorionic ? 20 : 16;\n const birth = plannedBirthWindow(plurality, chorionicity, guideline);\n\n const events: AntenatalEvent[] = [\n {\n key: 'surveillance',\n category: 'scan',\n startDay: ga(fromWeek, 0),\n // Runs until the planned-birth window opens (fallback 36w if none).\n endDay: birth ? birth.startDay : ga(36, 0),\n source: isDichorionic ? 'NICE-NG137' : 'ISUOG-2025',\n meta: { everyWeeks, fromWeek },\n },\n ];\n\n if (birth) {\n events.push({\n key: 'birth',\n category: 'milestone',\n startDay: birth.startDay,\n endDay: birth.endDay,\n source: birth.source,\n });\n }\n\n return events;\n}\n\n/* ------------------------------------------------------------------ */\n/* Resolution */\n/* ------------------------------------------------------------------ */\n\n/** Does an event apply, given the pregnancy's plurality/chorionicity/conds? */\nfunction eventApplies(\n event: AntenatalEvent,\n opts: Required<\n Pick<AntenatalScheduleOptions, 'plurality' | 'chorionicity'>\n > & {\n rhNegative: boolean;\n gdmRisk?: GdmRisk;\n includeOnIndication: boolean;\n },\n): boolean {\n if (event.plurality && !event.plurality.includes(opts.plurality)) {\n return false;\n }\n if (event.chorionicity && !event.chorionicity.includes(opts.chorionicity)) {\n return false;\n }\n switch (event.condition) {\n case 'rh-negative':\n return opts.rhNegative;\n case 'gdm-high':\n return opts.gdmRisk === 'high';\n case 'gdm-medium':\n return opts.gdmRisk === 'medium';\n case 'on-indication':\n return opts.includeOnIndication;\n default:\n return true;\n }\n}\n\nfunction statusFor(\n start: Date,\n end: Date,\n today: Date,\n nearDays: number,\n): { status: AntenatalStatus; near: boolean } {\n const daysUntilStart = differenceInCalendarDays(start, today);\n const daysUntilEnd = differenceInCalendarDays(end, today);\n // Window already closed.\n if (daysUntilEnd < 0) return { status: 'past', near: false };\n // Open now (start ≤ today ≤ end) → current, and always worth flagging.\n if (daysUntilStart <= 0) return { status: 'current', near: true };\n // Not yet open → upcoming; \"near\" if it opens within nearDays.\n return { status: 'upcoming', near: daysUntilStart <= nearDays };\n}\n\n/**\n * Resolve the antenatal schedule for a pregnancy to dated, status-tagged\n * windows, ordered by start date (then end date). Pure: the only clock is\n * `opts.today` (defaults to a fresh `Date`).\n */\nexport function computeAntenatalSchedule(\n gestationalStart: Date,\n opts: AntenatalScheduleOptions = {},\n): ResolvedAntenatalEvent[] {\n const {\n today = new Date(),\n schedule = 'it',\n plurality = 'singleton',\n chorionicity = 'unknown',\n rhNegative = false,\n gdmRisk,\n includeOnIndication = false,\n birthGuideline = 'nice',\n nearDays = 14,\n } = opts;\n\n return [\n ...baseEvents(schedule),\n ...multipleEvents(plurality, chorionicity, birthGuideline),\n ]\n .filter((event) =>\n eventApplies(event, {\n plurality,\n chorionicity,\n rhNegative,\n gdmRisk,\n includeOnIndication,\n }),\n )\n .map((event): ResolvedAntenatalEvent => {\n const start = addDays(gestationalStart, event.startDay);\n const end = addDays(gestationalStart, event.endDay);\n const { status, near } = statusFor(start, end, today, nearDays);\n return {\n ...event,\n start,\n end,\n single: event.startDay === event.endDay,\n status,\n near,\n };\n })\n .sort((a, b) => {\n const byStart = a.startDay - b.startDay;\n return byStart !== 0 ? byStart : a.endDay - b.endDay;\n });\n}\n","/* ------------------------------------------------------------------ */\n/* AntenatalScheduleTimeline — the presentational list of resolved */\n/* antenatal windows, shared by the `showSchedule` appendix on */\n/* GestationalAgeCalculator and DueDateCalculator. Pure display: it takes */\n/* already-resolved events and renders the Card + the sr-only now-due */\n/* summary. No inputs, no state, no maths. */\n/* ------------------------------------------------------------------ */\n\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Card } from '../card';\nimport { Badge } from '../badge';\nimport type { IconKey, InsertCardField } from './insert-result';\nimport type {\n ResolvedAntenatalEvent,\n AntenatalStatus,\n AntenatalCategory,\n} from './antenatal-schedule';\n\n/** Status → on-screen Badge variant. `near` upcoming items borrow `warning`. */\nfunction statusBadgeVariant(\n status: AntenatalStatus,\n near: boolean,\n): 'neutral' | 'info' | 'warning' {\n if (status === 'past') return 'neutral';\n if (status === 'current') return 'warning';\n return near ? 'warning' : 'info';\n}\n\n/** Compact gestational-age label for a day offset, e.g. 97 → \"13+6\". */\nfunction gaLabel(days: number): string {\n return `${Math.floor(days / 7)}+${days % 7}`;\n}\n\n/** Each schedule category maps to one of the inserted-card glyph keys. */\nconst CATEGORY_ICON: Record<AntenatalCategory, IconKey> = {\n scan: 'activity',\n screening: 'activity',\n diagnostic: 'activity',\n lab: 'droplets',\n prophylaxis: 'heart',\n milestone: 'calendar',\n};\n\n/** Minimal translator shape this module needs (matches react-i18next's `t`). */\ntype Translate = (key: string, opts?: Record<string, unknown>) => string;\n\n/** Localised \"label · range\" for one event (e.g. for the sr-only summary). */\nfunction eventLabelFor(event: ResolvedAntenatalEvent, t: Translate): string {\n return t(`antenatalSchedule.event.${event.key}`, event.meta ?? {});\n}\n\n/**\n * Build the inserted-card rows for a resolved schedule, so a host calculator's\n * single Insert button can carry the schedule in its payload (rather than a\n * second Insert button on the schedule card). One row per event: a\n * category-tinted glyph, the localised label, and the date range.\n */\nexport function buildScheduleInsertFields(\n events: ResolvedAntenatalEvent[],\n t: Translate,\n formatDate: (date: Date) => string,\n): InsertCardField[] {\n return events.map((event) => ({\n icon: CATEGORY_ICON[event.category],\n label: eventLabelFor(event, t),\n value: event.single\n ? formatDate(event.start)\n : `${formatDate(event.start)} – ${formatDate(event.end)}`,\n }));\n}\n\nexport interface AntenatalScheduleTimelineProps {\n /** Resolved schedule events (from `computeAntenatalSchedule`). */\n events: ResolvedAntenatalEvent[];\n}\n\nexport function AntenatalScheduleTimeline({\n events,\n}: AntenatalScheduleTimelineProps) {\n const { t, i18n } = useTranslation();\n\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }),\n [i18n.language],\n );\n\n const eventLabel = (event: ResolvedAntenatalEvent): string =>\n eventLabelFor(event, t);\n\n const formatRange = (event: ResolvedAntenatalEvent): string =>\n event.single\n ? dateFormatter.format(event.start)\n : `${dateFormatter.format(event.start)} – ${dateFormatter.format(\n event.end,\n )}`;\n\n // No own live region: this timeline is always embedded in a host calculator\n // that already owns a `role=\"status\"` result announcement, so a second one\n // here would double-announce. The schedule is fully present in the DOM\n // (labelled list + per-row status Badge) for assistive tech to browse.\n return (\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('antenatalSchedule.scheduleLabel')}\n </span>\n <ul className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {events.map((event) => (\n <li\n key={event.key}\n data-status={event.status}\n className=\"ds:flex ds:flex-wrap ds:items-start ds:justify-between ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-xs)] ds:border-b ds:border-border ds:pb-[var(--spacing-sm)] ds:last:border-b-0 ds:last:pb-0\"\n >\n <span className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-body ds:text-foreground\">\n {eventLabel(event)}\n </span>\n <span className=\"type-meta ds:text-muted-foreground\">\n {t(`antenatalSchedule.category.${event.category}`)} ·{' '}\n {gaLabel(event.startDay)}\n {event.single ? '' : ` – ${gaLabel(event.endDay)}`} ·{' '}\n {t(`antenatalSchedule.source.${event.source}`)}\n {event.condition === 'on-indication'\n ? ` · ${t('antenatalSchedule.onIndication')}`\n : ''}\n </span>\n </span>\n <span className=\"ds:flex ds:flex-col ds:items-end ds:gap-[var(--spacing-2xs)] ds:text-end\">\n <span className=\"type-body ds:text-foreground\">\n {formatRange(event)}\n </span>\n <Badge variant={statusBadgeVariant(event.status, event.near)}>\n {event.status === 'upcoming' && event.near\n ? t('antenatalSchedule.near')\n : t(`antenatalSchedule.status.${event.status}`)}\n </Badge>\n </span>\n </li>\n ))}\n </ul>\n <p className=\"type-meta ds:text-muted-foreground\">\n {t('antenatalSchedule.disclaimer')}\n </p>\n </Card.Body>\n </Card>\n );\n}\n"],"names":["GESTATION_DAYS","CONCEPTION_OFFSET_DAYS","TERM_FROM_CONCEPTION_DAYS","DEFAULT_CYCLE_LENGTH","trimesterForWeeks","totalDays","weeks","computeDueDate","input","today","method","date","gestationalStart","dueDate","cycle","addDays","subDays","embryo","conceptionDate","differenceInCalendarDays","gestationalAge","MILESTONE_WEEKS","gestationalMilestones","week","TRIMESTER_BADGE_VARIANT","TRIMESTER_HIGHLIGHT_TOKEN","trimesterHighlightToken","trimester","day","d","plannedBirthWindow","plurality","chorionicity","guideline","effective","CRL_DATING_MIN_MM","CRL_DATING_MAX_MM","crlToGestationalAgeDays","crlMm","redatingThresholdDays","gaByLmpDays","redateByCrl","gaByCrlDays","discrepancyDays","thresholdDays","redated","ga","datingNt","locale","nipt","cvs","amnio","morphology","growth","ogttHigh","ogttMedium","gbs","antiD","term","edd","chorionicityDetermination","baseEvents","multipleEvents","isDichorionic","everyWeeks","fromWeek","birth","events","eventApplies","event","opts","statusFor","start","end","nearDays","daysUntilStart","computeAntenatalSchedule","schedule","rhNegative","gdmRisk","includeOnIndication","birthGuideline","status","near","a","b","byStart","statusBadgeVariant","gaLabel","days","CATEGORY_ICON","eventLabelFor","t","buildScheduleInsertFields","formatDate","AntenatalScheduleTimeline","i18n","useTranslation","dateFormatter","useMemo","eventLabel","formatRange","jsx","Card","jsxs","Badge"],"mappings":"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"}
1
+ {"version":3,"file":"antenatal-schedule-timeline-CdiqkF05.js","sources":["../../src/components/_shared/obstetrics.ts","../../src/components/_shared/antenatal-schedule.ts","../../src/components/_shared/antenatal-schedule-timeline.tsx"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* Obstetric maths — pure, framework-free, unit-testable. */\n/* */\n/* Estimated-due-date dating, gestational age, trimester classification */\n/* and milestone projection, plus the trimester→presentation maps the */\n/* obstetric calculators share. All three dating methods are normalised */\n/* onto a single \"gestational start\" (the notional first day of the last */\n/* menstrual period, GA day 0) so gestational age and trimester are */\n/* computed identically regardless of how the pregnancy was dated. */\n/* */\n/* Home for cross-component obstetric logic: the due-date and */\n/* gestational-age calculators both consume this module, so it lives in */\n/* `_shared/` rather than inside a single component directory. */\n/* `due-date-calculator/gestation.ts` re-exports this file for */\n/* back-compatibility with the public package barrel. */\n/* ------------------------------------------------------------------ */\n\nimport { addDays, subDays, differenceInCalendarDays } from 'date-fns';\n\nexport type DueDateMethod = 'lmp' | 'conception' | 'ivf';\n\n/** Embryo age at transfer, in days (cleavage vs blastocyst). */\nexport type EmbryoAge = 3 | 5;\n\nexport type Trimester =\n | 'preconception'\n | 'first'\n | 'second'\n | 'third'\n | 'postterm';\n\n/** Number of fetuses. Drives surveillance schedule and planned-birth timing. */\nexport type Plurality = 'singleton' | 'twin' | 'triplet';\n\n/**\n * Placentation of a multiple pregnancy. `unknown` is the safe default — managed\n * as monochorionic (the higher-risk assumption) until proven otherwise, per\n * NICE QS46. Only meaningful when `plurality !== 'singleton'`.\n */\nexport type Chorionicity =\n | 'dichorionic-diamniotic'\n | 'monochorionic-diamniotic'\n | 'monochorionic-monoamniotic'\n | 'unknown';\n\n/** Naegele's rule: a term pregnancy is 280 days from the LMP. */\nexport const GESTATION_DAYS = 280;\n/** Ovulation/conception sits ~14 days after the LMP in a 28-day cycle. */\nexport const CONCEPTION_OFFSET_DAYS = 14;\n/** A term pregnancy is 266 days from conception. */\nexport const TERM_FROM_CONCEPTION_DAYS = 266;\n/** Standard menstrual-cycle length Naegele assumes. */\nexport const DEFAULT_CYCLE_LENGTH = 28;\n\nexport interface DueDateInput {\n method: DueDateMethod;\n /** The reference date for the chosen method (LMP / conception / transfer). */\n date: Date;\n /** LMP only — average cycle length in days. Defaults to 28. */\n cycleLength?: number;\n /** IVF only — embryo age at transfer in days. Defaults to 5 (blastocyst). */\n embryoAge?: EmbryoAge;\n}\n\nexport interface GestationalAge {\n weeks: number;\n days: number;\n totalDays: number;\n}\n\nexport interface DueDateResult {\n /** Estimated date of delivery. */\n dueDate: Date;\n /** GA day-0 anchor (notional LMP) the trimester maths counts from. */\n gestationalStart: Date;\n /** Gestational age as of `today`; `null` before conception. */\n gestationalAge: GestationalAge | null;\n trimester: Trimester;\n}\n\n/** Classify gestational age (in completed weeks) into a trimester. */\nexport function trimesterForWeeks(totalDays: number): Trimester {\n if (totalDays < 0) return 'preconception';\n const weeks = Math.floor(totalDays / 7);\n if (weeks < 14) return 'first';\n if (weeks < 28) return 'second';\n if (weeks < 42) return 'third';\n return 'postterm';\n}\n\n/**\n * Resolve the gestational start (notional LMP) and due date for a method.\n * `cycleLength` shifts a longer/shorter cycle's ovulation, moving the due\n * date while GA stays counted from the LMP — the standard convention.\n */\nexport function computeDueDate(\n input: DueDateInput,\n today: Date,\n): DueDateResult {\n const { method, date } = input;\n\n let gestationalStart: Date;\n let dueDate: Date;\n\n if (method === 'lmp') {\n const cycle = input.cycleLength ?? DEFAULT_CYCLE_LENGTH;\n gestationalStart = date;\n dueDate = addDays(date, GESTATION_DAYS + (cycle - DEFAULT_CYCLE_LENGTH));\n } else if (method === 'conception') {\n gestationalStart = subDays(date, CONCEPTION_OFFSET_DAYS);\n dueDate = addDays(date, TERM_FROM_CONCEPTION_DAYS);\n } else {\n // IVF: back out the conception (egg-retrieval) date from the transfer.\n const embryo = input.embryoAge ?? 5;\n const conceptionDate = subDays(date, embryo);\n gestationalStart = subDays(conceptionDate, CONCEPTION_OFFSET_DAYS);\n dueDate = addDays(conceptionDate, TERM_FROM_CONCEPTION_DAYS);\n }\n\n const totalDays = differenceInCalendarDays(today, gestationalStart);\n const gestationalAge: GestationalAge | null =\n totalDays < 0\n ? null\n : {\n weeks: Math.floor(totalDays / 7),\n days: totalDays % 7,\n totalDays,\n };\n\n return {\n dueDate,\n gestationalStart,\n gestationalAge,\n trimester: trimesterForWeeks(totalDays),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Milestones */\n/* ------------------------------------------------------------------ */\n\n/** Gestational weeks at which clinically notable milestones fall. */\nexport const MILESTONE_WEEKS = [12, 24, 28, 37, 40] as const;\n\nexport interface GestationalMilestone {\n /** Stable key (`w12`, `w24`, …) for i18n lookup. */\n key: string;\n /** Completed gestational weeks. */\n week: number;\n /** Calendar date the milestone is reached. */\n date: Date;\n}\n\n/**\n * Project the standard milestone dates from a gestational start (notional\n * LMP / GA day 0): end of first trimester (12w), viability (24w), third\n * trimester (28w), term (37w) and the 40-week due date.\n */\nexport function gestationalMilestones(\n gestationalStart: Date,\n): GestationalMilestone[] {\n return MILESTONE_WEEKS.map((week) => ({\n key: `w${week}`,\n week,\n date: addDays(gestationalStart, week * 7),\n }));\n}\n\n/* ------------------------------------------------------------------ */\n/* Trimester presentation */\n/* */\n/* Shared by DueDateCalculator and GestationalAgeCalculator so the */\n/* on-screen badge and the inserted result-card chip stay in lockstep. */\n/* These are plain string maps (no React/Badge import) — the same */\n/* pattern as `_shared/entity-card`'s state→badge maps. */\n/* ------------------------------------------------------------------ */\n\n/** Badge `variant` names used for trimesters (the Badge component's union). */\nexport type TrimesterBadgeVariant =\n | 'neutral'\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\n/** Trimester → on-screen Badge variant. */\nexport const TRIMESTER_BADGE_VARIANT: Record<Trimester, TrimesterBadgeVariant> =\n {\n preconception: 'neutral',\n first: 'info',\n second: 'success',\n third: 'warning',\n postterm: 'error',\n };\n\n/**\n * DS token NAME backing each trimester's result-card chip — the solid-fill\n * companion of `TRIMESTER_BADGE_VARIANT` (Badge `error` fills `--destructive`;\n * `neutral` fills `--muted`). Passed as the card's `highlightToken` so the\n * inserted PNG chip matches the on-screen trimester badge; `InsertButton`\n * resolves the name to a concrete colour at raster time.\n *\n * `third` resolves to `--warning-readable`, which the result card's colour\n * probe resolves in the live themed DOM: orange-600 in light, non-accessible\n * mode (where bare `--warning` yellow only reaches ~3.2:1 on the white card)\n * and `--warning` elsewhere, whose deepened ramp already clears contrast.\n * Resolving the token NAME at the card means the choice tracks the live theme\n * regardless of where the theme class lives.\n */\nexport const TRIMESTER_HIGHLIGHT_TOKEN: Record<Trimester, string> = {\n preconception: '--muted',\n first: '--info',\n second: '--success',\n third: '--warning-readable',\n postterm: '--destructive',\n};\n\n/** The DS token name for a trimester's result-card chip. */\nexport function trimesterHighlightToken(trimester: Trimester): string {\n return TRIMESTER_HIGHLIGHT_TOKEN[trimester];\n}\n\n/* ------------------------------------------------------------------ */\n/* Multiple pregnancy — planned-birth timing */\n/* */\n/* For multiples the \"due date\" is not a single 40-week point but a */\n/* recommended planned-birth window that depends on chorionicity. The */\n/* UK (NICE NG137) and US (ACOG PB231) bodies diverge by ~1 week for */\n/* diamniotic twins, so the guideline is selectable; Italian practice */\n/* aligns closer to the earlier NICE stance, so `nice` is the default. */\n/* ------------------------------------------------------------------ */\n\n/** Which body's planned-birth timing to use for multiples. */\nexport type BirthGuideline = 'nice' | 'acog';\n\n/** Planned-birth window as GA days (week*7 + day), inclusive, with source. */\nexport interface BirthWindow {\n startDay: number;\n endDay: number;\n source: string;\n}\n\nconst day = (week: number, d = 0): number => week * 7 + d;\n\n/**\n * Recommended planned-birth window for a multiple pregnancy, by chorionicity.\n * Singletons return `null` (use the 40-week EDD instead). `unknown`\n * chorionicity is managed as monochorionic-diamniotic — the higher-risk\n * default (NICE QS46).\n */\nexport function plannedBirthWindow(\n plurality: Plurality,\n chorionicity: Chorionicity = 'unknown',\n guideline: BirthGuideline = 'nice',\n): BirthWindow | null {\n if (plurality === 'singleton') return null;\n\n if (plurality === 'triplet') {\n // NICE/ACOG: offer planned birth for uncomplicated triplets at ~35 weeks.\n return { startDay: day(35, 0), endDay: day(35, 6), source: 'NICE-NG137' };\n }\n\n // Twins. `unknown` is managed as monochorionic-diamniotic.\n const effective: Chorionicity =\n chorionicity === 'unknown' ? 'monochorionic-diamniotic' : chorionicity;\n\n if (guideline === 'acog') {\n switch (effective) {\n case 'dichorionic-diamniotic':\n return {\n startDay: day(38, 0),\n endDay: day(38, 6),\n source: 'ACOG-PB231',\n };\n case 'monochorionic-diamniotic':\n return {\n startDay: day(36, 0),\n endDay: day(37, 6),\n source: 'ACOG-PB231',\n };\n case 'monochorionic-monoamniotic':\n return {\n startDay: day(32, 0),\n endDay: day(34, 0),\n source: 'ACOG-PB231',\n };\n }\n }\n\n // NICE NG137 (default).\n switch (effective) {\n case 'dichorionic-diamniotic':\n return { startDay: day(37, 0), endDay: day(37, 6), source: 'NICE-NG137' };\n case 'monochorionic-diamniotic':\n return { startDay: day(36, 0), endDay: day(36, 6), source: 'NICE-NG137' };\n case 'monochorionic-monoamniotic':\n return { startDay: day(32, 0), endDay: day(33, 6), source: 'NICE-NG137' };\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Ultrasound (CRL) redating — ACOG Committee Opinion 700 */\n/* */\n/* A first-trimester crown-rump length gives a gestational age via */\n/* Robinson–Fleming. When it disagrees with the LMP by more than the */\n/* ACOG CO 700 threshold (which widens with gestation), the ultrasound */\n/* estimate replaces the LMP dating. Below threshold, the LMP stands. */\n/* The returned `ecoDiffDays` mirrors the server-side `eco_diff_days` */\n/* offset so the kit and the editor-actions backend can be reconciled. */\n/* ------------------------------------------------------------------ */\n\n/** Robinson–Fleming dating is validated for CRL 45–84 mm. */\nexport const CRL_DATING_MIN_MM = 45;\nexport const CRL_DATING_MAX_MM = 84;\n\n/** Gestational age in days from a crown-rump length (mm), Robinson–Fleming. */\nexport function crlToGestationalAgeDays(crlMm: number): number {\n // GA(days) = 8.052·√(CRL·1.037) + 23.73\n return 8.052 * Math.sqrt(crlMm * 1.037) + 23.73;\n}\n\n/**\n * ACOG CO 700 redating threshold (in days) for a given GA-by-LMP: re-date the\n * EDD to the ultrasound estimate only when the discrepancy EXCEEDS this.\n */\nexport function redatingThresholdDays(gaByLmpDays: number): number {\n if (gaByLmpDays <= day(8, 6)) return 5; // ≤ 8+6\n if (gaByLmpDays <= day(15, 6)) return 7; // 9+0 – 15+6\n if (gaByLmpDays <= day(21, 6)) return 10; // 16+0 – 21+6\n if (gaByLmpDays <= day(27, 6)) return 14; // 22+0 – 27+6\n return 21; // ≥ 28+0 (with a growth-restriction caveat the UI should note)\n}\n\nexport interface CrlRedatingInput {\n /** Reported first day of the last menstrual period. */\n lmp: Date;\n /** Date the ultrasound CRL was measured. */\n scanDate: Date;\n /** Crown-rump length, mm. */\n crlMm: number;\n}\n\nexport interface CrlRedatingResult {\n /** Notional LMP (GA day 0) after the rule — the ultrasound's or the original. */\n gestationalStart: Date;\n /** Whether the ultrasound estimate replaced the LMP dating. */\n redated: boolean;\n /** |GA-by-LMP − GA-by-CRL| at the scan, in days. */\n discrepancyDays: number;\n /** The ACOG CO 700 threshold (days) that applied. */\n thresholdDays: number;\n /** CRL − LMP dating, in days (+ = fetus ahead of dates). Server `eco_diff_days`. */\n ecoDiffDays: number;\n /** Whether the CRL is within the 45–84 mm dating-validity window. */\n crlInRange: boolean;\n}\n\n/** Apply the ACOG CO 700 CRL-redating rule to an LMP. */\nexport function redateByCrl(input: CrlRedatingInput): CrlRedatingResult {\n const gaByLmpDays = differenceInCalendarDays(input.scanDate, input.lmp);\n const gaByCrlDays = Math.round(crlToGestationalAgeDays(input.crlMm));\n const discrepancyDays = Math.abs(gaByLmpDays - gaByCrlDays);\n const thresholdDays = redatingThresholdDays(gaByLmpDays);\n const redated = discrepancyDays > thresholdDays;\n return {\n gestationalStart: redated\n ? subDays(input.scanDate, gaByCrlDays)\n : input.lmp,\n redated,\n discrepancyDays,\n thresholdDays,\n ecoDiffDays: gaByCrlDays - gaByLmpDays,\n crlInRange:\n input.crlMm >= CRL_DATING_MIN_MM && input.crlMm <= CRL_DATING_MAX_MM,\n };\n}\n","/* ------------------------------------------------------------------ */\n/* Antenatal schedule — pure, framework-free, clinically cited. */\n/* */\n/* Given a gestational start (GA day 0 = notional LMP, from */\n/* `obstetrics.ts`), resolves the time-sensitive antenatal exams and */\n/* screenings to absolute date windows with a past / current / upcoming */\n/* status. The schedule is locale-configurable because guidelines */\n/* genuinely diverge (e.g. the anomaly scan is 19+0–21+6 in Italy but */\n/* 18+0–20+6 in the UK), and conditional items (anti-D, OGTT tier, */\n/* CVS/amnio) are opt-in so a patient is never shown every test. */\n/* */\n/* Every window carries a `source` citation key so the UI can show */\n/* provenance and a clinician can audit the data. Windows are NOT */\n/* ported from the original Metricare app — its constants carry a */\n/* documented 2-week-late dating shift (the first-trimester screening */\n/* rendered after its window had closed). These are the guideline */\n/* windows, anchored to the kit's correct `computeDueDate` maths. */\n/* */\n/* Sources (citation keys): */\n/* SIEOG-2021 — SIEOG ministerial ultrasound guidelines 2021 (IT) */\n/* ISS — ISS 'Gravidanza fisiologica' / LEA (IT) */\n/* SID-AMD — SID-AMD/ISS gestational-diabetes screening (IT) */\n/* ACOG-CO700 — ACOG Committee Opinion 700 (EDD methods) */\n/* NICE-NG201 — NICE NG201 routine antenatal care (UK) */\n/* NICE-NG137 — NICE NG137 twin & triplet pregnancy (UK) */\n/* ISUOG-2025 — ISUOG twin-pregnancy ultrasound guidelines 2025 */\n/* ------------------------------------------------------------------ */\n\nimport { addDays, differenceInCalendarDays } from 'date-fns';\nimport {\n plannedBirthWindow,\n type Plurality,\n type Chorionicity,\n type BirthGuideline,\n} from './obstetrics';\n\nexport type AntenatalCategory =\n | 'scan'\n | 'screening'\n | 'diagnostic'\n | 'lab'\n | 'prophylaxis'\n | 'milestone';\n\n/** Which national schedule to resolve. Italy is the default market. */\nexport type ScheduleLocale = 'it' | 'uk' | 'international';\n\n/** Status of a window relative to the reference date (keyed off its end). */\nexport type AntenatalStatus = 'past' | 'current' | 'upcoming';\n\n/** Gestational-diabetes risk tier (drives which OGTT window applies). */\nexport type GdmRisk = 'high' | 'medium';\n\n/** A clinical condition gating whether an event applies to a pregnancy. */\nexport type AntenatalCondition =\n | 'rh-negative'\n | 'gdm-high'\n | 'gdm-medium'\n | 'on-indication';\n\nexport interface AntenatalEvent {\n /** Stable key → i18n lookup `antenatalSchedule.event.<key>`. */\n key: string;\n category: AntenatalCategory;\n /** Window start as GA days from gestationalStart (week*7 + day). Inclusive. */\n startDay: number;\n /** Window end as GA days. Inclusive. Equals `startDay` for single dates. */\n endDay: number;\n /** Restrict to these pluralities (omit ⇒ applies to all). */\n plurality?: Plurality[];\n /** Restrict to these chorionicities (omit ⇒ any). */\n chorionicity?: Chorionicity[];\n /** Gate behind a clinical condition (omit ⇒ always applies). */\n condition?: AntenatalCondition;\n /** Citation key for provenance display. */\n source: string;\n /** Interpolation values for the event's i18n string (e.g. surveillance cadence). */\n meta?: Record<string, string | number>;\n}\n\nexport interface ResolvedAntenatalEvent extends AntenatalEvent {\n /** Absolute window start date. */\n start: Date;\n /** Absolute window end date (=== `start` for a single-date event). */\n end: Date;\n /** True when the event is a single calendar date, not a range. */\n single: boolean;\n /** Status relative to the reference date, keyed off the window end. */\n status: AntenatalStatus;\n /** Reference date is within `nearDays` before the window end. */\n near: boolean;\n}\n\nexport interface AntenatalScheduleOptions {\n /** Reference date for status. Defaults to the host's current date. */\n today?: Date;\n /** National schedule. Defaults to `'it'`. */\n schedule?: ScheduleLocale;\n /** Number of fetuses. Defaults to `'singleton'`. */\n plurality?: Plurality;\n /** Placentation, for multiples. Defaults to `'unknown'`. */\n chorionicity?: Chorionicity;\n /** Surface the anti-D prophylaxis event (Rh-negative, non-sensitised). */\n rhNegative?: boolean;\n /** Surface the matching OGTT window for the patient's GDM risk tier. */\n gdmRisk?: GdmRisk;\n /** Include `on-indication` diagnostics (CVS, amnio, NIPT). Default false. */\n includeOnIndication?: boolean;\n /** Planned-birth guideline for multiples. Defaults to `'nice'`. */\n birthGuideline?: BirthGuideline;\n /** Days before a window's end still counted as `current`. Default 14. */\n nearDays?: number;\n}\n\n/** Gestational-age days from a week + day pair (e.g. `ga(13, 6)` → 97). */\nconst ga = (week: number, day = 0): number => week * 7 + day;\n\n/* ------------------------------------------------------------------ */\n/* Schedule data — one table per locale. */\n/* Common events are defined once and reused; only the windows that */\n/* genuinely diverge between locales are overridden. */\n/* ------------------------------------------------------------------ */\n\n/**\n * First-trimester dating scan + nuchal translucency + combined/bi-test.\n * NT is only measurable at CRL 45–84 mm, which is the 11+0–13+6 window;\n * the combined-test bloods (PAPP-A, free β-hCG) share it. (UK opens it a\n * touch later, 11+2–14+1, anchored to NICE's CRL band.)\n */\nconst datingNt = (locale: ScheduleLocale): AntenatalEvent =>\n locale === 'uk'\n ? {\n key: 'dating-nt',\n category: 'screening',\n startDay: ga(11, 2),\n endDay: ga(14, 1),\n source: 'NICE-NG201',\n }\n : {\n key: 'dating-nt',\n category: 'screening',\n startDay: ga(11, 0),\n endDay: ga(13, 6),\n source: 'SIEOG-2021',\n };\n\n/** NIPT / cell-free DNA — earliest 10+0; co-timed with the combined test. */\nconst nipt: AntenatalEvent = {\n key: 'nipt',\n category: 'screening',\n startDay: ga(10, 0),\n endDay: ga(13, 6),\n condition: 'on-indication',\n source: 'ACOG-CO700',\n};\n\n/** Chorionic villus sampling — never before 10–11w (limb-reduction risk). */\nconst cvs: AntenatalEvent = {\n key: 'cvs',\n category: 'diagnostic',\n startDay: ga(11, 0),\n endDay: ga(13, 6),\n condition: 'on-indication',\n source: 'ISS',\n};\n\n/** Amniocentesis — from 15+0 (typically 15–18w). */\nconst amnio: AntenatalEvent = {\n key: 'amnio',\n category: 'diagnostic',\n startDay: ga(15, 0),\n endDay: ga(18, 0),\n condition: 'on-indication',\n source: 'ISS',\n};\n\n/** Second-trimester anomaly / morphology scan — the key locale divergence. */\nconst morphology = (locale: ScheduleLocale): AntenatalEvent => {\n if (locale === 'uk') {\n return {\n key: 'morphology',\n category: 'scan',\n startDay: ga(18, 0),\n endDay: ga(20, 6),\n source: 'NICE-NG201',\n };\n }\n if (locale === 'international') {\n return {\n key: 'morphology',\n category: 'scan',\n startDay: ga(18, 0),\n endDay: ga(22, 0),\n source: 'ACOG-CO700',\n };\n }\n return {\n key: 'morphology',\n category: 'scan',\n startDay: ga(19, 0),\n endDay: ga(21, 6),\n source: 'SIEOG-2021',\n };\n};\n\n/**\n * Third-trimester growth scan — `on-indication` everywhere: not routine in\n * the Italian low-risk pathway (ISS uses symphysis-fundal height from 24w);\n * NICE/ACOG also reserve late scans for indications in low-risk pregnancies.\n */\nconst growth: AntenatalEvent = {\n key: 'growth',\n category: 'scan',\n startDay: ga(30, 0),\n endDay: ga(33, 6),\n condition: 'on-indication',\n source: 'SIEOG-2021',\n};\n\n/** OGTT 75 g, high-risk tier (BMI ≥ 30 / prior GDM / fasting 100–125). */\nconst ogttHigh: AntenatalEvent = {\n key: 'ogtt-high',\n category: 'lab',\n startDay: ga(16, 0),\n endDay: ga(18, 6),\n condition: 'gdm-high',\n source: 'SID-AMD',\n};\n\n/** OGTT 75 g, medium-risk tier (≥ 1 of: family hx, BMI ≥ 25, age ≥ 35 …). */\nconst ogttMedium: AntenatalEvent = {\n key: 'ogtt-medium',\n category: 'lab',\n startDay: ga(24, 0),\n endDay: ga(28, 6),\n condition: 'gdm-medium',\n source: 'SID-AMD',\n};\n\n/** Group-B streptococcus vagino-rectal swab. */\nconst gbs = (locale: ScheduleLocale): AntenatalEvent =>\n locale === 'it'\n ? {\n key: 'gbs',\n category: 'lab',\n startDay: ga(36, 0),\n endDay: ga(37, 6),\n source: 'ISS',\n }\n : {\n // CDC / legacy international protocols open a week earlier.\n key: 'gbs',\n category: 'lab',\n startDay: ga(35, 0),\n endDay: ga(37, 6),\n source: 'NICE-NG201',\n };\n\n/** Routine antenatal anti-D prophylaxis for non-sensitised Rh(D)-neg women. */\nconst antiD: AntenatalEvent = {\n key: 'anti-d',\n category: 'prophylaxis',\n startDay: ga(28, 0),\n endDay: ga(28, 0),\n condition: 'rh-negative',\n source: 'ISS',\n};\n\n/**\n * Term threshold (37+0) — singletons only. Multiples are delivered earlier\n * (see `plannedBirthWindow`), so a 37-week \"term\" milestone would fall after\n * their recommended birth window and read as clinically contradictory.\n */\nconst term: AntenatalEvent = {\n key: 'term',\n category: 'milestone',\n startDay: ga(37, 0),\n endDay: ga(37, 0),\n plurality: ['singleton'],\n source: 'ACOG-CO700',\n};\n\n/** Estimated due date (40+0) — singleton only; twins use a birth window. */\nconst edd: AntenatalEvent = {\n key: 'edd',\n category: 'milestone',\n startDay: ga(40, 0),\n endDay: ga(40, 0),\n plurality: ['singleton'],\n source: 'ACOG-CO700',\n};\n\n/**\n * Chorionicity + amnionicity determination — twins/triplets only, at the\n * first-trimester scan (before 13+6 / CRL 45–84 mm). If presentation is\n * later, determine at the earliest opportunity.\n */\nconst chorionicityDetermination: AntenatalEvent = {\n key: 'chorionicity',\n category: 'scan',\n startDay: ga(11, 2),\n endDay: ga(14, 1),\n plurality: ['twin', 'triplet'],\n source: 'ISUOG-2025',\n};\n\n/** Build the ordered base event list for a locale (pre-filtering). */\nfunction baseEvents(locale: ScheduleLocale): AntenatalEvent[] {\n return [\n datingNt(locale),\n nipt,\n cvs,\n chorionicityDetermination,\n amnio,\n morphology(locale),\n ogttHigh,\n growth,\n ogttMedium,\n term,\n gbs(locale),\n antiD,\n edd,\n ];\n}\n\n/**\n * Extra events for a multiple pregnancy: increased ultrasound surveillance\n * (cadence by chorionicity) and the planned-birth window (which replaces the\n * singleton EDD). Monochorionic twins are scanned every 2 weeks from 16w to\n * catch TTTS; dichorionic every 4 weeks from 20w. `unknown` chorionicity is\n * managed as monochorionic (the higher-risk default).\n */\nfunction multipleEvents(\n plurality: Plurality,\n chorionicity: Chorionicity,\n guideline: BirthGuideline,\n): AntenatalEvent[] {\n if (plurality === 'singleton') return [];\n\n const isDichorionic = chorionicity === 'dichorionic-diamniotic';\n const everyWeeks = isDichorionic ? 4 : 2;\n const fromWeek = isDichorionic ? 20 : 16;\n const birth = plannedBirthWindow(plurality, chorionicity, guideline);\n\n const events: AntenatalEvent[] = [\n {\n key: 'surveillance',\n category: 'scan',\n startDay: ga(fromWeek, 0),\n // Runs until the planned-birth window opens (fallback 36w if none).\n endDay: birth ? birth.startDay : ga(36, 0),\n source: isDichorionic ? 'NICE-NG137' : 'ISUOG-2025',\n meta: { everyWeeks, fromWeek },\n },\n ];\n\n if (birth) {\n events.push({\n key: 'birth',\n category: 'milestone',\n startDay: birth.startDay,\n endDay: birth.endDay,\n source: birth.source,\n });\n }\n\n return events;\n}\n\n/* ------------------------------------------------------------------ */\n/* Resolution */\n/* ------------------------------------------------------------------ */\n\n/** Does an event apply, given the pregnancy's plurality/chorionicity/conds? */\nfunction eventApplies(\n event: AntenatalEvent,\n opts: Required<\n Pick<AntenatalScheduleOptions, 'plurality' | 'chorionicity'>\n > & {\n rhNegative: boolean;\n gdmRisk?: GdmRisk;\n includeOnIndication: boolean;\n },\n): boolean {\n if (event.plurality && !event.plurality.includes(opts.plurality)) {\n return false;\n }\n if (event.chorionicity && !event.chorionicity.includes(opts.chorionicity)) {\n return false;\n }\n switch (event.condition) {\n case 'rh-negative':\n return opts.rhNegative;\n case 'gdm-high':\n return opts.gdmRisk === 'high';\n case 'gdm-medium':\n return opts.gdmRisk === 'medium';\n case 'on-indication':\n return opts.includeOnIndication;\n default:\n return true;\n }\n}\n\nfunction statusFor(\n start: Date,\n end: Date,\n today: Date,\n nearDays: number,\n): { status: AntenatalStatus; near: boolean } {\n const daysUntilStart = differenceInCalendarDays(start, today);\n const daysUntilEnd = differenceInCalendarDays(end, today);\n // Window already closed.\n if (daysUntilEnd < 0) return { status: 'past', near: false };\n // Open now (start ≤ today ≤ end) → current, and always worth flagging.\n if (daysUntilStart <= 0) return { status: 'current', near: true };\n // Not yet open → upcoming; \"near\" if it opens within nearDays.\n return { status: 'upcoming', near: daysUntilStart <= nearDays };\n}\n\n/**\n * Resolve the antenatal schedule for a pregnancy to dated, status-tagged\n * windows, ordered by start date (then end date). Pure: the only clock is\n * `opts.today` (defaults to a fresh `Date`).\n */\nexport function computeAntenatalSchedule(\n gestationalStart: Date,\n opts: AntenatalScheduleOptions = {},\n): ResolvedAntenatalEvent[] {\n const {\n today = new Date(),\n schedule = 'it',\n plurality = 'singleton',\n chorionicity = 'unknown',\n rhNegative = false,\n gdmRisk,\n includeOnIndication = false,\n birthGuideline = 'nice',\n nearDays = 14,\n } = opts;\n\n return [\n ...baseEvents(schedule),\n ...multipleEvents(plurality, chorionicity, birthGuideline),\n ]\n .filter((event) =>\n eventApplies(event, {\n plurality,\n chorionicity,\n rhNegative,\n gdmRisk,\n includeOnIndication,\n }),\n )\n .map((event): ResolvedAntenatalEvent => {\n const start = addDays(gestationalStart, event.startDay);\n const end = addDays(gestationalStart, event.endDay);\n const { status, near } = statusFor(start, end, today, nearDays);\n return {\n ...event,\n start,\n end,\n single: event.startDay === event.endDay,\n status,\n near,\n };\n })\n .sort((a, b) => {\n const byStart = a.startDay - b.startDay;\n return byStart !== 0 ? byStart : a.endDay - b.endDay;\n });\n}\n","/* ------------------------------------------------------------------ */\n/* AntenatalScheduleTimeline — the presentational list of resolved */\n/* antenatal windows, shared by the `showSchedule` appendix on */\n/* GestationalAgeCalculator and DueDateCalculator. Pure display: it takes */\n/* already-resolved events and renders the Card + the sr-only now-due */\n/* summary. No inputs, no state, no maths. */\n/* ------------------------------------------------------------------ */\n\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Card } from '../card';\nimport { Badge } from '../badge';\nimport type { IconKey, InsertCardField } from './insert-result';\nimport type {\n ResolvedAntenatalEvent,\n AntenatalStatus,\n AntenatalCategory,\n} from './antenatal-schedule';\n\n/** Status → on-screen Badge variant. `near` upcoming items borrow `warning`. */\nfunction statusBadgeVariant(\n status: AntenatalStatus,\n near: boolean,\n): 'neutral' | 'info' | 'warning' {\n if (status === 'past') return 'neutral';\n if (status === 'current') return 'warning';\n return near ? 'warning' : 'info';\n}\n\n/** Compact gestational-age label for a day offset, e.g. 97 → \"13+6\". */\nfunction gaLabel(days: number): string {\n return `${Math.floor(days / 7)}+${days % 7}`;\n}\n\n/** Each schedule category maps to one of the inserted-card glyph keys. */\nconst CATEGORY_ICON: Record<AntenatalCategory, IconKey> = {\n scan: 'activity',\n screening: 'activity',\n diagnostic: 'activity',\n lab: 'droplets',\n prophylaxis: 'heart',\n milestone: 'calendar',\n};\n\n/** Minimal translator shape this module needs (matches react-i18next's `t`). */\ntype Translate = (key: string, opts?: Record<string, unknown>) => string;\n\n/** Localised \"label · range\" for one event (e.g. for the sr-only summary). */\nfunction eventLabelFor(event: ResolvedAntenatalEvent, t: Translate): string {\n return t(`antenatalSchedule.event.${event.key}`, event.meta ?? {});\n}\n\n/**\n * Build the inserted-card rows for a resolved schedule, so a host calculator's\n * single Insert button can carry the schedule in its payload (rather than a\n * second Insert button on the schedule card). One row per event: a\n * category-tinted glyph, the localised label, and the date range.\n */\nexport function buildScheduleInsertFields(\n events: ResolvedAntenatalEvent[],\n t: Translate,\n formatDate: (date: Date) => string,\n): InsertCardField[] {\n return events.map((event) => ({\n icon: CATEGORY_ICON[event.category],\n label: eventLabelFor(event, t),\n value: event.single\n ? formatDate(event.start)\n : `${formatDate(event.start)} – ${formatDate(event.end)}`,\n }));\n}\n\nexport interface AntenatalScheduleTimelineProps {\n /** Resolved schedule events (from `computeAntenatalSchedule`). */\n events: ResolvedAntenatalEvent[];\n}\n\nexport function AntenatalScheduleTimeline({\n events,\n}: AntenatalScheduleTimelineProps) {\n const { t, i18n } = useTranslation();\n\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }),\n [i18n.language],\n );\n\n const eventLabel = (event: ResolvedAntenatalEvent): string =>\n eventLabelFor(event, t);\n\n const formatRange = (event: ResolvedAntenatalEvent): string =>\n event.single\n ? dateFormatter.format(event.start)\n : `${dateFormatter.format(event.start)} – ${dateFormatter.format(\n event.end,\n )}`;\n\n // No own live region: this timeline is always embedded in a host calculator\n // that already owns a `role=\"status\"` result announcement, so a second one\n // here would double-announce. The schedule is fully present in the DOM\n // (labelled list + per-row status Badge) for assistive tech to browse.\n return (\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <span className=\"type-label ds:text-muted-foreground\">\n {t('antenatalSchedule.scheduleLabel')}\n </span>\n <ul className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n {events.map((event) => (\n <li\n key={event.key}\n data-status={event.status}\n className=\"ds:flex ds:flex-wrap ds:items-start ds:justify-between ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-xs)] ds:border-b ds:border-border ds:pb-[var(--spacing-sm)] ds:last:border-b-0 ds:last:pb-0\"\n >\n <span className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)]\">\n <span className=\"type-body ds:text-foreground\">\n {eventLabel(event)}\n </span>\n <span className=\"type-meta ds:text-muted-foreground\">\n {t(`antenatalSchedule.category.${event.category}`)} ·{' '}\n {gaLabel(event.startDay)}\n {event.single ? '' : ` – ${gaLabel(event.endDay)}`} ·{' '}\n {t(`antenatalSchedule.source.${event.source}`)}\n {event.condition === 'on-indication'\n ? ` · ${t('antenatalSchedule.onIndication')}`\n : ''}\n </span>\n </span>\n <span className=\"ds:flex ds:flex-col ds:items-end ds:gap-[var(--spacing-2xs)] ds:text-end\">\n <span className=\"type-body ds:text-foreground\">\n {formatRange(event)}\n </span>\n <Badge variant={statusBadgeVariant(event.status, event.near)}>\n {event.status === 'upcoming' && event.near\n ? t('antenatalSchedule.near')\n : t(`antenatalSchedule.status.${event.status}`)}\n </Badge>\n </span>\n </li>\n ))}\n </ul>\n <p className=\"type-meta ds:text-muted-foreground\">\n {t('antenatalSchedule.disclaimer')}\n </p>\n </Card.Body>\n </Card>\n );\n}\n"],"names":["GESTATION_DAYS","CONCEPTION_OFFSET_DAYS","TERM_FROM_CONCEPTION_DAYS","DEFAULT_CYCLE_LENGTH","trimesterForWeeks","totalDays","weeks","computeDueDate","input","today","method","date","gestationalStart","dueDate","cycle","addDays","subDays","embryo","conceptionDate","differenceInCalendarDays","gestationalAge","MILESTONE_WEEKS","gestationalMilestones","week","TRIMESTER_BADGE_VARIANT","TRIMESTER_HIGHLIGHT_TOKEN","trimesterHighlightToken","trimester","day","d","plannedBirthWindow","plurality","chorionicity","guideline","effective","CRL_DATING_MIN_MM","CRL_DATING_MAX_MM","crlToGestationalAgeDays","crlMm","redatingThresholdDays","gaByLmpDays","redateByCrl","gaByCrlDays","discrepancyDays","thresholdDays","redated","ga","datingNt","locale","nipt","cvs","amnio","morphology","growth","ogttHigh","ogttMedium","gbs","antiD","term","edd","chorionicityDetermination","baseEvents","multipleEvents","isDichorionic","everyWeeks","fromWeek","birth","events","eventApplies","event","opts","statusFor","start","end","nearDays","daysUntilStart","computeAntenatalSchedule","schedule","rhNegative","gdmRisk","includeOnIndication","birthGuideline","status","near","a","b","byStart","statusBadgeVariant","gaLabel","days","CATEGORY_ICON","eventLabelFor","t","buildScheduleInsertFields","formatDate","AntenatalScheduleTimeline","i18n","useTranslation","dateFormatter","useMemo","eventLabel","formatRange","jsx","Card","jsxs","Badge"],"mappings":"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"}
@@ -10,7 +10,7 @@ import { N as S } from "./number-input-Dj5L3pXK.js";
10
10
  import { C as k } from "./card-DPmk26CL.js";
11
11
  import { B } from "./badge-zsf5i5bH.js";
12
12
  import { I as X } from "./insert-result-DNdi_JYW.js";
13
- import { D as y, r as Z, c as ee, e as ae, f as te, A as le, h as re, i as se } from "./antenatal-schedule-timeline-Dg0m0yFl.js";
13
+ import { D as y, r as Z, c as ee, e as ae, f as te, A as le, h as re, i as se } from "./antenatal-schedule-timeline-CdiqkF05.js";
14
14
  const de = Q("ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]", {
15
15
  variants: {
16
16
  width: { full: "ds:w-full", auto: "ds:inline-flex" }
@@ -253,4 +253,4 @@ ce.displayName = "DueDateCalculator";
253
253
  export {
254
254
  ce as D
255
255
  };
256
- //# sourceMappingURL=due-date-calculator-tDqZXPWO.js.map
256
+ //# sourceMappingURL=due-date-calculator-DykajWzh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"due-date-calculator-DykajWzh.js","sources":["../../src/components/due-date-calculator/due-date-calculator.tsx"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* DueDateCalculator — estimate the date of delivery from one of three */\n/* dating methods, with current gestational age + trimester. */\n/* */\n/* - Maths lives in `./gestation` (pure, separately tested). */\n/* - Three methods: LMP (Naegele, cycle-length adjustable), conception, */\n/* and IVF transfer (Day-3 vs Day-5 embryo). */\n/* - The reference date can't be in the future, so the DatePicker caps */\n/* at today. */\n/* ------------------------------------------------------------------ */\n\nimport { forwardRef, useEffect, useMemo, useState } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { RadioGroup, Radio } from '../radio-group';\nimport { FormField } from '../form-field';\nimport { DatePicker } from '../date-picker';\nimport { NumberInput } from '../number-input';\nimport { Card } from '../card';\nimport { Badge } from '../badge';\nimport {\n InsertButton,\n type InsertPayload,\n type InsertVariant,\n type InsertMode,\n} from '../_shared/insert-result';\nimport {\n type DueDateMethod,\n type EmbryoAge,\n type DueDateResult,\n computeDueDate,\n redateByCrl,\n DEFAULT_CYCLE_LENGTH,\n TRIMESTER_BADGE_VARIANT,\n trimesterHighlightToken,\n} from '../_shared/obstetrics';\nimport {\n computeAntenatalSchedule,\n type AntenatalScheduleOptions,\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/** Reference-date i18n key per method. */\nconst DATE_LABEL_KEY: Record<DueDateMethod, string> = {\n lmp: 'dueDateCalculator.lmpDate',\n conception: 'dueDateCalculator.conceptionDate',\n ivf: 'dueDateCalculator.transferDate',\n};\n\nexport interface DueDateCalculatorProps extends VariantProps<\n typeof rootVariants\n> {\n /** Initial dating method. Defaults to `'lmp'`. */\n defaultMethod?: DueDateMethod;\n /** Fires whenever a due date can be computed (and with `null` when it can't). */\n onResultChange?: (result: DueDateResult | null) => void;\n /** When provided, shows an \"Insert\" button that emits the result for an editor. */\n onInsert?: (payload: InsertPayload) => void;\n /**\n * Which verb the result button performs. Defaults to `'insert'`.\n * Use `'copy'` in an app-shell surface (no editor to insert into) — the\n * button writes the result to the clipboard as a multi-format `ClipboardItem`.\n */\n insertVariant?: InsertVariant;\n /** `copy` variant only — fired after a successful clipboard write. */\n onCopy?: (mode: InsertMode) => void;\n /** `copy` variant only — fired if the clipboard write can't proceed. */\n onError?: (error: unknown) => void;\n /**\n * Brand wordmark printed in the inserted/copied result-card footer.\n * Omitted → no brand line (and no footer hairline); a string → that custom\n * brand; `false` → no brand line. Brand is opt-in.\n */\n insertBrand?: string | false;\n /**\n * Append the antenatal exam schedule (the time-sensitive screening windows)\n * below the result, dated from the computed gestational start.\n */\n showSchedule?: boolean;\n /**\n * Passthrough options for the appended schedule (national `schedule`,\n * `plurality`, `chorionicity`, `rhNegative`, `gdmRisk`, …). `today` is\n * supplied by the component. Ignored unless `showSchedule` is set.\n */\n scheduleOptions?: Omit<AntenatalScheduleOptions, 'today'>;\n /** Opaque instance id, emitted as `data-component-id`. */\n id?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n}\n\n/**\n * @deprecated Superseded by `PregnancyDating`, which unifies the due-date and\n * gestational-age calculators (any anchor → both EDD and current GA) and adds a\n * manual ±days dating adjustment. This component will be removed in a future\n * release; migrate to `PregnancyDating` (`defaultMethod=\"lmp\"`).\n */\nexport const DueDateCalculator = forwardRef<\n HTMLDivElement,\n DueDateCalculatorProps\n>(\n (\n {\n defaultMethod = 'lmp',\n onResultChange,\n onInsert,\n insertVariant = 'insert',\n onCopy,\n onError,\n insertBrand,\n showSchedule = false,\n scheduleOptions,\n id,\n width,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const [method, setMethod] = useState<DueDateMethod>(defaultMethod);\n const [refDate, setRefDate] = useState<Date | undefined>(undefined);\n const [cycleLength, setCycleLength] = useState<number | null>(\n DEFAULT_CYCLE_LENGTH,\n );\n const [embryoAge, setEmbryoAge] = useState<EmbryoAge>(5);\n // Optional first-trimester ultrasound (LMP method only) for ACOG CO700 redating.\n const [crlMm, setCrlMm] = useState<number | null>(null);\n const [scanDate, setScanDate] = useState<Date | undefined>(undefined);\n\n // Real today — caps the date inputs (LMP / ultrasound can't be in the future).\n const today = useMemo(() => new Date(), []);\n // The date GA, trimester and schedule status are evaluated against; defaults\n // to today but can be a future appointment date to project forward. (The EDD\n // itself is dating-anchored and does not depend on this.)\n const [asOfDate, setAsOfDate] = useState<Date>(() => new Date());\n\n // ACOG CO700 CRL redating — only when an LMP, a CRL and a scan date are set.\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 result = useMemo<DueDateResult | null>(() => {\n if (!refDate) return null;\n // A confirmed redating moves the effective LMP to the ultrasound's; the\n // CRL already reflects true gestation, so cycle adjustment no longer applies.\n const effectiveDate =\n method === 'lmp' && redating?.redated\n ? redating.gestationalStart\n : refDate;\n const effectiveCycle =\n method === 'lmp' && redating?.redated\n ? DEFAULT_CYCLE_LENGTH\n : (cycleLength ?? DEFAULT_CYCLE_LENGTH);\n return computeDueDate(\n {\n method,\n date: effectiveDate,\n cycleLength: effectiveCycle,\n embryoAge,\n },\n asOfDate,\n );\n }, [method, refDate, cycleLength, embryoAge, redating, asOfDate]);\n\n const dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'long' }),\n [i18n.language],\n );\n\n useEffect(() => {\n onResultChange?.(result);\n }, [result, onResultChange]);\n\n const schedule = useMemo(() => {\n if (!showSchedule || !result) return null;\n return computeAntenatalSchedule(result.gestationalStart, {\n ...scheduleOptions,\n today: asOfDate,\n });\n }, [showSchedule, result, asOfDate, scheduleOptions]);\n\n return (\n <div\n ref={ref}\n data-component=\"due-date-calculator\"\n data-component-id={id}\n className={rootVariants({ width, className })}\n >\n <RadioGroup\n label={t('dueDateCalculator.method.label')}\n variant=\"horizontal\"\n value={method}\n onValueChange={(next) => setMethod(next as DueDateMethod)}\n >\n <Radio label={t('dueDateCalculator.method.lmp')} value=\"lmp\" />\n <Radio\n label={t('dueDateCalculator.method.conception')}\n value=\"conception\"\n />\n <Radio label={t('dueDateCalculator.method.ivf')} value=\"ivf\" />\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 value={refDate} onChange={setRefDate} maxDate={today} />\n </FormField>\n\n {method === 'lmp' && (\n <FormField\n label={t('dueDateCalculator.cycleLength')}\n description={t('dueDateCalculator.cycleLengthHint')}\n >\n <NumberInput\n mode=\"integer\"\n min={20}\n max={45}\n value={cycleLength}\n onChange={setCycleLength}\n />\n </FormField>\n )}\n\n {method === 'ivf' && (\n <RadioGroup\n label={t('dueDateCalculator.embryoAge')}\n variant=\"horizontal\"\n value={String(embryoAge)}\n onValueChange={(next) => setEmbryoAge(Number(next) as EmbryoAge)}\n >\n <Radio label={t('dueDateCalculator.day3')} value=\"3\" />\n <Radio label={t('dueDateCalculator.day5')} value=\"5\" />\n </RadioGroup>\n )}\n </div>\n\n <FormField\n label={t('dueDateCalculator.asOfDate')}\n description={t('dueDateCalculator.asOfDateHint')}\n >\n <DatePicker value={asOfDate} onChange={(d) => d && setAsOfDate(d)} />\n </FormField>\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('dueDateCalculator.crl')}\n description={t('dueDateCalculator.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('dueDateCalculator.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('dueDateCalculator.redated', {\n days: redating.discrepancyDays,\n })\n : t('dueDateCalculator.datesAgree')}\n </Badge>\n {!redating.crlInRange ? (\n <span className=\"type-meta ds:text-muted-foreground\">\n {t('dueDateCalculator.crlOutOfRange')}\n </span>\n ) : null}\n </div>\n ) : null}\n </div>\n ) : null}\n\n {/* Concise polite announcement when a due date resolves. */}\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {result\n ? `${t('dueDateCalculator.result.dueDateLabel')}: ${dateFormatter.format(\n result.dueDate,\n )}. ${t('dueDateCalculator.result.trimesterLabel')}: ${t(\n `dueDateCalculator.trimester.${result.trimester}`,\n )}.`\n : ''}\n </p>\n\n {result ? (\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <dl className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-3\">\n <div className=\"ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('dueDateCalculator.result.trimesterLabel')}\n </dt>\n <dd>\n <Badge\n variant={TRIMESTER_BADGE_VARIANT[result.trimester]}\n size=\"lg\"\n >\n {t(`dueDateCalculator.trimester.${result.trimester}`)}\n </Badge>\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('dueDateCalculator.result.gestationLabel')}\n </dt>\n <dd className=\"type-body ds:text-foreground\">\n {result.gestationalAge\n ? t('dueDateCalculator.result.gestation', {\n weeks: result.gestationalAge.weeks,\n days: result.gestationalAge.days,\n })\n : '—'}\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('dueDateCalculator.result.dueDateLabel')}\n </dt>\n <dd className=\"type-metric ds:text-foreground\">\n {dateFormatter.format(result.dueDate)}\n </dd>\n </div>\n </dl>\n </Card.Body>\n </Card>\n ) : (\n <p className=\"type-body ds:text-muted-foreground\">\n {t('dueDateCalculator.empty')}\n </p>\n )}\n\n {schedule ? <AntenatalScheduleTimeline events={schedule} /> : null}\n\n {/* One result-action group for the whole result — sits after both the\n due-date card and the schedule, and its payload carries the schedule\n rows when shown (no per-card buttons). */}\n {result && (insertVariant === 'copy' || onInsert) ? (\n <InsertButton\n variant={insertVariant}\n onInsert={onInsert}\n onCopy={onCopy}\n onError={onError}\n card={{\n title: t('insert.title.dueDate'),\n icon: 'calendar-heart',\n highlight: dateFormatter.format(result.dueDate),\n // Chip tinted with the trimester's semantic token so the inserted\n // PNG carries the same clinical-stage colour as the on-screen\n // trimester badge — with the contrast-safe orange override for the\n // `--warning` third trimester.\n highlightToken: trimesterHighlightToken(result.trimester),\n brand: insertBrand,\n fields: [\n {\n // The estimated date of delivery → calendar glyph.\n icon: 'calendar',\n label: t('dueDateCalculator.result.dueDateLabel'),\n value: dateFormatter.format(result.dueDate),\n },\n {\n // Gestational age is an elapsed duration → clock glyph.\n icon: 'clock',\n label: t('dueDateCalculator.result.gestationLabel'),\n value: result.gestationalAge\n ? t('dueDateCalculator.result.gestation', {\n weeks: result.gestationalAge.weeks,\n days: result.gestationalAge.days,\n })\n : '—',\n },\n {\n // Trimester is a clinical-stage classification → tag.\n icon: 'tag',\n label: t('dueDateCalculator.result.trimesterLabel'),\n value: t(`dueDateCalculator.trimester.${result.trimester}`),\n },\n // When the schedule is shown, the single Insert button carries\n // the exam windows too (no second button).\n ...(schedule\n ? buildScheduleInsertFields(schedule, t, (d) =>\n dateFormatter.format(d),\n )\n : []),\n ],\n }}\n />\n ) : null}\n </div>\n );\n },\n);\n\nDueDateCalculator.displayName = 'DueDateCalculator';\n"],"names":["rootVariants","cva","DATE_LABEL_KEY","DueDateCalculator","forwardRef","defaultMethod","onResultChange","onInsert","insertVariant","onCopy","onError","insertBrand","showSchedule","scheduleOptions","id","width","className","ref","t","i18n","useTranslation","method","setMethod","useState","refDate","setRefDate","cycleLength","setCycleLength","DEFAULT_CYCLE_LENGTH","embryoAge","setEmbryoAge","crlMm","setCrlMm","scanDate","setScanDate","today","useMemo","asOfDate","setAsOfDate","redating","redateByCrl","result","effectiveDate","effectiveCycle","computeDueDate","dateFormatter","useEffect","schedule","computeAntenatalSchedule","jsxs","RadioGroup","next","jsx","Radio","FormField","DatePicker","NumberInput","Badge","Card","TRIMESTER_BADGE_VARIANT","AntenatalScheduleTimeline","InsertButton","trimesterHighlightToken","buildScheduleInsertFields"],"mappings":";;;;;;;;;;;;;AA6CA,MAAMA,KAAeC,EAAI,kDAAkD;AAAA,EACzE,UAAU;AAAA,IACR,OAAO,EAAE,MAAM,aAAa,MAAM,iBAAA;AAAA,EAAiB;AAAA,EAErD,iBAAiB,EAAE,OAAO,OAAA;AAC5B,CAAC,GAGKC,KAAgD;AAAA,EACpD,KAAK;AAAA,EACL,YAAY;AAAA,EACZ,KAAK;AACP,GAkDaC,KAAoBC;AAAA,EAI/B,CACE;AAAA,IACE,eAAAC,IAAgB;AAAA,IAChB,gBAAAC;AAAA,IACA,UAAAC;AAAA,IACA,eAAAC,IAAgB;AAAA,IAChB,QAAAC;AAAA,IACA,SAAAC;AAAA,IACA,aAAAC;AAAA,IACA,cAAAC,IAAe;AAAA,IACf,iBAAAC;AAAA,IACA,IAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC;AAAA,EAAA,GAEFC,MACG;AACH,UAAM,EAAE,GAAAC,GAAG,MAAAC,EAAA,IAASC,EAAA,GAEd,CAACC,GAAQC,CAAS,IAAIC,EAAwBlB,CAAa,GAC3D,CAACmB,GAASC,CAAU,IAAIF,EAA2B,MAAS,GAC5D,CAACG,GAAaC,CAAc,IAAIJ;AAAA,MACpCK;AAAA,IAAA,GAEI,CAACC,GAAWC,CAAY,IAAIP,EAAoB,CAAC,GAEjD,CAACQ,GAAOC,CAAQ,IAAIT,EAAwB,IAAI,GAChD,CAACU,GAAUC,CAAW,IAAIX,EAA2B,MAAS,GAG9DY,IAAQC,EAAQ,0BAAU,KAAA,GAAQ,CAAA,CAAE,GAIpC,CAACC,GAAUC,CAAW,IAAIf,EAAe,MAAM,oBAAI,MAAM,GAGzDgB,IAAWH,EAAQ,MACnBf,MAAW,SAAS,CAACG,KAAWO,MAAU,QAAQ,CAACE,IAC9C,OAEFO,EAAY,EAAE,KAAKhB,GAAS,UAAAS,GAAU,OAAAF,GAAO,GACnD,CAACV,GAAQG,GAASO,GAAOE,CAAQ,CAAC,GAE/BQ,IAASL,EAA8B,MAAM;AACjD,UAAI,CAACZ,EAAS,QAAO;AAGrB,YAAMkB,IACJrB,MAAW,UAASkB,KAAA,QAAAA,EAAU,WAC1BA,EAAS,mBACTf,GACAmB,IACJtB,MAAW,UAASkB,KAAA,QAAAA,EAAU,WAC1BX,IACCF,KAAeE;AACtB,aAAOgB;AAAA,QACL;AAAA,UACE,QAAAvB;AAAA,UACA,MAAMqB;AAAA,UACN,aAAaC;AAAA,UACb,WAAAd;AAAA,QAAA;AAAA,QAEFQ;AAAA,MAAA;AAAA,IAEJ,GAAG,CAAChB,GAAQG,GAASE,GAAaG,GAAWU,GAAUF,CAAQ,CAAC,GAE1DQ,IAAgBT;AAAA,MACpB,MAAM,IAAI,KAAK,eAAejB,EAAK,UAAU,EAAE,WAAW,QAAQ;AAAA,MAClE,CAACA,EAAK,QAAQ;AAAA,IAAA;AAGhB,IAAA2B,EAAU,MAAM;AACd,MAAAxC,KAAA,QAAAA,EAAiBmC;AAAA,IACnB,GAAG,CAACA,GAAQnC,CAAc,CAAC;AAE3B,UAAMyC,IAAWX,EAAQ,MACnB,CAACxB,KAAgB,CAAC6B,IAAe,OAC9BO,GAAyBP,EAAO,kBAAkB;AAAA,MACvD,GAAG5B;AAAA,MACH,OAAOwB;AAAA,IAAA,CACR,GACA,CAACzB,GAAc6B,GAAQJ,GAAUxB,CAAe,CAAC;AAEpD,WACE,gBAAAoC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAhC;AAAA,QACA,kBAAe;AAAA,QACf,qBAAmBH;AAAA,QACnB,WAAWd,GAAa,EAAE,OAAAe,GAAO,WAAAC,GAAW;AAAA,QAE5C,UAAA;AAAA,UAAA,gBAAAiC;AAAA,YAACC;AAAA,YAAA;AAAA,cACC,OAAOhC,EAAE,gCAAgC;AAAA,cACzC,SAAQ;AAAA,cACR,OAAOG;AAAA,cACP,eAAe,CAAC8B,MAAS7B,EAAU6B,CAAqB;AAAA,cAExD,UAAA;AAAA,gBAAA,gBAAAC,EAACC,KAAM,OAAOnC,EAAE,8BAA8B,GAAG,OAAM,OAAM;AAAA,gBAC7D,gBAAAkC;AAAA,kBAACC;AAAA,kBAAA;AAAA,oBACC,OAAOnC,EAAE,qCAAqC;AAAA,oBAC9C,OAAM;AAAA,kBAAA;AAAA,gBAAA;AAAA,kCAEPmC,GAAA,EAAM,OAAOnC,EAAE,8BAA8B,GAAG,OAAM,MAAA,CAAM;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAG/D,gBAAA+B,EAAC,OAAA,EAAI,WAAU,uEACb,UAAA;AAAA,YAAA,gBAAAG,EAACE,GAAA,EAAU,OAAOpC,EAAEhB,GAAemB,CAAM,CAAC,GACxC,UAAA,gBAAA+B,EAACG,GAAA,EAAW,OAAO/B,GAAS,UAAUC,GAAY,SAASU,GAAO,GACpE;AAAA,YAECd,MAAW,SACV,gBAAA+B;AAAA,cAACE;AAAA,cAAA;AAAA,gBACC,OAAOpC,EAAE,+BAA+B;AAAA,gBACxC,aAAaA,EAAE,mCAAmC;AAAA,gBAElD,UAAA,gBAAAkC;AAAA,kBAACI;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAK;AAAA,oBACL,KAAK;AAAA,oBACL,OAAO9B;AAAA,oBACP,UAAUC;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACZ;AAAA,YAAA;AAAA,YAIHN,MAAW,SACV,gBAAA4B;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,OAAOhC,EAAE,6BAA6B;AAAA,gBACtC,SAAQ;AAAA,gBACR,OAAO,OAAOW,CAAS;AAAA,gBACvB,eAAe,CAACsB,MAASrB,EAAa,OAAOqB,CAAI,CAAc;AAAA,gBAE/D,UAAA;AAAA,kBAAA,gBAAAC,EAACC,KAAM,OAAOnC,EAAE,wBAAwB,GAAG,OAAM,KAAI;AAAA,oCACpDmC,GAAA,EAAM,OAAOnC,EAAE,wBAAwB,GAAG,OAAM,IAAA,CAAI;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UACvD,GAEJ;AAAA,UAEA,gBAAAkC;AAAA,YAACE;AAAA,YAAA;AAAA,cACC,OAAOpC,EAAE,4BAA4B;AAAA,cACrC,aAAaA,EAAE,gCAAgC;AAAA,cAE/C,UAAA,gBAAAkC,EAACG,GAAA,EAAW,OAAOlB,GAAU,UAAU,CAAC,MAAM,KAAKC,EAAY,CAAC,EAAA,CAAG;AAAA,YAAA;AAAA,UAAA;AAAA,UAGpEjB,MAAW,QACV,gBAAA4B,EAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,uEACb,UAAA;AAAA,cAAA,gBAAAG;AAAA,gBAACE;AAAA,gBAAA;AAAA,kBACC,OAAOpC,EAAE,uBAAuB;AAAA,kBAChC,aAAaA,EAAE,2BAA2B;AAAA,kBAE1C,UAAA,gBAAAkC;AAAA,oBAACI;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,KAAK;AAAA,sBACL,MAAM;AAAA,sBACN,OAAOzB;AAAA,sBACP,UAAUC;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACZ;AAAA,cAAA;AAAA,cAEF,gBAAAoB,EAACE,GAAA,EAAU,OAAOpC,EAAE,4BAA4B,GAC9C,UAAA,gBAAAkC;AAAA,gBAACG;AAAA,gBAAA;AAAA,kBACC,OAAOtB;AAAA,kBACP,UAAUC;AAAA,kBACV,SAASC;AAAA,gBAAA;AAAA,cAAA,EACX,CACF;AAAA,YAAA,GACF;AAAA,YACCI,IACC,gBAAAU,EAAC,OAAA,EAAI,WAAU,mEACb,UAAA;AAAA,cAAA,gBAAAG,EAACK,GAAA,EAAM,SAASlB,EAAS,UAAU,YAAY,WAC5C,UAAAA,EAAS,UACNrB,EAAE,6BAA6B;AAAA,gBAC7B,MAAMqB,EAAS;AAAA,cAAA,CAChB,IACDrB,EAAE,8BAA8B,GACtC;AAAA,cACEqB,EAAS,aAIP,OAHF,gBAAAa,EAAC,QAAA,EAAK,WAAU,sCACb,UAAAlC,EAAE,iCAAiC,EAAA,CACtC;AAAA,YACE,EAAA,CACN,IACE;AAAA,UAAA,EAAA,CACN,IACE;AAAA,UAGJ,gBAAAkC,EAAC,KAAA,EAAE,WAAU,cAAa,MAAK,UAAS,aAAU,UAC/C,UAAAX,IACG,GAAGvB,EAAE,uCAAuC,CAAC,KAAK2B,EAAc;AAAA,YAC9DJ,EAAO;AAAA,UAAA,CACR,KAAKvB,EAAE,yCAAyC,CAAC,KAAKA;AAAA,YACrD,+BAA+BuB,EAAO,SAAS;AAAA,UAAA,CAChD,MACD,IACN;AAAA,UAECA,IACC,gBAAAW,EAACM,GAAA,EAAK,SAAQ,YACZ,UAAA,gBAAAN,EAACM,EAAK,MAAL,EAAU,WAAU,kDACnB,UAAA,gBAAAT,EAAC,MAAA,EAAG,WAAU,uEACZ,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,iEACb,UAAA;AAAA,cAAA,gBAAAG,EAAC,MAAA,EAAG,WAAU,uCACX,UAAAlC,EAAE,yCAAyC,GAC9C;AAAA,gCACC,MAAA,EACC,UAAA,gBAAAkC;AAAA,gBAACK;AAAA,gBAAA;AAAA,kBACC,SAASE,GAAwBlB,EAAO,SAAS;AAAA,kBACjD,MAAK;AAAA,kBAEJ,UAAAvB,EAAE,+BAA+BuB,EAAO,SAAS,EAAE;AAAA,gBAAA;AAAA,cAAA,EACtD,CACF;AAAA,YAAA,GACF;AAAA,YACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,cAAA,gBAAAG,EAAC,MAAA,EAAG,WAAU,uCACX,UAAAlC,EAAE,yCAAyC,GAC9C;AAAA,gCACC,MAAA,EAAG,WAAU,gCACX,UAAAuB,EAAO,iBACJvB,EAAE,sCAAsC;AAAA,gBACtC,OAAOuB,EAAO,eAAe;AAAA,gBAC7B,MAAMA,EAAO,eAAe;AAAA,cAAA,CAC7B,IACD,IAAA,CACN;AAAA,YAAA,GACF;AAAA,YACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,cAAA,gBAAAG,EAAC,MAAA,EAAG,WAAU,uCACX,UAAAlC,EAAE,uCAAuC,GAC5C;AAAA,cACA,gBAAAkC,EAAC,QAAG,WAAU,kCACX,YAAc,OAAOX,EAAO,OAAO,EAAA,CACtC;AAAA,YAAA,EAAA,CACF;AAAA,UAAA,EAAA,CACF,EAAA,CACF,GACF,IAEA,gBAAAW,EAAC,OAAE,WAAU,sCACV,UAAAlC,EAAE,yBAAyB,EAAA,CAC9B;AAAA,UAGD6B,IAAW,gBAAAK,EAACQ,IAAA,EAA0B,QAAQb,GAAU,IAAK;AAAA,UAK7DN,MAAWjC,MAAkB,UAAUD,KACtC,gBAAA6C;AAAA,YAACS;AAAA,YAAA;AAAA,cACC,SAASrD;AAAA,cACT,UAAAD;AAAA,cACA,QAAAE;AAAA,cACA,SAAAC;AAAA,cACA,MAAM;AAAA,gBACJ,OAAOQ,EAAE,sBAAsB;AAAA,gBAC/B,MAAM;AAAA,gBACN,WAAW2B,EAAc,OAAOJ,EAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,gBAK9C,gBAAgBqB,GAAwBrB,EAAO,SAAS;AAAA,gBACxD,OAAO9B;AAAA,gBACP,QAAQ;AAAA,kBACN;AAAA;AAAA,oBAEE,MAAM;AAAA,oBACN,OAAOO,EAAE,uCAAuC;AAAA,oBAChD,OAAO2B,EAAc,OAAOJ,EAAO,OAAO;AAAA,kBAAA;AAAA,kBAE5C;AAAA;AAAA,oBAEE,MAAM;AAAA,oBACN,OAAOvB,EAAE,yCAAyC;AAAA,oBAClD,OAAOuB,EAAO,iBACVvB,EAAE,sCAAsC;AAAA,sBACtC,OAAOuB,EAAO,eAAe;AAAA,sBAC7B,MAAMA,EAAO,eAAe;AAAA,oBAAA,CAC7B,IACD;AAAA,kBAAA;AAAA,kBAEN;AAAA;AAAA,oBAEE,MAAM;AAAA,oBACN,OAAOvB,EAAE,yCAAyC;AAAA,oBAClD,OAAOA,EAAE,+BAA+BuB,EAAO,SAAS,EAAE;AAAA,kBAAA;AAAA;AAAA;AAAA,kBAI5D,GAAIM,IACAgB;AAAA,oBAA0BhB;AAAA,oBAAU7B;AAAA,oBAAG,CAAC,MACtC2B,EAAc,OAAO,CAAC;AAAA,kBAAA,IAExB,CAAA;AAAA,gBAAC;AAAA,cACP;AAAA,YACF;AAAA,UAAA,IAEA;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEA1C,GAAkB,cAAc;"}
@@ -11,7 +11,7 @@ import { S as se } from "./switch-BJ6HD3Mn.js";
11
11
  import { C as R } from "./card-DPmk26CL.js";
12
12
  import { B as T } from "./badge-zsf5i5bH.js";
13
13
  import { I as ie } from "./insert-result-DNdi_JYW.js";
14
- import { c as ne, g as oe, e as re, f as de, A as ce, h as me, i as ge, G as ue } from "./antenatal-schedule-timeline-Dg0m0yFl.js";
14
+ import { c as ne, g as oe, e as re, f as de, A as ce, h as me, i as ge, G as ue } from "./antenatal-schedule-timeline-CdiqkF05.js";
15
15
  import { s as he } from "./subDays-Bs00akhK.js";
16
16
  import { i as pe } from "./date-picker-variants-CXEAx3O_.js";
17
17
  const fe = ae("ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]", {
@@ -308,4 +308,4 @@ ve.displayName = "GestationalAgeCalculator";
308
308
  export {
309
309
  ve as G
310
310
  };
311
- //# sourceMappingURL=gestational-age-calculator-DbDfTJU2.js.map
311
+ //# sourceMappingURL=gestational-age-calculator-Bc55hq6t.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gestational-age-calculator-Bc55hq6t.js","sources":["../../src/components/gestational-age-calculator/gestational-age-calculator.tsx"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* GestationalAgeCalculator — current gestational age, trimester and */\n/* milestone dates, from either a known LMP or a known due date. */\n/* */\n/* Reuses the shared `gestation` maths from due-date-calculator: GA day */\n/* 0 is the LMP; from an EDD we back out LMP = EDD − 280 days. */\n/* ------------------------------------------------------------------ */\n\nimport { forwardRef, useEffect, useMemo, useState } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { subDays, isAfter } from 'date-fns';\nimport { RadioGroup, Radio } from '../radio-group';\nimport { FormField } from '../form-field';\nimport { DatePicker } from '../date-picker';\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 Trimester,\n type GestationalAge,\n type Plurality,\n type Chorionicity,\n computeDueDate,\n gestationalMilestones,\n GESTATION_DAYS,\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\ntype DateMethod = 'lmp' | 'edd';\n\nexport interface GestationalAgeResult {\n gestationalAge: GestationalAge | null;\n trimester: Trimester;\n dueDate: Date;\n}\n\nexport interface GestationalAgeCalculatorProps extends VariantProps<\n typeof rootVariants\n> {\n /** Whether the input date is the last period (`lmp`) or the due date (`edd`). */\n defaultMethod?: DateMethod;\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: GestationalAgeResult | null) => void;\n /** When provided, shows the result-action buttons that emit / copy the result. */\n onInsert?: (payload: InsertPayload) => void;\n /**\n * Which verb the result button performs. Defaults to `'insert'`.\n * Use `'copy'` in an app-shell surface (no editor to insert into) — the\n * button writes the result to the clipboard as a multi-format `ClipboardItem`.\n */\n insertVariant?: InsertVariant;\n /** `copy` variant only — fired after a successful clipboard write. */\n onCopy?: (mode: InsertMode) => void;\n /** `copy` variant only — fired if the clipboard write can't proceed. */\n onError?: (error: unknown) => void;\n /**\n * Brand wordmark printed in the inserted/copied result-card footer.\n * Omitted → no brand line (and no footer hairline); a string → that custom\n * brand; `false` → no brand line. Brand is opt-in.\n */\n insertBrand?: string | false;\n /**\n * Append the antenatal exam schedule (the time-sensitive screening windows)\n * below the result, dated from the computed gestational start, and reveal the\n * plurality / chorionicity inputs that drive it.\n */\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\n/**\n * @deprecated Superseded by `PregnancyDating`, which unifies the due-date and\n * gestational-age calculators (any anchor → both EDD and current GA) and adds a\n * manual ±days dating adjustment. This component will be removed in a future\n * release; migrate to `PregnancyDating` (`defaultMethod=\"edd\"` for the\n * date-back-from-EDD flow).\n */\nexport const GestationalAgeCalculator = forwardRef<\n HTMLDivElement,\n GestationalAgeCalculatorProps\n>(\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<DateMethod>(defaultMethod);\n const [refDate, setRefDate] = useState<Date | undefined>(\n defaultReferenceDate,\n );\n // The date the result is evaluated against (\"as of\"); defaults to today but\n // can be a future appointment date to project the GA/schedule forward.\n const [asOfDate, setAsOfDate] = useState<Date>(() => new Date());\n // Real today — caps the dating-anchor input (an LMP can't be in the future).\n const today = useMemo(() => 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 const data = useMemo(() => {\n if (!refDate) return null;\n // Normalise to an LMP, then reuse the shared gestation maths.\n const lmp = method === 'lmp' ? refDate : subDays(refDate, GESTATION_DAYS);\n const r = computeDueDate({ method: 'lmp', date: lmp }, asOfDate);\n return {\n result: {\n gestationalAge: r.gestationalAge,\n trimester: r.trimester,\n dueDate: r.dueDate,\n } satisfies GestationalAgeResult,\n milestones: gestationalMilestones(r.gestationalStart),\n gestationalStart: r.gestationalStart,\n };\n }, [method, refDate, asOfDate]);\n\n const schedule = useMemo(() => {\n if (!showSchedule || !data) return null;\n return computeAntenatalSchedule(data.gestationalStart, {\n ...scheduleOptions,\n today: asOfDate,\n plurality,\n chorionicity,\n rhNegative,\n gdmRisk: gdmRisk === 'none' ? undefined : gdmRisk,\n });\n }, [\n showSchedule,\n data,\n asOfDate,\n scheduleOptions,\n plurality,\n chorionicity,\n rhNegative,\n gdmRisk,\n ]);\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 dateFormatter = useMemo(\n () => new Intl.DateTimeFormat(i18n.language, { dateStyle: 'medium' }),\n [i18n.language],\n );\n\n useEffect(() => {\n onResultChange?.(data?.result ?? null);\n }, [data, onResultChange]);\n\n const gaText = (ga: GestationalAge | null): string =>\n ga\n ? t('gestationalAgeCalculator.gestation', {\n weeks: ga.weeks,\n days: ga.days,\n })\n : '—';\n\n return (\n <div\n ref={ref}\n data-component=\"gestational-age-calculator\"\n data-component-id={id}\n className={rootVariants({ width, className })}\n >\n <RadioGroup\n label={t('gestationalAgeCalculator.method.label')}\n variant=\"horizontal\"\n value={method}\n onValueChange={(next) => setMethod(next as DateMethod)}\n >\n <Radio label={t('gestationalAgeCalculator.method.lmp')} value=\"lmp\" />\n <Radio label={t('gestationalAgeCalculator.method.edd')} value=\"edd\" />\n </RadioGroup>\n\n <FormField\n label={t(\n method === 'lmp'\n ? 'gestationalAgeCalculator.lmpDate'\n : 'gestationalAgeCalculator.eddDate',\n )}\n >\n <DatePicker\n value={refDate}\n onChange={setRefDate}\n maxDate={method === 'lmp' ? today : undefined}\n />\n </FormField>\n\n <FormField\n label={t('gestationalAgeCalculator.asOfDate')}\n description={t('gestationalAgeCalculator.asOfDateHint')}\n >\n <DatePicker value={asOfDate} onChange={(d) => d && setAsOfDate(d)} />\n </FormField>\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 {data\n ? `${t('gestationalAgeCalculator.gestationLabel')}: ${gaText(\n data.result.gestationalAge,\n )}. ${t('gestationalAgeCalculator.trimesterLabel')}: ${t(\n `gestationalAgeCalculator.trimester.${data.result.trimester}`,\n )}.`\n : ''}\n </p>\n\n {data ? (\n <Card variant=\"elevated\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <dl className=\"ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-md)] ds:sm:grid-cols-2\">\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('gestationalAgeCalculator.trimesterLabel')}\n </dt>\n <dd>\n <Badge\n variant={TRIMESTER_BADGE_VARIANT[data.result.trimester]}\n size=\"lg\"\n >\n {t(\n `gestationalAgeCalculator.trimester.${data.result.trimester}`,\n )}\n </Badge>\n </dd>\n </div>\n <div className=\"ds:flex ds:flex-col ds:items-end ds:gap-[var(--spacing-xs)] ds:text-end\">\n <dt className=\"type-label ds:text-muted-foreground\">\n {t('gestationalAgeCalculator.gestationLabel')}\n </dt>\n <dd className=\"type-metric ds:text-foreground\">\n {gaText(data.result.gestationalAge)}\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('gestationalAgeCalculator.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(`gestationalAgeCalculator.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 {dateFormatter.format(m.date)}\n </span>\n {reached ? (\n <Badge variant=\"success\">\n {t('gestationalAgeCalculator.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('gestationalAgeCalculator.empty')}\n </p>\n )}\n\n {schedule ? <AntenatalScheduleTimeline events={schedule} /> : null}\n\n {/* One result-action group for the whole result — sits after both the\n gestational-age card and the schedule, and its payload carries the\n schedule rows when shown (no per-card buttons). */}\n {data && (insertVariant === 'copy' || onInsert) ? (\n <InsertButton\n onInsert={onInsert}\n variant={insertVariant}\n onCopy={onCopy}\n onError={onError}\n card={{\n title: t('insert.title.gestationalAge'),\n icon: 'baby',\n highlight: t(\n `gestationalAgeCalculator.trimester.${data.result.trimester}`,\n ),\n // Chip shares the trimester's semantic token so the inserted PNG\n // chip matches the on-screen trimester badge — with the\n // contrast-safe orange override for the `--warning` third trimester.\n highlightToken: trimesterHighlightToken(data.result.trimester),\n brand: insertBrand,\n fields: [\n {\n // Gestational age is an elapsed duration → clock glyph.\n icon: 'clock',\n label: t('gestationalAgeCalculator.gestationLabel'),\n value: gaText(data.result.gestationalAge),\n },\n {\n // Trimester is a clinical-stage classification → tag.\n icon: 'tag',\n label: t('gestationalAgeCalculator.trimesterLabel'),\n value: t(\n `gestationalAgeCalculator.trimester.${data.result.trimester}`,\n ),\n },\n // When the schedule is shown, the single Insert button carries\n // the exam windows too (no second button).\n ...(schedule\n ? buildScheduleInsertFields(schedule, t, (d) =>\n dateFormatter.format(d),\n )\n : []),\n ],\n }}\n />\n ) : null}\n </div>\n );\n },\n);\n\nGestationalAgeCalculator.displayName = 'GestationalAgeCalculator';\n"],"names":["rootVariants","cva","GestationalAgeCalculator","forwardRef","defaultMethod","defaultReferenceDate","onResultChange","onInsert","insertVariant","onCopy","onError","insertBrand","showSchedule","defaultPlurality","defaultChorionicity","defaultRhNegative","defaultGdmRisk","scheduleOptions","id","width","className","ref","t","i18n","useTranslation","method","setMethod","useState","refDate","setRefDate","asOfDate","setAsOfDate","today","useMemo","plurality","setPlurality","chorionicity","setChorionicity","rhNegative","setRhNegative","gdmRisk","setGdmRisk","data","lmp","subDays","GESTATION_DAYS","r","computeDueDate","gestationalMilestones","schedule","computeAntenatalSchedule","chorionicityOptions","c","dateFormatter","useEffect","gaText","ga","jsxs","RadioGroup","next","jsx","Radio","FormField","DatePicker","d","Fragment","Select","Switch","Card","Badge","TRIMESTER_BADGE_VARIANT","m","reached","isAfter","AntenatalScheduleTimeline","InsertButton","trimesterHighlightToken","buildScheduleInsertFields"],"mappings":"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"}