@alfadocs/ui-kit-debug 1.101.0 → 1.102.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 (48) hide show
  1. package/dist/_chunks/{calendar-appointment-editor-dialog-CUJMnFL7.js → calendar-appointment-editor-dialog-EYyVorFR.js} +3 -3
  2. package/dist/_chunks/{calendar-appointment-editor-dialog-CUJMnFL7.js.map → calendar-appointment-editor-dialog-EYyVorFR.js.map} +1 -1
  3. package/dist/_chunks/{care-plan-header-BBh0X7EO.js → care-plan-header-lROoTjYn.js} +2 -2
  4. package/dist/_chunks/{care-plan-header-BBh0X7EO.js.map → care-plan-header-lROoTjYn.js.map} +1 -1
  5. package/dist/_chunks/{contact-profile-card-CFAhByRk.js → contact-profile-card-D0KqxoE5.js} +37 -35
  6. package/dist/_chunks/{contact-profile-card-CFAhByRk.js.map → contact-profile-card-D0KqxoE5.js.map} +1 -1
  7. package/dist/_chunks/{key-value-pair-BoXOtBL1.js → key-value-pair-CB37UXsz.js} +43 -28
  8. package/dist/_chunks/key-value-pair-CB37UXsz.js.map +1 -0
  9. package/dist/_chunks/{patient-summary-card-CL04aq8h.js → patient-summary-card-B1jvxdY8.js} +2 -2
  10. package/dist/_chunks/{patient-summary-card-CL04aq8h.js.map → patient-summary-card-B1jvxdY8.js.map} +1 -1
  11. package/dist/_chunks/{payment-request-card-BbpN8GQg.js → payment-request-card-DPN5yklX.js} +2 -2
  12. package/dist/_chunks/{payment-request-card-BbpN8GQg.js.map → payment-request-card-DPN5yklX.js.map} +1 -1
  13. package/dist/_chunks/{periodontal-chart-Cw-ZsIls.js → periodontal-chart-X4_4WPK8.js} +2 -2
  14. package/dist/_chunks/{periodontal-chart-Cw-ZsIls.js.map → periodontal-chart-X4_4WPK8.js.map} +1 -1
  15. package/dist/_chunks/{periodontal-chart-card-CG8mxR62.js → periodontal-chart-card-BzL3YkEW.js} +2 -2
  16. package/dist/_chunks/{periodontal-chart-card-CG8mxR62.js.map → periodontal-chart-card-BzL3YkEW.js.map} +1 -1
  17. package/dist/_chunks/{specialty-icon-KuovHTxh.js → specialty-icon-BkpExzMh.js} +2 -1
  18. package/dist/_chunks/{specialty-icon-KuovHTxh.js.map → specialty-icon-BkpExzMh.js.map} +1 -1
  19. package/dist/_chunks/specialty-list-BzalHR8_.js +100 -0
  20. package/dist/_chunks/specialty-list-BzalHR8_.js.map +1 -0
  21. package/dist/_chunks/{use-appointment-details-read-BbIoPWO6.js → use-appointment-details-read-BNtTap_B.js} +2 -2
  22. package/dist/_chunks/{use-appointment-details-read-BbIoPWO6.js.map → use-appointment-details-read-BNtTap_B.js.map} +1 -1
  23. package/dist/_chunks/{workflow-map-k-dQkpe7.js → workflow-map-Dm27iPKB.js} +2 -2
  24. package/dist/_chunks/{workflow-map-k-dQkpe7.js.map → workflow-map-Dm27iPKB.js.map} +1 -1
  25. package/dist/agent-catalog.json +1 -1
  26. package/dist/components/appointment-details-panel/index.js +1 -1
  27. package/dist/components/care-plan-header/index.js +1 -1
  28. package/dist/components/contact-profile-card/contact-profile-card.d.ts.map +1 -1
  29. package/dist/components/contact-profile-card/index.js +1 -1
  30. package/dist/components/key-value-pair/index.js +1 -1
  31. package/dist/components/key-value-pair/key-value-pair.d.ts.map +1 -1
  32. package/dist/components/patient-summary-card/index.js +1 -1
  33. package/dist/components/payment-card/index.js +1 -1
  34. package/dist/components/periodontal-chart/index.js +1 -1
  35. package/dist/components/periodontal-chart-card/index.js +1 -1
  36. package/dist/components/specialty-icon/index.js +1 -1
  37. package/dist/components/specialty-icon/specialty-icon.d.ts.map +1 -1
  38. package/dist/components/specialty-list/index.js +1 -1
  39. package/dist/components/specialty-list/specialty-list.d.ts.map +1 -1
  40. package/dist/components/workflow/index.js +1 -1
  41. package/dist/core.css +1 -1
  42. package/dist/index.js +12 -12
  43. package/dist/patterns/calendar/index.js +1 -1
  44. package/dist/tokens.css +1 -1
  45. package/package.json +1 -1
  46. package/dist/_chunks/key-value-pair-BoXOtBL1.js.map +0 -1
  47. package/dist/_chunks/specialty-list-urUQJLk3.js +0 -67
  48. package/dist/_chunks/specialty-list-urUQJLk3.js.map +0 -1
@@ -4,7 +4,7 @@ import { c as R } from "./index-D2ZczOXr.js";
4
4
  import { useTranslation as ae } from "react-i18next";
5
5
  import { B as re } from "./badge-BUk4RjTS.js";
6
6
  import { C as S } from "./card-C85_Ndhb.js";
7
- import { K as ne, a as se } from "./key-value-pair-BoXOtBL1.js";
7
+ import { K as ne, a as se } from "./key-value-pair-CB37UXsz.js";
8
8
  import { u as oe } from "./registry-DvAUVLHh.js";
9
9
  const de = {
10
10
  id: "periodontal-chart-card",
@@ -452,4 +452,4 @@ export {
452
452
  he as a,
453
453
  de as p
454
454
  };
455
- //# sourceMappingURL=periodontal-chart-card-CG8mxR62.js.map
455
+ //# sourceMappingURL=periodontal-chart-card-BzL3YkEW.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"periodontal-chart-card-CG8mxR62.js","sources":["../../src/components/periodontal-chart-card/periodontal-chart-card.agent.ts","../../src/components/periodontal-chart-card/periodontal-chart-card.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { PeriodontalChartCardHandle } from './periodontal-chart-card';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalChartCard — agent adapter */\n/* */\n/* Read-only clinical chart. The handle returns STRUCTURAL state only — */\n/* the set of charted FDI tooth ids, how many probing sites breach the */\n/* 4mm / 6mm thresholds, and the chart date. NEVER patient identity, */\n/* names, or any free-text PHI — the chart never holds those. */\n/* -------------------------------------------------------------------- */\n\nexport const periodontalChartCardAgent: AgentAdapter<PeriodontalChartCardHandle> =\n {\n id: 'periodontal-chart-card',\n capabilities: [],\n state: {\n toothIds: {\n type: 'string[]',\n descriptionKey: 'ui.agent.periodontalChartCard.state.toothIds',\n description:\n 'FDI ids of the teeth currently charted. Tooth identifiers only — no patient identity.',\n read: (handle) => handle.getToothIds(),\n },\n siteCount: {\n type: 'number',\n descriptionKey: 'ui.agent.periodontalChartCard.state.siteCount',\n description: 'Total number of probing sites rendered.',\n read: (handle) => handle.getSiteCount(),\n },\n deepPocketCount: {\n type: 'number',\n descriptionKey: 'ui.agent.periodontalChartCard.state.deepPocketCount',\n description:\n 'Number of sites with a probing depth at or above the 6mm severe threshold.',\n read: (handle) => handle.getDeepPocketCount(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'periodontal-chart-card',\n description: 'Marks the PeriodontalChartCard root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n };\n","import {\n forwardRef,\n useId,\n useMemo,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '../badge/badge';\nimport { Card } from '../card/card';\nimport { KeyValueList, KeyValuePair } from '../key-value-pair/key-value-pair';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { periodontalChartCardAgent } from './periodontal-chart-card.agent';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalChartCard */\n/* */\n/* A DISPLAY-ONLY periodontal (gum) chart. There is no kit equivalent — */\n/* the dental ToothScheme charts caries/restorations per tooth, whereas */\n/* a perio chart records probing measurements per SITE (6 sites/tooth): */\n/* pocket depth (PD), gingival recession (REC), bleeding on probing */\n/* (BoP), suppuration, and tooth mobility. */\n/* */\n/* It renders a compact per-quadrant TABLE (real <table>/<th> semantics */\n/* + scope + caption — NOT a colour-only grid) of teeth x sites. Pocket */\n/* depths >= 4mm are flagged with the warning token, >= 6mm with the */\n/* destructive token, and EACH flag also carries a non-colour cue */\n/* (bold weight + an asterisk / double-asterisk) so the severity is */\n/* legible without colour. Bleeding and suppuration render as small */\n/* glyphs WITH an accessible per-cell label. */\n/* */\n/* The component owns no editing affordance — it is a passive read */\n/* surface for a chart captured elsewhere. */\n/* */\n/* All visible text flows through `useTranslation('ui')` against the */\n/* `periodontalChartCard.*` namespace. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n // Matches the kit's other `surface` props. `elevated` wraps in\n // `<Card variant=\"elevated\">`; `flat` drops the chrome for use\n // inside an existing Card / Sheet.\n surface: {\n flat: '',\n elevated: '',\n },\n },\n defaultVariants: { surface: 'elevated' },\n});\n\n// Per-measurement-cell severity. The colour is paired with a weight bump\n// so the flag survives greyscale / forced-colors — colour is never the\n// sole cue (the asterisk in the cell content carries the same signal).\nconst measureVariants = cva(\n 'ds:[font-variant-numeric:var(--font-feature-tabular)] ds:tabular-nums',\n {\n variants: {\n severity: {\n normal: 'ds:text-[color:var(--foreground)]',\n moderate: 'ds:font-semibold ds:text-[color:var(--warning-foreground)]',\n severe: 'ds:font-bold ds:text-[color:var(--destructive)]',\n },\n },\n defaultVariants: { severity: 'normal' },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* Constants */\n/* -------------------------------------------------------------------- */\n\n/** Probing depth (mm) at/above which a site is flagged moderate. */\nconst MODERATE_POCKET_MM = 4;\n/** Probing depth (mm) at/above which a site is flagged severe. */\nconst SEVERE_POCKET_MM = 6;\n\n/** The six standard probing sites, in buccal-then-lingual display order. */\nexport const PERIODONTAL_SITE_ORDER = [\n 'db',\n 'b',\n 'mb',\n 'dl',\n 'l',\n 'ml',\n] as const;\n\nexport type PeriodontalSiteId = (typeof PERIODONTAL_SITE_ORDER)[number];\n\n/** English fallback labels for the six probing sites (belt-and-braces). */\nconst SITE_DEFAULT: Record<PeriodontalSiteId, string> = {\n db: 'Disto-buccal',\n b: 'Buccal',\n mb: 'Mesio-buccal',\n dl: 'Disto-lingual',\n l: 'Lingual',\n ml: 'Mesio-lingual',\n};\n\n/** FDI quadrant ids (first digit of the FDI tooth number). */\nconst QUADRANT_ORDER = ['1', '2', '3', '4'] as const;\ntype QuadrantId = (typeof QUADRANT_ORDER)[number];\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** One probing-site reading. */\nexport interface PeriodontalSite {\n /** FDI tooth number, e.g. `'11'`, `'46'`. */\n tooth: string;\n /** Probing site: mesio-/disto- buccal/lingual, mid buccal/lingual. */\n site: PeriodontalSiteId;\n /** Pocket depth in millimetres. */\n pocketDepthMm?: number;\n /** Gingival recession in millimetres. */\n recessionMm?: number;\n /** Bleeding on probing at this site. */\n bleeding?: boolean;\n /** Suppuration (pus) at this site. */\n suppuration?: boolean;\n}\n\n/** Aggregate chart summary, consumer-supplied. */\nexport interface PeriodontalChartSummary {\n /** Whole-mouth mean probing depth in millimetres. */\n meanPocketDepthMm?: number;\n /** Bleeding-on-probing as a percentage of sites (0–100). */\n bleedingOnProbingPercent?: number;\n}\n\n/** Tooth-mobility grade (Miller 0–3). */\nexport type PeriodontalMobility = 0 | 1 | 2 | 3;\n\n/** Imperative handle — structural state only, never PHI. */\nexport interface PeriodontalChartCardHandle {\n /** FDI ids of the charted teeth, in display order. */\n getToothIds: () => string[];\n /** Total probing sites rendered. */\n getSiteCount: () => number;\n /** Count of sites at/above the 6mm severe threshold. */\n getDeepPocketCount: () => number;\n}\n\nexport interface PeriodontalChartCardProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children'\n> {\n /** Probing-site readings. Sites are grouped per tooth automatically. */\n sites: PeriodontalSite[];\n /**\n * ISO-8601 date the chart was captured. Rendered as a localised date in\n * the header and exposed as the table caption context. Optional.\n */\n dateIso?: string;\n /**\n * Dentition the chart covers. Drives only the localised header label —\n * tooth grouping is derived from the FDI numbers in `sites`.\n */\n dentition?: 'permanent' | 'primary' | 'mixed';\n /** Per-tooth Miller mobility grade, keyed by FDI tooth number. */\n mobility?: Record<string, PeriodontalMobility>;\n /** Aggregate summary stats rendered above the per-quadrant tables. */\n summary?: PeriodontalChartSummary;\n\n /* ----- i18n / formatting ----- */\n\n /** Locale for date + number formatting. Falls back to `i18n.language`. */\n locale?: string;\n\n /* ----- Styling ----- */\n\n /**\n * `'elevated'` (default) wraps in `<Card variant=\"elevated\">`. `'flat'`\n * drops the Card — use inside another card / sheet.\n */\n surface?: 'flat' | 'elevated';\n\n /* ----- a11y ----- */\n\n /** Override the default region aria-label. */\n 'aria-label'?: string;\n /** Agent-readiness consumer id, surfaced as `data-component-id`. */\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\n/** Classify a pocket depth into a severity band. */\nfunction pocketSeverity(\n depth: number | undefined,\n): 'normal' | 'moderate' | 'severe' {\n if (depth == null || !Number.isFinite(depth)) return 'normal';\n if (depth >= SEVERE_POCKET_MM) return 'severe';\n if (depth >= MODERATE_POCKET_MM) return 'moderate';\n return 'normal';\n}\n\n/** Non-colour severity cue appended to the measurement (`''`/`*`/`**`). */\nfunction severityMarker(severity: 'normal' | 'moderate' | 'severe'): string {\n if (severity === 'severe') return '∗∗';\n if (severity === 'moderate') return '∗';\n return '';\n}\n\n/** FDI quadrant (first digit) of a tooth number, or null if unparseable. */\nfunction quadrantOf(tooth: string): QuadrantId | null {\n const first = tooth.trim().charAt(0);\n return (QUADRANT_ORDER as readonly string[]).includes(first)\n ? (first as QuadrantId)\n : null;\n}\n\ninterface ToothRow {\n tooth: string;\n sites: Partial<Record<PeriodontalSiteId, PeriodontalSite>>;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const PeriodontalChartCard = forwardRef<\n HTMLDivElement,\n PeriodontalChartCardProps\n>(\n (\n {\n sites,\n dateIso,\n dentition = 'permanent',\n mobility,\n summary,\n locale,\n surface = 'elevated',\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const headingId = useId();\n const resolvedLocale = locale ?? i18n.language ?? 'en';\n\n // Group sites by tooth, then bucket teeth into FDI quadrants. The\n // grouping is derived purely from the FDI numbers — the consumer\n // passes a flat site list and the kit owns the layout.\n const { quadrants, toothIds, siteCount, deepPocketCount } = useMemo(() => {\n const byTooth = new Map<string, ToothRow>();\n let sCount = 0;\n let deep = 0;\n for (const site of sites) {\n sCount += 1;\n if ((site.pocketDepthMm ?? 0) >= SEVERE_POCKET_MM) deep += 1;\n let row = byTooth.get(site.tooth);\n if (!row) {\n row = { tooth: site.tooth, sites: {} };\n byTooth.set(site.tooth, row);\n }\n row.sites[site.site] = site;\n }\n\n // Sort teeth within a quadrant by their FDI position digit (2nd\n // char) ascending; keep insertion order as a stable fallback.\n const rows = Array.from(byTooth.values());\n const grouped: Array<{\n quadrant: QuadrantId | null;\n teeth: ToothRow[];\n }> = QUADRANT_ORDER.map((q) => ({\n quadrant: q as QuadrantId | null,\n teeth: rows\n .filter((r) => quadrantOf(r.tooth) === q)\n .sort((a, b) => a.tooth.localeCompare(b.tooth, 'en')),\n })).filter((g) => g.teeth.length > 0);\n\n // Teeth with an unparseable FDI quadrant render in their own group\n // so nothing is silently dropped.\n const unassigned = rows.filter((r) => quadrantOf(r.tooth) === null);\n if (unassigned.length > 0) {\n grouped.push({ quadrant: null, teeth: unassigned });\n }\n\n const ids = grouped.flatMap((g) => g.teeth.map((tt) => tt.tooth));\n return {\n quadrants: grouped,\n toothIds: ids,\n siteCount: sCount,\n deepPocketCount: deep,\n };\n }, [sites]);\n\n useAgentRegistration(\n periodontalChartCardAgent,\n {\n getToothIds: () => toothIds,\n getSiteCount: () => siteCount,\n getDeepPocketCount: () => deepPocketCount,\n },\n id,\n );\n\n const formattedDate = useMemo(() => {\n if (!dateIso) return undefined;\n const parsed = new Date(dateIso);\n if (Number.isNaN(parsed.getTime())) return undefined;\n try {\n return new Intl.DateTimeFormat(resolvedLocale, {\n dateStyle: 'medium',\n }).format(parsed);\n } catch {\n return parsed.toISOString().slice(0, 10);\n }\n }, [dateIso, resolvedLocale]);\n\n const resolvedHeading = t(\n 'periodontalChartCard.heading',\n 'Periodontal chart',\n );\n const resolvedAriaLabel = ariaLabel ?? resolvedHeading;\n\n const DENTITION_DEFAULT: Record<typeof dentition, string> = {\n permanent: 'Permanent dentition',\n primary: 'Primary dentition',\n mixed: 'Mixed dentition',\n };\n const dentitionLabel = t(`periodontalChartCard.dentition.${dentition}`, {\n defaultValue: DENTITION_DEFAULT[dentition],\n });\n\n const formatNumber = (n: number): string => {\n try {\n return new Intl.NumberFormat(resolvedLocale, {\n maximumFractionDigits: 1,\n }).format(n);\n } catch {\n return String(n);\n }\n };\n\n /* ------------------------------------------------------------ */\n /* Summary rows */\n /* ------------------------------------------------------------ */\n\n const summaryRows: Array<{ key: string; label: string; value: ReactNode }> =\n [];\n if (summary?.meanPocketDepthMm != null) {\n summaryRows.push({\n key: 'meanPocketDepth',\n label: t(\n 'periodontalChartCard.summary.meanPocketDepth',\n 'Mean probing depth',\n ),\n value: t('periodontalChartCard.unit.mm', {\n value: formatNumber(summary.meanPocketDepthMm),\n defaultValue: '{{value}} mm',\n }),\n });\n }\n if (summary?.bleedingOnProbingPercent != null) {\n summaryRows.push({\n key: 'bleedingOnProbing',\n label: t(\n 'periodontalChartCard.summary.bleedingOnProbing',\n 'Bleeding on probing',\n ),\n value: t('periodontalChartCard.unit.percent', {\n value: formatNumber(summary.bleedingOnProbingPercent),\n defaultValue: '{{value}}%',\n }),\n });\n }\n\n /* ------------------------------------------------------------ */\n /* Render a single measurement cell */\n /* ------------------------------------------------------------ */\n\n const renderMeasure = (\n depth: number | undefined,\n kind: 'pocket' | 'recession',\n ): ReactNode => {\n if (depth == null || !Number.isFinite(depth)) {\n return (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n );\n }\n const severity = kind === 'pocket' ? pocketSeverity(depth) : 'normal';\n const marker = kind === 'pocket' ? severityMarker(severity) : '';\n const numeric = formatNumber(depth);\n // The flag is announced as a worded suffix for SR users; sighted\n // users get the colour + bold + asterisk. The asterisk itself is\n // aria-hidden so it isn't read as punctuation.\n const srSuffix =\n severity === 'severe'\n ? ` ${t('periodontalChartCard.flag.severe', 'severe pocket')}`\n : severity === 'moderate'\n ? ` ${t('periodontalChartCard.flag.moderate', 'moderate pocket')}`\n : '';\n return (\n <span className={measureVariants({ severity })}>\n <span>{numeric}</span>\n {marker ? <span aria-hidden=\"true\">{marker}</span> : null}\n {srSuffix ? <span className=\"ds:sr-only\">{srSuffix}</span> : null}\n </span>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* Render bleeding / suppuration indicator cell */\n /* ------------------------------------------------------------ */\n\n const renderSigns = (site: PeriodontalSite | undefined): ReactNode => {\n if (!site || (!site.bleeding && !site.suppuration)) {\n return (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n );\n }\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n {site.bleeding ? (\n <span\n role=\"img\"\n aria-label={t(\n 'periodontalChartCard.sign.bleeding',\n 'Bleeding on probing',\n )}\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--destructive)]\"\n />\n ) : null}\n {site.suppuration ? (\n <span\n role=\"img\"\n aria-label={t(\n 'periodontalChartCard.sign.suppuration',\n 'Suppuration',\n )}\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--warning)]\"\n />\n ) : null}\n </span>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* One quadrant table */\n /* ------------------------------------------------------------ */\n\n const renderQuadrant = (group: {\n quadrant: QuadrantId | null;\n teeth: ToothRow[];\n }): ReactNode => {\n const QUADRANT_DEFAULT: Record<QuadrantId, string> = {\n '1': 'Upper right (Q1)',\n '2': 'Upper left (Q2)',\n '3': 'Lower left (Q3)',\n '4': 'Lower right (Q4)',\n };\n const captionText =\n group.quadrant != null\n ? t(`periodontalChartCard.quadrant.${group.quadrant}`, {\n defaultValue: QUADRANT_DEFAULT[group.quadrant],\n })\n : t('periodontalChartCard.quadrant.other', 'Other teeth');\n const cellClass =\n 'ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-center ds:border-b ds:border-[color:var(--border)]';\n const rowHeaderClass =\n 'ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-start ds:font-medium ds:border-b ds:border-[color:var(--border)] ds:whitespace-nowrap';\n return (\n <div\n key={group.quadrant ?? 'other'}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:overflow-x-auto\"\n >\n <table className=\"type-body-sm ds:w-full ds:border-collapse\">\n <caption className=\"type-label ds:text-start ds:mb-[var(--spacing-2xs)] ds:text-[color:var(--muted-foreground)]\">\n {captionText}\n </caption>\n <thead>\n <tr>\n <th\n scope=\"col\"\n className=\"ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-start ds:border-b ds:border-[color:var(--border)]\"\n >\n {t('periodontalChartCard.column.measure', 'Measurement')}\n </th>\n {group.teeth.map((row) => (\n <th\n key={row.tooth}\n scope=\"col\"\n data-tooth-id={row.tooth}\n className=\"ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-center ds:border-b ds:border-[color:var(--border)] ds:[font-variant-numeric:var(--font-feature-tabular)] ds:tabular-nums\"\n >\n <span className=\"ds:sr-only\">\n {t('periodontalChartCard.toothHeader', {\n tooth: row.tooth,\n defaultValue: 'Tooth {{tooth}}',\n })}\n </span>\n <span aria-hidden=\"true\">{row.tooth}</span>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {/* Pocket depth row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t(\n 'periodontalChartCard.row.pocketDepth',\n 'Pocket depth (PD)',\n )}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:items-center ds:justify-center ds:gap-[var(--spacing-2xs)]\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId} className=\"ds:sr-only\">\n {t(`periodontalChartCard.site.${siteId}`, {\n defaultValue: SITE_DEFAULT[siteId],\n })}\n </span>\n ))}\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)]\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderMeasure(\n row.sites[siteId]?.pocketDepthMm,\n 'pocket',\n )}\n </span>\n ))}\n </span>\n </span>\n </td>\n ))}\n </tr>\n {/* Recession row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t('periodontalChartCard.row.recession', 'Recession (REC)')}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)] ds:justify-center\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderMeasure(\n row.sites[siteId]?.recessionMm,\n 'recession',\n )}\n </span>\n ))}\n </span>\n </td>\n ))}\n </tr>\n {/* Bleeding / suppuration row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t(\n 'periodontalChartCard.row.signs',\n 'Bleeding / suppuration',\n )}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)] ds:justify-center\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderSigns(row.sites[siteId])}\n </span>\n ))}\n </span>\n </td>\n ))}\n </tr>\n {/* Mobility row — only when any tooth in the quadrant has a grade */}\n {mobility &&\n group.teeth.some((row) => mobility[row.tooth] != null) ? (\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t('periodontalChartCard.row.mobility', 'Mobility')}\n </th>\n {group.teeth.map((row) => {\n const grade = mobility[row.tooth];\n return (\n <td key={row.tooth} className={cellClass}>\n {grade != null ? (\n <Badge\n variant={grade >= 2 ? 'warning' : 'neutral'}\n size=\"sm\"\n aria-label={t(\n 'periodontalChartCard.mobility.label',\n {\n grade,\n defaultValue: 'Mobility grade {{grade}}',\n },\n )}\n >\n {grade}\n </Badge>\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n )}\n </td>\n );\n })}\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* Legend — explains the non-colour cues */\n /* ------------------------------------------------------------ */\n\n const legend = (\n <div\n role=\"group\"\n className=\"type-meta ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)] ds:text-[color:var(--muted-foreground)]\"\n aria-label={t('periodontalChartCard.legend.label', 'Chart legend')}\n >\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:font-semibold ds:text-[color:var(--warning-foreground)]\"\n >\n {'∗'}\n </span>\n {t('periodontalChartCard.legend.moderate', {\n threshold: MODERATE_POCKET_MM,\n defaultValue: 'PD ≥ {{threshold}} mm',\n })}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:font-bold ds:text-[color:var(--destructive)]\"\n >\n {'∗∗'}\n </span>\n {t('periodontalChartCard.legend.severe', {\n threshold: SEVERE_POCKET_MM,\n defaultValue: 'PD ≥ {{threshold}} mm',\n })}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--destructive)]\"\n />\n {t('periodontalChartCard.sign.bleeding', 'Bleeding on probing')}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--warning)]\"\n />\n {t('periodontalChartCard.sign.suppuration', 'Suppuration')}\n </span>\n </div>\n );\n\n const isEmpty = quadrants.length === 0;\n\n const inner = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <h2\n id={headingId}\n className=\"type-title-card ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {resolvedHeading}\n </h2>\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {formattedDate\n ? t('periodontalChartCard.subtitle.dated', {\n dentition: dentitionLabel,\n date: formattedDate,\n defaultValue: '{{dentition}} · {{date}}',\n })\n : dentitionLabel}\n </p>\n </div>\n\n {summaryRows.length > 0 ? (\n <KeyValueList rowGap=\"sm\">\n {summaryRows.map((row) => (\n <KeyValuePair key={row.key} label={row.label} value={row.value} />\n ))}\n </KeyValueList>\n ) : null}\n\n {isEmpty ? (\n <p\n role=\"status\"\n className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\"\n >\n {t(\n 'periodontalChartCard.empty',\n 'No periodontal readings recorded.',\n )}\n </p>\n ) : (\n <>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {quadrants.map((group) => renderQuadrant(group))}\n </div>\n {legend}\n </>\n )}\n </div>\n );\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-labelledby={headingId}\n data-component=\"periodontal-chart-card\"\n data-component-id={id}\n id={id}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {surface === 'elevated' ? (\n <Card variant=\"elevated\">\n <Card.Body>{inner}</Card.Body>\n </Card>\n ) : (\n inner\n )}\n </div>\n );\n },\n);\n\nPeriodontalChartCard.displayName = 'PeriodontalChartCard';\n\nexport type PeriodontalChartCardSurface = NonNullable<\n VariantProps<typeof rootVariants>['surface']\n>;\n"],"names":["periodontalChartCardAgent","handle","rootVariants","cva","measureVariants","MODERATE_POCKET_MM","SEVERE_POCKET_MM","PERIODONTAL_SITE_ORDER","SITE_DEFAULT","QUADRANT_ORDER","pocketSeverity","depth","severityMarker","severity","quadrantOf","tooth","first","PeriodontalChartCard","forwardRef","sites","dateIso","dentition","mobility","summary","locale","surface","ariaLabel","id","className","rest","ref","t","i18n","useTranslation","headingId","useId","resolvedLocale","quadrants","toothIds","siteCount","deepPocketCount","useMemo","byTooth","sCount","deep","site","row","rows","grouped","q","r","a","b","g","unassigned","ids","tt","useAgentRegistration","formattedDate","parsed","resolvedHeading","resolvedAriaLabel","DENTITION_DEFAULT","dentitionLabel","formatNumber","n","summaryRows","renderMeasure","kind","jsx","marker","numeric","srSuffix","renderSigns","jsxs","renderQuadrant","group","QUADRANT_DEFAULT","captionText","cellClass","rowHeaderClass","siteId","_a","grade","Badge","legend","isEmpty","inner","KeyValueList","KeyValuePair","Fragment","Card"],"mappings":"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"}
1
+ {"version":3,"file":"periodontal-chart-card-BzL3YkEW.js","sources":["../../src/components/periodontal-chart-card/periodontal-chart-card.agent.ts","../../src/components/periodontal-chart-card/periodontal-chart-card.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { PeriodontalChartCardHandle } from './periodontal-chart-card';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalChartCard — agent adapter */\n/* */\n/* Read-only clinical chart. The handle returns STRUCTURAL state only — */\n/* the set of charted FDI tooth ids, how many probing sites breach the */\n/* 4mm / 6mm thresholds, and the chart date. NEVER patient identity, */\n/* names, or any free-text PHI — the chart never holds those. */\n/* -------------------------------------------------------------------- */\n\nexport const periodontalChartCardAgent: AgentAdapter<PeriodontalChartCardHandle> =\n {\n id: 'periodontal-chart-card',\n capabilities: [],\n state: {\n toothIds: {\n type: 'string[]',\n descriptionKey: 'ui.agent.periodontalChartCard.state.toothIds',\n description:\n 'FDI ids of the teeth currently charted. Tooth identifiers only — no patient identity.',\n read: (handle) => handle.getToothIds(),\n },\n siteCount: {\n type: 'number',\n descriptionKey: 'ui.agent.periodontalChartCard.state.siteCount',\n description: 'Total number of probing sites rendered.',\n read: (handle) => handle.getSiteCount(),\n },\n deepPocketCount: {\n type: 'number',\n descriptionKey: 'ui.agent.periodontalChartCard.state.deepPocketCount',\n description:\n 'Number of sites with a probing depth at or above the 6mm severe threshold.',\n read: (handle) => handle.getDeepPocketCount(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'periodontal-chart-card',\n description: 'Marks the PeriodontalChartCard root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n };\n","import {\n forwardRef,\n useId,\n useMemo,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Badge } from '../badge/badge';\nimport { Card } from '../card/card';\nimport { KeyValueList, KeyValuePair } from '../key-value-pair/key-value-pair';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { periodontalChartCardAgent } from './periodontal-chart-card.agent';\n\n/* -------------------------------------------------------------------- */\n/* PeriodontalChartCard */\n/* */\n/* A DISPLAY-ONLY periodontal (gum) chart. There is no kit equivalent — */\n/* the dental ToothScheme charts caries/restorations per tooth, whereas */\n/* a perio chart records probing measurements per SITE (6 sites/tooth): */\n/* pocket depth (PD), gingival recession (REC), bleeding on probing */\n/* (BoP), suppuration, and tooth mobility. */\n/* */\n/* It renders a compact per-quadrant TABLE (real <table>/<th> semantics */\n/* + scope + caption — NOT a colour-only grid) of teeth x sites. Pocket */\n/* depths >= 4mm are flagged with the warning token, >= 6mm with the */\n/* destructive token, and EACH flag also carries a non-colour cue */\n/* (bold weight + an asterisk / double-asterisk) so the severity is */\n/* legible without colour. Bleeding and suppuration render as small */\n/* glyphs WITH an accessible per-cell label. */\n/* */\n/* The component owns no editing affordance — it is a passive read */\n/* surface for a chart captured elsewhere. */\n/* */\n/* All visible text flows through `useTranslation('ui')` against the */\n/* `periodontalChartCard.*` namespace. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n // Matches the kit's other `surface` props. `elevated` wraps in\n // `<Card variant=\"elevated\">`; `flat` drops the chrome for use\n // inside an existing Card / Sheet.\n surface: {\n flat: '',\n elevated: '',\n },\n },\n defaultVariants: { surface: 'elevated' },\n});\n\n// Per-measurement-cell severity. The colour is paired with a weight bump\n// so the flag survives greyscale / forced-colors — colour is never the\n// sole cue (the asterisk in the cell content carries the same signal).\nconst measureVariants = cva(\n 'ds:[font-variant-numeric:var(--font-feature-tabular)] ds:tabular-nums',\n {\n variants: {\n severity: {\n normal: 'ds:text-[color:var(--foreground)]',\n moderate: 'ds:font-semibold ds:text-[color:var(--warning-foreground)]',\n severe: 'ds:font-bold ds:text-[color:var(--destructive)]',\n },\n },\n defaultVariants: { severity: 'normal' },\n },\n);\n\n/* -------------------------------------------------------------------- */\n/* Constants */\n/* -------------------------------------------------------------------- */\n\n/** Probing depth (mm) at/above which a site is flagged moderate. */\nconst MODERATE_POCKET_MM = 4;\n/** Probing depth (mm) at/above which a site is flagged severe. */\nconst SEVERE_POCKET_MM = 6;\n\n/** The six standard probing sites, in buccal-then-lingual display order. */\nexport const PERIODONTAL_SITE_ORDER = [\n 'db',\n 'b',\n 'mb',\n 'dl',\n 'l',\n 'ml',\n] as const;\n\nexport type PeriodontalSiteId = (typeof PERIODONTAL_SITE_ORDER)[number];\n\n/** English fallback labels for the six probing sites (belt-and-braces). */\nconst SITE_DEFAULT: Record<PeriodontalSiteId, string> = {\n db: 'Disto-buccal',\n b: 'Buccal',\n mb: 'Mesio-buccal',\n dl: 'Disto-lingual',\n l: 'Lingual',\n ml: 'Mesio-lingual',\n};\n\n/** FDI quadrant ids (first digit of the FDI tooth number). */\nconst QUADRANT_ORDER = ['1', '2', '3', '4'] as const;\ntype QuadrantId = (typeof QUADRANT_ORDER)[number];\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** One probing-site reading. */\nexport interface PeriodontalSite {\n /** FDI tooth number, e.g. `'11'`, `'46'`. */\n tooth: string;\n /** Probing site: mesio-/disto- buccal/lingual, mid buccal/lingual. */\n site: PeriodontalSiteId;\n /** Pocket depth in millimetres. */\n pocketDepthMm?: number;\n /** Gingival recession in millimetres. */\n recessionMm?: number;\n /** Bleeding on probing at this site. */\n bleeding?: boolean;\n /** Suppuration (pus) at this site. */\n suppuration?: boolean;\n}\n\n/** Aggregate chart summary, consumer-supplied. */\nexport interface PeriodontalChartSummary {\n /** Whole-mouth mean probing depth in millimetres. */\n meanPocketDepthMm?: number;\n /** Bleeding-on-probing as a percentage of sites (0–100). */\n bleedingOnProbingPercent?: number;\n}\n\n/** Tooth-mobility grade (Miller 0–3). */\nexport type PeriodontalMobility = 0 | 1 | 2 | 3;\n\n/** Imperative handle — structural state only, never PHI. */\nexport interface PeriodontalChartCardHandle {\n /** FDI ids of the charted teeth, in display order. */\n getToothIds: () => string[];\n /** Total probing sites rendered. */\n getSiteCount: () => number;\n /** Count of sites at/above the 6mm severe threshold. */\n getDeepPocketCount: () => number;\n}\n\nexport interface PeriodontalChartCardProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children'\n> {\n /** Probing-site readings. Sites are grouped per tooth automatically. */\n sites: PeriodontalSite[];\n /**\n * ISO-8601 date the chart was captured. Rendered as a localised date in\n * the header and exposed as the table caption context. Optional.\n */\n dateIso?: string;\n /**\n * Dentition the chart covers. Drives only the localised header label —\n * tooth grouping is derived from the FDI numbers in `sites`.\n */\n dentition?: 'permanent' | 'primary' | 'mixed';\n /** Per-tooth Miller mobility grade, keyed by FDI tooth number. */\n mobility?: Record<string, PeriodontalMobility>;\n /** Aggregate summary stats rendered above the per-quadrant tables. */\n summary?: PeriodontalChartSummary;\n\n /* ----- i18n / formatting ----- */\n\n /** Locale for date + number formatting. Falls back to `i18n.language`. */\n locale?: string;\n\n /* ----- Styling ----- */\n\n /**\n * `'elevated'` (default) wraps in `<Card variant=\"elevated\">`. `'flat'`\n * drops the Card — use inside another card / sheet.\n */\n surface?: 'flat' | 'elevated';\n\n /* ----- a11y ----- */\n\n /** Override the default region aria-label. */\n 'aria-label'?: string;\n /** Agent-readiness consumer id, surfaced as `data-component-id`. */\n id?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\n/** Classify a pocket depth into a severity band. */\nfunction pocketSeverity(\n depth: number | undefined,\n): 'normal' | 'moderate' | 'severe' {\n if (depth == null || !Number.isFinite(depth)) return 'normal';\n if (depth >= SEVERE_POCKET_MM) return 'severe';\n if (depth >= MODERATE_POCKET_MM) return 'moderate';\n return 'normal';\n}\n\n/** Non-colour severity cue appended to the measurement (`''`/`*`/`**`). */\nfunction severityMarker(severity: 'normal' | 'moderate' | 'severe'): string {\n if (severity === 'severe') return '∗∗';\n if (severity === 'moderate') return '∗';\n return '';\n}\n\n/** FDI quadrant (first digit) of a tooth number, or null if unparseable. */\nfunction quadrantOf(tooth: string): QuadrantId | null {\n const first = tooth.trim().charAt(0);\n return (QUADRANT_ORDER as readonly string[]).includes(first)\n ? (first as QuadrantId)\n : null;\n}\n\ninterface ToothRow {\n tooth: string;\n sites: Partial<Record<PeriodontalSiteId, PeriodontalSite>>;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const PeriodontalChartCard = forwardRef<\n HTMLDivElement,\n PeriodontalChartCardProps\n>(\n (\n {\n sites,\n dateIso,\n dentition = 'permanent',\n mobility,\n summary,\n locale,\n surface = 'elevated',\n 'aria-label': ariaLabel,\n id,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const headingId = useId();\n const resolvedLocale = locale ?? i18n.language ?? 'en';\n\n // Group sites by tooth, then bucket teeth into FDI quadrants. The\n // grouping is derived purely from the FDI numbers — the consumer\n // passes a flat site list and the kit owns the layout.\n const { quadrants, toothIds, siteCount, deepPocketCount } = useMemo(() => {\n const byTooth = new Map<string, ToothRow>();\n let sCount = 0;\n let deep = 0;\n for (const site of sites) {\n sCount += 1;\n if ((site.pocketDepthMm ?? 0) >= SEVERE_POCKET_MM) deep += 1;\n let row = byTooth.get(site.tooth);\n if (!row) {\n row = { tooth: site.tooth, sites: {} };\n byTooth.set(site.tooth, row);\n }\n row.sites[site.site] = site;\n }\n\n // Sort teeth within a quadrant by their FDI position digit (2nd\n // char) ascending; keep insertion order as a stable fallback.\n const rows = Array.from(byTooth.values());\n const grouped: Array<{\n quadrant: QuadrantId | null;\n teeth: ToothRow[];\n }> = QUADRANT_ORDER.map((q) => ({\n quadrant: q as QuadrantId | null,\n teeth: rows\n .filter((r) => quadrantOf(r.tooth) === q)\n .sort((a, b) => a.tooth.localeCompare(b.tooth, 'en')),\n })).filter((g) => g.teeth.length > 0);\n\n // Teeth with an unparseable FDI quadrant render in their own group\n // so nothing is silently dropped.\n const unassigned = rows.filter((r) => quadrantOf(r.tooth) === null);\n if (unassigned.length > 0) {\n grouped.push({ quadrant: null, teeth: unassigned });\n }\n\n const ids = grouped.flatMap((g) => g.teeth.map((tt) => tt.tooth));\n return {\n quadrants: grouped,\n toothIds: ids,\n siteCount: sCount,\n deepPocketCount: deep,\n };\n }, [sites]);\n\n useAgentRegistration(\n periodontalChartCardAgent,\n {\n getToothIds: () => toothIds,\n getSiteCount: () => siteCount,\n getDeepPocketCount: () => deepPocketCount,\n },\n id,\n );\n\n const formattedDate = useMemo(() => {\n if (!dateIso) return undefined;\n const parsed = new Date(dateIso);\n if (Number.isNaN(parsed.getTime())) return undefined;\n try {\n return new Intl.DateTimeFormat(resolvedLocale, {\n dateStyle: 'medium',\n }).format(parsed);\n } catch {\n return parsed.toISOString().slice(0, 10);\n }\n }, [dateIso, resolvedLocale]);\n\n const resolvedHeading = t(\n 'periodontalChartCard.heading',\n 'Periodontal chart',\n );\n const resolvedAriaLabel = ariaLabel ?? resolvedHeading;\n\n const DENTITION_DEFAULT: Record<typeof dentition, string> = {\n permanent: 'Permanent dentition',\n primary: 'Primary dentition',\n mixed: 'Mixed dentition',\n };\n const dentitionLabel = t(`periodontalChartCard.dentition.${dentition}`, {\n defaultValue: DENTITION_DEFAULT[dentition],\n });\n\n const formatNumber = (n: number): string => {\n try {\n return new Intl.NumberFormat(resolvedLocale, {\n maximumFractionDigits: 1,\n }).format(n);\n } catch {\n return String(n);\n }\n };\n\n /* ------------------------------------------------------------ */\n /* Summary rows */\n /* ------------------------------------------------------------ */\n\n const summaryRows: Array<{ key: string; label: string; value: ReactNode }> =\n [];\n if (summary?.meanPocketDepthMm != null) {\n summaryRows.push({\n key: 'meanPocketDepth',\n label: t(\n 'periodontalChartCard.summary.meanPocketDepth',\n 'Mean probing depth',\n ),\n value: t('periodontalChartCard.unit.mm', {\n value: formatNumber(summary.meanPocketDepthMm),\n defaultValue: '{{value}} mm',\n }),\n });\n }\n if (summary?.bleedingOnProbingPercent != null) {\n summaryRows.push({\n key: 'bleedingOnProbing',\n label: t(\n 'periodontalChartCard.summary.bleedingOnProbing',\n 'Bleeding on probing',\n ),\n value: t('periodontalChartCard.unit.percent', {\n value: formatNumber(summary.bleedingOnProbingPercent),\n defaultValue: '{{value}}%',\n }),\n });\n }\n\n /* ------------------------------------------------------------ */\n /* Render a single measurement cell */\n /* ------------------------------------------------------------ */\n\n const renderMeasure = (\n depth: number | undefined,\n kind: 'pocket' | 'recession',\n ): ReactNode => {\n if (depth == null || !Number.isFinite(depth)) {\n return (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n );\n }\n const severity = kind === 'pocket' ? pocketSeverity(depth) : 'normal';\n const marker = kind === 'pocket' ? severityMarker(severity) : '';\n const numeric = formatNumber(depth);\n // The flag is announced as a worded suffix for SR users; sighted\n // users get the colour + bold + asterisk. The asterisk itself is\n // aria-hidden so it isn't read as punctuation.\n const srSuffix =\n severity === 'severe'\n ? ` ${t('periodontalChartCard.flag.severe', 'severe pocket')}`\n : severity === 'moderate'\n ? ` ${t('periodontalChartCard.flag.moderate', 'moderate pocket')}`\n : '';\n return (\n <span className={measureVariants({ severity })}>\n <span>{numeric}</span>\n {marker ? <span aria-hidden=\"true\">{marker}</span> : null}\n {srSuffix ? <span className=\"ds:sr-only\">{srSuffix}</span> : null}\n </span>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* Render bleeding / suppuration indicator cell */\n /* ------------------------------------------------------------ */\n\n const renderSigns = (site: PeriodontalSite | undefined): ReactNode => {\n if (!site || (!site.bleeding && !site.suppuration)) {\n return (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n );\n }\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n {site.bleeding ? (\n <span\n role=\"img\"\n aria-label={t(\n 'periodontalChartCard.sign.bleeding',\n 'Bleeding on probing',\n )}\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--destructive)]\"\n />\n ) : null}\n {site.suppuration ? (\n <span\n role=\"img\"\n aria-label={t(\n 'periodontalChartCard.sign.suppuration',\n 'Suppuration',\n )}\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--warning)]\"\n />\n ) : null}\n </span>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* One quadrant table */\n /* ------------------------------------------------------------ */\n\n const renderQuadrant = (group: {\n quadrant: QuadrantId | null;\n teeth: ToothRow[];\n }): ReactNode => {\n const QUADRANT_DEFAULT: Record<QuadrantId, string> = {\n '1': 'Upper right (Q1)',\n '2': 'Upper left (Q2)',\n '3': 'Lower left (Q3)',\n '4': 'Lower right (Q4)',\n };\n const captionText =\n group.quadrant != null\n ? t(`periodontalChartCard.quadrant.${group.quadrant}`, {\n defaultValue: QUADRANT_DEFAULT[group.quadrant],\n })\n : t('periodontalChartCard.quadrant.other', 'Other teeth');\n const cellClass =\n 'ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-center ds:border-b ds:border-[color:var(--border)]';\n const rowHeaderClass =\n 'ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-start ds:font-medium ds:border-b ds:border-[color:var(--border)] ds:whitespace-nowrap';\n return (\n <div\n key={group.quadrant ?? 'other'}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:overflow-x-auto\"\n >\n <table className=\"type-body-sm ds:w-full ds:border-collapse\">\n <caption className=\"type-label ds:text-start ds:mb-[var(--spacing-2xs)] ds:text-[color:var(--muted-foreground)]\">\n {captionText}\n </caption>\n <thead>\n <tr>\n <th\n scope=\"col\"\n className=\"ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-start ds:border-b ds:border-[color:var(--border)]\"\n >\n {t('periodontalChartCard.column.measure', 'Measurement')}\n </th>\n {group.teeth.map((row) => (\n <th\n key={row.tooth}\n scope=\"col\"\n data-tooth-id={row.tooth}\n className=\"ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs)] ds:text-center ds:border-b ds:border-[color:var(--border)] ds:[font-variant-numeric:var(--font-feature-tabular)] ds:tabular-nums\"\n >\n <span className=\"ds:sr-only\">\n {t('periodontalChartCard.toothHeader', {\n tooth: row.tooth,\n defaultValue: 'Tooth {{tooth}}',\n })}\n </span>\n <span aria-hidden=\"true\">{row.tooth}</span>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {/* Pocket depth row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t(\n 'periodontalChartCard.row.pocketDepth',\n 'Pocket depth (PD)',\n )}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:items-center ds:justify-center ds:gap-[var(--spacing-2xs)]\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId} className=\"ds:sr-only\">\n {t(`periodontalChartCard.site.${siteId}`, {\n defaultValue: SITE_DEFAULT[siteId],\n })}\n </span>\n ))}\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)]\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderMeasure(\n row.sites[siteId]?.pocketDepthMm,\n 'pocket',\n )}\n </span>\n ))}\n </span>\n </span>\n </td>\n ))}\n </tr>\n {/* Recession row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t('periodontalChartCard.row.recession', 'Recession (REC)')}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)] ds:justify-center\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderMeasure(\n row.sites[siteId]?.recessionMm,\n 'recession',\n )}\n </span>\n ))}\n </span>\n </td>\n ))}\n </tr>\n {/* Bleeding / suppuration row */}\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t(\n 'periodontalChartCard.row.signs',\n 'Bleeding / suppuration',\n )}\n </th>\n {group.teeth.map((row) => (\n <td key={row.tooth} className={cellClass}>\n <span className=\"ds:flex ds:gap-[var(--spacing-2xs)] ds:justify-center\">\n {PERIODONTAL_SITE_ORDER.map((siteId) => (\n <span key={siteId}>\n {renderSigns(row.sites[siteId])}\n </span>\n ))}\n </span>\n </td>\n ))}\n </tr>\n {/* Mobility row — only when any tooth in the quadrant has a grade */}\n {mobility &&\n group.teeth.some((row) => mobility[row.tooth] != null) ? (\n <tr>\n <th scope=\"row\" className={rowHeaderClass}>\n {t('periodontalChartCard.row.mobility', 'Mobility')}\n </th>\n {group.teeth.map((row) => {\n const grade = mobility[row.tooth];\n return (\n <td key={row.tooth} className={cellClass}>\n {grade != null ? (\n <Badge\n variant={grade >= 2 ? 'warning' : 'neutral'}\n size=\"sm\"\n aria-label={t(\n 'periodontalChartCard.mobility.label',\n {\n grade,\n defaultValue: 'Mobility grade {{grade}}',\n },\n )}\n >\n {grade}\n </Badge>\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"ds:text-[color:var(--muted-foreground)]\"\n >\n {t('periodontalChartCard.cell.empty', '–')}\n </span>\n )}\n </td>\n );\n })}\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n );\n };\n\n /* ------------------------------------------------------------ */\n /* Legend — explains the non-colour cues */\n /* ------------------------------------------------------------ */\n\n const legend = (\n <div\n role=\"group\"\n className=\"type-meta ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)] ds:text-[color:var(--muted-foreground)]\"\n aria-label={t('periodontalChartCard.legend.label', 'Chart legend')}\n >\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:font-semibold ds:text-[color:var(--warning-foreground)]\"\n >\n {'∗'}\n </span>\n {t('periodontalChartCard.legend.moderate', {\n threshold: MODERATE_POCKET_MM,\n defaultValue: 'PD ≥ {{threshold}} mm',\n })}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:font-bold ds:text-[color:var(--destructive)]\"\n >\n {'∗∗'}\n </span>\n {t('periodontalChartCard.legend.severe', {\n threshold: SEVERE_POCKET_MM,\n defaultValue: 'PD ≥ {{threshold}} mm',\n })}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--destructive)]\"\n />\n {t('periodontalChartCard.sign.bleeding', 'Bleeding on probing')}\n </span>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-2 ds:rounded-[var(--radius-full)] ds:bg-[var(--warning)]\"\n />\n {t('periodontalChartCard.sign.suppuration', 'Suppuration')}\n </span>\n </div>\n );\n\n const isEmpty = quadrants.length === 0;\n\n const inner = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <h2\n id={headingId}\n className=\"type-title-card ds:m-0 ds:text-[color:var(--foreground)]\"\n >\n {resolvedHeading}\n </h2>\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {formattedDate\n ? t('periodontalChartCard.subtitle.dated', {\n dentition: dentitionLabel,\n date: formattedDate,\n defaultValue: '{{dentition}} · {{date}}',\n })\n : dentitionLabel}\n </p>\n </div>\n\n {summaryRows.length > 0 ? (\n <KeyValueList rowGap=\"sm\">\n {summaryRows.map((row) => (\n <KeyValuePair key={row.key} label={row.label} value={row.value} />\n ))}\n </KeyValueList>\n ) : null}\n\n {isEmpty ? (\n <p\n role=\"status\"\n className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\"\n >\n {t(\n 'periodontalChartCard.empty',\n 'No periodontal readings recorded.',\n )}\n </p>\n ) : (\n <>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {quadrants.map((group) => renderQuadrant(group))}\n </div>\n {legend}\n </>\n )}\n </div>\n );\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-labelledby={headingId}\n data-component=\"periodontal-chart-card\"\n data-component-id={id}\n id={id}\n className={rootVariants({ surface, className })}\n {...rest}\n >\n {surface === 'elevated' ? (\n <Card variant=\"elevated\">\n <Card.Body>{inner}</Card.Body>\n </Card>\n ) : (\n inner\n )}\n </div>\n );\n },\n);\n\nPeriodontalChartCard.displayName = 'PeriodontalChartCard';\n\nexport type PeriodontalChartCardSurface = NonNullable<\n VariantProps<typeof rootVariants>['surface']\n>;\n"],"names":["periodontalChartCardAgent","handle","rootVariants","cva","measureVariants","MODERATE_POCKET_MM","SEVERE_POCKET_MM","PERIODONTAL_SITE_ORDER","SITE_DEFAULT","QUADRANT_ORDER","pocketSeverity","depth","severityMarker","severity","quadrantOf","tooth","first","PeriodontalChartCard","forwardRef","sites","dateIso","dentition","mobility","summary","locale","surface","ariaLabel","id","className","rest","ref","t","i18n","useTranslation","headingId","useId","resolvedLocale","quadrants","toothIds","siteCount","deepPocketCount","useMemo","byTooth","sCount","deep","site","row","rows","grouped","q","r","a","b","g","unassigned","ids","tt","useAgentRegistration","formattedDate","parsed","resolvedHeading","resolvedAriaLabel","DENTITION_DEFAULT","dentitionLabel","formatNumber","n","summaryRows","renderMeasure","kind","jsx","marker","numeric","srSuffix","renderSigns","jsxs","renderQuadrant","group","QUADRANT_DEFAULT","captionText","cellClass","rowHeaderClass","siteId","_a","grade","Badge","legend","isEmpty","inner","KeyValueList","KeyValuePair","Fragment","Card"],"mappings":"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"}
@@ -261,6 +261,7 @@ const R = C(
261
261
  "svg",
262
262
  {
263
263
  focusable: "false",
264
+ "data-slot": "ring",
264
265
  className: "ds:absolute ds:inset-[calc(var(--border-width-sm)/2)] ds:size-[calc(100%-var(--border-width-sm))] ds:overflow-visible",
265
266
  children: [
266
267
  /* @__PURE__ */ r("defs", { children: /* @__PURE__ */ a("linearGradient", { id: m, x1: "0", y1: "0", x2: "1", y2: "1", children: [
@@ -335,4 +336,4 @@ export {
335
336
  R as c,
336
337
  P as r
337
338
  };
338
- //# sourceMappingURL=specialty-icon-KuovHTxh.js.map
339
+ //# sourceMappingURL=specialty-icon-BkpExzMh.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"specialty-icon-KuovHTxh.js","sources":["../../src/components/specialty-icon/glyph-loaders.ts","../../src/components/specialty-icon/specialty-map.ts","../../src/components/specialty-icon/specialty-icon.tsx"],"sourcesContent":["// Generated by scripts/build-specialty-icons.mjs. Do not edit by hand.\n// Glyph artwork: Healthicons, CC0 1.0 Universal (public domain).\n// https://github.com/resolvetosavelives/healthicons\nimport type { SpecialtyGlyph } from './specialty-glyph';\n\n/** One dynamic import per glyph, so a page only downloads what it renders. */\nexport const SPECIALTY_GLYPH_LOADERS = {\n 'acupuncture-1': () => import('./glyphs/acupuncture-1'),\n allergies: () => import('./glyphs/allergies'),\n antibody: () => import('./glyphs/antibody'),\n anus: () => import('./glyphs/anus'),\n 'blood-cells': () => import('./glyphs/blood-cells'),\n 'blood-vessel': () => import('./glyphs/blood-vessel'),\n braces: () => import('./glyphs/braces'),\n breast: () => import('./glyphs/breast'),\n cardiology: () => import('./glyphs/cardiology'),\n 'child-cognition': () => import('./glyphs/child-cognition'),\n 'dental-hygiene': () => import('./glyphs/dental-hygiene'),\n dermatology: () => import('./glyphs/dermatology'),\n diabetes: () => import('./glyphs/diabetes'),\n dna: () => import('./glyphs/dna'),\n doctor: () => import('./glyphs/doctor'),\n 'ears-nose-and-throat': () => import('./glyphs/ears-nose-and-throat'),\n 'eco-care': () => import('./glyphs/eco-care'),\n exercise: () => import('./glyphs/exercise'),\n eyeglasses: () => import('./glyphs/eyeglasses'),\n foot: () => import('./glyphs/foot'),\n fruits: () => import('./glyphs/fruits'),\n 'general-surgery': () => import('./glyphs/general-surgery'),\n geriatrics: () => import('./glyphs/geriatrics'),\n 'group-discussion-meeting': () => import('./glyphs/group-discussion-meeting'),\n gym: () => import('./glyphs/gym'),\n gynecology: () => import('./glyphs/gynecology'),\n head: () => import('./glyphs/head'),\n 'health-cross': () => import('./glyphs/health-cross'),\n 'health-worker': () => import('./glyphs/health-worker'),\n 'heart-organ': () => import('./glyphs/heart-organ'),\n hepatology: () => import('./glyphs/hepatology'),\n justice: () => import('./glyphs/justice'),\n 'liquid-medicine': () => import('./glyphs/liquid-medicine'),\n lungs: () => import('./glyphs/lungs'),\n 'lymph-nodes': () => import('./glyphs/lymph-nodes'),\n maxillofacial: () => import('./glyphs/maxillofacial'),\n 'mental-disorders': () => import('./glyphs/mental-disorders'),\n 'mental-health-therapy': () => import('./glyphs/mental-health-therapy'),\n microscope: () => import('./glyphs/microscope'),\n mouth: () => import('./glyphs/mouth'),\n nephrology: () => import('./glyphs/nephrology'),\n nerve: () => import('./glyphs/nerve'),\n 'neuro-surgery': () => import('./glyphs/neuro-surgery'),\n neurology: () => import('./glyphs/neurology'),\n nurse: () => import('./glyphs/nurse'),\n obstetricsmonia: () => import('./glyphs/obstetricsmonia'),\n odontology: () => import('./glyphs/odontology'),\n 'odontology-implant': () => import('./glyphs/odontology-implant'),\n oncology: () => import('./glyphs/oncology'),\n opthalmology: () => import('./glyphs/opthalmology'),\n orthopaedics: () => import('./glyphs/orthopaedics'),\n orthotics: () => import('./glyphs/orthotics'),\n pain: () => import('./glyphs/pain'),\n 'pediatric-surgery': () => import('./glyphs/pediatric-surgery'),\n pediatrics: () => import('./glyphs/pediatrics'),\n 'physical-therapy': () => import('./glyphs/physical-therapy'),\n poison: () => import('./glyphs/poison'),\n psychology: () => import('./glyphs/psychology'),\n radiology: () => import('./glyphs/radiology'),\n respirology: () => import('./glyphs/respirology'),\n rheumatology: () => import('./glyphs/rheumatology'),\n 'sexual-reproductive-health': () =>\n import('./glyphs/sexual-reproductive-health'),\n 'skin-layers': () => import('./glyphs/skin-layers'),\n sonography: () => import('./glyphs/sonography'),\n 'speech-language-therapist': () =>\n import('./glyphs/speech-language-therapist'),\n spine: () => import('./glyphs/spine'),\n stethoscope: () => import('./glyphs/stethoscope'),\n stitches: () => import('./glyphs/stitches'),\n stomach: () => import('./glyphs/stomach'),\n syringe: () => import('./glyphs/syringe'),\n testicles: () => import('./glyphs/testicles'),\n thyroid: () => import('./glyphs/thyroid'),\n tooth: () => import('./glyphs/tooth'),\n urology: () => import('./glyphs/urology'),\n 'varicose-vein': () => import('./glyphs/varicose-vein'),\n 'vascular-surgery': () => import('./glyphs/vascular-surgery'),\n vegetables: () => import('./glyphs/vegetables'),\n xray: () => import('./glyphs/xray'),\n} satisfies Record<string, () => Promise<{ default: SpecialtyGlyph }>>;\n\nexport type SpecialtyIconId = keyof typeof SPECIALTY_GLYPH_LOADERS;\n\nexport const SPECIALTY_ICON_IDS = Object.keys(\n SPECIALTY_GLYPH_LOADERS,\n) as SpecialtyIconId[];\n","// Generated by scripts/build-specialty-icons.mjs. Do not edit by hand.\n// Glyph artwork: Healthicons, CC0 1.0 Universal (public domain).\n// https://github.com/resolvetosavelives/healthicons\nimport type { SpecialtyIconId } from './glyph-loaders';\n\nexport interface SpecialtyMapEntry {\n icon: SpecialtyIconId;\n /** Not used for layout yet: kept for a grouped list later. */\n group: string;\n}\n\n/** Profession key (the platform's profession seoUrl slug) to icon id. */\nexport const SPECIALTY_MAP: Record<string, SpecialtyMapEntry> = {\n agopuntura: { icon: 'acupuncture-1', group: 'complementaryMedicine' },\n allergologo: { icon: 'allergies', group: 'specialistVisits' },\n andrologo: { icon: 'testicles', group: 'specialistVisits' },\n anestesista: { icon: 'syringe', group: 'specialistVisits' },\n angiologo: { icon: 'blood-vessel', group: 'specialistVisits' },\n biologo: { icon: 'microscope', group: 'diagnostics' },\n cardiochirurgo: { icon: 'heart-organ', group: 'surgery' },\n cardiologo: { icon: 'cardiology', group: 'specialistVisits' },\n chiropratico: { icon: 'spine', group: 'rehabilitation' },\n 'chirurgia-toracica': { icon: 'lungs', group: 'surgery' },\n chirurgo: { icon: 'general-surgery', group: 'surgery' },\n 'chirurgo-generale': { icon: 'general-surgery', group: 'surgery' },\n 'chirurgo-maxillofacciale': { icon: 'maxillofacial', group: 'surgery' },\n 'chirurgo-pediatrico': { icon: 'pediatric-surgery', group: 'surgery' },\n 'chirurgo-plastico': { icon: 'skin-layers', group: 'surgery' },\n 'chirurgo-vascolare': { icon: 'vascular-surgery', group: 'surgery' },\n dentista: { icon: 'tooth', group: 'dentistry' },\n dermatologo: { icon: 'dermatology', group: 'specialistVisits' },\n diabetologo: { icon: 'diabetes', group: 'specialistVisits' },\n dietista: { icon: 'vegetables', group: 'nutrition' },\n dietologo: { icon: 'vegetables', group: 'nutrition' },\n ecografista: { icon: 'sonography', group: 'diagnostics' },\n 'educatore-professionale-socio-sanitario': {\n icon: 'group-discussion-meeting',\n group: 'mentalHealth',\n },\n ematologo: { icon: 'blood-cells', group: 'specialistVisits' },\n endocrinochirurgo: { icon: 'thyroid', group: 'surgery' },\n endocrinologo: { icon: 'thyroid', group: 'specialistVisits' },\n endodontista: { icon: 'tooth', group: 'dentistry' },\n epatologo: { icon: 'hepatology', group: 'specialistVisits' },\n fisiatra: { icon: 'physical-therapy', group: 'rehabilitation' },\n fisioterapista: { icon: 'physical-therapy', group: 'rehabilitation' },\n flebologo: { icon: 'varicose-vein', group: 'specialistVisits' },\n gastroenterologo: { icon: 'stomach', group: 'specialistVisits' },\n genetista: { icon: 'dna', group: 'diagnostics' },\n geriatra: { icon: 'geriatrics', group: 'generalMedicine' },\n ginecologo: { icon: 'gynecology', group: 'womenAndChildren' },\n gnatologo: { icon: 'mouth', group: 'dentistry' },\n igienista: { icon: 'dental-hygiene', group: 'dentistry' },\n 'igienista-dentale': { icon: 'dental-hygiene', group: 'dentistry' },\n immunologo: { icon: 'antibody', group: 'specialistVisits' },\n implantologo: { icon: 'odontology-implant', group: 'dentistry' },\n infermiere: { icon: 'nurse', group: 'generalMedicine' },\n internista: { icon: 'stethoscope', group: 'generalMedicine' },\n kinesiologo: { icon: 'exercise', group: 'rehabilitation' },\n linfologo: { icon: 'lymph-nodes', group: 'specialistVisits' },\n logopedista: { icon: 'speech-language-therapist', group: 'rehabilitation' },\n massofisioterapista: { icon: 'physical-therapy', group: 'rehabilitation' },\n massoterapista: { icon: 'physical-therapy', group: 'rehabilitation' },\n 'medico-chirurgo': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-competente': { icon: 'health-worker', group: 'generalMedicine' },\n 'medico-del-lavoro': { icon: 'health-worker', group: 'generalMedicine' },\n 'medico-dello-sport': { icon: 'gym', group: 'specialistVisits' },\n 'medico-di-base': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-di-famiglia': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-di-medicina-generale': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-estetico': { icon: 'skin-layers', group: 'specialistVisits' },\n 'medico-generico': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-genetista': { icon: 'dna', group: 'diagnostics' },\n 'medico-legale': { icon: 'justice', group: 'generalMedicine' },\n 'medico-omeopata': {\n icon: 'liquid-medicine',\n group: 'complementaryMedicine',\n },\n naturopata: { icon: 'eco-care', group: 'complementaryMedicine' },\n nefrologo: { icon: 'nephrology', group: 'specialistVisits' },\n neurochirurgo: { icon: 'neuro-surgery', group: 'surgery' },\n neurofisiopatologo: { icon: 'nerve', group: 'diagnostics' },\n neurologo: { icon: 'neurology', group: 'specialistVisits' },\n 'neuropsichiatra-infantile': {\n icon: 'child-cognition',\n group: 'womenAndChildren',\n },\n neuropsicologo: { icon: 'psychology', group: 'mentalHealth' },\n neuropsicomotricista: { icon: 'child-cognition', group: 'rehabilitation' },\n 'nutrizione-clinica': { icon: 'fruits', group: 'nutrition' },\n nutrizionista: { icon: 'fruits', group: 'nutrition' },\n oculista: { icon: 'opthalmology', group: 'specialistVisits' },\n odontoiatra: { icon: 'odontology', group: 'dentistry' },\n omeopata: { icon: 'liquid-medicine', group: 'complementaryMedicine' },\n omotossicologo: { icon: 'liquid-medicine', group: 'complementaryMedicine' },\n oncologo: { icon: 'oncology', group: 'specialistVisits' },\n ortodontista: { icon: 'braces', group: 'dentistry' },\n ortopedico: { icon: 'orthopaedics', group: 'specialistVisits' },\n ortottista: { icon: 'eyeglasses', group: 'rehabilitation' },\n osteopata: { icon: 'spine', group: 'rehabilitation' },\n ostetrica: { icon: 'obstetricsmonia', group: 'womenAndChildren' },\n otorino: { icon: 'ears-nose-and-throat', group: 'specialistVisits' },\n otorinolaringoiatra: {\n icon: 'ears-nose-and-throat',\n group: 'specialistVisits',\n },\n parodontologo: { icon: 'tooth', group: 'dentistry' },\n pediatra: { icon: 'pediatrics', group: 'womenAndChildren' },\n pedodontista: { icon: 'tooth', group: 'dentistry' },\n pneumologo: { icon: 'respirology', group: 'specialistVisits' },\n podologo: { icon: 'foot', group: 'rehabilitation' },\n posturologo: { icon: 'spine', group: 'rehabilitation' },\n proctologo: { icon: 'anus', group: 'specialistVisits' },\n protesista: { icon: 'odontology-implant', group: 'dentistry' },\n psichiatra: { icon: 'mental-disorders', group: 'mentalHealth' },\n psicoanalista: { icon: 'psychology', group: 'mentalHealth' },\n psicologo: { icon: 'psychology', group: 'mentalHealth' },\n 'psicologo-clinico': { icon: 'psychology', group: 'mentalHealth' },\n 'psicologo-del-lavoro': { icon: 'psychology', group: 'mentalHealth' },\n 'psicologo-dello-sport': { icon: 'psychology', group: 'mentalHealth' },\n 'psicologo-forense': { icon: 'psychology', group: 'mentalHealth' },\n psicomotricista: { icon: 'child-cognition', group: 'rehabilitation' },\n psiconeuroendocrinoimmunologia: {\n icon: 'neurology',\n group: 'complementaryMedicine',\n },\n psicoterapeuta: { icon: 'mental-health-therapy', group: 'mentalHealth' },\n psiiconeurobiologo: { icon: 'neurology', group: 'complementaryMedicine' },\n radiologo: { icon: 'radiology', group: 'diagnostics' },\n reumatologo: { icon: 'rheumatology', group: 'specialistVisits' },\n senologo: { icon: 'breast', group: 'womenAndChildren' },\n sessuologo: { icon: 'sexual-reproductive-health', group: 'mentalHealth' },\n 'tecnico-ortopedico': { icon: 'orthotics', group: 'rehabilitation' },\n 'tecnico-sanitario-di-radiologia-medica': {\n icon: 'xray',\n group: 'diagnostics',\n },\n 'terapista-del-dolore': { icon: 'pain', group: 'specialistVisits' },\n tossicologo: { icon: 'poison', group: 'diagnostics' },\n tricologo: { icon: 'head', group: 'specialistVisits' },\n urologo: { icon: 'urology', group: 'specialistVisits' },\n vulnologo: { icon: 'stitches', group: 'specialistVisits' },\n} as Record<string, SpecialtyMapEntry>;\n\n/** Shown for a key that is not in the map. */\nexport const SPECIALTY_FALLBACK_ICON: SpecialtyIconId = 'health-cross';\n","import {\n forwardRef,\n useEffect,\n useId,\n useReducer,\n type HTMLAttributes,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { SPECIALTY_GLYPH_LOADERS, type SpecialtyIconId } from './glyph-loaders';\nimport { SPECIALTY_FALLBACK_ICON, SPECIALTY_MAP } from './specialty-map';\nimport type { SpecialtyGlyph } from './specialty-glyph';\n\n/* -------------------------------------------------------------------- */\n/* SpecialtyIcon */\n/* */\n/* A medical speciality glyph (Healthicons, CC0) drawn in the brand */\n/* gradient, inside a gradient ring. */\n/* */\n/* The icon is a fixed-size box (a kit token), so nothing moves while a */\n/* glyph loads. Glyphs are separate */\n/* modules, fetched with `import()` the first time an id is rendered and */\n/* kept in a module cache after that. */\n/* -------------------------------------------------------------------- */\n\n/** Slightly heavier line than the artwork, in glyph user units. */\nconst GLYPH_STROKE = 0.45;\n\n// The box is a kit size, never a literal: the ring is `size-8` (32px, the\n// Avatar `sm` size) and the glyph inside it is a medium kit icon\n// (`--icon-size-md`, 20px). The row that holds the icon keeps the 44px touch\n// target. The text colour is the forced-colours fallback (currentColor\n// becomes CanvasText there).\nconst iconVariants = cva(\n 'ds:relative ds:inline-grid ds:size-8 ds:shrink-0 ds:place-items-center ds:text-[color:var(--primary)]',\n);\n\nconst STOP_PRIMARY = 'ds:[stop-color:var(--primary)]';\nconst STOP_ACCENT = 'ds:[stop-color:var(--accent)]';\nconst FORCED_INK =\n 'ds:forced-colors:[fill:currentColor] ds:forced-colors:[stroke:currentColor]';\n\nconst glyphCache = new Map<SpecialtyIconId, SpecialtyGlyph>();\nconst glyphRequests = new Map<SpecialtyIconId, Promise<SpecialtyGlyph>>();\n\nfunction requestGlyph(id: SpecialtyIconId): Promise<SpecialtyGlyph> {\n let request = glyphRequests.get(id);\n if (!request) {\n request = SPECIALTY_GLYPH_LOADERS[id]().then((module) => {\n glyphCache.set(id, module.default);\n return module.default;\n });\n // A failed request is forgotten, so a later render can try again.\n request.catch(() => glyphRequests.delete(id));\n glyphRequests.set(id, request);\n }\n return request;\n}\n\n/** The glyph for an id: `undefined` until its module has loaded. */\nfunction useGlyph(id: SpecialtyIconId): SpecialtyGlyph | undefined {\n const [, update] = useReducer((count: number) => count + 1, 0);\n const cached = glyphCache.get(id);\n useEffect(() => {\n if (glyphCache.has(id)) return;\n let live = true;\n requestGlyph(id).then(\n () => {\n if (live) update();\n },\n () => {\n // The glyph stays blank: the ring (or empty box) is still drawn.\n },\n );\n return () => {\n live = false;\n };\n }, [id]);\n return cached;\n}\n\n/**\n * The icon id for a profession key. A key that is not in the map, or an\n * unknown icon id, gives the health cross.\n */\nexport function resolveSpecialtyIconId(\n specialty?: string,\n icon?: string,\n): SpecialtyIconId {\n if (icon && Object.hasOwn(SPECIALTY_GLYPH_LOADERS, icon)) {\n return icon as SpecialtyIconId;\n }\n if (specialty && Object.hasOwn(SPECIALTY_MAP, specialty)) {\n return SPECIALTY_MAP[specialty].icon;\n }\n return SPECIALTY_FALLBACK_ICON;\n}\n\nexport interface SpecialtyIconProps extends Omit<\n HTMLAttributes<HTMLSpanElement>,\n 'children' | 'aria-hidden'\n> {\n /**\n * Profession key: the platform's profession seoUrl slug, for example\n * `dentista` or `medico-di-base`. A key the kit does not know shows the\n * health cross.\n */\n specialty?: string;\n /** Icon id (for example `tooth`). Wins over `specialty` when both are set. */\n icon?: string;\n}\n\nexport const SpecialtyIcon = forwardRef<HTMLSpanElement, SpecialtyIconProps>(\n ({ specialty, icon, className, ...rest }, ref) => {\n // The id feeds `url(#…)`, so keep to characters that need no escaping.\n const uid = useId().replace(/[^a-zA-Z0-9_-]/g, '');\n const ringGradientId = `${uid}-ring`;\n const glyphGradientId = `${uid}-glyph`;\n\n const id = resolveSpecialtyIconId(specialty, icon);\n const glyph = useGlyph(id);\n\n let bounds: [number, number, number, number] | undefined;\n if (glyph) {\n const [x, y, w, h] = glyph.viewBox.split(' ').map(Number);\n bounds = [x, y, w, h];\n }\n const paint = `url(#${glyphGradientId})`;\n\n return (\n <span\n ref={ref}\n aria-hidden=\"true\"\n data-component=\"specialty-icon\"\n data-icon={id}\n className={iconVariants({ className })}\n {...rest}\n >\n {/* The ring fills the box. Its width is a kit border token and does\n not scale with the box (`non-scaling-stroke`); the inset keeps the\n whole stroke inside the box. */}\n <svg\n focusable=\"false\"\n className=\"ds:absolute ds:inset-[calc(var(--border-width-sm)/2)] ds:size-[calc(100%-var(--border-width-sm))] ds:overflow-visible\"\n >\n <defs>\n <linearGradient id={ringGradientId} x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0\" className={STOP_PRIMARY} />\n <stop offset=\"1\" className={STOP_ACCENT} />\n </linearGradient>\n </defs>\n <circle\n cx=\"50%\"\n cy=\"50%\"\n r=\"50%\"\n fill=\"none\"\n vectorEffect=\"non-scaling-stroke\"\n stroke={`url(#${ringGradientId})`}\n className=\"ds:[stroke-width:var(--border-width-sm)] ds:forced-colors:[stroke:currentColor]\"\n />\n </svg>\n {glyph && bounds ? (\n <svg\n focusable=\"false\"\n viewBox={glyph.viewBox}\n className=\"ds:relative ds:size-[var(--icon-size-md)]\"\n >\n <defs>\n <linearGradient\n id={glyphGradientId}\n gradientUnits=\"userSpaceOnUse\"\n x1={bounds[0]}\n y1={bounds[1]}\n x2={bounds[0] + bounds[2]}\n y2={bounds[1] + bounds[3]}\n >\n <stop offset=\"0\" className={STOP_PRIMARY} />\n <stop offset=\"1\" className={STOP_ACCENT} />\n </linearGradient>\n </defs>\n {glyph.paths.map((path, index) => (\n <path\n key={index}\n d={path.d}\n fill={paint}\n stroke={paint}\n strokeWidth={GLYPH_STROKE}\n strokeLinejoin=\"round\"\n paintOrder=\"stroke\"\n fillRule={path.evenodd ? 'evenodd' : 'nonzero'}\n clipRule={path.evenodd ? 'evenodd' : 'nonzero'}\n className={FORCED_INK}\n />\n ))}\n </svg>\n ) : null}\n </span>\n );\n },\n);\n\nSpecialtyIcon.displayName = 'SpecialtyIcon';\n"],"names":["SPECIALTY_GLYPH_LOADERS","SPECIALTY_ICON_IDS","SPECIALTY_MAP","SPECIALTY_FALLBACK_ICON","GLYPH_STROKE","iconVariants","cva","STOP_PRIMARY","STOP_ACCENT","FORCED_INK","glyphCache","glyphRequests","requestGlyph","id","request","module","useGlyph","update","useReducer","count","cached","useEffect","live","resolveSpecialtyIconId","specialty","icon","SpecialtyIcon","forwardRef","className","rest","ref","uid","useId","ringGradientId","glyphGradientId","glyph","bounds","x","y","w","h","paint","jsxs","jsx","path","index"],"mappings":";;;AAMO,MAAMA,IAA0B;AAAA,EACrC,iBAAiB,MAAM,OAAO,6BAAwB;AAAA,EACtD,WAAW,MAAM,OAAO,yBAAoB;AAAA,EAC5C,UAAU,MAAM,OAAO,wBAAmB;AAAA,EAC1C,MAAM,MAAM,OAAO,oBAAe;AAAA,EAClC,eAAe,MAAM,OAAO,2BAAsB;AAAA,EAClD,gBAAgB,MAAM,OAAO,4BAAuB;AAAA,EACpD,QAAQ,MAAM,OAAO,sBAAiB;AAAA,EACtC,QAAQ,MAAM,OAAO,sBAAiB;AAAA,EACtC,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,mBAAmB,MAAM,OAAO,+BAA0B;AAAA,EAC1D,kBAAkB,MAAM,OAAO,8BAAyB;AAAA,EACxD,aAAa,MAAM,OAAO,2BAAsB;AAAA,EAChD,UAAU,MAAM,OAAO,wBAAmB;AAAA,EAC1C,KAAK,MAAM,OAAO,mBAAc;AAAA,EAChC,QAAQ,MAAM,OAAO,sBAAiB;AAAA,EACtC,wBAAwB,MAAM,OAAO,oCAA+B;AAAA,EACpE,YAAY,MAAM,OAAO,wBAAmB;AAAA,EAC5C,UAAU,MAAM,OAAO,wBAAmB;AAAA,EAC1C,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,MAAM,MAAM,OAAO,oBAAe;AAAA,EAClC,QAAQ,MAAM,OAAO,sBAAiB;AAAA,EACtC,mBAAmB,MAAM,OAAO,+BAA0B;AAAA,EAC1D,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,4BAA4B,MAAM,OAAO,wCAAmC;AAAA,EAC5E,KAAK,MAAM,OAAO,mBAAc;AAAA,EAChC,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,MAAM,MAAM,OAAO,oBAAe;AAAA,EAClC,gBAAgB,MAAM,OAAO,4BAAuB;AAAA,EACpD,iBAAiB,MAAM,OAAO,6BAAwB;AAAA,EACtD,eAAe,MAAM,OAAO,2BAAsB;AAAA,EAClD,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,SAAS,MAAM,OAAO,uBAAkB;AAAA,EACxC,mBAAmB,MAAM,OAAO,+BAA0B;AAAA,EAC1D,OAAO,MAAM,OAAO,qBAAgB;AAAA,EACpC,eAAe,MAAM,OAAO,2BAAsB;AAAA,EAClD,eAAe,MAAM,OAAO,6BAAwB;AAAA,EACpD,oBAAoB,MAAM,OAAO,gCAA2B;AAAA,EAC5D,yBAAyB,MAAM,OAAO,qCAAgC;AAAA,EACtE,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,OAAO,MAAM,OAAO,qBAAgB;AAAA,EACpC,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,OAAO,MAAM,OAAO,qBAAgB;AAAA,EACpC,iBAAiB,MAAM,OAAO,6BAAwB;AAAA,EACtD,WAAW,MAAM,OAAO,yBAAoB;AAAA,EAC5C,OAAO,MAAM,OAAO,qBAAgB;AAAA,EACpC,iBAAiB,MAAM,OAAO,+BAA0B;AAAA,EACxD,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,sBAAsB,MAAM,OAAO,kCAA6B;AAAA,EAChE,UAAU,MAAM,OAAO,wBAAmB;AAAA,EAC1C,cAAc,MAAM,OAAO,4BAAuB;AAAA,EAClD,cAAc,MAAM,OAAO,4BAAuB;AAAA,EAClD,WAAW,MAAM,OAAO,yBAAoB;AAAA,EAC5C,MAAM,MAAM,OAAO,oBAAe;AAAA,EAClC,qBAAqB,MAAM,OAAO,iCAA4B;AAAA,EAC9D,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,oBAAoB,MAAM,OAAO,gCAA2B;AAAA,EAC5D,QAAQ,MAAM,OAAO,sBAAiB;AAAA,EACtC,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,WAAW,MAAM,OAAO,yBAAoB;AAAA,EAC5C,aAAa,MAAM,OAAO,2BAAsB;AAAA,EAChD,cAAc,MAAM,OAAO,4BAAuB;AAAA,EAClD,8BAA8B,MAC5B,OAAO,0CAAqC;AAAA,EAC9C,eAAe,MAAM,OAAO,2BAAsB;AAAA,EAClD,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,6BAA6B,MAC3B,OAAO,yCAAoC;AAAA,EAC7C,OAAO,MAAM,OAAO,qBAAgB;AAAA,EACpC,aAAa,MAAM,OAAO,2BAAsB;AAAA,EAChD,UAAU,MAAM,OAAO,wBAAmB;AAAA,EAC1C,SAAS,MAAM,OAAO,uBAAkB;AAAA,EACxC,SAAS,MAAM,OAAO,uBAAkB;AAAA,EACxC,WAAW,MAAM,OAAO,yBAAoB;AAAA,EAC5C,SAAS,MAAM,OAAO,uBAAkB;AAAA,EACxC,OAAO,MAAM,OAAO,qBAAgB;AAAA,EACpC,SAAS,MAAM,OAAO,uBAAkB;AAAA,EACxC,iBAAiB,MAAM,OAAO,6BAAwB;AAAA,EACtD,oBAAoB,MAAM,OAAO,gCAA2B;AAAA,EAC5D,YAAY,MAAM,OAAO,0BAAqB;AAAA,EAC9C,MAAM,MAAM,OAAO,oBAAe;AACpC,GAIaC,IAAqB,OAAO;AAAA,EACvCD;AACF,GCjFaE,IAAmD;AAAA,EAC9D,YAAY,EAAE,MAAM,iBAAiB,OAAO,wBAAA;AAAA,EAC5C,aAAa,EAAE,MAAM,aAAa,OAAO,mBAAA;AAAA,EACzC,WAAW,EAAE,MAAM,aAAa,OAAO,mBAAA;AAAA,EACvC,aAAa,EAAE,MAAM,WAAW,OAAO,mBAAA;AAAA,EACvC,WAAW,EAAE,MAAM,gBAAgB,OAAO,mBAAA;AAAA,EAC1C,SAAS,EAAE,MAAM,cAAc,OAAO,cAAA;AAAA,EACtC,gBAAgB,EAAE,MAAM,eAAe,OAAO,UAAA;AAAA,EAC9C,YAAY,EAAE,MAAM,cAAc,OAAO,mBAAA;AAAA,EACzC,cAAc,EAAE,MAAM,SAAS,OAAO,iBAAA;AAAA,EACtC,sBAAsB,EAAE,MAAM,SAAS,OAAO,UAAA;AAAA,EAC9C,UAAU,EAAE,MAAM,mBAAmB,OAAO,UAAA;AAAA,EAC5C,qBAAqB,EAAE,MAAM,mBAAmB,OAAO,UAAA;AAAA,EACvD,4BAA4B,EAAE,MAAM,iBAAiB,OAAO,UAAA;AAAA,EAC5D,uBAAuB,EAAE,MAAM,qBAAqB,OAAO,UAAA;AAAA,EAC3D,qBAAqB,EAAE,MAAM,eAAe,OAAO,UAAA;AAAA,EACnD,sBAAsB,EAAE,MAAM,oBAAoB,OAAO,UAAA;AAAA,EACzD,UAAU,EAAE,MAAM,SAAS,OAAO,YAAA;AAAA,EAClC,aAAa,EAAE,MAAM,eAAe,OAAO,mBAAA;AAAA,EAC3C,aAAa,EAAE,MAAM,YAAY,OAAO,mBAAA;AAAA,EACxC,UAAU,EAAE,MAAM,cAAc,OAAO,YAAA;AAAA,EACvC,WAAW,EAAE,MAAM,cAAc,OAAO,YAAA;AAAA,EACxC,aAAa,EAAE,MAAM,cAAc,OAAO,cAAA;AAAA,EAC1C,2CAA2C;AAAA,IACzC,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,WAAW,EAAE,MAAM,eAAe,OAAO,mBAAA;AAAA,EACzC,mBAAmB,EAAE,MAAM,WAAW,OAAO,UAAA;AAAA,EAC7C,eAAe,EAAE,MAAM,WAAW,OAAO,mBAAA;AAAA,EACzC,cAAc,EAAE,MAAM,SAAS,OAAO,YAAA;AAAA,EACtC,WAAW,EAAE,MAAM,cAAc,OAAO,mBAAA;AAAA,EACxC,UAAU,EAAE,MAAM,oBAAoB,OAAO,iBAAA;AAAA,EAC7C,gBAAgB,EAAE,MAAM,oBAAoB,OAAO,iBAAA;AAAA,EACnD,WAAW,EAAE,MAAM,iBAAiB,OAAO,mBAAA;AAAA,EAC3C,kBAAkB,EAAE,MAAM,WAAW,OAAO,mBAAA;AAAA,EAC5C,WAAW,EAAE,MAAM,OAAO,OAAO,cAAA;AAAA,EACjC,UAAU,EAAE,MAAM,cAAc,OAAO,kBAAA;AAAA,EACvC,YAAY,EAAE,MAAM,cAAc,OAAO,mBAAA;AAAA,EACzC,WAAW,EAAE,MAAM,SAAS,OAAO,YAAA;AAAA,EACnC,WAAW,EAAE,MAAM,kBAAkB,OAAO,YAAA;AAAA,EAC5C,qBAAqB,EAAE,MAAM,kBAAkB,OAAO,YAAA;AAAA,EACtD,YAAY,EAAE,MAAM,YAAY,OAAO,mBAAA;AAAA,EACvC,cAAc,EAAE,MAAM,sBAAsB,OAAO,YAAA;AAAA,EACnD,YAAY,EAAE,MAAM,SAAS,OAAO,kBAAA;AAAA,EACpC,YAAY,EAAE,MAAM,eAAe,OAAO,kBAAA;AAAA,EAC1C,aAAa,EAAE,MAAM,YAAY,OAAO,iBAAA;AAAA,EACxC,WAAW,EAAE,MAAM,eAAe,OAAO,mBAAA;AAAA,EACzC,aAAa,EAAE,MAAM,6BAA6B,OAAO,iBAAA;AAAA,EACzD,qBAAqB,EAAE,MAAM,oBAAoB,OAAO,iBAAA;AAAA,EACxD,gBAAgB,EAAE,MAAM,oBAAoB,OAAO,iBAAA;AAAA,EACnD,mBAAmB,EAAE,MAAM,UAAU,OAAO,kBAAA;AAAA,EAC5C,qBAAqB,EAAE,MAAM,iBAAiB,OAAO,kBAAA;AAAA,EACrD,qBAAqB,EAAE,MAAM,iBAAiB,OAAO,kBAAA;AAAA,EACrD,sBAAsB,EAAE,MAAM,OAAO,OAAO,mBAAA;AAAA,EAC5C,kBAAkB,EAAE,MAAM,UAAU,OAAO,kBAAA;AAAA,EAC3C,sBAAsB,EAAE,MAAM,UAAU,OAAO,kBAAA;AAAA,EAC/C,+BAA+B,EAAE,MAAM,UAAU,OAAO,kBAAA;AAAA,EACxD,mBAAmB,EAAE,MAAM,eAAe,OAAO,mBAAA;AAAA,EACjD,mBAAmB,EAAE,MAAM,UAAU,OAAO,kBAAA;AAAA,EAC5C,oBAAoB,EAAE,MAAM,OAAO,OAAO,cAAA;AAAA,EAC1C,iBAAiB,EAAE,MAAM,WAAW,OAAO,kBAAA;AAAA,EAC3C,mBAAmB;AAAA,IACjB,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,YAAY,EAAE,MAAM,YAAY,OAAO,wBAAA;AAAA,EACvC,WAAW,EAAE,MAAM,cAAc,OAAO,mBAAA;AAAA,EACxC,eAAe,EAAE,MAAM,iBAAiB,OAAO,UAAA;AAAA,EAC/C,oBAAoB,EAAE,MAAM,SAAS,OAAO,cAAA;AAAA,EAC5C,WAAW,EAAE,MAAM,aAAa,OAAO,mBAAA;AAAA,EACvC,6BAA6B;AAAA,IAC3B,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,gBAAgB,EAAE,MAAM,cAAc,OAAO,eAAA;AAAA,EAC7C,sBAAsB,EAAE,MAAM,mBAAmB,OAAO,iBAAA;AAAA,EACxD,sBAAsB,EAAE,MAAM,UAAU,OAAO,YAAA;AAAA,EAC/C,eAAe,EAAE,MAAM,UAAU,OAAO,YAAA;AAAA,EACxC,UAAU,EAAE,MAAM,gBAAgB,OAAO,mBAAA;AAAA,EACzC,aAAa,EAAE,MAAM,cAAc,OAAO,YAAA;AAAA,EAC1C,UAAU,EAAE,MAAM,mBAAmB,OAAO,wBAAA;AAAA,EAC5C,gBAAgB,EAAE,MAAM,mBAAmB,OAAO,wBAAA;AAAA,EAClD,UAAU,EAAE,MAAM,YAAY,OAAO,mBAAA;AAAA,EACrC,cAAc,EAAE,MAAM,UAAU,OAAO,YAAA;AAAA,EACvC,YAAY,EAAE,MAAM,gBAAgB,OAAO,mBAAA;AAAA,EAC3C,YAAY,EAAE,MAAM,cAAc,OAAO,iBAAA;AAAA,EACzC,WAAW,EAAE,MAAM,SAAS,OAAO,iBAAA;AAAA,EACnC,WAAW,EAAE,MAAM,mBAAmB,OAAO,mBAAA;AAAA,EAC7C,SAAS,EAAE,MAAM,wBAAwB,OAAO,mBAAA;AAAA,EAChD,qBAAqB;AAAA,IACnB,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,eAAe,EAAE,MAAM,SAAS,OAAO,YAAA;AAAA,EACvC,UAAU,EAAE,MAAM,cAAc,OAAO,mBAAA;AAAA,EACvC,cAAc,EAAE,MAAM,SAAS,OAAO,YAAA;AAAA,EACtC,YAAY,EAAE,MAAM,eAAe,OAAO,mBAAA;AAAA,EAC1C,UAAU,EAAE,MAAM,QAAQ,OAAO,iBAAA;AAAA,EACjC,aAAa,EAAE,MAAM,SAAS,OAAO,iBAAA;AAAA,EACrC,YAAY,EAAE,MAAM,QAAQ,OAAO,mBAAA;AAAA,EACnC,YAAY,EAAE,MAAM,sBAAsB,OAAO,YAAA;AAAA,EACjD,YAAY,EAAE,MAAM,oBAAoB,OAAO,eAAA;AAAA,EAC/C,eAAe,EAAE,MAAM,cAAc,OAAO,eAAA;AAAA,EAC5C,WAAW,EAAE,MAAM,cAAc,OAAO,eAAA;AAAA,EACxC,qBAAqB,EAAE,MAAM,cAAc,OAAO,eAAA;AAAA,EAClD,wBAAwB,EAAE,MAAM,cAAc,OAAO,eAAA;AAAA,EACrD,yBAAyB,EAAE,MAAM,cAAc,OAAO,eAAA;AAAA,EACtD,qBAAqB,EAAE,MAAM,cAAc,OAAO,eAAA;AAAA,EAClD,iBAAiB,EAAE,MAAM,mBAAmB,OAAO,iBAAA;AAAA,EACnD,gCAAgC;AAAA,IAC9B,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,gBAAgB,EAAE,MAAM,yBAAyB,OAAO,eAAA;AAAA,EACxD,oBAAoB,EAAE,MAAM,aAAa,OAAO,wBAAA;AAAA,EAChD,WAAW,EAAE,MAAM,aAAa,OAAO,cAAA;AAAA,EACvC,aAAa,EAAE,MAAM,gBAAgB,OAAO,mBAAA;AAAA,EAC5C,UAAU,EAAE,MAAM,UAAU,OAAO,mBAAA;AAAA,EACnC,YAAY,EAAE,MAAM,8BAA8B,OAAO,eAAA;AAAA,EACzD,sBAAsB,EAAE,MAAM,aAAa,OAAO,iBAAA;AAAA,EAClD,0CAA0C;AAAA,IACxC,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,wBAAwB,EAAE,MAAM,QAAQ,OAAO,mBAAA;AAAA,EAC/C,aAAa,EAAE,MAAM,UAAU,OAAO,cAAA;AAAA,EACtC,WAAW,EAAE,MAAM,QAAQ,OAAO,mBAAA;AAAA,EAClC,SAAS,EAAE,MAAM,WAAW,OAAO,mBAAA;AAAA,EACnC,WAAW,EAAE,MAAM,YAAY,OAAO,mBAAA;AACxC,GAGaC,IAA2C,gBCxHlDC,IAAe,MAOfC,IAAeC;AAAA,EACnB;AACF,GAEMC,IAAe,kCACfC,IAAc,iCACdC,IACJ,+EAEIC,wBAAiB,IAAA,GACjBC,wBAAoB,IAAA;AAE1B,SAASC,EAAaC,GAA8C;AAClE,MAAIC,IAAUH,EAAc,IAAIE,CAAE;AAClC,SAAKC,MACHA,IAAUd,EAAwBa,CAAE,EAAA,EAAI,KAAK,CAACE,OAC5CL,EAAW,IAAIG,GAAIE,EAAO,OAAO,GAC1BA,EAAO,QACf,GAEDD,EAAQ,MAAM,MAAMH,EAAc,OAAOE,CAAE,CAAC,GAC5CF,EAAc,IAAIE,GAAIC,CAAO,IAExBA;AACT;AAGA,SAASE,EAASH,GAAiD;AACjE,QAAM,CAAA,EAAGI,CAAM,IAAIC,EAAW,CAACC,MAAkBA,IAAQ,GAAG,CAAC,GACvDC,IAASV,EAAW,IAAIG,CAAE;AAChC,SAAAQ,EAAU,MAAM;AACd,QAAIX,EAAW,IAAIG,CAAE,EAAG;AACxB,QAAIS,IAAO;AACX,WAAAV,EAAaC,CAAE,EAAE;AAAA,MACf,MAAM;AACJ,QAAIS,KAAML,EAAA;AAAA,MACZ;AAAA,MACA,MAAM;AAAA,MAEN;AAAA,IAAA,GAEK,MAAM;AACX,MAAAK,IAAO;AAAA,IACT;AAAA,EACF,GAAG,CAACT,CAAE,CAAC,GACAO;AACT;AAMO,SAASG,EACdC,GACAC,GACiB;AACjB,SAAIA,KAAQ,OAAO,OAAOzB,GAAyByB,CAAI,IAC9CA,IAELD,KAAa,OAAO,OAAOtB,GAAesB,CAAS,IAC9CtB,EAAcsB,CAAS,EAAE,OAE3BrB;AACT;AAgBO,MAAMuB,IAAgBC;AAAA,EAC3B,CAAC,EAAE,WAAAH,GAAW,MAAAC,GAAM,WAAAG,GAAW,GAAGC,EAAA,GAAQC,MAAQ;AAEhD,UAAMC,IAAMC,EAAA,EAAQ,QAAQ,mBAAmB,EAAE,GAC3CC,IAAiB,GAAGF,CAAG,SACvBG,IAAkB,GAAGH,CAAG,UAExBlB,IAAKU,EAAuBC,GAAWC,CAAI,GAC3CU,IAAQnB,EAASH,CAAE;AAEzB,QAAIuB;AACJ,QAAID,GAAO;AACT,YAAM,CAACE,GAAGC,GAAGC,GAAGC,CAAC,IAAIL,EAAM,QAAQ,MAAM,GAAG,EAAE,IAAI,MAAM;AACxD,MAAAC,IAAS,CAACC,GAAGC,GAAGC,GAAGC,CAAC;AAAA,IACtB;AACA,UAAMC,IAAQ,QAAQP,CAAe;AAErC,WACE,gBAAAQ;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAZ;AAAA,QACA,eAAY;AAAA,QACZ,kBAAe;AAAA,QACf,aAAWjB;AAAA,QACX,WAAWR,EAAa,EAAE,WAAAuB,GAAW;AAAA,QACpC,GAAGC;AAAA,QAKJ,UAAA;AAAA,UAAA,gBAAAa;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,WAAU;AAAA,cAEV,UAAA;AAAA,gBAAA,gBAAAC,EAAC,QAAA,EACC,UAAA,gBAAAD,EAAC,kBAAA,EAAe,IAAIT,GAAgB,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,KAC1D,UAAA;AAAA,kBAAA,gBAAAU,EAAC,QAAA,EAAK,QAAO,KAAI,WAAWpC,GAAc;AAAA,kBAC1C,gBAAAoC,EAAC,QAAA,EAAK,QAAO,KAAI,WAAWnC,EAAA,CAAa;AAAA,gBAAA,EAAA,CAC3C,EAAA,CACF;AAAA,gBACA,gBAAAmC;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,IAAG;AAAA,oBACH,IAAG;AAAA,oBACH,GAAE;AAAA,oBACF,MAAK;AAAA,oBACL,cAAa;AAAA,oBACb,QAAQ,QAAQV,CAAc;AAAA,oBAC9B,WAAU;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACZ;AAAA,YAAA;AAAA,UAAA;AAAA,UAEDE,KAASC,IACR,gBAAAM;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,SAASP,EAAM;AAAA,cACf,WAAU;AAAA,cAEV,UAAA;AAAA,gBAAA,gBAAAQ,EAAC,QAAA,EACC,UAAA,gBAAAD;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,IAAIR;AAAA,oBACJ,eAAc;AAAA,oBACd,IAAIE,EAAO,CAAC;AAAA,oBACZ,IAAIA,EAAO,CAAC;AAAA,oBACZ,IAAIA,EAAO,CAAC,IAAIA,EAAO,CAAC;AAAA,oBACxB,IAAIA,EAAO,CAAC,IAAIA,EAAO,CAAC;AAAA,oBAExB,UAAA;AAAA,sBAAA,gBAAAO,EAAC,QAAA,EAAK,QAAO,KAAI,WAAWpC,GAAc;AAAA,sBAC1C,gBAAAoC,EAAC,QAAA,EAAK,QAAO,KAAI,WAAWnC,EAAA,CAAa;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA,GAE7C;AAAA,gBACC2B,EAAM,MAAM,IAAI,CAACS,GAAMC,MACtB,gBAAAF;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,GAAGC,EAAK;AAAA,oBACR,MAAMH;AAAA,oBACN,QAAQA;AAAA,oBACR,aAAarC;AAAA,oBACb,gBAAe;AAAA,oBACf,YAAW;AAAA,oBACX,UAAUwC,EAAK,UAAU,YAAY;AAAA,oBACrC,UAAUA,EAAK,UAAU,YAAY;AAAA,oBACrC,WAAWnC;AAAA,kBAAA;AAAA,kBATNoC;AAAA,gBAAA,CAWR;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA,IAED;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEAnB,EAAc,cAAc;"}
1
+ {"version":3,"file":"specialty-icon-BkpExzMh.js","sources":["../../src/components/specialty-icon/glyph-loaders.ts","../../src/components/specialty-icon/specialty-map.ts","../../src/components/specialty-icon/specialty-icon.tsx"],"sourcesContent":["// Generated by scripts/build-specialty-icons.mjs. Do not edit by hand.\n// Glyph artwork: Healthicons, CC0 1.0 Universal (public domain).\n// https://github.com/resolvetosavelives/healthicons\nimport type { SpecialtyGlyph } from './specialty-glyph';\n\n/** One dynamic import per glyph, so a page only downloads what it renders. */\nexport const SPECIALTY_GLYPH_LOADERS = {\n 'acupuncture-1': () => import('./glyphs/acupuncture-1'),\n allergies: () => import('./glyphs/allergies'),\n antibody: () => import('./glyphs/antibody'),\n anus: () => import('./glyphs/anus'),\n 'blood-cells': () => import('./glyphs/blood-cells'),\n 'blood-vessel': () => import('./glyphs/blood-vessel'),\n braces: () => import('./glyphs/braces'),\n breast: () => import('./glyphs/breast'),\n cardiology: () => import('./glyphs/cardiology'),\n 'child-cognition': () => import('./glyphs/child-cognition'),\n 'dental-hygiene': () => import('./glyphs/dental-hygiene'),\n dermatology: () => import('./glyphs/dermatology'),\n diabetes: () => import('./glyphs/diabetes'),\n dna: () => import('./glyphs/dna'),\n doctor: () => import('./glyphs/doctor'),\n 'ears-nose-and-throat': () => import('./glyphs/ears-nose-and-throat'),\n 'eco-care': () => import('./glyphs/eco-care'),\n exercise: () => import('./glyphs/exercise'),\n eyeglasses: () => import('./glyphs/eyeglasses'),\n foot: () => import('./glyphs/foot'),\n fruits: () => import('./glyphs/fruits'),\n 'general-surgery': () => import('./glyphs/general-surgery'),\n geriatrics: () => import('./glyphs/geriatrics'),\n 'group-discussion-meeting': () => import('./glyphs/group-discussion-meeting'),\n gym: () => import('./glyphs/gym'),\n gynecology: () => import('./glyphs/gynecology'),\n head: () => import('./glyphs/head'),\n 'health-cross': () => import('./glyphs/health-cross'),\n 'health-worker': () => import('./glyphs/health-worker'),\n 'heart-organ': () => import('./glyphs/heart-organ'),\n hepatology: () => import('./glyphs/hepatology'),\n justice: () => import('./glyphs/justice'),\n 'liquid-medicine': () => import('./glyphs/liquid-medicine'),\n lungs: () => import('./glyphs/lungs'),\n 'lymph-nodes': () => import('./glyphs/lymph-nodes'),\n maxillofacial: () => import('./glyphs/maxillofacial'),\n 'mental-disorders': () => import('./glyphs/mental-disorders'),\n 'mental-health-therapy': () => import('./glyphs/mental-health-therapy'),\n microscope: () => import('./glyphs/microscope'),\n mouth: () => import('./glyphs/mouth'),\n nephrology: () => import('./glyphs/nephrology'),\n nerve: () => import('./glyphs/nerve'),\n 'neuro-surgery': () => import('./glyphs/neuro-surgery'),\n neurology: () => import('./glyphs/neurology'),\n nurse: () => import('./glyphs/nurse'),\n obstetricsmonia: () => import('./glyphs/obstetricsmonia'),\n odontology: () => import('./glyphs/odontology'),\n 'odontology-implant': () => import('./glyphs/odontology-implant'),\n oncology: () => import('./glyphs/oncology'),\n opthalmology: () => import('./glyphs/opthalmology'),\n orthopaedics: () => import('./glyphs/orthopaedics'),\n orthotics: () => import('./glyphs/orthotics'),\n pain: () => import('./glyphs/pain'),\n 'pediatric-surgery': () => import('./glyphs/pediatric-surgery'),\n pediatrics: () => import('./glyphs/pediatrics'),\n 'physical-therapy': () => import('./glyphs/physical-therapy'),\n poison: () => import('./glyphs/poison'),\n psychology: () => import('./glyphs/psychology'),\n radiology: () => import('./glyphs/radiology'),\n respirology: () => import('./glyphs/respirology'),\n rheumatology: () => import('./glyphs/rheumatology'),\n 'sexual-reproductive-health': () =>\n import('./glyphs/sexual-reproductive-health'),\n 'skin-layers': () => import('./glyphs/skin-layers'),\n sonography: () => import('./glyphs/sonography'),\n 'speech-language-therapist': () =>\n import('./glyphs/speech-language-therapist'),\n spine: () => import('./glyphs/spine'),\n stethoscope: () => import('./glyphs/stethoscope'),\n stitches: () => import('./glyphs/stitches'),\n stomach: () => import('./glyphs/stomach'),\n syringe: () => import('./glyphs/syringe'),\n testicles: () => import('./glyphs/testicles'),\n thyroid: () => import('./glyphs/thyroid'),\n tooth: () => import('./glyphs/tooth'),\n urology: () => import('./glyphs/urology'),\n 'varicose-vein': () => import('./glyphs/varicose-vein'),\n 'vascular-surgery': () => import('./glyphs/vascular-surgery'),\n vegetables: () => import('./glyphs/vegetables'),\n xray: () => import('./glyphs/xray'),\n} satisfies Record<string, () => Promise<{ default: SpecialtyGlyph }>>;\n\nexport type SpecialtyIconId = keyof typeof SPECIALTY_GLYPH_LOADERS;\n\nexport const SPECIALTY_ICON_IDS = Object.keys(\n SPECIALTY_GLYPH_LOADERS,\n) as SpecialtyIconId[];\n","// Generated by scripts/build-specialty-icons.mjs. Do not edit by hand.\n// Glyph artwork: Healthicons, CC0 1.0 Universal (public domain).\n// https://github.com/resolvetosavelives/healthicons\nimport type { SpecialtyIconId } from './glyph-loaders';\n\nexport interface SpecialtyMapEntry {\n icon: SpecialtyIconId;\n /** Not used for layout yet: kept for a grouped list later. */\n group: string;\n}\n\n/** Profession key (the platform's profession seoUrl slug) to icon id. */\nexport const SPECIALTY_MAP: Record<string, SpecialtyMapEntry> = {\n agopuntura: { icon: 'acupuncture-1', group: 'complementaryMedicine' },\n allergologo: { icon: 'allergies', group: 'specialistVisits' },\n andrologo: { icon: 'testicles', group: 'specialistVisits' },\n anestesista: { icon: 'syringe', group: 'specialistVisits' },\n angiologo: { icon: 'blood-vessel', group: 'specialistVisits' },\n biologo: { icon: 'microscope', group: 'diagnostics' },\n cardiochirurgo: { icon: 'heart-organ', group: 'surgery' },\n cardiologo: { icon: 'cardiology', group: 'specialistVisits' },\n chiropratico: { icon: 'spine', group: 'rehabilitation' },\n 'chirurgia-toracica': { icon: 'lungs', group: 'surgery' },\n chirurgo: { icon: 'general-surgery', group: 'surgery' },\n 'chirurgo-generale': { icon: 'general-surgery', group: 'surgery' },\n 'chirurgo-maxillofacciale': { icon: 'maxillofacial', group: 'surgery' },\n 'chirurgo-pediatrico': { icon: 'pediatric-surgery', group: 'surgery' },\n 'chirurgo-plastico': { icon: 'skin-layers', group: 'surgery' },\n 'chirurgo-vascolare': { icon: 'vascular-surgery', group: 'surgery' },\n dentista: { icon: 'tooth', group: 'dentistry' },\n dermatologo: { icon: 'dermatology', group: 'specialistVisits' },\n diabetologo: { icon: 'diabetes', group: 'specialistVisits' },\n dietista: { icon: 'vegetables', group: 'nutrition' },\n dietologo: { icon: 'vegetables', group: 'nutrition' },\n ecografista: { icon: 'sonography', group: 'diagnostics' },\n 'educatore-professionale-socio-sanitario': {\n icon: 'group-discussion-meeting',\n group: 'mentalHealth',\n },\n ematologo: { icon: 'blood-cells', group: 'specialistVisits' },\n endocrinochirurgo: { icon: 'thyroid', group: 'surgery' },\n endocrinologo: { icon: 'thyroid', group: 'specialistVisits' },\n endodontista: { icon: 'tooth', group: 'dentistry' },\n epatologo: { icon: 'hepatology', group: 'specialistVisits' },\n fisiatra: { icon: 'physical-therapy', group: 'rehabilitation' },\n fisioterapista: { icon: 'physical-therapy', group: 'rehabilitation' },\n flebologo: { icon: 'varicose-vein', group: 'specialistVisits' },\n gastroenterologo: { icon: 'stomach', group: 'specialistVisits' },\n genetista: { icon: 'dna', group: 'diagnostics' },\n geriatra: { icon: 'geriatrics', group: 'generalMedicine' },\n ginecologo: { icon: 'gynecology', group: 'womenAndChildren' },\n gnatologo: { icon: 'mouth', group: 'dentistry' },\n igienista: { icon: 'dental-hygiene', group: 'dentistry' },\n 'igienista-dentale': { icon: 'dental-hygiene', group: 'dentistry' },\n immunologo: { icon: 'antibody', group: 'specialistVisits' },\n implantologo: { icon: 'odontology-implant', group: 'dentistry' },\n infermiere: { icon: 'nurse', group: 'generalMedicine' },\n internista: { icon: 'stethoscope', group: 'generalMedicine' },\n kinesiologo: { icon: 'exercise', group: 'rehabilitation' },\n linfologo: { icon: 'lymph-nodes', group: 'specialistVisits' },\n logopedista: { icon: 'speech-language-therapist', group: 'rehabilitation' },\n massofisioterapista: { icon: 'physical-therapy', group: 'rehabilitation' },\n massoterapista: { icon: 'physical-therapy', group: 'rehabilitation' },\n 'medico-chirurgo': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-competente': { icon: 'health-worker', group: 'generalMedicine' },\n 'medico-del-lavoro': { icon: 'health-worker', group: 'generalMedicine' },\n 'medico-dello-sport': { icon: 'gym', group: 'specialistVisits' },\n 'medico-di-base': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-di-famiglia': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-di-medicina-generale': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-estetico': { icon: 'skin-layers', group: 'specialistVisits' },\n 'medico-generico': { icon: 'doctor', group: 'generalMedicine' },\n 'medico-genetista': { icon: 'dna', group: 'diagnostics' },\n 'medico-legale': { icon: 'justice', group: 'generalMedicine' },\n 'medico-omeopata': {\n icon: 'liquid-medicine',\n group: 'complementaryMedicine',\n },\n naturopata: { icon: 'eco-care', group: 'complementaryMedicine' },\n nefrologo: { icon: 'nephrology', group: 'specialistVisits' },\n neurochirurgo: { icon: 'neuro-surgery', group: 'surgery' },\n neurofisiopatologo: { icon: 'nerve', group: 'diagnostics' },\n neurologo: { icon: 'neurology', group: 'specialistVisits' },\n 'neuropsichiatra-infantile': {\n icon: 'child-cognition',\n group: 'womenAndChildren',\n },\n neuropsicologo: { icon: 'psychology', group: 'mentalHealth' },\n neuropsicomotricista: { icon: 'child-cognition', group: 'rehabilitation' },\n 'nutrizione-clinica': { icon: 'fruits', group: 'nutrition' },\n nutrizionista: { icon: 'fruits', group: 'nutrition' },\n oculista: { icon: 'opthalmology', group: 'specialistVisits' },\n odontoiatra: { icon: 'odontology', group: 'dentistry' },\n omeopata: { icon: 'liquid-medicine', group: 'complementaryMedicine' },\n omotossicologo: { icon: 'liquid-medicine', group: 'complementaryMedicine' },\n oncologo: { icon: 'oncology', group: 'specialistVisits' },\n ortodontista: { icon: 'braces', group: 'dentistry' },\n ortopedico: { icon: 'orthopaedics', group: 'specialistVisits' },\n ortottista: { icon: 'eyeglasses', group: 'rehabilitation' },\n osteopata: { icon: 'spine', group: 'rehabilitation' },\n ostetrica: { icon: 'obstetricsmonia', group: 'womenAndChildren' },\n otorino: { icon: 'ears-nose-and-throat', group: 'specialistVisits' },\n otorinolaringoiatra: {\n icon: 'ears-nose-and-throat',\n group: 'specialistVisits',\n },\n parodontologo: { icon: 'tooth', group: 'dentistry' },\n pediatra: { icon: 'pediatrics', group: 'womenAndChildren' },\n pedodontista: { icon: 'tooth', group: 'dentistry' },\n pneumologo: { icon: 'respirology', group: 'specialistVisits' },\n podologo: { icon: 'foot', group: 'rehabilitation' },\n posturologo: { icon: 'spine', group: 'rehabilitation' },\n proctologo: { icon: 'anus', group: 'specialistVisits' },\n protesista: { icon: 'odontology-implant', group: 'dentistry' },\n psichiatra: { icon: 'mental-disorders', group: 'mentalHealth' },\n psicoanalista: { icon: 'psychology', group: 'mentalHealth' },\n psicologo: { icon: 'psychology', group: 'mentalHealth' },\n 'psicologo-clinico': { icon: 'psychology', group: 'mentalHealth' },\n 'psicologo-del-lavoro': { icon: 'psychology', group: 'mentalHealth' },\n 'psicologo-dello-sport': { icon: 'psychology', group: 'mentalHealth' },\n 'psicologo-forense': { icon: 'psychology', group: 'mentalHealth' },\n psicomotricista: { icon: 'child-cognition', group: 'rehabilitation' },\n psiconeuroendocrinoimmunologia: {\n icon: 'neurology',\n group: 'complementaryMedicine',\n },\n psicoterapeuta: { icon: 'mental-health-therapy', group: 'mentalHealth' },\n psiiconeurobiologo: { icon: 'neurology', group: 'complementaryMedicine' },\n radiologo: { icon: 'radiology', group: 'diagnostics' },\n reumatologo: { icon: 'rheumatology', group: 'specialistVisits' },\n senologo: { icon: 'breast', group: 'womenAndChildren' },\n sessuologo: { icon: 'sexual-reproductive-health', group: 'mentalHealth' },\n 'tecnico-ortopedico': { icon: 'orthotics', group: 'rehabilitation' },\n 'tecnico-sanitario-di-radiologia-medica': {\n icon: 'xray',\n group: 'diagnostics',\n },\n 'terapista-del-dolore': { icon: 'pain', group: 'specialistVisits' },\n tossicologo: { icon: 'poison', group: 'diagnostics' },\n tricologo: { icon: 'head', group: 'specialistVisits' },\n urologo: { icon: 'urology', group: 'specialistVisits' },\n vulnologo: { icon: 'stitches', group: 'specialistVisits' },\n} as Record<string, SpecialtyMapEntry>;\n\n/** Shown for a key that is not in the map. */\nexport const SPECIALTY_FALLBACK_ICON: SpecialtyIconId = 'health-cross';\n","import {\n forwardRef,\n useEffect,\n useId,\n useReducer,\n type HTMLAttributes,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { SPECIALTY_GLYPH_LOADERS, type SpecialtyIconId } from './glyph-loaders';\nimport { SPECIALTY_FALLBACK_ICON, SPECIALTY_MAP } from './specialty-map';\nimport type { SpecialtyGlyph } from './specialty-glyph';\n\n/* -------------------------------------------------------------------- */\n/* SpecialtyIcon */\n/* */\n/* A medical speciality glyph (Healthicons, CC0) drawn in the brand */\n/* gradient, inside a gradient ring. */\n/* */\n/* The icon is a fixed-size box (a kit token), so nothing moves while a */\n/* glyph loads. Glyphs are separate */\n/* modules, fetched with `import()` the first time an id is rendered and */\n/* kept in a module cache after that. */\n/* -------------------------------------------------------------------- */\n\n/** Slightly heavier line than the artwork, in glyph user units. */\nconst GLYPH_STROKE = 0.45;\n\n// The box is a kit size, never a literal: the ring is `size-8` (32px, the\n// Avatar `sm` size) and the glyph inside it is a medium kit icon\n// (`--icon-size-md`, 20px). The row that holds the icon keeps the 44px touch\n// target. The text colour is the forced-colours fallback (currentColor\n// becomes CanvasText there).\nconst iconVariants = cva(\n 'ds:relative ds:inline-grid ds:size-8 ds:shrink-0 ds:place-items-center ds:text-[color:var(--primary)]',\n);\n\nconst STOP_PRIMARY = 'ds:[stop-color:var(--primary)]';\nconst STOP_ACCENT = 'ds:[stop-color:var(--accent)]';\nconst FORCED_INK =\n 'ds:forced-colors:[fill:currentColor] ds:forced-colors:[stroke:currentColor]';\n\nconst glyphCache = new Map<SpecialtyIconId, SpecialtyGlyph>();\nconst glyphRequests = new Map<SpecialtyIconId, Promise<SpecialtyGlyph>>();\n\nfunction requestGlyph(id: SpecialtyIconId): Promise<SpecialtyGlyph> {\n let request = glyphRequests.get(id);\n if (!request) {\n request = SPECIALTY_GLYPH_LOADERS[id]().then((module) => {\n glyphCache.set(id, module.default);\n return module.default;\n });\n // A failed request is forgotten, so a later render can try again.\n request.catch(() => glyphRequests.delete(id));\n glyphRequests.set(id, request);\n }\n return request;\n}\n\n/** The glyph for an id: `undefined` until its module has loaded. */\nfunction useGlyph(id: SpecialtyIconId): SpecialtyGlyph | undefined {\n const [, update] = useReducer((count: number) => count + 1, 0);\n const cached = glyphCache.get(id);\n useEffect(() => {\n if (glyphCache.has(id)) return;\n let live = true;\n requestGlyph(id).then(\n () => {\n if (live) update();\n },\n () => {\n // The glyph stays blank: the ring (or empty box) is still drawn.\n },\n );\n return () => {\n live = false;\n };\n }, [id]);\n return cached;\n}\n\n/**\n * The icon id for a profession key. A key that is not in the map, or an\n * unknown icon id, gives the health cross.\n */\nexport function resolveSpecialtyIconId(\n specialty?: string,\n icon?: string,\n): SpecialtyIconId {\n if (icon && Object.hasOwn(SPECIALTY_GLYPH_LOADERS, icon)) {\n return icon as SpecialtyIconId;\n }\n if (specialty && Object.hasOwn(SPECIALTY_MAP, specialty)) {\n return SPECIALTY_MAP[specialty].icon;\n }\n return SPECIALTY_FALLBACK_ICON;\n}\n\nexport interface SpecialtyIconProps extends Omit<\n HTMLAttributes<HTMLSpanElement>,\n 'children' | 'aria-hidden'\n> {\n /**\n * Profession key: the platform's profession seoUrl slug, for example\n * `dentista` or `medico-di-base`. A key the kit does not know shows the\n * health cross.\n */\n specialty?: string;\n /** Icon id (for example `tooth`). Wins over `specialty` when both are set. */\n icon?: string;\n}\n\nexport const SpecialtyIcon = forwardRef<HTMLSpanElement, SpecialtyIconProps>(\n ({ specialty, icon, className, ...rest }, ref) => {\n // The id feeds `url(#…)`, so keep to characters that need no escaping.\n const uid = useId().replace(/[^a-zA-Z0-9_-]/g, '');\n const ringGradientId = `${uid}-ring`;\n const glyphGradientId = `${uid}-glyph`;\n\n const id = resolveSpecialtyIconId(specialty, icon);\n const glyph = useGlyph(id);\n\n let bounds: [number, number, number, number] | undefined;\n if (glyph) {\n const [x, y, w, h] = glyph.viewBox.split(' ').map(Number);\n bounds = [x, y, w, h];\n }\n const paint = `url(#${glyphGradientId})`;\n\n return (\n <span\n ref={ref}\n aria-hidden=\"true\"\n data-component=\"specialty-icon\"\n data-icon={id}\n className={iconVariants({ className })}\n {...rest}\n >\n {/* The ring fills the box. Its width is a kit border token and does\n not scale with the box (`non-scaling-stroke`); the inset keeps the\n whole stroke inside the box. `data-slot=\"ring\"` lets a host that\n draws its own frame (SpecialtyList's chips) hide it. */}\n <svg\n focusable=\"false\"\n data-slot=\"ring\"\n className=\"ds:absolute ds:inset-[calc(var(--border-width-sm)/2)] ds:size-[calc(100%-var(--border-width-sm))] ds:overflow-visible\"\n >\n <defs>\n <linearGradient id={ringGradientId} x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0\" className={STOP_PRIMARY} />\n <stop offset=\"1\" className={STOP_ACCENT} />\n </linearGradient>\n </defs>\n <circle\n cx=\"50%\"\n cy=\"50%\"\n r=\"50%\"\n fill=\"none\"\n vectorEffect=\"non-scaling-stroke\"\n stroke={`url(#${ringGradientId})`}\n className=\"ds:[stroke-width:var(--border-width-sm)] ds:forced-colors:[stroke:currentColor]\"\n />\n </svg>\n {glyph && bounds ? (\n <svg\n focusable=\"false\"\n viewBox={glyph.viewBox}\n className=\"ds:relative ds:size-[var(--icon-size-md)]\"\n >\n <defs>\n <linearGradient\n id={glyphGradientId}\n gradientUnits=\"userSpaceOnUse\"\n x1={bounds[0]}\n y1={bounds[1]}\n x2={bounds[0] + bounds[2]}\n y2={bounds[1] + bounds[3]}\n >\n <stop offset=\"0\" className={STOP_PRIMARY} />\n <stop offset=\"1\" className={STOP_ACCENT} />\n </linearGradient>\n </defs>\n {glyph.paths.map((path, index) => (\n <path\n key={index}\n d={path.d}\n fill={paint}\n stroke={paint}\n strokeWidth={GLYPH_STROKE}\n strokeLinejoin=\"round\"\n paintOrder=\"stroke\"\n fillRule={path.evenodd ? 'evenodd' : 'nonzero'}\n clipRule={path.evenodd ? 'evenodd' : 'nonzero'}\n className={FORCED_INK}\n />\n ))}\n </svg>\n ) : null}\n </span>\n );\n },\n);\n\nSpecialtyIcon.displayName = 'SpecialtyIcon';\n"],"names":["SPECIALTY_GLYPH_LOADERS","SPECIALTY_ICON_IDS","SPECIALTY_MAP","SPECIALTY_FALLBACK_ICON","GLYPH_STROKE","iconVariants","cva","STOP_PRIMARY","STOP_ACCENT","FORCED_INK","glyphCache","glyphRequests","requestGlyph","id","request","module","useGlyph","update","useReducer","count","cached","useEffect","live","resolveSpecialtyIconId","specialty","icon","SpecialtyIcon","forwardRef","className","rest","ref","uid","useId","ringGradientId","glyphGradientId","glyph","bounds","x","y","w","h","paint","jsxs","jsx","path","index"],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ import { jsxs as p, jsx as s, Fragment as v } from "react/jsx-runtime";
2
+ import { forwardRef as b, useState as k, useId as y } from "react";
3
+ import { useTranslation as w } from "react-i18next";
4
+ import { B as _ } from "./button-DohK_Ak_.js";
5
+ import { c as S } from "./specialty-icon-BkpExzMh.js";
6
+ const m = [
7
+ "ds:relative ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]",
8
+ "ds:min-h-[var(--min-target-size)] ds:text-foreground ds:no-underline",
9
+ "ds:rounded-[var(--radius-md)]",
10
+ "ds:md:[min-block-size:var(--accessible-target-floor,0px)] ds:md:gap-[var(--spacing-2xs)] ds:md:rounded-full",
11
+ "ds:md:ps-[var(--spacing-xs)] ds:md:pe-[var(--spacing-md)]",
12
+ // The chip frame needs `mask-composite: exclude` (Chromium 120+). Without
13
+ // it the ring stays and there is no outline, rather than a gradient
14
+ // painted over the label. `--foreground` is only the mask's opaque source.
15
+ "ds:md:supports-[mask-composite:exclude]:[&_[data-slot=ring]]:hidden",
16
+ "ds:md:supports-[mask-composite:exclude]:before:pointer-events-none ds:md:supports-[mask-composite:exclude]:before:absolute",
17
+ 'ds:md:supports-[mask-composite:exclude]:before:inset-0 ds:md:supports-[mask-composite:exclude]:before:content-[""]',
18
+ "ds:md:supports-[mask-composite:exclude]:before:rounded-[inherit] ds:md:supports-[mask-composite:exclude]:before:p-[var(--border-width-sm)]",
19
+ "ds:md:supports-[mask-composite:exclude]:before:[background:var(--gradient-wordmark)]",
20
+ "ds:md:supports-[mask-composite:exclude]:before:[mask:linear-gradient(var(--foreground)_0_0)_content-box_exclude,linear-gradient(var(--foreground)_0_0)]",
21
+ "ds:md:forced-colors:before:hidden ds:md:forced-colors:[border:var(--border-width-sm)_solid_CanvasText]",
22
+ "ds:md:forced-colors:[&_[data-slot=ring]]:hidden"
23
+ ].join(" "), N = [
24
+ "ds:group",
25
+ "ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid",
26
+ "ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]",
27
+ "ds:forced-colors:focus-visible:outline-[CanvasText]"
28
+ ].join(" "), L = [
29
+ "ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-2xs)] ds:p-0",
30
+ "ds:md:flex-row ds:md:flex-wrap ds:md:gap-[var(--spacing-sm)]"
31
+ ].join(" ");
32
+ function j({
33
+ item: e,
34
+ hidden: r
35
+ }) {
36
+ const d = /* @__PURE__ */ p(v, { children: [
37
+ /* @__PURE__ */ s(S, { specialty: e.key }),
38
+ /* @__PURE__ */ s(
39
+ "span",
40
+ {
41
+ dir: "auto",
42
+ className: "type-body ds:min-w-0 ds:underline-offset-4 ds:group-hover:underline ds:group-focus-visible:underline",
43
+ children: e.label
44
+ }
45
+ )
46
+ ] });
47
+ return /* @__PURE__ */ s(
48
+ "li",
49
+ {
50
+ hidden: r,
51
+ className: "ds:min-w-0 ds:max-w-full ds:[&[hidden]]:hidden",
52
+ children: e.href ? /* @__PURE__ */ s("a", { href: e.href, className: `${m} ${N}`, children: d }) : /* @__PURE__ */ s("span", { className: m, children: d })
53
+ }
54
+ );
55
+ }
56
+ const C = b(
57
+ ({ items: e, collapsedCount: r = 5, className: d, ...u }, f) => {
58
+ const { t: a } = w("ui"), [n, g] = k(!1), t = y(), i = Math.max(0, r), l = Math.max(0, e.length - i), x = l > 0, h = [
59
+ "ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)] ds:md:gap-[var(--spacing-xs)]",
60
+ d
61
+ ].filter(Boolean).join(" ");
62
+ return /* @__PURE__ */ p(
63
+ "div",
64
+ {
65
+ ref: f,
66
+ "data-component": "specialty-list",
67
+ className: h,
68
+ ...u,
69
+ children: [
70
+ /* @__PURE__ */ s("ul", { id: t, className: L, children: e.map((o, c) => /* @__PURE__ */ s(
71
+ j,
72
+ {
73
+ item: o,
74
+ hidden: c >= i && !n ? !0 : void 0
75
+ },
76
+ `${o.key}-${c}`
77
+ )) }),
78
+ x ? /* @__PURE__ */ s(
79
+ _,
80
+ {
81
+ type: "button",
82
+ intent: "link",
83
+ size: "md",
84
+ className: "ds:!ps-0 ds:!pe-0",
85
+ "aria-expanded": n,
86
+ "aria-controls": t,
87
+ onClick: () => g((o) => !o),
88
+ children: n ? a("specialtyList.showLess") : a("specialtyList.showAll", { count: l })
89
+ }
90
+ ) : null
91
+ ]
92
+ }
93
+ );
94
+ }
95
+ );
96
+ C.displayName = "SpecialtyList";
97
+ export {
98
+ C as S
99
+ };
100
+ //# sourceMappingURL=specialty-list-BzalHR8_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specialty-list-BzalHR8_.js","sources":["../../src/components/specialty-list/specialty-list.tsx"],"sourcesContent":["import {\n forwardRef,\n useId,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '../button/button';\nimport { SpecialtyIcon } from '../specialty-icon/specialty-icon';\n\n/* -------------------------------------------------------------------- */\n/* SpecialtyList */\n/* */\n/* A practice's specialities. Below `md` one per line: the ring icon, */\n/* then the label. From `md` the items wrap as chips: a gradient outline */\n/* with a clear centre, the glyph without its own ring, the same label. */\n/* */\n/* Every item is always in the DOM. Items after `collapsedCount` carry */\n/* the `hidden` attribute until the toggle opens the list, so crawlers */\n/* read all of them (find-in-page only sees the open ones). Opened chips */\n/* keep flowing in the same list rather than starting a new line. */\n/* -------------------------------------------------------------------- */\n\nexport interface SpecialtyListItem {\n /** Profession key (platform seoUrl slug). Unknown keys get the health cross. */\n key: string;\n /** Display label, already localised by the consumer. */\n label: string;\n /** When set the item is a link; otherwise plain text. */\n href?: string;\n}\n\nexport interface SpecialtyListProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'children'\n> {\n /** The specialities, in display order. */\n items: SpecialtyListItem[];\n /**\n * How many items show before the toggle. Defaults to 5. The rest stay in\n * the DOM, hidden. No toggle is rendered when `items.length` is not above it.\n */\n collapsedCount?: number;\n}\n\n// Below md a row is at least the 44px touch target; the icon inside it is\n// 32px. From md it is a 32px chip, like Button `sm`: WCAG 2.5.8 asks for\n// 24px and the chips sit 8px apart. The accessible themes raise it to their\n// target floor. The outline is a masked ::before in `--border-width-sm`, so\n// the centre stays clear whatever the surface behind it; in forced colours\n// a real border replaces it. The icon's own ring is hidden because the chip\n// is the frame.\nconst ROW_BASE = [\n 'ds:relative ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]',\n 'ds:min-h-[var(--min-target-size)] ds:text-foreground ds:no-underline',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:md:[min-block-size:var(--accessible-target-floor,0px)] ds:md:gap-[var(--spacing-2xs)] ds:md:rounded-full',\n 'ds:md:ps-[var(--spacing-xs)] ds:md:pe-[var(--spacing-md)]',\n // The chip frame needs `mask-composite: exclude` (Chromium 120+). Without\n // it the ring stays and there is no outline, rather than a gradient\n // painted over the label. `--foreground` is only the mask's opaque source.\n 'ds:md:supports-[mask-composite:exclude]:[&_[data-slot=ring]]:hidden',\n 'ds:md:supports-[mask-composite:exclude]:before:pointer-events-none ds:md:supports-[mask-composite:exclude]:before:absolute',\n 'ds:md:supports-[mask-composite:exclude]:before:inset-0 ds:md:supports-[mask-composite:exclude]:before:content-[\"\"]',\n 'ds:md:supports-[mask-composite:exclude]:before:rounded-[inherit] ds:md:supports-[mask-composite:exclude]:before:p-[var(--border-width-sm)]',\n 'ds:md:supports-[mask-composite:exclude]:before:[background:var(--gradient-wordmark)]',\n 'ds:md:supports-[mask-composite:exclude]:before:[mask:linear-gradient(var(--foreground)_0_0)_content-box_exclude,linear-gradient(var(--foreground)_0_0)]',\n 'ds:md:forced-colors:before:hidden ds:md:forced-colors:[border:var(--border-width-sm)_solid_CanvasText]',\n 'ds:md:forced-colors:[&_[data-slot=ring]]:hidden',\n].join(' ');\n\n// Only links underline their label on hover and focus.\nconst LINK_EXTRA = [\n 'ds:group',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n].join(' ');\n\nconst LIST_CLASS = [\n 'ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-2xs)] ds:p-0',\n 'ds:md:flex-row ds:md:flex-wrap ds:md:gap-[var(--spacing-sm)]',\n].join(' ');\n\nfunction SpecialtyItem({\n item,\n hidden,\n}: {\n item: SpecialtyListItem;\n hidden?: boolean;\n}) {\n const content = (\n <>\n <SpecialtyIcon specialty={item.key} />\n <span\n dir=\"auto\"\n className=\"type-body ds:min-w-0 ds:underline-offset-4 ds:group-hover:underline ds:group-focus-visible:underline\"\n >\n {item.label}\n </span>\n </>\n );\n return (\n <li\n hidden={hidden}\n className=\"ds:min-w-0 ds:max-w-full ds:[&[hidden]]:hidden\"\n >\n {item.href ? (\n <a href={item.href} className={`${ROW_BASE} ${LINK_EXTRA}`}>\n {content}\n </a>\n ) : (\n <span className={ROW_BASE}>{content}</span>\n )}\n </li>\n );\n}\n\nexport const SpecialtyList = forwardRef<HTMLDivElement, SpecialtyListProps>(\n ({ items, collapsedCount = 5, className, ...rest }, ref) => {\n const { t } = useTranslation('ui');\n const [expanded, setExpanded] = useState(false);\n const listId = useId();\n\n const shown = Math.max(0, collapsedCount);\n const moreCount = Math.max(0, items.length - shown);\n const hasToggle = moreCount > 0;\n\n const rootClass = [\n 'ds:flex ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)] ds:md:gap-[var(--spacing-xs)]',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n ref={ref}\n data-component=\"specialty-list\"\n className={rootClass}\n {...rest}\n >\n <ul id={listId} className={LIST_CLASS}>\n {items.map((item, index) => (\n <SpecialtyItem\n key={`${item.key}-${index}`}\n item={item}\n hidden={index >= shown && !expanded ? true : undefined}\n />\n ))}\n </ul>\n {hasToggle ? (\n <Button\n type=\"button\"\n intent=\"link\"\n size=\"md\"\n // The kit's inline text-button idiom (EditableDescription): no\n // side padding, so the text lines up with the items above it.\n className=\"ds:!ps-0 ds:!pe-0\"\n aria-expanded={expanded}\n aria-controls={listId}\n onClick={() => setExpanded((open) => !open)}\n >\n {expanded\n ? t('specialtyList.showLess')\n : t('specialtyList.showAll', { count: moreCount })}\n </Button>\n ) : null}\n </div>\n );\n },\n);\n\nSpecialtyList.displayName = 'SpecialtyList';\n"],"names":["ROW_BASE","LINK_EXTRA","LIST_CLASS","SpecialtyItem","item","hidden","content","jsxs","Fragment","jsx","SpecialtyIcon","SpecialtyList","forwardRef","items","collapsedCount","className","rest","ref","t","useTranslation","expanded","setExpanded","useState","listId","useId","shown","moreCount","hasToggle","rootClass","index","Button","open"],"mappings":";;;;;AAoDA,MAAMA,IAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAGJC,IAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,IAAa;AAAA,EACjB;AAAA,EACA;AACF,EAAE,KAAK,GAAG;AAEV,SAASC,EAAc;AAAA,EACrB,MAAAC;AAAA,EACA,QAAAC;AACF,GAGG;AACD,QAAMC,IACJ,gBAAAC,EAAAC,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAC,EAACC,GAAA,EAAc,WAAWN,EAAK,IAAA,CAAK;AAAA,IACpC,gBAAAK;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAI;AAAA,QACJ,WAAU;AAAA,QAET,UAAAL,EAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EACR,GACF;AAEF,SACE,gBAAAK;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,QAAAJ;AAAA,MACA,WAAU;AAAA,MAET,YAAK,OACJ,gBAAAI,EAAC,OAAE,MAAML,EAAK,MAAM,WAAW,GAAGJ,CAAQ,IAAIC,CAAU,IACrD,UAAAK,EAAA,CACH,sBAEC,QAAA,EAAK,WAAWN,GAAW,UAAAM,EAAA,CAAQ;AAAA,IAAA;AAAA,EAAA;AAI5C;AAEO,MAAMK,IAAgBC;AAAA,EAC3B,CAAC,EAAE,OAAAC,GAAO,gBAAAC,IAAiB,GAAG,WAAAC,GAAW,GAAGC,EAAA,GAAQC,MAAQ;AAC1D,UAAM,EAAE,GAAAC,EAAA,IAAMC,EAAe,IAAI,GAC3B,CAACC,GAAUC,CAAW,IAAIC,EAAS,EAAK,GACxCC,IAASC,EAAA,GAETC,IAAQ,KAAK,IAAI,GAAGX,CAAc,GAClCY,IAAY,KAAK,IAAI,GAAGb,EAAM,SAASY,CAAK,GAC5CE,IAAYD,IAAY,GAExBE,IAAY;AAAA,MAChB;AAAA,MACAb;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,WACE,gBAAAR;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAU;AAAA,QACA,kBAAe;AAAA,QACf,WAAWW;AAAA,QACV,GAAGZ;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAP,EAAC,MAAA,EAAG,IAAIc,GAAQ,WAAWrB,GACxB,UAAAW,EAAM,IAAI,CAACT,GAAMyB,MAChB,gBAAApB;AAAA,YAACN;AAAA,YAAA;AAAA,cAEC,MAAAC;AAAA,cACA,QAAQyB,KAASJ,KAAS,CAACL,IAAW,KAAO;AAAA,YAAA;AAAA,YAFxC,GAAGhB,EAAK,GAAG,IAAIyB,CAAK;AAAA,UAAA,CAI5B,GACH;AAAA,UACCF,IACC,gBAAAlB;AAAA,YAACqB;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,QAAO;AAAA,cACP,MAAK;AAAA,cAGL,WAAU;AAAA,cACV,iBAAeV;AAAA,cACf,iBAAeG;AAAA,cACf,SAAS,MAAMF,EAAY,CAACU,MAAS,CAACA,CAAI;AAAA,cAEzC,UAAAX,IACGF,EAAE,wBAAwB,IAC1BA,EAAE,yBAAyB,EAAE,OAAOQ,EAAA,CAAW;AAAA,YAAA;AAAA,UAAA,IAEnD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEAf,EAAc,cAAc;"}
@@ -16,7 +16,7 @@ import { E as zt } from "./editable-description-KU56SP4P.js";
16
16
  import { N as Xe } from "./note-timeline-BrjHBQfx.js";
17
17
  import { P as Ot } from "./panel-header-CbtlTe85.js";
18
18
  import { P as Ge } from "./panel-subview-DCyvn-49.js";
19
- import { P as _t } from "./patient-summary-card-CL04aq8h.js";
19
+ import { P as _t } from "./patient-summary-card-B1jvxdY8.js";
20
20
  import { S as ne } from "./section-card-D1sV4Voz.js";
21
21
  import { C as nn, S as ue } from "./skeleton-tTWJpvAq.js";
22
22
  import { T as an } from "./text-area-COMVJ1yE.js";
@@ -2195,4 +2195,4 @@ export {
2195
2195
  Kn as s,
2196
2196
  _s as u
2197
2197
  };
2198
- //# sourceMappingURL=use-appointment-details-read-BbIoPWO6.js.map
2198
+ //# sourceMappingURL=use-appointment-details-read-BNtTap_B.js.map