@alfadocs/ui-kit 1.4.16 → 1.5.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 (82) hide show
  1. package/dist/_chunks/{anamnesis-summary-rows-CVzxC2X3.js → anamnesis-summary-rows-BpYztFUv.js} +20 -4
  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/tooth-data-DR8Kdnup.js +903 -0
  6. package/dist/_chunks/tooth-finding-palette-vqC-D2Ye.js +708 -0
  7. package/dist/_chunks/tooth-scheme-BPXE1_3N.js +2051 -0
  8. package/dist/agent-catalog.json +465 -21
  9. package/dist/agent-i18n/en.json +23 -6
  10. package/dist/components/care-plan-card/index.js +1 -1
  11. package/dist/components/care-plan-entry-card/index.js +1 -1
  12. package/dist/components/index.d.ts +1 -0
  13. package/dist/components/periodontal-chart/index.js +1 -1
  14. package/dist/components/tooth-finding-palette/index.d.ts +4 -0
  15. package/dist/components/tooth-finding-palette/index.js +9 -0
  16. package/dist/components/tooth-finding-palette/tooth-finding-palette.agent.d.ts +4 -0
  17. package/dist/components/tooth-finding-palette/tooth-finding-palette.d.ts +89 -0
  18. package/dist/components/tooth-scheme/index.d.ts +2 -2
  19. package/dist/components/tooth-scheme/index.js +57 -30
  20. package/dist/components/tooth-scheme/tooth-data.d.ts +279 -10
  21. package/dist/components/tooth-scheme/tooth-scheme.agent.d.ts +2 -2
  22. package/dist/components/tooth-scheme/tooth-scheme.d.ts +30 -3
  23. package/dist/i18n/locales/ar.d.ts +40 -1
  24. package/dist/i18n/locales/ar.js +41 -2
  25. package/dist/i18n/locales/de.d.ts +40 -1
  26. package/dist/i18n/locales/de.js +41 -2
  27. package/dist/i18n/locales/el.d.ts +40 -1
  28. package/dist/i18n/locales/el.js +41 -2
  29. package/dist/i18n/locales/en.d.ts +40 -1
  30. package/dist/i18n/locales/en.js +41 -2
  31. package/dist/i18n/locales/es.d.ts +40 -1
  32. package/dist/i18n/locales/es.js +41 -2
  33. package/dist/i18n/locales/fr.d.ts +40 -1
  34. package/dist/i18n/locales/fr.js +41 -2
  35. package/dist/i18n/locales/hi.d.ts +40 -1
  36. package/dist/i18n/locales/hi.js +41 -2
  37. package/dist/i18n/locales/it.d.ts +40 -1
  38. package/dist/i18n/locales/it.js +41 -2
  39. package/dist/i18n/locales/ja.d.ts +40 -1
  40. package/dist/i18n/locales/ja.js +41 -2
  41. package/dist/i18n/locales/nl.d.ts +40 -1
  42. package/dist/i18n/locales/nl.js +41 -2
  43. package/dist/i18n/locales/pl.d.ts +40 -1
  44. package/dist/i18n/locales/pl.js +41 -2
  45. package/dist/i18n/locales/pt.d.ts +40 -1
  46. package/dist/i18n/locales/pt.js +41 -2
  47. package/dist/i18n/locales/ro.d.ts +40 -1
  48. package/dist/i18n/locales/ro.js +41 -2
  49. package/dist/i18n/locales/ru.d.ts +40 -1
  50. package/dist/i18n/locales/ru.js +41 -2
  51. package/dist/i18n/locales/sq.d.ts +40 -1
  52. package/dist/i18n/locales/sq.js +41 -2
  53. package/dist/i18n/locales/sv.d.ts +40 -1
  54. package/dist/i18n/locales/sv.js +41 -2
  55. package/dist/i18n/locales/tr.d.ts +40 -1
  56. package/dist/i18n/locales/tr.js +41 -2
  57. package/dist/i18n/locales/zh.d.ts +40 -1
  58. package/dist/i18n/locales/zh.js +41 -2
  59. package/dist/index.js +448 -415
  60. package/dist/locales/ar.json +41 -2
  61. package/dist/locales/de.json +41 -2
  62. package/dist/locales/el.json +41 -2
  63. package/dist/locales/en.json +41 -2
  64. package/dist/locales/es.json +41 -2
  65. package/dist/locales/fr.json +41 -2
  66. package/dist/locales/hi.json +41 -2
  67. package/dist/locales/it.json +41 -2
  68. package/dist/locales/ja.json +41 -2
  69. package/dist/locales/nl.json +41 -2
  70. package/dist/locales/pl.json +41 -2
  71. package/dist/locales/pt.json +41 -2
  72. package/dist/locales/ro.json +41 -2
  73. package/dist/locales/ru.json +41 -2
  74. package/dist/locales/sq.json +41 -2
  75. package/dist/locales/sv.json +41 -2
  76. package/dist/locales/tr.json +41 -2
  77. package/dist/locales/zh.json +41 -2
  78. package/dist/patterns/anamnesis/index.js +1 -1
  79. package/dist/tokens.css +1 -1
  80. package/package.json +5 -1
  81. package/dist/_chunks/tooth-data-BwuoKFf4.js +0 -660
  82. package/dist/_chunks/tooth-scheme-s0ipC0-Z.js +0 -1483
@@ -1,1483 +0,0 @@
1
- import { jsxs as b, jsx as a, Fragment as hi } from "react/jsx-runtime";
2
- import { forwardRef as ui, useState as E, useRef as Le, useEffect as be, useMemo as ye, useCallback as A, useImperativeHandle as pi } from "react";
3
- import { createPortal as fi } from "react-dom";
4
- import * as N from "@radix-ui/react-tooltip";
5
- import { c as U } from "./index-D2ZczOXr.js";
6
- import { useTranslation as Ot } from "react-i18next";
7
- import { u as mi } from "./registry-DvAUVLHh.js";
8
- import { I as gi } from "./icon-button-9c9Gp41m.js";
9
- import { P as Be } from "./popover-Btj6N25H.js";
10
- import { S as vi } from "./select-BW5ecXlX.js";
11
- import { S as Ve } from "./switch-OILsBLWo.js";
12
- import { i as Ct, p as bi, T as yi, o as je, q as Oe, m as xi, S as wi, F as re, v as Ge, u as Rt, w as G, n as $t, b as Xe, C as we, t as _t, a as Si, r as ki, x as Ii, y as x, A as W, j as Mt, z as Ti, s as Ai, B as Di } from "./tooth-data-BwuoKFf4.js";
13
- import { S as Ci } from "./settings-d25ju_6L.js";
14
- const z = {
15
- type: "string",
16
- description: "FDI tooth id ('11'–'48' permanent, '51'–'85' primary) or a special-element id ('Q1'–'Q4' quadrants, 'S1'–'S6' sextants, 'AS'/'AI' arches, 'general'; primary mirrors with an 'm' prefix)."
17
- }, _e = {
18
- enum: [
19
- "caries",
20
- "filled",
21
- "crowned",
22
- "temporaryCrown",
23
- "bridge",
24
- "missing",
25
- "implant",
26
- "implantExtraction",
27
- "stub",
28
- "destroyed",
29
- "rootCanal"
30
- ]
31
- }, Ri = {
32
- enum: ["mesial", "distal", "occlusal", "buccal", "lingual"]
33
- }, $i = {
34
- type: "object",
35
- properties: {
36
- id: { type: "string" },
37
- url: { type: "string" },
38
- thumbnailUrl: { type: "string" },
39
- date: { type: "string", description: "ISO acquisition date (YYYY-MM-DD)." },
40
- note: { type: "string" },
41
- kind: { enum: ["periapical", "bitewing", "panoramic", "other"] },
42
- alt: { type: "string" }
43
- },
44
- required: ["id", "url"]
45
- }, Ni = {
46
- id: "tooth-scheme",
47
- // pick — focus/select a tooth (`focus_tooth`, transient, not persisted);
48
- // set_value / edit_inline — `set_finding` records a finding and marks the
49
- // affected surfaces (set-surface), `remove_finding` clears one;
50
- // view_change — the side/plan projection + dentition are view props.
51
- capabilities: ["pick", "set_value", "edit_inline", "view_change"],
52
- state: {
53
- chart: {
54
- type: "object",
55
- descriptionKey: "ui.agent.toothScheme.state.chart",
56
- description: "Current dental chart — findings (and marked surfaces) keyed by FDI id, or by a special-element id (quadrant / sextant / arch / general) for region-spanning findings.",
57
- read: (r) => r.getChart()
58
- },
59
- chartedTeeth: {
60
- type: "string[]",
61
- descriptionKey: "ui.agent.toothScheme.state.chartedTeeth",
62
- description: "Ids carrying at least one finding — FDI tooth ids and/or special-element ids (quadrant / sextant / arch / general).",
63
- read: (r) => Object.keys(r.getChart())
64
- },
65
- radiographs: {
66
- // A9: the always-on state snapshot carries identifiers + enums only —
67
- // never PHI free-text (the radiograph `note`), service dates, or the
68
- // consumer-hosted image URLs. Those are fetched deliberately, per tooth,
69
- // via the audited `get_radiographs` action.
70
- type: "Record<string, { id: string; kind?: string }[]>",
71
- descriptionKey: "ui.agent.toothScheme.state.radiographs",
72
- description: "Structural references (id + kind) to the radiographs on each tooth, keyed by FDI id. Notes, dates and image URLs are not exposed here — fetch them on demand via get_radiographs.",
73
- read: (r) => Object.fromEntries(
74
- r.teethWithRadiographs().map((n) => [
75
- n,
76
- r.getRadiographs(n).map((u) => ({ id: u.id, kind: u.kind ?? "periapical" }))
77
- ])
78
- )
79
- },
80
- teethWithRadiographs: {
81
- type: "string[]",
82
- descriptionKey: "ui.agent.toothScheme.state.teethWithRadiographs",
83
- description: "FDI ids of every tooth carrying at least one radiograph.",
84
- read: (r) => r.teethWithRadiographs()
85
- }
86
- },
87
- actions: {
88
- focus_tooth: {
89
- safety: "read",
90
- argsType: "{ id: FdiId }",
91
- argsSchema: {
92
- type: "object",
93
- properties: { id: z },
94
- required: ["id"]
95
- },
96
- idempotent: !0,
97
- descriptionKey: "ui.agent.toothScheme.actions.focusTooth",
98
- description: "Move focus to a specific tooth by FDI id.",
99
- invoke: (r, n) => {
100
- r.focusTooth(n.id);
101
- }
102
- },
103
- get_tooth: {
104
- safety: "read",
105
- argsType: "{ id: FdiId }",
106
- argsSchema: {
107
- type: "object",
108
- properties: { id: z },
109
- required: ["id"]
110
- },
111
- returns: "ToothCondition[]",
112
- returnsSchema: { type: "array", items: _e },
113
- idempotent: !0,
114
- descriptionKey: "ui.agent.toothScheme.actions.getTooth",
115
- description: "Read the findings recorded on one tooth (FDI id).",
116
- invoke: (r, n) => r.getTooth(n.id)
117
- },
118
- teeth_with: {
119
- safety: "read",
120
- argsType: "{ condition: ToothCondition }",
121
- argsSchema: {
122
- type: "object",
123
- properties: { condition: _e },
124
- required: ["condition"]
125
- },
126
- returns: "FdiId[]",
127
- returnsSchema: { type: "array", items: z },
128
- idempotent: !0,
129
- descriptionKey: "ui.agent.toothScheme.actions.teethWith",
130
- description: "List the ids carrying a given finding — FDI tooth ids and/or special-element ids (e.g. all teeth with caries).",
131
- invoke: (r, n) => r.teethWith(n.condition)
132
- },
133
- get_radiographs: {
134
- safety: "read",
135
- argsType: "{ id: FdiId }",
136
- argsSchema: {
137
- type: "object",
138
- properties: { id: z },
139
- required: ["id"]
140
- },
141
- returns: "Radiograph[]",
142
- returnsSchema: { type: "array", items: $i },
143
- idempotent: !0,
144
- descriptionKey: "ui.agent.toothScheme.actions.getRadiographs",
145
- description: "Read the radiographs (x-rays) attached to one tooth.",
146
- invoke: (r, n) => r.getRadiographs(n.id)
147
- },
148
- open_radiographs: {
149
- safety: "read",
150
- argsType: "{ id: FdiId }",
151
- argsSchema: {
152
- type: "object",
153
- properties: { id: z },
154
- required: ["id"]
155
- },
156
- idempotent: !0,
157
- descriptionKey: "ui.agent.toothScheme.actions.openRadiographs",
158
- description: "Focus a tooth and open its radiograph archive (fires the host's onOpenRadiographs).",
159
- invoke: (r, n) => {
160
- r.openRadiographs(n.id);
161
- }
162
- },
163
- set_finding: {
164
- safety: "write",
165
- argsType: "{ id: FdiId; condition: ToothCondition; surfaces?: Surface[] }",
166
- argsSchema: {
167
- type: "object",
168
- properties: {
169
- id: z,
170
- condition: _e,
171
- surfaces: { type: "array", items: Ri }
172
- },
173
- required: ["id", "condition"]
174
- },
175
- idempotent: !0,
176
- descriptionKey: "ui.agent.toothScheme.actions.setFinding",
177
- description: "Record a finding on a tooth or region element (crown, implant, root canal, caries, …). Optionally mark the affected surfaces for a surface finding.",
178
- invoke: (r, n) => {
179
- r.setFinding(n.id, n.condition, n.surfaces);
180
- }
181
- },
182
- remove_finding: {
183
- safety: "write",
184
- argsType: "{ id: FdiId; condition: ToothCondition }",
185
- argsSchema: {
186
- type: "object",
187
- properties: { id: z, condition: _e },
188
- required: ["id", "condition"]
189
- },
190
- idempotent: !0,
191
- descriptionKey: "ui.agent.toothScheme.actions.removeFinding",
192
- description: "Remove a single finding from a tooth.",
193
- invoke: (r, n) => {
194
- r.removeFinding(n.id, n.condition);
195
- }
196
- },
197
- clear_tooth: {
198
- safety: "destructive",
199
- argsType: "{ id: FdiId }",
200
- argsSchema: {
201
- type: "object",
202
- properties: { id: z },
203
- required: ["id"]
204
- },
205
- idempotent: !0,
206
- descriptionKey: "ui.agent.toothScheme.actions.clearTooth",
207
- description: "Clear every finding from a tooth.",
208
- invoke: (r, n) => {
209
- r.clearTooth(n.id);
210
- }
211
- }
212
- },
213
- domHooks: {
214
- root: { attr: "data-component", value: "tooth-scheme" },
215
- instanceId: {
216
- attr: "data-component-id",
217
- sourceProp: "id",
218
- description: "Sourced from the id prop."
219
- },
220
- item: {
221
- attr: "data-fdi",
222
- description: "Each rendered tooth `<g>` carries its FDI id as `data-fdi`; selectable special-element slots carry their id there too (plus `data-special` naming the kind). The `data-projection` / `data-view-mode` attributes on the root expose the side/plan/both view."
223
- }
224
- }
225
- }, Li = U(
226
- [
227
- "ds:tooth-scheme-alfadocs",
228
- "ds:flex ds:flex-col",
229
- "ds:gap-[var(--spacing-sm)]",
230
- "ds:bg-[var(--background)] ds:text-[var(--foreground)]",
231
- // Block-level flex column so the SVG's w-full can grow to fill the frame.
232
- // min-w-fit on the SVG floors it at natural size, so narrow frames scroll
233
- // here rather than shrinking the per-tooth hit target below the 44px floor.
234
- "ds:max-w-full ds:overflow-x-auto",
235
- // When the scroll container itself is the tab stop (display mode, see
236
- // scrollTabIndex) it needs a focus ring. Use an outline (not box-shadow):
237
- // forced-colors / high-contrast mode zeroes box-shadow, which would leave
238
- // HCM keyboard users with no visible focus. outline survives, and the
239
- // CanvasText fallback repaints it in the system palette.
240
- "ds:outline-none",
241
- "ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid",
242
- "ds:focus-visible:outline-[var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]",
243
- "ds:forced-colors:focus-visible:outline-[CanvasText]"
244
- ].join(" ")
245
- ), ji = U(["ds:flex ds:flex-col ds:gap-0"].join(" ")), Oi = U(
246
- [
247
- "ds:block",
248
- "ds:w-full ds:min-w-fit ds:h-auto",
249
- "ds:text-[var(--foreground)]"
250
- ].join(" ")
251
- ), Nt = U(
252
- [
253
- "ds:group ds:cursor-pointer",
254
- "ds:focus:outline-none",
255
- "ds:transition-[fill,stroke,opacity] ds:duration-[var(--animation-duration)]",
256
- "ds:motion-reduce:transition-none"
257
- ].join(" ")
258
- ), _i = U(
259
- [
260
- "ds:flex ds:flex-wrap ds:items-center",
261
- "ds:gap-[var(--spacing-sm)]",
262
- "type-meta ds:text-[var(--muted-foreground)]"
263
- ].join(" ")
264
- ), Mi = U(
265
- ["ds:inline-flex ds:items-center", "ds:gap-[var(--spacing-xs)]"].join(" ")
266
- ), Fi = U(["ds:sr-only"].join(" ")), Ei = U(
267
- [
268
- "ds:cursor-pointer ds:outline-none",
269
- "ds:fill-transparent ds:stroke-transparent",
270
- "ds:transition-[fill] ds:duration-[var(--animation-duration)]",
271
- "ds:motion-reduce:transition-none",
272
- "ds:hover:fill-[color-mix(in_srgb,var(--accent)_18%,transparent)]",
273
- "ds:focus-visible:fill-[color-mix(in_srgb,var(--accent)_22%,transparent)]",
274
- "ds:focus-visible:stroke-[var(--ring)]",
275
- "ds:forced-colors:focus-visible:stroke-[CanvasText]"
276
- ].join(" ")
277
- );
278
- function Qe(r) {
279
- return r.value !== void 0;
280
- }
281
- function Me() {
282
- return { conditions: [], surfaces: [] };
283
- }
284
- function Lt(r, n) {
285
- const u = r ?? [];
286
- return n ? u.includes(n) ? u.filter((m) => m !== n) : [...u, n] : u.length === 0 ? ["caries"] : [];
287
- }
288
- function jt(r, n) {
289
- switch (r.labelKey) {
290
- case "quadrant":
291
- return n("toothScheme.special.quadrant", { n: r.labelIndex });
292
- case "sextant":
293
- return n("toothScheme.special.sextant", { n: r.labelIndex });
294
- case "archUpper":
295
- return n("toothScheme.special.archUpper");
296
- case "archLower":
297
- return n("toothScheme.special.archLower");
298
- default:
299
- return n("toothScheme.special.general");
300
- }
301
- }
302
- function Wi(r, n, u) {
303
- var D;
304
- return u ? ((D = {
305
- top: { ArrowDown: "center" },
306
- bottom: { ArrowUp: "center" },
307
- left: { ArrowRight: "center" },
308
- right: { ArrowLeft: "center" },
309
- center: {
310
- ArrowUp: "top",
311
- ArrowDown: "bottom",
312
- ArrowLeft: "left",
313
- ArrowRight: "right"
314
- }
315
- }[r]) == null ? void 0 : D[n]) ?? r : n === "ArrowUp" ? "top" : n === "ArrowDown" ? "bottom" : n === "ArrowLeft" ? "left" : n === "ArrowRight" ? "right" : r;
316
- }
317
- const qi = [
318
- "caries",
319
- "filled",
320
- "crowned",
321
- "temporaryCrown",
322
- "bridge",
323
- "rootCanal",
324
- "implant",
325
- "implantExtraction",
326
- "stub",
327
- "destroyed",
328
- "missing"
329
- ];
330
- function Hi({
331
- condition: r,
332
- assetBaseUrl: n
333
- }) {
334
- const u = re[16], m = Xe[r], D = r === "missing", Q = r === "caries" || r === "filled", C = 36 * 0.9, Z = 62 * 0.9, P = (36 - C) / 2, p = (62 - Z) / 2;
335
- return /* @__PURE__ */ b(
336
- "svg",
337
- {
338
- width: "22",
339
- height: "38",
340
- viewBox: "0 0 36 62",
341
- "aria-hidden": "true",
342
- className: "ds:block ds:shrink-0",
343
- children: [
344
- /* @__PURE__ */ a(
345
- "image",
346
- {
347
- href: _t(u, n),
348
- x: P,
349
- y: p,
350
- width: C,
351
- height: Z,
352
- preserveAspectRatio: "xMidYMid meet",
353
- opacity: D ? 0.25 : 1
354
- }
355
- ),
356
- m ? /* @__PURE__ */ a(
357
- "image",
358
- {
359
- href: Mt(u, n, m),
360
- x: P,
361
- y: p,
362
- width: C,
363
- height: Z,
364
- preserveAspectRatio: "xMidYMid meet"
365
- }
366
- ) : null,
367
- Q ? /* @__PURE__ */ a(
368
- "rect",
369
- {
370
- x: 3,
371
- y: 2,
372
- width: 30,
373
- height: 58,
374
- fill: "none",
375
- stroke: we[r],
376
- strokeWidth: 2,
377
- strokeDasharray: r === "filled" ? "4 2" : void 0,
378
- rx: 6
379
- }
380
- ) : null,
381
- D ? /* @__PURE__ */ a(
382
- "path",
383
- {
384
- d: "M7 9 L29 53 M29 9 L7 53",
385
- stroke: we.missing,
386
- strokeWidth: 2,
387
- fill: "none"
388
- }
389
- ) : null
390
- ]
391
- }
392
- );
393
- }
394
- function Ki({ assetBaseUrl: r }) {
395
- const { t: n } = Ot();
396
- return /* @__PURE__ */ b(
397
- "section",
398
- {
399
- "aria-label": n("toothScheme.legendLabel"),
400
- "data-testid": "tooth-scheme-legend",
401
- className: "ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:rounded-[var(--radius-md)] ds:bg-[var(--card)] ds:border ds:border-[color:var(--card-border)] ds:p-[var(--spacing-sm)] ds:shadow-[var(--shadow-card)] ds:[.theme-accessible_&]:border-2",
402
- children: [
403
- /* @__PURE__ */ a("span", { className: "type-eyebrow ds:text-[color:var(--muted-foreground)]", children: n("toothScheme.legendLabel") }),
404
- /* @__PURE__ */ a("ul", { className: _i(), children: qi.map((u) => /* @__PURE__ */ b(
405
- "li",
406
- {
407
- className: Mi(),
408
- "data-condition": u,
409
- "data-testid": `tooth-scheme-legend-item-${u}`,
410
- children: [
411
- /* @__PURE__ */ a(Hi, { condition: u, assetBaseUrl: r }),
412
- /* @__PURE__ */ a("span", { children: n(`toothScheme.condition.${u}`) })
413
- ]
414
- },
415
- u
416
- )) })
417
- ]
418
- }
419
- );
420
- }
421
- function Ze({
422
- label: r,
423
- value: n,
424
- options: u,
425
- onValueChange: m,
426
- container: D
427
- }) {
428
- return /* @__PURE__ */ b("div", { className: "ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]", children: [
429
- /* @__PURE__ */ a(
430
- "span",
431
- {
432
- "aria-hidden": "true",
433
- className: "type-label ds:text-[color:var(--muted-foreground)]",
434
- children: r
435
- }
436
- ),
437
- /* @__PURE__ */ a(
438
- vi,
439
- {
440
- size: "md",
441
- "aria-label": r,
442
- value: n,
443
- options: u,
444
- onValueChange: m,
445
- container: D
446
- }
447
- )
448
- ] });
449
- }
450
- function Yi(r, n) {
451
- return r.date === n.date ? 0 : r.date ? n.date && r.date < n.date ? 1 : -1 : 1;
452
- }
453
- const xe = ui(
454
- ({
455
- id: r,
456
- dentition: n = "permanent",
457
- numbering: u = "fdi",
458
- mode: m = "interactive",
459
- projection: D = "side",
460
- specialElements: Q,
461
- value: C,
462
- defaultValue: Z,
463
- onChange: P,
464
- onSelect: p,
465
- conditions: ae,
466
- radiographs: R,
467
- radiographDisplay: Je = "badge",
468
- onOpenRadiographs: X,
469
- activeCondition: S,
470
- assetBaseUrl: J = "/toothscheme/teeth",
471
- legend: Se = !1,
472
- controls: _ = !1,
473
- controlsContainer: ke,
474
- ariaLabel: Ft,
475
- className: Et,
476
- _arch: ee,
477
- _numbersPosition: se = "between",
478
- _inner: Ie = !1,
479
- _contentWidth: Wt
480
- }, qt) => {
481
- var xt;
482
- const { t: s } = Ot(), [Ht, et] = E(n), [Kt, tt] = E(u), [Yt, it] = E(D), [zt, ot] = E(Se), [Ut, nt] = E(
483
- Q
484
- ), [Fe, Pt] = E(null), $ = _ ? Ht : n, de = _ ? Kt : u, rt = _ ? zt : Se, ce = _ ? Yt : D, k = ce === "plan" ? "plan" : "side", Te = ce === "both" && !Ie, at = ce === "both", q = _ ? Ut ?? at : Q ?? at, st = Le(_);
485
- be(() => {
486
- _ && !st.current && (et(n), tt(u), it(D), ot(Se), nt(Q)), st.current = _;
487
- }, [
488
- _,
489
- n,
490
- u,
491
- D,
492
- Se,
493
- Q
494
- ]);
495
- const [Bt, dt] = E(() => C !== void 0 ? C : Z !== void 0 ? Z : ae ? Ct(ae) : {}), c = Qe({ value: C }) ? C : Bt;
496
- be(() => {
497
- Qe({ value: C }) || ae !== void 0 && dt(Ct(ae));
498
- }, [ae, C]);
499
- const v = k === "plan" ? 44 : yi, I = ye(
500
- () => bi($, v, ee ? { arch: ee } : {}),
501
- [$, v, ee]
502
- ), le = ye(() => {
503
- if (!q) return [];
504
- if (ee)
505
- return je(
506
- Oe($, ee, k),
507
- I.width
508
- ).specials;
509
- const e = je(
510
- Oe($, "upper", k),
511
- I.width
512
- ).specials, t = v + Di, i = je(
513
- Oe($, "lower", k),
514
- I.width
515
- ).specials.map((o) => ({ ...o, y: t }));
516
- return [...e, ...i];
517
- }, [q, ee, $, k, I.width, v]), Vt = ye(() => {
518
- if (!Te) return;
519
- if (!q) return I.width;
520
- let e = I.width;
521
- for (const t of ["upper", "lower"])
522
- for (const i of ["side", "plan"]) {
523
- const o = je(
524
- Oe($, t, i),
525
- I.width
526
- ).width;
527
- o > e && (e = o);
528
- }
529
- return e;
530
- }, [Te, q, $, I.width]), B = ye(
531
- () => [
532
- ...I.teeth.map((e) => e.fdi),
533
- // Special slots join keyboard nav only when interactive — in display /
534
- // radiograph-open mode they are decorative (role="img"), so the
535
- // radiograph-open keyboard path never reaches a region id.
536
- ...m === "interactive" ? le.map((e) => e.element.id) : []
537
- ],
538
- [I, le, m]
539
- ), Ee = B[0], [he, H] = E(Ee);
540
- be(() => {
541
- (!he || !B.includes(he)) && H(Ee);
542
- }, [Ee, he, B]);
543
- const [Gt, ue] = E(""), We = Le(null), T = A(
544
- (e) => {
545
- Qe({ value: C }) || dt(e), P == null || P(e);
546
- },
547
- [P, C]
548
- ), L = A((e) => {
549
- const t = We.current;
550
- if (!t) return;
551
- const i = t.querySelector(`g[data-fdi="${e}"]`);
552
- i && (i.focus(), H(e));
553
- }, []), te = A(
554
- (e, t) => {
555
- const i = t.map((o) => s(`toothScheme.condition.${o}`)).join(", ");
556
- if (xi(e)) {
557
- const o = jt(wi[e], s);
558
- return t.length > 0 ? s("toothScheme.elementSelected", {
559
- name: o,
560
- conditions: i
561
- }) : s("toothScheme.elementDeselected", { name: o });
562
- }
563
- return t.length > 0 ? s("toothScheme.selected", { id: e, conditions: i }) : s("toothScheme.deselected", { id: e });
564
- },
565
- [s]
566
- ), M = k === "plan" && m === "interactive" && (S === "caries" || S === "filled"), [w, pe] = E(null);
567
- be(() => {
568
- (!M || w && !B.includes(w.fdi)) && pe(null);
569
- }, [M, w, B]);
570
- const ct = A((e, t) => {
571
- var o;
572
- const i = (o = We.current) == null ? void 0 : o.querySelector(
573
- `path[data-fdi="${e}"][data-zone="${t}"]`
574
- );
575
- i == null || i.focus();
576
- }, []), qe = Le(null);
577
- be(() => {
578
- w ? ct(w.fdi, w.zone) : qe.current && L(qe.current.fdi), qe.current = w;
579
- }, [w, ct, L]);
580
- const Qt = A(
581
- (e, t) => {
582
- const i = c[e];
583
- return !!(i && i.surfaces.includes(t) && i.conditions.includes(S));
584
- },
585
- [c, S]
586
- ), lt = A(
587
- (e, t) => {
588
- t && t.conditions.length > 0 ? ue(
589
- s("toothScheme.selected", {
590
- id: e,
591
- conditions: t.conditions.map((i) => s(`toothScheme.condition.${i}`)).join(", ")
592
- })
593
- ) : ue(s("toothScheme.deselected", { id: e }));
594
- },
595
- [s]
596
- ), He = A(
597
- (e, t) => {
598
- if (!M) return;
599
- const i = S, o = c[e] ?? Me(), l = o.surfaces.includes(t), y = o.conditions.includes(i);
600
- let d, g;
601
- l && y ? (d = o.surfaces.filter((F) => F !== t), g = d.length === 0 ? o.conditions.filter((F) => F !== i) : o.conditions) : (d = l ? o.surfaces : [...o.surfaces, t], g = y ? o.conditions : [...o.conditions, i]);
602
- const f = { ...c };
603
- g.length === 0 && d.length === 0 ? delete f[e] : f[e] = { ...o, conditions: g, surfaces: d }, T(f), lt(e, f[e]), p == null || p(e);
604
- },
605
- [
606
- M,
607
- S,
608
- c,
609
- T,
610
- lt,
611
- p
612
- ]
613
- ), Ke = A((e) => {
614
- const t = re[e];
615
- t && (H(e), pe({ fdi: e, zone: Ge(t)[0] }));
616
- }, []), Zt = A(
617
- (e, t, i) => {
618
- const o = re[t];
619
- if (o)
620
- switch (e.key) {
621
- case "ArrowUp":
622
- case "ArrowDown":
623
- case "ArrowLeft":
624
- case "ArrowRight": {
625
- e.preventDefault(), e.stopPropagation();
626
- const l = Ge(o).includes("center"), y = Wi(i, e.key, l);
627
- y !== i && pe({ fdi: t, zone: y });
628
- return;
629
- }
630
- case " ":
631
- case "Enter": {
632
- e.preventDefault(), e.stopPropagation(), He(t, Rt(o, i));
633
- return;
634
- }
635
- case "Escape": {
636
- e.preventDefault(), e.stopPropagation(), pe(null);
637
- return;
638
- }
639
- default:
640
- return;
641
- }
642
- },
643
- [He]
644
- ), Xt = Le(null), Ae = m === "display" && typeof X == "function", fe = m === "interactive" || Ae, me = A(
645
- (e) => {
646
- H(e), p == null || p(e), X == null || X(e);
647
- },
648
- [p, X]
649
- ), Ye = ye(
650
- () => ({
651
- focusTooth: (e) => {
652
- L(e);
653
- },
654
- getChart: () => c,
655
- getTooth: (e) => {
656
- var t;
657
- return ((t = c[e]) == null ? void 0 : t.conditions) ?? [];
658
- },
659
- teethWith: (e) => Object.entries(c).filter(([, t]) => t.conditions.includes(e)).map(([t]) => t),
660
- setFinding: (e, t, i) => {
661
- const o = c[e] ?? Me();
662
- if (o.conditions.includes(t) && !i) return;
663
- const l = {
664
- ...c,
665
- [e]: {
666
- ...o,
667
- conditions: o.conditions.includes(t) ? o.conditions : [...o.conditions, t],
668
- surfaces: i ?? o.surfaces
669
- }
670
- };
671
- T(l);
672
- },
673
- removeFinding: (e, t) => {
674
- const i = c[e];
675
- if (!i || !i.conditions.includes(t)) return;
676
- const o = i.conditions.filter((y) => y !== t), l = { ...c };
677
- o.length === 0 ? delete l[e] : l[e] = { ...i, conditions: o }, T(l);
678
- },
679
- clearTooth: (e) => {
680
- if (!c[e]) return;
681
- const t = { ...c };
682
- delete t[e], T(t);
683
- },
684
- getRadiographs: (e) => (R == null ? void 0 : R[e]) ?? [],
685
- teethWithRadiographs: () => Object.keys(R ?? {}).filter(
686
- (e) => {
687
- var t;
688
- return (((t = R == null ? void 0 : R[e]) == null ? void 0 : t.length) ?? 0) > 0;
689
- }
690
- ),
691
- openRadiographs: (e) => {
692
- L(e), me(e);
693
- }
694
- }),
695
- [c, T, L, R, me]
696
- );
697
- pi(qt, () => Ye, [Ye]), mi(
698
- Ni,
699
- Ye,
700
- Ie ? void 0 : r
701
- );
702
- const ht = A(
703
- (e, t) => {
704
- var y;
705
- if (!fe) return;
706
- const i = re[t], o = B, l = o.indexOf(t);
707
- switch (e.key) {
708
- case "ArrowRight": {
709
- e.preventDefault();
710
- const d = Math.min(o.length - 1, l + 1);
711
- L(o[d]);
712
- return;
713
- }
714
- case "ArrowLeft": {
715
- e.preventDefault();
716
- const d = Math.max(0, l - 1);
717
- L(o[d]);
718
- return;
719
- }
720
- case "ArrowUp":
721
- case "ArrowDown": {
722
- if (e.preventDefault(), !i) return;
723
- const g = {
724
- 1: 4,
725
- 4: 1,
726
- 2: 3,
727
- 3: 2,
728
- 5: 8,
729
- 8: 5,
730
- 6: 7,
731
- 7: 6
732
- }[i.quadrant];
733
- if (!g) return;
734
- const f = `${g}${i.positionInQuadrant}`;
735
- o.includes(f) && L(f);
736
- return;
737
- }
738
- case "Home": {
739
- if (e.preventDefault(), !i) return;
740
- const d = o.filter(
741
- (g) => {
742
- var f;
743
- return ((f = re[g]) == null ? void 0 : f.quadrant) === i.quadrant;
744
- }
745
- );
746
- d.length > 0 && L(d[0]);
747
- return;
748
- }
749
- case "End": {
750
- if (e.preventDefault(), !i) return;
751
- const d = o.filter(
752
- (g) => {
753
- var f;
754
- return ((f = re[g]) == null ? void 0 : f.quadrant) === i.quadrant;
755
- }
756
- );
757
- d.length > 0 && L(d[d.length - 1]);
758
- return;
759
- }
760
- case " ":
761
- case "Enter": {
762
- if (e.preventDefault(), Ae) {
763
- me(t);
764
- return;
765
- }
766
- if (M && i) {
767
- Ke(t);
768
- return;
769
- }
770
- const d = (y = c[t]) == null ? void 0 : y.conditions, g = Lt(d, S), f = { ...c };
771
- g.length === 0 ? delete f[t] : f[t] = {
772
- ...c[t] ?? Me(),
773
- conditions: g
774
- }, ue(te(t, g)), T(f), p == null || p(t);
775
- return;
776
- }
777
- default:
778
- return;
779
- }
780
- },
781
- [
782
- S,
783
- te,
784
- c,
785
- T,
786
- Ke,
787
- L,
788
- me,
789
- p,
790
- Ae,
791
- M,
792
- fe,
793
- B
794
- ]
795
- ), ut = A(
796
- (e) => {
797
- var l;
798
- if (m !== "interactive") return;
799
- H(e);
800
- const t = (l = c[e]) == null ? void 0 : l.conditions, i = Lt(t, S), o = { ...c };
801
- i.length === 0 ? delete o[e] : o[e] = {
802
- ...c[e] ?? Me(),
803
- conditions: i
804
- }, ue(te(e, i)), T(o), p == null || p(e);
805
- },
806
- [S, te, c, T, m, p]
807
- ), V = $ === "primary" ? "mGeneral" : "general", pt = (((xt = c[V]) == null ? void 0 : xt.conditions.length) ?? 0) > 0, Jt = A(
808
- (e) => {
809
- var i;
810
- const t = { ...c };
811
- e ? t[V] = {
812
- conditions: [S ?? "caries"],
813
- surfaces: []
814
- } : delete t[V], ue(
815
- te(V, ((i = t[V]) == null ? void 0 : i.conditions) ?? [])
816
- ), T(t), p == null || p(V);
817
- },
818
- [
819
- S,
820
- te,
821
- c,
822
- T,
823
- V,
824
- p
825
- ]
826
- ), ft = se === "above" ? 16 : 2, ei = se === "below" ? 16 : 2, ti = le.length > 0 ? Math.max(...le.map((e) => e.x)) + G : 0, mt = Math.max(
827
- Wt ?? 0,
828
- I.width,
829
- ti
830
- ) + 4, gt = I.height + ft + ei, ze = Ft ?? s("toothScheme.ariaLabel"), ii = fe ? void 0 : 0, vt = Te ? null : /* @__PURE__ */ b(
831
- "svg",
832
- {
833
- ref: We,
834
- viewBox: `0 ${-ft} ${mt} ${gt}`,
835
- width: mt,
836
- height: gt,
837
- className: Oi(),
838
- role: "group",
839
- "aria-label": ze,
840
- focusable: "false",
841
- "data-testid": "tooth-scheme-svg",
842
- xmlns: "http://www.w3.org/2000/svg",
843
- children: [
844
- I.teeth.map((e) => {
845
- var Dt;
846
- const t = c[e.fdi], i = (Dt = t == null ? void 0 : t.conditions) == null ? void 0 : Dt[0], o = s(`toothScheme.anatomy.${e.meta.anatomy}`), l = i ? `, ${s(`toothScheme.condition.${i}`)}` : "", y = (R == null ? void 0 : R[e.fdi]) ?? [], d = y.length, g = d > 0, f = g ? [...y].sort(Yi)[0] : void 0, F = Je === "thumbnail" && f !== void 0, Re = g ? `, ${s("toothScheme.radiographBadge", { count: d })}` : "", K = Ie ? `, ${s(k === "plan" ? "toothScheme.view.occlusal" : "toothScheme.view.side")}` : "", Ue = s("toothScheme.toothLabel", {
847
- id: $t(e.fdi, de),
848
- anatomy: o,
849
- conditionSuffix: l
850
- }) + Re + K, $e = fe ? w ? -1 : e.fdi === he ? 0 : -1 : void 0, ie = (t == null ? void 0 : t.conditions) ?? [], wt = ie.includes("missing"), ri = ie.map((h) => ({
851
- condition: h,
852
- spec: Xe[h]
853
- })).filter(
854
- (h) => !!h.spec
855
- ), Pe = ie.find(
856
- (h) => h !== "missing" && !Xe[h]
857
- ), St = Pe ? we[Pe] : void 0, ai = (i ? `${o} · ${s(`toothScheme.condition.${i}`)}` : o) + (g ? ` · ${s("toothScheme.radiographBadge", { count: d })}` : ""), kt = $t(e.fdi, de), si = _t(
858
- e.meta,
859
- J,
860
- "default",
861
- k
862
- ), di = F && f ? f.thumbnailUrl ?? f.url : si, ci = k === "plan" ? ie.flatMap((h) => {
863
- const O = Si[h];
864
- return O ? ((t == null ? void 0 : t.surfaces) ?? []).map((Ne) => ({
865
- key: `${h}-${Ne}`,
866
- url: ki(
867
- e.meta,
868
- J,
869
- O,
870
- Ne
871
- )
872
- })) : [];
873
- }) : [], It = (e.meta.dentition === "primary" ? Ii : 1) * 0.9, oe = W * It, ne = v * It, ge = (W - oe) / 2, ve = (v - ne) / 2, j = M && (w == null ? void 0 : w.fdi) === e.fdi, Tt = M ? Ge(e.meta) : [], li = Tt.includes("center"), At = se === "above" ? -4 : se === "below" ? v + 12 : se === "none" ? null : e.meta.arch === "upper" ? v + 12 : -4;
874
- return /* @__PURE__ */ b(N.Root, { children: [
875
- /* @__PURE__ */ a(N.Trigger, { asChild: !0, children: /* @__PURE__ */ b(
876
- "g",
877
- {
878
- "data-fdi": e.fdi,
879
- "data-anatomy": e.meta.anatomy,
880
- "data-arch": e.meta.arch,
881
- "data-side": e.meta.side,
882
- "data-quadrant": e.meta.quadrant,
883
- "data-condition": i ?? "none",
884
- "data-testid": `tooth-${e.fdi}`,
885
- transform: `translate(${e.x}, ${e.y})`,
886
- tabIndex: $e,
887
- role: j ? "group" : fe ? "button" : "img",
888
- "aria-label": Ue,
889
- "aria-pressed": j ? void 0 : m === "interactive" ? i !== void 0 : void 0,
890
- className: Nt(),
891
- onClick: j ? void 0 : m === "interactive" ? M ? () => Ke(e.fdi) : () => ut(e.fdi) : Ae ? () => me(e.fdi) : void 0,
892
- onFocus: () => H(e.fdi),
893
- onKeyDown: j ? void 0 : (h) => ht(h, e.fdi),
894
- children: [
895
- /* @__PURE__ */ a(
896
- "rect",
897
- {
898
- x: -x,
899
- y: -x,
900
- width: W + x * 2,
901
- height: v + x * 2,
902
- fill: "transparent"
903
- }
904
- ),
905
- /* @__PURE__ */ a(
906
- "image",
907
- {
908
- href: di,
909
- x: ge,
910
- y: ve,
911
- width: oe,
912
- height: ne,
913
- preserveAspectRatio: F ? "xMidYMid slice" : "xMidYMid meet",
914
- opacity: wt && !F ? 0.25 : 1,
915
- "aria-hidden": "true"
916
- }
917
- ),
918
- k === "side" ? ri.map(({ condition: h, spec: O }) => /* @__PURE__ */ a(
919
- "image",
920
- {
921
- href: Mt(
922
- e.meta,
923
- J,
924
- O
925
- ),
926
- x: ge,
927
- y: ve,
928
- width: oe,
929
- height: ne,
930
- preserveAspectRatio: "xMidYMid meet",
931
- "aria-hidden": "true",
932
- pointerEvents: "none"
933
- },
934
- h
935
- )) : null,
936
- k === "plan" ? ci.map(({ key: h, url: O }) => /* @__PURE__ */ a(
937
- "image",
938
- {
939
- href: O,
940
- x: ge,
941
- y: ve,
942
- width: oe,
943
- height: ne,
944
- preserveAspectRatio: "xMidYMid meet",
945
- "aria-hidden": "true",
946
- pointerEvents: "none"
947
- },
948
- h
949
- )) : null,
950
- M ? Tt.map((h) => {
951
- const O = Rt(e.meta, h), Ne = Qt(e.fdi, O);
952
- return /* @__PURE__ */ a(
953
- "path",
954
- {
955
- d: Ti(
956
- h,
957
- { x: ge, y: ve, w: oe, h: ne },
958
- li
959
- ),
960
- "data-fdi": e.fdi,
961
- "data-zone": h,
962
- "data-surface": O,
963
- "data-testid": `tooth-${e.fdi}-zone-${h}`,
964
- role: j ? "button" : void 0,
965
- tabIndex: j ? (w == null ? void 0 : w.zone) === h ? 0 : -1 : void 0,
966
- "aria-label": j ? s("toothScheme.toothLabel", {
967
- id: kt,
968
- anatomy: s(
969
- `toothScheme.surface.${O}`
970
- ),
971
- conditionSuffix: ""
972
- }) : void 0,
973
- "aria-pressed": j ? Ne : void 0,
974
- strokeWidth: "var(--focus-ring-width)",
975
- className: Ei(),
976
- onClick: (Y) => {
977
- Y.stopPropagation(), j || H(e.fdi), He(e.fdi, O);
978
- },
979
- onKeyDown: j ? (Y) => Zt(Y, e.fdi, h) : void 0,
980
- onFocus: j ? () => pe(
981
- (Y) => Y && Y.fdi === e.fdi && Y.zone === h ? Y : { fdi: e.fdi, zone: h }
982
- ) : void 0
983
- },
984
- h
985
- );
986
- }) : null,
987
- k === "side" && St ? /* @__PURE__ */ a(
988
- "rect",
989
- {
990
- x: 3,
991
- y: 2,
992
- width: W - 6,
993
- height: v - 4,
994
- fill: "none",
995
- stroke: St,
996
- strokeWidth: "2",
997
- strokeDasharray: Pe === "filled" ? "4 2" : void 0,
998
- rx: "6",
999
- pointerEvents: "none"
1000
- }
1001
- ) : null,
1002
- wt ? /* @__PURE__ */ a(
1003
- "path",
1004
- {
1005
- d: `M7 9 L${W - 7} ${v - 9} M${W - 7} 9 L7 ${v - 9}`,
1006
- stroke: we.missing,
1007
- strokeWidth: "2",
1008
- fill: "none",
1009
- pointerEvents: "none"
1010
- }
1011
- ) : null,
1012
- F ? /* @__PURE__ */ a(
1013
- "rect",
1014
- {
1015
- x: ge,
1016
- y: ve,
1017
- width: oe,
1018
- height: ne,
1019
- fill: "none",
1020
- stroke: "var(--border)",
1021
- strokeWidth: "1",
1022
- rx: "3",
1023
- pointerEvents: "none"
1024
- }
1025
- ) : null,
1026
- g ? /* @__PURE__ */ b(
1027
- "g",
1028
- {
1029
- "data-testid": `tooth-${e.fdi}-radiograph-badge`,
1030
- "data-radiograph-count": d,
1031
- transform: `translate(${W - (d >= 10 ? 19 : 15)}, ${v - 13})`,
1032
- pointerEvents: "none",
1033
- "aria-hidden": "true",
1034
- children: [
1035
- /* @__PURE__ */ a(
1036
- "rect",
1037
- {
1038
- width: d >= 10 ? 17 : 13,
1039
- height: 12,
1040
- rx: "3.5",
1041
- fill: "var(--card)",
1042
- stroke: "var(--info-foreground)",
1043
- strokeWidth: "0.75"
1044
- }
1045
- ),
1046
- /* @__PURE__ */ a(
1047
- "text",
1048
- {
1049
- x: (d >= 10 ? 17 : 13) / 2,
1050
- y: 9,
1051
- textAnchor: "middle",
1052
- fontSize: "9",
1053
- fontWeight: "600",
1054
- fill: "var(--info-foreground)",
1055
- className: "ds:select-none",
1056
- children: d
1057
- }
1058
- )
1059
- ]
1060
- }
1061
- ) : null,
1062
- /* @__PURE__ */ a(
1063
- "rect",
1064
- {
1065
- x: -x,
1066
- y: -x,
1067
- width: W + x * 2,
1068
- height: v + x * 2,
1069
- fill: "none",
1070
- stroke: "var(--ring)",
1071
- strokeWidth: "var(--focus-ring-width)",
1072
- className: [
1073
- "ds:opacity-0",
1074
- "ds:group-focus-visible:opacity-100",
1075
- "ds:forced-colors:stroke-[CanvasText]"
1076
- ].join(" "),
1077
- "data-testid": `tooth-${e.fdi}-focus-ring`,
1078
- pointerEvents: "none",
1079
- rx: "4"
1080
- }
1081
- ),
1082
- At !== null ? /* @__PURE__ */ a(
1083
- "text",
1084
- {
1085
- x: W / 2,
1086
- y: At,
1087
- textAnchor: "middle",
1088
- fontSize: "10",
1089
- fill: "var(--muted-foreground)",
1090
- className: "ds:select-none",
1091
- "aria-hidden": "true",
1092
- children: kt
1093
- }
1094
- ) : null
1095
- ]
1096
- }
1097
- ) }),
1098
- /* @__PURE__ */ a(N.Portal, { children: /* @__PURE__ */ b(
1099
- N.Content,
1100
- {
1101
- side: "top",
1102
- sideOffset: 6,
1103
- className: "ds:z-[var(--z-tooltip)] ds:rounded-[var(--radius-sm)] ds:bg-[var(--foreground)] ds:text-[var(--background)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-xs)] ds:pt-[calc(var(--spacing-xs)/2)] ds:pb-[calc(var(--spacing-xs)/2)] ds:text-[length:var(--font-size-xs)]",
1104
- children: [
1105
- ai,
1106
- /* @__PURE__ */ a(N.Arrow, { className: "ds:fill-[var(--foreground)]" })
1107
- ]
1108
- }
1109
- ) })
1110
- ] }, e.fdi);
1111
- }),
1112
- le.map(({ element: e, x: t, y: i }) => {
1113
- var $e;
1114
- const o = c[e.id], l = ($e = o == null ? void 0 : o.conditions) == null ? void 0 : $e[0], y = l !== void 0, d = jt(e, s), g = l ? `, ${s(`toothScheme.condition.${l}`)}` : "", f = s("toothScheme.elementLabel", {
1115
- name: d,
1116
- conditionSuffix: g
1117
- }), F = l ? we[l] : void 0, Re = Ai(e, J), K = m === "interactive", Ue = K ? e.id === he ? 0 : -1 : void 0;
1118
- return /* @__PURE__ */ b(N.Root, { children: [
1119
- /* @__PURE__ */ a(N.Trigger, { asChild: !0, children: /* @__PURE__ */ b(
1120
- "g",
1121
- {
1122
- "data-fdi": e.id,
1123
- "data-special": e.kind,
1124
- "data-arch": e.arch,
1125
- "data-condition": l ?? "none",
1126
- "data-testid": `element-${e.id}`,
1127
- transform: `translate(${t}, ${i})`,
1128
- tabIndex: Ue,
1129
- role: K ? "button" : "img",
1130
- "aria-label": f,
1131
- "aria-pressed": K ? y : void 0,
1132
- className: Nt(),
1133
- onClick: K ? () => ut(e.id) : void 0,
1134
- onFocus: K ? () => H(e.id) : void 0,
1135
- onKeyDown: K ? (ie) => ht(ie, e.id) : void 0,
1136
- children: [
1137
- /* @__PURE__ */ a(
1138
- "rect",
1139
- {
1140
- x: -x,
1141
- y: -x,
1142
- width: G + x * 2,
1143
- height: v + x * 2,
1144
- fill: "transparent"
1145
- }
1146
- ),
1147
- /* @__PURE__ */ a(
1148
- "rect",
1149
- {
1150
- x: 0,
1151
- y: 0,
1152
- width: G,
1153
- height: v,
1154
- rx: 6,
1155
- fill: y ? "var(--accent)" : "var(--card)",
1156
- fillOpacity: y ? 0.16 : 1,
1157
- stroke: F ?? "var(--border)",
1158
- strokeWidth: y ? 2 : 1
1159
- }
1160
- ),
1161
- Re ? /* @__PURE__ */ b(hi, { children: [
1162
- /* @__PURE__ */ a(
1163
- "image",
1164
- {
1165
- href: Re,
1166
- x: 3,
1167
- y: 3,
1168
- width: G - 6,
1169
- height: v - 16,
1170
- preserveAspectRatio: "xMidYMid meet",
1171
- "aria-hidden": "true",
1172
- pointerEvents: "none"
1173
- }
1174
- ),
1175
- /* @__PURE__ */ a(
1176
- "text",
1177
- {
1178
- x: G / 2,
1179
- y: v - 4,
1180
- textAnchor: "middle",
1181
- fontSize: "9",
1182
- fontWeight: "600",
1183
- fill: "var(--muted-foreground)",
1184
- className: "ds:select-none",
1185
- "aria-hidden": "true",
1186
- children: e.code
1187
- }
1188
- )
1189
- ] }) : /* @__PURE__ */ a(
1190
- "text",
1191
- {
1192
- x: G / 2,
1193
- y: v / 2,
1194
- textAnchor: "middle",
1195
- dominantBaseline: "central",
1196
- fontSize: "11",
1197
- fontWeight: "600",
1198
- fill: "var(--foreground)",
1199
- className: "ds:select-none",
1200
- "aria-hidden": "true",
1201
- children: e.code
1202
- }
1203
- ),
1204
- /* @__PURE__ */ a(
1205
- "rect",
1206
- {
1207
- x: -x,
1208
- y: -x,
1209
- width: G + x * 2,
1210
- height: v + x * 2,
1211
- fill: "none",
1212
- stroke: "var(--ring)",
1213
- strokeWidth: "var(--focus-ring-width)",
1214
- className: [
1215
- "ds:opacity-0",
1216
- "ds:group-focus-visible:opacity-100",
1217
- "ds:forced-colors:stroke-[CanvasText]"
1218
- ].join(" "),
1219
- "data-testid": `element-${e.id}-focus-ring`,
1220
- pointerEvents: "none",
1221
- rx: "6"
1222
- }
1223
- )
1224
- ]
1225
- }
1226
- ) }),
1227
- /* @__PURE__ */ a(N.Portal, { children: /* @__PURE__ */ b(
1228
- N.Content,
1229
- {
1230
- side: "top",
1231
- sideOffset: 6,
1232
- className: "ds:z-[var(--z-tooltip)] ds:rounded-[var(--radius-sm)] ds:bg-[var(--foreground)] ds:text-[var(--background)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-xs)] ds:pt-[calc(var(--spacing-xs)/2)] ds:pb-[calc(var(--spacing-xs)/2)] ds:text-[length:var(--font-size-xs)]",
1233
- children: [
1234
- l ? `${d} · ${s(`toothScheme.condition.${l}`)}` : d,
1235
- /* @__PURE__ */ a(N.Arrow, { className: "ds:fill-[var(--foreground)]" })
1236
- ]
1237
- }
1238
- ) })
1239
- ] }, e.id);
1240
- })
1241
- ]
1242
- }
1243
- ), bt = /* @__PURE__ */ a(
1244
- "div",
1245
- {
1246
- className: Fi(),
1247
- "aria-live": "polite",
1248
- "aria-atomic": "true",
1249
- "data-testid": "tooth-scheme-live",
1250
- children: Gt
1251
- }
1252
- );
1253
- if (Ie)
1254
- return /* @__PURE__ */ b(N.Provider, { delayDuration: 200, children: [
1255
- vt,
1256
- bt
1257
- ] });
1258
- const oi = (e) => s(e === "upper" ? "toothScheme.arch.upper" : "toothScheme.arch.lower"), De = (e, t) => `${ze} — ${oi(e)}, ${s(t === "plan" ? "toothScheme.view.occlusal" : "toothScheme.view.side")}`, Ce = {
1259
- dentition: $,
1260
- numbering: de,
1261
- mode: m,
1262
- value: c,
1263
- onChange: T,
1264
- onSelect: p,
1265
- activeCondition: S,
1266
- assetBaseUrl: J,
1267
- radiographs: R,
1268
- radiographDisplay: Je,
1269
- onOpenRadiographs: X,
1270
- specialElements: q,
1271
- _inner: !0,
1272
- _contentWidth: Vt
1273
- }, ni = /* @__PURE__ */ b("div", { className: ji(), "data-testid": "tooth-scheme-both", children: [
1274
- /* @__PURE__ */ a(
1275
- xe,
1276
- {
1277
- ...Ce,
1278
- projection: "side",
1279
- _arch: "upper",
1280
- _numbersPosition: "above",
1281
- ariaLabel: De("upper", "side")
1282
- }
1283
- ),
1284
- /* @__PURE__ */ a(
1285
- xe,
1286
- {
1287
- ...Ce,
1288
- projection: "plan",
1289
- _arch: "upper",
1290
- _numbersPosition: "none",
1291
- ariaLabel: De("upper", "plan")
1292
- }
1293
- ),
1294
- /* @__PURE__ */ a(
1295
- xe,
1296
- {
1297
- ...Ce,
1298
- projection: "plan",
1299
- _arch: "lower",
1300
- _numbersPosition: "none",
1301
- ariaLabel: De("lower", "plan")
1302
- }
1303
- ),
1304
- /* @__PURE__ */ a(
1305
- xe,
1306
- {
1307
- ...Ce,
1308
- projection: "side",
1309
- _arch: "lower",
1310
- _numbersPosition: "below",
1311
- ariaLabel: De("lower", "side")
1312
- }
1313
- )
1314
- ] }), yt = _ ? /* @__PURE__ */ a(
1315
- "div",
1316
- {
1317
- className: ke != null ? "ds:flex ds:justify-end" : "ds:flex ds:w-full ds:justify-end",
1318
- "data-testid": "tooth-scheme-controls",
1319
- children: /* @__PURE__ */ b(Be.Root, { children: [
1320
- /* @__PURE__ */ a(Be.Trigger, { asChild: !0, children: /* @__PURE__ */ a(
1321
- gi,
1322
- {
1323
- size: "sm",
1324
- intent: "outline",
1325
- icon: /* @__PURE__ */ a(Ci, { "aria-hidden": "true" }),
1326
- "aria-label": s("toothScheme.options.label"),
1327
- tooltip: s("toothScheme.options.label")
1328
- }
1329
- ) }),
1330
- /* @__PURE__ */ a(
1331
- Be.Content,
1332
- {
1333
- ref: Pt,
1334
- align: "end",
1335
- size: "md",
1336
- "aria-label": s("toothScheme.options.label"),
1337
- children: /* @__PURE__ */ b("div", { className: "ds:flex ds:w-[var(--popover-size-sm)] ds:max-w-full ds:flex-col ds:gap-[var(--spacing-md)]", children: [
1338
- /* @__PURE__ */ b("div", { className: "ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:border-b ds:border-[color:var(--border)] ds:pb-[var(--spacing-sm)] ds:[&>*]:w-full ds:[&>*]:justify-between", children: [
1339
- /* @__PURE__ */ a(
1340
- Ve,
1341
- {
1342
- label: s("toothScheme.options.legend"),
1343
- labelSide: "start",
1344
- checked: rt,
1345
- onCheckedChange: ot
1346
- }
1347
- ),
1348
- /* @__PURE__ */ a(
1349
- Ve,
1350
- {
1351
- label: s("toothScheme.options.specialElements"),
1352
- labelSide: "start",
1353
- checked: q,
1354
- onCheckedChange: nt
1355
- }
1356
- )
1357
- ] }),
1358
- /* @__PURE__ */ a(
1359
- Ze,
1360
- {
1361
- container: Fe,
1362
- label: s("toothScheme.options.dentition"),
1363
- value: $,
1364
- onValueChange: (e) => et(e),
1365
- options: [
1366
- {
1367
- value: "permanent",
1368
- label: s("toothScheme.dentition.permanent")
1369
- },
1370
- {
1371
- value: "primary",
1372
- label: s("toothScheme.dentition.primary")
1373
- },
1374
- {
1375
- value: "mixed",
1376
- label: s("toothScheme.dentition.mixed")
1377
- }
1378
- ]
1379
- }
1380
- ),
1381
- /* @__PURE__ */ a(
1382
- Ze,
1383
- {
1384
- container: Fe,
1385
- label: s("toothScheme.options.numbering"),
1386
- value: de,
1387
- onValueChange: (e) => tt(e),
1388
- options: [
1389
- {
1390
- value: "fdi",
1391
- label: s("toothScheme.numbering.fdi")
1392
- },
1393
- {
1394
- value: "universal",
1395
- label: s("toothScheme.numbering.universal")
1396
- },
1397
- {
1398
- value: "palmer",
1399
- label: s("toothScheme.numbering.palmer")
1400
- }
1401
- ]
1402
- }
1403
- ),
1404
- /* @__PURE__ */ a(
1405
- Ze,
1406
- {
1407
- container: Fe,
1408
- label: s("toothScheme.options.view"),
1409
- value: ce,
1410
- onValueChange: (e) => it(e),
1411
- options: [
1412
- {
1413
- value: "side",
1414
- label: s("toothScheme.view.side")
1415
- },
1416
- {
1417
- value: "plan",
1418
- label: s("toothScheme.view.occlusal")
1419
- },
1420
- {
1421
- value: "both",
1422
- label: s("toothScheme.view.both")
1423
- }
1424
- ]
1425
- }
1426
- )
1427
- ] })
1428
- }
1429
- )
1430
- ] })
1431
- }
1432
- ) : null;
1433
- return /* @__PURE__ */ a(N.Provider, { delayDuration: 200, children: /* @__PURE__ */ b(
1434
- "div",
1435
- {
1436
- ref: Xt,
1437
- role: "region",
1438
- "aria-label": ze,
1439
- tabIndex: ii,
1440
- className: [Li(), Et].filter(Boolean).join(" "),
1441
- "data-component": "tooth-scheme",
1442
- "data-component-id": r,
1443
- "data-testid": "tooth-scheme-root",
1444
- "data-dentition": $,
1445
- "data-numbering": de,
1446
- "data-mode": m,
1447
- "data-projection": k,
1448
- "data-view-mode": ce,
1449
- "data-special-elements": q ? "true" : "false",
1450
- children: [
1451
- ke === void 0 ? yt : ke ? fi(yt, ke) : null,
1452
- Te ? ni : vt,
1453
- q && (m === "interactive" || pt) ? /* @__PURE__ */ a(
1454
- "div",
1455
- {
1456
- className: "ds:flex ds:w-full ds:items-center ds:pt-[var(--spacing-2xs)]",
1457
- "data-testid": "tooth-scheme-general",
1458
- children: /* @__PURE__ */ a(
1459
- Ve,
1460
- {
1461
- label: s("toothScheme.special.general"),
1462
- labelSide: "end",
1463
- checked: pt,
1464
- disabled: m !== "interactive",
1465
- onCheckedChange: Jt
1466
- }
1467
- )
1468
- }
1469
- ) : null,
1470
- rt ? /* @__PURE__ */ a(Ki, { assetBaseUrl: J }) : null,
1471
- bt
1472
- ]
1473
- }
1474
- ) });
1475
- }
1476
- );
1477
- xe.displayName = "ToothScheme";
1478
- export {
1479
- xe as T,
1480
- Li as r,
1481
- Ni as t
1482
- };
1483
- //# sourceMappingURL=tooth-scheme-s0ipC0-Z.js.map