standard-ui/components/dist/notifications.min.js
sairaj mote e47bb90750 feature update
-- added option method to remove specific notification based on notification ID returned when pushing
-- consistent style improvements
2022-10-18 02:54:42 +05:30

1 line
11 KiB
JavaScript

const smNotifications=document.createElement("template");smNotifications.innerHTML='\n <style>\n *{\n padding: 0;\n margin: 0;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n } \n :host{\n display: flex;\n --icon-height: 1.5rem;\n --icon-width: 1.5rem;\n }\n .hide{\n opacity: 0 !important;\n pointer-events: none !important;\n }\n .notification-panel{\n display: grid;\n width: 100%;\n gap: 0.5rem;\n position: fixed;\n left: 0;\n top: 0;\n z-index: 100;\n max-height: 100%;\n padding: 1rem;\n overflow: hidden auto;\n -ms-scroll-chaining: none;\n overscroll-behavior: contain;\n touch-action: none;\n }\n .notification-panel:empty{\n display:none;\n }\n .notification{\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n position: relative;\n border-radius: 0.3rem;\n background: rgba(var(--foreground-color, (255,255,255)), 1);\n overflow: hidden;\n overflow-wrap: break-word;\n word-wrap: break-word;\n -ms-word-break: break-all;\n word-break: break-all;\n word-break: break-word;\n -ms-hyphens: auto;\n -webkit-hyphens: auto;\n hyphens: auto;\n max-width: 100%;\n padding: 1rem;\n align-items: center;\n box-shadow: 0 0.5rem 1rem 0 rgba(0,0,0,0.14);\n touch-action: none;\n }\n .icon-container:not(:empty){\n margin-right: 0.5rem;\n height: var(--icon-height);\n width: var(--icon-width);\n }\n h4:first-letter,\n p:first-letter{\n text-transform: uppercase;\n }\n h4{\n font-weight: 400;\n }\n p{\n line-height: 1.6;\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n color: rgba(var(--text-color, (17,17,17)), 0.9);\n overflow-wrap: break-word;\n overflow-wrap: break-word;\n word-wrap: break-word;\n -ms-word-break: break-all;\n word-break: break-all;\n word-break: break-word;\n -ms-hyphens: auto;\n -webkit-hyphens: auto;\n hyphens: auto;\n max-width: 100%;\n }\n .notification:last-of-type{\n margin-bottom: 0;\n }\n .icon {\n height: 100%;\n width: 100%;\n fill: rgba(var(--text-color, (17,17,17)), 0.7);\n }\n .icon--success {\n fill: var(--green);\n }\n .icon--failure,\n .icon--error {\n fill: var(--danger-color);\n }\n .close{\n height: 2rem;\n width: 2rem;\n border: none;\n cursor: pointer;\n margin-left: 1rem;\n border-radius: 50%;\n padding: 0.3rem;\n transition: background-color 0.3s, transform 0.3s;\n background-color: transparent;\n flex-shrink: 0;\n }\n .close:active{\n transform: scale(0.9);\n }\n .action{\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.5rem 0.8rem;\n border-radius: 0.2rem;\n border: none;\n background-color: rgba(var(--text-color, (17,17,17)), 0.03);\n font-family: inherit;\n font-size: inherit;\n color: var(--accent-color, teal);\n font-weight: 500;\n cursor: pointer;\n }\n @media screen and (max-width: 640px){\n .notification-panel:not(:empty){\n padding-bottom: 3rem;\n }\n }\n @media screen and (min-width: 640px){\n .notification-panel{\n max-width: 28rem;\n width: max-content;\n top: auto;\n bottom: 0;\n }\n .notification{\n width: auto;\n border: solid 1px rgba(var(--text-color, (17,17,17)), 0.2);\n }\n }\n @media (any-hover: hover){\n ::-webkit-scrollbar{\n width: 0.5rem;\n }\n \n ::-webkit-scrollbar-thumb{\n background: rgba(var(--text-color, (17,17,17)), 0.3);\n border-radius: 1rem;\n &:hover{\n background: rgba(var(--text-color, (17,17,17)), 0.5);\n }\n }\n .close:hover{\n background-color: rgba(var(--text-color, (17,17,17)), 0.1);\n }\n }\n </style>\n <div class="notification-panel"></div>\n ',customElements.define("sm-notifications",class extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"}).append(smNotifications.content.cloneNode(!0)),this.notificationPanel=this.shadowRoot.querySelector(".notification-panel"),this.animationOptions={duration:300,fill:"forwards",easing:"cubic-bezier(0.175, 0.885, 0.32, 1.275)"},this.push=this.push.bind(this),this.createNotification=this.createNotification.bind(this),this.removeNotification=this.removeNotification.bind(this),this.clearAll=this.clearAll.bind(this),this.remove=this.remove.bind(this),this.handlePointerMove=this.handlePointerMove.bind(this),this.startX=0,this.currentX=0,this.endX=0,this.swipeDistance=0,this.swipeDirection="",this.swipeThreshold=0,this.startTime=0,this.swipeTime=0,this.swipeTimeThreshold=200,this.currentTarget=null,this.mediaQuery=window.matchMedia("(min-width: 640px)"),this.handleOrientationChange=this.handleOrientationChange.bind(this),this.isLandscape=!1}randString(n){let t="";const i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";for(let e=0;e<n;e++)t+=i.charAt(Math.floor(Math.random()*i.length));return t}createNotification(n,t={}){const{pinned:i=!1,icon:e="",action:o}=t,r=document.createElement("div");r.id=this.randString(8),r.classList.add("notification");let a="";return a+=`\n <div class="icon-container">${e}</div>\n <output>${n}</output>\n `,o&&(a+=`\n <button class="action">${o.label}</button>\n `),i&&(r.classList.add("pinned"),a+='\n <button class="close">\n <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="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></svg>\n </button>\n '),r.innerHTML=a,r}push(n,t={}){const i=this.createNotification(n,t);return this.isLandscape?this.notificationPanel.append(i):this.notificationPanel.prepend(i),this.notificationPanel.animate([{transform:`translateY(${this.isLandscape?"":"-"}${i.clientHeight}px)`},{transform:"none"}],this.animationOptions),i.animate([{transform:"translateY(-1rem)",opacity:"0"},{transform:"none",opacity:"1"}],this.animationOptions).onfinish=(n=>{n.target.commitStyles(),n.target.cancel()}),i.querySelector(".action")&&i.querySelector(".action").addEventListener("click",t.action.callback),i.id}removeNotification(n,t="left"){if(!n)return;const i="left"===t?"-":"+";n.animate([{transform:this.currentX?`translateX(${this.currentX}px)`:"none",opacity:"1"},{transform:`translateX(calc(${i}${Math.abs(this.currentX)}px ${i} 1rem))`,opacity:"0"}],this.animationOptions).onfinish=(()=>{n.remove()})}remove(n){const t=this.notificationPanel.querySelector(`#${n}`);t&&this.removeNotification(t)}clearAll(){Array.from(this.notificationPanel.children).forEach(n=>{this.removeNotification(n)})}handlePointerMove(n){this.currentX=n.clientX-this.startX,this.currentTarget.style.transform=`translateX(${this.currentX}px)`}handleOrientationChange(n){this.isLandscape=n.matches,n.matches}connectedCallback(){this.handleOrientationChange(this.mediaQuery),this.mediaQuery.addEventListener("change",this.handleOrientationChange),this.notificationPanel.addEventListener("pointerdown",n=>{n.target.closest(".close")?this.removeNotification(n.target.closest(".notification")):n.target.closest(".notification")&&(this.swipeThreshold=n.target.closest(".notification").getBoundingClientRect().width/2,this.currentTarget=n.target.closest(".notification"),this.currentTarget.setPointerCapture(n.pointerId),this.startTime=Date.now(),this.startX=n.clientX,this.startY=n.clientY,this.notificationPanel.addEventListener("pointermove",this.handlePointerMove))}),this.notificationPanel.addEventListener("pointerup",n=>{this.endX=n.clientX,this.endY=n.clientY,this.swipeDistance=Math.abs(this.endX-this.startX),this.swipeTime=Date.now()-this.startTime,this.endX>this.startX?this.swipeDirection="right":this.swipeDirection="left",this.swipeTime<this.swipeTimeThreshold?this.swipeDistance>50&&this.removeNotification(this.currentTarget,this.swipeDirection):this.swipeDistance>this.swipeThreshold?this.removeNotification(this.currentTarget,this.swipeDirection):this.currentTarget.animate([{transform:`translateX(${this.currentX}px)`},{transform:"none"}],this.animationOptions).onfinish=(n=>{n.target.commitStyles(),n.target.cancel()}),this.notificationPanel.removeEventListener("pointermove",this.handlePointerMove),this.notificationPanel.releasePointerCapture(n.pointerId),this.currentX=0});const n=new MutationObserver(n=>{n.forEach(n=>{"childList"===n.type&&n.addedNodes.length&&!n.addedNodes[0].classList.contains("pinned")&&setTimeout(()=>{this.removeNotification(n.addedNodes[0])},5e3)})});n.observe(this.notificationPanel,{childList:!0})}disconnectedCallback(){mediaQueryList.removeEventListener("change",handleOrientationChange)}});