ziko-ui
Version:
1,417 lines (1,360 loc) • 44.8 kB
JavaScript
/*
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  
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 };