ziko
Version:
A versatile JavaScript library offering a rich set of Hyperscript Based UI components, advanced mathematical utilities, interactivity ,animations, client side routing and more ...
1,601 lines (1,488 loc) • 185 kB
JavaScript
/*
Project: ziko.js
Author: Zakaria Elalaoui
Date : Sun Dec 07 2025 00:00:39 GMT+0100 (UTC+01:00)
Git-Repo : https://github.com/zakarialaoui10/ziko.js
Git-Wiki : https://github.com/zakarialaoui10/ziko.js/wiki
Released under MIT License
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Ziko = {}));
})(this, (function (exports) { 'use strict';
const { PI: PI$1, E } = Math;
const EPSILON=Number.EPSILON;
const is_primitive = value => typeof value !== 'object' && typeof value !== 'function' || value === null;
const mapfun=(fun,...X)=>{
const Y=X.map(x=>{
if(is_primitive(x) || x?.__mapfun__) return fun(x)
if(x instanceof Array) return x.map(n=>mapfun(fun,n));
if(ArrayBuffer.isView(x)) return x.map(n=>fun(n));
if(x instanceof Set) return new Set(mapfun(fun,...[...x]));
if(x instanceof Map) return new Map([...x].map(n=>[n[0],mapfun(fun,n[1])]));
if(x.isMatrix?.()) return new x.constructor(x.rows, x.cols, mapfun(x.arr.flat(1)))
else if(x instanceof Object){
return Object.fromEntries(
Object.entries(x).map(
n=>n=[n[0],mapfun(fun,n[1])]
)
)
}
});
return Y.length==1? Y[0]: Y;
};
// import {sum,prod,deg2rad} from "../utils/index.js";
// Should avoid CD
class Complex{
constructor(a = 0, b = 0) {
if(a instanceof Complex){
this.a=a.a;
this.b=a.b;
}
else if(typeof(a)==="object"){
if(("a" in a && "b" in a)){
this.a = a.a;
this.b = a.b;
}
else if(("a" in a && "z" in a)){
this.a = a.a;
this.b = Math.sqrt((a.z**2)-(a.a**2));
}
else if(("a" in a && "phi" in a)){
this.a = a.a;
this.b = a.a * Math.tan(a.phi);
}
else if(("b" in a && "z" in a)){
this.b = a.b;
this.a = Math.sqrt((a.z**2)-(a.b**2));
}
else if(("b" in a && "phi" in a)){
this.b = b;
this.a = a.b / Math.tan(a.phi);
}
else if(("z" in a && "phi" in a)){
this.a = + a.z * Math.cos(a.phi).toFixed(15);
this.b = + a.z * Math.sin(a.phi).toFixed(15);
}
}
else if(typeof(a)==="number" && typeof(b)==="number"){
this.a = + a.toFixed(32);
this.b = + b.toFixed(32);
}
}
get __mapfun__(){
return true
}
isComplex(){
return true
}
toString(){
let str = "";
if (this.a !== 0)
this.b >= 0
? (str = `${this.a}+${this.b}*i`)
: (str = `${this.a}-${Math.abs(this.b)}*i`);
else
this.b >= 0
? (str = `${this.b}*i`)
: (str = `-${Math.abs(this.b)}*i`);
return str;
}
clone() {
return new Complex(this.a, this.b);
}
get z(){
return Math.hypot(this.a,this.b);
}
get phi(){
return Math.atan2(this.b , this.a);
}
static Zero() {
return new Complex(0, 0);
}
get conj() {
return new Complex(this.a, -this.b);
}
get inv() {
return new Complex(
this.a / Math.hypot(this.a, this.b),
-this.b / Math.hypot(this.a, this.b)
);
}
add(...c) {
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
this.a += c[i].a;
this.b += c[i].b;
}
return this;
}
sub(...c) {
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
this.a -= c[i].a;
this.b -= c[i].b;
}
return this;
}
mul(...c){
let {z, phi} = this;
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
z *= c[i].z;
phi += c[i].z;
}
this.a = z*Math.cos(phi);
this.b = z*Math.sin(phi);
return this;
}
div(...c){
let {z, phi} = this;
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
z /= c[i].z;
phi -= c[i].z;
}
this.a = z*Math.cos(phi);
this.b = z*Math.sin(phi);
return this;
}
modulo(...c) {
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
this.a %= c[i].a;
this.b %= c[i].b;
}
return this;
}
static fromExpo(z, phi) {
return new Complex(
+(z * cos(phi)).toFixed(13),
+(z * sin(phi)).toFixed(13)
);
}
get expo() {
return [this.z, this.phi];
}
static add(c,...z) {
return c.clone().add(...z);
}
static sub(c,...z) {
return c.clone().sub(...z);
}
static mul(c,...z) {
return c.clone().mul(...z);
}
static div(c,...z) {
return c.clone().div(...z);
}
nthr(n=2){
return complex({z: this.z ** (1/n), phi: this.phi / n});
}
get sqrt(){
return this.nrth(2);
}
get cbrt(){
return this.nrth(3);
}
get log(){
return complex(this.z, this.phi);
}
get cos(){
return complex(
Math.cos(this.a) * Math.cosh(this.b),
Math.sin(this.a) * Math.sinh(this.b)
)
}
get sin(){
return complex(
Math.sin(this.a) * Math.cosh(this.b),
Math.cos(this.a) * Math.sinh(this.b)
)
}
get tan(){
const D=cos(this.a*2)+cosh(this.b*2);
return complex(
Math.sin(2 * this.a) / D,
Math.sinh(2 * this.b) / D
);
}
}
const complex=(a,b)=>{
if((a instanceof Array||ArrayBuffer.isView(a)) && (b instanceof Array||ArrayBuffer.isView(a)))return a.map((n,i)=>complex(a[i],b[i]));
if(a.isMatrix?.() && b.isMatrix?.()){
if((a.shape[0]!==b.shape[0])||(a.shape[1]!==b.shape[1]))return Error(0)
const arr=a.arr.map((n,i)=>complex(a.arr[i],b.arr[i]));
return new a.constructor(a.rows,a.cols,...arr)
}
return new Complex(a,b)
};
const deg2rad = (...deg) => mapfun(x => x * Math.PI / 180, ...deg);
const rad2deg = (...rad) => mapfun(x => x / Math.PI * 180, ...rad);
const abs = (...x) => mapfun(
x =>{
if(x.isComplex?.()) return x.z;
return Math.abs(x)
},
...x
);
const pow$1 = (...x) => {
const n = x.pop();
return mapfun(
x => {
if(x.isComplex?.()) {
if(n.isComplex?.()) return new x.constructor({
z: Math.exp(n.a * Math.log(x.z) - n.b * x.phi),
phi: n.b * Math.log(x.z) + n.a * x.phi
})
return new x.constructor({z: x.z ** n, phi: x.phi * n});
}
if(n.isComplex?.()) return new x.constructor({
z: Math.exp(n.a * Math.log(x)),
phi: n.b * Math.log(x)
})
return Math.pow(x, n)
},
...x
)
};
const sqrt$2 = (...x) => mapfun(
x=>{
if(x.isComplex?.())
return new x.constructor({z: x.z**(1/2), phi: x.phi/2});
if(x < 0) return complex(0, Math.sqrt(-x))
return Math.sqrt(x);
},
...x
);
const cbrt = (...x) => mapfun(
x=>{
if(x.isComplex?.())
return new x.constructor({z: x.z**(1/3), phi: x.phi/3})
return Math.cbrt(x);
},
...x
);
const nthr = (...x) => {
const n = x.pop();
if(typeof n !== 'number') throw Error('nthr expects a real number n');
return mapfun(
x => {
if(x.isComplex?.()) return new x.constructor({z: x.z ** (1/n), phi: x.phi / n});
if(x<0) return n%2===2 ? complex(0, (-x)**(1/n)) : -1 * (-x)**(1/n)
return x**(1/n)
},
...x
)
};
const croot = (...x) =>{
const c = x.pop();
if(!c.isComplex?.()) throw Error('croot expect Complex number as root')
return mapfun(
x => {
if(typeof x === 'number') x = new c.constructor(x, 0);
const {a : c_a, b : c_b} = c;
const {z, phi} = x;
const D = Math.hypot(c_a, c_b);
const A = Math.exp((Math.log(z)*c_a + phi*c_b)/D);
const B = (phi*c_a - Math.log(z)*c_b)/D;
return new c.constructor(
A * Math.cos(B),
A * Math.sin(B)
)
},
...x
)
};
const exp$1 = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.exp(x.a) * Math.cos(x.b),
Math.exp(x.a) * Math.sin(x.b)
);
return Math.exp(x)
}
,...x
);
const ln = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.log(x.z),
x.phi
);
return Math.log(x)
}
,...x
);
const sign = (...x) => mapfun(
x => {
if(x.isComplex?.()){
const {z, phi} = x;
if(z===0) return new x.constructor(0, 0);
return new x.constructor({z:1, phi})
}
return Math.sign(x)
}
,...x
);
const floor = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.floor(x.a),
Math.floor(x.b)
)
return Math.floor(x)
},
...x
);
const ceil = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.ceil(x.a),
Math.ceil(x.b)
)
return Math.ceil(x)
},
...x
);
const round = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.round(x.a),
Math.round(x.b)
)
return Math.round(x)
},
...x
);
const trunc = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.trunc(x.a),
Math.trunc(x.b)
)
return Math.trunc(x)
},
...x
);
const fract = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
x.a - Math.trunc(x.a),
x.b - Math.trunc(x.b)
)
return x - Math.trunc(x)
},
...x
);
const cos$3 = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.cos(x.a) * Math.cosh(x.b),
-Math.sin(x.a) * Math.sinh(x.b)
);
return Math.cos(x)
}
,...x
);
const sin$3 = (...x) => mapfun(
x =>{
if(x?.isComplex) return new x.constructor(
Math.sin(x.a) * Math.cosh(x.b),
Math.cos(x.a) * Math.sinh(x.b)
);
return Math.sin(x)
}
, ...x
);
const tan = (...x) => mapfun(
x =>{
if(x?.isComplex){
const D = Math.cos(2*x.a) + Math.cosh(2*x.b);
return new x.constructor(
Math.sin(2*x.a) / D,
Math.sinh(2*x.b) / D
);
}
return Math.tan(x)
},
...x
);
const sec = (...x) => mapfun(
x => {
if(x.isComplex?.()) ;
return 1 / Math.cos(x)
}
,...x
);
const acos$1 = (...x) => mapfun(
x =>{
if(x?.isComplex){
const { a, b } = x;
const Rp = Math.hypot(a + 1, b);
const Rm = Math.hypot(a - 1, b);
globalThis.Rp = Rp;
globalThis.Rm = Rm;
return new x.constructor(
Math.acos((Rp - Rm) / 2),
-Math.acosh((Rp + Rm) / 2),
)
}
return Math.acos(x)
},
...x
);
const asin = (...x) => mapfun(
x => {
if(x?.isComplex){
const { a, b } = x;
const Rp = Math.hypot(a + 1, b);
const Rm = Math.hypot(a - 1, b);
return new x.constructor(
Math.asin((Rp - Rm) / 2),
Math.acosh((Rp + Rm) / 2)
);
}
return Math.asin(x);
},
...x
);
const atan = (...x) => mapfun(
x => {
if(x?.isComplex){
const { a, b } = x;
return new x.constructor(
Math.atan((a*2/(1-a**2-b**2)))/2,
Math.log((a**2 + (1+b)**2)/(a**2 + (1-b)**2))/4
)
}
return Math.atan(x);
},
...x
);
const acot = (...x) => mapfun(
x => {
if(x?.isComplex){
const { a, b } = x;
return new x.constructor(
Math.atan(2*a/(a**2+(b-1)*(b+1)))/2,
Math.log((a**2 + (b-1)**2)/(a**2 + (b+1)**2))/4
)
}
return Math.PI/2 - Math.atan(x);
},
...x
);
const cosh$2 = (...x) => mapfun(
x =>{
if(x?.isComplex) return new x.constructor(
Math.cosh(x.a) * Math.cos(x.b),
Math.sinh(x.a) * Math.sin(x.b)
);
return Math.cosh(x)
},
...x
);
const sinh$1 = (...x) => mapfun(
x =>{
if(x?.isComplex) return new x.constructor(
Math.sinh(x.a) * Math.cos(x.b),
Math.cosh(x.a) * Math.sin(x.b)
);
return Math.sinh(x)
},
...x
);
const tanh = (...x) => mapfun(
x =>{
if(x?.isComplex){
const D = Math.cosh(2*a) + Math.cos(2*b);
return new x.constructor(
Math.sinh(2*a) / D,
Math.sin(2*b) / D
)
}
return Math.tanh(x)
},
...x
);
const coth = (...x) => mapfun(
x =>{
if(x?.isComplex){
const {a, b} = x;
const D = (Math.sinh(a)**2)*(Math.cos(b)**2) + (Math.cosh(a)**2)*(Math.sin(b)**2);
return new x.constructor(
Math.cosh(a) * Math.sinh(a) / D,
- Math.sin(b) * Math.cos(b) / D
)
}
return 1/Math.tanh(x)
},
...x
);
const acosh = (...x) => mapfun(
x =>{
if(x?.isComplex){
return ln(x.clone().add(sqrt$2(x.clone().mul(x.clone()).sub(1))))
}
return Math.acosh(x)
},
...x
);
const asinh = (...x) => mapfun(
x =>{
if(x?.isComplex){
return ln(x.clone().add(sqrt$2(x.clone().mul(x.clone()).add(1))))
}
return Math.asinh(x)
},
...x
);
const atanh = (...x) => mapfun(
x =>{
if(x?.isComplex);
return Math.atanh(x)
},
...x
);
const sig = (...x) => mapfun(
x =>{
if(x?.isComplex);
return 1/(1+Math.exp(-x))
},
...x
);
const _add = (x, y) =>{
if(typeof x === 'number'){
if(typeof y === 'number') return x + y;
if(y.isComplex?.()) {
return y.clone().add(x);
}
}
if(x.isComplex?.()){
if(typeof y === 'number' || y.isComplex?.()) return new x.clone().add(y);
}
};
const _sub = (x, y) =>{
if(typeof x === 'number'){
if(typeof y === 'number') return x - y;
if(y.isComplex?.()) return new y.constructor(x - y.a, y.b);
}
if(x.isComplex?.()){
if(typeof y === 'number' || y.isComplex?.()) return new x.clone().sub(y);
}
};
const _mul = (x, y) =>{
if(typeof x === 'number'){
if(typeof y === 'number') return x * y;
if(y.isComplex?.()) return y.clone().mul(x);
}
if(x.isComplex?.()){
if(typeof y === 'number' || y.isComplex?.()) return new x.clone().mul(y);
}
};
const _div = (x, y) =>{
if(typeof x === 'number'){
if(typeof y === 'number') return x / y;
if(y.isComplex?.()) return new y.constructor(x, 0).div(y)
}
if(x.isComplex?.()){
if(typeof y === 'number' || y.isComplex?.()) return new x.clone().mul(y);
}
};
const _modulo = (x, y) =>{
if(typeof x === 'number'){
if(typeof y === 'number') return x % y;
if(y.isComplex?.()) return new y.constructor(x, 0).modulo(y)
}
if(x.isComplex?.()){
if(typeof y === 'number' || y.isComplex?.()) return new x.clone().modulo(y);
}
};
const add=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = _add(res, b[i]);
return res;
};
const sub=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = _sub(res, b[i]);
return res;
};
const mul=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = _mul(res, b[i]);
return res;
};
const div=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = _div(res, b[i]);
return res;
};
const modulo=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = _modulo(res, b[i]);
return res;
};
const norm = (x, min, max) => {
if(x.isComplex?.()) return new x.constructor(
norm(x.a, min, max),
norm(x.b, min, max)
)
if(x.isMatrix?.()) return new x.constructor(
x.rows,
x.cols,
norm(x.arr.flat(1), min, max)
);
return min !== max ? (value - min) / (max - min) : 0;
};
const lerp = (x, min, max) => {
if(x.isComplex?.()) return new x.constructor(
lerp(x.a, min, max),
lerp(x.b, min, max)
)
if(x.isMatrix?.()) return new x.constructor(
x.rows,
x.cols,
lerp(x.arr.flat(1), min, max)
);
return (max - min) * value + min;
};
const map$1 = (x, min, max) => {
if(x.isComplex?.()) return new x.constructor(
map$1(x.a),
map$1(x.b)
)
if(x.isMatrix?.()) return new x.constructor(
x.rows,
x.cols,
map$1(x.arr.flat(1))
);
return lerp(norm(x, a, b), c, d);
};
const clamp = (x, min, max) => {
if(x.isComplex?.()) return new x.constructor(
clamp(x.a, min, max),
clamp(x.b, min, max)
)
if(x.isMatrix?.()) return new x.constructor(
x.rows,
x.cols,
clamp(x.arr.flat(1), min, max)
);
return Math.min(Math.max(c, min), max)
};
const hypot = (...x) => {
const c0 = x.find(a => a.isComplex?.());
if (c0) {
const W = x.map(n => n.isComplex?.() ? n : new c0.constructor(n, 0));
return Math.hypot(...W.map(c => c.z));
}
return Math.hypot(...x);
};
const atan2 = (x, y, rad = true) =>{
};
const preload=(url)=>{
const xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.send();
if (xhr.status === 200) {
return xhr.responseText;
} else {
throw new Error(`Failed to fetch data from ${url}. Status: ${xhr.status}`);
}
};
async function fetchdom(url='https://github.com/zakarialaoui10') {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const html = await response.text();
const dom = new DOMParser().parseFromString(html, 'text/html');
return dom.documentElement;
} catch (err) {
console.error('Failed to fetch DOM:', err);
throw err;
}
}
function fetchdomSync(url='https://github.com/zakarialaoui10') {
try {
const data = preload(url);
const dom = new DOMParser().parseFromString(data, 'text/html');
return dom.documentElement;
} catch (err) {
console.error('Failed to fetch DOM synchronously:', err);
throw err;
}
}
globalThis.fetchdom=fetchdom;
globalThis.fetchdomSync=fetchdomSync;
const csv2arr = (csv, delimiter = ",")=>csv.trim().trimEnd().split("\n").map(n=>n.split(delimiter));
const csv2matrix = (csv, delimiter = ",")=>new Matrix(csv2arr(csv,delimiter));
const csv2object = (csv, delimiter = ",") => {
const [header, ...rows] = csv2arr(csv,delimiter);
const result = rows.map(row => {
const obj = {};
header.forEach((key, index) => {
obj[key] = row[index];
});
return obj;
});
return result;
};
const csv2json = (csv, delimiter = ",") => JSON.stringify(csv2object(csv,delimiter));
const csv2sql=(csv, Table)=>{
const lines = csv.trim().trimEnd().split('\n').filter(n=>n);
const columns = lines[0].split(',');
let sqlQuery = `INSERT INTO ${Table} (${columns.join(', ')}) Values `;
let sqlValues = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(',');
sqlValues.push(`(${values})`);
}
return sqlQuery+sqlValues.join(",\n");
};
const _objects2arr=data=>data instanceof Array?[Object.keys(data[0]),...data.map(n=>Object.values(n))]:[Object.keys(data)];
const _objects2csv=(data,delimiter)=>_objects2arr(data).map(n=>n.join(delimiter)).join("\n");
const json2arr=json=>json instanceof Object?_objects2arr(json):_objects2arr(JSON.parse(json));
const json2csv=(json,delimiter=",")=>json instanceof Object?_objects2csv(json,delimiter):_objects2csv(JSON.parse(json),delimiter);
const json2csvFile=(json,delimiter)=>{
const str=json2csv(json,delimiter);
const blob=new Blob([str], { type: 'text/csv;charset=utf-8;' });
return {
str,
blob,
url:URL.createObjectURL(blob)
}
};
const _processObject=(obj, indent)=>{
const yml = [];
if (Array.isArray(obj)) {
obj.forEach(item => {
if (typeof item === 'object' && item !== null) {
yml.push(`${indent}-`);
const nestedLines = _processObject(item, `${indent} `);
yml.push(...nestedLines);
} else yml.push(`${indent}- ${item}`);
});
} else {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
if (typeof value === 'object' && value !== null) {
yml.push(`${indent}${key}:`);
const nestedLines = _processObject(value, `${indent} `);
yml.push(...nestedLines);
} else {
yml.push(`${indent}${key}: ${value}`);
}
}
}
}
return yml;
};
const _object2yml=(object,indent="")=>_processObject(object,indent).join('\n');
const json2yml=(json,indent)=>json instanceof Object?_object2yml(json,indent):_object2yml(JSON.parse(json),indent);
const json2ymlFile=(json,indent)=>{
const str=json2yml(json,indent);
const blob=new Blob([str], { type: 'text/yml;charset=utf-8;' });
return {
str,
blob,
url:URL.createObjectURL(blob)
}
};
const json2xml=(json, indent = 1)=>{
let xml = '';
for (const key in json) {
if (json.hasOwnProperty(key)) {
const value = json[key];
xml += '\n' + ' '.repeat(indent) + `<${key}>`;
(typeof value === 'object') ? xml += json2xml(value, indent + 2) : xml += `${value}`;
xml += `</${key}>`;
}
}
return xml.trim();
};
const json2xmlFile=(json,indent)=>{
const str=json2xml(json,indent);
const blob=new Blob([str], { type: 'text/xml;charset=utf-8;' });
return {
str,
blob,
url:URL.createObjectURL(blob)
}
};
class UINode {
constructor(node){
this.cache = {
node
};
}
isZikoUINode(){
return true
}
get node(){
return this.cache.node;
}
}
// globalThis.node = (node) => new UINode(node);
function parseQueryParams$1(queryString) {
const params = {};
queryString.replace(/[A-Z0-9]+?=([\w|:|\/\.]*)/gi, (match) => {
const [key, value] = match.split('=');
params[key] = value;
});
return params;
}
function defineParamsGetter$1(target ){
Object.defineProperties(target, {
'QueryParams': {
get: function() {
return parseQueryParams$1(globalThis.location.search.substring(1));
},
configurable: false,
enumerable: true
},
'HashParams': {
get: function() {
const hash = globalThis.location.hash.substring(1);
return hash.split("#");
},
configurable: false,
enumerable: true
}
});
}
class UIStore extends Array {
constructor(...args) {
super(...args);
}
clear(){
this.length = 0;
return this;
}
getItemById(id) {
return this.find(n => n.element.id === id);
}
getItemsByTagName(tag) {
return this.filter(n => n.element.tagName.toLowerCase() === tag.toLowerCase());
}
getElementsByClassName(className) {
return this.filter(n => n.element.classList?.contains(className));
}
querySelector(selector) {
const el = globalThis?.document?.querySelector(selector);
if (!el) return null;
return this.find(ui => ui.element === el) || null;
}
querySelectorAll(selector) {
const els = globalThis?.document?.querySelectorAll(selector);
return Array.from(els)
.map(el => this.find(ui => ui.element === el))
.filter(Boolean);
}
}
// create the singleton
const __UI__ = new UIStore();
const __Config__ = {
default:{
target:null,
render:true,
math:{
mode:"deg"
}
},
setDefault:function(pairs){
const keys=Object.keys(pairs);
const values=Object.values(pairs);
for(let i=0; i<keys.length; i++) this.default[keys[i]]=values[i];
},
init:()=>{
// document.documentElement.setAttribute("data-engine","zikojs")
},
renderingMode :"spa",
isSSC : false,
};
const __HYDRATION__ = {
store : new Map(),
index : 0,
register: function(component){
this.store.set(this.index++ , component);
},
reset(){
this.index = 0;
this.store.clear();
}
};
const __CACHE__ = {
ui_index : 0,
get_ui_index:function(){
return this.ui_index ++
},
register_ui: function(UIElement){
}
};
class UseIPC {
#channel;
#eventData;
#handlers;
#uuid;
#subscribers;
#currentRooms;
constructor(name = "") {
this.#channel = new BroadcastChannel(name);
this.#eventData = new Map();
this.#handlers = new Map(); // Map<event, Array<{fn, rooms}>>
this.#uuid = "ziko-channel:" + (Math.random()*10e16); // To Be Replaced by UUID
this.#subscribers = new Set([this.#uuid]);
this.#currentRooms = new Set();
this.#channel.addEventListener("message", (e) => {
const { last_sent_event, userId, eventData, rooms } = e.data;
if (userId === this.#uuid) return; // ignore own messages
// broadcast if no rooms, else check intersection
if (rooms && rooms.length && !rooms.some(r => this.#currentRooms.has(r))) return;
this.#subscribers.add(userId);
this.#eventData = new Map(eventData);
const handlersList = this.#handlers.get(last_sent_event);
if (!handlersList) return;
handlersList.forEach(({ fn, rooms: handlerRooms }) => {
// trigger if listener has no room filter, or intersects subscriber rooms
if (!handlerRooms || handlerRooms.length === 0 ||
!rooms || rooms.some(r => handlerRooms.includes(r))) {
fn(this.#eventData.get(last_sent_event));
}
});
});
}
emit(event, data, rooms) {
this.#eventData.set(event, data);
if(typeof rooms === 'string') rooms = [rooms];
this.#channel.postMessage({
eventData: Array.from(this.#eventData.entries()),
last_sent_event: event,
userId: this.#uuid,
rooms: rooms && rooms.length ? rooms : undefined
});
return this;
}
on(event, handler = console.log, rooms) {
if (!this.#handlers.has(event)) this.#handlers.set(event, []);
if(typeof rooms === 'string') rooms = [rooms];
this.#handlers.get(event).push({ fn: handler, rooms });
return this;
}
off(event, handler) {
if (!this.#handlers.has(event)) return this;
this.#handlers.set(
event,
this.#handlers.get(event).filter(h => h.fn !== handler)
);
return this;
}
once(event, handler, rooms) {
const wrapper = (data) => {
handler(data);
this.off(event, wrapper);
};
this.on(event, wrapper, rooms);
return this;
}
join(...rooms) {
rooms.forEach(r => this.#currentRooms.add(r));
return this;
}
leave(...rooms) {
if (!rooms.length) this.#currentRooms.clear();
else rooms.forEach(r => this.#currentRooms.delete(r));
return this;
}
close() {
this.#channel.close();
return this;
}
}
const useIPC = (name) => new UseIPC(name);
class UseStorage {
constructor(storage, globalKey, initialValue, use_channel = true) {
this.cache = {
storage,
globalKey,
channel: use_channel ? useIPC(`Ziko:useStorage-${globalKey}`) : null,
oldItemKeys: new Set()
};
this.#init(initialValue, use_channel);
}
get items() {
const raw = this.cache.storage.getItem(this.cache.globalKey);
if (!raw) return {};
try {
return JSON.parse(raw);
} catch {
return {};
}
}
#maintain() {
const items = this.items;
this.cache.oldItemKeys.forEach(k => delete this[k]);
for (const key in items) {
this[key] = items[key];
this.cache.oldItemKeys.add(key);
}
}
#init(initialValue, use_channel) {
if (use_channel && this.cache.channel) this.cache.channel.on("Ziko-Storage-Updated", () => this.#maintain());
if (!initialValue) {
this.#maintain();
return;
}
if (this.cache.storage.getItem(this.cache.globalKey)) {
const existing = this.items;
Object.keys(existing).forEach(k => this.cache.oldItemKeys.add(k));
this.#maintain();
}
else this.set(initialValue);
}
set(data) {
this.cache.storage.setItem(this.cache.globalKey, JSON.stringify(data));
if (this.cache.channel) this.cache.channel.emit("Ziko-Storage-Updated", data);
this.#maintain();
return this;
}
add(data) {
this.set({
...this.items,
...data
});
return this;
}
remove(...keys) {
const items = { ...this.items };
keys.forEach(key => {
delete items[key];
delete this[key];
this.cache.oldItemKeys.delete(key);
});
this.set(items);
return this;
}
get(key) {
return this.items[key];
}
clear() {
this.cache.storage.removeItem(this.cache.globalKey);
this.cache.oldItemKeys.forEach(k => delete this[k]);
this.cache.oldItemKeys.clear();
this.#maintain();
return this;
}
onStorageUpdated(callback) {
if (this.cache.channel) {
this.cache.channel.on("Ziko-Storage-Updated", callback);
}
return this;
}
}
// factory functions
const useLocaleStorage = (key, initialValue, use_channel = true) =>
new UseStorage(localStorage, key, initialValue, use_channel);
const useSessionStorage = (key, initialValue, use_channel = true) =>
new UseStorage(sessionStorage, key, initialValue, use_channel);
var __State__ = {
store : new Map(),
index : 0,
session_storage : null,
register: function(state){
if(!undefined.SSR && undefined.DEV){
if(!this.session) this.session_storage = useSessionStorage('ziko-state', {});
const savedValue = this.session_storage.get(this.index);
if(!savedValue) this.session_storage.add({[this.index] : state.value});
else state.value = savedValue;
}
this.store.set(this.index++, state);
},
update: function(index, value){
if(!undefined.SSR && undefined.DEV){
this.session_storage.add({[index] : value});
}
},
};
function __init__global__(){
if ( !globalThis?.__Ziko__ ){
globalThis.__Ziko__ = {
__UI__,
__HYDRATION__,
__State__,
__Config__,
__CACHE__,
};
defineParamsGetter$1(__Ziko__);
}
}
__init__global__();
class UIElementCore extends UINode{
constructor(){
super();
}
init(element, name, type, render){
this.target = globalThis.__Ziko__.__Config__.default.target||globalThis?.document?.body;
if(typeof element === "string") {
switch(type){
case "html" : {
element = globalThis?.document?.createElement(element);
// console.log('1')
} break;
case "svg" : {
element = globalThis?.document?.createElementNS("http://www.w3.org/2000/svg", element);
// console.log('2')
} break;
default : throw Error("Not supported")
}
}
else this.target = element?.parentElement;
Object.assign(this.cache, {
name,
isInteractive : false,
parent:null,
isBody:false,
isRoot:false,
isHidden: false,
isFrozzen:false,
legacyParent : null,
attributes: {},
filters: {},
temp:{}
});
this.events = {
ptr:null,
mouse:null,
wheel:null,
key:null,
drag:null,
drop:null,
click:null,
clipboard:null,
focus:null,
swipe:null,
custom:null,
};
this.observer={
resize:null,
intersection:null
};
if(element) Object.assign(this.cache,{element});
// useDefaultStyle && this.style({
// position: "relative",
// boxSizing:"border-box",
// margin:0,
// padding:0,
// width : "auto",
// height : "auto"
// });
this.items = new UIStore();
globalThis.__Ziko__.__UI__[this.cache.name]?globalThis.__Ziko__.__UI__[this.cache.name]?.push(this):globalThis.__Ziko__.__UI__[this.cache.name]=[this];
element && render && this?.render?.();
globalThis.__Ziko__.__UI__.push(this);
}
get element(){
return this.cache.element;
}
[Symbol.iterator]() {
return this.items[Symbol.iterator]();
}
maintain() {
for (let i = 0; i < this.items.length; i++) {
Object.defineProperty(this, i, {
value: this.items[i],
writable: true,
configurable: true,
enumerable: false
});
}
}
isInteractive(){
return this.cache.isInteractive;
}
isUIElement(){
return true;
}
}
function register_to_class(target, ...mixins){
mixins.forEach(n => _register_to_class_(target, n));
}
function _register_to_class_(target, mixin) {
const descriptors = Object.getOwnPropertyDescriptors(mixin);
for (const key of Reflect.ownKeys(descriptors)) {
const desc = descriptors[key];
if ('get' in desc || 'set' in desc || typeof desc.value !== 'function') {
Object.defineProperty(Object.getPrototypeOf(target), key, desc);
} else if (typeof desc.value === 'function') {
if (!Object.getPrototypeOf(target).hasOwnProperty(key)) {
Object.defineProperty(Object.getPrototypeOf(target), key, desc);
}
}
}
}
// export function mount(target = this.target) {
// if(this.isBody) return ;
// if(target?.isUIElement)target=target.element;
// this.target=target;
// this.target?.appendChild(this.element);
// return this;
// }
// export function unmount(){
// if(this.cache.parent)this.cache.parent.remove(this);
// else if(this.target?.children?.length && [...this.target?.children].includes(this.element)) this.target.removeChild(this.element);
// return this;
// }
// export function mountAfter(target = this.target, t = 1) {
// setTimeout(() => this.mount(), t);
// return this;
// }
// export function unmountAfter(t = 1) {
// setTimeout(() => this.unmount(), t);
// return this;
// }
function mount(target = this.target, delay = 0) {
if (delay > 0) {
setTimeout(() => this.mount(target, 0), delay);
return this;
}
if (this.isBody) return this;
if (target?.isUIElement) target = target.element;
this.target = target;
this.target?.appendChild(this.element);
return this;
}
function unmount(delay = 0) {
if (delay > 0) {
setTimeout(() => this.unmount(0), delay);
return this;
}
if (this.cache.parent) {
this.cache.parent.remove(this);
} else if (
this.target?.children?.length &&
[...this.target.children].includes(this.element)
) {
this.target.removeChild(this.element);
}
return this;
}
var LifecycleMethods = /*#__PURE__*/Object.freeze({
__proto__: null,
mount: mount,
unmount: unmount
});
if(!globalThis.__Ziko__) __init__global__();
function useState(initialValue) {
const {store, index} = __Ziko__.__State__;
__Ziko__.__State__.register({
value : initialValue,
subscribers : new Set(),
paused : false
});
let current = store.get(index);
function getValue() {
return {
value: current.value,
isStateGetter: () => true,
_subscribe: (fn) => current.subscribers.add(fn),
};
}
function setValue(newValue) {
if (current.paused) return;
if (typeof newValue === "function") {
newValue = newValue(current.value);
}
if (newValue !== current.value) {
current.value = newValue;
current.subscribers.forEach(fn => fn(current.value));
__Ziko__.__State__.update(index, newValue);
}
}
const controller = {
pause: () => { current.paused = true; },
resume: () => { current.paused = false; },
clear: () => { current.subscribers.clear(); },
force: (newValue) => {
if (typeof newValue === "function") newValue = newValue(current.value);
current.value = newValue;
current.subscribers.forEach(fn => fn(current.value));
},
getSubscribers: () => new Set(current.subscribers),
};
return [getValue, setValue, controller];
}
const isStateGetter = (arg) => {
return typeof arg === 'function' && arg?.()?.isStateGetter?.();
};
const camel2hyphencase$1 = (text = '') => text.replace(/[A-Z]/g, match => '-' + match.toLowerCase());
const is_camelcase$1 = (text = '') =>{
if (text.length === 0) return false;
const camelCasePattern = /^[a-z][a-zA-Z0-9]*$/;
return camelCasePattern.test(text);
};
class ZikoUIText extends UINode {
constructor(...value) {
super("span", "text", false, ...value);
this.element = globalThis?.document?.createTextNode(...value);
}
isText(){
return true
}
}
const text = (...str) => new ZikoUIText(...str);
async function __addItem__(adder, pusher, ...ele) {
if (this.cache.isFrozzen) {
console.warn("You can't append new item to frozzen element");
return this;
}
for (let i = 0; i < ele.length; i++) {
if (["number", "string"].includes(typeof ele[i])) ele[i] = text(ele[i]);
// Fix Items Latter
if (ele[i] instanceof Function) {
const getter = ele[i]();
if (getter.isStateGetter) {
ele[i] = text(getter.value);
getter._subscribe(
(newValue) => (ele[i].element.textContent = newValue),
ele[i]
);
// this.element.appendChild(textNode);
}
}
if (typeof globalThis?.Node === "function" && ele[i] instanceof globalThis?.Node) ele[i] = new this.constructor(ele[i]);
if (ele[i]?.isZikoUINode) {
ele[i].cache.parent = this;
this.element?.[adder](ele[i].element);
ele[i].target = this.element;
this.items[pusher](ele[i]);
}
else if(ele[i] instanceof Promise){
const UIEle = await ele[i];
UIEle.cache.parent = this;
this.element?.[adder](UIEle.element);
UIEle.target = this.element;
this.items[pusher](UIEle);
}
else if (ele[i] instanceof Object) {
if (ele[i]?.style) this.style(ele[i]?.style);
if (ele[i]?.attr) {
Object.entries(ele[i].attr).forEach((n) =>
this.setAttr("" + n[0], n[1]),
);
}
}
}
this.maintain();
return this;
}
function _set_attrs_(name, value){
if(globalThis.SVGAElement && this.element instanceof globalThis.SVGAElement) name = is_camelcase$1(name) ? camel2hyphencase$1(name) : name;
if(this?.attr[name] && this?.attr[name]===value) return;
if(isStateGetter(value)){
const getter = value();
getter._subscribe(
(newValue) => this.element?.setAttribute(name, newValue),
this
);
}
else this.element?.setAttribute(name, value);
Object.assign(this.cache.attributes, {[name]:value});
}
// import {
// is_camelcase,
// camel2hyphencase
// } from '../../data/string/index.js'
function setAttr(name, value) {
if(name instanceof Object){
const [names,values]=[Object.keys(name),Object.values(name)];
for(let i=0;i<names.length;i++){
if(values[i] instanceof Array)value[i] = values[i].join(" ");
_set_attrs_.call(this, names[i], values[i]);
}
}
else {
if(value instanceof Array) value = value.join(" ");
_set_attrs_.call(this, name, value);
}
return this;
}
function removeAttr(...names) {
for(let i=0;i<names.length;i++)this.element?.removeAttribute(names[i]);
return this;
}
function getAttr(name){
name = is_camelcase(name) ? camel2hyphencase(name) : name;
return this.element.attributes[name].value;
}
function setContentEditable(bool = true) {
this.setAttr("contenteditable", bool);
return this;
}
var AttrsMethods = /*#__PURE__*/Object.freeze({
__proto__: null,
getAttr: getAttr,
removeAttr: removeAttr,
setAttr: setAttr,
setContentEditable: setContentEditable
});
function append(...ele) {
__addItem__.call(this, "append", "push", ...ele);
return this;
}
function prepend(...ele) {
this.__addItem__.call(this, "prepend", "unshift", ...ele);
return this;
}
function insertAt(index, ...ele) {
if (index >= this.element.children.length) this.append(...ele);
else
for (let i = 0; i < ele.length; i++) {
if (["number", "string"].includes(typeof ele[i])) ele[i] = text(ele[i]);
this.element?.insertBefore(ele[i].element, this.items[index].element);
this.items.splice(index, 0, ele[i]);
}
return this;
}
function remove(...ele) {
const remove = (ele) => {
if (typeof ele === "number") ele = this.items[ele];
if (ele?.isUIElement) this.element?.removeChild(ele.element);
this.items = this.items.filter((n) => n !== ele);
};
for (let i = 0; i < ele.length; i++) remove(ele[i]);
for (let i = 0; i < this.items.length; i++)
Object.assign(this, { [[i]]: this.items[i] });
// Remove from item
return this;
}
function clear(){
this?.items?.forEach(n=>n.unmount());
this.element.innerHTML = "";
return this;
}
function replaceElementWith(new_element){
this.cache.element.replaceWith(new_element);
this.cache.element = new_element;
// To do : Dispose Events and States
return this
}
function after(ui){
if(ui?.isUIElement) ui=ui.element;
this.element?.after(ui);
return this;
}
function before(ui){
if(ui?.isUIElement) ui=ui.element;
this.element?.before(ui);
return this;
}
var DomMethods = /*#__PURE__*/Object.freeze({
__p