ziko 1.6.0 → 1.7.0

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.
@@ -12,7 +12,9 @@ export class UISwap extends UIElement {
12
12
  };
13
13
 
14
14
  this.append(...items);
15
- this.render();
15
+ requestAnimationFrame(() => {
16
+ this.render();
17
+ });
16
18
  }
17
19
  get activeItem(){
18
20
  return this.items[this.states.activeIndex]
@@ -20,7 +22,7 @@ export class UISwap extends UIElement {
20
22
  render() {
21
23
  this.items.forEach((n, i) => {
22
24
 
23
- const initialDisplay = n.element?.style?.display || '';
25
+ const initialDisplay = getComputedStyle(n.element).display;
24
26
  this.#DISPLAYS_MAP.set(n, initialDisplay);
25
27
 
26
28
  if (i !== this.states.activeIndex) {
@@ -28,6 +30,9 @@ export class UISwap extends UIElement {
28
30
  }
29
31
  });
30
32
  }
33
+ get DS(){
34
+ return this.#DISPLAYS_MAP
35
+ }
31
36
  next(n = 1) {
32
37
  return this.activate(this.states.activeIndex + n);
33
38
  }
@@ -16,7 +16,7 @@ import {
16
16
  ViewListeners,
17
17
  } from '../../events/index.js'
18
18
  class UIElement extends UIElementCore{
19
- constructor({element, name ='', type='html', render = __Ziko__.__Config__.default.render}={}){
19
+ constructor({element, name ='', type = 'html', render = __Ziko__.__Config__.default.render, props}={}){
20
20
  super()
21
21
  this.exp = {
22
22
  events : {
@@ -36,7 +36,7 @@ class UIElement extends UIElementCore{
36
36
  ViewListeners,
37
37
  );
38
38
 
39
- if(element)this.init(element, name, type, render);
39
+ if(element) this.init({element, name, type, render, props});
40
40
  }
41
41
  on(event_name, callback, {details_setter, category = 'global', isCustom = false, preventDefault = false} = {}){
42
42
  if(event_name instanceof Array) event_name.forEach(
@@ -1,12 +1,13 @@
1
1
  import {UINode} from "./UINode.js";
2
2
  import {__init__global__} from '../../__ziko__/index.js';
3
3
  import { UIStore } from "../../__ziko__/__ui__.js";
4
+ import { parse_props } from "../utils/parse_props.js";
4
5
  __init__global__()
5
6
  class UIElementCore extends UINode{
6
7
  constructor(){
7
8
  super()
8
9
  }
9
- init(element, name, type, render){
10
+ init({element, name, type, render, props = {}, items = []} = {}){
10
11
  this.target = globalThis.__Ziko__.__Config__.default.target||globalThis?.document?.body;
11
12
  if(typeof element === "string") {
12
13
  switch(type){
@@ -54,9 +55,26 @@ class UIElementCore extends UINode{
54
55
  }
55
56
  if(element) Object.assign(this.cache,{element});
56
57
  this.items = new UIStore();
57
- globalThis.__Ziko__.__UI__[this.cache.name]?globalThis.__Ziko__.__UI__[this.cache.name]?.push(this):globalThis.__Ziko__.__UI__[this.cache.name]=[this];
58
+ globalThis.__Ziko__.__UI__[this.cache.name]
59
+ ? globalThis.__Ziko__.__UI__[this.cache.name]?.push(this)
60
+ : globalThis.__Ziko__.__UI__[this.cache.name]=[this];
58
61
  element && render && this?.render?.()
59
62
  globalThis.__Ziko__.__UI__.push(this)
63
+
64
+ // console.log({props})
65
+ const parsed_props = parse_props(props);
66
+
67
+ this.parsed_props = parsed_props;
68
+
69
+ this.style(parsed_props.style);
70
+ this.setAttr(parsed_props.attrs);
71
+
72
+ const Events = Object.entries(parsed_props.events);
73
+
74
+ Events.forEach(([ev, callback]) => this[ev](callback.bind(this)))
75
+
76
+
77
+ if(items.length > 0) this.append(...items)
60
78
  }
61
79
  get element(){
62
80
  return this.cache.element;
@@ -1,4 +1,5 @@
1
1
  import { text } from "../../text/index.js";
2
+ import { isStateGetter } from "../../../hooks/use-state.js";
2
3
 
3
4
  export function append(...ele) {
4
5
  __addItem__.call(this, "append", "push", ...ele);
@@ -79,8 +80,8 @@ export async function __addItem__(adder, pusher, ...ele) {
79
80
  if (["number", "string"].includes(typeof ele[i])) ele[i] = text(ele[i]);
80
81
  // Fix Items Latter
81
82
  if (ele[i] instanceof Function) {
82
- const getter = ele[i]();
83
- if (getter.isStateGetter) {
83
+ if (isStateGetter(ele[i])) {
84
+ const getter = ele[i]();
84
85
  ele[i] = text(getter.value);
85
86
  getter._subscribe(
86
87
  (newValue) => (ele[i].element.textContent = newValue),
@@ -1,51 +1,28 @@
1
1
  import {UIElement} from "../constructors/UIElement.js";
2
2
  import { HTMLTags, SVGTags, MathMLTags } from "./tags-list.js";
3
+ import { isStateGetter } from "../../hooks/use-state.js";
4
+ import { call_with_optional_props } from "../utils/call_with_optional_props.js";
5
+ import { is_ui_item } from "../utils/is_ui_item.js";
3
6
 
4
- const tags = new Proxy({}, {
7
+ export const tags = new Proxy({}, {
5
8
  get(target, prop) {
6
9
  if (typeof prop !== 'string') return undefined;
7
10
  let tag = prop.replaceAll("_","-").toLowerCase();
8
11
  let type ;
9
- if(HTMLTags.includes(tag)) type = 'html'
10
- if(SVGTags.includes(tag)) type = 'svg'
11
- if(MathMLTags.includes(tag)) type = 'mathml'
12
- return (...args)=>{
13
- // Fix undefined
14
- // console.log(isStateGetter(args[0]))
15
- // console.log(!!args)
12
+ if(HTMLTags.includes(tag)) type = 'html';
13
+ if(SVGTags.includes(tag)) type = 'svg';
14
+ if(MathMLTags.includes(tag)) type = 'mathml';
15
+ return (...args) => {
16
16
  if(args.length === 0) {
17
- // console.log('length 0')
18
17
  return new UIElement({element : tag, name : tag, type})
19
18
  }
20
19
  if(
21
20
  ['string', 'number'].includes(typeof args[0])
22
21
  || args[0] instanceof UIElement
23
- || (typeof args[0] === 'function' && args[0]().isStateGetter())
22
+ || isStateGetter(args[0])
23
+ || args[0] instanceof HTMLElement
24
24
  ) return new UIElement({element : tag, name : tag, type}).append(...args);
25
- // console.log(args[0])
26
- return new UIElement({element : tag, type}).setAttr(args.shift()).append(...args)
25
+ return new UIElement({element : tag, type, props : args.shift()}).append(...args)
27
26
  }
28
- // if(SVGTags.includes(tag)) return (...args) => new UIElement(tag,"",{el_type : "svg"}).append(...args);
29
- // return (...args)=>{
30
- // if(!(args[0] instanceof UIElement) && args[0] instanceof Object){
31
- // let attributes = args.shift()
32
- // return new UIElement(tag).setAttr(attributes).append(...args)
33
- // }
34
- // return new UIElement(tag).append(...args);
35
- // }
36
- // // switch(tag){
37
- // case "html" : globalThis?.document?.createElement("html")
38
- // case "head" :
39
- // case "style" :
40
- // case "link" :
41
- // case "meta" :
42
- // case "srcipt":
43
- // case "body" : return null; break;
44
- // default : return new UIElement(tag);
45
- // }
46
27
  }
47
- });
48
-
49
- export {
50
- tags
51
- }
28
+ });
@@ -0,0 +1,14 @@
1
+ import { is_primitive } from "./checkers.js";
2
+ export const call_with_optional_props = (Component) => {
3
+ return (...args) => {
4
+ const first = args[0];
5
+
6
+ const isChild = first?.isUIElement?.() || is_primitive(first);
7
+
8
+ if (isChild) {
9
+ return new Component({}, ...args);
10
+ }
11
+
12
+ return new Component(first, ...args.slice(1));
13
+ };
14
+ };
@@ -0,0 +1 @@
1
+ export const is_primitive = (value) => typeof value !== 'object' && typeof value !== 'function' || value === null;
@@ -1,12 +1,7 @@
1
- export const call_with_optional_props = (Component) => {
2
- return (...args) => {
3
- const first = args[0];
4
- const isChild = first?.isUIElement?.() || isPrimitive(first) ;
5
- return isChild
6
- ? new Component({}, ...args)
7
- : new Component(first, ...args.slice(1))
8
- };
9
- };
1
+ export * from './call_with_optional_props.js';
2
+ export * from './parse_props.js';
3
+ export * from './checkers.js'
4
+
10
5
  export function add_vendor_prefix(property) {
11
6
  const propertyUC = property.slice(0, 1).toUpperCase() + property.slice(1);
12
7
  const vendors = ['Webkit', 'Moz', 'O', 'ms'];
@@ -59,9 +54,9 @@ const CloneElement = (UIElement) => {
59
54
  const cloneUI=UIElement=>{
60
55
  return Object.assign(Object.create(Object.getPrototypeOf(UIElement)),UIElement)
61
56
  }
62
- function isPrimitive(value) {
63
- return typeof value !== 'object' && typeof value !== 'function' || value === null;
64
- }
57
+ // function isPrimitive(value) {
58
+ // return typeof value !== 'object' && typeof value !== 'function' || value === null;
59
+ // }
65
60
  const waitElm=(UIElement)=>{
66
61
  return new Promise(resolve => {
67
62
  if (UIElement) {
@@ -87,7 +82,7 @@ export{
87
82
  linkStyle,
88
83
  CloneElement,
89
84
  cloneUI,
90
- isPrimitive,
85
+ // isPrimitive,
91
86
  // addSuffixeToNumber,
92
87
  waitElm
93
88
  }
@@ -0,0 +1,10 @@
1
+ import { isStateGetter } from '../../hooks/use-state.js'
2
+ import { UIElement } from '../constructors/UIElement.js'
3
+ export const is_ui_item = item => {
4
+ return (
5
+ ['string', 'number'].includes(item)
6
+ || isStateGetter(item)
7
+ || item instanceof HTMLElement
8
+ || item instanceof UIElement
9
+ )
10
+ }
@@ -0,0 +1,26 @@
1
+ export const parse_props = (props = {}) => {
2
+
3
+ const result = {
4
+ methods: {},
5
+ events: {},
6
+ style: {},
7
+ attrs: {}
8
+ };
9
+
10
+ for (const [key, value] of Object.entries(props)) {
11
+ if (key === "style") {
12
+ result.style = value;
13
+ }
14
+ else if (key.startsWith("$")) {
15
+ result.methods[key.slice(1)] = value;
16
+ }
17
+ else if (/^on[A-Z]/.test(key)) {
18
+ result.events[key] = value;
19
+ }
20
+ else {
21
+ result.attrs[key] = value;
22
+ }
23
+ }
24
+
25
+ return result;
26
+ }
@@ -2,8 +2,9 @@
2
2
 
3
3
  // if (!globalThis.__Ziko__) __init__global__();
4
4
 
5
+ export const STATE_GETTER = Symbol.for("ziko.stateGetter");
6
+
5
7
  export function useState(initialValue) {
6
-
7
8
  const state = {
8
9
  value: initialValue,
9
10
  subscribers: new Set(),
@@ -13,7 +14,6 @@ export function useState(initialValue) {
13
14
  function getValue() {
14
15
  return {
15
16
  value: state.value,
16
- isStateGetter: () => true,
17
17
  _subscribe: (fn) => {
18
18
  state.subscribers.add(fn);
19
19
  return () => state.subscribers.delete(fn);
@@ -21,6 +21,8 @@ export function useState(initialValue) {
21
21
  };
22
22
  }
23
23
 
24
+ getValue[STATE_GETTER] = true;
25
+
24
26
  function setValue(newValue) {
25
27
  if (state.paused) return;
26
28
 
@@ -42,6 +44,7 @@ export function useState(initialValue) {
42
44
  if (typeof newValue === "function") {
43
45
  newValue = newValue(state.value);
44
46
  }
47
+
45
48
  state.value = newValue;
46
49
  state.subscribers.forEach((fn) => fn(state.value));
47
50
  },
@@ -51,6 +54,4 @@ export function useState(initialValue) {
51
54
  return [getValue, setValue, controller];
52
55
  }
53
56
 
54
- export const isStateGetter = (arg) => {
55
- return typeof arg === "function" && arg?.()?.isStateGetter?.() === true;
56
- };
57
+ export const isStateGetter = (arg) => typeof arg === "function" && arg[STATE_GETTER] === true;
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Easing function used by animations.
3
+ *
4
+ * @param t - Normalized animation progress value between 0 and 1.
5
+ * @returns The transformed progress value.
6
+ */
7
+ export type EasingFunction = (t: number) => number;
8
+
9
+ /**
10
+ * Configuration options for a TimeAnimation instance.
11
+ */
12
+ export interface TimeAnimationOptions {
13
+ /**
14
+ * Easing function applied to the normalized progress.
15
+ *
16
+ * @default linear
17
+ */
18
+ ease?: EasingFunction;
19
+
20
+ /**
21
+ * Interval step between animation updates in milliseconds.
22
+ *
23
+ * @default 50
24
+ */
25
+ step?: number;
26
+
27
+ /**
28
+ * Initial time offset.
29
+ *
30
+ * @default 0
31
+ */
32
+ t0?: number;
33
+
34
+ /**
35
+ * Automatically start the animation after creation.
36
+ *
37
+ * @default true
38
+ */
39
+ start?: boolean;
40
+
41
+ /**
42
+ * Animation duration in milliseconds.
43
+ *
44
+ * @default 3000
45
+ */
46
+ duration?: number;
47
+ }
48
+
49
+ /**
50
+ * Runtime state of a TimeAnimation instance.
51
+ */
52
+ export interface TimeAnimationState {
53
+ /**
54
+ * Whether the animation is currently running.
55
+ */
56
+ isRunning: boolean;
57
+
58
+ /**
59
+ * Internal interval identifier.
60
+ */
61
+ animationId: ReturnType<typeof setInterval> | null;
62
+
63
+ /**
64
+ * Timestamp when the animation started.
65
+ */
66
+ startTime: number | null;
67
+
68
+ /**
69
+ * Current easing function.
70
+ */
71
+ ease: EasingFunction;
72
+
73
+ /**
74
+ * Interval step duration.
75
+ */
76
+ step: number;
77
+
78
+ /**
79
+ * Whether the animation starts automatically.
80
+ */
81
+ autoStart: boolean;
82
+
83
+ /**
84
+ * Total animation duration.
85
+ */
86
+ duration: number;
87
+ }
88
+
89
+ /**
90
+ * Callback executed on every animation tick.
91
+ *
92
+ * @param animation - Current animation instance.
93
+ */
94
+ export type AnimationCallback = (animation: TimeAnimation) => void;
95
+
96
+ /**
97
+ * Time-based animation controller.
98
+ *
99
+ * Provides start, pause, resume, stop and reset lifecycle methods.
100
+ * The callback receives the animation instance containing the current
101
+ * elapsed time and progress values.
102
+ */
103
+ export declare class TimeAnimation {
104
+ /**
105
+ * Creates a new time animation.
106
+ *
107
+ * @param callback - Function called on each animation step.
108
+ * @param options - Animation configuration.
109
+ */
110
+ constructor(
111
+ callback: AnimationCallback,
112
+ options?: TimeAnimationOptions
113
+ );
114
+
115
+ /**
116
+ * Animation state.
117
+ */
118
+ state: TimeAnimationState;
119
+
120
+ /**
121
+ * Elapsed animation time in milliseconds.
122
+ */
123
+ t: number;
124
+
125
+ /**
126
+ * Normalized progress value between 0 and 1.
127
+ */
128
+ tx: number;
129
+
130
+ /**
131
+ * Eased progress value.
132
+ */
133
+ ty: number;
134
+
135
+ /**
136
+ * Current animation step index.
137
+ */
138
+ i: number;
139
+
140
+ /**
141
+ * Starts or restarts the animation.
142
+ *
143
+ * @returns The current animation instance.
144
+ */
145
+ start(): this;
146
+
147
+ /**
148
+ * Pauses the animation.
149
+ *
150
+ * @returns The current animation instance.
151
+ */
152
+ pause(): this;
153
+
154
+ /**
155
+ * Resumes a paused animation.
156
+ *
157
+ * @returns The current animation instance.
158
+ */
159
+ resume(): this;
160
+
161
+ /**
162
+ * Stops the animation and resets its progress.
163
+ *
164
+ * @returns The current animation instance.
165
+ */
166
+ stop(): this;
167
+
168
+ /**
169
+ * Resets animation progress.
170
+ *
171
+ * @param restart - Whether to restart automatically after reset.
172
+ *
173
+ * @returns The current animation instance.
174
+ */
175
+ reset(restart?: boolean): this;
176
+ }
177
+
178
+ /**
179
+ * Creates a time-based animation instance.
180
+ *
181
+ * @param callback - Function executed on every animation tick.
182
+ * @param options - Animation configuration.
183
+ *
184
+ * @returns A new TimeAnimation instance.
185
+ */
186
+ export declare const animation: (
187
+ callback: AnimationCallback,
188
+ options?: TimeAnimationOptions
189
+ ) => TimeAnimation;
@@ -1,4 +1,5 @@
1
1
  export type * from './ease/index.d.ts'
2
2
  export type * from './clocks/index.d.ts'
3
3
  export type * from './decorators/index.d.ts'
4
- export type * from './loop/index.d.ts'
4
+ export type * from './loop/index.d.ts'
5
+ export type * from './animation/index.d.ts'
@@ -1,47 +0,0 @@
1
- function parseXML(xmlString) {
2
- const parser = new DOMParser();
3
- const xmlDoc = parser.parseFromString(xmlString, 'text/xml');
4
- const rootNode = xmlDoc.documentElement;
5
- const result = parseNode(rootNode);
6
- return result;
7
- }
8
-
9
- function parseNode(node) {
10
- const obj = {
11
- type: node.nodeName,
12
- attributes: {},
13
- children: []
14
- };
15
- for (let i = 0; i < node.attributes.length; i++) {
16
- const attr = node.attributes[i];
17
- obj.attributes[attr.name] = attr.value;
18
- }
19
- for (let i = 0; i < node.childNodes.length; i++) {
20
- const child = node.childNodes[i];
21
- if (child.nodeType === Node.ELEMENT_NODE) {
22
- obj.children.push(parseNode(child));
23
- } else if (child.nodeType === Node.TEXT_NODE) {
24
- obj.text = child.textContent.trim();
25
- }
26
- }
27
- return obj;
28
- }
29
- export default parseXML;
30
-
31
- // function htmlParser(element) {
32
- // const obj = {
33
- // type: element.tagName,
34
- // attributes: {},
35
- // children: [],
36
- // };
37
- // for (let i = 0; i < element.attributes.length; i++) {
38
- // const attr = element.attributes[i];
39
- // obj.attributes[attr.name] = attr.value;
40
- // }
41
- // for (let i = 0; i < element.children.length; i++) {
42
- // const child = element.children[i];
43
- // obj.children.push(htmlParser(child));
44
- // }
45
- // return obj;
46
- // }
47
-