@alfadocs/ui-kit 1.4.17 → 1.6.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 (92) hide show
  1. package/dist/_chunks/{booking-CGKof8QU.js → booking-D84O6H2X.js} +553 -546
  2. package/dist/_chunks/{care-plan-card-C83Hb9EE.js → care-plan-card-CehAU7F_.js} +2 -2
  3. package/dist/_chunks/{care-plan-entry-card-CHMPSTCz.js → care-plan-entry-card-ChWRMfMw.js} +2 -2
  4. package/dist/_chunks/{periodontal-chart-brakjj0s.js → periodontal-chart-C0nNQKKK.js} +121 -121
  5. package/dist/_chunks/practice-profile-hero-Bdd0bFqC.js +187 -0
  6. package/dist/_chunks/{practice-results-DWUZRm2x.js → practice-results-CKoLD_x5.js} +220 -206
  7. package/dist/_chunks/tooth-data-DR8Kdnup.js +903 -0
  8. package/dist/_chunks/tooth-finding-palette-vqC-D2Ye.js +708 -0
  9. package/dist/_chunks/tooth-scheme-BPXE1_3N.js +2051 -0
  10. package/dist/agent-catalog.json +497 -56
  11. package/dist/agent-i18n/en.json +29 -11
  12. package/dist/components/booking/booking-types.d.ts +9 -0
  13. package/dist/components/booking/index.js +1 -1
  14. package/dist/components/care-plan-card/index.js +1 -1
  15. package/dist/components/care-plan-entry-card/index.js +1 -1
  16. package/dist/components/index.d.ts +2 -0
  17. package/dist/components/periodontal-chart/index.js +1 -1
  18. package/dist/components/practice-profile-hero/index.d.ts +4 -0
  19. package/dist/components/practice-profile-hero/index.js +6 -0
  20. package/dist/components/practice-profile-hero/practice-profile-hero.agent.d.ts +4 -0
  21. package/dist/components/practice-profile-hero/practice-profile-hero.d.ts +60 -0
  22. package/dist/components/practice-results/index.js +1 -1
  23. package/dist/components/practice-results/practice-results.d.ts +15 -1
  24. package/dist/components/tooth-finding-palette/index.d.ts +4 -0
  25. package/dist/components/tooth-finding-palette/index.js +9 -0
  26. package/dist/components/tooth-finding-palette/tooth-finding-palette.agent.d.ts +4 -0
  27. package/dist/components/tooth-finding-palette/tooth-finding-palette.d.ts +89 -0
  28. package/dist/components/tooth-scheme/index.d.ts +2 -2
  29. package/dist/components/tooth-scheme/index.js +57 -30
  30. package/dist/components/tooth-scheme/tooth-data.d.ts +279 -10
  31. package/dist/components/tooth-scheme/tooth-scheme.agent.d.ts +2 -2
  32. package/dist/components/tooth-scheme/tooth-scheme.d.ts +30 -3
  33. package/dist/host-compat.css +1 -4
  34. package/dist/i18n/locales/ar.d.ts +41 -1
  35. package/dist/i18n/locales/ar.js +42 -2
  36. package/dist/i18n/locales/de.d.ts +41 -1
  37. package/dist/i18n/locales/de.js +42 -2
  38. package/dist/i18n/locales/el.d.ts +41 -1
  39. package/dist/i18n/locales/el.js +42 -2
  40. package/dist/i18n/locales/en.d.ts +41 -1
  41. package/dist/i18n/locales/en.js +42 -2
  42. package/dist/i18n/locales/es.d.ts +41 -1
  43. package/dist/i18n/locales/es.js +42 -2
  44. package/dist/i18n/locales/fr.d.ts +41 -1
  45. package/dist/i18n/locales/fr.js +42 -2
  46. package/dist/i18n/locales/hi.d.ts +41 -1
  47. package/dist/i18n/locales/hi.js +42 -2
  48. package/dist/i18n/locales/it.d.ts +41 -1
  49. package/dist/i18n/locales/it.js +42 -2
  50. package/dist/i18n/locales/ja.d.ts +41 -1
  51. package/dist/i18n/locales/ja.js +42 -2
  52. package/dist/i18n/locales/nl.d.ts +41 -1
  53. package/dist/i18n/locales/nl.js +42 -2
  54. package/dist/i18n/locales/pl.d.ts +41 -1
  55. package/dist/i18n/locales/pl.js +42 -2
  56. package/dist/i18n/locales/pt.d.ts +41 -1
  57. package/dist/i18n/locales/pt.js +42 -2
  58. package/dist/i18n/locales/ro.d.ts +41 -1
  59. package/dist/i18n/locales/ro.js +42 -2
  60. package/dist/i18n/locales/ru.d.ts +41 -1
  61. package/dist/i18n/locales/ru.js +42 -2
  62. package/dist/i18n/locales/sq.d.ts +41 -1
  63. package/dist/i18n/locales/sq.js +42 -2
  64. package/dist/i18n/locales/sv.d.ts +41 -1
  65. package/dist/i18n/locales/sv.js +42 -2
  66. package/dist/i18n/locales/tr.d.ts +41 -1
  67. package/dist/i18n/locales/tr.js +42 -2
  68. package/dist/i18n/locales/zh.d.ts +41 -1
  69. package/dist/i18n/locales/zh.js +42 -2
  70. package/dist/index.js +561 -525
  71. package/dist/locales/ar.json +42 -2
  72. package/dist/locales/de.json +42 -2
  73. package/dist/locales/el.json +42 -2
  74. package/dist/locales/en.json +42 -2
  75. package/dist/locales/es.json +42 -2
  76. package/dist/locales/fr.json +42 -2
  77. package/dist/locales/hi.json +42 -2
  78. package/dist/locales/it.json +42 -2
  79. package/dist/locales/ja.json +42 -2
  80. package/dist/locales/nl.json +42 -2
  81. package/dist/locales/pl.json +42 -2
  82. package/dist/locales/pt.json +42 -2
  83. package/dist/locales/ro.json +42 -2
  84. package/dist/locales/ru.json +42 -2
  85. package/dist/locales/sq.json +42 -2
  86. package/dist/locales/sv.json +42 -2
  87. package/dist/locales/tr.json +42 -2
  88. package/dist/locales/zh.json +42 -2
  89. package/dist/tokens.css +1 -1
  90. package/package.json +9 -1
  91. package/dist/_chunks/tooth-data-BwuoKFf4.js +0 -660
  92. package/dist/_chunks/tooth-scheme-s0ipC0-Z.js +0 -1483
@@ -3,10 +3,67 @@ export type Dentition = 'permanent' | 'primary' | 'mixed';
3
3
  export type Numbering = 'fdi' | 'universal' | 'palmer';
4
4
  export type ToothMode = 'interactive' | 'display';
5
5
  export type Surface = 'mesial' | 'distal' | 'occlusal' | 'buccal' | 'lingual';
6
- export type ToothCondition = 'caries' | 'filled' | 'crowned' | 'temporaryCrown' | 'bridge' | 'missing' | 'implant' | 'implantExtraction' | 'stub' | 'destroyed' | 'rootCanal';
6
+ /**
7
+ * Built-in findings. `destroyed` is the platform's *radice persistente*
8
+ * (retained root); the id is frozen for backward compatibility but the label
9
+ * and docs read "Retained root" so the two systems describe the same thing.
10
+ * `xray` is the chartable radiograph SYMBOL — distinct from the `radiographs`
11
+ * image archive a tooth can also carry.
12
+ */
13
+ export type ToothCondition = 'caries' | 'filled' | 'crowned' | 'temporaryCrown' | 'bridge' | 'missing' | 'implant' | 'implantExtraction' | 'stub' | 'destroyed' | 'rootCanal' | 'pin' | 'rootAmputation' | 'anchorage' | 'hook' | 'attachment' | 'mucogingivalSurgery' | 'periodontalSurgery' | 'curettage' | 'medication' | 'xray';
14
+ /**
15
+ * Open condition id: a built-in, or an id from a consumer's condition registry.
16
+ * The `(string & {})` keeps editor autocomplete on the built-ins while still
17
+ * accepting a practice-defined finding.
18
+ */
19
+ export type ConditionId = ToothCondition | (string & {});
20
+ /** Which anatomical layer a symbol marks — mirrors the platform's `part`. */
21
+ export type SymbolPart = 'element' | 'surface' | 'root';
22
+ /** Planned vs already executed. Matches the Care Plan's blue/green convention. */
23
+ export type SymbolStatus = 'planned' | 'executed';
24
+ /**
25
+ * A tooth's roots, named anatomically; `'single'` covers every one-rooted
26
+ * tooth. For flank-mounted markers (anchorage, hook) `mesial` / `distal` select
27
+ * which SIDE of the tooth the marker sits on rather than a root proper.
28
+ */
29
+ export type Root = 'mesial' | 'distal' | 'palatal' | 'buccal' | 'single';
30
+ /**
31
+ * One charted finding. Unlike the legacy `conditions` + `surfaces` pair — where
32
+ * a single flat surface list is shared by every condition on the tooth — a
33
+ * symbol scopes its own surfaces and roots, so two fillings on one tooth (one
34
+ * mesial, one distal) are finally representable.
35
+ */
36
+ export interface ToothSymbol {
37
+ /**
38
+ * Provenance — the platform's carePlanEntryId / findingEntryId. Lets a
39
+ * consumer route a click on the symbol back to the record that produced it.
40
+ */
41
+ id?: string;
42
+ condition: ConditionId;
43
+ /** Defaults to the condition's natural part (see `conditionPart`). */
44
+ part?: SymbolPart;
45
+ surfaces?: Surface[];
46
+ roots?: Root[];
47
+ /**
48
+ * Where a flank-mounted marker sits — the gingival surgeries ship
49
+ * `left` / `right` / `total` / `repeat` renders rather than per-root ones.
50
+ * Omitted, they fall back to `repeat`.
51
+ */
52
+ region?: SymbolRegion;
53
+ status?: SymbolStatus;
54
+ /** Per-practice colour override (a CSS colour or `var(--token)`). */
55
+ color?: string;
56
+ note?: string;
57
+ }
7
58
  export interface ToothState {
8
59
  conditions: ToothCondition[];
9
60
  surfaces: Surface[];
61
+ /**
62
+ * Per-symbol findings. When present these WIN over `conditions`/`surfaces`;
63
+ * when absent `symbolsForTooth()` derives the equivalent list from them, so
64
+ * the renderer only ever walks one shape.
65
+ */
66
+ symbols?: ToothSymbol[];
10
67
  notes?: string;
11
68
  }
12
69
  export type ToothChart = Record<FdiId, ToothState>;
@@ -81,24 +138,150 @@ export declare const FDI_TO_PALMER: Record<FdiId, string>;
81
138
  export declare function assetFdi(meta: ToothMeta): FdiId;
82
139
  /** Render scale applied to a tooth image (primary teeth are smaller). */
83
140
  export declare const PRIMARY_TOOTH_SCALE = 0.72;
141
+ /** Positional file stem used by the per-root `rootTreatment` renders. */
142
+ export type RootFileStem = 'full' | 'left' | 'right' | 'center';
143
+ /**
144
+ * The roots a tooth's artwork distinguishes: upper molars are three-rooted
145
+ * (mesial, distal, palatal), lower molars two-rooted, everything else renders
146
+ * as one root. Derived from `assetFdi` rather than `meta.anatomy` because a
147
+ * primary molar reuses PREMOLAR art (54 draws 14) and so has one root's worth
148
+ * of renders. The upper first premolars 14/24 are treated as single-rooted for
149
+ * the same reason — clinically they are often bifurcated, but no second render
150
+ * ships, and a wrong answer here resolves to a file that does not exist.
151
+ */
152
+ export declare function rootsForTooth(meta: ToothMeta): Root[];
153
+ /**
154
+ * Which SCREEN side a tooth's mesial or distal root faces. The chart is FIXED
155
+ * to clinical orientation — the patient's right sits on the viewer's left in
156
+ * BOTH arches — so the midline falls on the viewer's RIGHT for the patient's
157
+ * right quadrants (1 & 4) and on the viewer's LEFT for the patient's left
158
+ * quadrants (2 & 3). Mesial means "toward the midline", so it flips with it;
159
+ * distal is always its opposite. This is the same flip `zoneSurface` applies
160
+ * to the plan view's left/right zones. Primary quadrants normalise (5-8 → 1-4).
161
+ */
162
+ export declare function rootScreenSide(meta: ToothMeta, root: 'mesial' | 'distal'): 'left' | 'right';
163
+ /**
164
+ * Map an anatomical root to the `rootTreatment` file stem. `center` is the
165
+ * palatal root and ships for upper molars only; a root the tooth does not
166
+ * distinguish falls back to the whole-tooth render rather than a dead URL.
167
+ */
168
+ export declare function rootFileStem(meta: ToothMeta, root: Root): RootFileStem;
84
169
  /** CSS variable name (without the leading `var(...)`) that drives a condition's colour. */
85
170
  export declare const CONDITION_TOKENS: Record<ToothCondition, string>;
86
171
  /**
87
172
  * Convenience: the `fill="var(--destructive)"` string ready to paste onto
88
- * an SVG attribute. Kept in sync with `CONDITION_TOKENS`. Used for the legend
89
- * swatch + the surface-condition ring; whole-tooth conditions render a
90
- * distinct symbol image (the glyph is the colour-independent channel).
173
+ * an SVG attribute. DERIVED from `CONDITION_TOKENS` so the two can never drift.
174
+ * Used for the legend swatch + the surface-condition ring; whole-tooth
175
+ * conditions render a distinct symbol image (the glyph is the
176
+ * colour-independent channel).
91
177
  */
92
178
  export declare const CONDITION_COLORS: Record<ToothCondition, string>;
93
- export interface SideSymbolSpec {
94
- /** Asset folder under `side/`. */
179
+ /**
180
+ * Every built-in condition id, in declaration order. Derived from
181
+ * `CONDITION_TOKENS`, which the compiler forces to be exhaustive — so a new
182
+ * condition can never silently fall out of a hand-maintained list.
183
+ */
184
+ export declare const TOOTH_CONDITIONS: ToothCondition[];
185
+ /** True when an id names a built-in condition rather than a registry entry. */
186
+ export declare function isBuiltInCondition(id: ConditionId): id is ToothCondition;
187
+ /** The layer each built-in finding marks, used when a symbol omits `part`. */
188
+ export declare const CONDITION_PART: Record<ToothCondition, SymbolPart>;
189
+ /**
190
+ * Built-ins the chart draws ITSELF rather than from artwork — `missing` is an
191
+ * SVG cross, `caries` / `filled` fall back to the surface ring in the side
192
+ * view. They must never take the registry's glyph badge.
193
+ */
194
+ export declare const INTRINSIC_CONDITIONS: ToothCondition[];
195
+ export declare const STATUS_TOKENS: Record<SymbolStatus, string>;
196
+ /** The `var(...)` form of `STATUS_TOKENS`, ready for an SVG attribute. */
197
+ export declare const STATUS_COLORS: Record<SymbolStatus, string>;
198
+ /** The second, non-colour channel: a planned symbol renders lighter. */
199
+ export declare const STATUS_OPACITY: Record<SymbolStatus, number>;
200
+ /** i18n key for a status label (`ui.toothScheme.status.*`). */
201
+ export declare function statusLabelKey(status: SymbolStatus): string;
202
+ /**
203
+ * Screen-relative marker slot. `repeat` is what the BARE gingival-surgery type
204
+ * resolves to — it is the default marker, not a "repeat treatment" variant.
205
+ */
206
+ export type SymbolRegion = 'left' | 'right' | 'total' | 'repeat';
207
+ /** Corner glyph stem in `side/other/` — curettage, medication, x-ray. */
208
+ export type SymbolLetter = 'c' | 'm' | 'x';
209
+ /**
210
+ * How a symbol's file resolves inside `{folder}/{view}/`. A discriminated union
211
+ * rather than a bare enum because two shapes carry their own data: `per-fdi-root`
212
+ * has to know whether a multi-rooted tooth also ships a whole-tooth render, and
213
+ * `letter` pins the single glyph its condition owns.
214
+ */
215
+ export type SideSymbolSpec =
216
+ /** `{fdi}.webp` — one render per tooth. */
217
+ {
95
218
  folder: string;
96
- /** How the file resolves inside `{folder}/{view}/`. */
97
- resolve: 'per-fdi' | 'general' | 'rct';
219
+ resolve: 'per-fdi';
220
+ }
221
+ /** `general.webp` — one render per arch. */
222
+ | {
223
+ folder: string;
224
+ resolve: 'general';
225
+ }
226
+ /** `{fdi}/{full|left|right|center}.webp` — per-FDI subdirectory. */
227
+ | {
228
+ folder: string;
229
+ resolve: 'rct';
230
+ }
231
+ /**
232
+ * `{fdi}[-{mesial|distal|palatal}].webp`. `wholeTooth` distinguishes two
233
+ * folders that look symmetric and are not: `pin` ships a bare file for every
234
+ * FDI, `rootAmputation` only for single-rooted teeth.
235
+ */
236
+ | {
237
+ folder: string;
238
+ resolve: 'per-fdi-root';
239
+ wholeTooth: 'always' | 'single-rooted-only';
240
+ }
241
+ /** `{fdi}-{mesial|distal}.webp` — always suffixed, no bare file. */
242
+ | {
243
+ folder: string;
244
+ resolve: 'per-fdi-side';
245
+ }
246
+ /** `{fdi}_{left|right}.webp` — the only folder using an UNDERSCORE. */
247
+ | {
248
+ folder: string;
249
+ resolve: 'per-fdi-lr';
250
+ }
251
+ /** `{left|right|total|repeat}.webp` — no FDI in the name. */
252
+ | {
253
+ folder: string;
254
+ resolve: 'region';
255
+ }
256
+ /** `{left|right}.webp` — no FDI, and only the two sides ship. */
257
+ | {
258
+ folder: string;
259
+ resolve: 'screen-side';
260
+ }
261
+ /** `{c|m|x}.webp`. */
262
+ | {
263
+ folder: string;
264
+ resolve: 'letter';
265
+ letter: SymbolLetter;
266
+ };
267
+ /**
268
+ * Which instance of a symbol to resolve. The two fields are independent
269
+ * discriminators read by different `resolve` strategies (roots by the per-root
270
+ * shapes, regions by the screen-side ones) — passed in, never module state.
271
+ */
272
+ export interface SymbolTarget {
273
+ /** Root, or tooth side for a flank-mounted marker. */
274
+ root?: Root;
275
+ /** Explicit screen-relative slot; wins over `root` where both apply. */
276
+ region?: SymbolRegion;
98
277
  }
99
278
  export declare const CONDITION_SIDE_SYMBOL: Partial<Record<ToothCondition, SideSymbolSpec>>;
100
- /** Resolve the side-view symbol overlay URL for a condition on a tooth. */
101
- export declare function conditionSymbolUrl(meta: ToothMeta, assetBaseUrl: string, spec: SideSymbolSpec): string;
279
+ /**
280
+ * Resolve the side-view symbol overlay URL for a condition on a tooth. `target`
281
+ * picks a specific root / side; omitted, every strategy resolves to the
282
+ * whole-tooth or default marker, which is what the legacy call sites want.
283
+ */
284
+ export declare function conditionSymbolUrl(meta: ToothMeta, assetBaseUrl: string, spec: SideSymbolSpec, target?: SymbolTarget): string;
102
285
  export type Projection = 'side' | 'plan';
103
286
  /** The user-selectable view: a single projection, or both stacked together. */
104
287
  export type ViewMode = Projection | 'both';
@@ -108,6 +291,84 @@ export declare const SURFACE_ASSET_NAME: Record<Surface, string>;
108
291
  export declare const CONDITION_PLAN_FOLDER: Partial<Record<ToothCondition, string>>;
109
292
  /** Resolve a per-surface plan-view overlay URL (e.g. caries on the distal). */
110
293
  export declare function surfaceSymbolUrl(meta: ToothMeta, assetBaseUrl: string, folder: string, surface: Surface): string;
294
+ /**
295
+ * Whole-tooth symbols in the PLAN projection. Without these a crowned tooth
296
+ * reads as a plain tooth in the occlusal view, which also made `projection`
297
+ * `'both'` disagree with itself between its own rows.
298
+ *
299
+ * `anchorage` is the odd one: the plan art is two generic screen-side markers
300
+ * (no FDI in the name) composited over the default render, so its mesial/distal
301
+ * root has to be flipped through the quadrant — `symbolUrl` does that.
302
+ */
303
+ export declare const CONDITION_PLAN_SYMBOL: Partial<Record<ToothCondition, SideSymbolSpec>>;
304
+ /** Resolve the plan-view whole-tooth symbol overlay URL for a condition. */
305
+ export declare function planSymbolUrl(meta: ToothMeta, assetBaseUrl: string, spec: SideSymbolSpec, target?: SymbolTarget): string;
306
+ /**
307
+ * How much to scale a plan overlay so its tooth registers with the base render.
308
+ * `1` for everything on the standard canvas.
309
+ */
310
+ export declare function planOverlayScale(url: string): number;
311
+ export interface ConditionDefinition {
312
+ id: string;
313
+ /** Already-translated label — the CONSUMER owns custom-condition copy. */
314
+ label: string;
315
+ color?: string;
316
+ part?: SymbolPart;
317
+ sideSymbol?: SideSymbolSpec;
318
+ planSymbol?: SideSymbolSpec;
319
+ planFolder?: string;
320
+ /** 1–3 char mark rendered when the condition has no artwork. */
321
+ glyph?: string;
322
+ }
323
+ export type ConditionRegistry = readonly ConditionDefinition[];
324
+ /**
325
+ * A condition's display name. Built-ins resolve to an i18n key; registry
326
+ * entries carry literal text, because their copy lives in the consuming app.
327
+ */
328
+ export type ConditionLabel = {
329
+ kind: 'key';
330
+ key: string;
331
+ } | {
332
+ kind: 'text';
333
+ text: string;
334
+ };
335
+ /** Colour used when a condition is neither registered nor built in. */
336
+ export declare const FALLBACK_CONDITION_TOKEN = "--muted-foreground";
337
+ /** i18n key for a built-in condition label (`ui.toothScheme.condition.*`). */
338
+ export declare function conditionLabelKey(condition: ToothCondition): string;
339
+ /**
340
+ * Look up a registry entry. Registry ids shadow built-ins field by field, so a
341
+ * practice can re-tint or re-label a shipped finding without losing its art.
342
+ */
343
+ export declare function conditionDefinition(condition: ConditionId, registry?: ConditionRegistry): ConditionDefinition | undefined;
344
+ export declare function conditionLabel(condition: ConditionId, registry?: ConditionRegistry): ConditionLabel;
345
+ /** Paintable colour for a condition — never empty, so nothing renders unseen. */
346
+ export declare function conditionColor(condition: ConditionId, registry?: ConditionRegistry): string;
347
+ /** Paint colour for ONE charted symbol — its own override wins. */
348
+ export declare function symbolColor(symbol: ToothSymbol, registry?: ConditionRegistry): string;
349
+ export declare function conditionSideSymbol(condition: ConditionId, registry?: ConditionRegistry): SideSymbolSpec | undefined;
350
+ export declare function conditionPlanSymbol(condition: ConditionId, registry?: ConditionRegistry): SideSymbolSpec | undefined;
351
+ export declare function conditionPlanFolder(condition: ConditionId, registry?: ConditionRegistry): string | undefined;
352
+ export declare function conditionPart(condition: ConditionId, registry?: ConditionRegistry): SymbolPart;
353
+ /**
354
+ * The 1–3 character mark that stands in when a condition ships no artwork.
355
+ * Falls back to the id's initials so a practice-defined finding can be charted
356
+ * the day it is registered, rather than rendering as a silent blank.
357
+ */
358
+ export declare function conditionGlyph(condition: ConditionId, registry?: ConditionRegistry): string;
359
+ /**
360
+ * Whether a condition has artwork in a projection. When false the renderer
361
+ * must fall back to the glyph badge — that seam is what lets a practice chart
362
+ * a finding before a designer draws it.
363
+ */
364
+ export declare function conditionHasArtwork(condition: ConditionId, projection: Projection, registry?: ConditionRegistry): boolean;
365
+ /**
366
+ * The findings on a tooth as a symbol list. `state.symbols` wins outright when
367
+ * present (an explicit empty array therefore means "no findings"); otherwise
368
+ * the legacy pair is derived faithfully — the shared `surfaces` list attaches
369
+ * only to surface-part conditions, exactly as the flat renderer treated it.
370
+ */
371
+ export declare function symbolsForTooth(state: ToothState | undefined, registry?: ConditionRegistry): ToothSymbol[];
111
372
  /**
112
373
  * Clickable surface regions of a plan-view tooth, named by SCREEN position.
113
374
  * `zoneSurface()` resolves each to the anatomical `Surface` per quadrant.
@@ -260,4 +521,12 @@ export declare function layoutSpecials(specials: SpecialElement[], teethWidth: n
260
521
  export declare function labelFor(id: FdiId, numbering: Numbering): string;
261
522
  export declare function emptyChart(): ToothChart;
262
523
  export declare function chartFromConditions(conditions: Partial<Record<FdiId, ToothCondition[]>>): ToothChart;
524
+ /**
525
+ * Build a chart from the richer per-symbol shape. Each entry also projects its
526
+ * built-in conditions and surfaces back onto the legacy pair so readers that
527
+ * predate `symbols` (the first-condition `data-condition`, the periodontal
528
+ * chart, the care-plan card) still see the tooth. Registry ids are omitted from
529
+ * that projection — a legacy reader does not know the custom vocabulary.
530
+ */
531
+ export declare function chartFromSymbols(symbols: Partial<Record<FdiId, ToothSymbol[]>>): ToothChart;
263
532
  //# sourceMappingURL=tooth-data.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { AgentAdapter } from '../../agent/types';
2
2
  import type { ToothSchemeHandle } from './tooth-scheme';
3
- import type { Radiograph, Surface, ToothCondition } from './tooth-data';
3
+ import type { ConditionId, Radiograph, RadiographKind, Root, Surface, SymbolPart, SymbolStatus, ToothCondition, ToothSymbol } from './tooth-data';
4
4
  export declare const toothSchemeAgent: AgentAdapter<ToothSchemeHandle>;
5
- export type { Radiograph, Surface, ToothCondition };
5
+ export type { ConditionId, Radiograph, RadiographKind, Root, Surface, SymbolPart, SymbolStatus, ToothCondition, ToothSymbol, };
6
6
  //# sourceMappingURL=tooth-scheme.agent.d.ts.map
@@ -1,4 +1,4 @@
1
- import { PERMANENT_TEETH, PRIMARY_TEETH, type Arch, type ViewMode, type Dentition, type FdiId, type Numbering, type Radiograph, type Surface, type ToothChart, type ToothCondition, type ToothMode } from './tooth-data';
1
+ import { PERMANENT_TEETH, PRIMARY_TEETH, type Arch, type ConditionDefinition, type ConditionId, type ToothSymbol, type ViewMode, type Dentition, type FdiId, type Numbering, type Radiograph, type Surface, type ToothChart, type ToothCondition, type ToothMode } from './tooth-data';
2
2
  export interface ToothSchemeProps {
3
3
  /** Opaque instance id — emitted as `data-component-id` for the agent registry. */
4
4
  id?: string;
@@ -67,8 +67,22 @@ export interface ToothSchemeProps {
67
67
  * The finding a tooth-click applies in interactive mode (the selected
68
68
  * tool in a Findings / "Stato dentale" panel). Clicking a tooth toggles
69
69
  * this condition. When unset, clicking cycles caries on/off.
70
+ *
71
+ * A surface-part tool (caries / filled) drills into the tooth's surfaces in
72
+ * the occlusal view; a root-part tool (root canal, post, apicectomy) drills
73
+ * into the roots of a multi-rooted tooth in the facial view. Accepts a
74
+ * `conditionRegistry` id as well as a built-in.
75
+ */
76
+ activeCondition?: ConditionId;
77
+ /**
78
+ * Practice-defined findings, resolved AHEAD of the built-in vocabulary field
79
+ * by field — so an entry may re-tint or re-label a shipped finding without
80
+ * losing its artwork, or add a wholly new one. An entry with no artwork
81
+ * renders its `glyph` badge, which is the seam that lets a practice chart a
82
+ * finding before a designer draws it. Labels are already-translated text:
83
+ * the consuming app owns custom-condition copy, not the kit.
70
84
  */
71
- activeCondition?: ToothCondition;
85
+ conditionRegistry?: ConditionDefinition[];
72
86
  /**
73
87
  * Base URL the photoreal tooth renders are served from. Resolves to
74
88
  * `${assetBaseUrl}/{side|plan}/{symbol}/{top|bottom}/{fdi}.webp`. Defaults
@@ -132,12 +146,25 @@ export interface ToothSchemeHandle {
132
146
  focusTooth: (id: FdiId) => void;
133
147
  /** Read the current chart state. */
134
148
  getChart: () => ToothChart;
135
- /** Read the findings recorded on one tooth (empty array if none). */
149
+ /**
150
+ * Read the built-in findings recorded on one tooth (empty array if none).
151
+ * Registry ids are omitted — use `getSymbols` for the full list.
152
+ */
136
153
  getTooth: (id: FdiId) => ToothCondition[];
154
+ /** Read the findings on one tooth as symbols, with surfaces, roots and status. */
155
+ getSymbols: (id: FdiId) => ToothSymbol[];
137
156
  /** Read the FDI ids of every tooth carrying a given finding. */
138
157
  teethWith: (condition: ToothCondition) => FdiId[];
158
+ /** As `teethWith`, but open to a `conditionRegistry` id. */
159
+ teethWithSymbol: (condition: ConditionId) => FdiId[];
139
160
  /** Add a finding to a tooth (no-op if already present). Optionally mark surfaces. */
140
161
  setFinding: (id: FdiId, condition: ToothCondition, surfaces?: Surface[]) => void;
162
+ /**
163
+ * Add or replace one symbol on a tooth — the surface-, root- and
164
+ * status-aware form of `setFinding`. Matched by `symbol.id` when the symbol
165
+ * carries provenance, else by its condition.
166
+ */
167
+ setSymbol: (id: FdiId, symbol: ToothSymbol) => void;
141
168
  /** Remove a finding from a tooth (no-op if absent). */
142
169
  removeFinding: (id: FdiId, condition: ToothCondition) => void;
143
170
  /** Clear every finding from a tooth. */
@@ -196,7 +196,7 @@
196
196
 
197
197
  /* ───────────────────────────────────────────────────────────────────────
198
198
  SECTION B — non-token declarations. ORIGINAL LAYER PRESERVED.
199
- 128 declarations across 124 rules.
199
+ 127 declarations across 123 rules.
200
200
 
201
201
  Kit-authored arbitrary-value utilities (`ds:w-[20rem]`) and the
202
202
  vendored AG Grid rules. These set real properties on real elements,
@@ -412,9 +412,6 @@
412
412
  .ds\:max-w-\[56rem\] {
413
413
  max-width:896px;
414
414
  }
415
- .ds\:max-w-\[64rem\] {
416
- max-width:1024px;
417
- }
418
415
  .ds\:max-w-\[76rem\] {
419
416
  max-width:1216px;
420
417
  }
@@ -1734,6 +1734,7 @@ export declare const arUi: {
1734
1734
  readonly noAvailability: "لا توفر — جرّب يوماً أو خدمة أخرى";
1735
1735
  readonly serviceListLabel: "الخدمات المتاحة";
1736
1736
  readonly serviceCardLabel: "{{label}}، {{duration}} دقيقة";
1737
+ readonly serviceCardLabelPrice: "{{label}}، {{price}}";
1737
1738
  readonly actions: {
1738
1739
  readonly back: "رجوع";
1739
1740
  readonly next: "التالي";
@@ -3090,6 +3091,7 @@ export declare const arUi: {
3090
3091
  readonly toothScheme: {
3091
3092
  readonly ariaLabel: "مخطط الأسنان";
3092
3093
  readonly legendLabel: "دليل الحالات";
3094
+ readonly legendStatusLabel: "الحالة";
3093
3095
  readonly view: {
3094
3096
  readonly side: "عرض جانبي";
3095
3097
  readonly occlusal: "عرض إطباقي";
@@ -3134,9 +3136,23 @@ export declare const arUi: {
3134
3136
  readonly rootCanal: "علاج جذر";
3135
3137
  readonly temporaryCrown: "تاج مؤقت";
3136
3138
  readonly bridge: "جسر";
3137
- readonly destroyed: "مُهدَّم";
3139
+ readonly destroyed: "جذر مستبقى";
3138
3140
  readonly implantExtraction: "إزالة زرعة";
3139
3141
  readonly stub: "جذر متبقٍ";
3142
+ readonly pin: "وتد جذري";
3143
+ readonly rootAmputation: "قطع ذروة الجذر";
3144
+ readonly anchorage: "مثبت الطقم الجزئي";
3145
+ readonly hook: "مشبك";
3146
+ readonly attachment: "ملحق تقويمي";
3147
+ readonly mucogingivalSurgery: "جراحة مخاطية لثوية";
3148
+ readonly periodontalSurgery: "جراحة دواعم السن";
3149
+ readonly curettage: "تجريف";
3150
+ readonly medication: "ضماد دوائي";
3151
+ readonly xray: "صورة شعاعية";
3152
+ };
3153
+ readonly status: {
3154
+ readonly planned: "مخطط";
3155
+ readonly executed: "منفَّذ";
3140
3156
  };
3141
3157
  readonly surface: {
3142
3158
  readonly mesial: "وسطاني";
@@ -3145,6 +3161,13 @@ export declare const arUi: {
3145
3161
  readonly buccal: "دهليزي";
3146
3162
  readonly lingual: "لساني";
3147
3163
  };
3164
+ readonly root: {
3165
+ readonly mesial: "الجذر الوسطاني";
3166
+ readonly distal: "الجذر الوحشي";
3167
+ readonly palatal: "الجذر الحنكي";
3168
+ readonly buccal: "الجذر الدهليزي";
3169
+ readonly single: "جذر مفرد";
3170
+ };
3148
3171
  readonly numbering: {
3149
3172
  readonly fdi: "FDI (ISO 3950)";
3150
3173
  readonly universal: "عالمي (ADA)";
@@ -3152,6 +3175,9 @@ export declare const arUi: {
3152
3175
  };
3153
3176
  readonly toothLabel: "السن {{id}}, {{anatomy}}{{conditionSuffix}}";
3154
3177
  readonly elementLabel: "{{name}}{{conditionSuffix}}";
3178
+ readonly symbolWithStatus: "{{condition}} ({{status}})";
3179
+ readonly symbolWithScope: "{{condition}} ({{scope}})";
3180
+ readonly symbolWithScopeAndStatus: "{{condition}} ({{scope}}, {{status}})";
3155
3181
  readonly selected: "تم تحديد السن {{id}}, {{conditions}}";
3156
3182
  readonly deselected: "تم إلغاء تحديد السن {{id}}";
3157
3183
  readonly elementSelected: "تم تحديد {{name}}, {{conditions}}";
@@ -3163,6 +3189,20 @@ export declare const arUi: {
3163
3189
  readonly radiographBadge_many: "{{count}} صورة شعاعية";
3164
3190
  readonly radiographBadge_other: "{{count}} صورة شعاعية";
3165
3191
  };
3192
+ readonly toothFindingPalette: {
3193
+ readonly ariaLabel: "الموجودات السنية";
3194
+ readonly statusLabel: "الحالة";
3195
+ readonly empty: "لا توجد موجودات متاحة";
3196
+ readonly group: {
3197
+ readonly decay: "التسوس والترميم";
3198
+ readonly prosthetics: "التعويضات السنية";
3199
+ readonly endodontics: "علاج الجذور";
3200
+ readonly periodontics: "دواعم السن";
3201
+ readonly orthodontics: "التقويم والأجهزة";
3202
+ readonly diagnosis: "حالة السن والتصوير";
3203
+ readonly custom: "موجودات العيادة";
3204
+ };
3205
+ };
3166
3206
  readonly privacyLock: {
3167
3207
  readonly triggerAriaLabel: "قفل الشاشة للخصوصية";
3168
3208
  readonly triggerTooltip: "قفل الشاشة";
@@ -1731,6 +1731,7 @@ const e = {
1731
1731
  noAvailability: "لا توفر — جرّب يوماً أو خدمة أخرى",
1732
1732
  serviceListLabel: "الخدمات المتاحة",
1733
1733
  serviceCardLabel: "{{label}}، {{duration}} دقيقة",
1734
+ serviceCardLabelPrice: "{{label}}، {{price}}",
1734
1735
  actions: {
1735
1736
  back: "رجوع",
1736
1737
  next: "التالي",
@@ -3058,6 +3059,7 @@ const e = {
3058
3059
  toothScheme: {
3059
3060
  ariaLabel: "مخطط الأسنان",
3060
3061
  legendLabel: "دليل الحالات",
3062
+ legendStatusLabel: "الحالة",
3061
3063
  view: {
3062
3064
  side: "عرض جانبي",
3063
3065
  occlusal: "عرض إطباقي",
@@ -3102,9 +3104,23 @@ const e = {
3102
3104
  rootCanal: "علاج جذر",
3103
3105
  temporaryCrown: "تاج مؤقت",
3104
3106
  bridge: "جسر",
3105
- destroyed: "مُهدَّم",
3107
+ destroyed: "جذر مستبقى",
3106
3108
  implantExtraction: "إزالة زرعة",
3107
- stub: "جذر متبقٍ"
3109
+ stub: "جذر متبقٍ",
3110
+ pin: "وتد جذري",
3111
+ rootAmputation: "قطع ذروة الجذر",
3112
+ anchorage: "مثبت الطقم الجزئي",
3113
+ hook: "مشبك",
3114
+ attachment: "ملحق تقويمي",
3115
+ mucogingivalSurgery: "جراحة مخاطية لثوية",
3116
+ periodontalSurgery: "جراحة دواعم السن",
3117
+ curettage: "تجريف",
3118
+ medication: "ضماد دوائي",
3119
+ xray: "صورة شعاعية"
3120
+ },
3121
+ status: {
3122
+ planned: "مخطط",
3123
+ executed: "منفَّذ"
3108
3124
  },
3109
3125
  surface: {
3110
3126
  mesial: "وسطاني",
@@ -3113,6 +3129,13 @@ const e = {
3113
3129
  buccal: "دهليزي",
3114
3130
  lingual: "لساني"
3115
3131
  },
3132
+ root: {
3133
+ mesial: "الجذر الوسطاني",
3134
+ distal: "الجذر الوحشي",
3135
+ palatal: "الجذر الحنكي",
3136
+ buccal: "الجذر الدهليزي",
3137
+ single: "جذر مفرد"
3138
+ },
3116
3139
  numbering: {
3117
3140
  fdi: "FDI (ISO 3950)",
3118
3141
  universal: "عالمي (ADA)",
@@ -3120,6 +3143,9 @@ const e = {
3120
3143
  },
3121
3144
  toothLabel: "السن {{id}}, {{anatomy}}{{conditionSuffix}}",
3122
3145
  elementLabel: "{{name}}{{conditionSuffix}}",
3146
+ symbolWithStatus: "{{condition}} ({{status}})",
3147
+ symbolWithScope: "{{condition}} ({{scope}})",
3148
+ symbolWithScopeAndStatus: "{{condition}} ({{scope}}, {{status}})",
3123
3149
  selected: "تم تحديد السن {{id}}, {{conditions}}",
3124
3150
  deselected: "تم إلغاء تحديد السن {{id}}",
3125
3151
  elementSelected: "تم تحديد {{name}}, {{conditions}}",
@@ -3131,6 +3157,20 @@ const e = {
3131
3157
  radiographBadge_many: "{{count}} صورة شعاعية",
3132
3158
  radiographBadge_other: "{{count}} صورة شعاعية"
3133
3159
  },
3160
+ toothFindingPalette: {
3161
+ ariaLabel: "الموجودات السنية",
3162
+ statusLabel: "الحالة",
3163
+ empty: "لا توجد موجودات متاحة",
3164
+ group: {
3165
+ decay: "التسوس والترميم",
3166
+ prosthetics: "التعويضات السنية",
3167
+ endodontics: "علاج الجذور",
3168
+ periodontics: "دواعم السن",
3169
+ orthodontics: "التقويم والأجهزة",
3170
+ diagnosis: "حالة السن والتصوير",
3171
+ custom: "موجودات العيادة"
3172
+ }
3173
+ },
3134
3174
  privacyLock: {
3135
3175
  triggerAriaLabel: "قفل الشاشة للخصوصية",
3136
3176
  triggerTooltip: "قفل الشاشة",