@decidables/decidables-elements
Version:
decidables-elements: Basic UI Web Components for the decidables project
216 lines (166 loc) • 5.39 kB
JavaScript
import {ifDefined} from 'lit/directives/if-defined.js';
import {css, html} from 'lit';
import DecidablesElement from './decidables-element';
export default class DecidablesSpinner extends DecidablesElement {
static get properties() {
return {
disabled: {
attribute: 'disabled',
type: Boolean,
reflect: true,
},
max: {
attribute: 'max',
type: Number,
reflect: true,
},
min: {
attribute: 'min',
type: Number,
reflect: true,
},
step: {
attribute: 'step',
type: Number,
reflect: true,
},
value: {
attribute: 'value',
type: Number,
reflect: true,
},
};
}
constructor() {
super();
// Attributes
this.disabled = false;
this.max = undefined;
this.min = undefined;
this.step = undefined;
this.value = undefined;
}
inputted(event) {
this.value = event.target.value;
}
static get styles() {
return [
super.styles,
css`
:host {
---decidables-spinner-font-size: var(--decidables-spinner-font-size, 1.125rem);
---decidables-spinner-input-width: var(--decidables-spinner-input-width, 4rem);
---decidables-spinner-prefix: var(--decidables-spinner-prefix, "");
---decidables-spinner-postfix: var(--decidables-spinner-postfix, "");
---decidables-spinner-postfix-padding: var(--decidables-spinner-postfix-padding, 0rem);
display: block;
}
label {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
margin: 0;
font-size: 0.75rem;
}
label::before {
position: absolute;
bottom: 1px;
left: calc(50% - var(---decidables-spinner-input-width) / 2 + 0.25rem);
font-size: var(---decidables-spinner-font-size);
line-height: normal;
content: var(---decidables-spinner-prefix);
}
label::after {
position: absolute;
right: 0.25rem;
bottom: 1px;
font-size: var(---decidables-spinner-font-size);
line-height: normal;
content: var(---decidables-spinner-postfix);
}
input[type=number] {
width: var(---decidables-spinner-input-width);
padding: 1px var(---decidables-spinner-postfix-padding) 1px 2px;
margin: 0;
font-family: var(---font-family-base);
font-size: var(---decidables-spinner-font-size);
color: inherit;
text-align: right;
appearance: none;
outline: none;
background: none;
border: 0;
border-radius: 0;
box-shadow: var(---shadow-2);
}
input[type=number]:hover {
box-shadow: var(---shadow-4);
}
input[type=number]:focus,
input[type=number]:active {
box-shadow: var(---shadow-8);
}
input[type=number]:disabled {
color: var(---color-text);
border: 0;
box-shadow: none;
}
/* HACK: Manage spinners in Firefox */
@supports (-moz-appearance: textfield) {
input[type=number] {
padding-right: calc(18px + var(---decidables-spinner-postfix-padding));
appearance: textfield;
}
/* HACK: Avoid elements shifting due to box-shadow! */
:host(.math) input[type=number]:hover {
box-shadow: var(---shadow-2);
}
:host(.math) input[type=number]:focus,
:host(.math) input[type=number]:active {
box-shadow: var(---shadow-8);
}
input[type=number]:hover,
input[type=number]:focus,
input[type=number]:active {
padding-right: var(---decidables-spinner-postfix-padding);
appearance: none;
}
input[type=number]:disabled {
padding-right: calc(18px + var(---decidables-spinner-postfix-padding));
appearance: textfield;
}
}
/* HACK: Manage spinners in Chrome/Edge/Safari */
input[type=number]::-webkit-inner-spin-button {
/* Avoid oversized spinners in Safari */
font-size: 1.125rem;
opacity: 0;
}
input[type=number]:hover::-webkit-inner-spin-button,
input[type=number]:focus::-webkit-inner-spin-button,
input[type=number]:active::-webkit-inner-spin-button {
opacity: 1;
}
input[type=number]:disabled::-webkit-inner-spin-button {
opacity: 0;
}
/* HACK: Adjust padding on mobile w/o spinners */
@media only screen and (hover: none) and (pointer: coarse) {
input[type=number] {
padding-right: calc(1.125rem + var(---decidables-spinner-postfix-padding));
}
}
`,
];
}
render() {
return html`
<label>
<slot></slot>
<input ?disabled=${this.disabled} type="number" min=${ifDefined(this.min)} max=${ifDefined(this.max)} step=${ifDefined(this.step)} .value=${this.value} @input=${this.inputted.bind(this)}>
</label>
`;
}
}
customElements.define('decidables-spinner', DecidablesSpinner);