ziko 0.68.0 → 0.68.1

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 : Fri Feb 20 2026 11:36:37 GMT+0000 (UTC)
5
+ Date : Wed Feb 25 2026 12:45:41 GMT+0000 (UTC)
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
@@ -2649,6 +2649,65 @@ var StyleMethods = /*#__PURE__*/Object.freeze({
2649
2649
  style: style$1
2650
2650
  });
2651
2651
 
2652
+ class EventController {
2653
+ constructor(target, category){
2654
+ this.cache = {
2655
+ category,
2656
+ target,
2657
+ listeners : {},
2658
+ currentEvent : null,
2659
+ event : null,
2660
+ customEvents : new Set()
2661
+ };
2662
+ }
2663
+ get event(){
2664
+ return this.cache.event
2665
+ }
2666
+ get element(){
2667
+ return this.cache.target.element;
2668
+ }
2669
+ get currentEvent(){
2670
+ return this.cache.currentEvent;
2671
+ }
2672
+ addListener(event_name, callback, {preventDefault = false, paused = false} = {}){
2673
+ this.cache.listeners[event_name] = {
2674
+ callback : e =>{
2675
+ this.cache.event = e;
2676
+ if(this.cache.listeners[event_name].preventDefault) e.preventDefault();
2677
+ if(!this.cache.listeners[event_name].paused) {
2678
+ this.cache.currentEvent = event_name;
2679
+ callback.call(this, this);
2680
+ }
2681
+ },
2682
+ preventDefault,
2683
+ paused,
2684
+ };
2685
+ this.element.addEventListener(event_name, this.cache.listeners[event_name].callback);
2686
+ return this;
2687
+ }
2688
+ removeListener(event_name){
2689
+ this.element.removeEventListener(event_name, this.cache.listeners[event_name].callback);
2690
+ return this;
2691
+ }
2692
+ pause(event_name){
2693
+ this.cache.listeners[event_name].paused = true;
2694
+ return this;
2695
+ }
2696
+ resume(event_name){
2697
+ this.cache.listeners[event_name].paused = false;
2698
+ return this;
2699
+ }
2700
+ preventDefault(event_name){
2701
+ // if(!event_name)
2702
+ this.cache.listeners[event_name].preventDefault = true;
2703
+ return this;
2704
+ }
2705
+ useDefault(event_name){
2706
+ this.cache.listeners[event_name].preventDefault = false;
2707
+ return this;
2708
+ }
2709
+ }
2710
+
2652
2711
  class ClickAwayEvent extends Event {
2653
2712
  constructor(originalEvent, targetElement) {
2654
2713
  super("clickaway", { bubbles: true, cancelable: true });
@@ -2684,26 +2743,6 @@ function register_click_away_event(element) {
2684
2743
  // // later, you can stop listening:
2685
2744
  // // stop();
2686
2745
 
2687
- const CATEGORY$2 = 'click';
2688
- const ClickListeners = {
2689
- onClick(callback){
2690
- this._on(
2691
- 'click', callback,
2692
- { category : CATEGORY$2 });
2693
- },
2694
- onDblClick(callback){
2695
- this._on(
2696
- 'dblclick', callback,
2697
- { category : CATEGORY$2});
2698
- },
2699
- onClickAway(callback){
2700
- register_click_away_event(this.element);
2701
- this._on(
2702
- 'clickaway', callback,
2703
- { category : CATEGORY$2});
2704
- },
2705
- };
2706
-
2707
2746
  const getCoordinates = (ctx, normalized = false) =>{
2708
2747
  const rect = ctx.element.getBoundingClientRect();
2709
2748
  const e = ctx.event;
@@ -2718,38 +2757,60 @@ const getCoordinates = (ctx, normalized = false) =>{
2718
2757
  }
2719
2758
 
2720
2759
  return {x, y};
2760
+ };
2761
+
2762
+ const isCustomEventRegistred = (ctx, category, event_name) => ctx.exp.events?.[category]?.cache?.customEvents?.has(event_name);
2763
+
2764
+ const CATEGORY$3 = 'click';
2765
+ const ClickListeners = {
2766
+ onClick(callback){
2767
+ return this.on(
2768
+ 'click', callback,
2769
+ { category : CATEGORY$3 })
2770
+ },
2771
+ onDblClick(callback){
2772
+ return this.on(
2773
+ 'dblclick', callback,
2774
+ { category : CATEGORY$3})
2775
+ },
2776
+ onClickAway(callback){
2777
+ if(!isCustomEventRegistred(this, CATEGORY$3, 'clickaway')) register_click_away_event(this.element);
2778
+ return this.on(
2779
+ 'clickaway', callback,
2780
+ { category : CATEGORY$3, isCustom : true})
2781
+ },
2721
2782
  };
2722
2783
 
2723
- const CATEGORY$1 = 'ptr';
2784
+ const CATEGORY$2 = 'ptr';
2724
2785
  const PtrListeners = {
2725
2786
  onPtrDown(callback, useNormalizedCoordinates = false){
2726
- this._on(
2787
+ return this.on(
2727
2788
  'pointerdown', callback,
2728
- { category : CATEGORY$1, details_setter : (ctx)=> {
2789
+ { category : CATEGORY$2, details_setter : (ctx)=> {
2729
2790
  const {x, y} = getCoordinates(ctx, useNormalizedCoordinates);
2730
2791
  ctx.dx = x;
2731
2792
  ctx.dy = y;
2732
2793
  ctx.isDown = true;
2733
2794
  ctx.isDragging = ctx.isMoving ?? false;
2734
2795
  }}
2735
- );
2796
+ )
2736
2797
  },
2737
2798
  onPtrMove(callback, useNormalizedCoordinates = false){
2738
- this._on(
2799
+ return this.on(
2739
2800
  'pointermove', callback,
2740
- { category : CATEGORY$1, details_setter : (ctx)=> {
2801
+ { category : CATEGORY$2, details_setter : (ctx)=> {
2741
2802
  const {x, y} = getCoordinates(ctx, useNormalizedCoordinates);
2742
2803
  ctx.mx = x;
2743
2804
  ctx.my = y;
2744
2805
  ctx.isMoving = true;
2745
2806
  ctx.isDragging = ctx.isDown ?? false;
2746
2807
  }}
2747
- );
2808
+ )
2748
2809
  },
2749
2810
  onPtrUp(callback, useNormalizedCoordinates = false){
2750
- this._on(
2811
+ return this.on(
2751
2812
  'pointerup', callback,
2752
- { category : CATEGORY$1, details_setter : (ctx)=> {
2813
+ { category : CATEGORY$2, details_setter : (ctx)=> {
2753
2814
  const {x, y} = getCoordinates(ctx, useNormalizedCoordinates);
2754
2815
  ctx.ux = x;
2755
2816
  ctx.uy = y;
@@ -2757,89 +2818,208 @@ const PtrListeners = {
2757
2818
  ctx.isMoving = false;
2758
2819
  ctx.isDragging = false;
2759
2820
  }}
2760
- );
2821
+ )
2761
2822
  }
2762
2823
  };
2763
2824
 
2764
- const CATEGORY = 'key';
2825
+ const CATEGORY$1 = 'key';
2765
2826
  const KeyListeners = {
2766
2827
  onKeyDown(callback){
2767
- this._on(
2828
+ return this.on(
2768
2829
  'keydown', callback,
2769
- { category : CATEGORY, details_setter : ctx=> { ctx.kd = ctx.event.key; }
2770
- });
2830
+ { category : CATEGORY$1, details_setter : ctx=> { ctx.kd = ctx.event.key; }
2831
+ })
2771
2832
  },
2772
2833
  onKeyPress(callback){
2773
- this._on(
2834
+ return this.on(
2774
2835
  'keypress', callback,
2775
- { category : CATEGORY, details_setter : ctx=> { ctx.kp = ctx.event.key; }
2776
- });
2836
+ { category : CATEGORY$1, details_setter : ctx=> { ctx.kp = ctx.event.key; }
2837
+ })
2777
2838
  },
2778
2839
  onKeyUp(callback){
2779
- this._on(
2840
+ return this.on(
2780
2841
  'keydown', callback,
2781
- { category : CATEGORY, details_setter : ctx=> { ctx.ku = ctx.event.key; }
2782
- });
2842
+ { category : CATEGORY$1, details_setter : ctx=> { ctx.ku = ctx.event.key; }
2843
+ })
2783
2844
  },
2784
2845
 
2785
2846
  };
2786
2847
 
2787
- class EventController {
2788
- constructor(target, category){
2789
- this.cache = {
2790
- category,
2791
- target,
2792
- listeners : {},
2793
- currentEvent : null,
2794
- event : null
2848
+ const debounce=(fn,delay=1000)=>{
2849
+ let id;
2850
+ return (...args) => id ? clearTimeout(id) : setTimeout(()=>fn(...args),delay);
2851
+ };
2852
+ const throttle=(fn,delay)=>{
2853
+ let lastTime=0;
2854
+ return (...args) => {
2855
+ const now = new Date().getTime();
2856
+ if(now-lastTime < delay) return;
2857
+ lastTime = now;
2858
+ fn(...args);
2859
+ }
2860
+ };
2861
+
2862
+ class ViewEvent extends CustomEvent {
2863
+ constructor(type, detail, { bubbles = true, cancelable = true } = {}) {
2864
+ super(type, { detail, bubbles, cancelable });
2865
+ }
2866
+ }
2867
+
2868
+ function register_view_event(
2869
+ element,
2870
+ {
2871
+ intersection = true,
2872
+ resize = true,
2873
+ threshold = 0,
2874
+ throttleResize = 100,
2875
+ throttleEnterExit = 0
2876
+ } = {}
2877
+ ) {
2878
+ let intersectionObserver, resizeObserver;
2879
+ const resizeCallback = entries => {
2880
+ for (let entry of entries) {
2881
+ const { width, height } = entry.contentRect;
2882
+
2883
+ element.dispatchEvent(
2884
+ new ViewEvent("resizeview", {
2885
+ width,
2886
+ height,
2887
+ entry
2888
+ })
2889
+ );
2890
+ }
2795
2891
  };
2796
- }
2797
- get event(){
2798
- return this.cache.event
2799
- }
2800
- get element(){
2801
- return this.cache.target.element;
2802
- }
2803
- get currentEvent(){
2804
- return this.cache.currentEvent;
2805
- }
2806
- addListener(event_name, callback, {preventDefault = false, paused = false} = {}){
2807
- this.cache.listeners[event_name] = {
2808
- callback : e =>{
2809
- this.cache.event = e;
2810
- if(this.cache.listeners[event_name].preventDefault) e.preventDefault();
2811
- if(!this.cache.listeners[event_name].paused) {
2812
- this.cache.currentEvent = event_name;
2813
- callback.call(this, this);
2892
+
2893
+ const throttledResize = throttleResize > 0
2894
+ ? throttle(resizeCallback, throttleResize)
2895
+ : resizeCallback;
2896
+
2897
+ const intersectionCallback = entries => {
2898
+ for (let entry of entries) {
2899
+ const type = entry.isIntersecting ? "enterview" : "exitview";
2900
+ element.dispatchEvent(new ViewEvent(type, entry));
2814
2901
  }
2815
- },
2816
- preventDefault,
2817
- paused,
2818
2902
  };
2819
- this.element.addEventListener(event_name, this.cache.listeners[event_name].callback);
2820
- return this;
2821
- }
2822
- removeListener(event_name){
2823
- this.element.removeEventListener(event_name, this.cache.listeners[event_name].callback);
2824
- return this;
2825
- }
2826
- pause(event_name){
2827
- this.cache.listeners[event_name].paused = true;
2828
- return this;
2829
- }
2830
- resume(event_name){
2831
- this.cache.listeners[event_name].paused = false;
2832
- return this;
2903
+
2904
+ const throttledIntersections = throttleEnterExit > 0
2905
+ ? throttle(intersectionCallback, throttleEnterExit)
2906
+ : intersectionCallback;
2907
+
2908
+ if (intersection) {
2909
+ intersectionObserver = new IntersectionObserver(throttledIntersections, { threshold });
2910
+ intersectionObserver.observe(element);
2911
+ }
2912
+
2913
+ if (resize) {
2914
+ resizeObserver = new ResizeObserver(throttledResize);
2915
+ resizeObserver.observe(element);
2916
+ }
2917
+
2918
+ // ---- UNREGISTER ----
2919
+ return () => {
2920
+ if (intersectionObserver) {
2921
+ intersectionObserver.unobserve(element);
2922
+ intersectionObserver.disconnect();
2923
+ }
2924
+ if (resizeObserver) {
2925
+ resizeObserver.unobserve(element);
2926
+ resizeObserver.disconnect();
2927
+ }
2928
+ };
2929
+ }
2930
+
2931
+ const CATEGORY = 'view';
2932
+ const ViewListeners = {
2933
+ onEnterView(callback){
2934
+ if(!this.exp.events?.[CATEGORY]) register_view_event(this.element);
2935
+ return this.on(
2936
+ 'enterview', callback,
2937
+ { category : CATEGORY, isCustom : true})
2938
+ },
2939
+ onExitView(callback){
2940
+ if(!this.exp.events?.[CATEGORY]) register_view_event(this.element);
2941
+ return this.on(
2942
+ 'exitview', callback,
2943
+ { category : CATEGORY, isCustom : true})
2944
+ },
2945
+ onResizeView(callback){
2946
+ if(!this.exp.events?.[CATEGORY]) register_view_event(this.element);
2947
+ return this.on(
2948
+ 'resizeview', callback,
2949
+ { category : CATEGORY, isCustom : true})
2950
+ },
2951
+ };
2952
+
2953
+ class SwipeEvent extends CustomEvent {
2954
+ constructor(type, detail) {
2955
+ super(type, {
2956
+ detail,
2957
+ bubbles: true,
2958
+ cancelable: true
2959
+ });
2833
2960
  }
2834
- preventDefault(event_name){
2835
- // if(!event_name)
2836
- this.cache.listeners[event_name].preventDefault = true;
2837
- return this;
2961
+ }
2962
+
2963
+ function register_swipe_event(
2964
+ element,
2965
+ threshold = 5,
2966
+ restraint = 100,
2967
+ allowedTime = 500
2968
+ ) {
2969
+ let startX = 0,
2970
+ startY = 0,
2971
+ startTime = 0,
2972
+ isPointerDown = false;
2973
+
2974
+ function onPointerDown(e) {
2975
+ startX = e.clientX;
2976
+ startY = e.clientY;
2977
+ startTime = performance.now();
2978
+ isPointerDown = true;
2838
2979
  }
2839
- useDefault(event_name){
2840
- this.cache.listeners[event_name].preventDefault = false;
2841
- return this;
2980
+
2981
+ function onPointerUp(e) {
2982
+ if (!isPointerDown) return;
2983
+ isPointerDown = false;
2984
+
2985
+ const distX = e.clientX - startX;
2986
+ const distY = e.clientY - startY;
2987
+ const elapsed = performance.now() - startTime;
2988
+
2989
+ let direction = null;
2990
+ let eventName = null;
2991
+
2992
+ if (elapsed <= allowedTime) {
2993
+ if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint) {
2994
+ direction = distX < 0 ? "left" : "right";
2995
+ eventName = "swipe" + direction;
2996
+ }
2997
+ else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint) {
2998
+ direction = distY < 0 ? "up" : "down";
2999
+ eventName = "swipe" + direction;
3000
+ }
3001
+ }
3002
+
3003
+ // Emit event
3004
+ if (eventName) {
3005
+ element.dispatchEvent(
3006
+ new SwipeEvent(eventName, {
3007
+ direction,
3008
+ distX,
3009
+ distY,
3010
+ originalEvent: e
3011
+ })
3012
+ );
3013
+ }
2842
3014
  }
3015
+
3016
+ element.addEventListener("pointerdown", onPointerDown, { passive: true });
3017
+ element.addEventListener("pointerup", onPointerUp, { passive: true });
3018
+
3019
+ return () => {
3020
+ element.removeEventListener("pointerdown", onPointerDown);
3021
+ element.removeEventListener("pointerup", onPointerUp);
3022
+ };
2843
3023
  }
2844
3024
 
2845
3025
  let UIElement$1 = class UIElement extends UIElementCore{
@@ -2856,24 +3036,26 @@ let UIElement$1 = class UIElement extends UIElementCore{
2856
3036
  AttrsMethods,
2857
3037
  DomMethods,
2858
3038
  StyleMethods,
2859
- IndexingMethods,
3039
+ IndexingMethods,
2860
3040
  PtrListeners,
2861
3041
  ClickListeners,
2862
- KeyListeners
3042
+ KeyListeners,
3043
+ ViewListeners,
2863
3044
  );
2864
3045
 
2865
3046
  if(element)this.init(element, name, type, render);
2866
3047
  }
2867
- _on(event, callback, {details_setter, category = 'global', preventDefault = false} = {}){
3048
+ on(event_name, callback, {details_setter, category = 'global', isCustom = false,preventDefault = false} = {}){
2868
3049
  if(category && !this.exp.events.hasOwnProperty(category)) this.exp.events[category] = new EventController(this, category);
3050
+ isCustom && this.exp.events[category].cache.customEvents.add(event_name);
2869
3051
  const EVENT = this.exp.events[category];
2870
- EVENT.addListener(event, (e)=>{
3052
+ EVENT.addListener(event_name, (e)=>{
2871
3053
  if(details_setter) details_setter(EVENT);
2872
3054
  callback(e);
2873
3055
  },{
2874
3056
  preventDefault
2875
3057
  });
2876
-
3058
+ return this;
2877
3059
  }
2878
3060
  _off(event, category = 'global'){
2879
3061
  this.exp.events[category].removeListener(event);
@@ -3861,20 +4043,6 @@ const Scheduler = (tasks, { repeat = null} = {}) => new TimeScheduler(tasks, { r
3861
4043
 
3862
4044
  const step_fps = (step_or_fps) => 1000 / step_or_fps;
3863
4045
 
3864
- const debounce=(fn,delay=1000)=>{
3865
- let id;
3866
- return (...args) => id ? clearTimeout(id) : setTimeout(()=>fn(...args),delay);
3867
- };
3868
- const throttle=(fn,delay)=>{
3869
- let lastTime=0;
3870
- return (...args) => {
3871
- const now = new Date().getTime();
3872
- if(now-lastTime < delay) return;
3873
- lastTime = now;
3874
- fn(...args);
3875
- }
3876
- };
3877
-
3878
4046
  const sleep= ms => new Promise(res => setTimeout(res, ms));
3879
4047
  function timeout(ms, fn) {
3880
4048
  let id;
@@ -4892,6 +5060,8 @@ if(globalThis?.document){
4892
5060
  }
4893
5061
 
4894
5062
  exports.App = App;
5063
+ exports.ClickAwayEvent = ClickAwayEvent;
5064
+ exports.ClickListeners = ClickListeners;
4895
5065
  exports.Clock = Clock;
4896
5066
  exports.CloneElement = CloneElement;
4897
5067
  exports.Complex = Complex;
@@ -4901,13 +5071,16 @@ exports.EventController = EventController;
4901
5071
  exports.FileBasedRouting = FileBasedRouting;
4902
5072
  exports.Flex = Flex;
4903
5073
  exports.HTMLWrapper = HTMLWrapper;
5074
+ exports.KeyListeners = KeyListeners;
4904
5075
  exports.Matrix = Matrix;
4905
5076
  exports.PI = PI$1;
5077
+ exports.PtrListeners = PtrListeners;
4906
5078
  exports.Random = Random;
4907
5079
  exports.SPA = SPA;
4908
5080
  exports.SVGWrapper = SVGWrapper;
4909
5081
  exports.Scheduler = Scheduler;
4910
5082
  exports.Suspense = Suspense;
5083
+ exports.SwipeEvent = SwipeEvent;
4911
5084
  exports.Switch = Switch;
4912
5085
  exports.Tick = Tick;
4913
5086
  exports.TimeAnimation = TimeAnimation;
@@ -4924,6 +5097,8 @@ exports.UseRoot = UseRoot;
4924
5097
  exports.UseThread = UseThread;
4925
5098
  exports.Utils = Utils;
4926
5099
  exports.View = View;
5100
+ exports.ViewEvent = ViewEvent;
5101
+ exports.ViewListeners = ViewListeners;
4927
5102
  exports.ZikoApp = ZikoApp;
4928
5103
  exports.ZikoSPA = ZikoSPA;
4929
5104
  exports.ZikoUISuspense = ZikoUISuspense;
@@ -5054,6 +5229,9 @@ exports.pgcd = pgcd;
5054
5229
  exports.pow = pow$1;
5055
5230
  exports.ppcm = ppcm;
5056
5231
  exports.rad2deg = rad2deg;
5232
+ exports.register_click_away_event = register_click_away_event;
5233
+ exports.register_swipe_event = register_swipe_event;
5234
+ exports.register_view_event = register_view_event;
5057
5235
  exports.remove_class = remove_class;
5058
5236
  exports.round = round;
5059
5237
  exports.script = script;