UNPKG

@dile/dile-select

Version:

Web Component to implement a plain selector interface, following open-wc recommendations

173 lines (159 loc) 5.78 kB
import { html, css, LitElement } from "lit"; import { DileEmmitChangeMixin } from '@dile/dile-form-mixin'; import { messageStyles } from '@dile/dile-input'; export class DileSelect extends DileEmmitChangeMixin(LitElement) { static get styles() { return [ messageStyles, css` :host { display: block; margin-bottom: 10px; } * { box-sizing: border-box; } label { display: block; margin-bottom: var(--dile-input-label-margin-bottom, 4px); font-size: var(--dile-input-label-font-size, 1em); color: var(--dile-input-label-color, #59e); font-weight: var(--dile-input-label-font-weight, normal); } ::slotted(select) { box-sizing: border-box; width: var(--dile-input-width, 100%); padding: var(--dile-input-padding, 7px 5px); line-height: var(--dile-input-line-height, 1.5em); font-size: var(--dile-select-font-size, 0.875em); border-radius: var(--dile-input-border-radius, 5px); border: var(--dile-input-border-width, 1px) solid var(--dile-input-border-color, #888); background-color: var(--dile-input-background-color, #fff); color: var(--dile-input-color, #303030); background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20256%20448%22%20enable-background%3D%22new%200%200%20256%20448%22%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E.arrow%7Bfill%3A%23303030%3B%7D%3C%2Fstyle%3E%3Cpath%20class%3D%22arrow%22%20d%3D%22M255.9%20168c0-4.2-1.6-7.9-4.8-11.2-3.2-3.2-6.9-4.8-11.2-4.8H16c-4.2%200-7.9%201.6-11.2%204.8S0%20163.8%200%20168c0%204.4%201.6%208.2%204.8%2011.4l112%20112c3.1%203.1%206.8%204.6%2011.2%204.6%204.4%200%208.2-1.5%2011.4-4.6l112-112c3-3.2%204.5-7%204.5-11.4z%22%2F%3E%3C%2Fsvg%3E%0A"); background-position: right 10px center; background-repeat: no-repeat; background-size: auto 50%; -moz-appearance: none; -webkit-appearance: none; appearance: none; } ::slotted(select.dark) { background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20256%20448%22%20enable-background%3D%22new%200%200%20256%20448%22%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E.arrow%7Bfill%3A%23ffffff%3B%7D%3C%2Fstyle%3E%3Cpath%20class%3D%22arrow%22%20d%3D%22M255.9%20168c0-4.2-1.6-7.9-4.8-11.2-3.2-3.2-6.9-4.8-11.2-4.8H16c-4.2%200-7.9%201.6-11.2%204.8S0%20163.8%200%20168c0%204.4%201.6%208.2%204.8%2011.4l112%20112c3.1%203.1%206.8%204.6%2011.2%204.6%204.4%200%208.2-1.5%2011.4-4.6l112-112c3-3.2%204.5-7%204.5-11.4z%22%2F%3E%3C%2Fsvg%3E%0A"); } ::slotted(select):focus { outline: none; border-color: var(--dile-input-focus-border-color, #6af); } ::slotted(select.errored) { border-color: var(--dile-input-error-border-color, #c00); } ::slotted(select.disabled) { background-color: #f5f5f5; border-color: var(--dile-input-disabled-border-color, #eee); } `]; } static get properties() { return { label: { type: String }, value: { type: String }, name: { type: String }, disabled: { type: Boolean }, errored: { type: Boolean }, message: { type: String }, hideErrorOnInput: { type: Boolean }, quietOnStart: { type: Boolean }, }; } render() { return html` <div> ${this.label ? html`<label for="textField">${this.label}</label>` : "" } <slot name="select"></slot> </div> ${this.message ? html`<div class="message ${this.errored ? 'errored-msg' : ''}"><span>${this.message}</span></div>` : '' } `; } get elselect() { return this.querySelector("select"); } constructor() { super(); this.errored = false; this.hideErrorOnInput = false; this.changeHandler = this.onChange.bind(this); this.quiet = false; } connectedCallback() { super.connectedCallback(); if (!this.elselect) { throw new Error('Use dile-select with a select element in the slot "select"'); } else { this.elselect.addEventListener("change", this.changeHandler); this.value = this.elselect.value; } } disconnectedCallback() { super.disconnectedCallback(); if (this.elselect) { this.elselect.removeEventListener("change", this.changeHandler); } } onChange(e) { this.value = e.target.value; if (this.hideErrorOnInput && this.errored) { this.errored = false; this.message = ''; } } updated(changedProperties) { if(changedProperties.has("value")) { this.elselect.value = this.value; if (this.quiet) { this.quiet = false; } else { this.emmitChange(); } } if(changedProperties.has("disabled")) { this.elselect.disabled = this.disabled; this.elselect.classList.toggle("disabled", this.disabled); } if(changedProperties.has("errored")) { this.elselect.classList.toggle("errored", this.errored); } } firstUpdated() { super.firstUpdated(); this.quiet = this.quietOnStart; if(this.value) { this.elselect.value = this.value; } else { this.value = this.elselect.value; } } clear() { this.value = undefined; } getOptionByValue(id) { let options = this.elselect.options; for(let i = 0; i < options.length; i++) { if(options[i].value === id) { return options[i]; } } } quietChange(value) { if (value != this.value) { this.quiet = true; this.value = value; } } }