kempo 3.2.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Component.js +1 -1
- package/dist/components/Dialog.js +1 -1
- package/dist/components/LazyComponent.js +1 -1
- package/dist/components/Toast.js +1 -0
- package/dist/utils/Server.js +1 -0
- package/dist/utils/drag.js +1 -1
- package/dist/utils/fs-utils.js +1 -0
- package/dist/utils/minify.js +1 -0
- package/docs/components/lazy-component.html +8 -0
- package/docs/components/toast.html +330 -0
- package/docs/icons/error.svg +1 -0
- package/docs/icons/warning.svg +1 -0
- package/docs/kempo/components/Component.js +1 -1
- package/docs/kempo/components/Dialog.js +1 -1
- package/docs/kempo/components/LazyComponent.js +1 -1
- package/docs/kempo/components/Toast.js +1 -0
- package/docs/kempo/utils/Server.js +1 -0
- package/docs/kempo/utils/drag.js +1 -1
- package/docs/kempo/utils/fs-utils.js +1 -0
- package/docs/kempo/utils/minify.js +1 -0
- package/docs/nav.inc.html +2 -1
- package/docs/utils/Server.html +119 -0
- package/icons/error.svg +1 -0
- package/icons/warning.svg +1 -0
- package/package.json +2 -4
- package/scripts/build.js +8 -8
- package/scripts/docs.js +20 -20
- package/src/components/Component.js +1 -0
- package/src/components/Dialog.js +11 -1
- package/src/components/LazyComponent.js +9 -5
- package/src/components/Toast.js +424 -0
- package/src/utils/Server.js +189 -0
- package/src/utils/fs-utils.js +41 -0
- package/test/index.js +27 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCase}from"../utils/string.js";export default class Component extends HTMLElement{constructor(t={}){super(),this.attachShadow({mode:"open",...t}),this.registerAttribute("rendered",!1)}async connectedCallback(){this.render(!0)}async disconnectedCallback(){}async attributeChangedCallback(){}async propChangedCallback(){}async render(t=!1){if(t||!this.rendered)return this.shadowRoot.innerHTML=`<link rel="stylesheet" href="${Component.pathToKempo}/kempo-styles.css" />${this.shadowTemplate}<style>${this.shadowStyles}</style>`,this.rendered=!0,!0}registerAttribute(t,e=""){const{camel:s,dash:r}=getCase(t),i=typeof e;Object.defineProperty(this,s,{get:()=>{const t=this.getAttribute(r);return"number"==i?parseFloat(t):"object"===i?"string"==typeof t?JSON.parse(t):t:"boolean"===i?"string"==typeof t?"true"===t.toLowerCase().trim():!!t:"string"===i?t||"":t},set:t=>{this[r]!==t&&("boolean"===i?t?this.setAttribute(r,"true"):this.removeAttribute(r):"object"===i?this.setAttribute(r,JSON.stringify(t||{})):"number"===i?t||0===t?this.setAttribute(r,t):this.removeAttribute(r):this.setAttribute(r,t))}}),null===this.getAttribute(r)&&(this[s]=e)}registerAttributes(t){for(const e in t)this.registerAttribute(e,t[e])}registerProp(t,e){const s=Symbol(t);this[s]=e,Object.defineProperty(this,t,{get:()=>this[s],set:e=>{if(this[s]!==e){const r=this[s];this[s]=e,this.propChangedCallback(t,r,e)}}})}registerProps(t){for(const e in t)this.registerProp(e,t[e])}renderIf(t,e){return t?e:""}get shadowTemplate(){return"\n <slot></slot>\n "}get shadowStyles(){return""}static observedAttributes=["rendered"];static pathToKempo=import.meta.url.substring(0,import.meta.url.indexOf("/components/Component.js"))}
|
|
1
|
+
import{getCase}from"../utils/string.js";export default class Component extends HTMLElement{constructor(t={}){super(),this.attachShadow({mode:"open",...t}),this.registerAttribute("rendered",!1)}async connectedCallback(){this.render(!0)}async disconnectedCallback(){}async attributeChangedCallback(){}async propChangedCallback(){}async render(t=!1){if(t||!this.rendered)return this.shadowRoot.innerHTML=`<link rel="stylesheet" href="${Component.pathToKempo}/kempo-styles.css" />${this.shadowTemplate}<style>${this.shadowStyles}</style>`,this.rendered=!0,!0}registerAttribute(t,e=""){const{camel:s,dash:r}=getCase(t),i=typeof e;Object.defineProperty(this,s,{get:()=>{const t=this.getAttribute(r);return"number"==i?parseFloat(t):"object"===i?"string"==typeof t?JSON.parse(t):t:"boolean"===i?"string"==typeof t?"true"===t.toLowerCase().trim():!!t:"string"===i?t||"":t},set:t=>{this[r]!==t&&("boolean"===i?t?this.setAttribute(r,"true"):this.removeAttribute(r):"object"===i?this.setAttribute(r,JSON.stringify(t||{})):"number"===i?t||0===t?this.setAttribute(r,t):this.removeAttribute(r):this.setAttribute(r,t))}}),null===this.getAttribute(r)&&(this[s]=e)}registerAttributes(t){for(const e in t)this.registerAttribute(e,t[e])}registerProp(t,e){const s=Symbol(t);this[s]=e,Object.defineProperty(this,t,{get:()=>this[s],set:e=>{if(this[s]!==e){const r=this[s];this[s]=e,this.propChangedCallback(t,r,e)}}})}registerProps(t){for(const e in t)this.registerProp(e,t[e])}renderIf(t,e){return t?e:""}get shadowTemplate(){return"\n <slot></slot>\n "}get shadowStyles(){return""}static observedAttributes=["rendered"];static pathToKempo=import.meta.url.substring(0,import.meta.url.indexOf("/components/Component.js"))}window.customElements.define("k-component",Component);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import Component from"./Component.js";import"./FocusCapture.js";import"./Icon.js";import{firstFocusable,onEvent,offEvent,dispatchEvent}from"../utils/element.js";export default class Dialog extends Component{constructor({opened:e=!1,closeBtn:
|
|
1
|
+
import Component from"./Component.js";import"./FocusCapture.js";import"./Icon.js";import{firstFocusable,onEvent,offEvent,dispatchEvent}from"../utils/element.js";export default class Dialog extends Component{constructor({opened:e=!1,closeBtn:n=!0,overlayClose:t=!0,confirmText:o="",confirmClasses:s="success ml",confirmAction:i=()=>{},cancelText:l="",cancelClasses:c="",cancelAction:a=()=>{},closeCallback:r=()=>{}}={}){super(),this.registerAttributes({opened:e,closeBtn:n,overlayClose:t,confirmText:o,confirmClasses:s,cancelText:l,cancelClasses:c}),this.registerProps({confirmAction:i,cancelAction:a,closeCallback:r,previousFocus:null,_clickHandler:e=>{const{target:{id:n}}=e;"overlay"==n&&this.overlayClose||"close"==n?this.close():"cancel"==n?(this.cancelAction(e),e.defaultPrevented||this.close()):"confirm"==n&&(this.confirmAction(e),e.defaultPrevented||this.close())},_keydownHandler:({keyCode:e})=>{27===e&&this.close()},_hasTitle:()=>!!this.querySelector('[slot="title"]')})}connectedCallback(){super.connectedCallback(),onEvent(this.shadowRoot,"click",this._clickHandler)}disconnectedCallback(){super.connectedCallback(),offEvent(this.shadowRoot,"click",this._clickHandler),offEvent(window,"keydown",this._keydownHandler)}attributeChangedCallback(e,n,t){super.attributeChangedCallback(e,n,t),"opened"===name&&dispatchEvent(this,t?"opened":"close")}open(){this.opened=!0;const e=this.shadowRoot.querySelector("[autofocus]")||firstFocusable(this.shadowRoot);e&&e.focus(),onEvent(window,"keydown",this._keydownHandler)}close(){this.opened=!1,this.blur(),this.closeCallback(),offEvent(window,"keydown",this._keydownHandler)}toggle(){this.opened?this.close():this.open()}focus(){const e=firstFocusable(this.shadowRoot);e&&(this.previousFocus=document.activeElement,e.focus())}blur(){this.previousFocus&&this.previousFocus.focus()}get shadowTemplate(){return`\n <k-focus-capture>\n <button id="overlay" aria-label="Close the Dialog"></button>\n <div id="wrapper">\n <div\n id="dialog"\n role="dialog"\n aria-modal="true"\n aria-labelledby="title"\n >\n <div\n id="header"\n class="${this._hasTitle()?"has-title":""}"\n >\n <div\n id="title"\n ><slot name="title"></slot></div>\n ${this.renderIf(this.closeBtn,'\n <button\n id="close"\n >\n <k-icon name="close"></k-icon>\n </button>\n ')}\n </div>\n <div id="body">\n ${super.shadowTemplate}\n </div>\n ${this.renderIf(this.cancelText||this.confirmText,`\n <div id="footer">\n ${this.renderIf(this.cancelText,`\n <button id="cancel" class="${this.cancelClasses}">\n ${this.cancelText}\n </button>\n `)}\n ${this.renderIf(this.confirmText,`\n <button id="confirm" class="${this.confirmClasses}">\n ${this.confirmText}\n </button>\n `)}\n </div>\n `)}\n </div>\n </div>\n </k-focus-capture>\n `}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: inline;\n height: 1px;\n width: 1px;\n position: fixed; /* The browser seems to sometimes lazy load this if its out of view, this seems to fix it*/\n top: 0;\n left: 0;\n z-index: 100;\n }\n :host(:not([opened])){\n display: none;\n }\n #overlay {\n position: fixed;\n width: 100vw;\n height: 100vh;\n top: 0;\n left: 0;\n background-color: var(--c_overlay);\n z-index: 100;\n border: 0px solid transparent;\n box-shadow: 0 0 0 transparent;\n }\n #wrapper {\n display: flex;\n justify-content: center;\n align-items: center;\n position: fixed;\n width: 100%;\n height: 100vh;\n top: 0;\n left: 0;\n z-index: 101;\n pointer-events: none;\n }\n #dialog {\n display: flex;\n flex-direction: column;\n min-width: var(--min_width, 20rem);\n width: var(--width, fit-content);\n max-width: var(--max_width, calc(100vw - 4rem));\n min-height: var(--min_height, 12rem);\n height: var(--height, fit-content);\n max-height: var(--max_height, calc(100vh - 4rem));\n background-color: var(--c_bg);\n box-shadow: var(--drop_shadow);\n border-radius: var(--radius);\n pointer-events: all;\n }\n #header {\n display: flex;\n align-items: center;\n }\n #header.has-title {\n border-bottom: 1px solid var(--c_border);\n }\n #title {\n flex: 1 1 auto;\n }\n #close {\n border: 0px;\n background: transparent;\n box-shadow: 0 0 0 transparent;\n color: var(--tc);\n }\n #close k-icon {\n pointer-events: none;\n }\n #body {\n flex: 1 1 auto;\n }\n #footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--spacer_h);\n }\n `}static renderOnChange=["opened","closeBtn","overlayClose","title","confirmText","cancelText"];static create(e="",n={}){!1!==n.closeExisting&&document.querySelectorAll("k-dialog").forEach((e=>e.close()));const{removeOnClose:t=!0,closeCallback:o=()=>{}}=n,s=new Dialog({opened:!0,...n,closeCallback:(...e)=>{t&&s.remove(),o(...e)}});return onEvent(s,"close",s.remove),e instanceof HTMLElement||e instanceof DocumentFragment?s.appendChild(e):e instanceof NodeList?e.forEach((e=>s.appendChild(e))):s.innerHTML=e,n.width&&s.style.setProperty("--width",n.width),n.minWidth&&s.style.setProperty("--min_width",n.minWidth),n.maxWidth&&s.style.setProperty("--max_width",n.maxWidth),n.height&&s.style.setProperty("--height",n.height),n.minHeight&&s.style.setProperty("--min_height",n.minHeight),n.maxHeight&&s.style.setProperty("--max_height",n.maxHeight),document.body.prepend(s),s.open(),s}static confirm(e,n,t={title:"Confirm"}){return Dialog.create(`\n <h5 slot="title" class="pyh px m0">${t.title}</h5>\n <p class="p">${e}</p>\n `,{...t,closeBtn:!1,overlayClose:!1,confirmText:"Yes",confirmClasses:"success ml",confirmAction:()=>n(!0),cancelText:"No",cancelClasses:"danger",cancelAction:()=>n(!1)})}static alert(e,n,t={title:"Alert"}){return Dialog.create(`\n <h5 slot="title" class="pyh px m0">${t.title}</h5>\n <p class="p">${e}</p>\n `,{closeCallback:n,cancelText:"Ok",...t})}static error(e,n,t={title:"Error"}){return Dialog.create(`\n <h5 slot="title" class="pyh px m0 tc-danger">${t.title}</h5>\n <p class="p">${e}</p>\n `,{closeCallback:n,cancelText:"Ok",...t})}static success(e,n,t={title:"Success"}){return Dialog.create(`\n <h5 slot="title" class="pyh px m0 tc-success">${t.title}</h5>\n <p class="p">${e}</p>\n `,{closeCallback:n,cancelText:"Ok",...t})}}window.customElements.define("k-dialog",Dialog);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import Component from"./Component.js";import{isInView}from"../utils/element.js";import raf from"../utils/raf.js";const
|
|
1
|
+
import Component from"./Component.js";import{isInView}from"../utils/element.js";import raf from"../utils/raf.js";const inViewIntervalId=Symbol();export default class LazyComponent extends Component{constructor(e){super(e),this[inViewIntervalId]=null,new IntersectionObserver((([e])=>{e.intersectionRatio>0&&!this.rendered?this.inViewCallback():this.outOfViewCallback()})).observe(this),this.registerAttributes({unrender:!1,inViewInterval:0})}connectedCallback(){this.renderSkelton(),raf((()=>{isInView(this)?this.inViewCallback():this.outOfViewCallback()}),2)}async inViewCallback(){return clearInterval(this[inViewIntervalId]),await this.render()}async outOfViewCallback(){return clearInterval(this[inViewIntervalId]),this[inViewIntervalId]=setInterval((async()=>{await isInView(this)&&this.inViewCallback()}),this.inViewInterval||LazyComponent.inViewIntervalTimeout),!!this.unrender&&(await this.renderSkelton(),!0)}async renderSkelton(){return this.shadowRoot.innerHTML=`<link rel="stylesheet" href="${Component.pathToKempo}/kempo-styles.css" />${this.skeletonTemplate}<style>${this.shadowStyles}</style>`,this.rendered=!1,!0}get skeletonTemplate(){return'<div style="height: var(--skeleton_height, 1rem)"></div>'}static inViewIntervalTimeout=1e3}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import Component from"./Component.js";import{onEvent,offEvent,dispatchEvent}from"../utils/element.js";const _position=Symbol();export class ToastContainer extends Component{constructor(t="bottom center"){super(),this[_position]=t.toLowerCase(),this.setAttribute("position",this[_position])}get position(){return this[_position]}set position(t){t!==this[_position]&&(this[_position]=t.toLowerCase(),this.setAttribute("position",this[_position]))}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n position: fixed;\n display: flex;\n flex-direction: column;\n gap: 8px;\n z-index: 1000;\n pointer-events: none;\n padding: 16px;\n box-sizing: border-box;\n max-width: 100%;\n max-height: 100%;\n overflow: hidden;\n }\n\n :host([position*="top"]) {\n top: 0;\n }\n\n :host([position*="bottom"]) {\n bottom: 0;\n }\n\n :host([position*="left"]) {\n left: 0;\n align-items: flex-start;\n }\n\n :host([position*="right"]) {\n right: 0;\n align-items: flex-end;\n }\n\n :host([position*="center"]:not([position*="top"]):not([position*="bottom"])) {\n top: 50%;\n transform: translateY(-50%);\n }\n \n :host([position="center"]),\n :host([position*="center"][position*="top"]),\n :host([position*="center"][position*="bottom"]) {\n left: 50%;\n transform: translateX(-50%);\n }\n\n :host([position*="center"]:not([position="center"])) {\n align-items: center;\n }\n \n /* Combined transforms for center vertically and horizontally */\n :host([position*="center"]:not([position*="top"]):not([position*="bottom"]):not([position="center"])) {\n transform: translate(-50%, -50%);\n }\n\n ::slotted(*) {\n pointer-events: auto;\n }\n `}}window.customElements.define("k-toast-container",ToastContainer);const closeHandler=Symbol(),actionHandler=Symbol(),timeoutId=Symbol(),animationEndHandler=Symbol(),_toastPosition=Symbol(),_closing=Symbol();export default class Toast extends Component{constructor({actionCallback:t=()=>{},closeCallback:n=()=>{},timeout:o=0,position:i="bottom center"}={}){super(),this[timeoutId]=-1,this[_toastPosition]=i.toLowerCase(),this[_closing]=!1,this[closeHandler]=()=>{this.close()},this[actionHandler]=()=>{!1!==this.actionCallback()&&this.close()},this[animationEndHandler]=t=>{t.animationName.includes("toast-hide")?(this.removeAttribute("animating"),this.opened=!1,dispatchEvent(this,"close openchange"),this.closeCallback(),this[_closing]=!1):t.animationName.includes("toast-show")&&this.removeAttribute("animating")},this.registerProps({actionCallback:t,closeCallback:n}),this.registerAttributes({hasAction:!1,hasClose:!1,hasIcon:!1,timeout:o,opened:!1,position:this[_toastPosition]})}async render(t){return!!await super.render(t)&&(onEvent(this.shadowRoot.getElementById("action"),"click",this[actionHandler]),onEvent(this.shadowRoot.getElementById("close"),"click",this[closeHandler]),onEvent(this,"animationend",this[animationEndHandler]),!0)}disconnectedCallback(){super.disconnectedCallback(),clearTimeout(this[timeoutId]),offEvent(this.shadowRoot.getElementById("action"),"click",this[actionHandler]),offEvent(this.shadowRoot.getElementById("close"),"click",this[closeHandler]),offEvent(this,"animationend",this[animationEndHandler])}attributeChangedCallback(t,n,o){super.attributeChangedCallback(t,n,o),"opened"===t&&n!==o&&o&&(this.hasAction=!!this.querySelector('[slot="action"]'),this.hasClose=!!this.querySelector('[slot="close"]'),this.hasIcon=!!this.querySelector('[slot="icon"]'))}open(){this[_closing]=!1,this.setAttribute("animating","in"),this.opened=!0,this.timeout&&(clearTimeout(this[timeoutId]),this[timeoutId]=setTimeout((()=>{this.close()}),this.timeout)),dispatchEvent(this,"open openchange")}close(){clearTimeout(this[timeoutId]),this.opened&&!this[_closing]&&(this[_closing]=!0,this.setAttribute("animating","out"))}get shadowTemplate(){return`\n <div id="icon">\n <slot name="icon"></slot>\n </div>\n <div id="message">\n ${super.shadowTemplate}\n </div>\n <button id="action" class="no-style">\n <slot name="action"></slot>\n </button>\n <button id="close" class="no-style">\n <slot name="close"></slot>\n </button>\n `}get shadowStyles(){return`\n ${super.shadowStyles}\n @keyframes toast-show-bottom {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n }\n @keyframes toast-hide-bottom {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(20px); }\n }\n @keyframes toast-show-top {\n from { opacity: 0; transform: translateY(-20px); }\n to { opacity: 1; transform: translateY(0); }\n }\n @keyframes toast-hide-top {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(-20px); }\n }\n @keyframes toast-show-left {\n from { opacity: 0; transform: translateX(-20px); }\n to { opacity: 1; transform: translateX(0); }\n }\n @keyframes toast-hide-left {\n from { opacity: 1; transform: translateX(0); }\n to { opacity: 0; transform: translateX(-20px); }\n }\n @keyframes toast-show-right {\n from { opacity: 0; transform: translateX(20px); }\n to { opacity: 1; transform: translateX(0); }\n }\n @keyframes toast-hide-right {\n from { opacity: 1; transform: translateX(0); }\n to { opacity: 0; transform: translateX(20px); }\n }\n :host {\n display: none;\n min-width: 16rem;\n max-width: calc(100% - ( 2 * var(--spacer) ));\n background-color: var(--c_bg);\n border-radius: var(--radius);\n box-shadow: var(--drop_shadow);\n }\n :host([opened="true"]) {\n display: flex;\n }\n :host([animating="in"][position*="bottom"]) {\n animation: toast-show-bottom var(--animation_ms, 300ms) ease forwards;\n }\n :host([animating="out"][position*="bottom"]) {\n animation: toast-hide-bottom var(--animation_ms, 300ms) ease forwards;\n }\n :host([animating="in"][position*="top"]) {\n animation: toast-show-top var(--animation_ms, 300ms) ease forwards;\n }\n :host([animating="out"][position*="top"]) {\n animation: toast-hide-top var(--animation_ms, 300ms) ease forwards;\n }\n :host([animating="in"][position*="left"]:not([position*="top"]):not([position*="bottom"])) {\n animation: toast-show-left var(--animation_ms, 300ms) ease forwards;\n }\n :host([animating="out"][position*="left"]:not([position*="top"]):not([position*="bottom"])) {\n animation: toast-hide-left var(--animation_ms, 300ms) ease forwards;\n }\n :host([animating="in"][position*="right"]:not([position*="top"]):not([position*="bottom"])) {\n animation: toast-show-right var(--animation_ms, 300ms) ease forwards;\n }\n :host([animating="out"][position*="right"]:not([position*="top"]):not([position*="bottom"])) {\n animation: toast-hide-right var(--animation_ms, 300ms) ease forwards;\n }\n #icon {\n padding: var(--spacer);\n padding-right: 0;\n }\n #message {\n padding: var(--spacer);\n flex: 1 1 auto;\n }\n :host(:not([has-close])) #close,\n :host(:not([has-action])) #action,\n :host(:not([has-icon])) #icon {\n display: none;\n }\n #action {\n background: transparent;\n border: none;\n color: var(--tc_primary, blue);\n cursor: pointer;\n padding: var(--spacer);\n }\n #action:hover {\n color: var(--tc_primary__hover, lightblue);\n }\n #close {\n background: transparent;\n border: none;\n cursor: pointer;\n padding: var(--spacer);\n opacity: 0.7;\n transition: opacity var(--animation_ms);\n }\n #close:hover {\n opacity: 1;\n }\n `}static observedAttributes=[...super.observedAttributes,"opened"];static create(t,n={}){let{position:o="auto",removeOnClose:i=!0,closeCallback:s=()=>{},action:e=!1,close:a=!1,icon:r=!1}=n;"auto"===o&&(o=window.innerWidth<=768?"bottom center":"top right");let c=document.querySelector(`k-toast-container[position="${o}"]`);c||(c=new ToastContainer(o),document.body.appendChild(c));const l=new Toast({position:o,timeout:5e3,...n,closeCallback:(...t)=>{i&&(l.remove(),0===c.children.length&&c.remove()),s(...t)}});if(l.innerHTML=t,r)if(r instanceof HTMLElement)r.slot="icon",l.appencChild(r);else if("string"==typeof r){const t=document.createElement("span");t.slot="icon",t.innerHTML=r,l.appendChild(t)}if(e)if(e instanceof HTMLElement)e.slot="action",l.appencChild(e);else if("string"==typeof e){const t=document.createElement("span");t.slot="action",t.innerHTML=e,l.appendChild(t)}if(a)if(a instanceof HTMLElement)a.slot="close",l.appencChild(a);else if("string"==typeof a){const t=document.createElement("span");t.slot="close",t.innerHTML=a,l.appendChild(t)}return l.open(),c.appendChild(l),l}static success(t,n={}){const o=Toast.create(t,{icon:'<k-icon name="check"></k-icon>',...n});return o.classList.add("bg-success"),o}static warning(t,n={}){const o=Toast.create(t,{icon:'<k-icon name="warning"></k-icon>',...n});return o.classList.add("bg-warning"),o}static error(t,n={}){const o=Toast.create(t,{icon:'<k-icon name="error"></k-icon>',...n});return o.classList.add("bg-danger"),o}}window.customElements.define("k-toast",Toast);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import http from"http";import{readFile}from"fs/promises";import{join,extname,normalize}from"path";export class Server{constructor(t={}){this.routes=[]}route(t,e,r){const n=r?r.map((t=>t.toUpperCase())):["ANY"];return this.routes.push({pattern:t,handler:e,methods:n}),this}get(t,e){return this.route(t,e,["GET"])}post(t,e){return this.route(t,e,["POST"])}put(t,e){return this.route(t,e,["PUT"])}delete(t,e){return this.route(t,e,["DELETE"])}patch(t,e){return this.route(t,e,["PATCH"])}async handleRequest(t,e){try{const[r,n=""]=t.url.split("?"),s=n.split("&").filter((t=>""!=t)).map((t=>{const[e,r]=t.split("=");return{[e]:decodeURIComponent(r)}})),i=this.routes.find((({methods:e,pattern:n})=>{if(!e.includes(t.method||"GET")&&!e.includes("ANY"))return!1;const s=r.split("/").filter((t=>""!=t)),i=n.split("/").filter((t=>""!=t));if(0==s.length&&0==i.length)return!0;const o=i.length>0&&"*"===i[i.length-1];if(!o&&s.length!==i.length)return!1;if(o&&s.length<i.length-1)return!1;const a=o?i.length-1:i.length;for(let t=0;t<a;t++)if(!i[t].startsWith(":")&&i[t]!==s[t])return!1;return!0}));if(!i)return e.writeHead(404,{"Content-Type":"text/plain"}),void e.end("Not Found");const{pattern:o,handler:a}=i;if("string"==typeof a){const t=o.split("/").filter((t=>""!=t)),n=r.split("/").filter((t=>""!=t)),s="*"===t[t.length-1]?n.slice(t.length-1).join("/"):"",i=a.endsWith("*")?a.slice(0,-1):a,l=i.startsWith("/")||/^[A-Z]:/i.test(i)?normalize(join(i,s)):join(process.cwd(),normalize(join(i,s)));l.endsWith("/")||l.endsWith("\\")?await Server.serveFile(join(l,"index.html"),e):await Server.serveFile(l,e)}else if("function"==typeof a){const n={};o.includes(":")&&o.split("/").filter((t=>""!=t)).forEach(((t,e)=>{t.startsWith(":")&&(n[t.slice(1)]=r.split("/").filter((t=>""!=t))[e])})),await a(t,e,n,s)}else console.error("Invalid Route Handler"),e.writeHead(500,{"Content-Type":"text/plain"}),e.end("Internal server error")}catch(t){console.error("Request error:",t),e.writeHead(500,{"Content-Type":"text/plain"}),e.end("Internal server error")}}listen(t=8080){return new Promise(((e,r)=>{try{const n=http.createServer(((t,e)=>this.handleRequest(t,e)));n.on("error",(e=>{"EADDRINUSE"===e.code?r(new Error(`Port ${t} is already in use`)):r(e)})),n.listen(t,(()=>{e(n)}))}catch(t){r(t)}}))}static mimeTypes={".html":"text/html; charset=utf-8",".js":"text/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".svg":"image/svg+xml",".ico":"image/x-icon",".txt":"text/plain; charset=utf-8",".md":"text/plain; charset=utf-8",".map":"application/json; charset=utf-8"};static textExtensions=[".txt",".md",".js",".css",".html",".json",".map"];static getMimeType(t){const e=extname(t).toLowerCase();return this.mimeTypes[e]?this.mimeTypes[e]:this.textExtensions.includes(e)?"text/plain; charset=utf-8":"application/octet-stream"}static async serveFile(t,e,r={}){try{const n=await readFile(t);e.writeHead(200,{"Content-Type":Server.getMimeType(t),...r}),e.end(n)}catch(t){const r="ENOENT"===t.code?404:500,n=404===r?"Not found":"Internal server error";e.writeHead(r,{"Content-Type":"text/plain"}),e.end(n)}}}
|
package/dist/utils/drag.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default(e={})=>{let t,o,n;const{element:s=(
|
|
1
|
+
export default(e={})=>{let t,o,n;const{element:s=()=>{},callback:a=()=>{},startCallback:v=()=>{},moveCallback:i=()=>{},endCallback:r=()=>{},preventScroll:d=!1}=e,u=s=>{d&&s.preventDefault(),clearTimeout(n);const v=s.pageX||s.touches[0].pageX,r=s.pageY||s.touches[0].pageY,u={x:v-t,y:r-o,...e};a(u),i(u)},c=({pageX:s,pageY:v})=>{clearTimeout(n);const i={x:s-t,y:v-o,...e};a(i),r(i),m()},p=s=>{clearTimeout(n),t=s.pageX||s.touches[0].pageX,o=s.pageY||s.touches[0].pageY;const a={x:0,y:0,...e};v(a),window.addEventListener("mousemove",u,{passive:!d}),window.addEventListener("mouseup",c,{passive:!d}),window.addEventListener("touchmove",u,{passive:!d}),window.addEventListener("touchend",c,{passive:!d})},m=()=>{window.removeEventListener("mousemove",u),window.removeEventListener("mouseup",c),window.removeEventListener("touchmove",u),window.removeEventListener("touchend",c)};return s.addEventListener("mousedown",p,{passive:!d}),s.addEventListener("touchstart",p,{passive:!d}),()=>{s.removeEventListener("mousedown",p),m()}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import fs from"fs/promises";import path from"path";export async function ensureDir(i){try{await fs.mkdir(i,{recursive:!0})}catch(i){if("EEXIST"!==i.code)throw i}}export async function copyDir(i,r){await ensureDir(r);const t=await fs.readdir(i,{withFileTypes:!0});for(const a of t){const t=path.join(i,a.name),o=path.join(r,a.name);a.isDirectory()?await copyDir(t,o):await fs.copyFile(t,o)}}export async function emptyDir(i){try{const r=await fs.readdir(i);await Promise.all(r.map((r=>fs.rm(path.join(i,r),{recursive:!0,force:!0}))))}catch(i){if("ENOENT"!==i.code)throw i}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function minifyCss(e){return e.replace(/\s*\{\s*/g,"{").replace(/\s*\}\s*/g,"}").replace(/\n/g,"").replace(/\r/g,"").replace(/\s+/g," ").replace(/\s*\:\s*/g,":").replace(/\s*\;\s*/g,";").replace(/;\}/g,"}")}
|
|
@@ -41,6 +41,14 @@
|
|
|
41
41
|
<p>Extend the <code>LazyComponent</code> class to create a lazy-loaded component. The component will render its content only when it becomes visible in the viewport.</p>
|
|
42
42
|
<pre><code class="hljs javascript"><span class="hljs-keyword">import</span> LazyComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'kempo'</span>;<br /><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyLazyComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LazyComponent</span> </span>{<br /> <span class="hljs-keyword">constructor</span>(){<br /> <span class="hljs-keyword">super</span>();<br /> <span class="hljs-comment">// Your Constructor</span><br /> }<br /> <span class="hljs-keyword">async</span> render(force){<br /> <span class="hljs-keyword">if</span>(<span class="hljs-keyword">await</span> <span class="hljs-keyword">super</span>.render(force)){<br /> <span class="hljs-comment">// Your render logic</span><br /> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br /> }<br /> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br /> }<br />}<br /><span class="hljs-built_in">window</span>.customElements.define(<span class="hljs-string">'my-lazy-component'</span>, MyLazyComponent);</code></pre>
|
|
43
43
|
|
|
44
|
+
<h3 id="basicUsage"><a href="#interval" class="no-link">In-View Interval Timeout</a></h3>
|
|
45
|
+
<p>In addition to using intersection observes to watch for components being scrolled into view, an interval is used to check if the component suddenly become visible via a display style change to itself or a parent. The timeout of the interval can be set for all instances of your LazyComponent by chaning the static member <code>inViewIntervalTimeout</code>.</p>
|
|
46
|
+
<pre><code class="hljs javascript"><span class="hljs-keyword">import</span> LazyComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'kempo'</span>;<br /><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyLazyComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LazyComponent</span> </span>{<br /> <span class="hljs-keyword">constructor</span>(){<br /> <span class="hljs-keyword">super</span>();<br /> <span class="hljs-comment">// Your Constructor</span><br /> }<br /> <span class="hljs-keyword">async</span> render(force){<br /> <span class="hljs-keyword">if</span>(<span class="hljs-keyword">await</span> <span class="hljs-keyword">super</span>.render(force)){<br /> <span class="hljs-comment">// Your render logic</span><br /> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br /> }<br /> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br /> }<br /><br /> <span class="hljs-keyword">static</span> inViewIntervalTimeout = <span class="hljs-number">200</span>; <span class="hljs-comment">// Change the inView checking interval to 200ms instead of the default 1000</span><br />}<br /><span class="hljs-built_in">window</span>.customElements.define(<span class="hljs-string">'my-lazy-component'</span>, MyLazyComponent);</code></pre>
|
|
47
|
+
|
|
48
|
+
<h5>Individal Component interval timer overwrites</h5>
|
|
49
|
+
<p>You can overwrite this interval timeout for individual elements by setting the <code>in-view-interval</code> attribute.</p>
|
|
50
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">my-lazy-component</span> <span class="hljs-attr">in-view-interval</span>=<span class="hljs-string">"5000"</span>></span><br /> <span class="hljs-comment"><!-- The interval to check if it is in-view (due to element/parent visibility change) is now set to check every 5 seconds --></span><br /><span class="hljs-tag"></<span class="hljs-name">my-lazy-component</span>></span></code></pre>
|
|
51
|
+
|
|
44
52
|
<h2 id="jsRef">JavaScript Reference</h2>
|
|
45
53
|
|
|
46
54
|
<h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Toast - Components - Kempo Docs - A Web Components Solution</title>
|
|
7
|
+
<link rel="stylesheet" href="../kempo/kempo-vars.css" /><link rel="stylesheet" href="../kempo/kempo-styles.css" />
|
|
8
|
+
<link rel="stylesheet" href="../kempo/kempo-hljs.css" />
|
|
9
|
+
<script type="module">
|
|
10
|
+
import Import from '../kempo/components/Import.js';
|
|
11
|
+
import Icon from '../kempo/components/Icon.js';
|
|
12
|
+
import Search from '../kempo/components/Search.js';
|
|
13
|
+
Import.addReplacement('root', '../');
|
|
14
|
+
Icon.pathToIcons = ['../icons'];
|
|
15
|
+
Search.searchDataUrl = '../search.json';
|
|
16
|
+
</script>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<k-import src="../nav.inc.html"></k-import>
|
|
20
|
+
<h1 class="ta-center">Toast</h1>
|
|
21
|
+
<main>
|
|
22
|
+
<details
|
|
23
|
+
class="b r mb"
|
|
24
|
+
>
|
|
25
|
+
<summary class="p">Table of Contents</summary>
|
|
26
|
+
<div class="m mt0 pl">
|
|
27
|
+
<h6>Examples</h6>
|
|
28
|
+
<a href="#basicUsage">Basic Usage</a><br />
|
|
29
|
+
<a href="#positions">Different Positions</a><br />
|
|
30
|
+
<a href="#timeouts">Timeouts</a><br />
|
|
31
|
+
<a href="#actionAndClose">Action and Close Buttons</a><br />
|
|
32
|
+
|
|
33
|
+
<h6 class="mt">JavaScript Reference</h6>
|
|
34
|
+
<a href="#constructor">Constructor</a><br />
|
|
35
|
+
<a href="#staticMethods">Static Methods</a><br />
|
|
36
|
+
<a href="#requirements">Requirements</a><br />
|
|
37
|
+
<a href="#attributes">Attributes</a><br />
|
|
38
|
+
<a href="#properties">Properties</a><br />
|
|
39
|
+
<a href="#methods">Methods</a><br />
|
|
40
|
+
<a href="#events">Events</a><br />
|
|
41
|
+
<a href="#toastContainer">ToastContainer</a><br />
|
|
42
|
+
</div>
|
|
43
|
+
</details>
|
|
44
|
+
|
|
45
|
+
<h3>Description</h3>
|
|
46
|
+
<p>The Toast component provides a way to display short-lived notifications to users. Toasts appear in a corner of the screen, can be configured with different positions, and can optionally include action and close buttons. Toasts can be set to automatically close after a specified timeout or remain until manually dismissed.</p>
|
|
47
|
+
|
|
48
|
+
<h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
|
|
49
|
+
<div class="row -mx">
|
|
50
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
51
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example1"</span>></span>Open Toast<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="javascript"><br /> <span class="hljs-keyword">import</span> Toast <span class="hljs-keyword">from</span> <span class="hljs-string">'/kempo/components/Toast.js'</span>;<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example1'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.create(<span class="hljs-string">"Hello World"</span>);<br /> });<br /></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
|
|
52
|
+
</div>
|
|
53
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
54
|
+
<button id="example1" class="mb">Open Toast</button>
|
|
55
|
+
<script type="module">
|
|
56
|
+
import Toast from '/kempo/components/Toast.js';
|
|
57
|
+
document.getElementById('example1').addEventListener('click', () => {
|
|
58
|
+
Toast.create("Hello World");
|
|
59
|
+
});
|
|
60
|
+
</script>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
<h3 id="positions"><a href="#positions" class="no-link">Different Positions</a></h3>
|
|
66
|
+
<p>Toasts can be positioned in different corners of the screen using the <code>position</code> property.</p>
|
|
67
|
+
<div class="row -mx">
|
|
68
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
69
|
+
|
|
70
|
+
</div>
|
|
71
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
72
|
+
<button id="example2-topleft" class="mb">Top Left</button>
|
|
73
|
+
<button id="example2-topcenter" class="mb">Top Center</button>
|
|
74
|
+
<button id="example2-topright" class="mb">Top Right</button><br />
|
|
75
|
+
<button id="example2-bottomleft" class="mb">Bottom Left</button>
|
|
76
|
+
<button id="example2-bottomcenter" class="mb">Bottom Center</button>
|
|
77
|
+
<button id="example2-bottomright" class="mb">Bottom Right</button>
|
|
78
|
+
<script type="module">
|
|
79
|
+
import Toast from '/kempo/components/Toast.js';
|
|
80
|
+
document.getElementById('example2-topleft').addEventListener('click', () => {
|
|
81
|
+
Toast.create("Hello Top Left", {
|
|
82
|
+
position: "top left"
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
document.getElementById('example2-topcenter').addEventListener('click', () => {
|
|
86
|
+
Toast.create("Hello Top Center", {
|
|
87
|
+
position: "top center"
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
document.getElementById('example2-topright').addEventListener('click', () => {
|
|
91
|
+
Toast.create("Hello Top Right", {
|
|
92
|
+
position: "top right"
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
document.getElementById('example2-bottomleft').addEventListener('click', () => {
|
|
96
|
+
Toast.create("Hello Bottom Left", {
|
|
97
|
+
position: "bottom left"
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
document.getElementById('example2-bottomcenter').addEventListener('click', () => {
|
|
101
|
+
Toast.create("Hello Bottom Center", {
|
|
102
|
+
position: "bottom center"
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
document.getElementById('example2-bottomright').addEventListener('click', () => {
|
|
106
|
+
Toast.create("Hello Bottom Right", {
|
|
107
|
+
position: "bottom right"
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
</script>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<h3 id="timeouts"><a href="#timeouts" class="no-link">Timeouts</a></h3>
|
|
115
|
+
<p>Toasts can automatically close after a specified timeout (in milliseconds). The default timeout when using <code>Toast.create</code> is <code>5000</code> (ms), or 5 seconds.</p>
|
|
116
|
+
<div class="row -mx">
|
|
117
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
118
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example3-1"</span>></span>Open 1 Second Timeout Toast<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example3-3"</span>></span>Open 3 Second Timeout Toast<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example3-10"</span>></span>Open 10 Second Timeout Toast<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="javascript"><br /> <span class="hljs-keyword">import</span> Toast <span class="hljs-keyword">from</span> <span class="hljs-string">'/kempo/components/Toast.js'</span>;<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example3-1'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.create(<span class="hljs-string">"I will timeout in 1 second"</span>, {<br /> <span class="hljs-attr">timeout</span>: <span class="hljs-number">1000</span><br /> });<br /> });<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example3-3'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.create(<span class="hljs-string">"I will timeout in 3 second"</span>, {<br /> <span class="hljs-attr">timeout</span>: <span class="hljs-number">3000</span><br /> });<br /> });<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example3-10'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.create(<span class="hljs-string">"I will timeout in 10 second"</span>, {<br /> <span class="hljs-attr">timeout</span>: <span class="hljs-number">10000</span><br /> });<br /> });<br /></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
121
|
+
<button id="example3-1" class="mb">Open 1 Second Timeout Toast</button>
|
|
122
|
+
<button id="example3-3" class="mb">Open 3 Second Timeout Toast</button>
|
|
123
|
+
<button id="example3-10" class="mb">Open 10 Second Timeout Toast</button>
|
|
124
|
+
<script type="module">
|
|
125
|
+
import Toast from '/kempo/components/Toast.js';
|
|
126
|
+
document.getElementById('example3-1').addEventListener('click', () => {
|
|
127
|
+
Toast.create("I will timeout in 1 second", {
|
|
128
|
+
timeout: 1000
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
document.getElementById('example3-3').addEventListener('click', () => {
|
|
132
|
+
Toast.create("I will timeout in 3 second", {
|
|
133
|
+
timeout: 3000
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
document.getElementById('example3-10').addEventListener('click', () => {
|
|
137
|
+
Toast.create("I will timeout in 10 second", {
|
|
138
|
+
timeout: 10000
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
</script>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
<h3 id="actionAndClose"><a href="#actionAndClose" class="no-link">Action and Close Buttons</a></h3>
|
|
147
|
+
<p>Toasts can have action and close buttons that trigger callbacks when clicked.</p>
|
|
148
|
+
<div class="row -mx">
|
|
149
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
150
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example4-action"</span>></span>Open Toast with Action<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example4-close"</span>></span>Open Toast with Close Button<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example4-action-close"</span>></span>Open Toast with Action and Close Button<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="javascript"><br /> <span class="hljs-keyword">import</span> Toast <span class="hljs-keyword">from</span> <span class="hljs-string">'/kempo/components/Toast.js'</span>;<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example4-action'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.create(<span class="hljs-string">"Hello World"</span>, {<br /> <span class="hljs-attr">timeout</span>: <span class="hljs-number">0</span>,<br /> <span class="hljs-attr">action</span>: <span class="hljs-string">'Click Me'</span>,<br /> <span class="hljs-attr">actionCallback</span>: <span class="hljs-function"><span class="hljs-params">()</span> =></span> {<br /> Toast.create(<span class="hljs-string">"You clicked the action"</span>);<br /> }<br /> });<br /> });<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example4-close'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.create(<span class="hljs-string">"Hello World"</span>, {<br /> <span class="hljs-attr">timeout</span>: <span class="hljs-number">0</span>,<br /> <span class="hljs-attr">close</span>: <span class="hljs-string">'<k-icon name="close"></div>'</span>,<br /> <span class="hljs-attr">closeCallback</span>: <span class="hljs-function"><span class="hljs-params">()</span> =></span> {<br /> Toast.create(<span class="hljs-string">"You closed the toast"</span>);<br /> }<br /> });<br /> });<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example4-action-close'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.create(<span class="hljs-string">"Hello World"</span>, {<br /> <span class="hljs-attr">timeout</span>: <span class="hljs-number">0</span>,<br /> <span class="hljs-attr">action</span>: <span class="hljs-string">'Click Me'</span>,<br /> <span class="hljs-attr">actionCallback</span>: <span class="hljs-function"><span class="hljs-params">()</span> =></span> {<br /> Toast.create(<span class="hljs-string">"You clicked the action"</span>);<br /> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; <span class="hljs-comment">// return false to prevent closing</span><br /> },<br /> <span class="hljs-attr">close</span>: <span class="hljs-string">'<k-icon name="close"></div>'</span>,<br /> <span class="hljs-attr">closeCallback</span>: <span class="hljs-function"><span class="hljs-params">()</span> =></span> {<br /> Toast.create(<span class="hljs-string">"You closed the toast"</span>);<br /> }<br /> });<br /> });<br /></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
|
|
151
|
+
</div>
|
|
152
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
153
|
+
<button id="example4-action" class="mb">Open Toast with Action</button>
|
|
154
|
+
<button id="example4-close" class="mb">Open Toast with Close Button</button>
|
|
155
|
+
<button id="example4-action-close" class="mb">Open Toast with Action and Close Button</button>
|
|
156
|
+
<script type="module">
|
|
157
|
+
import Toast from '/kempo/components/Toast.js';
|
|
158
|
+
document.getElementById('example4-action').addEventListener('click', () => {
|
|
159
|
+
Toast.create("Hello World", {
|
|
160
|
+
timeout: 0,
|
|
161
|
+
action: 'Click Me',
|
|
162
|
+
actionCallback: () => {
|
|
163
|
+
Toast.create("You clicked the action");
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
document.getElementById('example4-close').addEventListener('click', () => {
|
|
168
|
+
Toast.create("Hello World", {
|
|
169
|
+
timeout: 0,
|
|
170
|
+
close: '<k-icon name="close"></div>',
|
|
171
|
+
closeCallback: () => {
|
|
172
|
+
Toast.create("You closed the toast");
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
document.getElementById('example4-action-close').addEventListener('click', () => {
|
|
177
|
+
Toast.create("Hello World", {
|
|
178
|
+
timeout: 0,
|
|
179
|
+
action: 'Click Me',
|
|
180
|
+
actionCallback: () => {
|
|
181
|
+
Toast.create("You clicked the action");
|
|
182
|
+
return false; // return false to prevent closing
|
|
183
|
+
},
|
|
184
|
+
close: '<k-icon name="close"></div>',
|
|
185
|
+
closeCallback: () => {
|
|
186
|
+
Toast.create("You closed the toast");
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
</script>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<h3 id="successWarningError"><a href="#successWarningError" class="no-link">Success, Warning and Error</a></h3>
|
|
195
|
+
<p>Toasts can be created as a success, warning or error message.</p>
|
|
196
|
+
<div class="row -mx">
|
|
197
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
198
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example5-success"</span>></span>Success Toast<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example5-warning"</span>></span>Warning Toast<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"example5-error"</span>></span>Error Toast<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>></span><span class="javascript"><br /> <span class="hljs-keyword">import</span> Toast <span class="hljs-keyword">from</span> <span class="hljs-string">'/kempo/components/Toast.js'</span>;<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example5-success'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.success(<span class="hljs-string">"It Worked!"</span>);<br /> });<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example5-warning'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.warning(<span class="hljs-string">"Be Careful"</span>);<br /> });<br /> <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'example5-error'</span>).addEventListener(<span class="hljs-string">'click'</span>, () => {<br /> Toast.error(<span class="hljs-string">"That's a very bad idea"</span>);<br /> });<br /></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></code></pre>
|
|
199
|
+
</div>
|
|
200
|
+
<div class="col d-span-6 t-span-6 m-span-12 px">
|
|
201
|
+
<button id="example5-success" class="mb">Success Toast</button>
|
|
202
|
+
<button id="example5-warning" class="mb">Warning Toast</button>
|
|
203
|
+
<button id="example5-error" class="mb">Error Toast</button>
|
|
204
|
+
<script type="module">
|
|
205
|
+
import Toast from '/kempo/components/Toast.js';
|
|
206
|
+
document.getElementById('example5-success').addEventListener('click', () => {
|
|
207
|
+
Toast.success("It Worked!");
|
|
208
|
+
});
|
|
209
|
+
document.getElementById('example5-warning').addEventListener('click', () => {
|
|
210
|
+
Toast.warning("Be Careful");
|
|
211
|
+
});
|
|
212
|
+
document.getElementById('example5-error').addEventListener('click', () => {
|
|
213
|
+
Toast.error("That's a very bad idea");
|
|
214
|
+
});
|
|
215
|
+
</script>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
<h2 id="jsRef">JavaScript Reference</h2>
|
|
221
|
+
|
|
222
|
+
<h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
|
|
223
|
+
<h6>Extends <a href="./component.html">Component</a></h6>
|
|
224
|
+
<h5>
|
|
225
|
+
<code>new Toast()</code><br />
|
|
226
|
+
<code>new Toast(<i>object</i> options)</code>
|
|
227
|
+
</h5>
|
|
228
|
+
|
|
229
|
+
<h4>Parameters</h4>
|
|
230
|
+
<h5><code>options<i>: object</i></code></h5>
|
|
231
|
+
<p>An object with the following optional properties:</p>
|
|
232
|
+
<ul>
|
|
233
|
+
<li><code>actionCallback<i>: function</i></code> - Function to call when the action button is clicked. If this function returns <code>false</code>, the toast will not close.</li>
|
|
234
|
+
<li><code>actionHtml<i>: string</i></code> - HTML content for the action button.</li>
|
|
235
|
+
<li><code>closeCallback<i>: function</i></code> - Function to call when the toast is closed.</li>
|
|
236
|
+
<li><code>closeHtml<i>: string</i></code> - HTML content for the close button.</li>
|
|
237
|
+
<li><code>timeout<i>: number</i></code> - Time in milliseconds before the toast automatically closes. Default is 0 (no auto-close).</li>
|
|
238
|
+
</ul>
|
|
239
|
+
|
|
240
|
+
<h3 id="staticMethods"><a href="#staticMethods" class="no-link">Static Methods</a></h3>
|
|
241
|
+
<h5><code>Toast.create(message, options)<i>: Toast</i></code></h5>
|
|
242
|
+
<p>Creates and displays a new toast with the specified message and options. Returns the created Toast instance.</p>
|
|
243
|
+
<p>Options include:</p>
|
|
244
|
+
<ul>
|
|
245
|
+
<li><code>position<i>: string</i></code> - Position of the toast on the screen. Default is 'auto', which uses 'bottom center' on mobile and 'top right' on desktop. Valid positions are: 'top left', 'top center', 'top right', 'bottom left', 'bottom center', 'bottom right'.</li>
|
|
246
|
+
<li><code>removeOnClose<i>: boolean</i></code> - If true, the toast element will be removed from the DOM when closed. Default is true.</li>
|
|
247
|
+
<li><code>timeout<i>: number</i></code> - Time in milliseconds before the toast automatically closes. Default is 5000ms (5 seconds).</li>
|
|
248
|
+
<li><code>action<i>: string | HTMLElement</i></code> - Text or HTML element to use for the action button.</li>
|
|
249
|
+
<li><code>actionCallback<i>: function</i></code> - Function to call when the action button is clicked. If this function returns <code>false</code>, the toast will not close.</li>
|
|
250
|
+
<li><code>close<i>: string | HTMLElement</i></code> - Text or HTML element to use for the close button.</li>
|
|
251
|
+
<li><code>closeCallback<i>: function</i></code> - Function to call when the toast is closed.</li>
|
|
252
|
+
<li><code>icon<i>: string | HTMLElement</i></code> - Text or HTML element to use as an icon in the toast.</li>
|
|
253
|
+
</ul>
|
|
254
|
+
|
|
255
|
+
<h5><code>Toast.success(message, options)<i>: Toast</i></code></h5>
|
|
256
|
+
<p>Creates and displays a success toast with a check icon and applies a success background style. Accepts the same options as <code>Toast.create()</code>.</p>
|
|
257
|
+
|
|
258
|
+
<h5><code>Toast.warning(message, options)<i>: Toast</i></code></h5>
|
|
259
|
+
<p>Creates and displays a warning toast with a warning icon and applies a warning background style. Accepts the same options as <code>Toast.create()</code>.</p>
|
|
260
|
+
|
|
261
|
+
<h5><code>Toast.error(message, options)<i>: Toast</i></code></h5>
|
|
262
|
+
<p>Creates and displays an error toast with an error icon and applies a danger background style. Accepts the same options as <code>Toast.create()</code>.</p>
|
|
263
|
+
|
|
264
|
+
<h3 id="requirements"><a href="#requirements" class="no-link">Requirements</a></h3>
|
|
265
|
+
<ul>
|
|
266
|
+
<li><a href="./component.html">Component</a></li>
|
|
267
|
+
</ul>
|
|
268
|
+
|
|
269
|
+
<h3 id="attributes"><a href="#attributes" class="no-link">Attributes</a></h3>
|
|
270
|
+
<h5><code>action-html<i>: string</i></code></h5>
|
|
271
|
+
<p>HTML content for the action button.</p>
|
|
272
|
+
|
|
273
|
+
<h5><code>close-html<i>: string</i></code></h5>
|
|
274
|
+
<p>HTML content for the close button.</p>
|
|
275
|
+
|
|
276
|
+
<h5><code>timeout<i>: number</i></code></h5>
|
|
277
|
+
<p>Time in milliseconds before the toast automatically closes. Default is 0 (no auto-close).</p>
|
|
278
|
+
|
|
279
|
+
<h5><code>opened<i>: boolean</i></code></h5>
|
|
280
|
+
<p>Whether the toast is currently open. Default is false.</p>
|
|
281
|
+
|
|
282
|
+
<h3 id="properties"><a href="#properties" class="no-link">Properties</a></h3>
|
|
283
|
+
<h5><code>actionCallback<i>: function</i></code></h5>
|
|
284
|
+
<p>Function to call when the action button is clicked.</p>
|
|
285
|
+
|
|
286
|
+
<h5><code>closeCallback<i>: function</i></code></h5>
|
|
287
|
+
<p>Function to call when the toast is closed.</p>
|
|
288
|
+
|
|
289
|
+
<h5><code>actionHtml<i>: string</i></code></h5>
|
|
290
|
+
<p>HTML content for the action button.</p>
|
|
291
|
+
|
|
292
|
+
<h5><code>closeHtml<i>: string</i></code></h5>
|
|
293
|
+
<p>HTML content for the close button.</p>
|
|
294
|
+
|
|
295
|
+
<h5><code>timeout<i>: number</i></code></h5>
|
|
296
|
+
<p>Time in milliseconds before the toast automatically closes.</p>
|
|
297
|
+
|
|
298
|
+
<h5><code>opened<i>: boolean</i></code></h5>
|
|
299
|
+
<p>Whether the toast is currently open.</p>
|
|
300
|
+
|
|
301
|
+
<h3 id="methods"><a href="#methods" class="no-link">Methods</a></h3>
|
|
302
|
+
<h5><code>open()<i>: void</i></code></h5>
|
|
303
|
+
<p>Opens the toast. If a timeout is specified, this starts the timer for automatic closing.</p>
|
|
304
|
+
|
|
305
|
+
<h5><code>close()<i>: void</i></code></h5>
|
|
306
|
+
<p>Closes the toast and calls the <code>closeCallback</code> if provided.</p>
|
|
307
|
+
|
|
308
|
+
<h3 id="events"><a href="#events" class="no-link">Events</a></h3>
|
|
309
|
+
<h5><code>open</code></h5>
|
|
310
|
+
<p>Fired when the toast is opened.</p>
|
|
311
|
+
|
|
312
|
+
<h5><code>close</code></h5>
|
|
313
|
+
<p>Fired when the toast is closed.</p>
|
|
314
|
+
|
|
315
|
+
<h5><code>openchange</code></h5>
|
|
316
|
+
<p>Fired when the toast open state changes (both when opening and closing).</p>
|
|
317
|
+
|
|
318
|
+
<h3 id="toastContainer"><a href="#toastContainer" class="no-link">ToastContainer</a></h3>
|
|
319
|
+
<p>The <code>ToastContainer</code> is an internal component used to position and display toasts. It is automatically created when <code>Toast.create()</code> is called, but can also be used directly.</p>
|
|
320
|
+
|
|
321
|
+
<h5><code>new ToastContainer(position)</code></h5>
|
|
322
|
+
<p>Creates a new toast container at the specified position.</p>
|
|
323
|
+
|
|
324
|
+
<h5><code>position<i>: string</i></code></h5>
|
|
325
|
+
<p>The position of the container on the screen. Valid values are: 'top left', 'top center', 'top right', 'bottom left', 'bottom center', 'bottom right'.</p>
|
|
326
|
+
|
|
327
|
+
</main>
|
|
328
|
+
<script type="module" src="../kempo/components/Import.js"></script>
|
|
329
|
+
</body>
|
|
330
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="error" d="M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240ZM330-120 120-330v-300l210-210h300l210 210v300L630-120H330Zm34-80h232l164-164v-232L596-760H364L200-596v232l164 164Zm116-280Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="warning" d="m40-120 440-760 440 760H40Zm138-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm-40-120h80v-200h-80v200Zm40-100Z"/></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCase}from"../utils/string.js";export default class Component extends HTMLElement{constructor(t={}){super(),this.attachShadow({mode:"open",...t}),this.registerAttribute("rendered",!1)}async connectedCallback(){this.render(!0)}async disconnectedCallback(){}async attributeChangedCallback(){}async propChangedCallback(){}async render(t=!1){if(t||!this.rendered)return this.shadowRoot.innerHTML=`<link rel="stylesheet" href="${Component.pathToKempo}/kempo-styles.css" />${this.shadowTemplate}<style>${this.shadowStyles}</style>`,this.rendered=!0,!0}registerAttribute(t,e=""){const{camel:s,dash:r}=getCase(t),i=typeof e;Object.defineProperty(this,s,{get:()=>{const t=this.getAttribute(r);return"number"==i?parseFloat(t):"object"===i?"string"==typeof t?JSON.parse(t):t:"boolean"===i?"string"==typeof t?"true"===t.toLowerCase().trim():!!t:"string"===i?t||"":t},set:t=>{this[r]!==t&&("boolean"===i?t?this.setAttribute(r,"true"):this.removeAttribute(r):"object"===i?this.setAttribute(r,JSON.stringify(t||{})):"number"===i?t||0===t?this.setAttribute(r,t):this.removeAttribute(r):this.setAttribute(r,t))}}),null===this.getAttribute(r)&&(this[s]=e)}registerAttributes(t){for(const e in t)this.registerAttribute(e,t[e])}registerProp(t,e){const s=Symbol(t);this[s]=e,Object.defineProperty(this,t,{get:()=>this[s],set:e=>{if(this[s]!==e){const r=this[s];this[s]=e,this.propChangedCallback(t,r,e)}}})}registerProps(t){for(const e in t)this.registerProp(e,t[e])}renderIf(t,e){return t?e:""}get shadowTemplate(){return"\n <slot></slot>\n "}get shadowStyles(){return""}static observedAttributes=["rendered"];static pathToKempo=import.meta.url.substring(0,import.meta.url.indexOf("/components/Component.js"))}
|
|
1
|
+
import{getCase}from"../utils/string.js";export default class Component extends HTMLElement{constructor(t={}){super(),this.attachShadow({mode:"open",...t}),this.registerAttribute("rendered",!1)}async connectedCallback(){this.render(!0)}async disconnectedCallback(){}async attributeChangedCallback(){}async propChangedCallback(){}async render(t=!1){if(t||!this.rendered)return this.shadowRoot.innerHTML=`<link rel="stylesheet" href="${Component.pathToKempo}/kempo-styles.css" />${this.shadowTemplate}<style>${this.shadowStyles}</style>`,this.rendered=!0,!0}registerAttribute(t,e=""){const{camel:s,dash:r}=getCase(t),i=typeof e;Object.defineProperty(this,s,{get:()=>{const t=this.getAttribute(r);return"number"==i?parseFloat(t):"object"===i?"string"==typeof t?JSON.parse(t):t:"boolean"===i?"string"==typeof t?"true"===t.toLowerCase().trim():!!t:"string"===i?t||"":t},set:t=>{this[r]!==t&&("boolean"===i?t?this.setAttribute(r,"true"):this.removeAttribute(r):"object"===i?this.setAttribute(r,JSON.stringify(t||{})):"number"===i?t||0===t?this.setAttribute(r,t):this.removeAttribute(r):this.setAttribute(r,t))}}),null===this.getAttribute(r)&&(this[s]=e)}registerAttributes(t){for(const e in t)this.registerAttribute(e,t[e])}registerProp(t,e){const s=Symbol(t);this[s]=e,Object.defineProperty(this,t,{get:()=>this[s],set:e=>{if(this[s]!==e){const r=this[s];this[s]=e,this.propChangedCallback(t,r,e)}}})}registerProps(t){for(const e in t)this.registerProp(e,t[e])}renderIf(t,e){return t?e:""}get shadowTemplate(){return"\n <slot></slot>\n "}get shadowStyles(){return""}static observedAttributes=["rendered"];static pathToKempo=import.meta.url.substring(0,import.meta.url.indexOf("/components/Component.js"))}window.customElements.define("k-component",Component);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import Component from"./Component.js";import"./FocusCapture.js";import"./Icon.js";import{firstFocusable,onEvent,offEvent,dispatchEvent}from"../utils/element.js";export default class Dialog extends Component{constructor({opened:e=!1,closeBtn:
|
|
1
|
+
import Component from"./Component.js";import"./FocusCapture.js";import"./Icon.js";import{firstFocusable,onEvent,offEvent,dispatchEvent}from"../utils/element.js";export default class Dialog extends Component{constructor({opened:e=!1,closeBtn:n=!0,overlayClose:t=!0,confirmText:o="",confirmClasses:s="success ml",confirmAction:i=()=>{},cancelText:l="",cancelClasses:c="",cancelAction:a=()=>{},closeCallback:r=()=>{}}={}){super(),this.registerAttributes({opened:e,closeBtn:n,overlayClose:t,confirmText:o,confirmClasses:s,cancelText:l,cancelClasses:c}),this.registerProps({confirmAction:i,cancelAction:a,closeCallback:r,previousFocus:null,_clickHandler:e=>{const{target:{id:n}}=e;"overlay"==n&&this.overlayClose||"close"==n?this.close():"cancel"==n?(this.cancelAction(e),e.defaultPrevented||this.close()):"confirm"==n&&(this.confirmAction(e),e.defaultPrevented||this.close())},_keydownHandler:({keyCode:e})=>{27===e&&this.close()},_hasTitle:()=>!!this.querySelector('[slot="title"]')})}connectedCallback(){super.connectedCallback(),onEvent(this.shadowRoot,"click",this._clickHandler)}disconnectedCallback(){super.connectedCallback(),offEvent(this.shadowRoot,"click",this._clickHandler),offEvent(window,"keydown",this._keydownHandler)}attributeChangedCallback(e,n,t){super.attributeChangedCallback(e,n,t),"opened"===name&&dispatchEvent(this,t?"opened":"close")}open(){this.opened=!0;const e=this.shadowRoot.querySelector("[autofocus]")||firstFocusable(this.shadowRoot);e&&e.focus(),onEvent(window,"keydown",this._keydownHandler)}close(){this.opened=!1,this.blur(),this.closeCallback(),offEvent(window,"keydown",this._keydownHandler)}toggle(){this.opened?this.close():this.open()}focus(){const e=firstFocusable(this.shadowRoot);e&&(this.previousFocus=document.activeElement,e.focus())}blur(){this.previousFocus&&this.previousFocus.focus()}get shadowTemplate(){return`\n <k-focus-capture>\n <button id="overlay" aria-label="Close the Dialog"></button>\n <div id="wrapper">\n <div\n id="dialog"\n role="dialog"\n aria-modal="true"\n aria-labelledby="title"\n >\n <div\n id="header"\n class="${this._hasTitle()?"has-title":""}"\n >\n <div\n id="title"\n ><slot name="title"></slot></div>\n ${this.renderIf(this.closeBtn,'\n <button\n id="close"\n >\n <k-icon name="close"></k-icon>\n </button>\n ')}\n </div>\n <div id="body">\n ${super.shadowTemplate}\n </div>\n ${this.renderIf(this.cancelText||this.confirmText,`\n <div id="footer">\n ${this.renderIf(this.cancelText,`\n <button id="cancel" class="${this.cancelClasses}">\n ${this.cancelText}\n </button>\n `)}\n ${this.renderIf(this.confirmText,`\n <button id="confirm" class="${this.confirmClasses}">\n ${this.confirmText}\n </button>\n `)}\n </div>\n `)}\n </div>\n </div>\n </k-focus-capture>\n `}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: inline;\n height: 1px;\n width: 1px;\n position: fixed; /* The browser seems to sometimes lazy load this if its out of view, this seems to fix it*/\n top: 0;\n left: 0;\n z-index: 100;\n }\n :host(:not([opened])){\n display: none;\n }\n #overlay {\n position: fixed;\n width: 100vw;\n height: 100vh;\n top: 0;\n left: 0;\n background-color: var(--c_overlay);\n z-index: 100;\n border: 0px solid transparent;\n box-shadow: 0 0 0 transparent;\n }\n #wrapper {\n display: flex;\n justify-content: center;\n align-items: center;\n position: fixed;\n width: 100%;\n height: 100vh;\n top: 0;\n left: 0;\n z-index: 101;\n pointer-events: none;\n }\n #dialog {\n display: flex;\n flex-direction: column;\n min-width: var(--min_width, 20rem);\n width: var(--width, fit-content);\n max-width: var(--max_width, calc(100vw - 4rem));\n min-height: var(--min_height, 12rem);\n height: var(--height, fit-content);\n max-height: var(--max_height, calc(100vh - 4rem));\n background-color: var(--c_bg);\n box-shadow: var(--drop_shadow);\n border-radius: var(--radius);\n pointer-events: all;\n }\n #header {\n display: flex;\n align-items: center;\n }\n #header.has-title {\n border-bottom: 1px solid var(--c_border);\n }\n #title {\n flex: 1 1 auto;\n }\n #close {\n border: 0px;\n background: transparent;\n box-shadow: 0 0 0 transparent;\n color: var(--tc);\n }\n #close k-icon {\n pointer-events: none;\n }\n #body {\n flex: 1 1 auto;\n }\n #footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--spacer_h);\n }\n `}static renderOnChange=["opened","closeBtn","overlayClose","title","confirmText","cancelText"];static create(e="",n={}){!1!==n.closeExisting&&document.querySelectorAll("k-dialog").forEach((e=>e.close()));const{removeOnClose:t=!0,closeCallback:o=()=>{}}=n,s=new Dialog({opened:!0,...n,closeCallback:(...e)=>{t&&s.remove(),o(...e)}});return onEvent(s,"close",s.remove),e instanceof HTMLElement||e instanceof DocumentFragment?s.appendChild(e):e instanceof NodeList?e.forEach((e=>s.appendChild(e))):s.innerHTML=e,n.width&&s.style.setProperty("--width",n.width),n.minWidth&&s.style.setProperty("--min_width",n.minWidth),n.maxWidth&&s.style.setProperty("--max_width",n.maxWidth),n.height&&s.style.setProperty("--height",n.height),n.minHeight&&s.style.setProperty("--min_height",n.minHeight),n.maxHeight&&s.style.setProperty("--max_height",n.maxHeight),document.body.prepend(s),s.open(),s}static confirm(e,n,t={title:"Confirm"}){return Dialog.create(`\n <h5 slot="title" class="pyh px m0">${t.title}</h5>\n <p class="p">${e}</p>\n `,{...t,closeBtn:!1,overlayClose:!1,confirmText:"Yes",confirmClasses:"success ml",confirmAction:()=>n(!0),cancelText:"No",cancelClasses:"danger",cancelAction:()=>n(!1)})}static alert(e,n,t={title:"Alert"}){return Dialog.create(`\n <h5 slot="title" class="pyh px m0">${t.title}</h5>\n <p class="p">${e}</p>\n `,{closeCallback:n,cancelText:"Ok",...t})}static error(e,n,t={title:"Error"}){return Dialog.create(`\n <h5 slot="title" class="pyh px m0 tc-danger">${t.title}</h5>\n <p class="p">${e}</p>\n `,{closeCallback:n,cancelText:"Ok",...t})}static success(e,n,t={title:"Success"}){return Dialog.create(`\n <h5 slot="title" class="pyh px m0 tc-success">${t.title}</h5>\n <p class="p">${e}</p>\n `,{closeCallback:n,cancelText:"Ok",...t})}}window.customElements.define("k-dialog",Dialog);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import Component from"./Component.js";import{isInView}from"../utils/element.js";import raf from"../utils/raf.js";const
|
|
1
|
+
import Component from"./Component.js";import{isInView}from"../utils/element.js";import raf from"../utils/raf.js";const inViewIntervalId=Symbol();export default class LazyComponent extends Component{constructor(e){super(e),this[inViewIntervalId]=null,new IntersectionObserver((([e])=>{e.intersectionRatio>0&&!this.rendered?this.inViewCallback():this.outOfViewCallback()})).observe(this),this.registerAttributes({unrender:!1,inViewInterval:0})}connectedCallback(){this.renderSkelton(),raf((()=>{isInView(this)?this.inViewCallback():this.outOfViewCallback()}),2)}async inViewCallback(){return clearInterval(this[inViewIntervalId]),await this.render()}async outOfViewCallback(){return clearInterval(this[inViewIntervalId]),this[inViewIntervalId]=setInterval((async()=>{await isInView(this)&&this.inViewCallback()}),this.inViewInterval||LazyComponent.inViewIntervalTimeout),!!this.unrender&&(await this.renderSkelton(),!0)}async renderSkelton(){return this.shadowRoot.innerHTML=`<link rel="stylesheet" href="${Component.pathToKempo}/kempo-styles.css" />${this.skeletonTemplate}<style>${this.shadowStyles}</style>`,this.rendered=!1,!0}get skeletonTemplate(){return'<div style="height: var(--skeleton_height, 1rem)"></div>'}static inViewIntervalTimeout=1e3}
|