@unicef-polymer/etools-unicef
Version:
eTools UNICEF library of reusable components
386 lines (361 loc) • 11 kB
JavaScript
'use strict';
import { __decorate } from "tslib";
import { LitElement, html } from 'lit';
import { property, customElement } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
/**
* @customElement
* @polymer
*/
let TimeInput = class TimeInput extends LitElement {
set value(value) {
this._value = value;
this._valueChanged(this.value);
}
get value() {
return this._value;
}
set hoursInput(hoursInput) {
this._hoursInput = hoursInput;
this.computeTime(this.hoursInput, this.minutesInput);
}
get hoursInput() {
return this._hoursInput;
}
set minutesInput(minutesInput) {
this._minutesInput = minutesInput;
this.computeTime(this.hoursInput, this.minutesInput);
}
get minutesInput() {
return this._minutesInput;
}
render() {
// language=HTML
return html `
<style>
:host {
display: block;
--sl-input-required-content-offset: 3px;
--sl-input-required-content-color: #ea4022;
}
.form-control .form-control__label {
display: none;
}
.form-control .form-control__help-text {
display: none;
}
/* Label */
.form-control--has-label .form-control__label {
display: block;
color: var(--secondary-text-color);
line-height: 18px;
font-size: var(--etools-font-size-12, 12px);
}
:host([required]) .form-control--has-label .form-control__label::after {
content: var(--sl-input-required-content);
margin-inline-start: var(--sl-input-required-content-offset);
color: var(--sl-input-required-content-color);
}
:host([readonly]) .form-control--has-label .form-control__label::after {
content: '';
}
.input {
flex: 1 1 auto;
display: inline-flex;
align-items: stretch;
justify-content: start;
position: relative;
width: 100%;
font-family: inherit;
font-weight: inherit;
letter-spacing: inherit;
vertical-align: middle;
overflow: hidden;
cursor: text;
padding-bottom: 3px;
}
.input__control {
flex: 1 1 auto;
font-family: inherit;
font-size: inherit;
font-weight: inherit;
min-width: 0;
height: 100%;
color: var(--sl-input-color);
border: none;
background: inherit;
box-shadow: none;
padding: 0;
margin: 0;
cursor: inherit;
-webkit-appearance: none;
padding-inline-end: 5px;
}
.input__control::-webkit-search-decoration,
.input__control::-webkit-search-cancel-button,
.input__control::-webkit-search-results-button,
.input__control::-webkit-search-results-decoration {
-webkit-appearance: none;
}
.input__prefix {
display: inline-flex;
flex: 0 0 auto;
align-items: center;
cursor: default;
margin-inline-end: 5px;
}
.input__prefix etools-icon {
color: var(--sl-input-icon-color);
}
:host(:not([disabled]):not([readonly])) .invalid-message[visible] {
font-size: var(--etools-font-size-12, 12px);
visibility: visible;
height: 0;
overflow: visible;
}
.invalid-message {
visibility: hidden;
height: 0;
overflow: hidden;
white-space: nowrap;
}
.input::after {
content: '';
position: absolute;
width: 100%;
display: block;
bottom: 0;
border-bottom: 1px solid var(--secondary-text-color);
}
:host([invalid]:not([disabled]):not([readonly])) .input::after {
border-bottom: 2px solid red;
}
:host([invalid]:not([disabled]):not([readonly])) .form-control__label,
:host([invalid]:not([disabled]):not([readonly])) .invalid-message {
color: red;
}
:host([disabled]) .input::after {
border-bottom: 1px dashed var(--secondary-text-color);
}
:host([readonly]) .input::after {
border: none;
border-bottom: none;
}
.input input {
font-size: inherit;
border: 0;
text-align: center;
width: var(--etools-time-inputs-width, 34px);
}
input[type='number']::-webkit-inner-spin-button,
input[type='number']::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type='number'] {
background-color: transparent;
-moz-appearance: textfield;
}
*[hidden] {
display: none;
}
</style>
<div
part="form-control"
class=${classMap({
'form-control': true,
'form-control--has-label': !this.noLabelFloat
})}
>
<label
id="label"
part="form-control-label"
class="form-control__label"
aria-hidden=${this.label ? 'false' : 'true'}
>
${this.label}
</label>
<div part="form-control-input" class="form-control-input">
<div part="base" class="input">
<span part="prefix" class="input__prefix">
<etools-icon name="device:access-time" part="prefix" ?hidden="${this.hideIcon}"></etools-icon>
</span>
<div class="input__control">
<input
.value="${this.hoursInput}"
@change="${(e) => {
console.log(this.hoursInput, e.target.value);
if (this.hoursInput !== e.target.value) {
this.hoursInput = e.target.value;
}
}}"
@blur="${this._formatHour}"
?readonly="${this.readonly}"
?disabled="${this.disabled}"
placeholder="hh"
type="number"
min="0"
max="23"
/>
:
<input
.value="${this.minutesInput}"
@change="${(e) => {
console.log(this.minutesInput, e.target.value);
if (this.minutesInput !== e.target.value) {
this.minutesInput = e.target.value;
}
}}"
@blur="${this._formatMinutes}"
?readonly="${this.readonly}"
?disabled="${this.disabled}"
placeholder="mm"
type="number"
min="0"
max="59"
/>
</div>
</div>
</div>
<div part="invalid-message" class="invalid-message" ?visible=${this.invalid && this.errorMessage}>
${this.errorMessage}
</div>
</div>
`;
}
constructor() {
super();
this.readonly = false;
this.required = false;
this.disabled = false;
this.autoValidate = false;
this.label = 'Time';
this.invalid = false;
this.hideIcon = false;
this.errorMessage = 'Invalid time';
}
_valueChanged(newValue) {
if (!newValue) {
if (this.hoursInput || this.minutesInput) {
this._clearData();
}
return;
}
}
computeTime(hours, minutes) {
if (hours !== undefined && minutes !== undefined) {
if (this.autoValidate && this._isValidHours() && this._isValidMinutes()) {
this.invalid = false;
}
this.value = hours + ':' + minutes + ':00';
}
}
_formatHour() {
if (isNaN(Number(this.hoursInput)) || Number(this.hoursInput) < 0 || Number(this.hoursInput) > 23) {
if (this.autoValidate) {
console.log('h', 'invalid');
this.invalid = true;
}
}
else {
this.hoursInput = !this.hoursInput || this.hoursInput.length < 2 ? '0' + this.hoursInput : this.hoursInput;
}
}
_formatMinutes() {
if (isNaN(Number(this.minutesInput)) || Number(this.minutesInput) < 0 || Number(this.minutesInput) > 59) {
if (this.autoValidate) {
console.log('m', 'invalid');
this.invalid = true;
}
}
else {
this.minutesInput =
!this.minutesInput || this.minutesInput.length < 2 ? '0' + this.minutesInput : this.minutesInput;
}
}
_isValidHours() {
return Number(this.hoursInput) >= 0 && Number(this.hoursInput) < 24;
}
_isValidMinutes() {
return Number(this.minutesInput) >= 0 && Number(this.minutesInput) < 60;
}
_clearData() {
this.hoursInput = undefined;
this.minutesInput = undefined;
this.value = null;
this.invalid = false;
}
validate() {
const valid = this._isValidHours() && this._isValidMinutes();
this.invalid = !valid;
return valid;
}
};
__decorate([
property({
type: String
})
], TimeInput.prototype, "value", null);
__decorate([
property({
type: Boolean,
reflect: true
})
], TimeInput.prototype, "readonly", void 0);
__decorate([
property({
type: Boolean,
reflect: true
})
], TimeInput.prototype, "required", void 0);
__decorate([
property({
type: Boolean,
reflect: true
})
], TimeInput.prototype, "disabled", void 0);
__decorate([
property({
type: Boolean,
reflect: true,
attribute: 'auto-validate'
})
], TimeInput.prototype, "autoValidate", void 0);
__decorate([
property({
type: Number
})
], TimeInput.prototype, "hoursInput", null);
__decorate([
property({
type: Number
})
], TimeInput.prototype, "minutesInput", null);
__decorate([
property({
type: String
})
], TimeInput.prototype, "label", void 0);
__decorate([
property({
type: Boolean,
reflect: true
})
], TimeInput.prototype, "invalid", void 0);
__decorate([
property({
type: Boolean
})
], TimeInput.prototype, "hideIcon", void 0);
__decorate([
property({
type: String
})
], TimeInput.prototype, "errorMessage", void 0);
__decorate([
property({ type: Boolean, attribute: 'no-label-float' })
], TimeInput.prototype, "noLabelFloat", void 0);
TimeInput = __decorate([
customElement('time-input')
], TimeInput);
export { TimeInput };