From 5c3d8359ddb111c7f5aa76d30d5b48625750aa0b Mon Sep 17 00:00:00 2001 From: sairaj mote Date: Sat, 10 Jul 2021 17:03:54 +0530 Subject: [PATCH] directory name change --- Standard UI Components/components.js | 4124 ----------------- Standard UI Components/components.min.js | 1 - Standard UI Components/components.ts | 3591 -------------- Standard UI Components/tsconfig.json | 11 - .../.gitattributes | 0 .../README.md | 1190 ++--- .../_config.yml | 0 .../css/main.css | 0 .../css/main.css.map | 0 .../css/main.min.css | 0 .../css/main.scss | 980 ++-- .../dist/button.js | 0 .../dist/button.min.js | 0 .../dist/carousel.js | 0 .../dist/carousel.min.js | 0 .../dist/checkbox.js | 0 .../dist/checkbox.min.js | 0 .../dist/copy.js | 0 .../dist/copy.min.js | 0 .../dist/file-input.js | 0 .../dist/file-input.min.js | 0 .../dist/form.js | 0 .../dist/form.min.js | 0 .../dist/input.js | 0 .../dist/input.min.js | 0 .../dist/menu.js | 0 .../dist/menu.min.js | 0 .../dist/notifications.js | 0 .../dist/notifications.min.js | 0 .../dist/popup.js | 0 .../dist/popup.min.js | 0 .../dist/radio.js | 0 .../dist/radio.min.js | 0 .../dist/select.js | 0 .../dist/select.min.js | 0 .../dist/strip-select.js | 0 .../dist/strip-select.min.js | 0 .../dist/switch.js | 0 .../dist/switch.min.js | 0 .../dist/tabs.js | 0 .../dist/tabs.min.js | 0 .../dist/tags-input.js | 0 .../dist/tags-input.min.js | 0 .../dist/textarea.js | 0 .../dist/textarea.min.js | 0 .../index.html | 1896 ++++---- .../prettify.js | 0 .../resources/artwork1.svg | 0 .../resources/artwork2.svg | 0 .../resources/background.jpg | Bin .../resources/background2.jpg | Bin .../resources/background3.jpg | Bin .../resources/background4.jpg | Bin .../resources/background5.jpg | Bin .../resources/background6.jpg | Bin 55 files changed, 2033 insertions(+), 9760 deletions(-) delete mode 100644 Standard UI Components/components.js delete mode 100644 Standard UI Components/components.min.js delete mode 100644 Standard UI Components/components.ts delete mode 100644 Standard UI Components/tsconfig.json rename {Standard UI Components => components}/.gitattributes (100%) rename {Standard UI Components => components}/README.md (96%) rename {Standard UI Components => components}/_config.yml (100%) rename {Standard UI Components => components}/css/main.css (100%) rename {Standard UI Components => components}/css/main.css.map (100%) rename {Standard UI Components => components}/css/main.min.css (100%) rename {Standard UI Components => components}/css/main.scss (95%) rename {Standard UI Components => components}/dist/button.js (100%) rename {Standard UI Components => components}/dist/button.min.js (100%) rename {Standard UI Components => components}/dist/carousel.js (100%) rename {Standard UI Components => components}/dist/carousel.min.js (100%) rename {Standard UI Components => components}/dist/checkbox.js (100%) rename {Standard UI Components => components}/dist/checkbox.min.js (100%) rename {Standard UI Components => components}/dist/copy.js (100%) rename {Standard UI Components => components}/dist/copy.min.js (100%) rename {Standard UI Components => components}/dist/file-input.js (100%) rename {Standard UI Components => components}/dist/file-input.min.js (100%) rename {Standard UI Components => components}/dist/form.js (100%) rename {Standard UI Components => components}/dist/form.min.js (100%) rename {Standard UI Components => components}/dist/input.js (100%) rename {Standard UI Components => components}/dist/input.min.js (100%) rename {Standard UI Components => components}/dist/menu.js (100%) rename {Standard UI Components => components}/dist/menu.min.js (100%) rename {Standard UI Components => components}/dist/notifications.js (100%) rename {Standard UI Components => components}/dist/notifications.min.js (100%) rename {Standard UI Components => components}/dist/popup.js (100%) rename {Standard UI Components => components}/dist/popup.min.js (100%) rename {Standard UI Components => components}/dist/radio.js (100%) rename {Standard UI Components => components}/dist/radio.min.js (100%) rename {Standard UI Components => components}/dist/select.js (100%) rename {Standard UI Components => components}/dist/select.min.js (100%) rename {Standard UI Components => components}/dist/strip-select.js (100%) rename {Standard UI Components => components}/dist/strip-select.min.js (100%) rename {Standard UI Components => components}/dist/switch.js (100%) rename {Standard UI Components => components}/dist/switch.min.js (100%) rename {Standard UI Components => components}/dist/tabs.js (100%) rename {Standard UI Components => components}/dist/tabs.min.js (100%) rename {Standard UI Components => components}/dist/tags-input.js (100%) rename {Standard UI Components => components}/dist/tags-input.min.js (100%) rename {Standard UI Components => components}/dist/textarea.js (100%) rename {Standard UI Components => components}/dist/textarea.min.js (100%) rename {Standard UI Components => components}/index.html (97%) rename {Standard UI Components => components}/prettify.js (100%) rename {Standard UI Components => components}/resources/artwork1.svg (100%) rename {Standard UI Components => components}/resources/artwork2.svg (100%) rename {Standard UI Components => components}/resources/background.jpg (100%) rename {Standard UI Components => components}/resources/background2.jpg (100%) rename {Standard UI Components => components}/resources/background3.jpg (100%) rename {Standard UI Components => components}/resources/background4.jpg (100%) rename {Standard UI Components => components}/resources/background5.jpg (100%) rename {Standard UI Components => components}/resources/background6.jpg (100%) diff --git a/Standard UI Components/components.js b/Standard UI Components/components.js deleted file mode 100644 index 2cac250..0000000 --- a/Standard UI Components/components.js +++ /dev/null @@ -1,4124 +0,0 @@ -/*jshint esversion: 6 */ -//Button -const smButton = document.createElement('template') -smButton.innerHTML = ` - -`; -customElements.define('sm-button', - class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smButton.content.cloneNode(true)) - } - - get disabled() { - return this.isDisabled - } - - set disabled(value) { - if (value && !this.isDisabled) { - this.isDisabled = true - this.setAttribute('disabled', '') - this.button.removeAttribute('tabindex') - } else if (!value && this.isDisabled) { - this.isDisabled = false - this.removeAttribute('disabled') - } - } - - dispatch() { - if (this.isDisabled) { - this.dispatchEvent(new CustomEvent('disabled', { - bubbles: true, - composed: true - })) - } else { - this.dispatchEvent(new CustomEvent('clicked', { - bubbles: true, - composed: true - })) - } - } - - connectedCallback() { - this.isDisabled = false - this.button = this.shadowRoot.querySelector('.button') - if (this.hasAttribute('disabled') && !this.isDisabled) - this.isDisabled = true - this.addEventListener('click', (e) => { - this.dispatch() - }) - } - }) - -//Input -const smInput = document.createElement('template') -smInput.innerHTML = ` - -
- - -
-`; -customElements.define('sm-input', - class extends HTMLElement { - - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smInput.content.cloneNode(true)) - - this.inputParent = this.shadowRoot.querySelector('.input') - this.input = this.shadowRoot.querySelector('input') - this.clearBtn = this.shadowRoot.querySelector('.clear') - this.label = this.shadowRoot.querySelector('.label') - this.feedbackText = this.shadowRoot.querySelector('.feedback-text') - this.validationFunction - this.observeList = ['type', 'required', 'disabled', 'readonly', 'min', 'max', 'pattern', 'minlength', 'maxlength', 'step'] - } - - static get observedAttributes() { - return ['placeholder', 'type', 'required', 'disabled', 'readonly', 'min', 'max', 'pattern', 'minlength', 'maxlength', 'step'] - } - - get value() { - return this.input.value - } - - set value(val) { - this.input.value = val; - this.checkInput() - this.fireEvent() - } - - get placeholder() { - return this.getAttribute('placeholder') - } - - set placeholder(val) { - this.setAttribute('placeholder', val) - } - - get type() { - return this.getAttribute('type') - } - - set type(val) { - this.setAttribute('type', val) - } - - get isValid() { - if (this.hasAttribute('data-flo-id') || this.hasAttribute('data-private-key')) { - return this.validationFunction(this.input.value) - } - else { - return this.input.checkValidity() - } - } - - get validity() { - return this.input.validity - } - - set disabled(value) { - if (value) - this.inputParent.classList.add('disabled') - else - this.inputParent.classList.remove('disabled') - } - set readOnly(value) { - if (value) { - this.setAttribute('readonly', '') - } else { - this.removeAttribute('readonly') - } - } - set customValidation(val) { - this.validationFunction = val - } - reset = () => { - this.value = '' - } - - setValidity = (message) => { - this.feedbackText.textContent = message - } - - showValidity = () => { - this.feedbackText.classList.remove('hide-completely') - } - - hideValidity = () => { - this.feedbackText.classList.add('hide-completely') - } - - focusIn = () => { - this.input.focus() - } - - focusOut = () => { - this.input.blur() - } - - fireEvent = () => { - let event = new Event('input', { - bubbles: true, - cancelable: true, - composed: true - }); - this.dispatchEvent(event); - } - - checkInput = (e) => { - if (!this.hasAttribute('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') - } else { - if (this.animate) - this.inputParent.classList.remove('animate-label') - else - this.label.classList.remove('hide') - } - } - - - connectedCallback() { - this.animate = this.hasAttribute('animate') - if (this.hasAttribute('value')) { - this.input.value = this.getAttribute('value') - this.checkInput() - } - if (this.hasAttribute('error-text')) { - this.feedbackText.textContent = this.getAttribute('error-text') - } - if (!this.hasAttribute('type')) { - this.setAttribute('type', 'text') - } - - this.input.addEventListener('input', e => { - this.checkInput(e) - }) - this.clearBtn.addEventListener('click', this.reset) - } - - attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - if (this.observeList.includes(name)) { - if (this.hasAttribute(name)) { - this.input.setAttribute(name, this.getAttribute(name) ? this.getAttribute(name) : '') - } - else { - this.input.removeAttribute(name) - } - } - if (name === 'placeholder') { - this.label.textContent = newValue; - this.setAttribute('aria-label', newValue); - } - else if (name === 'type') { - if (this.hasAttribute('type') && this.getAttribute('type') === 'number') { - this.input.setAttribute('inputmode', 'numeric') - } - } - else if (name === 'readonly') { - if (this.hasAttribute('readonly')) { - this.inputParent.classList.add('readonly') - } else { - this.inputParent.classList.remove('readonly') - } - } - else if (name === 'disabled') { - if (this.hasAttribute('disabled')) { - this.inputParent.classList.add('disabled') - } - else { - this.inputParent.classList.remove('disabled') - } - } - } - } - }) - -//textarea -const smTextarea = document.createElement('template') -smTextarea.innerHTML = ` - - -`; -customElements.define('sm-textarea', - class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smTextarea.content.cloneNode(true)) - - this.textarea = this.shadowRoot.querySelector('textarea') - this.textareaBox = this.shadowRoot.querySelector('.textarea') - this.placeholder = this.shadowRoot.querySelector('.placeholder') - this.observeList = ['required', 'readonly', 'rows', 'minlength', 'maxlength'] - } - static get observedAttributes() { - return ['value', 'placeholder', 'required', 'readonly', 'rows', 'minlength', 'maxlength'] - } - get value() { - return this.textarea.value - } - set value(val) { - this.setAttribute('value', val) - this.fireEvent() - } - get isValid() { - return this.textarea.checkValidity() - } - reset = () => { - this.setAttribute('value', '') - } - focusIn = () => { - this.textarea.focus() - } - fireEvent = () => { - let event = new Event('input', { - bubbles: true, - cancelable: true, - composed: true - }); - this.dispatchEvent(event); - } - checkInput = () => { - if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder') === '') - return; - if (this.textarea.value !== '') { - this.placeholder.classList.add('hide') - } else { - this.placeholder.classList.remove('hide') - } - } - connectedCallback() { - this.textarea.addEventListener('input', e => { - this.textareaBox.dataset.value = this.textarea.value - this.checkInput() - }) - } - attributeChangedCallback(name, oldValue, newValue) { - if (this.observeList.includes(name)) { - if (this.hasAttribute(name)) { - this.textarea.setAttribute(name, this.getAttribute(name) ? this.getAttribute(name) : '') - } - else { - this.input.removeAttribute(name) - } - } - else if (name === 'placeholder') { - this.placeholder.textContent = this.getAttribute('placeholder') - } - else if (name === 'value') { - this.textarea.value = newValue; - this.textareaBox.dataset.value = newValue - this.checkInput() - } - } - }) - -//chcekbox - -const smCheckbox = document.createElement('template') -smCheckbox.innerHTML = ` - -` -customElements.define('sm-checkbox', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smCheckbox.content.cloneNode(true)) - - this.checkbox = this.shadowRoot.querySelector('.checkbox'); - this.input = this.shadowRoot.querySelector('input') - - this.isChecked = false - this.isDisabled = false - } - - static get observedAttributes() { - return ['disabled', 'checked'] - } - - get disabled() { - return this.isDisabled - } - - set disabled(val) { - if (val) { - this.setAttribute('disabled', '') - } else { - this.removeAttribute('disabled') - } - } - - get checked() { - return this.isChecked - } - - set checked(value) { - if (value) { - this.setAttribute('checked', '') - } - else { - this.removeAttribute('checked') - } - } - - 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 - })) - } - 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) { - if (name === 'disabled') { - if (newValue === 'true') { - this.isDisabled = true - } else { - this.isDisabled = false - } - } - else if (name === 'checked') { - if (this.hasAttribute('checked')) { - this.isChecked = true - this.input.checked = true - } - else { - this.input.checked = false - this.isChecked = false - } - this.dispatch() - } - } - } - disconnectedCallback() { - this.removeEventListener('keyup', this.handleKeyup) - this.removeEventListener('change', this.handleChange) - } -}) - -//switch - -const smSwitch = document.createElement('template') -smSwitch.innerHTML = ` - -` - -customElements.define('sm-switch', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smSwitch.content.cloneNode(true)) - this.switch = this.shadowRoot.querySelector('.switch'); - this.input = this.shadowRoot.querySelector('input') - this.isChecked = false - this.isDisabled = false - } - - static get observedAttributes() { - return ['disabled', 'checked'] - } - - get disabled() { - return this.isDisabled - } - - set disabled(val) { - if (val) { - this.setAttribute('disabled', '') - } else { - this.removeAttribute('disabled') - } - } - - get checked() { - return this.isChecked - } - - set checked(value) { - if (value) { - this.setAttribute('checked', '') - } else { - this.removeAttribute('checked') - } - } - - dispatch = () => { - this.dispatchEvent(new CustomEvent('change', { - bubbles: true, - composed: true, - detail: { - value: this.isChecked - } - })) - } - - connectedCallback() { - this.addEventListener('keyup', e => { - if ((e.code === "Enter" || e.code === "Space") && !this.isDisabled) { - this.input.click() - } - }) - this.input.addEventListener('click', e => { - if (this.input.checked) - this.checked = true - else - this.checked = false - this.dispatch() - }) - } - attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - if (name === 'disabled') { - if (this.hasAttribute('disabled')) { - this.disabled = true - } - else { - this.disabled = false - } - } - else if (name === 'checked') { - if (this.hasAttribute('checked')) { - this.isChecked = true - this.input.checked = true - } - else { - this.isChecked = false - this.input.checked = false - } - } - } - } - -}) - -// select -const smSelect = document.createElement('template') -smSelect.innerHTML = ` - -
-
-
- - - -
-
- -
-
`; -customElements.define('sm-select', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smSelect.content.cloneNode(true)) - } - static get observedAttributes() { - return ['value'] - } - get value() { - return this.getAttribute('value') - } - set value(val) { - this.setAttribute('value', val) - } - - reset = () => { - - } - - collapse() { - this.chevron.classList.remove('rotate') - this.optionList.animate(this.slideUp, this.animationOptions) - .onfinish = () => { - this.optionList.classList.add('hide') - this.open = false - } - } - connectedCallback() { - this.availableOptions - this.optionList = this.shadowRoot.querySelector('.options') - this.chevron = this.shadowRoot.querySelector('.toggle') - let slot = this.shadowRoot.querySelector('.options slot'), - selection = this.shadowRoot.querySelector('.selection'), - previousOption - this.open = false; - this.slideDown = [{ - transform: `translateY(-0.5rem)`, - opacity: 0 - }, - { - transform: `translateY(0)`, - opacity: 1 - } - ] - this.slideUp = [{ - transform: `translateY(0)`, - opacity: 1 - }, - { - transform: `translateY(-0.5rem)`, - opacity: 0 - } - ] - this.animationOptions = { - duration: 300, - fill: "forwards", - easing: 'ease' - } - selection.addEventListener('click', e => { - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.animate(this.slideDown, this.animationOptions) - this.chevron.classList.add('rotate') - this.open = true - } else { - this.collapse() - } - }) - selection.addEventListener('keydown', e => { - if (e.code === 'ArrowDown' || e.code === 'ArrowRight') { - e.preventDefault() - this.availableOptions[0].focus() - } - if (e.code === 'Enter' || e.code === 'Space') - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.animate(this.slideDown, this.animationOptions) - this.chevron.classList.add('rotate') - this.open = true - } else { - this.collapse() - } - }) - this.optionList.addEventListener('keydown', e => { - if (e.code === 'ArrowUp' || e.code === 'ArrowRight') { - e.preventDefault() - if (document.activeElement.previousElementSibling) { - document.activeElement.previousElementSibling.focus() - } - } - if (e.code === 'ArrowDown' || e.code === 'ArrowLeft') { - e.preventDefault() - if (document.activeElement.nextElementSibling) - document.activeElement.nextElementSibling.focus() - } - }) - this.addEventListener('optionSelected', e => { - if (previousOption !== e.target) { - this.setAttribute('value', e.detail.value) - this.shadowRoot.querySelector('.option-text').textContent = e.detail.text; - this.dispatchEvent(new CustomEvent('change', { - bubbles: true, - composed: true, - detail: { - value: e.detail.value - } - })) - if (previousOption) { - previousOption.classList.remove('check-selected') - } - previousOption = e.target; - } - if (!e.detail.switching) - this.collapse() - - e.target.classList.add('check-selected') - }) - slot.addEventListener('slotchange', e => { - this.availableOptions = slot.assignedElements() - if (this.availableOptions[0]) { - let firstElement = this.availableOptions[0]; - previousOption = firstElement; - firstElement.classList.add('check-selected') - this.setAttribute('value', firstElement.getAttribute('value')) - this.shadowRoot.querySelector('.option-text').textContent = firstElement.textContent - this.availableOptions.forEach((element, index) => { - element.setAttribute('data-rank', index + 1); - element.setAttribute('tabindex', "0"); - }) - } - }); - document.addEventListener('mousedown', e => { - if (!this.contains(e.target) && this.open) { - this.collapse() - } - }) - } -}) - -// option -const smOption = document.createElement('template') -smOption.innerHTML = ` - -
- - - - -
`; -customElements.define('sm-option', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smOption.content.cloneNode(true)) - } - - sendDetails(switching) { - let optionSelected = new CustomEvent('optionSelected', { - bubbles: true, - composed: true, - detail: { - text: this.textContent, - value: this.getAttribute('value'), - switching: switching - } - }) - this.dispatchEvent(optionSelected) - } - - connectedCallback() { - let validKey = [ - 'ArrowUp', - 'ArrowDown', - 'ArrowLeft', - 'ArrowRight' - ] - this.addEventListener('click', e => { - this.sendDetails() - }) - this.addEventListener('keyup', e => { - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - this.sendDetails(false) - } - if (validKey.includes(e.code)) { - e.preventDefault() - this.sendDetails(true) - } - }) - if (this.hasAttribute('default')) { - setTimeout(() => { - this.sendDetails() - }, 0); - } - } -}) - -// strip select -const stripSelect = document.createElement('template') -stripSelect.innerHTML = ` - -
-
- -
- -
- -
-
- -` -customElements.define('strip-select', class extends HTMLElement{ - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(stripSelect.content.cloneNode(true)) - this.stripSelect = this.shadowRoot.querySelector('.strip-select') - this.slottedOptions - this._value - this.scrollDistance - } - get value() { - return this._value - } - scrollLeft = () => { - this.stripSelect.scrollBy({ - left: -this.scrollDistance, - behavior: 'smooth' - }) - } - - scrollRight = () => { - this.stripSelect.scrollBy({ - left: this.scrollDistance, - behavior: 'smooth' - }) - } - fireEvent = () => { - this.dispatchEvent( - new CustomEvent("change", { - bubbles: true, - composed: true, - detail: { - value: this._value - } - }) - ) - } - connectedCallback() { - const slot = this.shadowRoot.querySelector('slot') - const coverLeft = this.shadowRoot.querySelector('.cover--left') - const coverRight = this.shadowRoot.querySelector('.cover--right') - const navButtonLeft = this.shadowRoot.querySelector('.nav-button--left') - const navButtonRight = this.shadowRoot.querySelector('.nav-button--right') - slot.addEventListener('slotchange', e => { - const assignedElements = slot.assignedElements() - assignedElements.forEach(elem => { - if (elem.hasAttribute('selected')) { - elem.setAttribute('active', '') - this._value = elem.value - } - }) - if (assignedElements.length > 0) { - firstOptionObserver.observe(slot.assignedElements()[0]) - lastOptionObserver.observe(slot.assignedElements()[slot.assignedElements().length - 1]) - } - else { - navButtonLeft.classList.add('hide') - navButtonRight.classList.add('hide') - coverLeft.classList.add('hide') - coverRight.classList.add('hide') - firstOptionObserver.disconnect() - lastOptionObserver.disconnect() - } - }) - const resObs = new ResizeObserver(entries => { - entries.forEach(entry => { - if(entry.contentBoxSize) { - // Firefox implements `contentBoxSize` as a single content rect, rather than an array - const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize; - - this.scrollDistance = contentBoxSize.inlineSize * 0.6 - } else { - this.scrollDistance = entry.contentRect.width * 0.6 - } - }) - }) - resObs.observe(this) - this.stripSelect.addEventListener('option-clicked', e => { - if (this._value !== e.target.value) { - this._value = e.target.value - slot.assignedElements().forEach(elem => elem.removeAttribute('active')) - e.target.setAttribute('active', '') - e.target.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" }) - this.fireEvent() - } - }) - const firstOptionObserver = new IntersectionObserver(entries => { - entries.forEach(entry => { - if (entry.isIntersecting) { - navButtonLeft.classList.add('hide') - coverLeft.classList.add('hide') - } - else { - navButtonLeft.classList.remove('hide') - coverLeft.classList.remove('hide') - } - }) - }, - { - threshold: 0.9, - root: this - }) - const lastOptionObserver = new IntersectionObserver(entries => { - entries.forEach(entry => { - if (entry.isIntersecting) { - navButtonRight.classList.add('hide') - coverRight.classList.add('hide') - } - else { - navButtonRight.classList.remove('hide') - coverRight.classList.remove('hide') - } - }) - }, - { - threshold: 0.9, - root: this - }) - navButtonLeft.addEventListener('click', this.scrollLeft) - navButtonRight.addEventListener('click', this.scrollRight) - } -}) - -//Strip option -const stripOption = document.createElement('template') -stripOption.innerHTML = ` - - -` -customElements.define('strip-option', class extends HTMLElement{ - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(stripOption.content.cloneNode(true)) - this._value - this.radioButton = this.shadowRoot.querySelector('input') - } - get value() { - return this._value - } - fireEvent = () => { - this.dispatchEvent( - new CustomEvent("option-clicked", { - bubbles: true, - composed: true, - detail: { - value: this._value - } - }) - ) - } - handleKeyDown = (e) => { - if (e.key === 'Enter' || e.key === 'Space') { - this.fireEvent() - } - } - connectedCallback() { - this._value = this.getAttribute('value') - this.addEventListener('click', this.fireEvent) - this.addEventListener('keydown', this.handleKeyDown) - } - disconnectedCallback() { - this.removeEventListener('click', this.fireEvent) - this.removeEventListener('keydown', this.handleKeyDown) - } -}) - - -//popup -const smPopup = document.createElement('template') -smPopup.innerHTML = ` - - -`; -customElements.define('sm-popup', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smPopup.content.cloneNode(true)) - - this.allowClosing = false - this.isOpen = false - } - - get open() { - return this.isOpen - } - - resumeScrolling = () => { - const scrollY = document.body.style.top; - window.scrollTo(0, parseInt(scrollY || '0') * -1); - setTimeout(() => { - document.body.style.overflow = 'auto'; - document.body.style.top= 'initial' - }, 300); - } - - show = (pinned, popupStack) => { - if (popupStack) - this.popupStack = popupStack - if (this.popupStack && !this.hasAttribute('open')) { - this.popupStack.push({ - popup: this, - permission: pinned - }) - if (this.popupStack.items.length > 1) { - this.popupStack.items[this.popupStack.items.length - 2].popup.classList.add('stacked') - } - this.dispatchEvent( - new CustomEvent("popupopened", { - bubbles: true, - detail: { - popup: this, - popupStack: this.popupStack - } - }) - ) - this.setAttribute('open', '') - this.pinned = pinned - this.isOpen = true - } - this.popupContainer.classList.remove('hide') - this.popup.style.transform = 'none'; - document.body.style.overflow = 'hidden'; - document.body.style.top= `-${window.scrollY}px` - return this.popupStack - } - hide = () => { - if (window.innerWidth < 640) - this.popup.style.transform = 'translateY(100%)'; - else - this.popup.style.transform = 'translateY(3rem)'; - this.popupContainer.classList.add('hide') - this.removeAttribute('open') - if (typeof this.popupStack !== 'undefined') { - this.popupStack.pop() - if (this.popupStack.items.length) { - this.popupStack.items[this.popupStack.items.length - 1].popup.classList.remove('stacked') - } else { - this.resumeScrolling() - } - } else { - this.resumeScrolling() - } - - if (this.inputFields.length) { - setTimeout(() => { - this.inputFields.forEach(field => { - if (field.type === 'radio' || field.tagName === 'SM-CHECKBOX') - field.checked = false - if (field.tagName === 'SM-INPUT' || field.tagName === 'TEXTAREA'|| field.tagName === 'SM-TEXTAREA') - field.value = '' - }) - }, 300); - } - setTimeout(() => { - this.dispatchEvent( - new CustomEvent("popupclosed", { - bubbles: true, - detail: { - popup: this, - popupStack: this.popupStack - } - }) - ) - this.isOpen = false - }, 300); - } - - handleTouchStart = (e) => { - this.touchStartY = e.changedTouches[0].clientY - this.popup.style.transition = 'transform 0.1s' - this.touchStartTime = e.timeStamp - } - - handleTouchMove = (e) => { - if (this.touchStartY < e.changedTouches[0].clientY) { - this.offset = e.changedTouches[0].clientY - this.touchStartY; - this.touchEndAnimataion = window.requestAnimationFrame(() => this.movePopup()) - } - /*else { - this.offset = this.touchStartY - e.changedTouches[0].clientY; - this.popup.style.transform = `translateY(-${this.offset}px)` - }*/ - } - - handleTouchEnd = (e) => { - this.touchEndTime = e.timeStamp - cancelAnimationFrame(this.touchEndAnimataion) - this.touchEndY = e.changedTouches[0].clientY - this.popup.style.transition = 'transform 0.3s' - this.threshold = this.popup.getBoundingClientRect().height * 0.3 - if (this.touchEndTime - this.touchStartTime > 200) { - if (this.touchEndY - this.touchStartY > this.threshold) { - if (this.pinned) { - this.show() - return - } else - this.hide() - } else { - this.show() - } - } else { - if (this.touchEndY > this.touchStartY) - if (this.pinned) { - this.show() - return - } - else - this.hide() - } - } - - movePopup = () => { - this.popup.style.transform = `translateY(${this.offset}px)` - } - - connectedCallback() { - this.pinned = false - this.popupStack - this.popupContainer = this.shadowRoot.querySelector('.popup-container') - this.popup = this.shadowRoot.querySelector('.popup') - this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot') - this.offset - this.popupHeader = this.shadowRoot.querySelector('.popup-top') - this.touchStartY = 0 - this.touchEndY = 0 - this.touchStartTime = 0 - this.touchEndTime = 0 - this.touchEndAnimataion; - this.threshold = this.popup.getBoundingClientRect().height * 0.3 - - if (this.hasAttribute('open')) - this.show() - this.popupContainer.addEventListener('mousedown', e => { - if (e.target === this.popupContainer && !this.pinned) { - if (this.pinned) { - this.show() - return - } else - this.hide() - } - }) - - this.popupBodySlot.addEventListener('slotchange', () => { - setTimeout(() => { - this.threshold = this.popup.getBoundingClientRect().height * 0.3 - }, 200); - this.inputFields = this.querySelectorAll('sm-input', 'sm-checkbox', 'textarea', 'sm-textarea', 'radio') - }) - - this.popupHeader.addEventListener('touchstart', (e) => { this.handleTouchStart(e) }, {passive: true}) - this.popupHeader.addEventListener('touchmove', (e) => {this.handleTouchMove(e)}, {passive: true}) - this.popupHeader.addEventListener('touchend', (e) => {this.handleTouchEnd(e)}, {passive: true}) - } - disconnectedCallback() { - this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, {passive: true}) - this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, {passive: true}) - this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, {passive: true}) - } -}) - -//carousel - -const smCarousel = document.createElement('template') -smCarousel.innerHTML = ` - - -`; - -customElements.define('sm-carousel', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smCarousel.content.cloneNode(true)) - - this.isAutoPlaying = false - this.autoPlayInterval = 5000 - this.autoPlayTimeout - this.initialTimeout - this.activeSlideNum = 0 - this.carouselItems - this.indicators - this.showIndicator = false - this.carousel = this.shadowRoot.querySelector('.carousel') - this.carouselContainer = this.shadowRoot.querySelector('.carousel-container') - this.carouselSlot = this.shadowRoot.querySelector('slot') - this.nextArrow = this.shadowRoot.querySelector('.carousel__button--right') - this.previousArrow = this.shadowRoot.querySelector('.carousel__button--left') - this.indicatorsContainer = this.shadowRoot.querySelector('.indicators') - } - - static get observedAttributes() { - return ['indicator', 'autoplay', 'interval'] - } - - scrollLeft = () => { - this.carousel.scrollBy({ - left: -this.scrollDistance, - behavior: 'smooth' - }) - } - - scrollRight = () => { - this.carousel.scrollBy({ - left: this.scrollDistance, - behavior: 'smooth' - }) - } - - handleIndicatorClick = (e) => { - if (e.target.closest('.dot')) { - const slideNum = parseInt(e.target.closest('.dot').dataset.rank) - if (this.activeSlideNum !== slideNum) { - this.showSlide(slideNum) - } - } - } - - showSlide = (slideNum) => { - this.carousel.scrollTo({ - left: (this.carouselItems[slideNum].getBoundingClientRect().left - this.carousel.getBoundingClientRect().left + this.carousel.scrollLeft), - behavior: 'smooth' - }) - } - - nextSlide = () => { - if (!this.carouselItems) return - let showSlideNo = (this.activeSlideNum + 1) < this.carouselItems.length ? this.activeSlideNum + 1 : 0 - this.showSlide(showSlideNo) - } - - autoPlay = () => { - this.nextSlide() - if (this.isAutoPlaying) { - this.autoPlayTimeout = setTimeout(() => { - this.autoPlay() - }, this.autoPlayInterval); - } - } - - startAutoPlay = () => { - this.setAttribute('autoplay', '') - } - - stopAutoPlay = () => { - this.removeAttribute('autoplay') - } - - connectedCallback() { - this.scrollDistance = this.carouselContainer.getBoundingClientRect().width / 3 - let frag = document.createDocumentFragment(); - if (this.hasAttribute('indicator')) - this.showIndicator = true - - - let firstVisible = false, - lastVisible = false - const allElementsObserver = new IntersectionObserver(entries => { - entries.forEach(entry => { - if (this.showIndicator) { - const activeRank = parseInt(entry.target.dataset.rank) - if (entry.isIntersecting) { - this.indicators[activeRank].classList.add('active') - this.activeSlideNum = activeRank - } - else - this.indicators[activeRank].classList.remove('active') - } - if (!entry.target.previousElementSibling) - if (entry.isIntersecting) { - this.previousArrow.classList.remove('expand') - firstVisible = true - } - else { - this.previousArrow.classList.add('expand') - firstVisible = false - } - if (!entry.target.nextElementSibling) - if (entry.isIntersecting) { - this.nextArrow.classList.remove('expand') - lastVisible = true - } - else { - this.nextArrow.classList.add('expand') - lastVisible = false - } - if (firstVisible && lastVisible) - this.indicatorsContainer.classList.add('hide') - else - this.indicatorsContainer.classList.remove('hide') - }) - }, { - root: this.carouselContainer, - threshold: 0.9 - }) - - const carouselObserver = new IntersectionObserver(entries => { - if (entries[0].isIntersecting) { - this.scrollDistance = this.carouselContainer.getBoundingClientRect().width / 3 - } - }) - - carouselObserver.observe(this.carouselContainer) - - this.carouselSlot.addEventListener('slotchange', e => { - this.carouselItems = this.carouselSlot.assignedElements() - this.carouselItems.forEach(item => allElementsObserver.observe(item)) - if (this.showIndicator) { - this.indicatorsContainer.innerHTML = `` - this.carouselItems.forEach((item, index) => { - let dot = document.createElement('div') - dot.classList.add('dot') - dot.dataset.rank = index - frag.append(dot) - item.dataset.rank = index - }) - this.indicatorsContainer.append(frag) - this.indicators = this.indicatorsContainer.children - } - }) - - this.addEventListener('keyup', e => { - if (e.code === 'ArrowLeft') - this.scrollRight() - else if (e.code === 'ArrowRight') - this.scrollRight() - }) - - this.nextArrow.addEventListener('click', this.scrollRight) - this.previousArrow.addEventListener('click', this.scrollLeft) - this.indicatorsContainer.addEventListener('click', this.handleIndicatorClick) - } - - async attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - if (name === 'indicator') { - if (this.hasAttribute('indicator')) - this.showIndicator = true - else - this.showIndicator = false - } - if (name === 'autoplay') { - if (this.hasAttribute('autoplay')) { - this.initialTimeout = setTimeout(() => { - this.isAutoPlaying = true - this.autoPlay() - }, this.autoPlayInterval); - } - else { - this.isAutoPlaying = false - clearTimeout(this.autoPlayTimeout) - clearTimeout(this.initialTimeout) - } - - } - if (name === 'interval') { - if (this.hasAttribute('interval') && this.getAttribute('interval').trim() !== '') { - this.autoPlayInterval = Math.abs(parseInt(this.getAttribute('interval').trim())) - } - else { - this.autoPlayInterval = 5000 - } - } - } - } - - disconnectedCallback() { - this.nextArrow.removeEventListener('click', this.scrollRight) - this.previousArrow.removeEventListener('click', this.scrollLeft) - this.indicatorsContainer.removeEventListener('click', this.handleIndicatorClick) - } -}) - -//notifications - -const smNotifications = document.createElement('template') -smNotifications.innerHTML = ` - -
-` - -customElements.define('sm-notifications', class extends HTMLElement { - constructor() { - super() - this.shadow = this.attachShadow({ - mode: 'open' - }).append(smNotifications.content.cloneNode(true)) - } - - handleTouchStart = (e) => { - this.notification = e.target.closest('.notification') - this.touchStartX = e.changedTouches[0].clientX - this.notification.style.transition = 'initial' - this.touchStartTime = e.timeStamp - } - - handleTouchMove = (e) => { - e.preventDefault() - if (this.touchStartX < e.changedTouches[0].clientX) { - this.offset = e.changedTouches[0].clientX - this.touchStartX; - this.touchEndAnimataion = requestAnimationFrame(this.movePopup) - } else { - this.offset = -(this.touchStartX - e.changedTouches[0].clientX); - this.touchEndAnimataion = requestAnimationFrame(this.movePopup) - } - } - - handleTouchEnd = (e) => { - this.notification.style.transition = 'transform 0.3s, opacity 0.3s' - this.touchEndTime = e.timeStamp - cancelAnimationFrame(this.touchEndAnimataion) - this.touchEndX = e.changedTouches[0].clientX - if (this.touchEndTime - this.touchStartTime > 200) { - if (this.touchEndX - this.touchStartX > this.threshold) { - this.removeNotification(this.notification) - } else if (this.touchStartX - this.touchEndX > this.threshold) { - this.removeNotification(this.notification, true) - } else { - this.resetPosition() - } - } else { - if (this.touchEndX > this.touchStartX) { - this.removeNotification(this.notification) - } else { - this.removeNotification(this.notification, true) - } - } - } - - movePopup = () => { - this.notification.style.transform = `translateX(${this.offset}px)` - } - - resetPosition = () => { - this.notification.style.transform = `translateX(0)` - } - - push = (messageBody, type, pinned) => { - let notification = document.createElement('div'), - composition = `` - notification.classList.add('notification') - if (pinned) - notification.classList.add('pinned') - if (type === 'error') { - composition += ` - - - - - ` - } else if (type === 'success') { - composition += ` - - - ` - } - composition += ` -

${messageBody}

- - Close - - - ` - notification.innerHTML = composition - this.notificationPanel.prepend(notification) - if (window.innerWidth > 640) { - notification.animate([{ - transform: `translateX(1rem)`, - opacity: '0' - }, - { - transform: 'translateX(0)', - opacity: '1' - } - ], this.animationOptions).onfinish = () => { - notification.setAttribute('style', `transform: none;`); - } - } else { - notification.setAttribute('style', `transform: translateY(0); opacity: 1`) - } - notification.addEventListener('touchstart', this.handleTouchStart) - notification.addEventListener('touchmove', this.handleTouchMove) - notification.addEventListener('touchend', this.handleTouchEnd) - } - - removeNotification = (notification, toLeft) => { - if (!this.offset) - this.offset = 0; - - if (toLeft) - notification.animate([{ - transform: `translateX(${this.offset}px)`, - opacity: '1' - }, - { - transform: `translateX(-100%)`, - opacity: '0' - } - ], this.animationOptions).onfinish = () => { - notification.remove() - } - else { - notification.animate([{ - transform: `translateX(${this.offset}px)`, - opacity: '1' - }, - { - transform: `translateX(100%)`, - opacity: '0' - } - ], this.animationOptions).onfinish = () => { - notification.remove() - } - } - } - - clearAll = () => { - Array.from(this.notificationPanel.children).forEach(child => { - this.removeNotification(child) - }) - } - - connectedCallback() { - this.notificationPanel = this.shadowRoot.querySelector('.notification-panel') - this.animationOptions = { - duration: 300, - fill: "forwards", - easing: "ease" - } - this.fontSize = Number(window.getComputedStyle(document.body).getPropertyValue('font-size').match(/\d+/)[0]) - this.notification - this.offset - this.touchStartX = 0 - this.touchEndX = 0 - this.touchStartTime = 0 - this.touchEndTime = 0 - this.threshold = this.notificationPanel.getBoundingClientRect().width * 0.3 - this.touchEndAnimataion; - - this.notificationPanel.addEventListener('click', e => { - if (e.target.closest('.close'))( - this.removeNotification(e.target.closest('.notification')) - ) - }) - - const observer = new MutationObserver(mutationList => { - mutationList.forEach(mutation => { - if (mutation.type === 'childList') { - if (mutation.addedNodes.length) { - if (!mutation.addedNodes[0].classList.contains('pinned')) - setTimeout(() => { - this.removeNotification(mutation.addedNodes[0]) - }, 5000); - if (window.innerWidth > 640) - this.notificationPanel.style.padding = '1.5rem 0 3rem 1.5rem'; - else - this.notificationPanel.style.padding = '1rem 1rem 2rem 1rem'; - } else if (mutation.removedNodes.length && !this.notificationPanel.children.length) { - this.notificationPanel.style.padding = 0; - } - } - }) - }) - observer.observe(this.notificationPanel, { - attributes: true, - childList: true, - subtree: true - }) - } -}) - - - -// sm-menu -const smMenu = document.createElement('template') -smMenu.innerHTML = ` - -
- -
- -
-
`; -customElements.define('sm-menu', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smMenu.content.cloneNode(true)) - } - static get observedAttributes() { - return ['value'] - } - get value() { - return this.getAttribute('value') - } - set value(val) { - this.setAttribute('value', val) - } - expand = () => { - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.classList.add('no-transformations') - this.open = true - this.icon.classList.add('focused') - this.availableOptions.forEach(option => { - option.setAttribute('tabindex', '0') - }) - } - } - collapse() { - if (this.open) { - this.open = false - this.icon.classList.remove('focused') - this.optionList.classList.add('hide') - this.optionList.classList.remove('no-transformations') - this.availableOptions.forEach(option => { - option.removeAttribute('tabindex') - }) - } - } - connectedCallback() { - this.availableOptions - this.containerDimensions - this.optionList = this.shadowRoot.querySelector('.options') - let slot = this.shadowRoot.querySelector('.options slot'), - menu = this.shadowRoot.querySelector('.menu') - this.icon = this.shadowRoot.querySelector('.icon') - this.open = false; - menu.addEventListener('click', e => { - if (!this.open) { - this.expand() - } else { - this.collapse() - } - }) - menu.addEventListener('keydown', e => { - if (e.code === 'ArrowDown' || e.code === 'ArrowRight') { - e.preventDefault() - this.availableOptions[0].focus() - } - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - if (!this.open) { - this.expand() - } else { - this.collapse() - } - } - }) - this.optionList.addEventListener('keydown', e => { - if (e.code === 'ArrowUp' || e.code === 'ArrowRight') { - e.preventDefault() - if (document.activeElement.previousElementSibling) { - document.activeElement.previousElementSibling.focus() - } - } - if (e.code === 'ArrowDown' || e.code === 'ArrowLeft') { - e.preventDefault() - if (document.activeElement.nextElementSibling) - document.activeElement.nextElementSibling.focus() - } - }) - this.optionList.addEventListener('click', e => { - this.collapse() - }) - slot.addEventListener('slotchange', e => { - this.availableOptions = slot.assignedElements() - this.containerDimensions = this.optionList.getBoundingClientRect() - }); - window.addEventListener('mousedown', e => { - if (!this.contains(e.target) && e.button !== 2) { - this.collapse() - } - }) - } -}) - -// option -const smMenuOption = document.createElement('template') -smMenuOption.innerHTML = ` - -
- -
`; -customElements.define('sm-menu-option', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smMenuOption.content.cloneNode(true)) - } - - connectedCallback() { - this.addEventListener('keyup', e => { - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - this.click() - } - }) - } -}) - - -// tags input -const tagsInput = document.createElement('template') -tagsInput.innerHTML = ` - -
- -

-
-` - -customElements.define('tags-input', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(tagsInput.content.cloneNode(true)) - this.input = this.shadowRoot.querySelector('input') - this.tagsWrapper = this.shadowRoot.querySelector('.tags-wrapper') - this.placeholder = this.shadowRoot.querySelector('.placeholder') - this.observeList = ['placeholder', 'limit'] - this.limit = undefined - this.tags = new Set() - } - static get observedAttributes() { - return ['placeholder', 'limit'] - } - get value() { - return [...this.tags].join() - } - reset = () => { - this.input.value = '' - this.tags.clear() - while (this.input.previousElementSibling) { - this.input.previousElementSibling.remove() - } - } - handleInput = e => { - const inputValueLength = e.target.value.trim().length - e.target.setAttribute('size', inputValueLength ? inputValueLength : '3') - if (inputValueLength) { - this.placeholder.classList.add('hide') - } - else if (!inputValueLength && !this.tags.size) { - this.placeholder.classList.remove('hide') - } - } - handleKeydown = e => { - if (e.key === ',' || e.key === '/') { - e.preventDefault() - } - if (e.target.value.trim() !== '') { - if (e.key === 'Enter' || e.key === ',' || e.key === '/' || e.code === 'Space') { - const tagValue = e.target.value.trim() - if (this.tags.has(tagValue)) { - this.tagsWrapper.querySelector(`[data-value="${tagValue}"]`).animate([ - { - backgroundColor: 'initial' - }, - { - backgroundColor: 'var(--accent-color)' - }, - { - backgroundColor: 'initial' - }, - ], { - duration: 300 - }) - } - else { - const tag = document.createElement('span') - tag.dataset.value = tagValue - tag.className = 'tag' - tag.innerHTML = ` - ${tagValue} - - ` - this.input.before(tag) - this.tags.add(tagValue) - } - e.target.value = '' - e.target.setAttribute('size', '3') - if (this.limit && this.limit < this.tags.size + 1) { - this.input.readOnly = true - return - } - } - } - else { - if (e.key === 'Backspace' && this.input.previousElementSibling) { - this.removeTag(this.input.previousElementSibling) - } - if (this.limit && this.limit > this.tags.size){ - this.input.readOnly = false - } - } - } - handleClick = e => { - if (e.target.closest('.tag')) { - this.removeTag(e.target.closest('.tag')) - } - else { - this.input.focus() - } - } - removeTag = (tag) => { - this.tags.delete(tag.dataset.value) - tag.remove() - if (!this.tags.size) { - this.placeholder.classList.remove('hide') - } - } - connectedCallback() { - this.input.addEventListener('input', this.handleInput) - this.input.addEventListener('keydown', this.handleKeydown) - this.tagsWrapper.addEventListener('click', this.handleClick) - } - attributeChangedCallback(name, oldValue, newValue) { - if (name === 'placeholder') { - this.placeholder.textContent = newValue - } - if (name === 'limit') { - this.limit = parseInt(newValue) - } - } - disconnectedCallback() { - this.input.removeEventListener('input', this.handleInput) - this.input.removeEventListener('keydown', this.handleKeydown) - this.tagsWrapper.removeEventListener('click', this.handleClick) - } -}) - -// file input -const fileInput = document.createElement('template') -fileInput.innerHTML = ` - - - -` - -customElements.define('file-input', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(fileInput.content.cloneNode(true)) - this.input = this.shadowRoot.querySelector('input') - this.fileInput = this.shadowRoot.querySelector('.file-input') - this.filesPreviewWraper = this.shadowRoot.querySelector('.files-preview-wrapper') - this.observeList = ['accept', 'multiple', 'capture'] - } - static get observedAttributes() { - return ['accept', 'multiple', 'capture'] - } - get files() { - return this.input.files - } - set accept(val) { - this.setAttribute('accept', val) - } - set multiple(val) { - if (val) { - this.setAttribute('mutiple', '') - } - else { - this.removeAttribute('mutiple') - } - } - set capture(val) { - this.setAttribute('capture', val) - } - set value(val) { - this.input.value = val - } - get isValid() { - return this.input.value !== '' - } - reset = () => { - this.input.value = '' - this.filesPreviewWraper.innerHTML = '' - } - formatBytes = (a,b=2) => {if(0===a)return"0 Bytes";const c=0>b?0:b,d=Math.floor(Math.log(a)/Math.log(1024));return parseFloat((a/Math.pow(1024,d)).toFixed(c))+" "+["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"][d]} - createFilePreview = (file) => { - const filePreview = document.createElement('li') - const {name, size} = file - filePreview.className = 'file-preview' - filePreview.innerHTML = ` -
${name}
-
${this.formatBytes(size)}
- ` - return filePreview - } - handleChange = (e) => { - this.filesPreviewWraper.innerHTML = '' - const frag = document.createDocumentFragment() - Array.from(e.target.files).forEach(file => { - frag.append( - this.createFilePreview(file) - ) - }); - this.filesPreviewWraper.append(frag) - } - handleKeyDown = e => { - if (e.key === 'Enter' || e.code === 'Space') { - e.preventDefault() - this.input.click() - } - } - connectedCallback() { - this.setAttribute('role', 'button') - this.setAttribute('aria-label', 'File upload') - this.input.addEventListener('change', this.handleChange) - this.fileInput.addEventListener('keydown', this.handleKeyDown) - } - attributeChangedCallback(name) { - if (this.observeList.includes(name)){ - if (this.hasAttribute(name)) { - this.input.setAttribute(name, this.getAttribute(name) ? this.getAttribute(name) : '') - } - else { - this.input.removeAttribute(name) - } - } - } - disconnectedCallback() { - this.input.removeEventListener('change', this.handleChange) - this.fileInput.removeEventListener('keydown', this.handleKeyDown) - } -}) - -// sm-form -const smForm = document.createElement('template') -smForm.innerHTML = ` - -
- -
-` - -customElements.define('sm-form', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smForm.content.cloneNode(true)) - - this.form = this.shadowRoot.querySelector('form') - this.formElements - this.requiredElements - this.submitButton - this.resetButton - this.allRequiredValid = false - } - debounce = (callback, wait) => { - let timeoutId = null; - return (...args) => { - window.clearTimeout(timeoutId); - timeoutId = window.setTimeout(() => { - callback.apply(null, args); - }, wait); - }; - } - handleInput = this.debounce((e) => { - this.allRequiredValid = this.requiredElements.every(elem => elem.isValid) - if (!this.submitButton) return; - if (this.allRequiredValid) { - this.submitButton.disabled = false; - } - else { - this.submitButton.disabled = true; - } - }, 100) - handleKeydown = this.debounce((e) => { - if (e.key === 'Enter') { - if (this.allRequiredValid) { - this.submitButton.click() - } - else { - // implement show validity logic - } - } - }, 100) - reset = () => { - this.formElements.forEach(elem => elem.reset()) - } - connectedCallback() { - const slot = this.shadowRoot.querySelector('slot') - slot.addEventListener('slotchange', e => { - this.formElements = [...this.querySelectorAll('sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-checkbox')] - this.requiredElements = this.formElements.filter(elem => elem.hasAttribute('required')) - this.submitButton = e.target.assignedElements().find(elem => elem.getAttribute('variant') === 'primary' || elem.getAttribute('type') === 'submit'); - this.resetButton = e.target.assignedElements().find(elem => elem.getAttribute('type') === 'reset'); - if (this.resetButton) { - this.resetButton.addEventListener('click', this.reset) - } - }) - this.addEventListener('input', this.handleInput) - this.addEventListener('keydown', this.handleKeydown) - } - disconnectedCallback() { - this.removeEventListener('input', this.handleInput) - } -}) - -// tab-header - -const smTabHeader = document.createElement('template') -smTabHeader.innerHTML = ` - -
-
- -
-
-
-`; - -customElements.define('sm-tab-header', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smTabHeader.content.cloneNode(true)) - - this.indicator = this.shadowRoot.querySelector('.indicator'); - this.tabSlot = this.shadowRoot.querySelector('slot'); - this.tabHeader = this.shadowRoot.querySelector('.tab-header'); - } - - sendDetails(element) { - this.dispatchEvent( - new CustomEvent("switchtab", { - bubbles: true, - detail: { - target: this.target, - rank: parseInt(element.getAttribute('rank')) - } - }) - ) - } - - moveIndiactor(tabDimensions) { - //if(this.isTab) - this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`) - //else - //this.indicator.setAttribute('style', `width: calc(${tabDimensions.width}px - 1.6rem); transform: translateX(calc(${ tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px + 0.8rem)`) - } - - connectedCallback() { - if (!this.hasAttribute('target') || this.getAttribute('target').value === '') return; - this.prevTab - this.allTabs - this.activeTab - this.isTab = false - this.target = this.getAttribute('target') - - if (this.hasAttribute('variant') && this.getAttribute('variant') === 'tab') { - this.isTab = true - } - - this.tabSlot.addEventListener('slotchange', () => { - this.tabSlot.assignedElements().forEach((tab, index) => { - tab.setAttribute('rank', index) - }) - }) - this.allTabs = this.tabSlot.assignedElements(); - - this.tabSlot.addEventListener('click', e => { - if (e.target === this.prevTab || !e.target.closest('sm-tab')) - return - if (this.prevTab) - this.prevTab.classList.remove('active') - e.target.classList.add('active') - - e.target.scrollIntoView({ - behavior: 'smooth', - block: 'nearest', - inline: 'center' - }) - this.moveIndiactor(e.target.getBoundingClientRect()) - this.sendDetails(e.target) - this.prevTab = e.target; - this.activeTab = e.target; - }) - let resizeObserver = new ResizeObserver(entries => { - entries.forEach((entry) => { - if (this.prevTab) { - let tabDimensions = this.activeTab.getBoundingClientRect(); - this.moveIndiactor(tabDimensions) - } - }) - }) - resizeObserver.observe(this) - let observer = new IntersectionObserver((entries) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - this.indicator.style.transition = 'none' - if (this.activeTab) { - let tabDimensions = this.activeTab.getBoundingClientRect(); - this.moveIndiactor(tabDimensions) - } else { - this.allTabs[0].classList.add('active') - let tabDimensions = this.allTabs[0].getBoundingClientRect(); - this.moveIndiactor(tabDimensions) - this.sendDetails(this.allTabs[0]) - this.prevTab = this.tabSlot.assignedElements()[0]; - this.activeTab = this.prevTab; - } - } - }) - }, { - threshold: 1.0 - }) - observer.observe(this) - } -}) - -// tab -const smTab = document.createElement('template') -smTab.innerHTML = ` - -
- -
-`; - -customElements.define('sm-tab', class extends HTMLElement { - constructor() { - super() - this.shadow = this.attachShadow({ - mode: 'open' - }).append(smTab.content.cloneNode(true)) - } -}) - -// tab-panels - -const smTabPanels = document.createElement('template') -smTabPanels.innerHTML = ` - -
- Nothing to see here. -
-`; - -customElements.define('sm-tab-panels', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smTabPanels.content.cloneNode(true)) - this.panelSlot = this.shadowRoot.querySelector('slot'); - } - connectedCallback() { - - //animations - let flyInLeft = [{ - opacity: 0, - transform: 'translateX(-1rem)' - }, - { - opacity: 1, - transform: 'none' - } - ], - flyInRight = [{ - opacity: 0, - transform: 'translateX(1rem)' - }, - { - opacity: 1, - transform: 'none' - } - ], - flyOutLeft = [{ - opacity: 1, - transform: 'none' - }, - { - opacity: 0, - transform: 'translateX(-1rem)' - } - ], - flyOutRight = [{ - opacity: 1, - transform: 'none' - }, - { - opacity: 0, - transform: 'translateX(1rem)' - } - ], - animationOptions = { - duration: 300, - fill: 'forwards', - easing: 'ease' - } - this.prevPanel - this.allPanels - this.previousRank - - this.panelSlot.addEventListener('slotchange', () => { - this.panelSlot.assignedElements().forEach((panel) => { - panel.classList.add('hide-completely') - }) - }) - this.allPanels = this.panelSlot.assignedElements() - this._targetBodyFlyRight = (targetBody) => { - targetBody.classList.remove('hide-completely') - targetBody.animate(flyInRight, animationOptions) - } - this._targetBodyFlyLeft = (targetBody) => { - targetBody.classList.remove('hide-completely') - targetBody.animate(flyInLeft, animationOptions) - } - document.addEventListener('switchtab', e => { - if (e.detail.target !== this.id) - return - - if (this.prevPanel) { - let targetBody = this.allPanels[e.detail.rank], - currentBody = this.prevPanel; - if (this.previousRank < e.detail.rank) { - if (currentBody && !targetBody) - currentBody.animate(flyOutLeft, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - } - else if (targetBody && !currentBody) { - this._targetBodyFlyRight(targetBody) - } else if (currentBody && targetBody) { - currentBody.animate(flyOutLeft, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - this._targetBodyFlyRight(targetBody) - } - } - } else { - if (currentBody && !targetBody) - currentBody.animate(flyOutRight, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - } - else if (targetBody && !currentBody) { - this._targetBodyFlyLeft(targetBody) - } else if (currentBody && targetBody) { - currentBody.animate(flyOutRight, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - this._targetBodyFlyLeft(targetBody) - } - } - } - } else { - this.allPanels[e.detail.rank].classList.remove('hide-completely') - } - this.previousRank = e.detail.rank - this.prevPanel = this.allPanels[e.detail.rank]; - }) - } -}) diff --git a/Standard UI Components/components.min.js b/Standard UI Components/components.min.js deleted file mode 100644 index d7c08f2..0000000 --- a/Standard UI Components/components.min.js +++ /dev/null @@ -1 +0,0 @@ -//Buttonconst smButton=document.createElement('template')smButton.innerHTML=`
`;customElements.define('sm-button', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smButton.content.cloneNode(true))}static get observedAttributes(){return ['disabled']}get disabled(){return this.getAttribute('disabled')}set disabled(val){this.setAttribute('disabled', val)}dispatch(){if (this.getAttribute('disabled')==='true'){this.dispatchEvent(new CustomEvent('disabled',{bubbles: true, composed: true}))}else{this.dispatchEvent(new CustomEvent('clicked',{bubbles: true, composed: true}))}}connectedCallback(){this.addEventListener('click', (e)=>{this.dispatch()}) this.addEventListener('keyup', (e)=>{if (e.code==="Enter" || e.code==="Space") this.dispatch()})}attributeChangedCallback(name, oldValue, newValue){}})//Inputconst smInput=document.createElement('template')smInput.innerHTML=`
`;customElements.define('sm-input', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smInput.content.cloneNode(true))}static get observedAttributes(){return ['placeholder']}get value(){return this.shadowRoot.querySelector('input').value}set value(val){this.shadowRoot.querySelector('input').value=val;}get placeholder(){return this.getAttribute('placeholder')}set placeholder(val){this.setAttribute('placeholder', val)}get type(){return this.getAttribute('type')}get isValid(){return this.shadowRoot.querySelector('input').checkValidity()}preventNonNumericalInput(e){let keyCode=e.keyCode; if (!((keyCode > 47 && keyCode < 56) || (keyCode > 36 && keyCode < 39) || (keyCode > 95 && keyCode < 104) || keyCode===110 || (keyCode > 7 && keyCode < 19))){e.preventDefault();}}checkInput(){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') this.clearBtn.classList.remove('hide')}else{if (this.animate) this.inputParent.classList.remove('animate-label') else this.label.classList.remove('hide') this.clearBtn.classList.add('hide')}if (this.valueChanged){if (this.input.checkValidity()){this.helperText.classList.add('hide') this.inputParent.style.boxShadow=``}else{this.helperText.classList.remove('hide') this.inputParent.style.boxShadow=`0 0 0 0.1rem ${this.computedStyle.getPropertyValue('--error-color')}`}}}connectedCallback(){this.inputParent=this.shadowRoot.querySelector('.input') this.computedStyle=window.getComputedStyle(this.inputParent) this.clearBtn=this.shadowRoot.querySelector('.clear') this.label=this.shadowRoot.querySelector('.label') this.helperText=this.shadowRoot.querySelector('.helper-text') this.valueChanged=false; this.animate=this.hasAttribute('animate') this.input=this.shadowRoot.querySelector('input') this.shadowRoot.querySelector('.label').textContent=this.getAttribute('placeholder') if (this.hasAttribute('value')){this.input.value=this.getAttribute('value') this.checkInput()}if (this.hasAttribute('helper-text')){this.helperText.textContent=this.getAttribute('helper-text')}if (this.hasAttribute('type')){if (this.getAttribute('type')==='number'){this.input.setAttribute('inputmode', 'numeric')}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.input.addEventListener('change', e=>{this.valueChanged=true; if (this.input.checkValidity()) this.helperText.classList.add('hide') else this.helperText.classList.remove('hide')}) this.clearBtn.addEventListener('click', e=>{this.input.value='' this.checkInput()})}attributeChangedCallback(name, oldValue, newValue){if (oldValue !==newValue){if (name==='placeholder') this.shadowRoot.querySelector('.label').textContent=newValue;}}})// tab-headerconst smTabs=document.createElement('template')smTabs.innerHTML=`
Nothing to see here
Nothing to see here
`;customElements.define('sm-tabs', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smTabs.content.cloneNode(true)) this.indicator=this.shadowRoot.querySelector('.indicator'); this.tabSlot=this.shadowRoot.querySelector('slot[name="tab"]'); this.panelSlot=this.shadowRoot.querySelector('slot[name="panel"]'); this.tabHeader=this.shadowRoot.querySelector('.tab-header');}connectedCallback(){//animations let flyInLeft=[{opacity: 0, transform: 'translateX(-1rem)'},{opacity: 1, transform: 'none'}], flyInRight=[{opacity: 0, transform: 'translateX(1rem)'},{opacity: 1, transform: 'none'}], flyOutLeft=[{opacity: 1, transform: 'none'},{opacity: 0, transform: 'translateX(-1rem)'}], flyOutRight=[{opacity: 1, transform: 'none'},{opacity: 0, transform: 'translateX(1rem)'}], animationOptions={duration: 300, fill: 'forwards', easing: 'ease'}this.prevTab this.allTabs this.shadowRoot.querySelector('slot[name="panel"]').addEventListener('slotchange', ()=>{this.shadowRoot.querySelector('slot[name="panel"]').assignedElements().forEach((panel, index)=>{panel.classList.add('hide-completely')})}) this.shadowRoot.querySelector('slot[name="tab"]').addEventListener('slotchange', ()=>{this.allTabs=this.shadowRoot.querySelector('slot[name="tab"]').assignedElements(); this.shadowRoot.querySelector('slot[name="tab"]').assignedElements().forEach((panel, index)=>{panel.setAttribute('rank', index + 1)})}) this._targetBodyFlyRight=(targetBody)=>{targetBody.classList.remove('hide-completely') targetBody.animate(flyInRight, animationOptions)}this._targetBodyFlyLeft=(targetBody)=>{targetBody.classList.remove('hide-completely') targetBody.animate(flyInLeft, animationOptions)}this.tabSlot.addEventListener('click', e=>{if (e.target===this.prevTab || !e.target.closest('sm-tab')) return if (this.prevTab) this.prevTab.classList.remove('active') e.target.classList.add('active') e.target.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'center'}) this.indicator.setAttribute('style', `width: ${e.target.getBoundingClientRect().width}px; transform: translateX(${e.target.getBoundingClientRect().left - e.target.parentNode.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`) if (this.prevTab){let targetBody=e.target.nextElementSibling, currentBody=this.prevTab.nextElementSibling; if (this.prevTab.getAttribute('rank') < e.target.getAttribute('rank')){if (currentBody && !targetBody) currentBody.animate(flyOutLeft, animationOptions).onfinish=()=>{currentBody.classList.add('hide-completely')}else if (targetBody && !currentBody){this._targetBodyFlyRight(targetBody)}else if (currentBody && targetBody){currentBody.animate(flyOutLeft, animationOptions).onfinish=()=>{currentBody.classList.add('hide-completely') this._targetBodyFlyRight(targetBody)}}}else{if (currentBody && !targetBody) currentBody.animate(flyOutRight, animationOptions).onfinish=()=>{currentBody.classList.add('hide-completely')}else if (targetBody && !currentBody){this._targetBodyFlyLeft(targetBody)}else if (currentBody && targetBody){currentBody.animate(flyOutRight, animationOptions).onfinish=()=>{currentBody.classList.add('hide-completely') this._targetBodyFlyLeft(targetBody)}}}}else{e.target.nextElementSibling.classList.remove('hide-completely')}this.prevTab=e.target;}) let resizeObserver=new ResizeObserver(entries=>{entries.forEach((entry)=>{if (this.prevTab){let tabDimensions=this.prevTab.getBoundingClientRect(); this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - this.tabSlot.assignedElements()[0].parentNode.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`)}})}) resizeObserver.observe(this) let observer=new IntersectionObserver((entries)=>{entries.forEach((entry)=>{this.indicator.style.transition='none' if (entry.isIntersecting){let activeElement=this.tabSlot.assignedElements().filter(element=>{if (element.classList.contains('active')) return true}) if (activeElement.length){let tabDimensions=activeElement[0].getBoundingClientRect(); this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - activeElement[0].parentNode.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`)}else{this.tabSlot.assignedElements()[0].classList.add('active') this.panelSlot.assignedElements()[0].classList.remove('hide-completely') let tabDimensions=this.tabSlot.assignedElements()[0].getBoundingClientRect(); this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - this.tabSlot.assignedElements()[0].parentNode.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`) this.prevTab=this.tabSlot.assignedElements()[0];}}})},{threshold: 1.0}) observer.observe(this) if (this.hasAttribute('enable-flick') && this.getAttribute('enable-flick')=='true'){let touchStartTime=0, touchEndTime=0, swipeTimeThreshold=200, swipeDistanceThreshold=20, startingPointX=0, endingPointX=0, currentIndex=0; this.addEventListener('touchstart', e=>{touchStartTime=e.timeStamp startingPointX=e.changedTouches[0].clientX}) this.panelSlot.addEventListener('touchend', e=>{touchEndTime=e.timeStamp endingPointX=e.changedTouches[0].clientX if (touchEndTime - touchStartTime < swipeTimeThreshold){currentIndex=this.allTabs.findIndex(element=> element.classList.contains('active')) if (startingPointX > endingPointX && startingPointX - endingPointX > swipeDistanceThreshold && currentIndex < this.allTabs.length){this.allTabs[currentIndex + 1].click()}else if (startingPointX < endingPointX && endingPointX - startingPointX > swipeDistanceThreshold && currentIndex > 0){this.allTabs[currentIndex - 1].click()}}})}}})// tabconst smTab=document.createElement('template')smTab.innerHTML=`
`;customElements.define('sm-tab', class extends HTMLElement{constructor(){super() this.shadow=this.attachShadow({mode: 'open'}).append(smTab.content.cloneNode(true))}})//chcekboxconst smCheckbox=document.createElement('template')smCheckbox.innerHTML=``customElements.define('sm-checkbox', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smCheckbox.content.cloneNode(true)) this.checkbox=this.shadowRoot.querySelector('.checkbox'); this.input=this.shadowRoot.querySelector('input') this.isChecked=false this.isDisabled=false}static get observedAttributes(){return ['disabled', 'checked']}get disabled(){return this.getAttribute('disabled')}set disabled(val){this.setAttribute('disabled', val)}get checked(){return this.getAttribute('checked')}set checked(value){this.setAttribute('checked', 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)}})}attributeChangedCallback(name, oldValue, newValue){if (oldValue !==newValue){if (name==='disabled'){if (newValue==='true'){this.checkbox.classList.add('disabled') this.isDisabled=true}else{this.checkbox.classList.remove('disabled') this.isDisabled=false}}if (name==='checked'){if (newValue=='true'){this.isChecked=true this.input.checked=true this.dispatch()}else{this.isChecked=false this.input.checked=false this.dispatch()}}}}})//audioconst smAudio=document.createElement('template')smAudio.innerHTML=`
playpause
/
`;customElements.define('sm-audio', class extends HTMLElement{constructor(){super(); this.attachShadow({mode: 'open'}).append(smAudio.content.cloneNode(true)) this.playing=false;}static get observedAttributes(){return ['src']}play(){this.audio.play() this.playing=false; this.pauseBtn.classList.remove('hide') this.playBtn.classList.add('hide')}pause(){this.audio.pause() this.playing=true; this.pauseBtn.classList.add('hide') this.playBtn.classList.remove('hide')}get isPlaying(){return this.playing;}connectedCallback(){this.playBtn=this.shadowRoot.querySelector('.play'); this.pauseBtn=this.shadowRoot.querySelector('.pause'); this.audio=this.shadowRoot.querySelector('audio') this.playBtn.addEventListener('click', e=>{this.play()}) this.pauseBtn.addEventListener('click', e=>{this.pause()}) this.audio.addEventListener('ended', e=>{this.pause()}) let width; if ('ResizeObserver' in window){let resizeObserver=new ResizeObserver(entries=>{entries.forEach(entry=>{width=entry.contentRect.width;})}) resizeObserver.observe(this)}else{let observer=new IntersectionObserver((entries, observer)=>{if (entries[0].isIntersecting) width=this.shadowRoot.querySelector('.audio').offsetWidth;},{threshold: 1}) observer.observe(this)}this.audio.addEventListener('timeupdate', e=>{let time=this.audio.currentTime, minutes=Math.floor(time / 60), seconds=Math.floor(time - minutes * 60), y=seconds < 10 ? "0" + seconds : seconds; this.shadowRoot.querySelector('.current-time').textContent=`${minutes}:${y}` this.shadowRoot.querySelector('.track').style.width=(width / this.audio.duration) * this.audio.currentTime + 'px'})}attributeChangedCallback(name, oldValue, newValue){if (oldValue !==newValue){if (name==='src'){if (this.hasAttribute('src') && newValue.trim() !==''){this.shadowRoot.querySelector('audio').src=newValue; this.shadowRoot.querySelector('audio').onloadedmetadata=()=>{let duration=this.audio.duration, minutes=Math.floor(duration / 60), seconds=Math.floor(duration - minutes * 60), y=seconds < 10 ? "0" + seconds : seconds; this.shadowRoot.querySelector('.duration').textContent=`${minutes}:${y}`;}}else this.classList.add('disabled')}}}})//switchconst smSwitch=document.createElement('template')smSwitch.innerHTML=``customElements.define('sm-switch', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smSwitch.content.cloneNode(true)) this.switch=this.shadowRoot.querySelector('.switch'); this.input=this.shadowRoot.querySelector('input') this.isChecked=false this.isDisabled=false}static get observedAttributes(){return ['disabled', 'checked']}get disabled(){return this.getAttribute('disabled')}set disabled(val){this.setAttribute('disabled', val)}get checked(){return this.isChecked}set checked(value){this.setAttribute('checked', 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)}})}attributeChangedCallback(name, oldValue, newValue){if (oldValue !==newValue){if (name==='disabled'){if (newValue==='true'){this.switch.classList.add('disabled') this.isDisabled=true}else{this.switch.classList.remove('disabled') this.isDisabled=false}}if (name==='checked'){if (newValue=='true'){this.isChecked=true this.input.checked=true this.dispatch()}else{this.isChecked=false this.input.checked=false this.dispatch()}}}}})// selectconst smSelect=document.createElement('template')smSelect.innerHTML=`
`;customElements.define('sm-select', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smSelect.content.cloneNode(true))}static get observedAttributes(){return ['value']}get value(){return this.getAttribute('value')}set value(val){this.setAttribute('value', val)}collapse(){this.optionList.animate(this.slideUp, this.animationOptions) this.optionList.classList.add('hide') this.chevron.classList.remove('rotate') this.open=false}connectedCallback(){this.availableOptions this.optionList=this.shadowRoot.querySelector('.options') this.chevron=this.shadowRoot.querySelector('.toggle') let slot=this.shadowRoot.querySelector('.options slot'), selection=this.shadowRoot.querySelector('.selection'), previousOption this.open=false; this.slideDown=[{transform: `translateY(-0.5rem)`},{transform: `translateY(0)`}], this.slideUp=[{transform: `translateY(0)`},{transform: `translateY(-0.5rem)`}], this.animationOptions={duration: 300, fill: "forwards", easing: 'ease'}selection.addEventListener('click', e=>{if (!this.open){this.optionList.classList.remove('hide') this.optionList.animate(this.slideDown, this.animationOptions) this.chevron.classList.add('rotate') this.open=true}else{this.collapse()}}) selection.addEventListener('keydown', e=>{if (e.code==='ArrowDown' || e.code==='ArrowRight'){e.preventDefault() this.availableOptions[0].focus()}if (e.code==='Enter' || e.code==='Space') if (!this.open){this.optionList.classList.remove('hide') this.optionList.animate(this.slideDown, this.animationOptions) this.chevron.classList.add('rotate') this.open=true}else{this.collapse()}}) this.optionList.addEventListener('keydown', e=>{if (e.code==='ArrowUp' || e.code==='ArrowRight'){e.preventDefault() if (document.activeElement.previousElementSibling){document.activeElement.previousElementSibling.focus()}}if (e.code==='ArrowDown' || e.code==='ArrowLeft'){e.preventDefault() if (document.activeElement.nextElementSibling) document.activeElement.nextElementSibling.focus()}}) this.addEventListener('optionSelected', e=>{if (previousOption !==e.target){this.setAttribute('value', e.detail.value) this.shadowRoot.querySelector('.option-text').textContent=e.detail.text; this.dispatchEvent(new CustomEvent('change',{bubbles: true, composed: true})) if (previousOption){previousOption.classList.remove('check-selected')}previousOption=e.target;}if (!e.detail.switching) this.collapse() e.target.classList.add('check-selected')}) slot.addEventListener('slotchange', e=>{this.availableOptions=slot.assignedElements() if (this.availableOptions[0]){let firstElement=this.availableOptions[0]; previousOption=firstElement; firstElement.classList.add('check-selected') this.setAttribute('value', firstElement.getAttribute('value')) this.shadowRoot.querySelector('.option-text').textContent=firstElement.textContent this.availableOptions.forEach((element, index)=>{element.setAttribute('data-rank', index + 1); element.setAttribute('tabindex', "0");})}}); document.addEventListener('mousedown', e=>{if (!this.contains(e.target) && this.open){this.collapse()}})}})// optionconst smOption=document.createElement('template')smOption.innerHTML=`
`;customElements.define('sm-option', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smOption.content.cloneNode(true))}sendDetails(switching){let optionSelected=new CustomEvent('optionSelected',{bubbles: true, composed: true, detail:{text: this.textContent, value: this.getAttribute('value'), switching: switching}}) this.dispatchEvent(optionSelected)}connectedCallback(){let validKey=[ 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'] this.addEventListener('click', e=>{this.sendDetails()}) this.addEventListener('keyup', e=>{if (e.code==='Enter' || e.code==='Space'){e.preventDefault() this.sendDetails(false)}if (validKey.includes(e.code)){e.preventDefault() this.sendDetails(true)}}) if (this.hasAttribute('default')){setTimeout(()=>{this.sendDetails()}, 0);}}})// selectconst smStripSelect=document.createElement('template')smStripSelect.innerHTML=`
Previous
Next
`;customElements.define('sm-strip-select', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smStripSelect.content.cloneNode(true))}static get observedAttributes(){return ['value']}get value(){return this.getAttribute('value')}set value(val){this.setAttribute('value', val)}scrollLeft(){this.select.scrollBy({top: 0, left: -this.scrollDistance, behavior: 'smooth'})}scrollRight(){this.select.scrollBy({top: 0, left: this.scrollDistance, behavior: 'smooth'})}connectedCallback(){let previousOption, slot=this.shadowRoot.querySelector('slot'); this.selectContainer=this.shadowRoot.querySelector('.select-container') this.select=this.shadowRoot.querySelector('.select') this.nextArrow=this.shadowRoot.querySelector('.next-item') this.previousArrow=this.shadowRoot.querySelector('.previous-item') this.nextGradient=this.shadowRoot.querySelector('.right') this.previousGradient=this.shadowRoot.querySelector('.left') this.selectOptions this.scrollDistance=this.selectContainer.getBoundingClientRect().width const firstElementObserver=new IntersectionObserver(entries=>{if (entries[0].isIntersecting){this.previousArrow.classList.add('hide') this.previousGradient.classList.add('hide')}else{this.previousArrow.classList.remove('hide') this.previousGradient.classList.remove('hide')}},{root: this.selectContainer, threshold: 0.95}) const lastElementObserver=new IntersectionObserver(entries=>{if (entries[0].isIntersecting){this.nextArrow.classList.add('hide') this.nextGradient.classList.add('hide')}else{this.nextArrow.classList.remove('hide') this.nextGradient.classList.remove('hide')}},{root: this.selectContainer, threshold: 0.95}) const selectObserver=new IntersectionObserver(entries=>{if (entries[0].isIntersecting){this.scrollDistance=this.selectContainer.getBoundingClientRect().width}}) selectObserver.observe(this.selectContainer) this.addEventListener('optionSelected', e=>{if (previousOption===e.target) return; if (previousOption) previousOption.classList.remove('active') e.target.classList.add('active') e.target.scrollIntoView({behavior: 'smooth', inline: 'center', block: 'nearest'}) this.setAttribute('value', e.detail.value) this.dispatchEvent(new CustomEvent('change',{bubbles: true, composed: true})) previousOption=e.target;}) slot.addEventListener('slotchange', e=>{this.selectOptions=slot.assignedElements() firstElementObserver.observe(this.selectOptions[0]) lastElementObserver.observe(this.selectOptions[this.selectOptions.length - 1]) if (this.selectOptions[0]){let firstElement=this.selectOptions[0]; this.setAttribute('value', firstElement.getAttribute('value')) firstElement.classList.add('active') previousOption=firstElement;}}); this.nextArrow.addEventListener('click', this.scrollRight) this.previousArrow.addEventListener('click', this.scrollLeft)}disconnectedCallback(){this.nextArrow.removeEventListener('click', this.scrollRight) this.previousArrow.removeEventListener('click', this.scrollLeft)}})// optionconst smStripOption=document.createElement('template')smStripOption.innerHTML=`
`;customElements.define('sm-strip-option', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smStripOption.content.cloneNode(true))}sendDetails(){let optionSelected=new CustomEvent('optionSelected',{bubbles: true, composed: true, detail:{text: this.textContent, value: this.getAttribute('value')}}) this.dispatchEvent(optionSelected)}connectedCallback(){this.addEventListener('click', e=>{this.sendDetails()}) this.addEventListener('keyup', e=>{if (e.code==='Enter' || e.code==='Space'){e.preventDefault() this.sendDetails(false)}}) if (this.hasAttribute('default')){setTimeout(()=>{this.sendDetails()}, 0);}}})//popupconst smPopup=document.createElement('template')smPopup.innerHTML=``;customElements.define('sm-popup', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smPopup.content.cloneNode(true))}resumeScrolling(){const scrollY=document.body.style.top; window.scrollTo(0, parseInt(scrollY || '0') * -1); setTimeout(()=>{document.body.setAttribute('style', `overflow: auto; top: initial`)}, 300);}show(pinned, popupStack){this.pinned=pinned this.popupStack=popupStack this.popupContainer.classList.remove('hide') if (window.innerWidth < 648) this.popup.style.transform='translateY(0)'; else this.popup.style.transform='scale(1)'; document.body.setAttribute('style', `overflow: hidden; top: -${window.scrollY}px`)}hide(){this.popupContainer.classList.add('hide') if (window.innerWidth < 648) this.popup.style.transform='translateY(100%)'; else this.popup.style.transform='scale(0.9)'; if (typeof this.popupStack !=='undefined'){this.popupStack.pop() if (this.popupStack.items.length===0){this.resumeScrolling()}}else{this.resumeScrolling()}}handleTouchStart(e){this.touchStartY=e.changedTouches[0].clientY this.popup.style.transition='initial' this.touchStartTime=e.timeStamp}handleTouchMove(e){if (this.touchStartY < e.changedTouches[0].clientY){this.offset=e.changedTouches[0].clientY - this.touchStartY; this.touchEndAnimataion=window.requestAnimationFrame(this.movePopup)}/*else{offset=touchStartY - e.changedTouches[0].clientY; this.popup.style.transform=`translateY(-${offset}px)`}*/}handleTouchEnd(e){this.touchEndTime=e.timeStamp cancelAnimationFrame(this.touchEndAnimataion) this.touchEndY=e.changedTouches[0].clientY this.popup.style.transition='transform 0.3s' if (this.touchEndTime - this.touchStartTime > 200){if (this.touchEndY - this.touchStartY > this.threshold){this.hide()}else{this.show()}}else{if (this.touchEndY > this.touchStartY) this.hide()}}movePopup(){this.popup.style.transform=`translateY(${this.offset}px)`}connectedCallback(){this.pinned=false this.popupStack this.popupContainer=this.shadowRoot.querySelector('.popup-container') this.popup=this.shadowRoot.querySelector('.popup') this.offset this.popupHeader=this.shadowRoot.querySelector('.popup-top') this.touchStartY=0 this.touchEndY=0 this.touchStartTime=0 this.touchEndTime=0 this.threshold=this.popup.getBoundingClientRect().height * 0.3 this.touchEndAnimataion; if (this.hasAttribute('heading')) this.shadowRoot.querySelector('.heading').textContent=this.getAttribute('heading') this.popupContainer.addEventListener('mousedown', e=>{if (e.target===this.popupContainer && !this.pinned){this.hide()}}) this.shadowRoot.querySelector('.close').addEventListener('click', e=>{this.hide()}) this.popupHeader.addEventListener('touchstart', this.handleTouchStart) this.popupHeader.addEventListener('touchmove', this.handleTouchMove) this.popupHeader.addEventListener('touchend', this.handleTouchEnd)}disconnectedCallback(){this.popupHeader.removeEventListener('touchstart', this.handleTouchStart) this.popupHeader.removeEventListener('touchmove', this.handleTouchMove) this.popupHeader.removeEventListener('touchend', this.handleTouchEnd)}})//carouselconst smCarousel=document.createElement('template')smCarousel.innerHTML=``;customElements.define('sm-carousel', class extends HTMLElement{constructor(){super() this.shadow=this.attachShadow({mode: 'open'}).append(smCarousel.content.cloneNode(true))}scrollLeft(){this.carousel.scrollBy({top: 0, left: -this.scrollDistance, behavior: 'smooth'})}scrollRight(){this.carousel.scrollBy({top: 0, left: this.scrollDistance, behavior: 'smooth'})}connectedCallback(){this.carousel=this.shadowRoot.querySelector('.carousel') this.carouselContainer=this.shadowRoot.querySelector('.carousel-container') this.carouselSlot=this.shadowRoot.querySelector('slot') this.nextArrow=this.shadowRoot.querySelector('.next-item') this.previousArrow=this.shadowRoot.querySelector('.previous-item') this.nextGradient=this.shadowRoot.querySelector('.right') this.previousGradient=this.shadowRoot.querySelector('.left') this.carouselItems this.scrollDistance=this.carouselContainer.getBoundingClientRect().width / 3 const firstElementObserver=new IntersectionObserver(entries=>{if (entries[0].isIntersecting){this.previousArrow.classList.remove('expand') this.previousGradient.classList.add('hide')}else{this.previousArrow.classList.add('expand') this.previousGradient.classList.remove('hide')}},{root: this.carouselContainer, threshold: 0.9}) const lastElementObserver=new IntersectionObserver(entries=>{if (entries[0].isIntersecting){this.nextArrow.classList.remove('expand') this.nextGradient.classList.add('hide')}else{this.nextArrow.classList.add('expand') this.nextGradient.classList.remove('hide')}},{root: this.carouselContainer, threshold: 0.9}) const carouselObserver=new IntersectionObserver(entries=>{if (entries[0].isIntersecting){this.scrollDistance=this.carouselContainer.getBoundingClientRect().width / 3}}) carouselObserver.observe(this.carouselContainer) this.carouselSlot.addEventListener('slotchange', e=>{this.carouselItems=this.carouselSlot.assignedElements() firstElementObserver.observe(this.carouselItems[0]) lastElementObserver.observe(this.carouselItems[this.carouselItems.length - 1])}) this.addEventListener('keyup', e=>{if (e.code==='ArrowLeft') this.scrollRight() else this.scrollRight()}) this.nextArrow.addEventListener('click', this.scrollRight) this.previousArrow.addEventListener('click', this.scrollLeft)}disconnectedCallback(){this.nextArrow.removeEventListener('click', this.scrollRight) this.previousArrow.removeEventListener('click', this.scrollLeft)}})//notificationsconst smNotifications=document.createElement('template')smNotifications.innerHTML=`
`customElements.define('sm-notifications', class extends HTMLElement{constructor(){super() this.shadow=this.attachShadow({mode: 'open'}).append(smNotifications.content.cloneNode(true))}handleTouchStart(e){this.notification=e.target.closest('.notification') this.touchStartX=e.changedTouches[0].clientX this.notification.style.transition='initial' this.touchStartTime=e.timeStamp}handleTouchMove(e){if (this.touchStartX < e.changedTouches[0].clientX){this.offset=e.changedTouches[0].clientX - this.touchStartX; this.touchEndAnimataion=requestAnimationFrame(this.movePopup)}else{this.offset=-(this.touchStartX - e.changedTouches[0].clientX); this.touchEndAnimataion=requestAnimationFrame(this.movePopup)}}handleTouchEnd(e){this.notification.style.transition='height 0.3s, transform 0.3s, opacity 0.3s' this.touchEndTime=e.timeStamp cancelAnimationFrame(this.touchEndAnimataion) this.touchEndX=e.changedTouches[0].clientX if (this.touchEndTime - this.touchStartTime > 200){if (this.touchEndX - this.touchStartX > this.threshold){this.removeNotification(this.notification)}else if (this.touchStartX - this.touchEndX > this.threshold){this.removeNotification(this.notification, true)}else{this.resetPosition()}}else{if (this.touchEndX > this.touchStartX){this.removeNotification(this.notification)}else{this.removeNotification(this.notification, true)}}}movePopup(){this.notification.style.transform=`translateX(${this.offset}px)`}resetPosition(){this.notification.style.transform=`translateX(0)`}push(messageHeader, messageBody, options){let notification=document.createElement('div'), composition=``,{pinned, type}=options; notification.classList.add('notification') if (pinned) notification.classList.add('pinned') composition +=`
` if (type==='error'){composition +=` `}else if (type==='success'){composition +=` `}composition +=`

${messageHeader}

Close

${messageBody}

` notification.innerHTML=composition this.notificationPanel.prepend(notification) if (window.innerWidth > 640){notification.animate([{transform: `translateX(1rem)`, opacity: '0'},{transform: 'translateX(0)', opacity: '1'}], this.animationOptions).onfinish=()=>{notification.setAttribute('style', `transform: none;`);}}else{notification.setAttribute('style', `transform: translateY(0); opacity: 1`)}notification.addEventListener('touchstart', this.handleTouchStart) notification.addEventListener('touchmove', this.handleTouchMove) notification.addEventListener('touchend', this.handleTouchEnd)}removeNotification(notification, toLeft){notification.style.height=notification.scrollHeight + 'px'; if (!this.offset) this.offset=0; if (toLeft) notification.animate([{transform: `translateX(${this.offset}px)`, opacity: '1'},{transform: `translateX(-100%)`, opacity: '0'}], this.animationOptions).onfinish=()=>{notification.setAttribute('style', `height: 0; margin-bottom: 0`);}else{notification.animate([{transform: `translateX(${this.offset}px)`, opacity: '1'},{transform: `translateX(100%)`, opacity: '0'}], this.animationOptions).onfinish=()=>{notification.setAttribute('style', `height: 0; margin-bottom: 0`);}}setTimeout(()=>{notification.remove()}, this.animationOptions.duration * 2)}connectedCallback(){this.notificationPanel=this.shadowRoot.querySelector('.notification-panel') this.animationOptions={duration: 300, fill: "forwards", easing: "ease"}this.fontSize=Number(window.getComputedStyle(document.body).getPropertyValue('font-size').match(/\d+/)[0]) this.notification this.offset this.touchStartX=0 this.touchEndX=0 this.touchStartTime=0 this.touchEndTime=0 this.threshold=this.notificationPanel.getBoundingClientRect().width * 0.3 this.touchEndAnimataion; this.notificationPanel.addEventListener('click', e=>{if (e.target.closest('.close')) ( this.removeNotification(e.target.closest('.notification')) )}) const observer=new MutationObserver(mutationList=>{mutationList.forEach(mutation=>{if (mutation.type==='childList'){if (mutation.addedNodes.length){if (!mutation.addedNodes[0].classList.contains('pinned')) setTimeout(()=>{this.removeNotification(mutation.addedNodes[0])}, 4000); if (window.innerWidth > 640) this.notificationPanel.style.padding='1.5rem 0 3rem 1.5rem'; else this.notificationPanel.style.padding='1rem 1rem 2rem 1rem';}else if (mutation.removedNodes.length && !this.notificationPanel.children.length){this.notificationPanel.style.padding=0;}}})}) observer.observe(this.notificationPanel,{attributes: true, childList: true, subtree: true})}})// sm-menuconst smMenu=document.createElement('template')smMenu.innerHTML=`
`;customElements.define('sm-menu', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smMenu.content.cloneNode(true))}static get observedAttributes(){return ['value']}get value(){return this.getAttribute('value')}set value(val){this.setAttribute('value', val)}expand(){if (!this.open){if (this.containerDimensions.left > this.containerDimensions.width){this.optionList.style.right=0}else{this.optionList.style.right='auto'}this.optionList.classList.remove('hide') this.optionList.classList.add('no-transformations') this.open=true this.icon.classList.add('focused')}}collapse(){if (this.open){this.open=false this.icon.classList.remove('focused') this.optionList.classList.add('hide') this.optionList.classList.remove('no-transformations')}}connectedCallback(){this.availableOptions this.containerDimensions this.optionList=this.shadowRoot.querySelector('.options') let slot=this.shadowRoot.querySelector('.options slot'), menu=this.shadowRoot.querySelector('.menu') this.icon=this.shadowRoot.querySelector('.icon') this.open=false; menu.addEventListener('click', e=>{if (!this.open){this.expand()}else{this.collapse()}}) menu.addEventListener('keydown', e=>{if (e.code==='ArrowDown' || e.code==='ArrowRight'){e.preventDefault() this.availableOptions[0].focus()}if (e.code==='Enter' || e.code==='Space'){e.preventDefault() if (!this.open){this.expand()}else{this.collapse()}}}) this.optionList.addEventListener('keydown', e=>{if (e.code==='ArrowUp' || e.code==='ArrowRight'){e.preventDefault() if (document.activeElement.previousElementSibling){document.activeElement.previousElementSibling.focus()}}if (e.code==='ArrowDown' || e.code==='ArrowLeft'){e.preventDefault() if (document.activeElement.nextElementSibling) document.activeElement.nextElementSibling.focus()}}) this.optionList.addEventListener('click', e=>{this.collapse()}) slot.addEventListener('slotchange', e=>{this.availableOptions=slot.assignedElements() this.containerDimensions=this.optionList.getBoundingClientRect() this.menuDimensions=menu.getBoundingClientRect() if (this.containerDimensions.left > this.containerDimensions.width){this.optionList.style.right=0}else{this.optionList.style.right='auto'}}); window.addEventListener('mousedown', e=>{if (!this.contains(e.target) && e.button !==2){this.collapse()}}) if (this.hasAttribute('set-context') && this.getAttribute('set-context')==='true'){this.parentNode.setAttribute('oncontextmenu', 'return false') this.parentNode.addEventListener('mouseup', e=>{if (e.button===2){this.expand()}})}const intersectionObserver=new IntersectionObserver(entries=>{entries.forEach(entry=>{if (!entry.isIntersecting && this.open){if (window.innerHeight - entry.intersectionRect.top < this.containerDimensions.height) this.optionList.classList.add('moveUp') else this.optionList.classList.remove('moveUp') if (entry.intersectionRect.left > this.containerDimensions.width){this.optionList.style.right=0}else{this.optionList.style.right='auto'}}})},{threshold: 1}) intersectionObserver.observe(this.optionList)}})// optionconst smMenuOption=document.createElement('template')smMenuOption.innerHTML=`
`;customElements.define('sm-menu-option', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smMenuOption.content.cloneNode(true))}connectedCallback(){this.addEventListener('keyup', e=>{if (e.code==='Enter' || e.code==='Space'){e.preventDefault() this.click()}}) this.setAttribute('tabindex', '0')}})// tab-headerconst smTabHeader=document.createElement('template')smTabHeader.innerHTML=`
`;customElements.define('sm-tab-header', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smTabHeader.content.cloneNode(true)) this.indicator=this.shadowRoot.querySelector('.indicator'); this.tabSlot=this.shadowRoot.querySelector('slot'); this.tabHeader=this.shadowRoot.querySelector('.tab-header');}sendDetails(element){this.dispatchEvent( new CustomEvent("switchtab",{bubbles: true, detail:{target: this.target, rank: parseInt(element.getAttribute('rank'))}}) )}connectedCallback(){if (!this.hasAttribute('target') || this.getAttribute('target').value==='') return; this.prevTab this.allTabs this.activeTab this.target=this.getAttribute('target') this.tabSlot.addEventListener('slotchange', ()=>{this.tabSlot.assignedElements().forEach((tab, index)=>{tab.setAttribute('rank', index)})}) this.allTabs=this.tabSlot.assignedElements(); this.tabSlot.addEventListener('click', e=>{if (e.target===this.prevTab || !e.target.closest('sm-tab')) return if (this.prevTab) this.prevTab.classList.remove('active') e.target.classList.add('active') e.target.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'center'}) this.indicator.setAttribute('style', `width: ${e.target.getBoundingClientRect().width}px; transform: translateX(${e.target.getBoundingClientRect().left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`) this.sendDetails(e.target) this.prevTab=e.target; this.activeTab=e.target;}) let resizeObserver=new ResizeObserver(entries=>{entries.forEach((entry)=>{if (this.prevTab){let tabDimensions=this.activeTab.getBoundingClientRect(); this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`)}})}) resizeObserver.observe(this) let observer=new IntersectionObserver((entries)=>{entries.forEach((entry)=>{if (entry.isIntersecting){this.indicator.style.transition='none' if (this.activeTab){let tabDimensions=this.activeTab.getBoundingClientRect(); this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`)}else{this.allTabs[0].classList.add('active') let tabDimensions=this.allTabs[0].getBoundingClientRect(); this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`) this.sendDetails(this.allTabs[0]) this.prevTab=this.tabSlot.assignedElements()[0]; this.activeTab=this.prevTab;}}})},{threshold: 1.0}) observer.observe(this)}})// tab-panelsconst smTabPanels=document.createElement('template')smTabPanels.innerHTML=`
Nothing to see here.
`;customElements.define('sm-tab-panels', class extends HTMLElement{constructor(){super() this.attachShadow({mode: 'open'}).append(smTabPanels.content.cloneNode(true)) this.panelSlot=this.shadowRoot.querySelector('slot');}connectedCallback(){//animations let flyInLeft=[{opacity: 0, transform: 'translateX(-1rem)'},{opacity: 1, transform: 'none'}], flyInRight=[{opacity: 0, transform: 'translateX(1rem)'},{opacity: 1, transform: 'none'}], flyOutLeft=[{opacity: 1, transform: 'none'},{opacity: 0, transform: 'translateX(-1rem)'}], flyOutRight=[{opacity: 1, transform: 'none'},{opacity: 0, transform: 'translateX(1rem)'}], animationOptions={duration: 300, fill: 'forwards', easing: 'ease'}this.prevPanel this.allPanels this.previousRank this.panelSlot.addEventListener('slotchange', ()=>{this.panelSlot.assignedElements().forEach((panel)=>{panel.classList.add('hide-completely')})}) this.allPanels=this.panelSlot.assignedElements() this._targetBodyFlyRight=(targetBody)=>{targetBody.classList.remove('hide-completely') targetBody.animate(flyInRight, animationOptions)}this._targetBodyFlyLeft=(targetBody)=>{targetBody.classList.remove('hide-completely') targetBody.animate(flyInLeft, animationOptions)}document.addEventListener('switchtab', e=>{if (e.detail.target !==this.id) return if (this.prevPanel){let targetBody=this.allPanels[e.detail.rank], currentBody=this.prevPanel; if (this.previousRank < e.detail.rank){if (currentBody && !targetBody) currentBody.animate(flyOutLeft, animationOptions).onfinish=()=>{currentBody.classList.add('hide-completely')}else if (targetBody && !currentBody){this._targetBodyFlyRight(targetBody)}else if (currentBody && targetBody){currentBody.animate(flyOutLeft, animationOptions).onfinish=()=>{currentBody.classList.add('hide-completely') this._targetBodyFlyRight(targetBody)}}}else{if (currentBody && !targetBody) currentBody.animate(flyOutRight, animationOptions).onfinish=()=>{currentBody.classList.add('hide-completely')}else if (targetBody && !currentBody){this._targetBodyFlyLeft(targetBody)}else if (currentBody && targetBody){currentBody.animate(flyOutRight, animationOptions).onfinish=()=>{currentBody.classList.add('hide-completely') this._targetBodyFlyLeft(targetBody)}}}}else{this.allPanels[e.detail.rank].classList.remove('hide-completely')}this.previousRank=e.detail.rank this.prevPanel=this.allPanels[e.detail.rank];})}}) \ No newline at end of file diff --git a/Standard UI Components/components.ts b/Standard UI Components/components.ts deleted file mode 100644 index 0ecb216..0000000 --- a/Standard UI Components/components.ts +++ /dev/null @@ -1,3591 +0,0 @@ -//Button -const smButton = document.createElement('template') -smButton.innerHTML = ` - -
- -
`; -customElements.define('sm-button', - class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smButton.content.cloneNode(true)) - } - - get disabled() { - return this.isDisabled - } - - set disabled(value) { - if (value && !this.isDisabled) { - this.isDisabled = true - this.setAttribute('disabled', '') - this.button.removeAttribute('tabindex') - } else if (!value && this.isDisabled) { - this.isDisabled = false - this.removeAttribute('disabled') - } - } - - dispatch() { - if (this.isDisabled) { - this.dispatchEvent(new CustomEvent('disabled', { - bubbles: true, - composed: true - })) - } else { - this.dispatchEvent(new CustomEvent('clicked', { - bubbles: true, - composed: true - })) - } - } - - connectedCallback() { - this.isDisabled = false - this.button = this.shadowRoot.querySelector('.button') - if (this.hasAttribute('disabled') && !this.isDisabled) - this.isDisabled = true - this.addEventListener('click', (e) => { - this.dispatch() - }) - this.addEventListener('keyup', (e) => { - if (e.code === "Enter" || e.code === "Space") - this.dispatch() - }) - } - }) - -//Input -const smInput = document.createElement('template') -smInput.innerHTML = ` - -
- - -
-`; -customElements.define('sm-input', - class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smInput.content.cloneNode(true)) - } - static get observedAttributes() { - return ['placeholder'] - } - - get value() { - return this.shadowRoot.querySelector('input').value - } - - set value(val) { - this.shadowRoot.querySelector('input').value = val; - this.checkInput() - this.fireEvent() - } - - get placeholder() { - return this.getAttribute('placeholder') - } - - set placeholder(val) { - this.setAttribute('placeholder', val) - } - - get type() { - return this.getAttribute('type') - } - - get isValid() { - 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') - else - this.shadowRoot.querySelector('.input').classList.remove('disabled') - } - set readOnly(value) { - if (value) { - this.shadowRoot.querySelector('input').setAttribute('readonly', '') - this.shadowRoot.querySelector('.input').classList.add('readonly') - } else { - this.shadowRoot.querySelector('input').removeAttribute('readonly') - this.shadowRoot.querySelector('.input').classList.remove('readonly') - } - } - - setValidity = (message) => { - this.feedbackText.textContent = message - } - - showValidity = () => { - this.feedbackText.classList.remove('hide-completely') - } - - hideValidity = () => { - this.feedbackText.classList.add('hide-completely') - } - - focusIn = () => { - this.input.focus() - } - - focusOut = () => { - this.input.blur() - } - - fireEvent = () => { - let event = new Event('input', { - bubbles: true, - cancelable: true, - composed: true - }); - this.dispatchEvent(event); - } - - checkInput = (e) => { - 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') - } - } - - - connectedCallback() { - this.inputParent = this.shadowRoot.querySelector('.input') - this.clearBtn = this.shadowRoot.querySelector('.clear') - this.label = this.shadowRoot.querySelector('.label') - 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') - this.input = this.shadowRoot.querySelector('input') - this.shadowRoot.querySelector('.label').textContent = this.getAttribute('placeholder') - if (this.hasAttribute('value')) { - this.input.value = this.getAttribute('value') - this.checkInput(e) - } - if (this.hasAttribute('required')) { - this.input.setAttribute('required', '') - } - if (this.hasAttribute('min')) { - let minValue = this.getAttribute('min') - this.input.setAttribute('min', minValue) - this.min = parseInt(minValue) - } - if (this.hasAttribute('max')) { - let maxValue = this.getAttribute('max') - this.input.setAttribute('max', maxValue) - this.max = parseInt(maxValue) - } - if (this.hasAttribute('minlength')) { - let minValue = this.getAttribute('minlength') - this.input.setAttribute('minlength', minValue) - } - if (this.hasAttribute('maxlength')) { - let maxValue = this.getAttribute('maxlength') - this.input.setAttribute('maxlength', maxValue) - } - if (this.hasAttribute('pattern')) { - this.input.setAttribute('pattern', this.getAttribute('pattern')) - } - if (this.hasAttribute('readonly')) { - this.input.setAttribute('readonly', '') - this.readonly = true - } - if (this.hasAttribute('disabled')) { - this.inputParent.classList.add('disabled') - } - 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('input', e => { - this.checkInput(e) - }) - this.clearBtn.addEventListener('click', e => { - this.value = '' - }) - } - - attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - if (name === 'placeholder') { - this.shadowRoot.querySelector('.label').textContent = newValue; - this.setAttribute('aria-label', newValue); - } - } - } - }) - -//textarea -const smTextarea = document.createElement('template') -smTextarea.innerHTML = ` - - -`; -customElements.define('sm-textarea', - class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smTextarea.content.cloneNode(true)) - } - static get observedAttributes() { - return ['placeholder'] - } - - get value() { - return this.shadowRoot.querySelector('textarea').value - } - - set value(val) { - this.shadowRoot.querySelector('textarea').value = val; - this.checkInput() - this.fireEvent() - } - - get placeholder() { - return this.getAttribute('placeholder') - } - - set placeholder(val) { - this.setAttribute('placeholder', val) - } - - fireEvent() { - let event = new Event('input', { - bubbles: true, - cancelable: true, - composed: true - }); - this.dispatchEvent(event); - } - - checkInput() { - 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') - } else { - if (this.animate) - this.inputParent.classList.remove('animate-label') - else - this.label.classList.remove('hide') - } - - this.input.style.height = 'auto' - this.input.style.height = (this.input.scrollHeight) + 'px'; - } - - - connectedCallback() { - this.inputParent = this.shadowRoot.querySelector('.input') - this.clearBtn = this.shadowRoot.querySelector('.clear') - this.label = this.shadowRoot.querySelector('.label') - this.valueChanged = false; - this.animate = this.hasAttribute('animate') - this.input = this.shadowRoot.querySelector('textarea') - this.shadowRoot.querySelector('.label').textContent = this.getAttribute('placeholder') - - this.input.setAttribute('style', 'height:' + (this.input.scrollHeight) + 'px;overflow-y:hidden;'); - - if (this.hasAttribute('value')) { - this.input.value = this.getAttribute('value') - this.checkInput() - } - if (this.hasAttribute('required')) { - this.input.setAttribute('required', '') - } - if (this.hasAttribute('readonly')) { - this.input.setAttribute('readonly', '') - } - this.input.addEventListener('input', e => { - this.checkInput() - }) - this.clearBtn.addEventListener('click', e => { - this.value = '' - }) - } - - attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - if (name === 'placeholder') - this.shadowRoot.querySelector('.label').textContent = newValue; - } - } - }) - -// tab -const smTab = document.createElement('template') -smTab.innerHTML = ` - -
- -
-`; - -customElements.define('sm-tab', class extends HTMLElement { - constructor() { - super() - this.shadow = this.attachShadow({ - mode: 'open' - }).append(smTab.content.cloneNode(true)) - } -}) - -//chcekbox - -const smCheckbox = document.createElement('template') -smCheckbox.innerHTML = ` - -` -customElements.define('sm-checkbox', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smCheckbox.content.cloneNode(true)) - - this.checkbox = this.shadowRoot.querySelector('.checkbox'); - this.input = this.shadowRoot.querySelector('input') - - this.isChecked = false - this.isDisabled = false - } - - static get observedAttributes() { - return ['disabled', 'checked'] - } - - get disabled() { - return this.getAttribute('disabled') - } - - set disabled(val) { - this.setAttribute('disabled', val) - } - - get checked() { - return this.getAttribute('checked') - } - - set checked(value) { - this.setAttribute('checked', 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) - } - }) - } - attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - if (name === 'disabled') { - if (newValue === 'true') { - this.checkbox.classList.add('disabled') - this.isDisabled = true - } else { - this.checkbox.classList.remove('disabled') - this.isDisabled = false - } - } - if (name === 'checked') { - if (newValue == 'true') { - this.isChecked = true - this.input.checked = true - this.dispatch() - } else { - this.isChecked = false - this.input.checked = false - this.dispatch() - } - } - } - } - -}) - -//switch - -const smSwitch = document.createElement('template') -smSwitch.innerHTML = ` - -` - -customElements.define('sm-switch', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smSwitch.content.cloneNode(true)) - this.switch = this.shadowRoot.querySelector('.switch'); - this.input = this.shadowRoot.querySelector('input') - this.isChecked = false - this.isDisabled = false - } - - get disabled() { - return this.getAttribute('disabled') - } - - set disabled(val) { - if (val) { - this.disabled = true - this.setAttribute('disabled', '') - this.switch.classList.add('disabled') - } else { - this.disabled = false - this.removeAttribute('disabled') - this.switch.classList.remove('disabled') - - } - } - - get checked() { - return this.isChecked - } - - set checked(value) { - if (value) { - this.setAttribute('checked', '') - this.isChecked = true - this.input.checked = true - } else { - this.removeAttribute('checked') - this.isChecked = false - this.input.checked = false - } - } - - dispatch = () => { - this.dispatchEvent(new CustomEvent('change', { - bubbles: true, - composed: true - })) - } - - connectedCallback() { - if (this.hasAttribute('disabled')) - this.switch.classList.add('disabled') - this.addEventListener('keyup', e => { - if ((e.code === "Enter" || e.code === "Space") && !this.isDisabled) { - this.input.click() - } - }) - this.input.addEventListener('click', e => { - if (this.input.checked) - this.checked = true - else - this.checked = false - this.dispatch() - }) - } -}) - -// select -const smSelect = document.createElement('template') -smSelect.innerHTML = ` - -
-
-
- - - -
-
- -
-
`; -customElements.define('sm-select', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smSelect.content.cloneNode(true)) - } - static get observedAttributes() { - return ['value'] - } - get value() { - return this.getAttribute('value') - } - set value(val) { - this.setAttribute('value', val) - } - - collapse() { - this.optionList.animate(this.slideUp, this.animationOptions) - this.optionList.classList.add('hide') - this.chevron.classList.remove('rotate') - this.open = false - } - connectedCallback() { - this.availableOptions - this.optionList = this.shadowRoot.querySelector('.options') - this.chevron = this.shadowRoot.querySelector('.toggle') - let slot = this.shadowRoot.querySelector('.options slot'), - selection = this.shadowRoot.querySelector('.selection'), - previousOption - this.open = false; - this.slideDown = [{ - transform: `translateY(-0.5rem)` - }, - { - transform: `translateY(0)` - } - ], - this.slideUp = [{ - transform: `translateY(0)` - }, - { - transform: `translateY(-0.5rem)` - } - ], - this.animationOptions = { - duration: 300, - fill: "forwards", - easing: 'ease' - } - selection.addEventListener('click', e => { - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.animate(this.slideDown, this.animationOptions) - this.chevron.classList.add('rotate') - this.open = true - } else { - this.collapse() - } - }) - selection.addEventListener('keydown', e => { - if (e.code === 'ArrowDown' || e.code === 'ArrowRight') { - e.preventDefault() - this.availableOptions[0].focus() - } - if (e.code === 'Enter' || e.code === 'Space') - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.animate(this.slideDown, this.animationOptions) - this.chevron.classList.add('rotate') - this.open = true - } else { - this.collapse() - } - }) - this.optionList.addEventListener('keydown', e => { - if (e.code === 'ArrowUp' || e.code === 'ArrowRight') { - e.preventDefault() - if (document.activeElement.previousElementSibling) { - document.activeElement.previousElementSibling.focus() - } - } - if (e.code === 'ArrowDown' || e.code === 'ArrowLeft') { - e.preventDefault() - if (document.activeElement.nextElementSibling) - document.activeElement.nextElementSibling.focus() - } - }) - this.addEventListener('optionSelected', e => { - if (previousOption !== e.target) { - this.setAttribute('value', e.detail.value) - this.shadowRoot.querySelector('.option-text').textContent = e.detail.text; - this.dispatchEvent(new CustomEvent('change', { - bubbles: true, - composed: true - })) - if (previousOption) { - previousOption.classList.remove('check-selected') - } - previousOption = e.target; - } - if (!e.detail.switching) - this.collapse() - - e.target.classList.add('check-selected') - }) - slot.addEventListener('slotchange', e => { - this.availableOptions = slot.assignedElements() - if (this.availableOptions[0]) { - let firstElement = this.availableOptions[0]; - previousOption = firstElement; - firstElement.classList.add('check-selected') - this.setAttribute('value', firstElement.getAttribute('value')) - this.shadowRoot.querySelector('.option-text').textContent = firstElement.textContent - this.availableOptions.forEach((element, index) => { - element.setAttribute('data-rank', index + 1); - element.setAttribute('tabindex', "0"); - }) - } - }); - document.addEventListener('mousedown', e => { - if (!this.contains(e.target) && this.open) { - this.collapse() - } - }) - } -}) - -// option -const smOption = document.createElement('template') -smOption.innerHTML = ` - -
- - - - -
`; -customElements.define('sm-option', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smOption.content.cloneNode(true)) - } - - sendDetails(switching) { - let optionSelected = new CustomEvent('optionSelected', { - bubbles: true, - composed: true, - detail: { - text: this.textContent, - value: this.getAttribute('value'), - switching: switching - } - }) - this.dispatchEvent(optionSelected) - } - - connectedCallback() { - let validKey = [ - 'ArrowUp', - 'ArrowDown', - 'ArrowLeft', - 'ArrowRight' - ] - this.addEventListener('click', e => { - this.sendDetails() - }) - this.addEventListener('keyup', e => { - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - this.sendDetails(false) - } - if (validKey.includes(e.code)) { - e.preventDefault() - this.sendDetails(true) - } - }) - if (this.hasAttribute('default')) { - setTimeout(() => { - this.sendDetails() - }, 0); - } - } -}) - -// select -const smStripSelect = document.createElement('template') -smStripSelect.innerHTML = ` - -
-
- - Previous - - -
- -
- - Next - - -
-
`; -customElements.define('sm-strip-select', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smStripSelect.content.cloneNode(true)) - } - static get observedAttributes() { - return ['value'] - } - get value() { - return this.getAttribute('value') - } - set value(val) { - this.setAttribute('value', val) - } - scrollLeft = () => { - this.select.scrollBy({ - top: 0, - left: -this.scrollDistance, - behavior: 'smooth' - }) - } - - scrollRight = () => { - this.select.scrollBy({ - top: 0, - left: this.scrollDistance, - behavior: 'smooth' - }) - } - connectedCallback() { - let previousOption, - slot = this.shadowRoot.querySelector('slot'); - this.selectContainer = this.shadowRoot.querySelector('.select-container') - this.select = this.shadowRoot.querySelector('.select') - this.nextArrow = this.shadowRoot.querySelector('.next-item') - this.previousArrow = this.shadowRoot.querySelector('.previous-item') - this.nextGradient = this.shadowRoot.querySelector('.right') - this.previousGradient = this.shadowRoot.querySelector('.left') - this.selectOptions - this.scrollDistance = this.selectContainer.getBoundingClientRect().width - const firstElementObserver = new IntersectionObserver(entries => { - if (entries[0].isIntersecting) { - this.previousArrow.classList.add('hide') - this.previousGradient.classList.add('hide') - } else { - this.previousArrow.classList.remove('hide') - this.previousGradient.classList.remove('hide') - } - }, { - root: this.selectContainer, - threshold: 0.95 - }) - const lastElementObserver = new IntersectionObserver(entries => { - if (entries[0].isIntersecting) { - this.nextArrow.classList.add('hide') - this.nextGradient.classList.add('hide') - } else { - this.nextArrow.classList.remove('hide') - this.nextGradient.classList.remove('hide') - } - }, { - root: this.selectContainer, - threshold: 0.95 - }) - - const selectObserver = new IntersectionObserver(entries => { - if (entries[0].isIntersecting) { - this.scrollDistance = this.selectContainer.getBoundingClientRect().width - } - }) - - selectObserver.observe(this.selectContainer) - this.addEventListener('optionSelected', e => { - if (previousOption === e.target) return; - if (previousOption) - previousOption.classList.remove('active') - e.target.classList.add('active') - e.target.scrollIntoView({ - behavior: 'smooth', - inline: 'center', - block: 'nearest' - }) - this.setAttribute('value', e.detail.value) - this.dispatchEvent(new CustomEvent('change', { - bubbles: true, - composed: true - })) - previousOption = e.target; - }) - slot.addEventListener('slotchange', e => { - this.selectOptions = slot.assignedElements() - firstElementObserver.observe(this.selectOptions[0]) - lastElementObserver.observe(this.selectOptions[this.selectOptions.length - 1]) - if (this.selectOptions[0]) { - let firstElement = this.selectOptions[0]; - this.setAttribute('value', firstElement.getAttribute('value')) - firstElement.classList.add('active') - previousOption = firstElement; - } - }); - this.nextArrow.addEventListener('click', this.scrollRight) - this.previousArrow.addEventListener('click', this.scrollLeft) - } - - disconnectedCallback() { - this.nextArrow.removeEventListener('click', this.scrollRight) - this.previousArrow.removeEventListener('click', this.scrollLeft) - } -}) - -// option -const smStripOption = document.createElement('template') -smStripOption.innerHTML = ` - -
- -
`; -customElements.define('sm-strip-option', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smStripOption.content.cloneNode(true)) - } - sendDetails() { - let optionSelected = new CustomEvent('optionSelected', { - bubbles: true, - composed: true, - detail: { - text: this.textContent, - value: this.getAttribute('value') - } - }) - this.dispatchEvent(optionSelected) - } - - connectedCallback() { - this.addEventListener('click', e => { - this.sendDetails() - }) - this.addEventListener('keyup', e => { - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - this.sendDetails(false) - } - }) - if (this.hasAttribute('default')) { - setTimeout(() => { - this.sendDetails() - }, 0); - } - } -}) - -//popup -const smPopup = document.createElement('template') -smPopup.innerHTML = ` - - -`; -customElements.define('sm-popup', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smPopup.content.cloneNode(true)) - - this.allowClosing = false - } - - resumeScrolling = () => { - const scrollY = document.body.style.top; - window.scrollTo(0, parseInt(scrollY || '0') * -1); - setTimeout(() => { - document.body.setAttribute('style', `overflow: auto; top: initial`) - }, 300); - } - - show = (pinned, popupStack) => { - if (popupStack) - this.popupStack = popupStack - if (this.popupStack && !this.hasAttribute('open')) { - this.popupStack.push({ - popup: this, - permission: pinned - }) - if (this.popupStack.items.length > 1) { - this.popupStack.items[this.popupStack.items.length - 2].popup.classList.add('stacked') - } - this.dispatchEvent( - new CustomEvent("popupopened", { - bubbles: true, - detail: { - popup: this, - popupStack: this.popupStack - } - }) - ) - this.setAttribute('open', '') - this.pinned = pinned - } - this.popupContainer.classList.remove('hide') - this.popup.style.transform = 'translateY(0)'; - document.body.setAttribute('style', `overflow: hidden; top: -${window.scrollY}px`) - return this.popupStack - } - hide = () => { - if (window.innerWidth < 640) - this.popup.style.transform = 'translateY(100%)'; - else - this.popup.style.transform = 'translateY(1rem)'; - this.popupContainer.classList.add('hide') - this.removeAttribute('open') - if (typeof this.popupStack !== 'undefined') { - this.popupStack.pop() - if (this.popupStack.items.length) { - this.popupStack.items[this.popupStack.items.length - 1].popup.classList.remove('stacked') - } else { - this.resumeScrolling() - } - } else { - this.resumeScrolling() - } - - if (this.inputFields.length) { - setTimeout(() => { - this.inputFields.forEach(field => { - if (field.type === 'radio' || field.tagName === 'SM-CHECKBOX') - field.checked = false - if (field.tagName === 'SM-INPUT' || field.tagName === 'TEXTAREA') - field.value = '' - }) - }, 300); - } - this.dispatchEvent( - new CustomEvent("popupclosed", { - bubbles: true, - detail: { - popup: this, - popupStack: this.popupStack - } - }) - ) - } - - handleTouchStart = (e) => { - this.touchStartY = e.changedTouches[0].clientY - this.popup.style.transition = 'transform 0.1s' - this.touchStartTime = e.timeStamp - } - - handleTouchMove = (e) => { - e.preventDefault() - if (this.touchStartY < e.changedTouches[0].clientY) { - this.offset = e.changedTouches[0].clientY - this.touchStartY; - this.touchEndAnimataion = window.requestAnimationFrame(() => this.movePopup()) - } - /*else { - this.offset = this.touchStartY - e.changedTouches[0].clientY; - this.popup.style.transform = `translateY(-${this.offset}px)` - }*/ - } - - handleTouchEnd = (e) => { - this.touchEndTime = e.timeStamp - cancelAnimationFrame(this.touchEndAnimataion) - this.touchEndY = e.changedTouches[0].clientY - this.popup.style.transition = 'transform 0.3s' - if (this.touchEndTime - this.touchStartTime > 200) { - if (this.touchEndY - this.touchStartY > this.threshold) { - if (this.pinned) { - this.show() - return - } else - this.hide() - } else { - this.show() - } - } else { - if (this.touchEndY > this.touchStartY) - if (this.pinned) { - this.show() - return - } - else - this.hide() - } - } - - movePopup = () => { - this.popup.style.transform = `translateY(${this.offset}px)` - } - - connectedCallback() { - this.pinned = false - this.popupStack - this.popupContainer = this.shadowRoot.querySelector('.popup-container') - this.popup = this.shadowRoot.querySelector('.popup') - this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot') - this.offset - this.popupHeader = this.shadowRoot.querySelector('.popup-top') - this.touchStartY = 0 - this.touchEndY = 0 - this.touchStartTime = 0 - this.touchEndTime = 0 - this.touchEndAnimataion; - this.threshold - - if (this.hasAttribute('open')) - this.show() - this.popupContainer.addEventListener('mousedown', e => { - if (e.target === this.popupContainer && !this.pinned) { - if (this.pinned) { - this.show() - return - } else - this.hide() - } - }) - - this.popupBodySlot.addEventListener('slotchange', () => { - setTimeout(() => { - this.threshold = this.popup.getBoundingClientRect().height * 0.3 - }, 200); - this.inputFields = this.querySelectorAll('sm-input', 'sm-checkbox', 'textarea', 'radio') - }) - - this.popupHeader.addEventListener('touchstart', (e) => { - this.handleTouchStart(e) - }) - this.popupHeader.addEventListener('touchmove', (e) => { - this.handleTouchMove(e) - }) - this.popupHeader.addEventListener('touchend', (e) => { - this.handleTouchEnd(e) - }) - } - disconnectedCallback() { - this.popupHeader.removeEventListener('touchstart', this.handleTouchStart) - this.popupHeader.removeEventListener('touchmove', this.handleTouchMove) - this.popupHeader.removeEventListener('touchend', this.handleTouchEnd) - } -}) - -//carousel - -const smCarousel = document.createElement('template') -smCarousel.innerHTML = ` - - -`; - -customElements.define('sm-carousel', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smCarousel.content.cloneNode(true)) - } - - static get observedAttributes() { - return ['indicator'] - } - - scrollLeft = () => { - this.carousel.scrollBy({ - top: 0, - left: -this.scrollDistance, - behavior: 'smooth' - }) - } - - scrollRight = () => { - this.carousel.scrollBy({ - top: 0, - left: this.scrollDistance, - behavior: 'smooth' - }) - } - - connectedCallback() { - this.carousel = this.shadowRoot.querySelector('.carousel') - this.carouselContainer = this.shadowRoot.querySelector('.carousel-container') - this.carouselSlot = this.shadowRoot.querySelector('slot') - this.nextArrow = this.shadowRoot.querySelector('.next-item') - this.previousArrow = this.shadowRoot.querySelector('.previous-item') - this.indicatorsContainer = this.shadowRoot.querySelector('.indicators') - this.carouselItems - this.indicators - this.showIndicator = false - this.scrollDistance = this.carouselContainer.getBoundingClientRect().width / 3 - let frag = document.createDocumentFragment(); - if (this.hasAttribute('indicator')) - this.showIndicator = true - - - let firstVisible = false, - lastVisible = false - const allElementsObserver = new IntersectionObserver(entries => { - entries.forEach(entry => { - if (this.showIndicator) - if (entry.isIntersecting) { - this.indicators[parseInt(entry.target.attributes.rank.textContent)].classList.add('active') - } - else - this.indicators[parseInt(entry.target.attributes.rank.textContent)].classList.remove('active') - if (!entry.target.previousElementSibling) - if (entry.isIntersecting) { - this.previousArrow.classList.remove('expand') - firstVisible = true - } - else { - this.previousArrow.classList.add('expand') - firstVisible = false - } - if (!entry.target.nextElementSibling) - if (entry.isIntersecting) { - this.nextArrow.classList.remove('expand') - lastVisible = true - } - else { - this.nextArrow.classList.add('expand') - - lastVisible = false - } - if (firstVisible && lastVisible) - this.indicatorsContainer.classList.add('hide') - else - this.indicatorsContainer.classList.remove('hide') - }) - }, { - root: this.carouselContainer, - threshold: 0.9 - }) - - const carouselObserver = new IntersectionObserver(entries => { - if (entries[0].isIntersecting) { - this.scrollDistance = this.carouselContainer.getBoundingClientRect().width / 3 - } - }) - - carouselObserver.observe(this.carouselContainer) - - this.carouselSlot.addEventListener('slotchange', e => { - this.carouselItems = this.carouselSlot.assignedElements() - this.carouselItems.forEach(item => allElementsObserver.observe(item)) - if (this.showIndicator) { - this.indicatorsContainer.innerHTML = `` - this.carouselItems.forEach((item, index) => { - let dot = document.createElement('div') - dot.classList.add('dot') - frag.append(dot) - item.setAttribute('rank', index) - }) - this.indicatorsContainer.append(frag) - this.indicators = this.indicatorsContainer.children - } - }) - - this.addEventListener('keyup', e => { - if (e.code === 'ArrowLeft') - this.scrollRight() - else - this.scrollRight() - }) - - this.nextArrow.addEventListener('click', this.scrollRight) - this.previousArrow.addEventListener('click', this.scrollLeft) - } - - attributeChangedCallback(name, oldValue, newValue) { - if (name === 'indicator') { - if (this.hasAttribute('indicator')) - this.showIndicator = true - else - this.showIndicator = false - } - } - - disconnectedCallback() { - this.nextArrow.removeEventListener('click', this.scrollRight) - this.previousArrow.removeEventListener('click', this.scrollLeft) - } -}) - -//notifications - -const smNotifications = document.createElement('template') -smNotifications.innerHTML = ` - -
-
-` - -customElements.define('sm-notifications', class extends HTMLElement { - constructor() { - super() - this.shadow = this.attachShadow({ - mode: 'open' - }).append(smNotifications.content.cloneNode(true)) - } - - handleTouchStart = (e) => { - this.notification = e.target.closest('.notification') - this.touchStartX = e.changedTouches[0].clientX - this.notification.style.transition = 'initial' - this.touchStartTime = e.timeStamp - } - - handleTouchMove = (e) => { - e.preventDefault() - if (this.touchStartX < e.changedTouches[0].clientX) { - this.offset = e.changedTouches[0].clientX - this.touchStartX; - this.touchEndAnimataion = requestAnimationFrame(this.movePopup) - } else { - this.offset = -(this.touchStartX - e.changedTouches[0].clientX); - this.touchEndAnimataion = requestAnimationFrame(this.movePopup) - } - } - - handleTouchEnd = (e) => { - this.notification.style.transition = 'transform 0.3s, opacity 0.3s' - this.touchEndTime = e.timeStamp - cancelAnimationFrame(this.touchEndAnimataion) - this.touchEndX = e.changedTouches[0].clientX - if (this.touchEndTime - this.touchStartTime > 200) { - if (this.touchEndX - this.touchStartX > this.threshold) { - this.removeNotification(this.notification) - } else if (this.touchStartX - this.touchEndX > this.threshold) { - this.removeNotification(this.notification, true) - } else { - this.resetPosition() - } - } else { - if (this.touchEndX > this.touchStartX) { - this.removeNotification(this.notification) - } else { - this.removeNotification(this.notification, true) - } - } - } - - movePopup = () => { - this.notification.style.transform = `translateX(${this.offset}px)` - } - - resetPosition = () => { - this.notification.style.transform = `translateX(0)` - } - - push = (messageBody, type, pinned) => { - let notification = document.createElement('div'), - composition = `` - notification.classList.add('notification') - if (pinned) - notification.classList.add('pinned') - if (type === 'error') { - composition += ` - - - - - ` - } else if (type === 'success') { - composition += ` - - - ` - } - composition += ` -

${messageBody}

- - Close - - - ` - notification.innerHTML = composition - this.notificationPanel.prepend(notification) - if (window.innerWidth > 640) { - notification.animate([{ - transform: `translateX(1rem)`, - opacity: '0' - }, - { - transform: 'translateX(0)', - opacity: '1' - } - ], this.animationOptions).onfinish = () => { - notification.setAttribute('style', `transform: none;`); - } - } else { - notification.setAttribute('style', `transform: translateY(0); opacity: 1`) - } - notification.addEventListener('touchstart', this.handleTouchStart) - notification.addEventListener('touchmove', this.handleTouchMove) - notification.addEventListener('touchend', this.handleTouchEnd) - } - - removeNotification = (notification, toLeft) => { - if (!this.offset) - this.offset = 0; - - if (toLeft) - notification.animate([{ - transform: `translateX(${this.offset}px)`, - opacity: '1' - }, - { - transform: `translateX(-100%)`, - opacity: '0' - } - ], this.animationOptions).onfinish = () => { - notification.remove() - } - else { - notification.animate([{ - transform: `translateX(${this.offset}px)`, - opacity: '1' - }, - { - transform: `translateX(100%)`, - opacity: '0' - } - ], this.animationOptions).onfinish = () => { - notification.remove() - } - } - } - - clearAll = () => { - Array.from(this.notificationPanel.children).forEach(child => { - this.removeNotification(child) - }) - } - - connectedCallback() { - this.notificationPanel = this.shadowRoot.querySelector('.notification-panel') - this.animationOptions = { - duration: 300, - fill: "forwards", - easing: "ease" - } - this.fontSize = Number(window.getComputedStyle(document.body).getPropertyValue('font-size').match(/\d+/)[0]) - this.notification - this.offset - this.touchStartX = 0 - this.touchEndX = 0 - this.touchStartTime = 0 - this.touchEndTime = 0 - this.threshold = this.notificationPanel.getBoundingClientRect().width * 0.3 - this.touchEndAnimataion; - - this.notificationPanel.addEventListener('click', e => { - if (e.target.closest('.close'))( - this.removeNotification(e.target.closest('.notification')) - ) - }) - - const observer = new MutationObserver(mutationList => { - mutationList.forEach(mutation => { - if (mutation.type === 'childList') { - if (mutation.addedNodes.length) { - if (!mutation.addedNodes[0].classList.contains('pinned')) - setTimeout(() => { - this.removeNotification(mutation.addedNodes[0]) - }, 5000); - if (window.innerWidth > 640) - this.notificationPanel.style.padding = '1.5rem 0 3rem 1.5rem'; - else - this.notificationPanel.style.padding = '1rem 1rem 2rem 1rem'; - } else if (mutation.removedNodes.length && !this.notificationPanel.children.length) { - this.notificationPanel.style.padding = 0; - } - } - }) - }) - observer.observe(this.notificationPanel, { - attributes: true, - childList: true, - subtree: true - }) - } -}) - - -// sm-menu -const smMenu = document.createElement('template') -smMenu.innerHTML = ` - -
- -
- -
-
`; -customElements.define('sm-menu', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smMenu.content.cloneNode(true)) - } - static get observedAttributes() { - return ['value'] - } - get value() { - return this.getAttribute('value') - } - set value(val) { - this.setAttribute('value', val) - } - expand = () => { - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.classList.add('no-transformations') - this.open = true - this.icon.classList.add('focused') - } - } - collapse() { - if (this.open) { - this.open = false - this.icon.classList.remove('focused') - this.optionList.classList.add('hide') - this.optionList.classList.remove('no-transformations') - } - } - connectedCallback() { - this.availableOptions - this.containerDimensions - this.optionList = this.shadowRoot.querySelector('.options') - let slot = this.shadowRoot.querySelector('.options slot'), - menu = this.shadowRoot.querySelector('.menu') - this.icon = this.shadowRoot.querySelector('.icon') - this.open = false; - menu.addEventListener('click', e => { - if (!this.open) { - this.expand() - } else { - this.collapse() - } - }) - menu.addEventListener('keydown', e => { - if (e.code === 'ArrowDown' || e.code === 'ArrowRight') { - e.preventDefault() - this.availableOptions[0].focus() - } - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - if (!this.open) { - this.expand() - } else { - this.collapse() - } - } - }) - this.optionList.addEventListener('keydown', e => { - if (e.code === 'ArrowUp' || e.code === 'ArrowRight') { - e.preventDefault() - if (document.activeElement.previousElementSibling) { - document.activeElement.previousElementSibling.focus() - } - } - if (e.code === 'ArrowDown' || e.code === 'ArrowLeft') { - e.preventDefault() - if (document.activeElement.nextElementSibling) - document.activeElement.nextElementSibling.focus() - } - }) - this.optionList.addEventListener('click', e => { - this.collapse() - }) - slot.addEventListener('slotchange', e => { - this.availableOptions = slot.assignedElements() - this.containerDimensions = this.optionList.getBoundingClientRect() - this.menuDimensions = menu.getBoundingClientRect() - }); - window.addEventListener('mousedown', e => { - if (!this.contains(e.target) && e.button !== 2) { - this.collapse() - } - }) - if (this.hasAttribute('set-context') && this.getAttribute('set-context') === 'true') { - this.parentNode.setAttribute('oncontextmenu', 'return false') - this.parentNode.addEventListener('mouseup', e => { - if (e.button === 2) { - this.expand() - } - }) - } - } -}) - -// option -const smMenuOption = document.createElement('template') -smMenuOption.innerHTML = ` - -
- -
`; -customElements.define('sm-menu-option', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smMenuOption.content.cloneNode(true)) - } - - connectedCallback() { - this.addEventListener('keyup', e => { - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - this.click() - } - }) - this.setAttribute('tabindex', '0') - } -}) - -// tab-header - -const smTabHeader = document.createElement('template') -smTabHeader.innerHTML = ` - -
-
- -
-
-
-`; - -customElements.define('sm-tab-header', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smTabHeader.content.cloneNode(true)) - - this.indicator = this.shadowRoot.querySelector('.indicator'); - this.tabSlot = this.shadowRoot.querySelector('slot'); - this.tabHeader = this.shadowRoot.querySelector('.tab-header'); - } - - sendDetails(element) { - this.dispatchEvent( - new CustomEvent("switchtab", { - bubbles: true, - detail: { - target: this.target, - rank: parseInt(element.getAttribute('rank')) - } - }) - ) - } - - moveIndiactor(tabDimensions) { - //if(this.isTab) - this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`) - //else - //this.indicator.setAttribute('style', `width: calc(${tabDimensions.width}px - 1.6rem); transform: translateX(calc(${ tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px + 0.8rem)`) - } - - connectedCallback() { - if (!this.hasAttribute('target') || this.getAttribute('target').value === '') return; - this.prevTab - this.allTabs - this.activeTab - this.isTab = false - this.target = this.getAttribute('target') - - if (this.hasAttribute('variant') && this.getAttribute('variant') === 'tab') { - this.isTab = true - } - - this.tabSlot.addEventListener('slotchange', () => { - this.tabSlot.assignedElements().forEach((tab, index) => { - tab.setAttribute('rank', index) - }) - }) - this.allTabs = this.tabSlot.assignedElements(); - - this.tabSlot.addEventListener('click', e => { - if (e.target === this.prevTab || !e.target.closest('sm-tab')) - return - if (this.prevTab) - this.prevTab.classList.remove('active') - e.target.classList.add('active') - - e.target.scrollIntoView({ - behavior: 'smooth', - block: 'nearest', - inline: 'center' - }) - this.moveIndiactor(e.target.getBoundingClientRect()) - this.sendDetails(e.target) - this.prevTab = e.target; - this.activeTab = e.target; - }) - let resizeObserver = new ResizeObserver(entries => { - entries.forEach((entry) => { - if (this.prevTab) { - let tabDimensions = this.activeTab.getBoundingClientRect(); - this.moveIndiactor(tabDimensions) - } - }) - }) - resizeObserver.observe(this) - let observer = new IntersectionObserver((entries) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - this.indicator.style.transition = 'none' - if (this.activeTab) { - let tabDimensions = this.activeTab.getBoundingClientRect(); - this.moveIndiactor(tabDimensions) - } else { - this.allTabs[0].classList.add('active') - let tabDimensions = this.allTabs[0].getBoundingClientRect(); - this.moveIndiactor(tabDimensions) - this.sendDetails(this.allTabs[0]) - this.prevTab = this.tabSlot.assignedElements()[0]; - this.activeTab = this.prevTab; - } - } - }) - }, { - threshold: 1.0 - }) - observer.observe(this) - } -}) - -// tab-panels - -const smTabPanels = document.createElement('template') -smTabPanels.innerHTML = ` - -
- Nothing to see here. -
-`; - -customElements.define('sm-tab-panels', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smTabPanels.content.cloneNode(true)) - this.panelSlot = this.shadowRoot.querySelector('slot'); - } - connectedCallback() { - - //animations - let flyInLeft = [{ - opacity: 0, - transform: 'translateX(-1rem)' - }, - { - opacity: 1, - transform: 'none' - } - ], - flyInRight = [{ - opacity: 0, - transform: 'translateX(1rem)' - }, - { - opacity: 1, - transform: 'none' - } - ], - flyOutLeft = [{ - opacity: 1, - transform: 'none' - }, - { - opacity: 0, - transform: 'translateX(-1rem)' - } - ], - flyOutRight = [{ - opacity: 1, - transform: 'none' - }, - { - opacity: 0, - transform: 'translateX(1rem)' - } - ], - animationOptions = { - duration: 300, - fill: 'forwards', - easing: 'ease' - } - this.prevPanel - this.allPanels - this.previousRank - - this.panelSlot.addEventListener('slotchange', () => { - this.panelSlot.assignedElements().forEach((panel) => { - panel.classList.add('hide-completely') - }) - }) - this.allPanels = this.panelSlot.assignedElements() - this._targetBodyFlyRight = (targetBody) => { - targetBody.classList.remove('hide-completely') - targetBody.animate(flyInRight, animationOptions) - } - this._targetBodyFlyLeft = (targetBody) => { - targetBody.classList.remove('hide-completely') - targetBody.animate(flyInLeft, animationOptions) - } - document.addEventListener('switchtab', e => { - if (e.detail.target !== this.id) - return - - if (this.prevPanel) { - let targetBody = this.allPanels[e.detail.rank], - currentBody = this.prevPanel; - if (this.previousRank < e.detail.rank) { - if (currentBody && !targetBody) - currentBody.animate(flyOutLeft, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - } - else if (targetBody && !currentBody) { - this._targetBodyFlyRight(targetBody) - } else if (currentBody && targetBody) { - currentBody.animate(flyOutLeft, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - this._targetBodyFlyRight(targetBody) - } - } - } else { - if (currentBody && !targetBody) - currentBody.animate(flyOutRight, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - } - else if (targetBody && !currentBody) { - this._targetBodyFlyLeft(targetBody) - } else if (currentBody && targetBody) { - currentBody.animate(flyOutRight, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - this._targetBodyFlyLeft(targetBody) - } - } - } - } else { - this.allPanels[e.detail.rank].classList.remove('hide-completely') - } - this.previousRank = e.detail.rank - this.prevPanel = this.allPanels[e.detail.rank]; - }) - } -}) - - -const slidingSection = document.createElement('template') -slidingSection.innerHTML = ` - -
- -
-` - -customElements.define('sm-sliding-section', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(slidingSection.content.cloneNode(true)) - } - connectedCallback() { - - } -}) - -const section = document.createElement('template') -section.innerHTML = ` - -
- -
-` - -customElements.define('sm-section', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(section.content.cloneNode(true)) - } -}) \ No newline at end of file diff --git a/Standard UI Components/tsconfig.json b/Standard UI Components/tsconfig.json deleted file mode 100644 index 8830f0a..0000000 --- a/Standard UI Components/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "ESNext", - "watch": true, - "lib": ["DOM", "ES2017"] - }, - "exclude": [ - "node_modules" - ] -} \ No newline at end of file diff --git a/Standard UI Components/.gitattributes b/components/.gitattributes similarity index 100% rename from Standard UI Components/.gitattributes rename to components/.gitattributes diff --git a/Standard UI Components/README.md b/components/README.md similarity index 96% rename from Standard UI Components/README.md rename to components/README.md index ef4600e..d4540e6 100644 --- a/Standard UI Components/README.md +++ b/components/README.md @@ -1,595 +1,595 @@ -# Components - -## Overview - -These components are based on HTML5 custom elements API. This is an attempt to unify UI development patterns and elements that are used multiple times throughout any general web app.It uses 'sm' namespace for all components. So every component tag starts with ***'sm-'.*** - -They can replace some older UI elements like `` `` ` -

SM Components

- - - -
-
-
-
-
Total components
-

-
-
-

Overview

-

- These components are based on HTML5 custom elements API. This is an attempt to unify UI - development - patterns and - elements that are used multiple times throughout any general web app.It uses 'sm' namespace for - all - components. So every - component tag starts with 'sm-' -

-

- They can replace some older UI elements like <select> - <input> - <checkbox> <button> - But also more modern additions like popups(modals), tabs and many more. -

-

- Some of the components have some cool tricks under their sleeves like custom events and - variantions. - They allow developers to access more information about component or simply react to whatever - state - change happen to them. - We will go more in-depth about all the variantions and customs events related to each event as - we go - further. -

-
-
- -
-

Quick Start

-

- To start using SM Components, Select components you want to download. -

-
- - - Get minified - - - Select all - Clear all -
-
-
- Copy source code - Download JS file -
-
- -
-

Buttons

-

- Buttons are used in various basic UI interactions to perform an action. -

- default - primary - outlined - no-outline - disabled -
-                    
-                        <sm-button>default</sm-button>
-                        <sm-button variant="primary">primary</sm-button>
-                        <sm-button variant="outlined">outlined</sm-button>
-                        <sm-button variant="no-outline">no-outline</sm-button>
-                        <sm-button variant="primary" disabled>disabled</sm-button>
-                    
-                
-
- - - -
-

Checkbox

-

- To start using SM Components -

- -
- -
-

Copy

-

- To start using SM Components -

- -
- -
-

File input

-

- To start using SM Components -

- -

-
-
-

Form

-

- To start using SM Components -

- - - Submit - -

-
-
-

Input

-

- To start using SM Components -

- -

-
- - - -
-

Notifications

-

- To start using SM Components -

-

Example

- - - push success notification - - push error notification - - push pinned notification -
- - - -
-

Radio

-

- Popups are used to show addition UI elements that you may want to hide at first and reveal them when - needed. -

- - - - -
- -
-

Switch

-

- To start using SM Components -

- - - -
- -
-

Select

-

- <sm-select> is very similar to starndatd HTML5 select and it's markup stucture is - also identical. -

- - option1 - option2 something - option3 - -
- -
-

Strip select

-

- To start using SM Components -

- - Movie - TV series - Video - Music - -
- -
-

Tabs

-

- To start using SM Components -

- - inbox - sent - draft - spam - - - - gjdhnsrfijbgn
bdfjnbj -
- - jadifjoaijdiajdo - dosfighjoi
- flkmgklfmzkl
- hbdsfhb -
- - Lorem ipsum dolor, sit amet consectetur adipisicing elit. Facere neque incidunt aut laudantium, - quam - id, - molestiae vero blanditiis nisi alias in magnam autem quasi cumque eveniet qui cupiditate nam - corrupti? - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis fuga ipsam, explicabo, eius - accusamus - consectetur ex sunt soluta voluptatem iure totam nulla expedita suscipit minus molestiae - similique - odio optio - quibusdam. - -
-
-
-

Tags input

-

- To start using SM Components -

- -
-
-

Textarea

-

- To start using SM Components -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + SM Components + + + + + + + + + +
+
+ +

SM Components

+ +
+ +
+
+
+
+
Total components
+

+
+
+

Overview

+

+ These components are based on HTML5 custom elements API. This is an attempt to unify UI + development + patterns and + elements that are used multiple times throughout any general web app.It uses 'sm' namespace for + all + components. So every + component tag starts with 'sm-' +

+

+ They can replace some older UI elements like <select> + <input> + <checkbox> <button> + But also more modern additions like popups(modals), tabs and many more. +

+

+ Some of the components have some cool tricks under their sleeves like custom events and + variantions. + They allow developers to access more information about component or simply react to whatever + state + change happen to them. + We will go more in-depth about all the variantions and customs events related to each event as + we go + further. +

+
+
+ +
+

Quick Start

+

+ To start using SM Components, Select components you want to download. +

+
+ + + Get minified + + + Select all + Clear all +
+
+
+ Copy source code + Download JS file +
+
+ +
+

Buttons

+

+ Buttons are used in various basic UI interactions to perform an action. +

+ default + primary + outlined + no-outline + disabled +
+                    
+                        <sm-button>default</sm-button>
+                        <sm-button variant="primary">primary</sm-button>
+                        <sm-button variant="outlined">outlined</sm-button>
+                        <sm-button variant="no-outline">no-outline</sm-button>
+                        <sm-button variant="primary" disabled>disabled</sm-button>
+                    
+                
+
+ + + +
+

Checkbox

+

+ To start using SM Components +

+ +
+ +
+

Copy

+

+ To start using SM Components +

+ +
+ +
+

File input

+

+ To start using SM Components +

+ +

+
+
+

Form

+

+ To start using SM Components +

+ + + Submit + +

+
+
+

Input

+

+ To start using SM Components +

+ +

+
+ + + +
+

Notifications

+

+ To start using SM Components +

+

Example

+ + + push success notification + + push error notification + + push pinned notification +
+ + + +
+

Radio

+

+ Popups are used to show addition UI elements that you may want to hide at first and reveal them when + needed. +

+ + + + +
+ +
+

Switch

+

+ To start using SM Components +

+ + + +
+ +
+

Select

+

+ <sm-select> is very similar to starndatd HTML5 select and it's markup stucture is + also identical. +

+ + option1 + option2 something + option3 + +
+ +
+

Strip select

+

+ To start using SM Components +

+ + Movie + TV series + Video + Music + +
+ +
+

Tabs

+

+ To start using SM Components +

+ + inbox + sent + draft + spam + + + + gjdhnsrfijbgn
bdfjnbj +
+ + jadifjoaijdiajdo + dosfighjoi
+ flkmgklfmzkl
+ hbdsfhb +
+ + Lorem ipsum dolor, sit amet consectetur adipisicing elit. Facere neque incidunt aut laudantium, + quam + id, + molestiae vero blanditiis nisi alias in magnam autem quasi cumque eveniet qui cupiditate nam + corrupti? + + + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis fuga ipsam, explicabo, eius + accusamus + consectetur ex sunt soluta voluptatem iure totam nulla expedita suscipit minus molestiae + similique + odio optio + quibusdam. + +
+
+
+

Tags input

+

+ To start using SM Components +

+ +
+
+

Textarea

+

+ To start using SM Components +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Standard UI Components/prettify.js b/components/prettify.js similarity index 100% rename from Standard UI Components/prettify.js rename to components/prettify.js diff --git a/Standard UI Components/resources/artwork1.svg b/components/resources/artwork1.svg similarity index 100% rename from Standard UI Components/resources/artwork1.svg rename to components/resources/artwork1.svg diff --git a/Standard UI Components/resources/artwork2.svg b/components/resources/artwork2.svg similarity index 100% rename from Standard UI Components/resources/artwork2.svg rename to components/resources/artwork2.svg diff --git a/Standard UI Components/resources/background.jpg b/components/resources/background.jpg similarity index 100% rename from Standard UI Components/resources/background.jpg rename to components/resources/background.jpg diff --git a/Standard UI Components/resources/background2.jpg b/components/resources/background2.jpg similarity index 100% rename from Standard UI Components/resources/background2.jpg rename to components/resources/background2.jpg diff --git a/Standard UI Components/resources/background3.jpg b/components/resources/background3.jpg similarity index 100% rename from Standard UI Components/resources/background3.jpg rename to components/resources/background3.jpg diff --git a/Standard UI Components/resources/background4.jpg b/components/resources/background4.jpg similarity index 100% rename from Standard UI Components/resources/background4.jpg rename to components/resources/background4.jpg diff --git a/Standard UI Components/resources/background5.jpg b/components/resources/background5.jpg similarity index 100% rename from Standard UI Components/resources/background5.jpg rename to components/resources/background5.jpg diff --git a/Standard UI Components/resources/background6.jpg b/components/resources/background6.jpg similarity index 100% rename from Standard UI Components/resources/background6.jpg rename to components/resources/background6.jpg