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">
|
<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>
|
<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>
|
</button>
|
||||||
<section class="sm-chips">
|
<section class="sm-chips" part="chips-wrapper">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</section>
|
</section>
|
||||||
<button class="nav-button nav-button--right hide">
|
<button class="nav-button nav-button--right hide">
|
||||||
@ -298,16 +298,6 @@ smChip.innerHTML = `
|
|||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
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{
|
:host([selected]) .sm-chip{
|
||||||
color: var(--selected-option-color, rgba(var(--background-color,white)));
|
color: var(--selected-option-color, rgba(var(--background-color,white)));
|
||||||
background-color: var(--selected-background-color, var(--accent-color,teal));
|
background-color: var(--selected-background-color, var(--accent-color,teal));
|
||||||
@ -321,10 +311,21 @@ smChip.innerHTML = `
|
|||||||
:host(:hover:not([selected])) .sm-chip{
|
:host(:hover:not([selected])) .sm-chip{
|
||||||
background-color: rgba(var(--text-color,(17,17,17)), 0.06);
|
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>
|
</style>
|
||||||
<label class="sm-chip">
|
<span class="sm-chip" part="chip">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</label>
|
</span>
|
||||||
`;
|
`;
|
||||||
customElements.define('sm-chip', class extends HTMLElement {
|
customElements.define('sm-chip', class extends HTMLElement {
|
||||||
constructor() {
|
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() {
|
reset() {
|
||||||
this.formElements.forEach(elem => elem.reset());
|
this.formElements.forEach(([elem, isWC]) => {
|
||||||
|
if (isWC) elem.reset();
|
||||||
|
else elem.value = '';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
elementsChanged() {
|
elementsChanged() {
|
||||||
this._requiredElements = [];
|
this.formElements = [...this.querySelectorAll('input, sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-radio')].map(elem => {
|
||||||
this.formElements = [...this.querySelectorAll('input, sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-radio')];
|
return [elem, elem.tagName.includes('-')];
|
||||||
this.formElements.forEach(elem => {
|
|
||||||
if (elem.hasAttribute('required')) {
|
|
||||||
this._requiredElements.push([elem, elem.tagName.includes('-')]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
this._requiredElements = this.formElements.filter(([elem]) => elem.hasAttribute('required'));
|
||||||
this.submitButton = this.querySelector('[variant="primary"], [type="submit"]');
|
this.submitButton = this.querySelector('[variant="primary"], [type="submit"]');
|
||||||
this.resetButton = this.querySelector('[type="reset"]');
|
this.resetButton = this.querySelector('[type="reset"]');
|
||||||
if (this.resetButton) {
|
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 = {}) {
|
show(options = {}) {
|
||||||
const { pinned = false } = options;
|
const { pinned = false, payload } = options;
|
||||||
if (this.isOpen) return;
|
if (this.isOpen) return;
|
||||||
const animOptions = {
|
const animOptions = {
|
||||||
duration: 300,
|
duration: 300,
|
||||||
easing: 'ease'
|
easing: 'ease'
|
||||||
}
|
}
|
||||||
|
this.payload = payload;
|
||||||
popupStack.push({
|
popupStack.push({
|
||||||
popup: this,
|
popup: this,
|
||||||
permission: pinned
|
permission: pinned
|
||||||
@ -279,10 +280,16 @@ customElements.define('sm-popup', class extends HTMLElement {
|
|||||||
this.backdrop.animate([
|
this.backdrop.animate([
|
||||||
{ opacity: 0 },
|
{ opacity: 0 },
|
||||||
{ opacity: 1 },
|
{ opacity: 1 },
|
||||||
], animOptions)
|
], animOptions).onfinish = () => {
|
||||||
|
this.resolveOpen(this.payload);
|
||||||
|
}
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent("popupopened", {
|
new CustomEvent("popupopened", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
detail: {
|
||||||
|
payload: this.payload
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
document.body.style.overflow = 'hidden';
|
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.popupHeader.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
||||||
this.backdrop.addEventListener('mousedown', this.handleSoftDismiss);
|
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 = {
|
const animOptions = {
|
||||||
duration: 150,
|
duration: 150,
|
||||||
easing: 'ease'
|
easing: 'ease'
|
||||||
@ -335,11 +351,13 @@ customElements.define('sm-popup', class extends HTMLElement {
|
|||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent("popupclosed", {
|
new CustomEvent("popupclosed", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
detail: {
|
detail: {
|
||||||
popup: this,
|
payload: payload || this.payload
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
this.resolveClose(payload || this.payload);
|
||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
})
|
})
|
||||||
popupStack.pop();
|
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>
|
<body>
|
||||||
<button>Show popup</button>
|
<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>
|
<sm-popup>
|
||||||
<input type="text" placeholder="fds">
|
<input type="text" placeholder="fds">
|
||||||
<button>dsfsd</button>
|
<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>
|
</sm-popup>
|
||||||
</body>
|
</body>
|
||||||
<script>
|
<script>
|
||||||
const popup = document.querySelector('sm-popup');
|
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', () => {
|
document.querySelector('button').addEventListener('click', () => {
|
||||||
popup.show();
|
popup.show();
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user