ziko 0.49.6 → 0.49.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ziko.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
  /*
3
3
  Project: ziko.js
4
4
  Author: Zakaria Elalaoui
5
- Date : Wed Nov 26 2025 12:01:55 GMT+0100 (UTC+01:00)
5
+ Date : Sat Nov 29 2025 19:48:11 GMT+0100 (UTC+01:00)
6
6
  Git-Repo : https://github.com/zakarialaoui10/ziko.js
7
7
  Git-Wiki : https://github.com/zakarialaoui10/ziko.js/wiki
8
8
  Released under MIT License
@@ -1180,36 +1180,28 @@ const __CACHE__ = {
1180
1180
  };
1181
1181
 
1182
1182
  class UseChannel {
1183
- // private fields
1184
1183
  #channel;
1185
1184
  #eventData;
1186
1185
  #handlers;
1187
1186
  #uuid;
1188
1187
  #subscribers;
1189
- #currentRooms; // now a Set for multiple rooms
1190
-
1188
+ #currentRooms;
1191
1189
  constructor(name = "") {
1192
1190
  this.#channel = new BroadcastChannel(name);
1193
1191
  this.#eventData = new Map();
1194
1192
  this.#handlers = new Map(); // Map<event, Array<{fn, rooms}>>
1195
1193
  this.#uuid = "ziko-channel:" + Random.string(10);
1196
1194
  this.#subscribers = new Set([this.#uuid]);
1197
- this.#currentRooms = new Set(); // multiple rooms
1198
-
1195
+ this.#currentRooms = new Set();
1199
1196
  this.#channel.addEventListener("message", (e) => {
1200
1197
  const { last_sent_event, userId, eventData, rooms } = e.data;
1201
-
1202
1198
  if (userId === this.#uuid) return; // ignore own messages
1203
-
1204
1199
  // broadcast if no rooms, else check intersection
1205
1200
  if (rooms && rooms.length && !rooms.some(r => this.#currentRooms.has(r))) return;
1206
-
1207
1201
  this.#subscribers.add(userId);
1208
1202
  this.#eventData = new Map(eventData);
1209
-
1210
1203
  const handlersList = this.#handlers.get(last_sent_event);
1211
1204
  if (!handlersList) return;
1212
-
1213
1205
  handlersList.forEach(({ fn, rooms: handlerRooms }) => {
1214
1206
  // trigger if listener has no room filter, or intersects subscriber rooms
1215
1207
  if (!handlerRooms || handlerRooms.length === 0 ||
@@ -1223,24 +1215,20 @@ class UseChannel {
1223
1215
  emit(event, data, rooms) {
1224
1216
  this.#eventData.set(event, data);
1225
1217
  if(typeof rooms === 'string') rooms = [rooms];
1226
-
1227
1218
  this.#channel.postMessage({
1228
1219
  eventData: Array.from(this.#eventData.entries()),
1229
1220
  last_sent_event: event,
1230
1221
  userId: this.#uuid,
1231
1222
  rooms: rooms && rooms.length ? rooms : undefined
1232
1223
  });
1233
-
1234
1224
  return this;
1235
1225
  }
1236
-
1237
1226
  on(event, handler = console.log, rooms) {
1238
1227
  if (!this.#handlers.has(event)) this.#handlers.set(event, []);
1239
1228
  if(typeof rooms === 'string') rooms = [rooms];
1240
1229
  this.#handlers.get(event).push({ fn: handler, rooms });
1241
1230
  return this;
1242
1231
  }
1243
-
1244
1232
  off(event, handler) {
1245
1233
  if (!this.#handlers.has(event)) return this;
1246
1234
  this.#handlers.set(
@@ -1249,7 +1237,6 @@ class UseChannel {
1249
1237
  );
1250
1238
  return this;
1251
1239
  }
1252
-
1253
1240
  once(event, handler, rooms) {
1254
1241
  const wrapper = (data) => {
1255
1242
  handler(data);
@@ -1258,95 +1245,115 @@ class UseChannel {
1258
1245
  this.on(event, wrapper, rooms);
1259
1246
  return this;
1260
1247
  }
1261
-
1262
1248
  join(...rooms) {
1263
1249
  rooms.forEach(r => this.#currentRooms.add(r));
1264
1250
  return this;
1265
1251
  }
1266
-
1267
1252
  leave(...rooms) {
1268
1253
  if (!rooms.length) this.#currentRooms.clear();
1269
1254
  else rooms.forEach(r => this.#currentRooms.delete(r));
1270
1255
  return this;
1271
1256
  }
1272
-
1273
1257
  close() {
1274
1258
  this.#channel.close();
1275
1259
  return this;
1276
1260
  }
1277
-
1278
1261
  }
1279
1262
 
1280
1263
  const useChannel = (name) => new UseChannel(name);
1281
1264
 
1282
- // To do : remove old items
1283
- class UseStorage{
1284
- constructor(storage, globalKey, initialValue){
1285
- this.cache={
1265
+ class UseStorage {
1266
+ constructor(storage, globalKey, initialValue, use_channel = true) {
1267
+ this.cache = {
1286
1268
  storage,
1287
1269
  globalKey,
1288
- channel:useChannel(`Ziko:useStorage-${globalKey}`),
1289
- oldItemKeys:new Set()
1270
+ channel: use_channel ? useChannel(`Ziko:useStorage-${globalKey}`) : null,
1271
+ oldItemKeys: new Set()
1290
1272
  };
1291
- this.#init(initialValue);
1292
- this.#maintain();
1273
+
1274
+ this.#init(initialValue, use_channel);
1293
1275
  }
1294
- get items(){
1295
- return JSON.parse(this.cache.storage[this.cache.globalKey]??null);
1276
+
1277
+ get items() {
1278
+ const raw = this.cache.storage.getItem(this.cache.globalKey);
1279
+ if (!raw) return {};
1280
+ try {
1281
+ return JSON.parse(raw);
1282
+ } catch {
1283
+ return {};
1284
+ }
1296
1285
  }
1286
+
1297
1287
  #maintain() {
1298
- for(let i in this.items)Object.assign(this, { [[i]]: this.items[i] });
1299
- }
1300
- #init(initialValue){
1301
- this.cache.channel=useChannel(`Ziko:useStorage-${this.cache.globalKey}`);
1302
- this.cache.channel.on("Ziko-Storage-Updated",()=>this.#maintain());
1303
- if(!initialValue)return;
1304
- if(this.cache.storage[this.cache.globalKey]){
1305
- Object.keys(this.items).forEach(key=>this.cache.oldItemKeys.add(key));
1306
- // console.group("Ziko:useStorage")
1307
- // console.warn(`Storage key '${this.cache.globalKey}' already exists. we will not overwrite it.`);
1308
- // console.info(`%cWe'll keep the existing data.`,"background-color:#2222dd; color:gold;");
1309
- // console.group("")
1288
+ const items = this.items;
1289
+ this.cache.oldItemKeys.forEach(k => delete this[k]);
1290
+ for (const key in items) {
1291
+ this[key] = items[key];
1292
+ this.cache.oldItemKeys.add(key);
1293
+ }
1294
+ }
1295
+ #init(initialValue, use_channel) {
1296
+ if (use_channel && this.cache.channel) this.cache.channel.on("Ziko-Storage-Updated", () => this.#maintain());
1297
+ if (!initialValue) {
1298
+ this.#maintain();
1299
+ return;
1310
1300
  }
1301
+ if (this.cache.storage.getItem(this.cache.globalKey)) {
1302
+ const existing = this.items;
1303
+ Object.keys(existing).forEach(k => this.cache.oldItemKeys.add(k));
1304
+ this.#maintain();
1305
+ }
1311
1306
  else this.set(initialValue);
1312
1307
  }
1313
- set(data){
1314
- this.cache.storage.setItem(this.cache.globalKey,JSON.stringify(data));
1315
- this.cache.channel.emit("Ziko-Storage-Updated",{});
1316
- Object.keys(data).forEach(key=>this.cache.oldItemKeys.add(key));
1308
+
1309
+ set(data) {
1310
+ this.cache.storage.setItem(this.cache.globalKey, JSON.stringify(data));
1311
+ if (this.cache.channel) this.cache.channel.emit("Ziko-Storage-Updated", data);
1317
1312
  this.#maintain();
1318
- return this
1313
+ return this;
1319
1314
  }
1320
- add(data){
1321
- const db={
1315
+
1316
+ add(data) {
1317
+ this.set({
1322
1318
  ...this.items,
1323
1319
  ...data
1324
- };
1325
- this.cache.storage.setItem(this.cache.globalKey,JSON.stringify(db));
1326
- this.#maintain();
1320
+ });
1327
1321
  return this;
1328
1322
  }
1329
- remove(...keys){
1330
- const db={...this.items};
1331
- for(let i=0;i<keys.length;i++){
1332
- delete db[keys[i]];
1333
- delete this[keys[i]];
1334
- }
1335
- this.set(db);
1323
+ remove(...keys) {
1324
+ const items = { ...this.items };
1325
+ keys.forEach(key => {
1326
+ delete items[key];
1327
+ delete this[key];
1328
+ this.cache.oldItemKeys.delete(key);
1329
+ });
1330
+ this.set(items);
1336
1331
  return this;
1337
1332
  }
1338
- get(key){
1333
+ get(key) {
1339
1334
  return this.items[key];
1340
1335
  }
1341
- clear(){
1336
+ clear() {
1342
1337
  this.cache.storage.removeItem(this.cache.globalKey);
1338
+ this.cache.oldItemKeys.forEach(k => delete this[k]);
1339
+ this.cache.oldItemKeys.clear();
1343
1340
  this.#maintain();
1344
1341
  return this;
1345
1342
  }
1346
-
1343
+ onStorageUpdated(callback) {
1344
+ if (this.cache.channel) {
1345
+ this.cache.channel.on("Ziko-Storage-Updated", callback);
1346
+ }
1347
+ return this;
1348
+ }
1347
1349
  }
1348
- const useLocaleStorage=(key,initialValue)=>new UseStorage(localStorage,key,initialValue);
1349
- const useSessionStorage=(key,initialValue)=>new UseStorage(sessionStorage,key,initialValue);
1350
+
1351
+ // factory functions
1352
+ const useLocaleStorage = (key, initialValue, use_channel = true) =>
1353
+ new UseStorage(localStorage, key, initialValue, use_channel);
1354
+
1355
+ const useSessionStorage = (key, initialValue, use_channel = true) =>
1356
+ new UseStorage(sessionStorage, key, initialValue, use_channel);
1350
1357
 
1351
1358
  const __State__ = {
1352
1359
  store : new Map(),
@@ -4798,76 +4805,79 @@ const timeTaken = callback => {
4798
4805
  };
4799
4806
 
4800
4807
  class UseEventEmitter {
4801
- constructor() {
4802
- this.events = {};
4803
- this.maxListeners = 10;
4808
+ constructor(maxListeners = 10) {
4809
+ this.events = {};
4810
+ this.maxListeners = maxListeners;
4804
4811
  }
4812
+
4805
4813
  on(event, listener) {
4806
- if (!this.events[event]) {
4807
- this.events[event] = [];
4808
- }
4809
- this.events[event].push(listener);
4810
- if (this.events[event].length > this.maxListeners) {
4811
- console.warn(`Warning: Possible memory leak. Event '${event}' has more than ${this.maxListeners} listeners.`);
4812
- }
4814
+ if (!this.events[event]) this.events[event] = [];
4815
+ this.events[event].push(listener);
4816
+ if (this.events[event].length > this.maxListeners) {
4817
+ console.warn(`Warning: Possible memory leak. Event '${event}' has more than ${this.maxListeners} listeners.`);
4818
+ }
4819
+ return this;
4813
4820
  }
4821
+
4814
4822
  once(event, listener) {
4815
- const onceListener = (data) => {
4816
- this.off(event, onceListener); // Remove the listener after it's been called
4817
- listener(data);
4818
- };
4819
- this.on(event, onceListener);
4823
+ const wrapper = (...args) => {
4824
+ this.off(event, wrapper);
4825
+ listener(...args);
4826
+ };
4827
+ return this.on(event, wrapper);
4820
4828
  }
4821
-
4829
+
4822
4830
  off(event, listener) {
4823
- const listeners = this.events[event];
4824
- if (listeners) {
4831
+ const listeners = this.events[event];
4832
+ if (!listeners) return this;
4833
+
4825
4834
  const index = listeners.indexOf(listener);
4826
4835
  if (index !== -1) {
4827
- listeners.splice(index, 1);
4836
+ listeners.splice(index, 1);
4828
4837
  }
4829
- }
4838
+
4839
+ return this;
4830
4840
  }
4831
-
4841
+
4832
4842
  emit(event, data) {
4833
- const listeners = this.events[event];
4834
- if (listeners) {
4835
- listeners.forEach(listener => {
4836
- listener(data);
4843
+ const listeners = this.events[event];
4844
+ if (!listeners) return false;
4845
+
4846
+ // Make a copy so removing listeners inside callbacks doesn't affect iteration
4847
+ [...listeners].forEach(listener => {
4848
+ try {
4849
+ listener(data);
4850
+ } catch (e) {
4851
+ console.error(`Error in listener for '${event}':`, e);
4852
+ }
4837
4853
  });
4838
- }
4839
- }
4840
-
4841
- clear(event) {
4842
- if (event) {
4843
- delete this.events[event];
4844
- } else {
4845
- this.events = {};
4846
- }
4854
+
4855
+ return true;
4847
4856
  }
4848
-
4849
- setMaxListener(event, max) {
4850
- this.maxListeners = max;
4857
+ remove(event){
4858
+ delete this.events[event];
4859
+ return this;
4851
4860
  }
4852
-
4853
- removeAllListeners(event) {
4854
- if (event) {
4855
- this.events[event] = [];
4856
- } else {
4861
+ clear() {
4857
4862
  this.events = {};
4858
- }
4863
+ return this;
4859
4864
  }
4860
- }
4861
4865
 
4862
- const useEventEmitter=()=>new UseEventEmitter();
4866
+ setMaxListeners(max) {
4867
+ this.maxListeners = max;
4868
+ return this;
4869
+ }
4870
+ }
4871
+
4872
+ const useEventEmitter = (maxListeners) => new UseEventEmitter(maxListeners);
4863
4873
 
4864
4874
  class ZikoUseFavIcon{
4865
- constructor(FavIcon,useEventEmitter=true){
4875
+ constructor(FavIcon,withEmitter=true){
4866
4876
  this.#init();
4867
4877
  this.cache={
4868
4878
  Emitter:null
4869
4879
  };
4870
- if(useEventEmitter)this.useEventEmitter();
4880
+ if(withEmitter)this.useEventEmitter();
4871
4881
  this.set(FavIcon);
4872
4882
  }
4873
4883
  #init(){
@@ -4896,7 +4906,7 @@ class ZikoUseFavIcon{
4896
4906
  }
4897
4907
 
4898
4908
  }
4899
- const useFavIcon=(FavIcon,useEventEmitter)=>new ZikoUseFavIcon(FavIcon,useEventEmitter);
4909
+ const useFavIcon=(FavIcon,withEmitter)=>new ZikoUseFavIcon(FavIcon,withEmitter);
4900
4910
 
4901
4911
  class ZikoMeta{
4902
4912
  constructor({viewport,charset,description,author,keywords}){
@@ -4976,7 +4986,7 @@ class ZikoUseTitle{
4976
4986
  return this;
4977
4987
  }
4978
4988
  }
4979
- const useTitle=(title, useEventEmitter)=>new ZikoUseTitle(title, useEventEmitter);
4989
+ const useTitle$1=(title, useEventEmitter)=>new ZikoUseTitle(title, useEventEmitter);
4980
4990
 
4981
4991
  // import {useLink} from "./";
4982
4992
  class ZikoHead{
@@ -4984,7 +4994,7 @@ class ZikoHead{
4984
4994
  this.html = globalThis?.document?.documentElement;
4985
4995
  this.head = globalThis?.document?.head;
4986
4996
 
4987
- title && useTitle(title);
4997
+ title && useTitle$1(title);
4988
4998
  lang && this.setLang(lang);
4989
4999
  icon && useFavIcon(icon);
4990
5000
  meta && useMeta(meta);
@@ -5221,7 +5231,7 @@ function useDerived(deriveFn, sources) {
5221
5231
  const subscribers = new Set();
5222
5232
 
5223
5233
  sources.forEach(source => {
5224
- const srcValue = source(); // getValue()
5234
+ const srcValue = source();
5225
5235
  srcValue._subscribe(() => {
5226
5236
  {
5227
5237
  const newVal = deriveFn(...sources.map(s => s().value));
@@ -5250,121 +5260,155 @@ const useReactive = (nested_value) => mapfun$1(
5250
5260
  nested_value
5251
5261
  );
5252
5262
 
5253
- class UseThreed {
5254
- #workerContent;
5263
+ class UseThread {
5264
+ #worker;
5265
+ #callbacks = new Map();
5266
+ #idCounter = 0;
5267
+
5255
5268
  constructor() {
5256
- this.#workerContent = (
5257
- function (msg) {
5269
+ const workerCode = `
5270
+ this.onmessage = function(e) {
5271
+ const { id, funStr, args, close } = e.data;
5258
5272
  try {
5259
- const func = new Function("return " + msg.data.fun)();
5260
- let result = func();
5261
- postMessage({ result });
5273
+ const func = new Function("return " + funStr)();
5274
+ const result = func(...args);
5275
+ postMessage({ id, result });
5262
5276
  } catch (error) {
5263
- postMessage({ error: error.message });
5277
+ postMessage({ id, error: error.message });
5264
5278
  } finally {
5265
- if (msg.data.close) self.close();
5279
+ if (close) self.close();
5266
5280
  }
5267
5281
  }
5268
- ).toString();
5269
- this.blob = new Blob(["this.onmessage = " + this.#workerContent], { type: "text/javascript" });
5270
- this.worker = new Worker(window.URL.createObjectURL(this.blob));
5282
+ `;
5283
+ const blob = new Blob([workerCode], { type: "text/javascript" });
5284
+ this.#worker = new Worker(URL.createObjectURL(blob));
5285
+
5286
+ this.#worker.addEventListener("message", (e) => {
5287
+ const { id, result, error } = e.data;
5288
+ const callback = this.#callbacks.get(id);
5289
+ if (!callback) return;
5290
+
5291
+ callback(result, error);
5292
+ this.#callbacks.delete(id);
5293
+ });
5271
5294
  }
5272
- call(func, callback, close = true) {
5273
- this.worker.postMessage({
5274
- fun: func.toString(),
5295
+ call(func, callback, args = [], close = true) {
5296
+ if (typeof func !== "function") throw new TypeError("func must be a function");
5297
+ const id = ++this.#idCounter;
5298
+ this.#callbacks.set(id, callback);
5299
+
5300
+ this.#worker.postMessage({
5301
+ id,
5302
+ funStr: func.toString(),
5303
+ args,
5275
5304
  close
5276
5305
  });
5277
- this.worker.onmessage = function (e) {
5278
- if (e.data.error) {
5279
- console.error(e.data.error);
5280
- } else {
5281
- callback(e.data.result);
5282
- }
5283
- };
5306
+
5284
5307
  return this;
5285
5308
  }
5286
- }
5287
5309
 
5288
- const useThread = (func, callback , close) => {
5289
- const T = new UseThreed();
5290
- if (func) {
5291
- T.call(func, callback , close);
5310
+ terminate() {
5311
+ this.#worker.terminate();
5292
5312
  }
5293
- return T;
5294
- };
5313
+ }
5295
5314
 
5296
- class UseRoot {
5297
- constructor(PropsMap, {namespace = 'Ziko', register, ValidateCssProps = false} = {}){
5298
- this.currentPropsMap = PropsMap;
5299
- this.namespace = namespace;
5300
- this.ValidateCssProps = ValidateCssProps;
5301
- // this.pairs = {};
5302
- // this.#maintain()
5303
- this.use(PropsMap);
5304
- }
5305
- use(PropsMap){
5306
- if(this.ValidateCssProps) ValidateCssProps(PropsMap);
5307
- this.currentPropsMap = PropsMap;
5308
- this.#maintain();
5309
- return this;
5315
+ /*
5316
+ [
5317
+ {
5318
+ query: '(min-width: 600px)',
5319
+ callback: () => console.log(1)
5320
+ },
5321
+ {
5322
+ query: '(max-width: 300px)',
5323
+ callback: () => console.log(2)
5310
5324
  }
5311
- #maintain(){
5312
- const root = globalThis?.document?.documentElement?.style;
5313
- for(let prop in this.currentPropsMap){
5314
- const cssProp = this.namespace ? `--${this.namespace}-${prop}` : `--${prop}`;
5315
- root.setProperty(
5316
- cssProp,
5317
- this.currentPropsMap[prop]
5318
- );
5319
- // Object.assign(this.pairs, {
5320
- // [prop] : `var(--${this.namespace}-${prop})`
5321
- // })
5322
- Object.defineProperty(this, prop, {
5323
- value: `var(${cssProp})`,
5324
- writable: true,
5325
- configurable: true,
5326
- enumerable: false
5327
- });
5328
- }
5325
+ ]
5326
+ */
5327
+
5328
+ class UseMediaQuery {
5329
+ #mediaQueryRules;
5330
+ #fallback;
5331
+ #lastCalledCallback = null;
5332
+
5333
+ constructor(mediaQueryRules = [], fallback = () => {}) {
5334
+ this.#mediaQueryRules = mediaQueryRules;
5335
+ this.#fallback = fallback;
5336
+
5337
+ this.#init();
5329
5338
  }
5330
- }
5331
5339
 
5332
- function ValidateCssProps(PropsMap){
5333
- const validProps = new Set(Object.keys(document.documentElement.style));
5334
- for (let key in PropsMap) {
5335
- if (!validProps.has(key)) {
5336
- throw new Error(`Invalid CSS property: "${key}"`);
5337
- }
5340
+ // PRIVATE: check if ANY rule matches
5341
+ #checkAllRules() {
5342
+ return this.#mediaQueryRules.some(
5343
+ ({ query }) => globalThis.matchMedia(query).matches
5344
+ );
5338
5345
  }
5339
- }
5340
5346
 
5341
- const useRoot = (PropsMap, {namespace, register, ValidateCssProps} = {}) => new UseRoot(PropsMap, {namespace, register, ValidateCssProps});
5347
+ // PRIVATE: installs listeners and initial checks
5348
+ #init() {
5349
+ this.#mediaQueryRules.forEach(({ query, callback }) => {
5350
+ const mediaQueryList = globalThis.matchMedia(query);
5342
5351
 
5343
- // Usage
5352
+ const checkMatches = () => {
5353
+ const anyMatch = this.#checkAllRules();
5344
5354
 
5345
- /*
5346
- const Styles = {
5347
- S1 : {
5348
- background : 'white',
5349
- color : 'darkblue'
5350
- border : '2px darkblue solid"'
5351
- },
5352
- S2 : {
5353
- background : 'darkblue',
5354
- color : 'white'
5355
- border : '2px green solid"'
5356
- }
5355
+ if (mediaQueryList.matches) {
5356
+ callback();
5357
+ this.#lastCalledCallback = callback;
5358
+ } else if (!anyMatch && this.#lastCalledCallback !== this.#fallback) {
5359
+ this.#fallback();
5360
+ this.#lastCalledCallback = this.#fallback;
5361
+ }
5362
+ };
5363
+
5364
+ checkMatches();
5365
+ mediaQueryList.addEventListener("change", checkMatches);
5366
+ });
5367
+ }
5357
5368
  }
5358
- const {use, border, background, color} = useRoot(Style.S1)
5359
5369
 
5360
- tags.p("Test useRoot ").style({
5361
- border,
5362
- color,
5363
- background,
5364
- padding : '10px'
5365
- })
5370
+ const useMediaQuery = (mediaQueryRules, fallback) =>
5371
+ new UseMediaQuery(mediaQueryRules, fallback);
5372
+
5373
+ class UseTitle {
5374
+ constructor(title = document.title, withEmitter = true) {
5375
+ this.cache = {
5376
+ emitter: null
5377
+ };
5366
5378
 
5367
- */
5379
+ if (withEmitter) this.useEventEmitter();
5380
+ this.set(title);
5381
+ }
5382
+
5383
+ useEventEmitter() {
5384
+ this.cache.emitter = useEventEmitter();
5385
+ return this;
5386
+ }
5387
+
5388
+ setTitle(title) {
5389
+ if (title !== document.title) {
5390
+ document.title = title;
5391
+
5392
+ if (this.cache.emitter) {
5393
+ this.cache.emitter.emit("ziko:title-changed", title);
5394
+ }
5395
+ }
5396
+ return this;
5397
+ }
5398
+
5399
+ get current() {
5400
+ return document.title;
5401
+ }
5402
+
5403
+ onChange(callback) {
5404
+ if (this.cache.emitter) {
5405
+ this.cache.emitter.on("ziko:title-changed", callback);
5406
+ }
5407
+ return this;
5408
+ }
5409
+ }
5410
+
5411
+ const useTitle = (title, withEmitter = true) => new UseTitle(title, withEmitter);
5368
5412
 
5369
5413
  let {sqrt, cos, sin, exp, log, cosh, sinh} = Math;
5370
5414
  // Math.abs = new Proxy(Math.abs, {
@@ -5459,7 +5503,7 @@ exports.UINode = UINode;
5459
5503
  exports.UISVGWrapper = UISVGWrapper;
5460
5504
  exports.UISwitch = UISwitch;
5461
5505
  exports.UIView = UIView;
5462
- exports.UseRoot = UseRoot;
5506
+ exports.UseThread = UseThread;
5463
5507
  exports.Utils = Utils;
5464
5508
  exports.View = View;
5465
5509
  exports.ZikoApp = ZikoApp;
@@ -5635,11 +5679,11 @@ exports.useChannel = useChannel;
5635
5679
  exports.useDerived = useDerived;
5636
5680
  exports.useEventEmitter = useEventEmitter;
5637
5681
  exports.useLocaleStorage = useLocaleStorage;
5682
+ exports.useMediaQuery = useMediaQuery;
5638
5683
  exports.useReactive = useReactive;
5639
- exports.useRoot = useRoot;
5640
5684
  exports.useSessionStorage = useSessionStorage;
5641
5685
  exports.useState = useState;
5642
- exports.useThread = useThread;
5686
+ exports.useTitle = useTitle;
5643
5687
  exports.wait = wait;
5644
5688
  exports.waitForUIElm = waitForUIElm;
5645
5689
  exports.waitForUIElmSync = waitForUIElmSync;