Dental Input
A Vue component that allows you to add a tooth selector input to your web applications.
Repository - CI - NPM - Demo
Installing and basic usage
npm install dental-input
Then inside your Vue component, you can import the DentalInput
Vue component, as well as its default styles:
import { DentalInput } from "dental-input";
import "dental-input/style";
Then define a data ref to use for v-model
:
import { ref } from "vue";
const selectedTeeth = ref(new Set);
Then in the template you can add the component:
<DentalInput
v-model="selectedTeeth"
:radio-mode="false"
style="width: min(32em, 100%)"
/>
How it works
It uses an SVG with IDs for different teeth. The teeth are a list of teeth numbered using the UNS system (tooth1
to tooth32
).
<path
id="tooth14"
style="fill:#ffffff;stroke-width:1.25;fill-opacity:1.0"
d="m 2840.3215,1923.7079 c -7.6354,-1.2854 ... z"
/>
Modes of operation
You can make the component behave either as a single select (radio-button) input, or a multiselect (checkbox) input.
You can control this using the radio-mode
property.
Filters & notations
The component provides filters that you can use to convert the tooth IDs (tooth1
to tooth32
) to different notations:
method | name | example | details |
---|---|---|---|
uns | Universal Numbering System / American System | 1,2,3, ... 32 | wikipedia |
palmer | Palmer notation / Military System | 2┘,└4,2┐,┌4 | wikipedia |
fdi | FDI World Dental Federation / ISO 3950 notation | 18,19, ... 48 | wikipedia |
alphanum | Alphanumeric notation / Letters and numbers system | UR8,UR7, ... LR8 | wikipedia |
paleoanthropology | Paleoanthropology dental notation | RM³,LI¹,LI₂,RC₋ | wikipedia |
ada | American Dental Association notation | 2nd Molar,Central incisor | news-medical |
type | Tooth type | Molar, Incisor, Canine | |
region | Tooth region | Upper Right, Lower Left |
In addition to the above filters, a special combinedPalmer
filter can be used to show all selected teeth in a combined palmer notation:
import { filters } from "dental-input";
filters.combinedPalmer(selectedTeeth); // Example output: `12┘└42 12┐┌42`
Events
The component emits mouseover:item
and mouseout:item
events for each tooth.
You can, for example, keep record of the tooth under the mouse cursor by storing it in a data ref:
<script setup>
const highlightedTooth = ref(null);
</script>
<template>
<DentalInput
...
@mouseover:item="highlightedTooth = $event.target.id"
@mouseout:item="highlightedTooth = null"
/>
</template>
Customization
Styling
The basic style control that you can directly use is using the selection-color
and hover-color
properties to change the colors of teeth.
<DentalInput
...
selection-color="green"
hover-color="lightgreen"
/>
You can also use teeth IDs to make any changes as desired:
@for $i from 1 through 32 {
$tooth: "tooth#{$i}";
##{$tooth} {
/* normal state props */
&.selected {
/* selected state props */
}
/* Show hover effect on devices that support it (non touch screens) */
@media (hover: hover) {
&:hover {
/* hover state props */
}
}
}
}
The provided default styles are very minimal, but you can still choose not to add them and write your own.
Changing the SVG
To use your own SVG, you can add it inside the component:
<template>
<DentalInput
...
>
<svg .../>
</DentalInput>
</template>
To keep your template clean, you can also import the raw SVG and use it as the v-html
of a div
:
<script setup>
import svg from './my.svg?raw'; // `?raw` makes Vue load the raw content.
</script>
<template>
<DentalInput ...>
<div v-html="svg"></div>
</DentalInput>
</template>
The SVG must have the tooth ids defined from tooth1
to tooth32
.
Note that the default styles will disable pointer events for everything else.
Other uses
This component is built in a way that there's a base generic component that allows selecting marked items in an SVG, with a tooth specific layer on top.
The base component can be extended or used as is for any other kinds of SVGs.
To do this, you can import the SvgInput
component, and build on top of it:
<script setup>
import { SvgInput } from "dental-input";
import svg from './my.svg?raw';
// Set of IDs in the SVG of items that we want to turn into checkboxes / radio buttons
const itemsSet = new Set([
'mouth',
'nose',
'right eye',
'left eye',
]);
</script>
<template>
<SvgInput :items-list="itemsSet">
<div v-html="svg"></div>
</SvgInput>
</template>
<style lang="scss" scoped>
div:deep(svg) {
$itemsSet: ['mouth','nose','right eye','left eye'];
@each $item in $itemsSet {
##{$item} {
/* styles */
}
}
}
</style>
The source code for this component is available under Examples.
TODO
- [ ] Rename
items-list
toitems-set
- [ ] Write tests
- [ ] Add examples to the main repo
- [ ] Alternative horizontal UI
- [ ] Support for Deciduous teeth (baby teeth)
- [ ] Victor Haderup notation
License
Why this project exists
I was planning to port a wxPython accounting application that I created for my father's business to the web, and couldn't find any tooth input component on the interwebz.