isncsci-ui
Version:
Web components package for the ISNCSCI project.
1,327 lines (1,216 loc) • 238 kB
JavaScript
import { MotorLevels, SensoryLevels } from '../core/domain/index.js';
/**
* @tagname praxis-isncsci-icon
*/
class PraxisIsncsciIcon extends HTMLElement {
static get is() {
return 'praxis-isncsci-icon';
}
static get observedAttributes() {
return ['href', 'size'];
}
constructor() {
super();
this.template = (href, size) => `
<style>
:host {
align-items: center;
display: inline-flex;
justify-content: center;
}
</style>
<svg viewBox="0 0 ${size} ${size}" width="${size}" height="${size}">
<use xlink:href="${href}"></use>
</svg>
`;
this.attachShadow({ mode: 'open' });
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue) {
return;
}
if (/^(href|size)$/.test(name) && this.shadowRoot) {
this.shadowRoot.innerHTML = this.template(this.getAttribute('href') || '', this.getAttribute('size') || '24');
}
}
}
window.customElements.define(PraxisIsncsciIcon.is, PraxisIsncsciIcon);
/**
* @tagname praxis-isncsci-app-bar
*/
class PraxisIsncsciAppBar extends HTMLElement {
static get is() {
return 'praxis-isncsci-app-bar';
}
template() {
return `
<style>
:host {
align-items: center;
background: var(--background, rgba(255, 255, 255, 0.1));
box-shadow: var(--box-shadow, 0 0 0.125rem rgba(95, 24, 119, 0.24));
display: flex;
flex-direction: row;
gap: var(--gap, 1.25rem);
height: var(--height, 3.5rem);
padding: var(--padding, 0.75rem);
}
::slotted([slot="title"]) {
flex-grow: 1;
font-family: var(--title-font-family, sans-serif);
font-size: var(--title-font-size, 1rem);
font-weight: var(--title-font-weight, 400);
line-height: var(--title-line-height, 1.375rem);
}
</style>
<slot name="menu-button"></slot>
<slot name="title"></slot>
<slot name="actions"></slot>
`;
}
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template();
}
}
window.customElements.define(PraxisIsncsciAppBar.is, PraxisIsncsciAppBar);
/**
* @tagname praxis-isncsci-app-layout
*/
class PraxisIsncsciAppLayout extends HTMLElement {
static get is() {
return 'praxis-isncsci-app-layout';
}
static get observedAttributes() {
return ['readonly'];
}
template() {
return `
<style>
:host {
container-type: inline-size;
display: flex;
flex-direction: column;
position: relative;
}
:host([no-app-bar]) :has(> [name=app-bar]){
display: none;
}
:host([classification-style="visible"]) :has(> [name=classification]),
:host([classification-style="static"]) :has(> [name=classification]) {
display: flex;
flex-direction: column;
}
:host([classification-style="static"]) :has(> [name=classification]) {
position: static;
}
:host([classification-style="static"]) :has(> [name=input-layout]) {
height: auto;
}
:host([readonly]) :has(> [name=input-controls]) {
display: none;
}
:has(> [name=app-bar]) {
order: 1;
}
.scrollable-content {
flex-grow: 1;
order: 2;
overflow-y: auto;
padding: 16px 0;
}
:has(> [name=input-controls]) {
order: 3;
}
:has(> [name=classification]) {
bottom: 0;
display: none;
left: 0;
order: 4;
position: absolute;
right: 0;
top: 0;
z-index: var(--classification-z-index, 1);
}
::slotted([slot="classification"]) {
flex-grow: 1;
}
@container (min-width: 48rem) {
.scrollable-content {
order: 3;
}
:has(> [name=input-controls]) {
order: 2;
}
:host([classification-style="visible"]) .scrollable-content {
padding-bottom: var(--calc-classification-height, 400px);
}
:has(> [name=classification]) {
top: auto;
}
}
</style>
<div><slot name="app-bar"></slot></div>
<div class="scrollable-content">
<slot name="input-layout"></slot>
</div>
<div><slot name="input-controls"></slot></div>
<div><slot name="classification"></slot></div>
`;
}
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template();
}
updateReadonly(readonly) {
const inputLayout = this.querySelector('[slot="input-layout"]');
if (!inputLayout) {
return;
}
if (readonly) {
inputLayout.setAttributeNode(document.createAttribute('readonly'));
}
else {
inputLayout.removeAttribute('readonly');
}
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue) {
return;
}
if (name === 'readonly') {
this.updateReadonly(newValue !== null);
}
}
}
window.customElements.define(PraxisIsncsciAppLayout.is, PraxisIsncsciAppLayout);
/**
* @tagname praxis-isncsci-cell
*/
class PraxisIsncsciCell extends HTMLElement {
static get is() {
return 'praxis-isncsci-cell';
}
static get observedAttributes() {
return ['message'];
}
constructor() {
super();
this.template = `
<style>
:host {
align-items: center;
background: linear-gradient(to bottom right, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.8));
box-shadow: 0 1px 2px rgba(0, 0, 0, .1);
border: solid .5px #525252;
border-radius: 2px;
display: flex;
flex-direction: column;
gap: 1px;
justify-content: center;
min-height: 32px;
min-width: 32px;
transition: transform .3s ease-in-out, border-color .3s ease-in-out;
user-select: none;
}
:host([highlighted]) {
transform: scale(1.03);
border: solid 1.4px var(--highlighted-cell-border-color, orange);
}
:host([error]) {
background-color: var(--error, rgba(184, 69, 28, 0.1));
color: var(--on-error, #682710);
}
:host([error])::before {
content: '!';
font-size: 0.5rem;
font-weight: bold;
display: inline-block;
border: solid 0.03125rem var(--on-error, #682710);
width: 10px;
height: 10px;
line-height: 10px;
border-radius: 5px;
text-align: center;
}
</style>
<slot></slot>
`;
this.messageElement = null;
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template;
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue) {
return;
}
if (name === 'message' && this.messageElement) {
this.messageElement.textContent = newValue;
return;
}
}
}
window.customElements.define(PraxisIsncsciCell.is, PraxisIsncsciCell);
/**
* @tagname praxis-isncsci-classification
*/
class PraxisIsncsciClassification extends HTMLElement {
static get is() {
return 'praxis-isncsci-classification';
}
template() {
return `
<style>
:host {
backdrop-filter: var(--backdrop-filter, blur(1.5rem));
-webkit-backdrop-filter: var(--backdrop-filter, blur(1.5rem));
background-color: var(--background-color, rgba(255, 255, 255, 0.4));
box-shadow: var(--box-shadow, inset 0 0 1rem rgba(255, 255, 255, 0.4), 0 2px 4px rgba(95, 24, 119, 0.1), 0 1px 6px rgba(95, 24, 119, 0.05));
display: flex;
flex-direction: column;
}
[content] {
display: flex;
flex-wrap: wrap;
gap: var(--gap, 2.5rem);
justify-content: center;
padding: var(--padding, 1rem 1rem 2rem 1rem);
}
</style>
<slot name="header"></slot>
<div content>
<slot name="neurological-levels"></slot>
<slot name="nli"></slot>
<slot name="injury-complete"></slot>
<slot name="ais"></slot>
<slot name="zpp"></slot>
<slot name="sub-scores"></slot>
</div>
`;
}
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.updateView();
}
updateView() {
if (!this.shadowRoot) {
throw new Error(`${PraxisIsncsciClassification.is} :: updateView :: No shadow-root available`);
}
this.shadowRoot.innerHTML = `${this.template()}`;
}
}
window.customElements.define(PraxisIsncsciClassification.is, PraxisIsncsciClassification);
/**
* @tagname praxis-isncsci-classification-grid
*/
class PraxisIsncsciClassificationGrid extends HTMLElement {
static get is() {
return 'praxis-isncsci-classification-grid';
}
template() {
return `
<style>
:host {
align-items: center;
display: flex;
flex-direction: column;
gap: var(--gap, 0.5rem);
}
::slotted([slot="heading"]) {
color: var(--heading-foreground, #5E5E5E);
font-family: var(--heading-font-family, sans-serif);
font-size: var(--heading-font-size, 0.625rem);
font-weight: var(--heading-weight, 400);
line-height: var(--heading-line-height, 1.875rem);
text-align: var(--heading-text-align, center);
}
::slotted([slot="grid"]) {
align-items: end;
display: inline-grid;
gap: var(--grid-gap, 0.25rem);
grid-auto-rows: max-content;
grid-template-columns: var(--grid-template-columns, auto auto auto);
}]
</style>
<slot name="heading"></slot>
<slot name="grid"></slot>
`;
}
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template();
}
}
window.customElements.define(PraxisIsncsciClassificationGrid.is, PraxisIsncsciClassificationGrid);
/**
* @tagname praxis-isncsci-classification-total
*/
class PraxisIsncsciClassificationTotal extends HTMLElement {
static get is() {
return 'praxis-isncsci-classification-total';
}
template() {
return `
<style>
:host {
font-family: var(--font-family, sans-serif);
font-size: var(--font-size, 0.625rem);
font-weight: var(--font-weight, 400);
line-height: var(--line-height, 1.875rem);
text-align: var(--text-align, center);
border-bottom: solid 0.0625rem var(--border-color, rgba(0, 0, 0, 0.6));
display: inline-block;
padding: var(--padding-top, 0.25rem) var(--padding-right, 0.5rem) var(--padding-bottom, 0.25rem) var(--padding-left, 0.5rem);
}
</style>
<slot></slot>
`;
}
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template();
}
}
window.customElements.define(PraxisIsncsciClassificationTotal.is, PraxisIsncsciClassificationTotal);
/**
* @tagname praxis-isncsci-dialog-header
*/
class PraxisIsncsciDialogHeader extends HTMLElement {
static get is() {
return 'praxis-isncsci-dialog-header';
}
template() {
return `
<style>
:host {
align-items: center;
display: flex;
flex-direction: row;
height: var(--height, 3.5rem);
gap: var(--gap, 0.5rem);
padding: var(--padding-top, 0) var(--padding-right, 0.75rem) var(--padding-bottom, 0) var(--padding-left, 3.25rem);
}
::slotted([slot="title"]) {
flex-grow: 1;
font-family: var(--title-font-family, sans-serif);
font-size: var(--title-font-size, 1rem);
font-weight: var(--title-font-weight, 400);
line-height: var(--title-line-height, 1.375rem);
text-align: center;
}
</style>
<slot name="title"></slot>
<slot name="close"></slot>
`;
}
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template();
}
}
window.customElements.define(PraxisIsncsciDialogHeader.is, PraxisIsncsciDialogHeader);
class PraxisIsncsciExtraInputs extends HTMLElement {
static get is() {
return 'praxis-isncsci-extra-inputs';
}
template() {
return `
<style>
:host {
display: flex;
flex-direction: column;
gap: var(--gap, 1.5rem);
justify-content: center;
padding: var(--padding, 0 1rem);
}
.non-key-muscles {
display: flex;
flex-direction: column;
}
.non-key-muscles,
.non-key-muscles .inputs,
.comments {
gap: var(--input-gap, 0.5rem);
}
.non-key-muscles,
.comments {
width: 100%
}
.inputs {
align-items: center;
display: grid;
grid-template-columns: minmax(min-content, max-content) 1fr;
}
.comments {
display: flex;
flex-direction: column;
}
::slotted([slot="non-key-muscles-header"]) {
color: var(--header-color, #303030);
font-family: var(--header-font-family, sans-serif);
font-size: var(--header-font-size, 0.75rem);
font-weight: var(--header-font-weight, 500);
line-height: var(--header-line-height, 1rem);
}
::slotted(label) {
color: var(--label-color, #303030);
font-family: var(--label-font-family, sans-serif);
font-size: var(--label-font-size, 0.75rem);
font-weight: var(--label-font-weight, 400);
line-height: var(--label-line-height, 1rem);
}
::slotted(select),
::slotted(textarea) {
border-color: var(--input-border-color, #525252);
border-radius: var(--input-border-radius, 0.125rem);
}
::slotted(select) {
height: var(--input-height, 2.26rem);
min-width: 0;
}
::slotted(textarea) {
height: 4.625rem;
resize: none;
}
@container (min-width: 48rem) {
:host {
flex-direction: row;
}
.non-key-muscles,
.comments {
max-width: 22.5rem;
}
}
</style>
<div class="non-key-muscles">
<slot name="non-key-muscles-header"></slot>
<div class="inputs">
<slot name="right-lowest-label"></slot>
<slot name="right-lowest"></slot>
<slot name="left-lowest-label"></slot>
<slot name="left-lowest"></slot>
</div>
</div>
<div class="comments">
<slot name="comments-label"></slot>
<slot name="cell-comments-display"></slot>
<slot name="comments"></slot>
</div>
`;
}
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template();
}
}
window.customElements.define(PraxisIsncsciExtraInputs.is, PraxisIsncsciExtraInputs);
/**
* @tagname praxis-isncsci-grid
*/
class PraxisIsncsciGrid extends HTMLElement {
static get is() {
return 'praxis-isncsci-grid';
}
static get observedAttributes() {
return ['highlighted-cells', 'left'];
}
constructor() {
super();
this.template = `
<style>
:host {
column-gap: var(--cell-gap);
display: grid;
grid-template-columns: repeat(4, var(--cell-width, 2.5rem));
grid-template-areas:
'side side side side'
'. mh lth pph'
'label motor light-touch pin-prick';
grid-template-rows: 1.625rem 1.5rem repeat(28, var(--cell-height, 2.375rem));
row-gap: var(--cell-gap, 0);
}
:host([left]) {
grid-template-areas:
'side side side side'
'lth pph mh .'
'light-touch pin-prick motor label';
}
:host([left]) .label {
padding-left: 12px;
padding-right: 0;
}
:host([labels-hidden]) .label {
display: none;
}
.header {
font-weight: 300;
margin: 0;
padding: 0;
text-align: center;
}
.header.side {
grid-column: side;
}
.header.motor {
grid-column: mh;
}
.header.light-touch {
grid-column: lth;
}
.header.pin-prick {
grid-column: pph;
}
.label {
align-items: center;
display: flex;
grid-column: label;
justify-content: right;
padding-right: 12px;
}
[motor] {
grid-column: motor;
}
[light-touch] {
grid-column: light-touch;
}
[pin-prick] {
grid-column: pin-prick;
}
</style>
`;
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.updateView(this.hasAttribute('left'));
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue) {
return;
}
if (name === 'left') {
console.log('ToDo: Dynamically change side');
return;
}
if (name === 'highlighted-cells') {
this.updateHighlights(newValue);
return;
}
}
getCell(side, observationType, level) {
if (observationType === 'motor' &&
!MotorLevels.includes(level)) {
return '';
}
const slug = `${side}-${observationType}-${level.toLowerCase()}`;
const value = this.getAttribute(slug);
return `<praxis-isncsci-cell data-observation="${slug}" ${observationType}>${value !== null && value !== void 0 ? value : ''}</praxis-isncsci-cell>`;
}
getHeader(left) {
return left
? `
<h3 class="header side">Left</h3>
<div class="header light-touch">LT</div><div class="header pin-prick">PP</div><div class="header motor">M</div>
`
: `
<h3 class="header side">Right</h3>
<div class="header motor">M</div><div class="header light-touch">LT</div><div class="header pin-prick">PP</div>
`;
}
getLevels(left) {
let levels = '';
SensoryLevels.forEach((level) => {
levels += left
? `
${this.getCell('left', 'light-touch', level)}
${this.getCell('left', 'pin-prick', level)}
${this.getCell('left', 'motor', level)}
<div class="label">${level}</div>
`
: `
<div class="label">${level}</div>
${this.getCell('right', 'motor', level)}
${this.getCell('right', 'light-touch', level)}
${this.getCell('right', 'pin-prick', level)}
`;
});
return levels;
}
updateView(left) {
if (!this.shadowRoot) {
throw new Error(`${PraxisIsncsciGrid.is} :: updateView :: No shadow root available`);
}
this.shadowRoot.innerHTML = `
${this.template}
${this.getHeader(left)}
${this.getLevels(left)}
`;
const buttons = this.shadowRoot.querySelectorAll('button.help-icon');
buttons.forEach((btn) => {
btn.addEventListener('click', (e) => {
const buttonEl = e.currentTarget;
const level = buttonEl.getAttribute('data-level') || '';
const side = buttonEl.getAttribute('data-side') || (left ? 'left' : 'right');
const type = buttonEl.getAttribute('data-type') || 'sensory';
// Dispatch a custom event for the outside to catch
this.dispatchEvent(new CustomEvent('help-icon-clicked', {
detail: { level, side, type },
bubbles: true,
composed: true
}));
});
});
}
updateHighlights(newValue) {
if (!this.shadowRoot) {
throw new Error('No shadow root available');
}
// Clear previous highlights
this.shadowRoot
.querySelectorAll('praxis-isncsci-cell[highlighted]')
.forEach((cell) => cell.removeAttribute('highlighted'));
// Set new highlights
if (!newValue) {
return;
}
const attribute = newValue
.split('|')
.map((observation) => `[data-observation="${observation}"]`)
.join(',');
this.shadowRoot
.querySelectorAll(attribute)
.forEach((cell) => cell.setAttribute('highlighted', ''));
}
}
window.customElements.define(PraxisIsncsciGrid.is, PraxisIsncsciGrid);
class PraxisIsncsciInput extends HTMLElement {
static get is() {
return 'praxis-isncsci-input';
}
static get observedAttributes() {
return ['disabled', 'sensory', 'selected-value'];
}
template() {
return `
<style>
:host {
position: relative;
align-items: center;
background: var(--background, rgba(255, 255, 255, 0.4));
border-radius: var(--border-radius, 0.5rem) var(--border-radius, 0.5rem) 0 0;
box-shadow: var(--box-shadow, 0 0 0.125rem rgba(95, 24, 119, 0.24));
container-type: inline-size;
display: flex;
flex-direction: column;
gap: 0;
padding: var(--padding, 1rem);
padding-top: 50px;
}
:host([show-unknown]) [unk] {
display: flex;
}
:host([show-unknown]) [buttons] > *:last-child {
grid-column: auto;
}
/* Button styles */
[buttons] {
display: grid;
gap: var(--buttons-gap, 0.25rem);
grid-template-columns: repeat(4, 1fr);
width: var(--buttons-width, 20.75rem);
}
[buttons] > *:last-child {
grid-column: 3 / 5;
}
button {
align-items: center;
background-color: var(--button-surface, #fff);
border: solid var(--button-border-width, 0.0625rem) var(--button-border-color, #ccc);
border-radius: var(--button-border-radius, 0.25rem);
color: var(--button-on-surface, #6a6a6a);
display: flex;
font-family: var(--button-font-family, sans-serif);
font-size: var(--button-font-size, 0.875rem);
font-weight: var(--button-font-weight, 400);
height: var(--button-height, 2.375rem);
justify-content: center;
line-height: var(--button-line-height, 1.25rem);
padding: 0;
transition: background-color ease 200ms, font-size ease 200ms;
}
button.left {
border-radius: var(--button-border-radius, 0.25rem)
var(--button-border-radius-none, 0)
var(--button-border-radius-none, 0)
var(--button-border-radius, 0.25rem);
border-right: none;
}
button.right {
border-radius: var(--button-border-radius-none, 0)
var(--button-border-radius, 0.25rem)
var(--button-border-radius, 0.25rem)
var(--button-border-radius-none, 0);
border-left: none;
width: 2.5rem;
}
button.right::before {
content: '';
display: inline-block;
background-color: var(--button-divider-color, #ccc);
width: var(--button-divider-width, 0.0625rem);
height: calc(100% - var(--button-divider-gap, 0.5rem));
}
button.right *:last-child {
flex-grow: 1;
}
button:disabled {
background-color: var(--button-disabled-surface, #f5f5f5);
color: var(--button-disabled-on-surface, #9e9e9e);
cursor: not-allowed;
}
button:hover:not(:disabled) {
background-color: var(--button-hover-surface, #faecff);
color: var(--button-on-surface, #6a6a6a);
}
button:active:not(:disabled) {
background-color: var(--button-active-surface, #f1c6ff);
font-size: var(--button-active-font-size, 0.75rem);
}
button[selected] {
background-color: var(--button-selected-surface, purple);
color: var(--button-selected-on-surface, #fff);
}
.button-group {
border-radius: var(--button-border-radius, 0.25rem);
display: flex;
flex-direction: row;
transition: box-shadow ease 200ms;
}
.button-group > *:first-child {
flex-grow: 1;
}
.button-group:has(button:hover:not(:disabled)) {
box-shadow: var(--button-hover-box-shadow, 0 2px 4px rgba(95, 24, 119, 0.1), 0 1px 6px rgba(95, 24, 119, 0.05));
}
/* Star input styles */
:host([show-star-input]) {
gap: var(--gap, 1rem);
}
:host([show-star-input]) [star-input] {
max-height: 13.75rem;
}
[star-input] {
display: flex;
flex-direction: column;
flex-grow: 1;
gap: var(--gap, 1rem);
max-height: 0px;
max-width: 63.75rem;
overflow: hidden;
transition: max-height ease 250ms;
}
[star-entries] {
display: flex;
flex-direction: column;
gap: var(--gap, 1rem);
}
.star-input-entry {
align-items: center;
display: flex;
flex-direction: row;
gap: .5rem;
}
.star-textarea-entry {
align-items: stretch;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.divider {
background-color: var(--divider-color, #d9d9d9);
height: var(--divider-height, 0.0625rem);
}
.label-container {
color: var(--label-color, #5e5e5e);
flex-grow: 1;
font-family: var(--label-font-family, sans-serif);
font-size: var(--label-font-size, 0.75rem);
font-weight: var(--label-font-weight, 400);
line-height: var(--label-line-height, 0.875rem);
}
.input-container {
display: flex;
}
::slotted(select) {
height: var(--input-height, 2.25rem);
width: var(--select-width, 11.25rem);
}
::slotted(textarea) {
height: var(--textarea-height, 3.5rem);
width: 100%;
}
[unk] {
display: none;
}
.toggle-switch{
position: absolute;
top: 10px;
right: 10px;
}
@container(min-width: 580px){
:host{
padding-top: var(--padding, 1rem);
}
}
@container (min-width: 48rem) {
:host {
border-radius: 0 0 var(--border-radius, 0.5rem) var(--border-radius, 0.5rem);
flex-direction: row;
}
[star-input] {
transition: none;
}
[star-entries] {
flex-direction: row;
padding: 0;
}
.star-input-entry {
align-items: stretch;
flex-direction: column;
max-width: 180px;
}
.star-textarea-entry {
flex-grow: 1;
}
.divider {
display: none;
}
::slotted(select) {
flex-grow: 1;
}
}
</style>
<div buttons>
<div class="button-group">
<button class="isncsci-input-button left" value="0">0</button>
<button class="isncsci-input-button right" value="0*"><span>*</span></button>
</div>
<div class="button-group">
<button class="isncsci-input-button left" value="1">1</button>
<button class="isncsci-input-button right" value="1*"><span>*</span></button>
</div>
<div class="button-group">
<button class="isncsci-input-button left" value="2">2</button>
<button class="isncsci-input-button right" value="2*" motor-only><span>*</span></button>
</div>
<div class="button-group">
<button class="isncsci-input-button left" value="3" motor-only>3</button>
<button class="isncsci-input-button right" value="3*" motor-only><span>*</span></button>
</div>
<div class="button-group">
<button class="isncsci-input-button left" value="4" motor-only>4</button>
<button class="isncsci-input-button right" value="4*" motor-only><span>*</span></button>
</div>
<div class="button-group">
<button class="isncsci-input-button" value="5" motor-only>5</button>
</div>
<div class="button-group" unk>
<button class="isncsci-input-button" value="UNK">UNK</button>
</div>
<div class="button-group">
<button class="isncsci-input-button left" value="NT">NT</button>
<button class="isncsci-input-button right" value="NT*"><span>*</span></button>
</div>
</div>
<div star-input>
<div class="divider"> </div>
<div star-entries>
<div class="star-input-entry">
<div class="label-container">
<slot name="consider-normal-label"></slot>
</div>
<div class="input-container">
<slot name="consider-normal"></slot>
</div>
</div>
<div class="star-input-entry">
<div class="label-container" dynamic-label>
<slot name="reason-for-impairment-not-due-to-sci-label"></slot>
</div>
<div class="input-container">
<slot name="reason-for-impairment-not-due-to-sci"></slot>
</div>
</div>
<div class="star-textarea-entry">
<div class="label-container">
<slot name="reason-for-impairment-not-due-to-sci-specify-label"></slot>
</div>
<div class="input-container">
<slot name="reason-for-impairment-not-due-to-sci-specify"></slot>
</div>
</div>
</div>
</div>
<label class="toggle-switch">
<input type="checkbox" id="multiple-selection-toggle" />
<span class="slider"></span>
<span class="label-text">Multi-select</span>
</label>
`;
}
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template();
}
connectedCallback() {
var _a;
(_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('button').forEach((b) => b.addEventListener('click', (e) => this.buttons_onClick(b)));
}
buttons_onClick(button) {
//THe update of the selected-value of the cell is done in the inputLayoutcontroller.ts
//Here is the flow
//inputLayout.controller.ts is capturning the 'value_click' event
//setCellsValueUseCase will be called in the callback function and will trigger the setCellsValueUseCase in the state provider
//within the callback function state provider function 'setCellsValueUserCase' will be called
//and 'SET_ACTIVE_CELLS' will be dispatched in the state provider function
//at the same time inputLayout.controller.ts is capturing the state change event
//updateInputButtons will be called to update the style of the cell
const value = button.hasAttribute('selected') ? "" : button.value;
if ((!value && value !== '') || !/^([0-4]\*?|5|UNK|NT\*{0,2})|\s*$/.test(value)) {
return;
}
this.dispatchEvent(new CustomEvent('value_click', { detail: { value } }));
}
attributeChangedCallback(name, oldValue, newValue) {
var _a, _b, _c, _d, _e, _f, _g;
if (oldValue === newValue) {
return;
}
if (name === 'sensory') {
const labelEl = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('[dynamic-label]');
if (labelEl) {
if (newValue === null) {
// for motor values
labelEl.textContent =
'If motor impairment not due to SCI, please indicate reason:';
}
else {
// for sensory values
labelEl.textContent =
'If sensory impairment not due to SCI, please indicate reason:';
}
}
if (newValue === null) {
(_b = this.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll('[motor-only]').forEach((b) => {
b.removeAttribute('disabled');
});
}
else {
(_c = this.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelectorAll('[motor-only]').forEach((b) => {
b.setAttribute('disabled', '');
});
}
}
if (name === 'selected-value') {
(_d = this.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelectorAll('[selected]').forEach((b) => b.removeAttribute('selected'));
const simplifiedValue = newValue === null || newValue === void 0 ? void 0 : newValue.replace(/\*\*$/, '*');
(_e = this.shadowRoot) === null || _e === void 0 ? void 0 : _e.querySelectorAll(`button[value="${simplifiedValue}"]`).forEach((b) => b.setAttribute('selected', ''));
}
if (name === 'disabled') {
if (newValue === null) {
const selector = this.hasAttribute('sensory')
? 'button:not([motor-only])'
: 'button';
(_f = this.shadowRoot) === null || _f === void 0 ? void 0 : _f.querySelectorAll(selector).forEach((b) => {
b.removeAttribute('disabled');
});
}
else {
(_g = this.shadowRoot) === null || _g === void 0 ? void 0 : _g.querySelectorAll('button').forEach((b) => {
b.setAttribute('disabled', '');
});
}
}
}
}
window.customElements.define(PraxisIsncsciInput.is, PraxisIsncsciInput);
/**
* @tagname praxis-isncsci-input-layout
*/
class PraxisIsncsciInputLayout extends HTMLElement {
static get is() {
return 'praxis-isncsci-input-layout';
}
static get observedAttributes() {
return ['readonly'];
}
constructor() {
super();
this.template = `
<style>
:host {
display: flex;
flex-direction: column;
gap: var(--space-6);
}
[grid-section] {
--grid-gap: var(--space-8);
display: flex;
justify-content: center;
}
[right-dermatomes],
[left-dermatomes] {
display: flex;
flex-direction: column;
}
[right-dermatomes] {
align-items: end;
margin-right: var(--grid-gap);
}
[left-dermatomes] {
align-items: start;
margin-left: var(--grid-gap);
}
[diagram] {
display: none;
flex-grow: 1;
padding-top: 1rem;
position: relative;
}
[diagram] ::slotted([slot="key-points-diagram"]) {
left: 50%;
position: relative;
transform: translateX(-50%);
}
@media (min-height: 76.5rem) {
[diagram] ::slotted([slot="key-points-diagram"]) {
position: fixed;
}
}
@container (min-width: 53.125rem) {
[diagram] {
display: block;
}
[diagram] ::slotted([slot="key-points-diagram"]) {
transform: translateX(-50%) scale(0.8);
}
}
@container (min-width: 58.125rem) {
[diagram] ::slotted([slot="key-points-diagram"]) {
transform: translateX(-50%) scale(1);
display: flex;
justify-content: center;
}
}
</style>
<div grid-section>
<div right-dermatomes>
<praxis-isncsci-grid></praxis-isncsci-grid>
<slot name="vac"></slot>
</div>
<div diagram>
<slot name="key-points-diagram"></slot>
</div>
<div left-dermatomes>
<praxis-isncsci-grid left></praxis-isncsci-grid>
<slot name="dap"></slot>
</div>
</div>
<praxis-isncsci-extra-inputs>
<slot name="non-key-muscles-header" slot="non-key-muscles-header"></slot>
<slot name="right-lowest-label" slot="right-lowest-label"></slot>
<slot name="right-lowest" slot="right-lowest"></slot>
<slot name="left-lowest-label" slot="left-lowest-label"></slot>
<slot name="left-lowest" slot="left-lowest"></slot>
<slot name="comments-label" slot="comments-label"></slot>
<slot name="cell-comments-display" slot="cell-comments-display"></slot>
<slot name="comments" slot="comments"></slot>
</praxis-isncsci-extra-inputs>
`;
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template;
}
updateReadonly(readonly) {
this.querySelectorAll('select, input, textarea').forEach((input) => {
const attributeName = input instanceof HTMLSelectElement ? 'disabled' : 'readonly';
if (readonly) {
input.setAttributeNode(document.createAttribute(attributeName));
}
else {
input.removeAttribute(attributeName);
}
});
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue) {
return;
}
if (name === 'readonly') {
this.updateReadonly(newValue !== null);
}
}
}
window.customElements.define(PraxisIsncsciInputLayout.is, PraxisIsncsciInputLayout);
class PraxisIsncsciKeyPointsDiagram extends HTMLElement {
static get is() {
return 'praxis-isncsci-key-points-diagram';
}
static get observedAttributes() {
const levels = [];
SensoryLevels.forEach((level) => {
const levelToLowerCase = level.toLowerCase();
levels.push(`right-${levelToLowerCase}`);
levels.push(`left-${levelToLowerCase}`);
});
return levels;
}
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = this.template();
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue || !this.shadowRoot) {
return;
}
this.shadowRoot
.querySelectorAll(`[data-level="${name}"]`)
.forEach((segment) => segment.setAttribute('fill', `var(--surface-${newValue})`));
}
template() {
return `
<style>
:host {
--surface--: #F9F9F9;
--surface--0: #EBA58C;
--surface-0-0: #E35522;
--surface-0-1: #E38A22;
--surface-0-2: #E3AD22;
--surface--1: #EBD08B;
--surface-1-1: #E3AD22;
--surface-1-2: #E3DB22;
--surface--2: #BEED81;
--surface-2-2: #8EE322;
display: block;
}
</style>
<svg width="299" height="547" viewBox="0 0 299 547" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<g>
<path d="M150.703 289.57C149.327 292.82 148.429 301.445 147.804 307.945C147.179 314.445 149.554 330.195 149.554 336.82C149.554 343.445 147.304 374.82 146.679 380.32C146.054 385.82 147.804 396.945 148.429 404.82C149.054 412.695 146.179 437.57 146.054 443.445C145.929 449.32 147.054 460.57 148.179 465.32C149.304 470.07 148.554 475.945 148.179 477.195C147.804 478.445 148.679 479.57 149.554 486.07C150.429 492.57 141.804 494.82 140.679 495.57C139.554 496.32 136.179 499.695 135.054 500.945C133.929 502.195 131.679 503.445 128.429 503.695C125.054 507.945 121.054 506.07 119.804 504.695C118.304 504.82 117.179 504.945 116.429 503.945C115.054 503.945 114.554 503.445 114.179 502.07C112.179 501.07 112.304 499.82 112.804 498.82C112.179 496.82 113.929 494.82 115.054 494.195C116.179 493.57 123.054 488.32 125.179 486.57C127.304 484.82 128.929 481.945 130.929 480.195C133.804 442.195 118.929 424.57 117.179 407.445C115.906 394.987 121.679 371.695 121.679 355.945C121.679 334.442 105.283 303.863 107.512 242.362C108.429 217.07 114.054 203.82 114.511 190.362C114.772 182.671 106.178 149.195 103.678 140.529C102.178 144.196 97.0108 157.529 94.1778 166.529C91.3448 175.529 90.8468 177.779 88.4288 181.196C86.3178 184.18 86.0538 193.571 82.1778 202.196C80.4368 206.071 69.6778 222.863 62.3448 232.363C61.3448 243.363 55.3038 263.321 53.0108 266.696C51.6278 268.731 48.3448 269.363 47.3448 268.696C46.5118 270.196 45.5048 270.815 44.0108 270.363C41.8038 269.696 42.1778 268.363 42.3438 263.03C39.8428 267.196 35.9288 273.571 32.3448 271.863C29.5828 270.548 34.3448 262.196 35.8448 257.863C31.8448 263.196 29.8588 267.516 26.5118 265.362C23.7288 263.571 27.8448 257.196 29.5108 254.53C31.1768 251.863 32.5108 249.03 33.3448 246.53C28.3038 250.197 26.4358 249.547 24.1778 247.697C22.8038 246.572 24.8508 244.538 26.6778 243.03C31.9288 238.697 36.6778 232.53 38.8458 229.363C41.0138 226.196 43.6778 224.53 47.1778 224.363C50.1788 213.071 52.3038 199.196 56.6778 188.363C59.7378 180.784 65.8828 171.803 67.9288 168.696C71.3038 163.571 71.9408 152.816 73.5118 145.529C75.9288 134.321 79.0518 131.075 81.6778 125.862C84.3858 120.486 83.1788 114.82 87.2438 106.57C92.2718 96.366 98.9488 94.901 102.756 94.781C106.716 94.656 107.804 92.07 126.344 84.862C137.492 80.528 135.845 72.529 135.512 67.529C134.679 66.196 133.178 63.862 132.178 56.529C127.345 56.529 126.412 53.416 124.679 49.718C122.012 44.029 122.98 37.862 126.678 38.195C124.345 15.028 138.402 10.195 150.703 10.195C163.004 10.195 177.061 15.028 174.728 38.195C178.426 37.862 179.394 44.028 176.727 49.718C174.994 53.415 174.061 56.529 169.228 56.529C168.228 63.862 166.727 66.196 165.894 67.529C165.561 72.529 163.914 80.528 175.062 84.862C193.602 92.07 194.69 94.656 198.65 94.781C202.457 94.901 209.133 96.366 214.162 106.57C218.227 114.82 217.02 120.486 219.728 125.862C222.354 131.075 225.477 134.32 227.894 145.529C229.465 152.815 230.102 163.571 233.477 168.696C235.523 171.803 241.668 180.784 244.728 188.363C249.102 199.196 251.227 213.071 254.228 224.363C257.728 224.53 260.392 226.196 262.56 229.363C264.728 232.53 269.477 238.696 274.728 243.03C276.555 244.538 278.602 246.572 277.228 247.697C274.97 249.547 273.102 250.197 268.061 246.53C268.895 249.03 270.229 251.863 271.895 254.53C273.561 257.196 277.677 263.571 274.894 265.362C271.547 267.516 269.561 263.196 265.561 257.863C267.061 262.196 271.823 270.548 269.061 271.863C265.477 273.571 261.563 267.196 259.062 263.03C259.228 268.363 259.602 269.696 257.395 270.363C255.901 270.815 254.894 270.196 254.061 268.696C253.061 269.363 249.778 268.731 248.395 266.696C246.102 263.321 240.061 243.363 239.061 232.363C231.728 222.863 220.969 206.071 219.228 202.196C215.352 193.571 215.088 184.18 212.977 181.196C210.559 177.779 210.061 175.529 207.228 166.529C204.395 157.529 199.228 144.195 197.728 140.529C195.228 149.196 186.634 182.671 186.895 190.362C187.352 203.82 192.977 217.07 193.894 242.362C196.123 303.863 179.727 334.442 179.727 355.945C179.727 371.695 185.5 394.987 184.227 407.445C182.477 424.57 167.602 442.195 170.477 480.195C172.477 481.945 174.102 484.82 176.227 486.57C178.352 488.32 185.227 493.57 186.352 494.195C187.477 494.82 189.227 496.82 188.602 498.82C189.102 499.82 189.227 501.07 187.227 502.07C186.852 503.445 186.352 503.945 184.977 503.945C184.227 504.945 183.102 504.82 181.602 504.695C180.352 506.07 176.352 507.945 172.977 503.695C169.727 503.445 167.477 502.195 166.352 500.945C165.227 499.695 161.852 496.32 160.727 495.57C159.602 494.82 150.977 492.57 151.852 486.07C152.727 479.57 153.602 478.445 153.227 477.195C152.852 475.945 152.102 470.07 153.227 465.32C154.352 460.57 155.477 449.32 155.352 443.445C155.227 437.57 152.352 412.695 152.977 404.82C153.602 396.945 155.352 385.82 154.727 380.32C154.102 374.82 151.852 343.445 151.852 336.82C151.852 330.195 154.227 314.445 153.602 307.945C152.977 301.445 152.079 292.82 150.703 289.57Z" fill="#ABABAB"/>
<g>
<path id="Vector" d="M164.866 67.853C164.876 67.725 164.888 67.587 164.896 67.462L164.913 67.212L165.047 66.999C165.901 65.634 167.278 63.512 168.237 56.477L168.355 55.695H169.228C172.976 55.695 173.924 53.532 175.359 50.383C175.508 50.054 175.662 49.675 175.822 49.335C177.644 45.447 177.546 41.739 176.508 40.105C176.084 39.438 175.538 39.139 174.819 39.202L173.613 39.306L173.734 38.098C174.647 29.034 173.053 22.163 168.997 17.678C165.107 13.378 158.953 11.197 150.704 11.197C142.455 11.197 136.301 13.377 132.411 17.677C128.354 22.162 126.761 29.032 127.674 38.096L127.795 39.301L126.589 39.193C125.875 39.127 125.325 39.419 124.901 40.086C123.862 41.72 123.763 45.409 125.586 49.296C125.746 49.637 125.899 50.057 126.049 50.386C127.484 53.534 128.432 55.698 132.18 55.698H133.053L133.171 56.479C134.13 63.514 135.509 65.678 136.332 66.995L136.465 67.188L136.512 67.475C136.521 67.611 136.534 67.76 136.545 67.899C139.555 71.454 145.895 73.431 150.705 73.431C155.514 73.428 161.857 71.415 164.866 67.853Z" fill="#F9F9F9"/>
<path data-level="left-s1" d="M187.527 498.903L187.648 498.52C188.085 497.123 186.741 495.554 185.867 495.068C184.649 494.391 177.663 489.047 175.592 487.341C174.652 486.567 173.821 485.609 173.029 484.632C175.194 491.752 181.62 496.831 186.542 500.707C186.688 500.822 186.824 500.931 186.967 501.042C187.364 500.825 187.787 500.529 187.89 500.161C187.956 499.924 187.897 499.634 187.709 499.259L187.527 498.903Z" fill="#F9F9F9"/>
<path data-level="right-s1" d="M130.216 482.369C129.818 482.834 129.419 483.331 129.011 483.844C128.026 485.08 127.007 486.36 125.814 487.342C123.743 489.048 116.756 494.393 115.539 495.07C114.665 495.556 113.321 497.126 113.758 498.523L113.879 498.908L113.698 499.268C113.51 499.643 113.451 499.941 113.517 500.178C113.635 500.604 114.185 500.956 114.625 501.176L115.024 501.376L115.092 501.554C115.436 501.281 115.791 501 116.161 500.708C121.592 496.432 128.871 490.7 130.216 482.369Z" fill="#F9F9F9"/>
<path d="M148.562 486.204C148.5 485.747 148.439 485.325 148.378 484.92C145.368 487.64 143.833 490.819 142.747 493.549C145.423 492.323 149.092 490.137 148.562 486.204Z" fill="#F9F9F9"/>
<path d="M153.177 483.966C153.068 484.633 152.955 485.37 152.843 486.204C152.216 490.858 157.474 493.071 160.001 494.134C160.081 494.168 160.148 494.197 160.222 494.227C158.997 491.041 157.243 487.09 153.177 483.966Z" fill="#F9F9F9"/>
<path data-level="right-l5" d="M141.454 494.113C142.608 491.085 144.196 487.33 147.736 484.152C143.997 483.863 142.06 482.277 142.06 479.362C142.06 462.895 129.08 388.713 122.36 363.055C121.919 368.699 121.08 374.827 120.251 380.826C118.835 391.065 117.498 400.737 118.174 407.343C118.757 413.052 120.841 418.847 123.253 425.556C127.969 438.672 133.838 454.995 131.926 480.27L131.895 480.678L131.587 480.948C131.507 481.018 131.429 481.1 131.35 481.176C130.548 490.626 122.632 496.888 116.783 501.494C116.336 501.847 115.914 502.18 115.507 502.505C115.698 502.7 115.956 502.695 116.43 502.695H116.93L117.23 503.22C117.441 503.5 117.695 503.715 118.43 503.715C118.786 503.715 119.175 503.712 119.597 503.677L120.213 503.642L120.545 504.014C120.952 504.462 122.13 505.313 123.677 505.313C125.129 505.313 126.464 504.56 127.647 503.071L127.918 502.73L128.353 502.697C132.121 502.408 133.867 500.771 134.312 500.276C135.39 499.078 138.878 495.569 140.125 494.738C140.393 494.56 140.795 494.39 141.405 494.134C141.419 494.127 141.438 494.119 141.454 494.113Z" fill="#F9F9F9"/>
<path data-level="left-l5" d="M185.921 501.494C180.418 497.161 173.087 491.361 171.567 482.822C170.99 482.122 170.419 481.473 169.818 480.948L169.51 480.678L169.479 480.27C167.567 454.996 173.436 438.672 178.152 425.556C180.564 418.847 182.648 413.052 183.231 407.343C183.907 400.738 182.57 391.066 181.154 380.826C180.508 376.148 179.856 371.392 179.388 366.845C172.458 395.37 160.642 463.592 160.642 479.362C160.642 482.277 158.731 483.883 154.992 484.174C158.778 487.585 160.323 491.657 161.502 494.779C161.523 494.836 161.543 494.887 161.565 494.943C162.99 496.034 166.089 499.159 167.095 500.276C167.54 500.771 169.286 502.408 173.054 502.698L173.489 502.731L173.76 503.073C174.943 504.562 176.278 505.317 177.729 505.317C179.277 505.317 180.456 504.47 180.862 504.022L181.194 503.658L181.811 503.709C182.232 503.745 182.621 503.778 182.977 503.778C183.712 503.778 183.966 503.501 184.177 503.22L184.477 502.695H184.977C185.773 502.695 185.968 502.72 186.243 501.748C186.134 501.662 186.033 501.582 185.921 501.494Z" fill="#F9F9F9"/>
<path data-level="right-l4" d="M147.445 479.987C147.128 478.578 146.953 477.8 147.22 476.908C147.58 475.707 148.261 470.008 147.205 465.551C146.035 460.613 144.93 449.239 145.053 443.424C145.098 441.324 145.488 436.85