npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-advanced-odontogram

v2.1.0

Published

Interactive dental chart editor component for Vue 3 with clinical charting, FHIR export, and multilingual UI

Readme

vue-advanced-odontogram

Vue 3 npm package — a Vue port of the full-featured React Odontogram Modul dental chart editor.

npm version Upstream: React License DOI

Vue TypeScript


🌐 Languages: 🇬🇧 English | 🇪🇸 Español | 🇩🇪 Deutsch | 🇭🇺 Magyar | 🇮🇹 Italiano | 🇸🇰 Slovenčina | 🇵🇱 Polski | 🇷🇺 Русский | 🇧🇷 Português (BR) | 🇸🇦 العربية

🇬🇧 English

📋 Overview

vue-advanced-odontogram is the Vue 3 edition of React Odontogram Modul — the same interactive dental chart editor, reimplemented as a standalone Vue library you can install from npm.

| | | |---|---| | Upstream (React) | ZoliQua/React-Odontogram-Modul — original React 18 editor | | This package (Vue) | vue-advanced-odontogram — Vue 3.5 + TypeScript, SFC shell (OdontogramShell) | | Shared behavior | JSON/FHIR payloads, SVG tooth templates, clinical state model, and chart rendering stay compatible with the React editor (payload version 2.10) |

Install it in any Vue 3 app, import the bundled styles, and embed OdontogramShell like any other component. The imperative odontogram engine (tooth state, FHIR export, plugins) is unchanged from the React lineage; only the UI shell was rewritten for Vue.

It renders layered SVG tooth templates to represent restorations, caries, endodontic status, mobility, and other clinical details, while providing multi-select, selection filters, and predefined status presets.


🔗 Live demo (React upstream): https://react-odontogram-modul.vercel.app/ — same editor UI and clinical feature set; this Vue package mirrors that behavior.


✨ Key Features

  • 🖱️ Fast selection and multi-select (CMD/CTRL + click)
  • 🦷 Tooth types: permanent, primary (milk), implant, subgingival, missing
  • 🦷 Tooth substrate (orthogonal to any restoration): natural, radix (root remnant), broken, prepared for crown
  • 👑 Restorations by type × material: crown / inlay / onlay / veneer / bridge in e.max, gold, gradia, zirconia, metal, metal-ceramic, telescope or temporary (onlay is occlusal-view only) — chosen from one combined low-click "Fix: Crown – …" picker; legacy metal crowns migrate to metal-ceramic (PFM); implants use the same type × material model, composed with an implant connector layer. The picker is scoped by tooth kind: an implant offers only crown/bridge (plus its five attachment options, below); a missing/gap tooth offers only a bridge pontic (plus removable-partial/-full); a radix substrate hides the restoration control entirely (no restoration can be authored on a root remnant)
  • 🦿 Removable/attachment prosthetics on the dedicated prosthesis axis ("Kivehető:" entries in the combined picker): implant healing abutment, locator, locator with overdenture, bar, bar with overdenture; tooth-supported removable partial or full denture
  • 🌉 Bridge teeth render both the crown cap and the saddle connector; a multi-tooth bridge-span overlay renders one continuous, arch-aware connector across consecutive bridge teeth (pontics + abutments) and the inter-tooth gaps between them (upper vs. lower arch use mirrored saddle geometry, keeping the connector aligned on both arches), included in PNG/JPG/SVG export; applying a bridge via a Statuses preset recomputes the overlay immediately
  • 🔍 Caries charting on 6 surfaces: mesial, distal, buccal, lingual, occlusal, subcrown
  • 🪥 Filling materials per surface: amalgam, composite, GIC, temporary
  • 🏥 One merged "Pulp / Endo status" selector (grouped: vital pulp vs. treated/endo): endodontic states (medicinal filling, root canal filling, incomplete root filling, glass fiber post, metal post) and AAE pulp diagnosis (pulpDx: normal / reversible / irreversible pulpitis / necrosis) are mutually exclusive — a root-treated tooth (endo set) cannot also carry a vital pulp diagnosis; on treatment, pulpDx is normalized to normal and the diseased-pulp glyph is suppressed. Reversible pulpitis renders a reduced pulp glyph. An optional 3-level pulp detail setting (pulpDetailLevel: simple / AAE / practical-Latin) surfaces 9 practical-Latin pulp subtypes (pulpa sana … gangraena pulpae) via pulpLatin; resection and parapulpal pin remain separate special indicators
  • 🦴 Apical diagnosis (apicalDx: symptomatic/asymptomatic apical periodontitis, acute/chronic apical abscess, condensing osteitis) drives the periapical glyph directly; a granuloma/cyst lesion-subtype qualifier is shown only under symptomatic/asymptomatic apical periodontitis (the redundant "abscess" subtype was dropped — it's already covered by the apical diagnosis)
  • 🩹 Merged "Root and periodontium" card (single collapsible section for root/periapical and periodontal findings)
  • ⚕️ Modifications: periapical inflammation (shown only on missing/extraction-socket teeth; hidden on present teeth, where apicalDx alone drives the periapical glyph, and on implants, where periImplant covers it), periodontal disease, mobility grades (M1/M2/M3, hidden on implants)
  • 🦷🔩 Peri-implant status (periImplant: none / mucositis / peri-implantitis-mild / -moderate / -severe) — 2018 World Workshop staging, shown as a dedicated selector on implants; mucositis reuses the periodontal gum glyph, peri-implantitis adds a graded peri-implant-bone-loss layer (opacity 0.4/0.7/1.0). Implants no longer render the periapical lesion glyph — their inflammation is expressed through this axis instead — and the periodontal-modifier checkboxes are hidden on implants (the ad-hoc "Peri-implantitis" checkbox relabel is retired)
  • 🏷️ Special indicators: crown needed, crown replacement needed, missing closed gap, extraction plan, fissure sealing, contact point loss
  • 👁️ Occlusal view, wisdom teeth, bone and pulp visibility toggles
  • 🔢 12 selection filters (all, present, permanent, milk, implants, missing, upper/lower, front/molars)
  • 📊 Predefined status presets (reset, primary dentition, mixed dentition, edentulous)
  • 📦 34 predefined restoration templates (bridges, removable dentures, bar dentures with implants)
  • 💾 Status export/import in JSON (version 2.10; imports still accept legacy 1.4, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, and 2.9 and migrate automatically, with plugin custom states and per-tooth notes)
  • 🔗 HL7 FHIR R4 export (collection Bundle of per-tooth Observations, ISO 3950 tooth coding for permanent dentition, local code system — SNOMED CT mapping planned)
  • ✚ Cross/plus surface selection UI (B/M/O/D/L) for caries and fillings
  • 🧱 Per-surface restoration materials (mixed fillings, e.g. buccal amalgam + distal composite)
  • 🖼️ PNG/JPG/SVG image export of the chart (downloadable; PNG/JPG rasterized from vector SVG)
  • 🦷 Caries/subcaries is a per-surface state machine: a caried surface with no filling renders as primary caries (ICDAS-tiered opacity); once a filling is present on that surface it renders as recurrent caries instead (the subcaries-{surface} layer, CARS-scored) — the two are never both active on the same surface
  • 🎯 Unified per-surface severity (cariesSeverity, 0–6, replacing the old separate ICDAS-depth + CARS fields): read as ICDAS depth on a primary surface, as a named CARS score (Sound … Extensive cavity) on a recurrent one, via a contextual popup that shows only the scale relevant to the surface's current state
  • 🌱 Root caries (rootCaries: none / active / arrested / active-cavitated), wiring the dedicated root-caries artwork layer at a severity-driven opacity (active 0.5 / arrested 0.7 / active-cavitated full)
  • 📡 Radiographic caries depth (radiographicDepth: none / E1 / E2 / D1 / D2 / D3 per surface), independent of the visual ICDAS/CARS severity scale, surfaced as a badge and round-tripped through its own FHIR Observation
  • 🎚️ Three caries granularity settings (secondaryCariesMode, rootCariesMode, radiographicDepthMode) plus a cariesDepthEnabled toggle, collapsing each scale to a simpler picker view without losing the stored value
  • 🩹 Fillings-panel subcaries summary line: lists any selected tooth with recurrent caries and its surfaces below the filling controls (e.g. "36 (O) has subcaries set on its filling.")
  • 🪛 Per-surface filling defects (fillingDefect: none / marginal / fracture / wear) on direct restorations, independent of recurrent caries — authored via a per-surface indicator on the Fillings card (mirroring the caries-depth indicator, its option list stacked vertically), rendered on the chart, and shown in the tooltip and the whole-mouth fillings summary with an explicit label (e.g. "36 (O) – Filling defect: O: marginal"), the same way recurrent caries is labeled on the Caries line; the Fillings card also shows a hint note for any selected tooth with a recorded filling defect (e.g. "36 has a filling defect recorded."), parallel to the existing subcaries hint note
  • 🦷💥 Tooth wear typed by clinical cause and location (wearEdge: none / attrition / erosion, incisal/occlusal; wearCervical: none / abrasion / abfraction / erosion, cervical) — replacing the two on/off bruxism-wear flags; authored via two dropdowns on the wear row, reuses the existing wear artwork, and shown in the tooltip and a new whole-mouth "Wear" summary section
  • 🎨 Tooth discoloration by cause (discoloration: none / tetracycline / fluorosis / nonvital / extrinsic / other) on permanent and milk teeth — tints the shown natural crown a representative colour when the tooth has no restoration and natural substrate; shown in the tooltip and a new whole-mouth "Discoloration" summary section; completes the surface & structural conditions set alongside filling defects and wear
  • ✏️ Anterior teeth (incisors/canines) label their occlusal surface "incisal" throughout the UI (picker, popup, summaries); the stored surface key stays occlusal
  • 🔤 Position-aware surface notation (Settings → Tooth details → "Surface notation", simple/full, default full): in full mode the caries/filling surface letter and label follow tooth anatomy — occlusal → I/incisal on anterior teeth, buccal → L/labial on anterior teeth, lingual → P/palatal on upper teeth and L/lingual on lower teeth (mesial/distal/subcrown are unaffected); simple mode always uses the generic B/M/O/D/L/SC set regardless of tooth position. Applies to the whole-mouth summary and to both the caries and filling-defect surface pickers (letter + caption); the stored surface key is unaffected
  • 🦷↕️ Per-tooth orthodontic charting (orthoAppliance: none / bracket / band; orthoDrift: none / mesial / distal; orthoVertical: none / extrusion / intrusion; orthoRotation: boolean) on a present natural tooth (permanent or milk) — reuses the dormant v2.5.0 ortho artwork (no new SVG); shown on the chart, in the tooltip, and a new whole-mouth "Orthodontics" summary section
  • 🪨 Calculus, and root resorption typed as internal or external-cervical (resorptionType)
  • 📏 Per-surface caries depth (superficial / dentin / deep), or optional ICDAS II scoring (0–6) via enableIcdas
  • 🩹 Crown marginal-leakage toggle, shown only for a crown or bridge restoration
  • 🧰 Unified topbar icon row with a tabbed Settings modal (General / Panels / Tooth details / Caries / Pulpa / Notes — numbering, notes, panel visibility, ICDAS, caries-depth toggle, root/radiographic caries granularity, pulp detail level, tooth wear/discoloration detail level, tooth information)
  • 🗂️ Settings → "Panels" tab: independently show/hide the Statuses and Orthodontics whole-mouth summary panels
  • 🩹 Secondary-caries (CARS) settings control merged into the Caries settings tab, positioned above Radiographic depth (the separate "Secondary caries" tab is retired)
  • 🎚️ Tooth details detail level (Settings → Tooth details): a simple/complex setting for tooth wear and for discoloration. Simple mode shows a yes/no toggle per finding (wear on → attrition/abrasion, discoloration on → other); complex mode (default) keeps the type/cause dropdowns, and the stored value is preserved when switching levels
  • 📋 Tooth information panel: live text summary of the whole chart (tooth counts, present/missing lists, caries incl. secondary, fillings, root canals, prosthetics, implants, periodontal status) — shown by default, toggleable in Settings
  • 🗂️ Consolidated Export dropdown (Status JSON / FHIR / PNG / JPG)
  • 📥 Import dropdown with FHIR import (round-trips exported Bundles)
  • ⏳ Progress overlay during image export
  • 🎓 12-step interactive intro tour
  • 🔢 Three numbering systems (FDI, Universal, Palmer)
  • 🌐 I18n (HU/EN/DE/ES/IT/SK/PL/RU/PT-BR/AR) with language switcher (500+ translation keys per language; Arabic enables RTL layout)
  • 🌗 Dark mode support with toggle button (standalone or controlled by parent app)
  • 🎨 Custom theme configuration (themeConfig prop) with CSS custom properties (--odon-*)
  • 📱 Mobile touch UX: tap-to-zoom popover, long-press context menu, pinch-to-zoom, WCAG 44px touch targets, arch toggle navigation
  • 🔌 Custom SVG plugin system: inject visual overlays, per-tooth custom state, JSON export/import support
  • ⚠️ State validation warnings for incompatible tooth state combinations
  • 🏷️ Automatic state tooltip on tooth tiles (shows all active states)
  • 🩺 Modernized per-tooth tooltip and whole-mouth summary panel: both surface the full set of clinical findings (pulp/apical diagnosis + lesion subtype, root resorption, peri-implant status, graded root caries, calculus, crown marginal leakage, fracture, contact loss, typed edge/cervical wear), with a dedicated "Diagnoses" section in the panel, a dedicated "Wear" section, and a coarse caries-severity qualifier (superficial/moderate/deep)
  • ♿ Keyboard accessibility (WCAG): ARIA listbox/option roles, Enter/Space selection, arrow key navigation, focus-visible outlines
  • 🔒 Read-only mode: disable all interactions for print/report/view use cases
  • ✨ Selection animations: pulsing dashed border and glowing drop-shadow on selected teeth (with prefers-reduced-motion support)
  • 📝 Per-tooth notes: double-click to add/edit notes, note icon next to tooth number, hover tooltip with note text, JSON export/import
  • 🧪 864 automated tests passing (1 additional test skipped) (Vitest) across 94 test files covering numbering, translations, presets, i18n, App component, theme, touch, plugins, accessibility, and clinical-axis/diagnosis parity
  • 📖 TypeDoc API documentation with JSDoc comments on all public exports (npm run docs)

📦 Modules

  • 🦷 Odontogram grid and tooth tile UI
  • 🎛️ Controls and status panel
  • 🎨 SVG layering engine and templates
  • 🔢 Tooth numbering and label mapping (FDI/Universal/Palmer)
  • 🌐 Localization (HU/EN/DE/ES/IT/SK/PL/RU/PT-BR)
  • 💾 Status export/import
  • 📋 Status extras: predefined restoration templates
  • 🎨 Theme configuration: customizable color palette via --odon-* CSS properties
  • 📱 Mobile touch interactions (tap-to-zoom, long-press, pinch-to-zoom, arch toggle)
  • 🔌 Custom SVG plugin system
  • ⚠️ State validation and tooltip system
  • ♿ Keyboard accessibility and ARIA support
  • 🔒 Read-only mode
  • ✨ Selection animations
  • 📝 Per-tooth notes system
  • 🧪 Automated test suite (Vitest + Testing Library)

🛠️ UI Controls

🔝 Topbar:

  • Language switcher (HU/EN/DE/ES/IT/SK/PL/RU/PT-BR dropdown)
  • Dark mode toggle button (sun/moon icon, switches between light and dark theme)
  • Numbering system switcher (FDI/Universal/Palmer dropdown)
  • Export Status / Import Status buttons

📊 Chart header:

  • Occlusal view toggle
  • Wisdom teeth visibility toggle
  • Bone visibility toggle
  • Pulp visibility toggle
  • Clear selection button

🔍 Selection filters:

  • Select All / All Present / Permanent / Milk / Implants / All Missing
  • Select Upper / Upper Front 6 / Upper Molars
  • Select Lower / Lower Front 6 / Lower Molars

📋 Status presets:

  • Reset All (reset mouth)
  • Primary Dentition
  • Mixed Dentition
  • Edentulous toggle

📦 Status extras dropdown:

  • Upper/Lower zircon bridges (12-22, 13-23, 16-26, full arch)
  • Upper/Lower metal bridges (12-22, 13-23, 16-26, full arch)
  • Upper/Lower partial removable dentures
  • Upper/Lower full removable dentures
  • Upper/Lower bar dentures with implants

🦷 Tooth editor panel (for the selected tooth/teeth, grouped into collapsible cards):

  • Base row: tooth selection (base type incl. broken-crown variants) and tooth substrate (natural/radix/broken/crownprep)
  • Restoration row: the combined "Fix: …" / "Kivehető: …" restoration dropdown (restorationType×restorationMaterial fixed options plus the prosthesis attachment/removable options, gated by tooth kind); crown marginal-leakage checkbox (crown/bridge only); broken-crown location checkboxes; crown needed / crown replacement needed toggles
  • Wear & discoloration row: incisal/occlusal wear type dropdown, cervical wear type dropdown, discoloration cause dropdown (each swaps to a simple yes/no toggle under Settings → Tooth details → simple mode)
  • Orthodontics card: appliance, mesial/distal drift, vertical movement (extrusion/intrusion), rotation toggle — shown on a present natural tooth
  • Caries card: caries-depth mode dropdown, subcrown caries checkbox, root-caries severity dropdown, and the B/M/O/D/L per-surface caries picker with a contextual ICDAS-depth/CARS popup and a radiographic-depth badge
  • Fillings card: filling-material dropdown, per-surface filling picker (with per-surface material), per-surface filling-defect indicator (marginal/fracture/wear), subcaries and filling-defect hint notes
  • Root and periodontium card: merged "Pulp / Endo status" selector, apical diagnosis selector, periapical lesion subtype selector (symptomatic/asymptomatic apical periodontitis only), root resorption type selector, mobility grade selector, peri-implant status selector (implants only)
  • Special indicators: extraction plan/wound, missing-closed, fissure sealing, contact-point loss, calculus, parapulpal pin, endo resection, bridge pillar

🦷 Tooth Types and States

Tooth selection (base type): | Value | Description | |---|---| | none | Missing tooth | | tooth-base | Permanent tooth | | milktooth | Primary (deciduous) tooth | | implant | Dental implant | | tooth-under-gum | Subgingival (unerupted) tooth |

Broken tooth variants: tooth-broken-inicisal, tooth-broken-distal-inicisal, tooth-broken-distal, tooth-broken-mesial-distal-inicisal, tooth-broken-mesial-distal, tooth-broken-mesial-inicisal, tooth-broken-mesial, no-tooth-after-extraction

Tooth substrate (permanent teeth): natural (default), radix (root remnant), broken, crownprep (prepared for crown)

Restoration type (permanent teeth): none, crown, inlay, onlay (occlusal view only), veneer, bridge

Restoration material (permanent teeth): none, emax, gold, gradia, zircon, metal, metal-ceramic (legacy metal crowns migrate here), telescope, temporary

Restoration options are gated by tooth kind (restorationOptions() in src/registry/restorations.ts): an implant offers only crown/bridge restoration types (composed with an implant connector layer) plus the five prosthesis attachment entries below; a missing/gap tooth offers only a bridge pontic plus the two removable-denture prosthesis entries; a radix substrate hides the restoration control entirely. The legacy flat crownMaterial/bridgeUnit fields (pre-v1.14 implant/bridge attachment values) are retired from the live model — only accepted as a read-only migration path for old payloads.

Prosthesis (prosthesis; orthogonal removable/attachment axis, surfaced as "Kivehető:" entries in the combined restoration dropdown): none, healing-abutment, locator, locator-denture, bar, bar-denture (implant attachments, with or without an overdenture), removable-partial, removable-full (tooth-supported dentures on a missing/gap tooth). A tooth has either a fixed restoration or a prosthesis, never both — setting one clears the other.

Crown marginal leakage (crownLeakage; boolean): shown only when restorationType is crown or bridge; activates the crown-leakage artwork layer.

Endodontic options (permanent teeth): none, endo-medical-filling, endo-filling, endo-filling-incomplete, endo-glass-pin, endo-metal-pin

Endodontic options (milk teeth): none, endo-medical-filling

endo and pulpDx are surfaced through one merged "Pulp / Endo status" <select> (grouped: vital pulp vs. treated/endo) and are mutually exclusive — choosing a treated (endo != none) option resets pulpDx to normal and choosing a pulp diagnosis resets endo to none.

Filling materials (permanent teeth): amalgam, composite, gic, temporary

Filling materials (milk teeth): composite, gic, temporary

Filling/caries surfaces: mesial, distal, buccal, lingual, occlusal, subcrown (caries only)

Modifications: inflammation (periapical), parodontal (periodontal), mobility (M1/M2/M3)

Periapical lesion type (periapicalType; qualifies the periapical glyph, shown only under symptomatic/asymptomatic apical periodontitis): none, granuloma, cyst — authoring options; the legacy abscess value is still accepted/stored but no longer offered in the picker, since it duplicates the apical diagnosis. On import it is dropped: folded into apicalDx when the tooth carries the inflammation modifier, otherwise cleared to none

Pulp diagnosis (AAE terminology; pulpDx): normal, reversible-pulpitis (renders a reduced pulp glyph), irreversible-pulpitis, necrosis — mutually exclusive with endo; normalized to normal on a root-treated tooth

Pulp diagnosis, practical Latin (pulpLatin; shown by the pulp picker only when pulpDetailLevel is latin): none, pulpa-sana, hyperaemia-pulpae, pulpitis-acuta-serosa, pulpitis-acuta-purulenta, pulpitis-chronica-clausa, pulpitis-chronica-ulcerosa, pulpitis-chronica-hyperplastica, necrosis-pulpae, gangraena-pulpae

Pulp detail level (pulpDetailLevel, global setting): simple, aae (default), latin — controls which pulp vocabulary the picker offers

Apical diagnosis (apicalDx; drives the periapical glyph): normal, symptomatic-apical-periodontitis, asymptomatic-apical-periodontitis, acute-apical-abscess, chronic-apical-abscess, condensing-osteitis

Root resorption type (resorptionType): none, internal, external-cervical

Peri-implant status (periImplant; implant-only, 2018 World Workshop staging): mucositis reuses the periodontal gum glyph; peri-implantitis-* adds the peri-implant-bone-loss layer at severity-scaled opacity (mild 0.4 / moderate 0.7 / severe 1.0). Implants no longer render the periapical lesion glyph (their inflammation is expressed via this axis instead), and the mods inflammation/parodontal checkboxes are hidden on implants: none, mucositis, peri-implantitis-mild, peri-implantitis-moderate, peri-implantitis-severe

Caries severity (cariesSeverity; unified per-surface field, 06): on a surface with no filling it is read as the ICDAS caries-depth scale (superficial / dentin / deep, or the raw ICDAS II codes 0–6 when enableIcdas is set) and renders the primary caries-{surface} layer; on a surface with a filling it is read as a named CARS score (0 sound … 6 extensive cavity) and renders the subcaries-{surface} (recurrent-caries) layer instead — a surface is never both primary and recurrent at once

Root caries (rootCaries; wires the caries-root artwork layer on a present tooth, opacity driven by severity — active 0.5 / arrested 0.7 / active-cavitated full): none, active, arrested, active-cavitated

Radiographic caries depth (radiographicDepth; per surface, independent of the visual ICDAS/CARS cariesSeverity scale): none, E1, E2, D1, D2, D3

Caries granularity settings (global): secondaryCariesMode (simple/standard/full, default standard), rootCariesMode (simple/severity, default simple), radiographicDepthMode (off/threeLevel/detailed, default off), cariesDepthEnabled (boolean, default true) — each collapses its scale to a simpler picker view without altering the stored value

Special indicators: crownNeeded, crownReplace, missingClosed, extractionPlan, extractionWound, bridgePillar, fissureSealing, contactMesial, contactDistal, endoResection, calculus, parapulpalPin

Tooth wear (wearEdge, wearCervical; per-location clinical type, gated on tooth-base + no restoration + natural substrate; render the existing tooth-bruxism-wear/tooth-bruxism-neck-wear layers): wearEdge: none, attrition, erosionwearCervical: none, abrasion, abfraction, erosion

Discoloration (discoloration; per-tooth cause, gated on a natural tooth-base or milk tooth + no restoration + natural substrate; tints the shown natural crown's fill — no new SVG): none, tetracycline, fluorosis, nonvital, extrinsic, other

Filling defect (fillingDefect; per surface, direct-restoration finding independent of recurrent caries — gated to surfaces present in fillingSurfaceMaterials; renders the defect-{surface} artwork layer): none, marginal, fracture, wear

Orthodontics (orthoAppliance, orthoDrift, orthoVertical, orthoRotation; per-tooth, gated on a present natural tooth — permanent or milk): orthoAppliance: none, bracket, bandorthoDrift: none, mesial, distalorthoVertical: none, extrusion (arrow-up glyph), intrusion (arrow-down glyph) — orthoRotation: boolean

Tooth detail / notation settings (global session settings, Settings → Tooth details): wearDetailLevel and discolorationDetailLevel (ToothDetailLevel: simple/complex, default complex — simple mode shows a yes/no toggle instead of the full type/cause dropdown, without mutating the stored value) and surfaceNotation (simple/full, default full — controls whether caries/filling surface letters/labels are position-aware; see "Position-aware surface notation" above)

⚙️ Settings

Opened from the topbar gear icon; a focus-trapped, ARIA dialog with a tabbed layout (Esc/backdrop-click to close, arrow keys to switch tabs). All settings are session-level UI state only, unless noted — none of them mutate per-tooth data or the export payload.

  • General: numbering system (FDI/Universal/Palmer), language, dark/light theme, tooth-information panel visibility
  • Panels: independently show/hide the whole-mouth Statuses card and the Orthodontics card (both default visible)
  • Tooth details: wear detail level and discoloration detail level (simple/complex, each default complex), surface notation (simple/full, default full)
  • Caries: ICDAS II scoring toggle (enableIcdas), caries-depth toggle (cariesDepthEnabled), root-caries granularity (rootCariesMode: simple/severity), secondary/CARS granularity (secondaryCariesMode: simple/standard/full), radiographic-depth granularity (radiographicDepthMode: off/threeLevel/detailed) — the former separate "Secondary caries" tab is merged into this one, with the CARS control positioned directly above radiographic depth
  • Pulpa: pulp detail level (pulpDetailLevel: simple/AAE/practical-Latin, default AAE) — controls which vocabulary the "Pulp / Endo status" picker offers; changing it live-refreshes the whole-mouth summary and every open tooltip
  • Notes: enable/disable per-tooth notes (enableNotes)

🖼️ SVG Template System

Tooth templates (in src/assets/teeth-svgs/): | Template | Teeth using it | |---|---| | 11.svg | 11, 12, 21, 22, 31, 32, 41, 42 (incisors) | | 13.svg | 13, 23, 33, 43 (canines) | | 14.svg / 14_occl.svg | 14, 15, 24, 25, 34, 35, 44, 45 (premolars) | | 16.svg / 16_occl.svg | 16, 17, 18, 26, 27, 28, 36, 37, 38, 46, 47, 48 (molars) |

Templates are rotated 180 degrees for the lower jaw and mirrored horizontally for the left side.

Icon SVGs (in src/assets/icon-svgs/): icon_8.svg (wisdom), icon_gum.svg (bone), icon_no_selection.svg (clear), icon_occl.svg (occlusal view), icon_pulp.svg (pulp)

🔢 Numbering Systems

FDI (ISO 3950): Adult teeth 11-18, 21-28, 31-38, 41-48. Primary teeth 51-55, 61-65, 71-75, 81-85.

Universal (USA): Adult teeth numbered 1-32. Primary teeth lettered A-T.

Palmer (Zsigmondy-Palmer): Quadrant + position format (e.g. UR-1, LL-5). Primary teeth use letters A-E per quadrant.

🚀 Usage

Install the Vue npm package (not the React upstream repo):

Install as an npm package

npm install vue-advanced-odontogram
# or
pnpm add vue-advanced-odontogram

Peer dependency: Vue 3.5+

<script setup lang="ts">
import OdontogramShell from "vue-advanced-odontogram";
import "vue-advanced-odontogram/style.css";

function onLanguageChange(lang: string) {
  console.log(lang);
}
</script>

<template>
  <OdontogramShell
    language="en"
    @language-change="onLanguageChange"
    numbering-system="FDI"
    @numbering-change="(system) => console.log(system)"
    :dark-mode="false"
    @dark-mode-change="(dark) => console.log(dark)"
  />
</template>

See NPM_PUBLISH.md for maintainer setup (npm token, GitHub Actions, release tagging).

Local development

npm install
npm run dev

Build:

npm run build

Preview:

npm run preview

🔗 Vue integration

After installing the package (see Usage above), embed OdontogramShell in any Vue 3 app. The examples below assume:

import OdontogramShell from "vue-advanced-odontogram";
import "vue-advanced-odontogram/style.css";

Dark mode integration:

  • Standalone mode: Omit dark-mode prop — the component manages its own theme state via the topbar toggle button and adds/removes the .dark class on <html>.
  • Controlled mode: Pass dark-mode and listen for @dark-mode-change — the parent app controls the theme. The toggle button still appears but emits darkModeChange instead of managing internal state. The parent is responsible for adding/removing the .dark class on <html>.

Custom theme:

<OdontogramShell
  :theme-config="{
    colors: {
      accent: '#e74c3c',
      background: '#fafafa',
      text: '#222222',
    },
  }"
/>

Plugin integration:

<script setup lang="ts">
import OdontogramShell, { type OdontogramPlugin, setPluginState } from "vue-advanced-odontogram";

const myPlugin: OdontogramPlugin = {
  id: "implant-brand",
  label: { en: "Implant Brand", hu: "Implantátum márka" },
  layer: "overlay",
  renderSvg: (toothNo, _quadrant, state) => {
    if (!state) return null;
    return `<text x="16" y="60" font-size="6" fill="#3b7bff">${state}</text>`;
  },
};
// Set plugin state for a tooth:
setPluginState(11, "implant-brand", "Straumann");
</script>

<template>
  <OdontogramShell :plugins="[myPlugin]" />
</template>

🧪 Testing

npm run test           # Run all 864 tests (1 additional test skipped)
npm run test:watch     # Watch mode
npm run test:coverage  # Coverage report

📖 API Documentation

npm run docs           # Generate TypeDoc docs in docs/

📡 Public API

Component props (camelCase in <script setup>; kebab-case in templates):

| Prop | Type | Default | Description | |---|---|---|---| | language | Language | 'hu' | UI language (hu/en/de/es/it/sk/pl/ru/pt-br/ar) | | numberingSystem | NumberingSystem | 'FDI' | Numbering system (FDI/Universal/Palmer) | | darkMode | boolean | undefined | Dark mode state. Omit for standalone mode. | | themeConfig | OdontogramThemeConfig | undefined | Custom color overrides via CSS custom properties (--odon-*). | | plugins | OdontogramPlugin[] | undefined | Custom SVG plugins for visual overlays and per-tooth custom state. | | readOnly | boolean | false | Disable all interactions (click, touch, keyboard). Useful for print/report views. | | enableNotes | boolean | false | Enable per-tooth notes. Double-click a tooth to add/edit notes. |

Emits:

| Event | Payload | Description | |---|---|---| | languageChange | Language | Emitted when the user changes UI language | | numberingChange | NumberingSystem | Emitted when the numbering system changes | | darkModeChange | boolean | Emitted when dark mode is toggled (controlled mode) |

Import named engine APIs from vue-advanced-odontogram (same module as the default OdontogramShell export).

Exported functions for external control:

| Function | Description | |---|---| | initOdontogram() | Initialize the engine and render all teeth | | destroyOdontogram() | Clean up the engine and remove event listeners | | setNumberingSystem(system) | Switch between FDI, Universal, Palmer | | clearSelection() | Deselect all teeth | | setOcclusalVisible(on) | Toggle occlusal view on/off | | setWisdomVisible(on) | Show/hide wisdom teeth | | setShowBase(on) | Show/hide bone layer | | setHealthyPulpVisible(on) | Show/hide healthy pulp | | registerPlugins(plugins) | Register custom SVG plugins | | setPluginState(toothNo, pluginId, value) | Set a plugin's custom state for a tooth | | getPluginState(toothNo, pluginId) | Get a plugin's custom state for a tooth | | getToothStateSummary(toothNo) | Get localized summary of all active states | | getOdontogramSummary() | Get a structured, localized text summary of the whole chart (counts, sections) | | onStateChange(callback) | Subscribe to state changes; returns an unsubscribe function | | setReadOnly(value) | Enable/disable read-only mode | | getReadOnly() | Get current read-only state | | setNotesEnabled(value) | Enable/disable per-tooth notes | | getNotesEnabled() | Get current notes-enabled state | | setPulpDetailLevel(level) | Set the pulp picker's vocabulary — "simple", "aae", or "latin" | | getPulpDetailLevel() | Get the current pulp detail level | | exportFhir(options?) | Export the chart as an HL7 FHIR R4 collection Bundle (JSON download). Optional { subject } reference; otherwise a placeholder Patient is embedded | | exportImage(format) | Download the chart as an image — "png" or "jpg" | | exportSvg() | Download the chart as a scalable SVG (vector) | | importFhirBundle(input) | Import a FHIR R4 Bundle (object or JSON string) produced by this module | | setImportFormat(format) | Set the next file import's parser — "status" or "fhir" | | startIntroTour() | Launch the 12-step interactive intro tour |

💾 Status Export/Import Format

The export creates a JSON file (version 2.10; imports also accept legacy 1.4, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, and 2.9 and migrate automatically) containing:

Global fields:

  • wisdomVisible - wisdom teeth visible
  • showBase - bone layer visible
  • occlusalVisible - occlusal view active
  • showHealthyPulp - healthy pulp visible
  • edentulous - edentulous mode active

Per-tooth fields (32 teeth):

  • toothSelection - base tooth type
  • toothSubstrate - tooth substrate (natural/radix/broken/crownprep), orthogonal to any restoration
  • restorationType - restoration type (none/crown/inlay/onlay/veneer/bridge)
  • restorationMaterial - restoration material (emax/gold/gradia/zircon/metal/metal-ceramic/telescope/temporary), paired with restorationType
  • prosthesis - removable/attachment axis (none/healing-abutment/locator/locator-denture/bar/bar-denture/removable-partial/removable-full), mutually exclusive with a fixed restorationType of crown/bridge
  • crownLeakage - crown marginal-leakage flag, meaningful only when restorationType is crown or bridge
  • endo - endodontic state; mutually exclusive with pulpDx (surfaced together via one merged "Pulp / Endo status" picker — treating a tooth normalizes pulpDx to normal)
  • mods - modifications array (inflammation, parodontal); inflammation is retired from the UI on present teeth (apicalDx drives the glyph there) but still applies to missing/extraction-socket teeth
  • caries - active caries surfaces
  • cariesActiveDepth - the ICDAS depth value staged by the caries-depth picker when a new surface is applied (not a per-surface stored value; see cariesSeverity for the stored per-surface field)
  • rootCaries - root caries severity (none/active/arrested/active-cavitated)
  • cariesSeverity - unified per-surface severity (0-6): ICDAS depth on a primary (unfilled) surface, CARS score on a recurrent (filled) surface
  • radiographicDepth - per-surface radiographic caries depth (none/E1/E2/D1/D2/D3), independent of the visual ICDAS/CARS scale
  • fillingMaterial - filling material
  • fillingSurfaces - filled surfaces
  • fillingSurfaceMaterials - per-surface filling material (mixed fillings, e.g. buccal amalgam + distal composite)
  • fillingDefect - per-surface filling defect (none/marginal/fracture/wear), filled-surface-gated, independent of recurrent caries
  • pulpDx - AAE pulp diagnosis (normal/reversible-pulpitis/irreversible-pulpitis/necrosis); reversible-pulpitis renders a reduced glyph
  • pulpLatin - practical-Latin pulp subtype (shown by the pulp picker only when pulpDetailLevel is latin)
  • apicalDx - apical diagnosis driving the periapical glyph
  • periapicalType - periapical lesion subtype (none/granuloma/cyst), shown only under symptomatic/asymptomatic apical periodontitis; legacy abscess still accepted on import
  • resorptionType - root resorption type (none/internal/external-cervical)
  • periImplant - implant-only peri-implant status (none/mucositis/peri-implantitis-mild/-moderate/-severe), 2018 World Workshop staging
  • endoResection - apicoectomy flag
  • fissureSealing - fissure sealant flag
  • calculus - calculus flag
  • contactMesial - mesial contact point loss
  • contactDistal - distal contact point loss
  • wearEdge - incisal/occlusal wear type (none/attrition/erosion)
  • wearCervical - cervical wear type (none/abrasion/abfraction/erosion)
  • discoloration - per-tooth discoloration cause (none/tetracycline/fluorosis/nonvital/extrinsic/other), tints the natural crown fill on a natural tooth-base/milk tooth with no restoration
  • orthoAppliance - orthodontic appliance (none/bracket/band)
  • orthoDrift - orthodontic drift (none/mesial/distal)
  • orthoVertical - orthodontic vertical movement (none/extrusion/intrusion)
  • orthoRotation - orthodontic rotation flag
  • brokenMesial, brokenIncisal, brokenDistal - fracture locations
  • extractionWound - post-extraction wound
  • extractionPlan - planned extraction
  • parapulpalPin - parapulpal pin flag
  • bridgePillar - bridge abutment tooth
  • mobility - mobility grade (none/m1/m2/m3)
  • crownNeeded - crown needed indicator
  • crownReplace - crown replacement needed indicator
  • missingClosed - gap closed after extraction
  • customStates - plugin custom states (object, keyed by plugin ID)
  • note - per-tooth text note (string, optional — only present when non-empty)

📁 Folder Structure

  • src/index.ts - npm package entry (vue-advanced-odontogram; default export + engine API re-exports)
  • src/App.vue - shell UI, topbar controls, language/numbering/dark mode/theme/plugin switcher
  • src/SettingsModal.vue - tabbed settings dialog
  • src/main.ts - dev SPA bootstrap
  • src/odontogram.ts - SVG layering engine, tooth state management, touch interactions, plugin overlays, UI wiring
  • src/plugin.ts - OdontogramPlugin type, PluginLayer, getQuadrant(), LAYER_Z z-index priorities
  • src/theme.ts - OdontogramThemeConfig type and applyThemeConfig() utility
  • src/status_extras.ts - 34 predefined restoration templates (bridges, dentures, bar constructions)
  • src/i18n/ - translations (HU/EN/DE/ES/IT/SK/PL/RU/PT-BR) and i18n hook
  • src/utils/numbering.ts - FDI, Universal, Palmer numbering conversion
  • src/registry/ - declarative clinical-axis registry: FHIR field mappings, SVG-clear-set/boolean-flag activation, restoration type×material matrix, UI option lists (single source of truth generating export/import, FHIR, and picker UI)
  • src/fhir/ - HL7 FHIR R4 export/import: toFhir.ts/fromFhir.ts, code systems, field mappings, primitives
  • src/bridgeOverlay.ts - multi-tooth bridge-span connector overlay (arch-aware saddle geometry)
  • src/SettingsModal.vue - tabbed Settings dialog (General/Panels/Tooth details/Caries/Pulpa/Notes)
  • src/__tests__/ + src/registry/__tests__/ - Vitest test suite (864 tests passing, 1 skipped, across 94 files)
  • src/assets/teeth-svgs/ - SVG tooth templates (6 files: incisors, canines, premolars, molars + occlusal views)
  • src/assets/icon-svgs/ - toolbar icon SVGs (5 files)

⚙️ Tech Stack

  • Vue 3 + Vite + TypeScript
  • Tailwind CSS for UI styling
  • SVG layering via DOM manipulation (non-Vue reactivity for performance)
  • Lightweight custom i18n system
  • Vitest + @vue/test-utils for automated tests
  • TypeDoc for API documentation
  • Vite path alias: @ mapped to ./src

📝 Notes

  • This is the Vue npm port of React Odontogram Modul. For the original React package and releases, see the upstream repository.
  • SVG assets ship inside the npm bundle — host apps do not need to serve src/assets/ separately when using the published package.
  • The odontogram engine uses its own internal state (not Vue reactivity) for performance and simplicity.
  • Milk teeth have a reduced set of available materials (no amalgam fillings, no pin-based endo).
  • Implant teeth have a different set of crown/abutment options than natural teeth.

📖 How to cite

If you use this module in your work, please cite it.

This version (v2.1.0):

Dul, Z. (2026). vue-advanced-odontogram (Vue port of React Odontogram Modul, v2.1.0). Zenodo. https://doi.org/10.5281/zenodo.21156787

All versions (concept DOI): https://doi.org/10.5281/zenodo.21156787

Machine-readable citation metadata is in CITATION.cff.

🇪🇸 Español

📋 Descripción general

vue-advanced-odontogram es la edición Vue 3 de React Odontogram Modul: el mismo editor interactivo de odontograma, reimplementado como biblioteca Vue independiente instalable desde npm.

| | | |---|---| | Upstream (React) | ZoliQua/React-Odontogram-Modul — editor original en React 18 | | Este paquete (Vue) | vue-advanced-odontogram — Vue 3.5 + TypeScript, shell SFC (OdontogramShell) | | Comportamiento compartido | Payloads JSON/FHIR, plantillas SVG, modelo de estado clínico y renderizado del odontograma compatibles con el editor React (payload versión 2.10) |

Instálelo en cualquier app Vue 3, importe los estilos empaquetados e integre OdontogramShell como cualquier otro componente. El motor imperativo del odontograma (estado dental, exportación FHIR, plugins) se mantiene de la línea React; solo la shell de UI se reescribió para Vue.

Renderiza plantillas SVG de dientes en capas para representar restauraciones, caries, estado endodóntico, movilidad y otros detalles clínicos, con selección múltiple, filtros y estados predefinidos.


🔗 Demo en vivo (upstream React): https://react-odontogram-modul.vercel.app/ — misma UI y funcionalidad clínica; este paquete Vue replica ese comportamiento.


✨ Características principales

  • 🖱️ Selección rápida y selección múltiple (CMD/CTRL + clic)
  • 🦷 Tipos de dientes: permanente, primario (de leche), implante, subgingival, ausente
  • 🦷 Sustrato dental (ortogonal a cualquier restauración): natural, radix (resto radicular), fracturado, preparado para corona
  • 👑 Restauraciones por tipo × material: corona / incrustación (inlay) / incrustación oclusal (onlay) / carilla / puente en e.max, oro, gradia, circonio, metal, metal-cerámica, telescópica o temporal (el onlay es solo de vista oclusal) — se eligen desde un único selector combinado "Fix: Corona – …" de pocos clics; las coronas metal heredadas migran a metal-ceramic (metal-cerámica); los implantes usan el mismo modelo tipo × material, compuesto con una capa de conector de implante. El selector se acota según el tipo de diente: un implante solo ofrece corona/puente (más sus cinco opciones de anclaje, ver abajo); un diente ausente/hueco solo ofrece póntico de puente (más removible parcial/completa); un sustrato radix oculta por completo el control de restauración (no se puede registrar restauración sobre un resto radicular)
  • 🦿 Prótesis removibles/de anclaje en el eje dedicado prosthesis (entradas "Kivehető:" en el selector combinado): pilar de cicatrización del implante, localizador, localizador con sobredentadura, barra, barra con sobredentadura; prótesis parcial o completa removible soportada por dientes
  • 🌉 Los dientes de puente renderizan tanto la corona como el conector de silla de montar; una superposición de tramo de puente multidiente renderiza un conector continuo y adaptado a la arcada a través de los dientes de puente consecutivos (pónticos + pilares) y los espacios entre ellos (la arcada superior e inferior usan geometría de silla espejada, manteniendo el conector alineado en ambas arcadas), incluido en la exportación PNG/JPG/SVG; añadir un puente mediante un estado predefinido recalcula la superposición de inmediato
  • 🔍 Registro de caries en 6 superficies: mesial, distal, bucal, lingual, oclusal, subcoronal
  • 🪥 Materiales de obturación por superficie: amalgama, composite, ionómero de vidrio, temporal
  • 🏥 Un único selector combinado "Estado pulpar / endo" (agrupado: pulpa vital vs. tratada/endo): los estados endodónticos (obturación medicinal, tratamiento de conductos, obturación incompleta, poste de fibra de vidrio, poste metálico) y el diagnóstico pulpar AAE (pulpDx: normal / pulpitis reversible / irreversible / necrosis) son mutuamente excluyentes — un diente con tratamiento de conducto (endo distinto de none) no puede tener a la vez un diagnóstico pulpar vital; al tratarlo, pulpDx se normaliza a normal y se suprime el glifo de pulpa enferma. La pulpitis reversible se renderiza con un glifo reducido. Un ajuste opcional de 3 niveles de detalle pulpar (pulpDetailLevel: simple / AAE / latín práctico) muestra 9 subtipos en latín práctico (pulpa sana … gangraena pulpae) mediante pulpLatin; resección y pin parapulpar siguen siendo indicadores especiales aparte
  • 🦴 Diagnóstico apical (apicalDx: periodontitis apical sintomática/asintomática, absceso apical agudo/crónico, osteítis condensante) determina directamente el glifo periapical; el subtipo de lesión granuloma/quiste solo se muestra bajo periodontitis apical sintomática/asintomática (se eliminó el subtipo redundante "absceso", ya cubierto por el diagnóstico apical)
  • 🩹 Tarjeta combinada "Raíz y periodonto" (sección colapsable única para hallazgos radiculares/periapicales y periodontales)
  • ⚕️ Modificaciones: inflamación periapical (visible solo en dientes ausentes/alvéolo de extracción; oculta en dientes presentes, donde el glifo periapical lo determina únicamente apicalDx, y en implantes, donde lo cubre periImplant), enfermedad periodontal, grados de movilidad (M1/M2/M3, ocultos en implantes)
  • 🦷🔩 Estado periimplantario (periImplant: none / mucositis / peri-implantitis-mild / -moderate / -severe) — clasificación del World Workshop 2018, mostrada como un selector dedicado en los implantes; la mucositis reutiliza el glifo gingival periodontal, y la periimplantitis añade una capa graduada peri-implant-bone-loss (opacidad 0.4/0.7/1.0). Los implantes ya no renderizan el glifo de lesión periapical — su inflamación se expresa mediante este eje — y las casillas de modificadores periodontales quedan ocultas en los implantes (se retira el renombrado ad-hoc "Peri-implantitis" de la casilla)
  • 🏷️ Indicadores especiales: corona necesaria, reemplazo de corona necesario, espacio cerrado, plan de extracción, sellado de fisuras, pérdida de punto de contacto
  • 👁️ Vista oclusal, muelas del juicio, visibilidad de hueso y pulpa
  • 🔢 12 filtros de selección (todos, presentes, permanentes, de leche, implantes, ausentes, superior/inferior, frontales/molares)
  • 📊 Estados predefinidos (restablecer, dentición primaria, dentición mixta, edéntulo)
  • 📦 34 plantillas de restauración predefinidas (puentes, prótesis removibles, prótesis con barra e implantes)
  • 💾 Exportación/importación de estado en JSON (versión 2.10; las importaciones siguen aceptando las versiones 1.4, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8 y 2.9 y se migran automáticamente, con estados personalizados de plugins y notas por diente)
  • 🔗 Exportación HL7 FHIR R4 (Bundle de colección con Observations por diente, codificación dental ISO 3950 para dentición permanente, sistema de códigos local — mapeo SNOMED CT planificado)
  • ✚ Selección de superficies en cruz (B/M/O/D/L) para caries y obturaciones
  • 🧱 Materiales de obturación por superficie (obturaciones mixtas, p. ej. bucal amalgama + distal composite)
  • 🖼️ Exportación de imagen PNG/JPG/SVG del odontograma (descargable; PNG/JPG rasterizado desde SVG vectorial)
  • 🦷 Caries/subcaries como máquina de estados por superficie: una superficie cariada sin obturación se renderiza como caries primaria (opacidad por niveles ICDAS); en cuanto esa superficie tiene una obturación, se renderiza como caries recurrente (capa subcaries-{surface}, puntuada con CARS) — ambas nunca están activas a la vez en la misma superficie
  • 🎯 Severidad unificada por superficie (cariesSeverity, 0–6, sustituye los antiguos campos separados de profundidad ICDAS + CARS): se lee como profundidad ICDAS en una superficie primaria y como puntuación CARS con nombre (Sana … Cavidad extensa) en una recurrente, mediante un popup contextual que muestra solo la escala relevante para el estado actual de la superficie
  • 🌱 Caries radicular (rootCaries: none / active / arrested / active-cavitated), que activa la capa de ilustración dedicada de caries radicular con una opacidad según la severidad (active 0.5 / arrested 0.7 / active-cavitated completa)
  • 📡 Profundidad radiográfica de caries (radiographicDepth: none / E1 / E2 / D1 / D2 / D3 por superficie), independiente de la escala visual ICDAS/CARS, mostrada como una insignia y recuperable mediante su propia Observation FHIR
  • 🎚️ Tres ajustes de granularidad de caries (secondaryCariesMode, rootCariesMode, radiographicDepthMode) más un interruptor cariesDepthEnabled, que reducen cada escala a una vista de selector más simple sin perder el valor almacenado
  • 🩹 Línea de resumen de subcaries en el panel de obturaciones: lista, debajo de los controles de obturación, cualquier diente seleccionado con caries recurrente y sus superficies (p. ej. "36 (O) tiene subcaries junto a su obturación.")
  • 🪛 Defectos de obturación por superficie (fillingDefect: none / marginal / fracture / wear) en restauraciones directas, independientes de la caries recurrente — se registran mediante un indicador por superficie en la tarjeta de Obturaciones (espejo del indicador de profundidad de caries, con su lista de opciones apilada verticalmente), se renderizan en el odontograma y se muestran en el tooltip y en el resumen de obturaciones de toda la boca con una etiqueta explícita (p. ej. "36 (O) – Defecto de obturación: O: marginal"), igual que la caries recurrente se etiqueta en la línea de Caries; la tarjeta de Obturaciones también muestra una nota para cualquier diente seleccionado con un defecto de obturación registrado (p. ej. "En 36 hay un defecto de obturación registrado."), en paralelo a la nota de subcaries ya existente
  • 🦷💥 Desgaste dental tipificado por causa clínica y localización (wearEdge: none / attrition / erosion, incisal/oclusal; wearCervical: none / abrasion / abfraction / erosion, cervical) — sustituye los dos indicadores on/off de desgaste por bruxismo; se registra mediante dos menús desplegables en la fila de desgaste, reutiliza el arte existente y se muestra en el tooltip y en una nueva sección de resumen "Desgaste" de toda la boca
  • 🎨 Decoloración dental por causa (discoloration: none / tetracycline / fluorosis / nonvital / extrinsic / other) en dientes permanentes y temporales — tiñe la corona natural mostrada con un color representativo cuando el diente no tiene restauración y su sustrato es natural; se muestra en el tooltip y en una nueva sección de resumen "Decoloración" de toda la boca; completa el conjunto de condiciones de superficie y estructurales junto con los defectos de obturación y el desgaste
  • ✏️ Los dientes anteriores (incisivos/caninos) rotulan su superficie oclusal como "incisal" en toda la interfaz (selector, popup, resúmenes); la clave de superficie almacenada sigue siendo occlusal
  • 🔤 Notación de superficie según la posición del diente (Ajustes → Detalles del diente → "Notación de superficie", simple/completa, por defecto completa): en modo completo, la letra y la etiqueta de superficie de caries/obturación siguen la anatomía dental — oclusal → I/incisal en dientes anteriores, bucal → L/labial en dientes anteriores, lingual → P/palatino en dientes superiores y L/lingual en dientes inferiores (mesial/distal/subcoronal no cambian); el modo simple usa siempre el conjunto genérico B/M/O/D/L/SC, sin importar la posición del diente. Se aplica al resumen de toda la boca y a ambos selectores de superficie (caries y defecto de obturación), tanto la letra como el texto; la clave de superficie almacenada no se ve afectada
  • 🦷↕️ Registro ortodóntico por diente (orthoAppliance: none / bracket / band; orthoDrift: none / mesial / distal; orthoVertical: none / extrusion / intrusion; orthoRotation: booleano) en un diente natural presente (permanente o temporal) — reutiliza el arte ortodóntico inactivo de la v2.5.0 (sin SVG nuevo); se muestra en el gráfico, en el tooltip y en una nueva sección de resumen "Ortodoncia" de toda la boca
  • 🪨 Cálculo, y reabsorción radicular tipificada como interna o cervical externa (resorptionType)
  • 📏 Profundidad de caries por superficie (superficial / dentina / profunda), o puntuación ICDAS II opcional (0–6) con enableIcdas
  • 🩹 Indicador de filtración marginal de corona, visible solo con una restauración de corona o puente
  • 🧰 Barra superior unificada de iconos con un modal de Ajustes por pestañas (General / Paneles / Detalles del diente / Caries / Pulpa / Notas — numeración, notas, visibilidad de paneles, ICDAS, interruptor de profundidad de caries, granularidad de caries radicular/radiográfica, nivel de detalle pulpar, nivel de detalle de desgaste/decoloración dental, información dental)
  • 🗂️ Ajustes → pestaña "Paneles": muestra/oculta de forma independiente los paneles de resumen de Estados y de Ortodoncia
  • 🩹 El control de caries secundaria (CARS) se fusionó en la pestaña de Ajustes de Caries, colocado encima de Profundidad radiográfica (se retira la pestaña separada "Caries secundaria")
  • 🎚️ Nivel de detalle dental: un ajuste simple/complejo para el desgaste dental y la decoloración (Ajustes → Detalles del diente). El modo simple muestra un interruptor sí/no por hallazgo (desgaste activado → attrition/abrasion, decoloración activada → other); el modo complejo (por defecto) conserva los menús desplegables de tipo/causa, y el valor almacenado se conserva al cambiar de nivel
  • 📋 Panel de información dental: resumen de texto en vivo de todo el odontograma (recuentos de dientes, listas presentes/ausentes, caries incl. secundaria, obturaciones, endodoncias, prótesis, implantes, estado periodontal) — visible por defecto, conmutable en Ajustes
  • 🗂️ Menú de exportación unificado (Estado JSON / FHIR / PNG / JPG)
  • 📥 Menú de importación con importación FHIR (recupera Bundles exportados)
  • ⏳ Superposición de progreso durante la exportación de imagen
  • 🎓 Tour interactivo de introducción de 12 pasos
  • 🔢 Tres sistemas de numeración (FDI, Universal, Palmer)
  • 🌐 I18n (HU/EN/DE/ES/IT/SK/PL/RU/PT-BR/AR) con selector de idioma (500+ claves de traducción por idioma; el árabe activa diseño RTL)
  • 🌗 Modo oscuro con botón de alternancia (independiente o controlado por la aplicación principal)
  • 🎨 Configuración de tema personalizado (prop themeConfig) con CSS custom properties (--odon-*)
  • 📱 UX táctil móvil: popover de zoom al tocar, menú contextual con pulsación larga, zoom con pellizco, áreas táctiles WCAG 44px, navegación por arcada
  • 🔌 Sistema de plugins SVG personalizados: superposiciones visuales, estado personalizado por diente, soporte de exportación/importación JSON
  • ⚠️ Validación de estado con advertencias para combinaciones incompatibles
  • 🏷️ Tooltip automático de estado en las losetas dentales (muestra todos los estados activos)
  • 🩺 Tooltip por diente y panel de resumen de toda la boca modernizados: ambos muestran el conjunto completo de hallazgos clínicos (diagnóstico pulpar/apical + subtipo de lesión, reabsorción radicular, estado periimplantario, caries radicular graduada, cálculo, filtración marginal de corona, fractura, pérdida de contacto, desgaste tipificado incisal/oclusal y cervical), con una sección "Diagnósticos" dedicada, una sección "Desgaste" dedicada en el panel y un calificador de gravedad de caries de grano grueso (superficial/moderada/profunda)
  • ♿ Accesibilidad por teclado (WCAG): roles ARIA listbox/option, selección con Enter/Espacio, navegación con flechas, contornos focus-visible
  • 🔒 Modo solo lectura: desactivar todas las interacciones para vistas de impresión/informes
  • ✨ Animaciones de selección: borde punteado pulsante y sombra brillante en los dientes seleccionados
  • 📝 Notas por diente: doble clic para añadir/editar notas, icono de nota junto al número de diente, tooltip con texto de nota, exportación/importación JSON
  • 🧪 864 pruebas automatizadas superadas (1 prueba adicional omitida) (Vitest) en 94 archivos de test, para numeración, traducciones, plantillas, i18n, componente App, tema, táctil, plugins, accesibilidad y paridad de ejes clínicos/diagnósticos
  • 📖 Documentación API TypeDoc con comentarios JSDoc en todas las exportaciones públicas (npm run docs)

📦 Módulos

  • 🦷 Cuadrícula del odontograma e interfaz de mosaicos dentales
  • 🎛️ Panel de controles y estado
  • 🎨 Motor de capas SVG y plantillas
  • 🔢 Numeración dental y mapeo de etiquetas (FDI/Universal/Palmer)
  • 🌐 Localización (HU/EN/DE/ES/IT/SK/PL/RU/PT-BR)
  • 💾 Exportación/importación de estado
  • 📋 Extras de estado: plantillas de restauración predefinidas
  • 🎨 Configuración de tema: paleta de colores personalizable mediante propiedades CSS --odon-*
  • 📱 Interacciones táctiles móviles (zoom al tocar, pulsación larga, zoom con pellizco, alternador de arcada)
  • 🔌 Sistema de plugins SVG personalizados
  • ⚠️ Sistema de validación de estado y tooltips
  • ♿ Accesibilidad por teclado y soporte ARIA
  • 🔒 Modo solo lectura
  • ✨ Animaciones de selección
  • 📝 Notas por diente
  • 🧪 Suite de pruebas automatizadas (Vitest + Testing Library)

🛠️ Controles de interfaz

🔝 Barra superior:

  • Selector de idioma (HU/EN/DE/ES/IT/SK/PL/RU/PT-BR desplegable)
  • Botón de modo oscuro (icono sol/luna, alterna entre tema claro y oscuro)
  • Selector de sistema de numeración (FDI/Universal/Palmer desplegable)
  • Botones Exportar estado / Importar estado

📊 Encabezado del gráfico:

  • Alternador de vista oclusal
  • Alternador de visibilidad de muelas del juicio
  • Alternador de visibilidad de hueso
  • Alternador de visibilidad de pulpa
  • Botón borrar selección

🔍 Filtros de selección:

  • Seleccionar todos / Todos presentes / Permanentes / De leche / Implantes / Todos ausentes
  • Superior / Superior 6 frontales / Molares superiores
  • Inferior / Inferior 6 frontales / Molares inferiores

📋 Estados predefinidos:

  • Restablecer todo (restablecer boca)
  • Dentición primaria
  • Dentición mixta
  • Edéntulo alternador

📦 Desplegable de extras de estado:

  • Puentes de circonio superiores/inferiores (12-22, 13-23, 16-26, arco completo)
  • Puentes metálicos superiores/inferiores (12-22, 13-23, 16-26, arco completo)
  • Prótesis parciales removibles superiores/inferiores
  • Prótesis completas removibles superiores/inferiores
  • Prótesis con barra superiores/inferiores con implantes

🦷 Panel editor de diente (para el diente/dientes seleccionados, agrupado en tarjetas colapsables):

  • Fila base: selección de diente (tipo base incl. variantes de corona fracturada) y sustrato dental (natural/radix/fracturado/preparación de corona)
  • Fila de restauración: el menú desplegable combinado de restauración "Fix: …" / "Kivehető: …" (opciones fijas restorationType×restorationMaterial más las opciones de anclaje/removible de prosthesis, condicionadas por el tipo de diente); casilla de filtración marginal de corona (solo corona/puente); casillas de ubicación de corona fracturada; interruptores de corona necesaria / reemplazo de corona necesario
  • Fila de desgaste y decoloración: menú desplegable de tipo de desgaste incisal/oclusal, menú desplegable de tipo de desgaste cervical, menú desplegable de causa de decoloración (cada uno cambia a un interruptor simple sí/no en Ajustes → Detalles del diente → modo simple)
  • Tarjeta de ortodoncia: aparato, desplazamiento mesial/distal, movimiento vertical (extrusión/intrusión), interruptor de rotación — visible en un diente natural presente
  • Tarjeta de caries: menú desplegable de modo de profundidad de caries, casilla de caries subcoronal, menú desplegable de severidad de caries radicular, y el selector de caries por superficie B/M/O/D/L con un popup contextual de profundidad ICDAS/CARS y una insignia de profundidad radiográfica
  • Tarjeta de obturaciones: menú desplegable de material de obturación, selector de obturación por superficie (con material por superficie), indicador de defecto de obturación por superficie (marginal/fractura/desgaste), notas de subcaries y de defecto de obturación
  • Tarjeta de raíz y periodonto: selector combinado "Estado pulpar / endo", selector de diagnóstico apical, selector de subtipo de lesión periapical (solo periodontitis apical sintomática/asintomática), selector de tipo de reabsorción radicular, selector de grado de movilidad, selector de estado periimplantario (solo implantes)
  • Indicadores especiales: plan/herida de extracción, espacio cerrado, sellado de fisuras, pérdida de punto de contacto, cálculo, pin parapulpar, resección endodóntica, pilar de puente

🦷 Tipos de dientes y estados

Selección de diente (tipo base): | Valor | Descripción | |---|---| | none | Diente ausente | | tooth-base | Diente permanente | | milktooth | Diente primario (deciduo) | | implant | Implante dental | | tooth-under-gum | Diente subgingival (no erupcionado) |

Variantes de diente fracturado: tooth-broken-inicisal, tooth-broken-distal-inicisal, tooth-broken-distal, tooth-broken-mesial-distal-inicisal, tooth-broken-mesial-distal, tooth-broken-mesial-inicisal, tooth-broken-mesial, no-tooth-after-extraction

Sustrato dental (dientes permanentes): natural (predeterminado), radix (resto radicular), broken, crownprep (preparado para corona)

Tipo de restauración (dientes permanentes): none, crown, inlay, onlay (solo vista