Functionality improvements and bug fixes
-- opening a popup will now return two promises (opened & closed). which will resolve on respective actions. - Also it is now possible to send some data with prop name "payload" in show/hide methods
This commit is contained in:
parent
d6c4c6401a
commit
182c4403ad
27
components/dist/chips.js
vendored
27
components/dist/chips.js
vendored
@ -126,7 +126,7 @@ smChips.innerHTML = `
|
||||
<button class="nav-button nav-button--left hide">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10.828 12l4.95 4.95-1.414 1.414L8 12l6.364-6.364 1.414 1.414z"/></svg>
|
||||
</button>
|
||||
<section class="sm-chips">
|
||||
<section class="sm-chips" part="chips-wrapper">
|
||||
<slot></slot>
|
||||
</section>
|
||||
<button class="nav-button nav-button--right hide">
|
||||
@ -298,16 +298,6 @@ smChip.innerHTML = `
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.sm-chip{
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
padding: var(--padding, 0.4rem 0.6rem);
|
||||
transition: background 0.3s;
|
||||
border-radius: var(--border-radius, 2rem);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
:host([selected]) .sm-chip{
|
||||
color: var(--selected-option-color, rgba(var(--background-color,white)));
|
||||
background-color: var(--selected-background-color, var(--accent-color,teal));
|
||||
@ -321,10 +311,21 @@ smChip.innerHTML = `
|
||||
:host(:hover:not([selected])) .sm-chip{
|
||||
background-color: rgba(var(--text-color,(17,17,17)), 0.06);
|
||||
}
|
||||
.sm-chip{
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
padding: var(--padding, 0.5rem 0.8rem);
|
||||
transition: background 0.3s;
|
||||
border-radius: var(--border-radius, 0.5rem);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background: var(--background,inherit);
|
||||
}
|
||||
</style>
|
||||
<label class="sm-chip">
|
||||
<span class="sm-chip" part="chip">
|
||||
<slot></slot>
|
||||
</label>
|
||||
</span>
|
||||
`;
|
||||
customElements.define('sm-chip', class extends HTMLElement {
|
||||
constructor() {
|
||||
|
||||
2
components/dist/chips.min.js
vendored
2
components/dist/chips.min.js
vendored
File diff suppressed because one or more lines are too long
14
components/dist/form.js
vendored
14
components/dist/form.js
vendored
@ -83,16 +83,16 @@ customElements.define('sm-form', class extends HTMLElement {
|
||||
}
|
||||
}
|
||||
reset() {
|
||||
this.formElements.forEach(elem => elem.reset());
|
||||
this.formElements.forEach(([elem, isWC]) => {
|
||||
if (isWC) elem.reset();
|
||||
else elem.value = '';
|
||||
});
|
||||
}
|
||||
elementsChanged() {
|
||||
this._requiredElements = [];
|
||||
this.formElements = [...this.querySelectorAll('input, sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-radio')];
|
||||
this.formElements.forEach(elem => {
|
||||
if (elem.hasAttribute('required')) {
|
||||
this._requiredElements.push([elem, elem.tagName.includes('-')]);
|
||||
}
|
||||
this.formElements = [...this.querySelectorAll('input, sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-radio')].map(elem => {
|
||||
return [elem, elem.tagName.includes('-')];
|
||||
});
|
||||
this._requiredElements = this.formElements.filter(([elem]) => elem.hasAttribute('required'));
|
||||
this.submitButton = this.querySelector('[variant="primary"], [type="submit"]');
|
||||
this.resetButton = this.querySelector('[type="reset"]');
|
||||
if (this.resetButton) {
|
||||
|
||||
2
components/dist/form.min.js
vendored
2
components/dist/form.min.js
vendored
@ -1 +1 @@
|
||||
const smForm = document.createElement("template"); smForm.innerHTML = ` <style> *{ padding: 0; margin: 0; box-sizing: border-box; } :host{ display: grid; width: 100%; } form{ display: inherit; gap: var(--gap, 1.5rem); width: 100%; } </style> <form part="form" onsubmit="return false"> <slot></slot> </form> `, customElements.define("sm-form", class extends HTMLElement { constructor() { super(), this.attachShadow({ mode: "open" }).append(smForm.content.cloneNode(!0)), this.form = this.shadowRoot.querySelector("form"), this.invalidFields = !1, this.debounce = this.debounce.bind(this), this._checkValidity = this._checkValidity.bind(this), this.handleKeydown = this.handleKeydown.bind(this), this.reset = this.reset.bind(this), this.elementsChanged = this.elementsChanged.bind(this) } debounce(e, t) { let i = null; return (...s) => { window.clearTimeout(i), i = window.setTimeout(() => { e.apply(null, s) }, t) } } _checkValidity() { this.submitButton && (this.invalidFields = this._requiredElements.filter(([e, t]) => t ? !e.isValid : !e.checkValidity()), this.submitButton.disabled = this.invalidFields.length > 0) } handleKeydown(e) { if ("Enter" === e.key && e.target.tagName.includes("INPUT")) { if (this.invalidFields.length) for (let [t, i] of this._requiredElements) { let s = i ? !t.isValid : !t.checkValidity(); if (s) { (t?.shadowRoot?.lastElementChild || t).animate([{ transform: "translateX(-1rem)" }, { transform: "translateX(1rem)" }, { transform: "translateX(-0.5rem)" }, { transform: "translateX(0.5rem)" }, { transform: "translateX(0)" },], { duration: 300, easing: "ease" }), i ? t.focusIn() : t.focus(); break } } else this.submitButton && this.submitButton.click(), this.dispatchEvent(new CustomEvent("submit", { bubbles: !0, composed: !0 })) } } reset() { this.formElements.forEach(e => e.reset()) } elementsChanged() { this._requiredElements = [], this.formElements = [...this.querySelectorAll("input, sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-radio")], this.formElements.forEach(e => { e.hasAttribute("required") && this._requiredElements.push([e, e.tagName.includes("-")]) }), this.submitButton = this.querySelector('[variant="primary"], [type="submit"]'), this.resetButton = this.querySelector('[type="reset"]'), this.resetButton && this.resetButton.addEventListener("click", this.reset), this._checkValidity() } connectedCallback() { this.shadowRoot.querySelector("slot").addEventListener("slotchange", this.elementsChanged), this.addEventListener("input", this.debounce(this._checkValidity, 100)), this.addEventListener("keydown", this.debounce(this.handleKeydown, 100)), this.mutationObserver = new MutationObserver(e => { e.forEach(e => { "childList" === e.type && this.elementsChanged() }) }), this.mutationObserver.observe(this, { childList: !0, subtree: !0 }) } disconnectedCallback() { this.removeEventListener("input", this.debounce(this._checkValidity, 100)), this.removeEventListener("keydown", this.debounce(this.handleKeydown, 100)), this.mutationObserver.disconnect() } });
|
||||
const smForm = document.createElement("template"); smForm.innerHTML = ` <style> *{ padding: 0; margin: 0; box-sizing: border-box; } :host{ display: grid; width: 100%; } form{ display: inherit; gap: var(--gap, 1.5rem); width: 100%; } </style> <form part="form" onsubmit="return false"> <slot></slot> </form> `, customElements.define("sm-form", class extends HTMLElement { constructor() { super(), this.attachShadow({ mode: "open" }).append(smForm.content.cloneNode(!0)), this.form = this.shadowRoot.querySelector("form"), this.invalidFields = !1, this.debounce = this.debounce.bind(this), this._checkValidity = this._checkValidity.bind(this), this.handleKeydown = this.handleKeydown.bind(this), this.reset = this.reset.bind(this), this.elementsChanged = this.elementsChanged.bind(this) } debounce(e, t) { let i = null; return (...s) => { window.clearTimeout(i), i = window.setTimeout(() => { e.apply(null, s) }, t) } } _checkValidity() { this.submitButton && (this.invalidFields = this._requiredElements.filter(([e, t]) => t ? !e.isValid : !e.checkValidity()), this.submitButton.disabled = this.invalidFields.length > 0) } handleKeydown(e) { if ("Enter" === e.key && e.target.tagName.includes("INPUT")) { if (this.invalidFields.length) for (let [t, i] of this._requiredElements) { let s = i ? !t.isValid : !t.checkValidity(); if (s) { (t?.shadowRoot?.lastElementChild || t).animate([{ transform: "translateX(-1rem)" }, { transform: "translateX(1rem)" }, { transform: "translateX(-0.5rem)" }, { transform: "translateX(0.5rem)" }, { transform: "translateX(0)" },], { duration: 300, easing: "ease" }), i ? t.focusIn() : t.focus(); break } } else this.submitButton && this.submitButton.click(), this.dispatchEvent(new CustomEvent("submit", { bubbles: !0, composed: !0 })) } } reset() { this.formElements.forEach(([e, t]) => { t ? e.reset() : e.value = "" }) } elementsChanged() { this.formElements = [...this.querySelectorAll("input, sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-radio")].map(e => [e, e.tagName.includes("-")]), this._requiredElements = this.formElements.filter(([e]) => e.hasAttribute("required")), this.submitButton = this.querySelector('[variant="primary"], [type="submit"]'), this.resetButton = this.querySelector('[type="reset"]'), this.resetButton && this.resetButton.addEventListener("click", this.reset), this._checkValidity() } connectedCallback() { this.shadowRoot.querySelector("slot").addEventListener("slotchange", this.elementsChanged), this.addEventListener("input", this.debounce(this._checkValidity, 100)), this.addEventListener("keydown", this.debounce(this.handleKeydown, 100)), this.mutationObserver = new MutationObserver(e => { e.forEach(e => { "childList" === e.type && this.elementsChanged() }) }), this.mutationObserver.observe(this, { childList: !0, subtree: !0 }) } disconnectedCallback() { this.removeEventListener("input", this.debounce(this._checkValidity, 100)), this.removeEventListener("keydown", this.debounce(this.handleKeydown, 100)), this.mutationObserver.disconnect() } });
|
||||
26
components/dist/popup.js
vendored
26
components/dist/popup.js
vendored
@ -258,12 +258,13 @@ customElements.define('sm-popup', class extends HTMLElement {
|
||||
}
|
||||
|
||||
show(options = {}) {
|
||||
const { pinned = false } = options;
|
||||
const { pinned = false, payload } = options;
|
||||
if (this.isOpen) return;
|
||||
const animOptions = {
|
||||
duration: 300,
|
||||
easing: 'ease'
|
||||
}
|
||||
this.payload = payload;
|
||||
popupStack.push({
|
||||
popup: this,
|
||||
permission: pinned
|
||||
@ -279,10 +280,16 @@ customElements.define('sm-popup', class extends HTMLElement {
|
||||
this.backdrop.animate([
|
||||
{ opacity: 0 },
|
||||
{ opacity: 1 },
|
||||
], animOptions)
|
||||
], animOptions).onfinish = () => {
|
||||
this.resolveOpen(this.payload);
|
||||
}
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("popupopened", {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: {
|
||||
payload: this.payload
|
||||
}
|
||||
})
|
||||
);
|
||||
document.body.style.overflow = 'hidden';
|
||||
@ -304,8 +311,17 @@ customElements.define('sm-popup', class extends HTMLElement {
|
||||
this.popupHeader.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
||||
this.backdrop.addEventListener('mousedown', this.handleSoftDismiss);
|
||||
}
|
||||
return {
|
||||
opened: new Promise((resolve) => {
|
||||
this.resolveOpen = resolve;
|
||||
}),
|
||||
closed: new Promise((resolve) => {
|
||||
this.resolveClose = resolve;
|
||||
})
|
||||
}
|
||||
}
|
||||
hide() {
|
||||
hide(options = {}) {
|
||||
const { payload } = options;
|
||||
const animOptions = {
|
||||
duration: 150,
|
||||
easing: 'ease'
|
||||
@ -335,11 +351,13 @@ customElements.define('sm-popup', class extends HTMLElement {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("popupclosed", {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: {
|
||||
popup: this,
|
||||
payload: payload || this.payload
|
||||
}
|
||||
})
|
||||
);
|
||||
this.resolveClose(payload || this.payload);
|
||||
this.isOpen = false;
|
||||
})
|
||||
popupStack.pop();
|
||||
|
||||
2
components/dist/popup.min.js
vendored
2
components/dist/popup.min.js
vendored
File diff suppressed because one or more lines are too long
@ -35,25 +35,29 @@
|
||||
|
||||
<body>
|
||||
<button>Show popup</button>
|
||||
<collapsed-text>
|
||||
Loreetur adipisicing elit. Architecto minima maiores autem iusto porro, odit
|
||||
iure
|
||||
ea emus dolor itaque unde sequi, reprehenderit ex aperiam
|
||||
|
||||
dinfgw egweb gnw
|
||||
|
||||
slideInRightgsdgs
|
||||
</collapsed-text>
|
||||
<sm-popup>
|
||||
<input type="text" placeholder="fds">
|
||||
<button>dsfsd</button>
|
||||
<collapsed-text>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Architecto minima maiores autem iusto porro, odit
|
||||
iure
|
||||
ea eveniet enim soluta ex a nihil? Dicta ducimus dolor itaque unde sequi, reprehenderit ex aperiam
|
||||
dignissimos
|
||||
inventore? Totam aliquid repellendus nulla culpa nemo perspiciatis tempora. Vel obcaecati asperiores nam,
|
||||
ratione sint itaque temporibus incidunt officiis iusto cumque reiciendis ab repellendus quaerat ducimus
|
||||
quibusdam quia maxime nostrum atque ad sequi eveniet est error ipsam voluptatem. Architecto molestiae ex et
|
||||
minima praesentium quasi ea, ad enim consequuntur at nisi nostrum. Quisquam nostrum, accusamus neque, fugiat
|
||||
esse deleniti ex vitae totam asperiores odit quaerat sunt voluptates.
|
||||
</collapsed-text>
|
||||
</sm-popup>
|
||||
</body>
|
||||
<script>
|
||||
const popup = document.querySelector('sm-popup');
|
||||
popup.show();
|
||||
const pPromise = popup.show({ payload: { opened: new Date() } })
|
||||
pPromise.opened.then((data) => {
|
||||
console.log('popup opened', data);
|
||||
});
|
||||
pPromise.closed.then((data) => {
|
||||
console.log('popup closed', data);
|
||||
});
|
||||
document.querySelector('button').addEventListener('click', () => {
|
||||
popup.show();
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user