UNPKG

@skhemata/skhemata-form

Version:

Skhemata Form Web Component. This web component can be used as base web component when working with forms and inputs.

237 lines (236 loc) 7.69 kB
import { __decorate } from "tslib"; import { html, css, property } from '@skhemata/skhemata-base'; import { faAngleDown } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@riovir/wc-fontawesome'; import { SkhemataFormInput } from './SkhemataFormInput'; export class SkhemataFormDropdown extends SkhemataFormInput { static get styles() { return [ ...super.styles, css ` .field { margin-bottom: 1rem; } ::slotted(*), .placeholder { text-align: left; padding: 0.5rem 0rem 0.5rem 1rem; white-space: nowrap; } ::slotted(*:hover), .placeholder:hover { background-color: whitesmoke; color: rgb(10, 10, 10); cursor: pointer; } .dropdown, .dropdown-trigger, .dropdown button { width: 100%; } .dropdown button span { margin-right: auto; } .dropdown .button { color: #d0d0d0; } `, ]; } static get scopedElements() { return { 'fa-icon': FontAwesomeIcon, }; } horizontal = false; description = ''; selected = ''; label = ''; menuOpen = false; required = false; name = 'name'; placeholder = 'Select One'; errorMessage = 'Select one'; submitOnSelect = false; valid = true; helpClass = ''; reset() { this.clearError(); this.setDefaultValue(); } validate() { this.helpClass = ''; if (this.required && (!this.value || this.value.length < 1)) { this.valid = false; this.helpClass = 'is-danger'; this.requestUpdate(); } this.dispatchEvent(new CustomEvent('is-valid', { detail: { valid: this.valid }, bubbles: true, composed: true, })); } clearError() { this.helpClass = ''; this.valid = true; this.requestUpdate(); } setDefaultValue(value) { const slot = this.shadowRoot?.querySelector('slot:not([name="placeholder"])'); const childNodes = slot?.assignedNodes({ flatten: true }); const children = childNodes ? Array.prototype.filter.call(childNodes, node => node.nodeType === Node.ELEMENT_NODE) : []; if (children && children.length > 0 && !this.placeholder) { this.placeholder = ''; if (value) { const initialOption = children.filter(child => child.value == value)[0]; this.value = initialOption?.value; this.selected = initialOption?.innerHTML; } else { this.selected = children[0].innerHTML; this.value = children[0].value; } } else if (value) { const initialOption = children.filter(child => child.value == value)[0]; this.value = initialOption?.value; this.selected = initialOption?.innerHTML; } else { this.selected = this.placeholder || ''; this.value = ''; } this.requestUpdate(); } async firstUpdated() { this.setDefaultValue(this.value); await super.firstUpdated(); } handleKeydown(event) { if (event.keyCode === '13') { if (!event.target.value) { this.reset(); } else { this.handleSelectValue(event); } } } handleSelectValue(event) { this.clearError(); this.selected = event.target.innerHTML; this.value = event.target.value; } toggleMenu() { this.menuOpen = !this.menuOpen; this.requestUpdate(); } render() { const field = html ` <div class="field"> ${this.label && !this.horizontal ? html `<label class="label">${this.label} ${this.required ? html `<span style="color: red">*</span>` : null}</label>` : null} <div class="control ${this.valid ? '' : 'has-icons-right'}"> ${this.description && !this.horizontal ? html `<p>${this.description}</p>` : null} <div class="dropdown ${this.menuOpen ? 'is-active' : ''}" @click=${this.toggleMenu} @keydown=${(event) => { if (event.keyCode === '13') this.toggleMenu(); }} > <div class="dropdown-trigger"> <button class="button" aria-haspopup="true" aria-controls="dropdown-menu" > <span>${this.selected || this.placeholder}</span> <span class="icon is-small"> <fa-icon .icon=${faAngleDown}></fa-icon> </span> </button> </div> <div class="dropdown-menu" id="dropdown-menu" role="menu"> <div class="dropdown-content"> ${this.placeholder ? html `<option class="placeholder" @click=${this.reset} @keydown=${this.handleKeydown} > ${this.placeholder} </option>` : ``} <slot @click=${this.handleSelectValue} @keydown=${this.handleKeydown} ></slot> </div> </div> </div> </div> ${!this.valid ? html `<p class="help ${this.helpClass}">${this.errorMessage}</p>` : ``} </div> `; const horizontalFieldLabel = html ` <div class="field-label column is-one-quarter" style="text-align: left"> ${this.label ? html `<label class="label">${this.label} ${this.required ? html `<span style="color: red">*</span>` : null}</label>` : null} ${this.description ? html `<p>${this.description}</p>` : null} </div> `; const horizontalField = html ` <div class="field is-horizontal"> ${this.label || this.description ? horizontalFieldLabel : null} <div class="field-body column">${field}</div> </div> `; return this.horizontal ? horizontalField : field; } } __decorate([ property({ type: Boolean }) ], SkhemataFormDropdown.prototype, "horizontal", void 0); __decorate([ property({ type: String }) ], SkhemataFormDropdown.prototype, "description", void 0); __decorate([ property({ type: String }) ], SkhemataFormDropdown.prototype, "selected", void 0); __decorate([ property({ type: String }) ], SkhemataFormDropdown.prototype, "label", void 0); __decorate([ property({ type: Boolean }) ], SkhemataFormDropdown.prototype, "menuOpen", void 0); __decorate([ property({ type: Boolean }) ], SkhemataFormDropdown.prototype, "required", void 0); __decorate([ property({ type: String }) ], SkhemataFormDropdown.prototype, "name", void 0); __decorate([ property({ type: String }) ], SkhemataFormDropdown.prototype, "placeholder", void 0); __decorate([ property({ type: String }) ], SkhemataFormDropdown.prototype, "errorMessage", void 0); __decorate([ property({ type: Boolean }) ], SkhemataFormDropdown.prototype, "submitOnSelect", void 0); __decorate([ property({ type: Boolean }) ], SkhemataFormDropdown.prototype, "valid", void 0); __decorate([ property({ type: String }) ], SkhemataFormDropdown.prototype, "helpClass", void 0); //# sourceMappingURL=SkhemataFormDropdown.js.map