UNPKG

ziko-ui

Version:

1,417 lines (1,360 loc) 44.8 kB
/* Project: ziko-ui Author: Date : Wed Nov 20 2024 17:29:34 GMT+0100 (UTC+01:00) */ import { ZikoUIElement, html, watchAttr, ZikoUIContainerElement, ZikoUIFlex, Section, Flex, text as text$1, h3, ZikoUISection } from 'ziko'; class ZikoUICollapbsible extends ZikoUIElement{ constructor(summary,content,openIcon="😁", closeIcon=openIcon){ super("details","Collapsible"); Object.assign(this.cache,{ icons:{ open : openIcon, close : closeIcon } }); this.summary=html("summary",summary).style({ fontSize:"1.1em", padding:"0.625rem", fontWeight:"bold", listStyleType:`"${openIcon}"`, cursor:"pointer", }); this.summary[0].style({ marginLeft:"0.5em", }); this.content=content.style({ margin:"0.7em", }); this.element?.append(this.summary.element,this.content.element); this.style({ marginBottom:"0.7em", }); watchAttr(this, e=>{ if(e.target.isOpen){ e.target.emit("open"); if(this?.parent?.isAccordion){ if(this.parent.cache.autoClose)this.parent.closeExcept(this); } this.summary.style({ listStyleType:`"${this.cache.icons.close}"` }); } else { e.target.emit("close"); this.summary.style({ listStyleType:`"${this.cache.icons.open}"` }); } }); } get isCollapsible(){ return true; } get isOpen(){ return this.element.open; } open(details=this){ this.element.open=true; this.emit("open",details); return this; } close(){ this.element.open=false; return this; } onOpen(callback){ this.on("open", callback); return this; } onClose(callback){ this.on("close", callback); return this; } toggle(){ this.element.open=!this.element.open; return this; } } const Collapsible=(summary, content, openIcon, closeIcon)=>new ZikoUICollapbsible(summary,content,openIcon, closeIcon); class ZikoUIAccordion extends ZikoUIContainerElement{ constructor(...Collapsible){ super("div", "Accordion"); this.append(...Collapsible); Object.assign(this.cache,{ autoClose : true }); } get isAccordion(){ return true; } closeAll(){ this.items.forEach(n=>n.close()); return this; } closeExcept(...Collapsibles){ this.items.filter(n=>!Collapsibles.includes(n)).forEach(n=>n.close()); return this; } open(CollapsibleOrIndex){ CollapsibleOrIndex.isCollapsible? CollapsibleOrIndex.open(): this.items[CollapsibleOrIndex].open(); this.closeExcept(CollapsibleOrIndex.isCollapsible? CollapsibleOrIndex: this.items[CollapsibleOrIndex]); return this; } enableAutoClose(){ this.cache.autoClose = true; return this; } disableAutoClose(){ this.cache.autoClose = false; return this; } toggleAutoClose(){ this.cache.autoClose = !this.cache.autoClose; } } const Accordion = (... Collapsible) => new ZikoUIAccordion(...Collapsible); class ZikoUICarousel extends ZikoUIFlex{ constructor(...ZikoUIElement){ super(); this.style({ position:"relative", overflow:"hidden", touchAction:"none", userSelect:"none" }); this.horizontal("space-around",0); this.track = Section(...ZikoUIElement).style({ display: "inline-flex" }); this.track.size(this.track.children.length * 100 + "vw"); this.track.setTarget(this); this.track.items.map((n) => n.style({ pointerEvents: "none", margin: "auto 10px" }) ); this.x0 = null; this.tx = 0; this.onPtrMove(e=>{ if(e.isDown){ let x = e.event.pageX; let dx = x - this.x0; this.track.st.translateX( this.tx + dx, 0 ); } }); this.onPtrDown(e=>{ console.log(e.event); this.x0 = e.event.pageX; const transformMatrix = window .getComputedStyle(this.track.element) .getPropertyValue("transform"); if (transformMatrix !== "none") { this.tx = +transformMatrix.split(",")[4]; } }); this.onPtrUp(e=>console.log(e.isDown)); this.onPtrLeave(e=>{ // Handle outside up }); } get isCarousel(){ return true; } } const Carousel=(...ZikoUIElement)=>new ZikoUICarousel(...ZikoUIElement); class ZikoUICodeNote extends ZikoUIFlex{ constructor(){ super("section"); Object.assign(this.cache,{ order:0, currentNote:null, currentNoteIndex:null }); this.vertical(0,0); } get isCodeNote(){ return true; } setCurrentNote(currentNote){ this.cache.currentNote=currentNote; this.cache.currentNoteIndex=this.items.findIndex(n=>n===currentNote); currentNote.focus(); this.items.forEach(n=>n.Input.style({ border: "1px solid #ccc" })); currentNote.Input.style({ border:"2px lightgreen solid" }); return this; } addNote(text=""){ this.append(CodeCell(text)); return this; } execute(){ this.cache.currentNote.execute(); this.incrementOrder(); return this; } incrementOrder(){ this.cache.order++; this.cache.currentNote.setOrder(this.cache.order); return this; } next(){ if(this.cache.currentNote===this.items.at(-1)){ this.addNote(); this.setCurrentNote(this.items.at(-1)); } else this.setCurrentNote(this.items[this.cache.currentNoteIndex+1]); return this; } previous(){ // add append before if(this.cache.currentNote!==this.items[0]){ this.setCurrentNote(this.items[this.cache.currentNoteIndex-1]); } return this; } data(){ return this.items.map(n=>n.cellData()); } serialize(){ return JSON.stringify(this.data()); } import(data=[]){ data.forEach((n,i)=>this.addNote(data[i].input)); return this; } } const CodeNote=()=>new ZikoUICodeNote(); const Input=(codeText="")=>html("code",codeText).style({ width:"100%", height:"auto", padding:"10px", boxSizing:"border-box", border: "1px solid #ccc", outline: "none", fontSize: "1rem", fontFamily: "Lucida Console, Courier New, monospace", padding: "1rem 0.5rem", wordBreak:"break-all", background:"#f6f8fa", color:"#0062C3" }).setAttr("contenteditable",true).setAttr("spellcheck",false); const Output=()=>html("output").style({ width:"100%", height:"auto", padding:"5px 0", }); const Left=(ctx)=>Flex( text$1("[ ]") ).style({ width:"50px", //height:getComputedStyle(ctx.Input.element).height, height:"50px", margin:"10px 4px", padding:"5px", color:"darkblue", borderBottom:"4px solid gold", }).horizontal(0,0); const BTN_STYLE={ background:"none", width:"25px", height:"25px", fontSize:"1.2rem", cursor:"pointer" }; const Right=(ctx)=>Flex( text$1('▶️').style(BTN_STYLE).onClick(e=>{ if(ctx.parent instanceof ZikoUICodeNote)ctx.parent.setCurrentNote(ctx); ctx.execute(); globalThis.__Ziko__.__Config__.default.target=e.target.parent.parent[1][1]; }), text$1('📋').style(BTN_STYLE).onClick(()=>{ navigator.clipboard.writeText(ctx.codeText); }), text$1('✖️').style(BTN_STYLE).onClick(()=>ctx.remove()), text$1('✖️').style(BTN_STYLE).onClick(()=>ctx.remove()), ).style({ width:"70px", height:"50px", //background:"cyan", margin:"10px 0" }).horizontal(0,0).wrap(true); class ZikoUICodeCell extends ZikoUIFlex{ constructor(code="",{type="js",order=null}={}){ super("section"); Object.assign(this.cache,{ state:null, order, type, metadata:{ created:Date.now(), updated:null } }); this.Input=Input(code); this.Output=Output(); this.InOut=Flex( this.Input, this.Output ).vertical().style({ width:"100%", margin:"10px auto" }); this.RightControl=Right(this); this.LeftControl=Left(); this.append( this.LeftControl, this.InOut, this.RightControl ); this.horizontal(-1,1).style({ //background:"#444", width:"95vw", margin:"0 auto", border:"1px darkblue dotted" }); let cm_content = this.Input.element.getElementsByClassName("cm-content")[0]; if( cm_content ){ cm_content.addEventListener("keydown",e=>{ if(e.key === "Enter" && e.shiftKey){ e.preventDefault(); this.execute(this.cache.order); } }); } else { this.Input.onKeyDown(e=>{ if(e.kd==="Enter"){ if(e.event.shiftKey){ e.event.preventDefault(); this.execute(this.cache.order); } } if(this.cache.parent instanceof ZikoUICodeNote){ if(e.kd==="ArrowDown" && e.event.shiftKey ){ this.cache.parent.next(); } if(e.kd==="ArrowUp" && e.event.shiftKey){ this.cache.parent.previous(); } } } ); this.Input.onFocus(()=>{ if(this.cache.parent instanceof ZikoUICodeNote){ this.cache.parent.cache.currentNote=this; this.cache.parent.setCurrentNote(this); } }); this.Input.onPaste((e)=>{ //e.event.preventDefault(); //this.setValue(this.codeText.trim()) }); // this.Input.onKeyPress(e=>{ // if(e.kp==="(")a.Input.element.textContent+=")"; // if(e.kp==="[")a.Input.element.textContent+="]"; // if(e.kp==="{")a.Input.element.textContent+="}"; // }) } } get isCodeCell(){ return true; } // space &nbsp get codeText() { return (this.Input.element.getElementsByClassName("cm-content")[0]) ?this.Input.element.getElementsByClassName("cm-content")[0].innerText.trim() :this.Input.element.innerText.trim() // return this.Input.element.innerText.trim(); } get codeHTML() { return this.Input.element.innerHTML; } get outputHTML(){ return this.Output.element.innerHTML; } setValue(codeText){ this.Input[0].setValue(codeText); return this; } cellData(){ return { input:this.codeText, output:this.outputHTML, order:this.cache.order, type:this.cache.type } } execute(order){ this.clearOutput(); this.evaluate(order); this.cache.metadata.updated=Date.now(); return this; } #evaluateJs(order){ try{ this.LeftControl[0].setValue("pending"); this.cache.state="pending"; // globalThis.eval(this.Input.element.innerText); globalThis.eval(this.codeText); } catch(err){ console.log(err); text(`Error : ${err.message}`).style({ color:"red", background:"gold", border:"2px red solid", padding:"10px", margin:"10px 0", display:"flex", justifyContent: "center", }); this.LeftControl[0].setValue("Err"); this.cache.state="Error"; } finally{ if(this.cache.state==="pending"){ this.cache.state="success"; this.setOrder(order); if(this.cache.parent instanceof ZikoUICodeNote){ this.cache.parent.incrementOrder(); this.cache.parent.next(); } } } } #evaluateMd(){ } #evaluateHtml(){ } evaluate(order){ globalThis.__Ziko__.__Config__.default.target=this.Output.element; switch(this.cache.type){ case "js":this.#evaluateJs(order);break; } return this; } clearInput(){ this.Output.element.innerText=""; return this; } clearOutput(){ this.Output.element.innerText=""; return this; } setOrder(order,render=true){ this.cache.order=order; if(render){ (typeof order === "number")?this.LeftControl[0].setValue(`[${order}]`):this.LeftControl[0].setValue("[-]"); } return this; } focus(){ this.Input.element.focus(); return this; } } const CodeCell=(codeText,{type,order}={})=>new ZikoUICodeCell(codeText,{type,order}); // Next // Previous // Vertical // Horizontal class ZikoUITabs extends ZikoUIFlex{ #ACTIVE_ELEMENT_INDEX=0; constructor(Controllers,Contents){ super("div","Tabs"); Object.assign(this.cache,{ config:{ controllersPercent : .50 } }); this.style({ boxSizing:"border-box", backgroundColor: "blanchedalmond", border:"1px red solid", margin:"30px", }); this.controllersContainer = Flex().size("auto","auto").style({ boxSizing:"border-box", justifyContent:"center", alignItems:"center", textAlign:"center", minWidth:"50px", minHeight:"50px", backgroundColor:"darkblue", border:"1px darkblue solid", }).setAttr("role","tablist"); this.contentContainer = Flex().style({ boxSizing:"border-box", justifyContent:"center", alignItems:"center", textAlign:"center", width:"100%", height:"100%", backgroundColor:"darkslategrey", }); this.append( this.controllersContainer, this.contentContainer ); if(Controllers.length!==Contents.length)console.error(""); else { this.controllersContainer.append(...Controllers); this.contentContainer.append(...Contents); } this.init(); this.display(0); this.useVertical(); } get isTabs(){ return true; } init(){ // Remove old listener for(let i=0;i<this.controllersContainer.length;i++){ this.controllersContainer[i].setAttr("role","tab").setAttr("aria-controls",`tab${i}`); this.contentContainer[i].setAttr("role","tabpanel").setAttr("aria-labelledby",`tab${i}`).setAttr("tabindex",-1); } this.controllersContainer.forEach(item=>item.onClick(e=>{ const tab=e.target.element.getAttribute("aria-controls"); const index=+tab.slice(3); this.contentContainer.filter(n=>n.element.getAttribute("aria-labelledby")===tab,()=>{ if(this.#ACTIVE_ELEMENT_INDEX!==index)this.display(index); }); })); return this; } addPairs(ControllerItem,ContentItem){ this.controllersContainer.append(ControllerItem); this.contentContainer.append(ContentItem); const length=this.controllersContainer.length; this.controllersContainer.at(-1).setAttr("role","tab").setAttr("aria-controls",`tab${length-1}`); this.contentContainer.at(-1).setAttr("role","tabpanel").setAttr("aria-labelledby",`tab${length-1}`).setAttr("tabindex",-1); // Add listener return this; } removePairs(index){ } display(index){ this.#ACTIVE_ELEMENT_INDEX=index%this.contentContainer.length; const ActiveContent = this.contentContainer.at(this.#ACTIVE_ELEMENT_INDEX); this.controllersContainer.forEach(n=>n.setAttr("tabindex",-1).setAttr("aria-selected",false)); this.controllersContainer.at(this.#ACTIVE_ELEMENT_INDEX).setAttr("tabindex",0).setAttr("aria-selected",true); this.contentContainer.forEach(n=>n.st.hide()); ActiveContent.st.translateX(100,0); ActiveContent.setAttr("tabindex",0).st.show(); ActiveContent.st.translateX(0,1000); return this; } next(i=1){ this.display(this.#ACTIVE_ELEMENT_INDEX+i); return this; } previous(i=1){ this.display(this.#ACTIVE_ELEMENT_INDEX-i); return this; } useVertical(){ this.vertical(0,0); this.controllersContainer.horizontal(0,0); this.controllersContainer.style({ width : "100%", height : `${this.cache.config.controllersPercent*100}%` }); this.contentContainer.style({ width : "100%", height : `${(1-this.cache.config.controllersPercent)*100}%` }); return this; } useHorizontal(){ this.horizontal(0,0); this.controllersContainer.vertical(0, 0); this.controllersContainer.style({ height : "100%", width : `${this.cache.config.controllersPercent*100}%` }); this.contentContainer.style({ height : "100%", width : `${(1-this.cache.config.controllersPercent)*100}%` }); return this; } // useHorizontalSwippe(){ // this.onPtrDown(); // this.onPtrUp(e=>this.next(Math.sign(e.swippe.delta_x))); // return this; // } // useVerticalSwippe(){ // this.onPtrDown(); // this.onPtrUp(e=>this.next(Math.sign(e.swippe.delta_y))); // return this; // } } const Tabs=(Controllers,Contents)=>new ZikoUITabs(Controllers,Contents); /* const cont=(txt = "A")=>btn(txt).style({width:"170px"}) a=Tabs( [cont("A1"),cont("A2"),cont("A3"),cont("A4")], [cont("A1"),cont("A2"),cont("A3"),cont("A4")] ).vertical().size("400px") a.controllersContainer.style({ overflowX:"auto" }) a.useHorizontal() */ /* a=Flex().size("400px","400px").style({background:"red"}) a.element.animate([ { borderRadius: "0" , background : "red" }, { borderRadius: "50% 0" }, { borderRadius: "50% 50%" }, { borderRadius: "0 50%" }, { borderRadius: "0", background : "yellow" }, ], { // temporisation duration: 2000, iterations: Infinity, }) */ class ZikoUIAlert extends ZikoUIFlex{ constructor(type, title, content){ super(); this.title = h3(title); this.icon = text$1(palette[type].icon).style({ display: "flex", justifyContent:"center", borderRadius:"50%", minWidth:"30px", minHeight:"30px", }); this.content = content; this.vertical() .size("200px", "auto") .style({ borderRadius:"10px", padding:"10px" }); this.append( Flex( this.title, this.icon ).size("100%", "40px").style({}).horizontal("space-between",0), this.content ); this.useType(type); } get isAlert(){ return true; } useType(type){ this.style({ color:palette[type].color, background:palette[type].bgColor, border: `1px darkblue solid`, borderLeft: `15px ${palette[type].borderColor} solid`, }); this.title.style({ color:palette[type].titleColor }); this.content.st.color(palette[type].titleColor); this.icon.setValue(palette[type].icon).style({ border:`2px ${palette[type].borderColor} solid`, alignItems: type==="warning"?"flex-start":"center", }); return this; } useSuccess(){ this.useType("success"); return this; } useInfo(){ this.useType("info"); return this; } useWarning(){ this.useType("warning"); return this; } useDanger(){ this.useType("danger"); return this; } } const successAlert=(title, content)=>new ZikoUIAlert("success", title, content); const infoAlert=(title, content)=>new ZikoUIAlert("info", title, content); const warningAlert=(title, content)=>new ZikoUIAlert("warning", title, content); const dangerAlert=(title, content)=>new ZikoUIAlert("danger", title, content); class __ZikoUISplitter__ extends ZikoUIElement{ constructor(flexDirection, resizerCursor, resizerProp){ super("div", "Splitter"); Object.assign(this.cache,{ isResizing : false, flexDirection, resizerCursor, resizerProp }); this.style({ display:"flex", flexDirection : this.cache.flexDirection, border: "2px solid #333", overflow: "hidden" }); this.resizer = new ZikoUIElement("div", "resizer").style({ [this.cache.resizerProp]:"5px", backgroundColor: "gold", cursor: this.cache.resizerCursor, touchAction: "none", }); this.onPtrDown(e=>{ this.cache.isResizing = true; this.style({ cursor : this.cache.resizerCursor // ns-resize }); this.resizer.element.setPointerCapture(e.event.pointerId); }); this.onPtrUp(e=>{ this.cache.isResizing = false; this.style({ cursor: "default" }); this.resizer.element.releasePointerCapture(e.event.pointerId); }); this.onPtrCancel(()=>{ this.cache.isResizing = false; this.style({ cursor: "default" }); }); this.onPtrOut(()=>{ if (this.cache.isResizing) { this.cache.isResizing = false; this.style({ cursor: "default" }); } }); } get isSplitter(){ return true; } styleResizer(style={}){ this.resizer.style(style); return this; } } class ZikoUIHorizontalSplitter extends __ZikoUISplitter__{ constructor(leftPane, rightPane){ super("row", "ew-resize", "width"); this.leftPane = leftPane.style({ width:"50%", flexGrow: 1, overflow: "hidden" }); this.rightPane = rightPane.style({ width:"50%", flexGrow: 1, overflow: "hidden" }); this.element?.append( this.leftPane.element, this.resizer.element, this.rightPane.element ); this.onPtrMove(e=>{ if (!this.cache.isResizing) return; const containerWidth = this.element.getBoundingClientRect().width; // height const pointerRelativeXpos = e.event.clientX - this.element.getBoundingClientRect().x; // y let newLeftPaneWidth = (pointerRelativeXpos / containerWidth) * 100; let newRightPaneWidth = 100 - newLeftPaneWidth; if (newLeftPaneWidth < 0) newLeftPaneWidth = 0; if (newRightPaneWidth < 0) newRightPaneWidth = 0; this.leftPane.element.style.width = `${newLeftPaneWidth}%`; this.rightPane.element.style.width = `${newRightPaneWidth}%`; }); } get isHorizontalSplitter(){ return true; } } const hSplitter=(leftPane, rightPane)=>new ZikoUIHorizontalSplitter(leftPane, rightPane); class ZikoUIVerticalSplitter extends __ZikoUISplitter__{ constructor(topPane, bottomPane){ super("column", "ns-resize", "height"); this.topPane = topPane.style({ height:"50%", flexGrow: 1, overflow: "hidden" }); this.bottomPane = bottomPane.style({ height:"50%", flexGrow: 1, overflow: "hidden" }); this.element?.append( this.topPane.element, this.resizer.element, this.bottomPane.element ); this.onPtrMove(e=>{ if (!this.cache.isResizing) return; const containerHeight = this.element.getBoundingClientRect().height; // height const pointerRelativeYpos = e.event.clientY - this.element.getBoundingClientRect().y; // y let newTopPaneHeight = (pointerRelativeYpos / containerHeight) * 100; let newBottomPaneHeight = 100 - newTopPaneHeight; if (newTopPaneHeight < 0) newTopPaneHeight = 0; if (newBottomPaneHeight < 0) newBottomPaneHeight = 0; this.topPane.element.style.height = `${newTopPaneHeight}%`; this.bottomPane.element.style.height = `${newBottomPaneHeight}%`; }); } get isHorizontalSplitter(){ return true; } } const vSplitter=(topPane, bottomPane)=>new ZikoUIVerticalSplitter(topPane, bottomPane); const Splitter = ({orintation = "horizontal",slides = []}) =>{ if(["v","vertical"].includes(orintation.toLowerCase())) return vSplitter(...slides); else if(["h","horizontal"].includes(orintation.toLowerCase())) return hSplitter(...slides); else ; }; class ZikoUIBreadcrumbs extends ZikoUIElement{ constructor(...items){ super("ul", "Breadcrumbs"); Object.assign(this.cache,{ separatorTextContent:"/" }); this.style({ listStyle: "none", display: "flex", flexWrap: "wrap" }); this.list=html('li').style({ display: "flex", flexWrap: "wrap" }); this.append(...items); } #addItem(item){ if(["string","number","boolean"].includes(typeof item))item = text$1(item); const li = html("li", item).style({ display: "flex", alignItems: "center" }); if(this.element.children.length>0){ const separator = text$1(this.cache.separatorTextContent).style({ padding: "0 4px" }); this.element?.append(separator.element); } this.element?.append(li.element); } append(...items){ items.forEach(n=>this.#addItem(n)); return this; } configSeparator(separatorTextContent = this.cache.separator, style = {}){ this.cache.separatorTextContent = separatorTextContent; const separators = [...this.element.children].filter(n=>n.tagName==="SPAN"); separators.forEach(node=>{ node.textContent = separatorTextContent; Object.assign(node.style, style); } ); return this; } } const Breadcrumbs=(...items)=>new ZikoUIBreadcrumbs(...items); class ZikoUIMenu3d extends ZikoUIFlex{ constructor(controller, content){ super("div", "menu3d"); this.controller = controller; this.content = content; this.cover = null; Object.assign(this.cache,{ config:{ useTransfo : false, isOpen : false, position : "left", threshold : 40, angle : 70, overlap : 6, width : 300, height : 300, transitionDuration: '0.5s', transitionEasing: 'ease', menuTransformOrigin : null, menuTransformClosed : null, menuTransformOpened : null, contentTransformOrigin : null, contentTransformClosed : null, contentTransformOpened : null, } }); this.append( this.controller, this.content ); this.update(); } get isOpen(){ return this.cache.config.isOpen; } update(){ this.controller.style({ display:"none", padding:"20px", overflow:"auto", background:"darkblue", color: "#eee", webkitboxSizing: "border-box", mozBoxSizing: "border-box", boxSizing:"border-box", }); this.content.style({ padding:"20px 40px", width: "100%", height: "100%", // overflowY:"auto", background:"gold", color: "#eee", webkitboxSizing: "border-box", mozBoxSizing: "border-box", boxSizing:"border-box", webkitOverflowScrolling:"touch", webkitTransformStyle: "preserve-3d" }); this.setupPositions(); this.setupWrapper(); this.setupCover(); this.setupMenu(); this.setupContent(); } setupPositions() { this.cache.config.menuTransformOpened = ''; this.cache.config.contentTransformClosed = ''; let menuAngle = this.cache.config.angle; let contentAngle = this.cache.config.angle / -2; switch( this.cache.config.position ) { case "top": this.cache.config.menuTransformOrigin = '50% 0%'; this.cache.config.menuTransformClosed = `rotateX(${menuAngle}deg) translateY(-100%) translateY(${this.cache.config.overlap}px)`; this.cache.config.contentTransformOrigin = '50% 0'; this.cache.config.contentTransformOpened = `translateY(${this.height/2}px) rotateX(${contentAngle}deg)`; break; case "right": this.cache.config.menuTransformOrigin = '100% 50%'; this.cache.config.menuTransformClosed = 'rotateY( ' + menuAngle + 'deg ) translateX( 100% ) translateX( -2px ) scale( 1.01 )'; this.cache.config.contentTransformOrigin = '100% 50%'; this.cache.config.contentTransformOpened = 'translateX( -'+ this.width/2 +'px ) rotateY( ' + contentAngle + 'deg )'; break; case "bottom": this.cache.config.menuTransformOrigin = '50% 100%'; this.cache.config.menuTransformClosed = 'rotateX( ' + -menuAngle + 'deg ) translateY( 100% ) translateY( -'+ this.cache.config.overlap +'px )'; this.cache.config.contentTransformOrigin = '50% 100%'; this.cache.config.contentTransformOpened = 'translateY( -'+ this.height/2 +'px ) rotateX( ' + -contentAngle + 'deg )'; break; default: this.cache.config.menuTransformOrigin = '100% 50%'; this.cache.config.menuTransformClosed = 'translateX( -100% ) translateX( '+ this.cache.config.overlap +'px ) scale( 1.01 ) rotateY( ' + -menuAngle + 'deg )'; this.cache.config.contentTransformOrigin = '0 50%'; this.cache.config.contentTransformOpened = 'translateX( '+ this.width/2 +'px ) rotateY( ' + -contentAngle + 'deg )'; break; } } setupWrapper() { this.style({ perspective : "800px", perspectiveOrigin : this.cache.config.contentTransformOrigin }); } setupCover(){ if( this.cover ) this.cover.element.parentNode.removeChild( this.cover.element ); this.cover=new ZikoUIElement("div","div").style({ position:"absolute", display:"block", width:"100%", height:"100%", left:0, top:0, zIndex:1000, visibility:"hidden", opacity:0, transition: `all ${this.cache.config.transitionDuration} ${this.cache.config.transitionEasing}` }); this.content.element.appendChild( this.cover.element ); } setupMenu() { // var style = dom.menu.style; switch( this.cache.config.position ) { case "top": this.controller.style({ width : "100%", height : `${this.height/2}px` });break; case "right": this.controller.style({ right : 0, width : `${this.width/2}px`, height : "100%" });break; case "bottom": this.controller.style({ bottom : "0", width : "100%", height : `${this.height/2}px` });break; case "left": this.controller.style({ width : `${this.width/2}px`, height : "100%" });break; } this.controller.style({ position : "fixed", display : "block", zIndex : 1, transform : this.cache.config.menuTransformClosed, transformOrigin : this.cache.config.menuTransformOrigin, transition : 'all ' + this.cache.config.transitionDuration +' '+ this.cache.config.transitionEasing }); } setupContent() { this.content.style({ transform : this.cache.config.contentTransformClosed, transformOrigin : this.cache.config.contentTransformOrigin, transition : `all ${this.cache.config.transitionDuration} ${this.cache.config.transitionEasing}` }); } open(){ if(!this.cache.config.isOpen){ this.cache.config.isOpen = true; this.cover.style({ height : this.content.element.scrollHeight + "px", visibility : "visible", opacity : 1, }); if(this.cache.config.useTransfo)this.content.style({ transform : this.cache.config.contentTransformOpened, userSelect : "default" }); this.controller.style({ transform : this.cache.config.menuTransformOpened, useSelect : "none" }); this.emit("opened"); } } close() { if( this.cache.config.isOpen ) { this.cache.config.isOpen = false; this.cover.style({ // height : this.content.element.scrollHeight + "px", visibility : "hidden", opacity : 0, }); this.content.style({ transform : this.cache.config.contentTransformClosed, useSelect : "default" }); this.controller.style({ transform : this.cache.config.menuTransformClosed, userSelect : "none" }); } this.emit("closed"); } onOpen(callback){ this.on("opened", callback.bind(this)); return this; } onClose(callback){ this.on("closed", callback.bind(this)); return this; } #usePosition(position){ if(this.cache.config.position!==position){ this.cache.config.position=position; const isOpen = this.isOpen; this.close(); this.update(); if(isOpen)this.open(); } } useRight(){ this.#usePosition("left"); return this; } useRight(){ this.#usePosition("right"); return this; } useTop(){ this.#usePosition("top"); return this; } useBottom(){ this.#usePosition("bottom"); return this; } } const menu3d = (controller, content) => new ZikoUIMenu3d(controller, content); globalThis.menu3d = menu3d; /* a = menu3d(Flex(text("Menu")), Flex(text("Content"))) .size("80vw", "50vh") .style({ userSelect: "none" }); a.onOpen((e) => console.log(e)); a.open(); a.controller.onSwipe(0.05, 1, (e) => { if (e.event.detail.direction.x === "left") a.close(); }); a.content.onSwipe(0.1, 1, (e) => { if (e.event.detail.direction.x === "left") a.close(); if (e.event.detail.direction.x === "right") a.open(); }); */ class ZikoUIModal extends ZikoUIContainerElement{ constructor(...UIElements){ super("dialog", "modal"); this.append(...UIElements); Object.assign(this.cache,{ config:{ mode:"modal", useTransition:true } }); this.style({ display:"flex", justifyContent:"center", alignItems:"center", position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", padding: "20px", border: "none", backgroundCcolor: "#f5f5f5", boxShadow: "0px 4px 10px rgba(0, 0, 0, 0.1)", borderRadius: "8px" }); this.close(); } open(){ if(!this.element.open){ switch(this.cache.config.mode){ case "modal": this.element.showModal(); break; case "dialog": this.element.show(); break; default : this.element.show(); break; } // this.style({ // display : "flex", // }) this.st.fadeIn(1000); this.emit("modal:opened"); } return this; } close(){ // this.style({ // display : "none" // }) this.st.fadeOut(1000); if(this.element.open){ this.element.close(); } this.emit("modal:closed"); return this; } closeAfter(t = 1000){ globalThis?.setTimeout(()=>this.close(), t); return this; } onOpen(callback){ this.on("modal:opened",callback.bind(this)); return this; } onClose(callback){ this.on("modal:closed",callback.bind(this)); return this; } useModal(){ this.cache.config.mode = "modal"; return this; } useDialog(){ this.cache.config.mode = "dialog"; return this; } useTransition(enabled = true){ this.cache.config.useTransition = enabled; return this; } } const Modal=(...UIElements)=>new ZikoUIModal(...UIElements); /* a=Modal(text("Hello")).style({ width:"100%", height:"100%" }) Flex(a).size("400px","400px").style({border:"1px red solid"}) */ class __ZikoUISlider__ extends ZikoUISection{ constructor(){ super("section",""); Object.assign(this.cache,{ currentIndex : 0, slideBuilder : null, }); this.container = Flex().size("100%","100%").vertical(0,0).style({ // width:"100%", overflow:"hidden" }); // this.style({ // // width:"100%", // overflow:"hidden" // }); this.container.setAttr({ ariaRoledescription : "carousel", ariaLive: "polite", ariaLabel : "Content Slider" }); this.track = Section().size("100%","100%").style({ transition : "transform 0.3s ease-in-out", }); this.bullets = Flex().style({ // position : "absolute", // top : 0, gap : "10px", padding:"10px", }); this.container.append( this.track, this.bullets ); this.append(this.container); } #updateAriaHidden(){ for(let i=0;i<this.track.items.length;i++){ this.track[i].setAttr({ ariaHidden : (i!==this.cache.currentIndex) }); } } goto(n = 0){ this.cache.currentIndex = n; this.__updatePos(); this.#updateAriaHidden(); } next(n = 1){ this.cache.currentIndex += n; this.__updatePos(); this.#updateAriaHidden(); return this; } previous(n = 1){ this.cache.currentIndex -= n; this.__updatePos(); this.#updateAriaHidden(); return this; } #update(){ const length = this.track.items.length; for(let i=0;i<length;i++){ this.track.items[i].setAttr({ ariaLabel : `Slide ${i+1} of ${length}`, dataSlideIndex : i }); this.bullets.items[i].setAttr({ dataIndex : i, ariaLabel : `Go to slide ${i}` }); this.bullets[i].events.click?.destroy(); this.bullets[i].onClick(()=>this.goto(i)); } } #addSlide(UIElement){ this.track.append(this.cache.slideBuilder(UIElement).setAttr({ ariaRoledescription : "slide", role : "group", ariaLabel : "" // link to update })); const bullet = text().size("15px","15px").style({ borderRadius:"50%", cursor : "pointer", border : "3px solid blue", background : "white" }).setAttr({ role : "button", tabIndex : 0 }) .onPtrEnter(e=>e.target.st.background("gold").scale(1.2,1.2)) .onPtrLeave(e=>e.target.st.background("white").scale(1,1)); this.bullets.append( bullet ); return this; } addSlides(...slides){ slides.forEach(n=>this.#addSlide(n)); this.#update(); this.#updateAriaHidden(); return this; } } class ZikoUIHorizontalSlider extends __ZikoUISlider__{ constructor(...slides){ super("section","hSlider"); this.container.vertical(0,0); Object.assign(this.cache,{ slideBuilder : (UIElement) => Flex(UIElement).style({ minWidth : "100%", width:"100%", height:"100%", }).vertical(0,0) }); this.track.size("100%","90%").style({ display : "flex" }); this.addSlides(...slides); this.bullets.horizontal(0,0).style({ width : "100%", height : "10%", }); } __updatePos(){ const width = this.container.width; this.track.st.translateX(-this.cache.currentIndex * width); } } const hSlider=(...slides)=>new ZikoUIHorizontalSlider(...slides); class ZikoUIVerticalSlider extends __ZikoUISlider__{ constructor(...slides){ super("section","vSlider"); Object.assign(this.cache,{ slideBuilder : (UIElement) => Flex(UIElement).size("100%","100%").vertical(0, 0) }); this.addSlides(...slides); this.container.horizontal(0,0); this.track.size("90%","100%"); this.bullets.vertical(0,0).style({ height : "100%", width : "10%" }); } __updatePos(){ const height = this.container.height; this.track.st.translateY(-this.cache.currentIndex * height); } } const vSlider=(...slides)=>new ZikoUIVerticalSlider(...slides); const Slider = ({orintation = "horizontal",slides = []}) =>{ if(["v","vertical"].includes(orintation.toLowerCase())) return vSlider(...slides); else if(["h","horizontal"].includes(orintation.toLowerCase())) return hSlider(...slides); else ; }; export { Accordion, Breadcrumbs, Carousel, CodeCell, CodeNote, Collapsible, Modal, Slider, Splitter, Tabs, ZikoUIAccordion, ZikoUIBreadcrumbs, ZikoUICodeNote, ZikoUIHorizontalSlider, ZikoUIHorizontalSplitter, ZikoUIMenu3d, ZikoUIModal, ZikoUIVerticalSlider, ZikoUIVerticalSplitter, dangerAlert, hSlider, hSplitter, infoAlert, menu3d, successAlert, vSlider, vSplitter, warningAlert };