From 60a7ba3b0b5ccb264dc4a9268b4e5765a681e2f8 Mon Sep 17 00:00:00 2001 From: sairaj mote Date: Mon, 15 Mar 2021 18:29:56 +0530 Subject: [PATCH] Code refactoring --- Standard UI Components/components.js | 1477 ++++++++++++++++++-------- 1 file changed, 1020 insertions(+), 457 deletions(-) diff --git a/Standard UI Components/components.js b/Standard UI Components/components.js index 7ebbf41..1008673 100644 --- a/Standard UI Components/components.js +++ b/Standard UI Components/components.js @@ -12,15 +12,18 @@ smButton.innerHTML = ` display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; + --padding: 0.6rem 1.2rem; + --border-radius: 0.3rem; + --background: rgba(var(--text-color), 0.1); } -:host([disabled]) .button{ +:host([disable]) .button{ cursor: not-allowed; - opacity: 1; + opacity: 0.6; background: rgba(var(--text-color), 0.3) !important; - color: rgba(var(--foreground-color), 1); + color: rgba(var(--foreground-color), 0.6); } :host([variant='primary']) .button{ - background: hsl(var(--hue), var(--saturation), var(--lightness)); + background: var(--accent-color); color: rgba(var(--foreground-color), 1); } :host([variant='outlined']) .button{ @@ -40,17 +43,18 @@ smButton.innerHTML = ` border-radius: 10rem; } .button { + position: relative; display: -webkit-box; display: -ms-flexbox; display: flex; width: 100%; - padding: 0.6rem 1rem; + padding: var(--padding); cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; - border-radius: 0.3rem; + border-radius: var(--border-radius); -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; @@ -60,30 +64,26 @@ smButton.innerHTML = ` transition: box-shadow 0.3s; transition: box-shadow 0.3s, -webkit-box-shadow 0.3s; text-transform: capitalize; + font-family: inherit; font-size: 0.9rem; font-weight: 500; - background: rgba(var(--text-color), 0.1); + background: var(--background); -webkit-tap-highlight-color: transparent; outline: none; + overflow: hidden; + border: none; + color: inherit; } -:host(:not([disabled])) .button:focus{ - -webkit-box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.2); - box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.2); +:host(:not([disable])) .button:focus-visible{ + -webkit-box-shadow: 0 0 0 0.1rem var(--accent-color); + box-shadow: 0 0 0 0.1rem var(--accent-color); } -:host([variant='outlined']) .button:focus{ - -webkit-box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset, 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.4rem 0.8rem rgba(0, 0, 0, 0.2); - box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset, 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.4rem 0.8rem rgba(0, 0, 0, 0.2); +:host([variant='outlined']) .button:focus-visible{ + -webkit-box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset, 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0 0 0.1rem var(--accent-color); + box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset, 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0 0 0.1rem var(--accent-color); } @media (hover: hover){ - :host(:not([disabled])) .button:active{ - -webkit-box-shadow: none !important; - box-shadow: none !important; - } - :host([variant='outlined']) .button:active{ - -webkit-box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset !important; - box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset !important; - } - :host(:not([disabled])) .button:hover{ + :host(:not([disable])) .button:hover{ -webkit-box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.12); box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.12); } @@ -91,15 +91,9 @@ smButton.innerHTML = ` -webkit-box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset, 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.4rem 0.8rem rgba(0, 0, 0, 0.12); box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset, 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.4rem 0.8rem rgba(0, 0, 0, 0.12); } - :host([variant="primary"]:not([disabled])) .button:active{ - background: hsl(var(--hue), var(--saturation), calc(var(--lightness) - 20%)) !important; - } - :host([variant="primary"]:not([disabled])) .button:hover{ - background: hsl(var(--hue), var(--saturation), calc(var(--lightness) - 10%)); - } } @media (hover: none){ - :host(:not([disabled])) .button:active{ + :host(:not([disable])) .button:active{ -webkit-box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.2); box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.2); } @@ -109,9 +103,9 @@ smButton.innerHTML = ` } } -
+
`; +`; customElements.define('sm-button', class extends HTMLElement { constructor() { @@ -128,17 +122,17 @@ customElements.define('sm-button', set disabled(value) { if (value && !this.isDisabled) { this.isDisabled = true - this.setAttribute('disabled', '') + this.setAttribute('disable', '') this.button.removeAttribute('tabindex') } else if (!value && this.isDisabled) { this.isDisabled = false - this.removeAttribute('disabled') + this.removeAttribute('disable') } } dispatch() { if (this.isDisabled) { - this.dispatchEvent(new CustomEvent('disabled', { + this.dispatchEvent(new CustomEvent('disable', { bubbles: true, composed: true })) @@ -153,15 +147,11 @@ customElements.define('sm-button', connectedCallback() { this.isDisabled = false this.button = this.shadowRoot.querySelector('.button') - if (this.hasAttribute('disabled') && !this.isDisabled) + if (this.hasAttribute('disable') && !this.isDisabled) this.isDisabled = true this.addEventListener('click', (e) => { this.dispatch() }) - this.addEventListener('keyup', (e) => { - if (e.code === "Enter" || e.code === "Space") - this.dispatch() - }) } }) @@ -205,6 +195,10 @@ border: none; display: -webkit-box; display: -ms-flexbox; display: flex; + --font-size: 1rem; + --border-radius: 0.3rem; + --padding: 0.7rem 1rem; + --background: rgba(var(--text-color), 0.06); } .hide{ opacity: 0 !important; @@ -214,19 +208,14 @@ border: none; display: none; } .icon { - fill: none; - height: 1.6em; - width: 1.6em; - padding: 0.5em; - stroke: rgba(var(--text-color), 0.7); - stroke-width: 10; - overflow: visible; - stroke-linecap: round; - border-radius: 1em; - stroke-linejoin: round; + fill: rgba(var(--text-color), 0.6); + height: 1.4rem; + width: 1.4rem; + border-radius: 1rem; cursor: pointer; min-width: 0; } + :host(.round) .input{ border-radius: 10rem; } @@ -234,51 +223,42 @@ border: none; display: -webkit-box; display: -ms-flexbox; display: flex; + cursor: text; + min-width: 0; + text-align: left; -webkit-box-align: center; -ms-flex-align: center; align-items: center; - text-align: left; position: relative; - gap: 1em; - padding: 0.7em 1em; - border-radius: 0.3em; + gap: 0.5rem; + padding: var(--padding); + border-radius: var(--border-radius); -webkit-transition: opacity 0.3s; -o-transition: opacity 0.3s; transition: opacity 0.3s; - background: rgba(var(--text-color), 0.06); - -webkit-box-shadow: 0 0 0.2rem rgba(var(--text-color), 0.2) inset; - box-shadow: 0 0 0.2rem rgba(var(--text-color), 0.2) inset; - font-family: var(--font-family); + background: var(--background); width: 100%; outline: none; - min-width: 0; } .input.readonly .clear{ opacity: 0 !important; + margin-right: -2rem; pointer-events: none !important; } .readonly{ pointer-events: none; } -input:focus{ - caret-color: var(--accent-color); -} .input:focus-within:not(.readonly){ - -webkit-box-shadow: 0 0 0 0.1em var(--accent-color) inset; - box-shadow: 0 0 0 0.1em var(--accent-color) inset; + box-shadow: 0 0 0 0.1rem var(--accent-color) inset !important; } .disabled{ pointer-events: none; opacity: 0.6; } .label { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; opacity: .7; font-weight: 400; - font-size: 1em; + font-size: var(--font-size); position: absolute; top: 0; -webkit-transition: -webkit-transform 0.3s; @@ -295,6 +275,7 @@ input:focus{ -o-text-overflow: ellipsis; text-overflow: ellipsis; width: 100%; + user-select: none; will-change: transform; } .outer-container{ @@ -315,38 +296,53 @@ input:focus{ flex: 1; } input{ - font-size: 1em; + font-size: var(--font-size); border: none; background: transparent; outline: none; color: rgba(var(--text-color), 1); width: 100%; } -.animate-label .container input { - -webkit-transform: translateY(0.6em); - -ms-transform: translateY(0.6em); - transform: translateY(0.6em); +:host(:not(.outlined)) .animate-label .container input { + -webkit-transform: translateY(0.6rem); + -ms-transform: translateY(0.6rem); + transform: translateY(0.6rem); } -.animate-label .container .label { - -webkit-transform: translateY(-0.6em) scale(0.8); - -ms-transform: translateY(-0.6em) scale(0.8); - transform: translateY(-0.6em) scale(0.8); +:host(:not(.outlined)) .animate-label .label { + -webkit-transform: translateY(-0.7em) scale(0.8); + -ms-transform: translateY(-0.7em) scale(0.8); + transform: translateY(-0.7em) scale(0.8); opacity: 1; color: var(--accent-color) } -.helper-text{ - top: 100%; - width: 100%; - position: absolute; - color: var(--error-color); +:host(.outlined) .input { + box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 0.4) inset; background: rgba(var(--foreground-color), 1); - margin-top: 0.5em; - border-radius: 0.2em; - border: solid 1px rgba(var(--text-color), 0.2); - padding: 0.6em 1em; } -.helper-text:empty{ +:host(.outlined) .label { + width: max-content; + margin-left: -0.5rem; + padding: 0 0.5rem; +} +:host(.outlined) .animate-label .label { + -webkit-transform: translate(0.1rem, -1.5rem) scale(0.8); + -ms-transform: translate(0.1rem, -1.5rem) scale(0.8); + transform: translate(0.1rem, -1.5rem) scale(0.8); + opacity: 1; + background: rgba(var(--foreground-color), 1); +} +.animate-label:focus-within:not(.readonly) .label{ + color: var(--accent-color) +} +.feedback-text{ + font-size: 0.9rem; + width: 100%; + color: var(--error-color); + padding: 0.6rem 1rem; + text-align: left; +} +.feedback-text:empty{ padding: 0; } @media (any-hover: hover){ @@ -362,23 +358,23 @@ input{
- - clear - - - + -
+
`; customElements.define('sm-input', class extends HTMLElement { + + static formAssociated = true; + constructor() { super() this.attachShadow({ mode: 'open' }).append(smInput.content.cloneNode(true)) } + static get observedAttributes() { return ['placeholder'] } @@ -409,6 +405,10 @@ customElements.define('sm-input', return this.shadowRoot.querySelector('input').checkValidity() } + get validity() { + return this.shadowRoot.querySelector('input').validity + } + set disabled(value) { if (value) this.shadowRoot.querySelector('.input').classList.add('disabled') @@ -425,6 +425,18 @@ customElements.define('sm-input', } } + setValidity = (message) => { + this.feedbackText.textContent = message + } + + showValidity = () => { + this.feedbackText.classList.remove('hide-completely') + } + + hideValidity = () => { + this.feedbackText.classList.add('hide-completely') + } + focusIn = () => { this.input.focus() } @@ -433,13 +445,6 @@ customElements.define('sm-input', this.input.blur() } - preventNonNumericalInput = (e) => { - let keyCode = e.keyCode; - if (!((keyCode > 47 && keyCode < 56) || (keyCode > 36 && keyCode < 39) || (keyCode > 95 && keyCode < 106) || keyCode === 110 || (keyCode > 7 && keyCode < 19))) { - e.preventDefault(); - } - } - fireEvent = () => { let event = new Event('input', { bubbles: true, @@ -450,22 +455,24 @@ customElements.define('sm-input', } checkInput = (e) => { - if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder') === '') - return; + if (!this.readonly) { + if (this.input.value !== '') { + this.clearBtn.classList.remove('hide') + } else { + this.clearBtn.classList.add('hide') + } + } + if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder') === '') return; if (this.input.value !== '') { if (this.animate) this.inputParent.classList.add('animate-label') else this.label.classList.add('hide') - if (!this.readonly) - this.clearBtn.classList.remove('hide') } else { if (this.animate) this.inputParent.classList.remove('animate-label') else this.label.classList.remove('hide') - if (!this.readonly) - this.clearBtn.classList.add('hide') } } @@ -474,9 +481,10 @@ customElements.define('sm-input', this.inputParent = this.shadowRoot.querySelector('.input') this.clearBtn = this.shadowRoot.querySelector('.clear') this.label = this.shadowRoot.querySelector('.label') - this.helperText = this.shadowRoot.querySelector('.helper-text') + this.feedbackText = this.shadowRoot.querySelector('.feedback-text') this.valueChanged = false; this.readonly = false + this.isNumeric = false this.min this.max this.animate = this.hasAttribute('animate') @@ -500,13 +508,17 @@ customElements.define('sm-input', this.max = parseInt(maxValue) } if (this.hasAttribute('minlength')) { - let minValue = this.getAttribute('minlength') + const minValue = this.getAttribute('minlength') this.input.setAttribute('minlength', minValue) } if (this.hasAttribute('maxlength')) { - let maxValue = this.getAttribute('maxlength') + const maxValue = this.getAttribute('maxlength') this.input.setAttribute('maxlength', maxValue) } + if (this.hasAttribute('step')) { + const steps = this.getAttribute('step') + this.input.setAttribute('step', steps) + } if (this.hasAttribute('pattern')) { this.input.setAttribute('pattern', this.getAttribute('pattern')) } @@ -517,23 +529,20 @@ customElements.define('sm-input', if (this.hasAttribute('disabled')) { this.inputParent.classList.add('disabled') } - if (this.hasAttribute('helper-text')) { - this.helperText.textContent = this.getAttribute('helper-text') + if (this.hasAttribute('error-text')) { + this.feedbackText.textContent = this.getAttribute('error-text') } if (this.hasAttribute('type')) { if (this.getAttribute('type') === 'number') { this.input.setAttribute('inputmode', 'numeric') this.input.setAttribute('type', 'number') + this.isNumeric = true } else this.input.setAttribute('type', this.getAttribute('type')) } else this.input.setAttribute('type', 'text') - this.input.addEventListener('keydown', e => { - if (this.getAttribute('type') === 'number') - this.preventNonNumericalInput(e); - }) this.input.addEventListener('input', e => { - this.checkInput() + this.checkInput(e) }) this.clearBtn.addEventListener('click', e => { this.value = '' @@ -554,7 +563,9 @@ customElements.define('sm-input', const smTextarea = document.createElement('template') smTextarea.innerHTML = ` -` customElements.define('sm-checkbox', class extends HTMLElement { constructor() { @@ -977,27 +904,58 @@ customElements.define('sm-checkbox', class extends HTMLElement { } get checked() { - return this.getAttribute('checked') + return this.isChecked } set checked(value) { - this.setAttribute('checked', value) + if (value) { + this.setAttribute('checked', '') + } + else { + this.removeAttribute('checked') + } } - dispatch() { + set value(val) { + this.val = val + this.setAttribute('value', value) + } + + get value() { + return getAttribute('value') + } + + dispatch = () => { this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })) } - - connectedCallback() { - this.addEventListener('keyup', e => { - if ((e.code === "Enter" || e.code === "Space") && this.isDisabled == false) { - this.isChecked = !this.isChecked - this.setAttribute('checked', this.isChecked) + handleKeyup = e => { + if ((e.code === "Enter" || e.code === "Space") && this.isDisabled == false) { + if (this.hasAttribute('checked')) { + this.input.checked = false + this.removeAttribute('checked') } - }) + else { + this.input.checked = true + this.setAttribute('checked', '') + } + } + } + handleChange = e => { + if (this.input.checked) { + this.setAttribute('checked', '') + } + else { + this.removeAttribute('checked') + } + } + + connectedCallback() { + this.val = '' + this.addEventListener('keyup', this.handleKeyup) + this.input.addEventListener('change', this.handleChange) } attributeChangedCallback(name, oldValue, newValue) { if (oldValue !== newValue) { @@ -1010,20 +968,23 @@ customElements.define('sm-checkbox', class extends HTMLElement { this.isDisabled = false } } - if (name === 'checked') { - if (newValue == 'true') { + else if (name === 'checked') { + if (this.hasAttribute('checked')) { this.isChecked = true this.input.checked = true - this.dispatch() - } else { - this.isChecked = false - this.input.checked = false - this.dispatch() } + else { + this.input.checked = false + this.isChecked = false + } + this.dispatch() } } } - + disconnectedCallback() { + this.removeEventListener('keyup', this.handleKeyup) + this.removeEventListener('change', this.handleChange) + } }) //switch @@ -1043,6 +1004,22 @@ smSwitch.innerHTML = ` display: -ms-inline-flexbox; display: inline-flex; } + label{ + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + outline: none; + cursor: pointer; + -webkit-tap-highlight-color: transparent; + } + :host(:not([disable])) label:focus-visible{ + -webkit-box-shadow: 0 0 0 0.1rem var(--accent-color); + box-shadow: 0 0 0 0.1rem var(--accent-color); + } .switch { position: relative; display: -webkit-box; @@ -1052,11 +1029,11 @@ smSwitch.innerHTML = ` -ms-flex-align: center; align-items: center; width: 2.4rem; + flex-shrink: 0; + margin-left: auto; padding: 0.2rem; cursor: pointer; - outline: none; border-radius: 2rem; - -webkit-tap-highlight-color: transparent; } input { @@ -1081,9 +1058,6 @@ smSwitch.innerHTML = ` .switch:focus .button::after{ opacity: 1 } - .switch:focus:not(:focus-visible){ - opacity: 0; - } .switch:focus-visible .button::after{ opacity: 1 } @@ -1125,7 +1099,7 @@ smSwitch.innerHTML = ` -o-transition: transform 0.3s; transition: transform 0.3s; transition: transform 0.3s, -webkit-transform 0.3s; - border: solid 0.3rem rgba(var(--foreground-color), 1); + border: solid 0.3rem white; } input:checked ~ .button { @@ -1142,10 +1116,13 @@ smSwitch.innerHTML = ` pointer-events: none; } -