cradova 3.10.0 → 3.11.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.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,4 @@
1
1
  export * from "./primitives/classes.js";
2
2
  export * from "./primitives/functions.js";
3
3
  export * from "./primitives/dom-objects.js";
4
- import type { Comp } from "./primitives/types.js";
5
- export type { Comp };
6
- export declare function clone<T extends (...args: any[]) => any>(fn: T): T;
7
- export declare function invoke<R>(fn: (...args: any[]) => R, args: any[]): R;
4
+ export type { Comp } from "./primitives/types.js";
package/dist/index.js CHANGED
@@ -14,10 +14,10 @@ var makeElement = (element, ElementChildrenAndPropertyList) => {
14
14
  }
15
15
  if (Array.isArray(child)) {
16
16
  if (child[1] instanceof Signal) {
17
- child[1].listen([child[0]], (x) => {
17
+ child[1].notify([child[0]], () => {
18
18
  element.innerHTML = "";
19
19
  element.appendChild(unroll_child_list([
20
- x[child[0]]
20
+ child[1].store[child[0]]
21
21
  ]));
22
22
  });
23
23
  element.appendChild(unroll_child_list([child[1].store[child[0]]]));
@@ -44,10 +44,8 @@ var makeElement = (element, ElementChildrenAndPropertyList) => {
44
44
  Object.assign(element.style, value);
45
45
  continue;
46
46
  }
47
- if (prop === "onmount") {
48
- window.CradovaEvent.after_comp_is_mounted.push(() => {
49
- typeof props["onmount"] === "function" && props["onmount"].apply(element);
50
- });
47
+ if (prop === "onmount" && typeof props["onmount"] === "function") {
48
+ window.CradovaEvent.after_comp_is_mounted.push(props["onmount"].bind(element));
51
49
  continue;
52
50
  }
53
51
  if (prop.includes("data-") || prop.includes("aria-")) {
@@ -63,8 +61,8 @@ var makeElement = (element, ElementChildrenAndPropertyList) => {
63
61
  if (value.length === 2 && value[1] instanceof Signal && typeof value[0] === "string") {
64
62
  const eventName = value[0];
65
63
  const signalInstance = value[1];
66
- signalInstance.listen([eventName], (x) => {
67
- element.setAttribute(prop, x[eventName]);
64
+ signalInstance.notify([eventName], () => {
65
+ element.setAttribute(prop, signalInstance.store[eventName]);
68
66
  });
69
67
  element.setAttribute(prop, signalInstance.store[eventName]);
70
68
  continue;
@@ -188,7 +186,7 @@ function useState(initialValue) {
188
186
  }
189
187
  if (!Object.is(currentState, nextState)) {
190
188
  self._state[idx] = nextState;
191
- funcManager.recall(self);
189
+ funcManager.recall(self, undefined);
192
190
  }
193
191
  };
194
192
  return [self._state[idx], setState];
@@ -270,7 +268,7 @@ function useReducer(reducer, initialArg, initializer) {
270
268
  }
271
269
  if (!Object.is(currentState, nextState)) {
272
270
  currentTracker.state = nextState;
273
- funcManager.recall(self);
271
+ funcManager.recall(self, undefined);
274
272
  }
275
273
  };
276
274
  return [tracker[idx].state, dispatch];
@@ -310,16 +308,16 @@ function initializeComponent(comp) {
310
308
  });
311
309
  return component;
312
310
  }
313
- var toComp = (comp) => {
311
+ var toComp = (comp, args) => {
314
312
  const component = initializeComponent(comp);
315
- return funcManager.render(component);
313
+ return funcManager.render(component, args);
316
314
  };
317
315
  var toCompNoRender = (comp) => {
318
316
  return initializeComponent(comp);
319
317
  };
320
318
  var funcManager = {
321
- render(component) {
322
- const html = component.apply(component, []);
319
+ render(component, args) {
320
+ const html = component.apply(component, args);
323
321
  if (html instanceof HTMLElement) {
324
322
  component.reference = html;
325
323
  component.rendered = true;
@@ -332,14 +330,16 @@ var funcManager = {
332
330
  return;
333
331
  }
334
332
  },
335
- recall(component) {
333
+ recall(component, args) {
336
334
  if (component.rendered && component.published) {
337
335
  setTimeout(() => {
338
- this.activate(component);
336
+ this.activate(component, args);
339
337
  }, 0);
340
338
  }
339
+ window.CradovaEvent.dispatchEvent("after_page_is_killed");
340
+ window.CradovaEvent.dispatchEvent("after_comp_is_mounted");
341
341
  },
342
- activate(component) {
342
+ activate(component, args) {
343
343
  component.published = false;
344
344
  if (!component.rendered || !component.reference) {
345
345
  return;
@@ -347,7 +347,7 @@ var funcManager = {
347
347
  const node = component.reference;
348
348
  if (document.body.contains(node)) {
349
349
  initializeComponent(component);
350
- const newHtml = component.apply(component);
350
+ const newHtml = component.apply(component, args);
351
351
  if (newHtml instanceof HTMLElement) {
352
352
  node.replaceWith(newHtml);
353
353
  node.insertAdjacentElement("beforebegin", newHtml);
@@ -425,11 +425,17 @@ var List = (signal, item, options) => {
425
425
  style: options?.style
426
426
  }, {
427
427
  onmount() {
428
- new VirtualList(this, signal, item);
428
+ const vl = new VirtualList(this, signal, item);
429
+ return () => {
430
+ vl.destroy();
431
+ };
429
432
  }
430
433
  });
431
434
  return list;
432
435
  };
436
+ function invoke(fn, args) {
437
+ return toComp(fn, args);
438
+ }
433
439
 
434
440
  // src/primitives/dom-objects.ts
435
441
  var a = cra("a");
@@ -494,7 +500,7 @@ class cradovaEvent {
494
500
  const eventListeners = this[eventName];
495
501
  while (eventListeners.length !== 0) {
496
502
  const en_cb = await eventListeners.shift()();
497
- if (en_cb) {
503
+ if (typeof en_cb === "function") {
498
504
  this.after_page_is_killed.push(en_cb);
499
505
  }
500
506
  }
@@ -599,9 +605,8 @@ class List2 {
599
605
 
600
606
  class Signal {
601
607
  pn;
602
- subs = {};
603
608
  isList = false;
604
- listening_subs = {};
609
+ subscribers = {};
605
610
  store;
606
611
  passers;
607
612
  constructor(initial, props) {
@@ -618,7 +623,6 @@ class Signal {
618
623
  this.publish(eventType);
619
624
  });
620
625
  }
621
- this.subs = {};
622
626
  if (props && props.persistName) {
623
627
  this.pn = props.persistName;
624
628
  const key = localStorage.getItem(props.persistName);
@@ -638,11 +642,19 @@ class Signal {
638
642
  }
639
643
  }
640
644
  publish(eventName) {
641
- this.subs[eventName]?.forEach((c) => {
642
- funcManager.recall(c);
645
+ this.subscribers[eventName]?.forEach((c) => {
646
+ if (c.published) {
647
+ funcManager.recall(c, undefined);
648
+ } else {
649
+ c();
650
+ }
643
651
  });
644
- this.listening_subs[eventName]?.forEach((c) => {
645
- c(this.store);
652
+ this.subscribers["__ALL__"]?.forEach((c) => {
653
+ if (c.published) {
654
+ funcManager.recall(c, undefined);
655
+ } else {
656
+ c();
657
+ }
646
658
  });
647
659
  if (this.pn) {
648
660
  localStorage.setItem(this.pn, JSON.stringify(this.isList ? this.store.items : this.store.$_internal_data));
@@ -651,81 +663,96 @@ class Signal {
651
663
  set(NEW) {
652
664
  const s = new Set;
653
665
  const events = this.store._set(NEW);
654
- const s2 = new Set;
655
666
  for (const event of events) {
656
- const subs = this.subs[event];
657
- if (subs) {
658
- subs.forEach((c) => {
659
- s.add(c);
660
- });
661
- }
662
- const subs2 = this.listening_subs[event];
667
+ const subs2 = this.subscribers[event];
663
668
  if (subs2) {
664
669
  for (const fn of subs2) {
665
- s2.add(fn);
670
+ s.add(fn);
666
671
  }
667
672
  }
668
673
  }
674
+ if (this.subscribers["__ALL__"]) {
675
+ for (const fn of this.subscribers["__ALL__"]) {
676
+ s.add(fn);
677
+ }
678
+ }
669
679
  for (const c of s.values()) {
670
- funcManager.recall(c);
680
+ if (c.published) {
681
+ funcManager.recall(c, undefined);
682
+ } else {
683
+ c();
684
+ }
671
685
  }
672
- for (const fn of s2.values())
673
- fn(events);
674
686
  if (this.pn) {
675
687
  localStorage.setItem(this.pn, JSON.stringify(this.isList ? this.store.items : this.store.$_internal_data));
676
688
  }
677
689
  }
678
- subscribe(eventName, comp) {
679
- if (typeof comp === "function") {
680
- if (Array.isArray(eventName)) {
681
- eventName.forEach((en) => {
682
- this.subscribe(en, comp);
683
- });
684
- return;
685
- }
686
- if (!comp.published) {
687
- if (!isArrowFunc(comp)) {
688
- comp = toCompNoRender(comp);
689
- } else {
690
- console.error(` ✘ Cradova err: ${String(comp)} is not a valid component or function`);
691
- return;
692
- }
693
- }
694
- if (comp.published)
695
- return;
696
- if (!(eventName in this.store)) {
697
- console.error(` ✘ Cradova err: ${String(eventName)} is not a valid event for this Signal`);
698
- return;
699
- }
700
- if (!this.subs[eventName]) {
701
- this.subs[eventName] = new Set([comp]);
690
+ notify(eventName, listener) {
691
+ if (!eventName) {
692
+ console.error(` ✘ Cradova err: eventName ${String(eventName)} or listener ${String(listener)} is not a valid event name or function`);
693
+ return;
694
+ }
695
+ if (typeof eventName === "function") {
696
+ listener = eventName;
697
+ if (this.isList) {
698
+ eventName = ["dataChanged", "itemUpdated"];
702
699
  } else {
703
- this.subs[eventName].add(comp);
700
+ eventName = Object.keys(this.store);
704
701
  }
705
- } else {
706
- console.error(` ✘ Cradova err: ${comp} is not a valid component`);
707
702
  }
708
- }
709
- listen(eventName, listener) {
703
+ if (typeof listener !== "function" || !eventName) {
704
+ console.error(` ✘ Cradova err: listener or eventName ${String(listener)} is not a valid listener function or string`);
705
+ return;
706
+ }
710
707
  if (Array.isArray(eventName)) {
711
708
  eventName.forEach((en) => {
712
- this.listen(en, listener);
709
+ this.notify(en, listener);
713
710
  });
714
711
  return;
715
712
  }
716
- if (!this.listening_subs[eventName]) {
717
- this.listening_subs[eventName] = [];
713
+ if (!this.subscribers[eventName]) {
714
+ this.subscribers[eventName] = [];
718
715
  }
719
- this.listening_subs[eventName].push(listener);
716
+ if (!isArrowFunc(listener)) {
717
+ listener = toCompNoRender(listener);
718
+ }
719
+ this.subscribers[eventName].push(listener);
720
720
  }
721
721
  computed(eventName, element) {
722
- let el = element(this.store);
722
+ if (!eventName) {
723
+ console.error(` ✘ Cradova err: eventName ${String(eventName)} or element ${String(element)} is not a valid event name or function`);
724
+ return;
725
+ }
726
+ if (typeof eventName === "function") {
727
+ element = eventName;
728
+ if (this.isList) {
729
+ eventName = "__ALL__";
730
+ } else {
731
+ eventName = "__ALL__";
732
+ }
733
+ }
734
+ const isComp = !isArrowFunc(element);
735
+ let el;
736
+ if (isComp) {
737
+ el = toComp(element);
738
+ } else {
739
+ el = element?.();
740
+ }
723
741
  if (el === undefined || !(el instanceof HTMLElement)) {
724
742
  console.error(` ✘ Cradova err: ${String(element)} is not a valid element or function`);
725
743
  return;
726
744
  }
727
745
  const listener = () => {
728
- const newEl = element(this.store);
746
+ if (!document.body.contains(listener.element)) {
747
+ this.subscribers[eventName].splice(listener.idx, 1);
748
+ return;
749
+ }
750
+ let newEl;
751
+ if (isComp) {
752
+ newEl = toComp(element);
753
+ } else {
754
+ newEl = element?.();
755
+ }
729
756
  if (newEl === undefined || !(newEl instanceof HTMLElement)) {
730
757
  console.error(` ✘ Cradova err: ${String(element)} is not a valid element or function`);
731
758
  return;
@@ -735,16 +762,11 @@ class Signal {
735
762
  listener.element = newEl;
736
763
  };
737
764
  listener.element = el;
738
- if (Array.isArray(eventName)) {
739
- eventName.forEach((en) => {
740
- this.listen(en, listener);
741
- });
742
- return el;
743
- }
744
- if (!this.listening_subs[eventName]) {
745
- this.listening_subs[eventName] = [];
765
+ if (!this.subscribers[eventName]) {
766
+ this.subscribers[eventName] = [];
746
767
  }
747
- this.listening_subs[eventName].push(listener);
768
+ listener.idx = this.subscribers[eventName].length;
769
+ this.subscribers[eventName].push(listener);
748
770
  return el;
749
771
  }
750
772
  get pass() {
@@ -1042,16 +1064,19 @@ class VirtualList {
1042
1064
  renderItem;
1043
1065
  renderScheduled;
1044
1066
  container;
1067
+ idxs = [];
1045
1068
  constructor(container, dataStore, renderItemFunction) {
1046
1069
  this.dataStore = dataStore;
1047
1070
  this.renderItem = renderItemFunction;
1048
1071
  this.renderScheduled = false;
1049
1072
  this.container = container;
1050
1073
  this.scheduleRender();
1051
- this.dataStore.listen("dataChanged", () => {
1074
+ this.idxs.push(dataStore.subscribers["dataChanged"]?.length || 0);
1075
+ this.dataStore.notify("dataChanged", () => {
1052
1076
  this.scheduleRender();
1053
1077
  });
1054
- this.dataStore.listen("itemUpdated", () => {
1078
+ this.idxs.push(dataStore.subscribers["itemUpdated"]?.length || 0);
1079
+ this.dataStore.notify("itemUpdated", () => {
1055
1080
  this.scheduleRender();
1056
1081
  });
1057
1082
  }
@@ -1091,16 +1116,16 @@ class VirtualList {
1091
1116
  }
1092
1117
  this.renderScheduled = false;
1093
1118
  }
1094
- }
1095
-
1096
- // src/index.ts
1097
- function clone(fn) {
1098
- return function(...args) {
1099
- return fn.apply(this, args);
1100
- };
1101
- }
1102
- function invoke(fn, args) {
1103
- return fn.apply(null, args);
1119
+ destroy() {
1120
+ this.renderItem = null;
1121
+ this.container.innerHTML = "";
1122
+ this.container = null;
1123
+ this.renderScheduled = false;
1124
+ this.dataStore.subscribers["dataChanged"].splice(this.idxs[0], 1);
1125
+ this.dataStore.subscribers["itemUpdated"].splice(this.idxs[1], 1);
1126
+ this.idxs.length = 0;
1127
+ this.dataStore = null;
1128
+ }
1104
1129
  }
1105
1130
  export {
1106
1131
  video,
@@ -1146,7 +1171,6 @@ export {
1146
1171
  div,
1147
1172
  cradovaEvent,
1148
1173
  cra,
1149
- clone,
1150
1174
  canvas,
1151
1175
  button,
1152
1176
  audio,
@@ -1,4 +1,4 @@
1
- import type { browserPageType, Comp, CradovaPageType, VJS_params_TYPE } from "./types.js";
1
+ import type { browserPageType, Comp, CradovaPageType } from "./types.js";
2
2
  declare class List<Type extends any[]> {
3
3
  notifier: (eventType: "dataChanged" | "itemUpdated", newItemData: Type[number]) => void;
4
4
  constructor(initialData: Type, notifier: (eventType: "dataChanged" | "itemUpdated", newItemData: Type[number]) => void);
@@ -21,10 +21,6 @@ declare class List<Type extends any[]> {
21
21
  * @constructor initial: Record<string, any>, props: {persist}
22
22
  */
23
23
  export declare class Signal<Type = any> {
24
- private pn?;
25
- private subs;
26
- private isList;
27
- private listening_subs;
28
24
  store: Type extends Array<any> ? List<Type> : Type extends Record<string, any> ? Type : never;
29
25
  passers?: Record<keyof Type, [string, Signal<Type>]>;
30
26
  constructor(initial: Type, props?: {
@@ -36,15 +32,6 @@ export declare class Signal<Type = any> {
36
32
  * fires actions if any available
37
33
  */
38
34
  set(NEW: Type): void;
39
- /**
40
- * Cradova Signal
41
- * ----
42
- * subscribe to an event
43
- *
44
- * @param name of event.
45
- * @param Comp component to bind to.
46
- */
47
- subscribe<T extends keyof Type>(eventName: T | "dataChanged" | "itemUpdated" | T[], comp: Comp | ((this: Comp) => HTMLDivElement)): void;
48
35
  /**
49
36
  * Cradova Signal
50
37
  * ----
@@ -53,8 +40,8 @@ export declare class Signal<Type = any> {
53
40
  * @param name of event.
54
41
  * @param callback function to call.
55
42
  */
56
- listen<T extends keyof Type>(eventName: T | "dataChanged" | "itemUpdated" | T[], listener: (store: Type extends Array<any> ? List<Type> : Type extends Record<string, any> ? Type : never) => void): void;
57
- computed<T extends keyof Type>(eventName: T | "dataChanged" | "itemUpdated" | T[], element: (store: Type extends Array<any> ? List<Type> : Type extends Record<string, any> ? Type : never) => HTMLElement | VJS_params_TYPE<HTMLElement>): HTMLElement | undefined;
43
+ notify<T extends keyof Type>(eventName: (T | "dataChanged" | "itemUpdated" | T[]) | (() => HTMLElement | void) | Comp | ((this: Comp) => HTMLElement), listener?: (() => HTMLElement | void) | Comp | ((this: Comp) => HTMLElement)): void;
44
+ computed<T extends keyof Type>(eventName: (T | "dataChanged" | "itemUpdated") | (() => HTMLElement) | Comp | ((this: Comp) => HTMLElement), element?: (() => HTMLElement) | Comp | ((this: Comp) => HTMLElement)): HTMLElement | undefined;
58
45
  /**
59
46
  * Cradova Signal
60
47
  * ----
@@ -161,6 +148,7 @@ export declare class __raw_ref<T = unknown> {
161
148
  bind(name: string): [__raw_ref<T>, string];
162
149
  }
163
150
  export declare class VirtualList {
151
+ idxs: number[];
164
152
  constructor(container: HTMLElement, dataStore: Signal<any[]>, renderItemFunction: (item: any, index: number) => HTMLElement);
165
153
  }
166
154
  export {};
@@ -19,12 +19,12 @@ export declare function loop<Type>(datalist: LoopData<Type>, component: (value:
19
19
  */
20
20
  export declare const fragment: (children: VJS_params_TYPE<HTMLElement>) => DocumentFragment;
21
21
  export declare const isArrowFunc: (fn: Function) => boolean;
22
- export declare const toComp: (comp: Comp) => HTMLElement | undefined;
22
+ export declare const toComp: (comp: Comp, args?: any[]) => HTMLElement | undefined;
23
23
  export declare const toCompNoRender: (comp: Comp) => Comp;
24
24
  export declare const funcManager: {
25
- render(component: Comp): HTMLElement | undefined;
26
- recall(component: Comp): void;
27
- activate(component: Comp): void;
25
+ render(component: Comp, args: any[] | undefined): HTMLElement | undefined;
26
+ recall(component: Comp, args: any[] | undefined): void;
27
+ activate(component: Comp, args: any[] | undefined): void;
28
28
  /**
29
29
  * @internal
30
30
  */
@@ -39,4 +39,11 @@ export declare const List: <T>(signal: Signal<T[]>, item: (item: T) => HTMLEleme
39
39
  id?: string;
40
40
  style?: Partial<CSS.Properties>;
41
41
  }) => HTMLDivElement;
42
+ /**
43
+ * Invokes a function with the provided arguments.
44
+ * @param fn - The function to invoke.
45
+ * @param args - The arguments to pass to the function.
46
+ * @returns The result of the function invocation, which is expected to be an HTMLElement.
47
+ */
48
+ export declare function invoke(fn: (...args: any[]) => HTMLElement, args: any[]): HTMLElement | undefined;
42
49
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cradova",
3
- "version": "3.10.0",
3
+ "version": "3.11.0",
4
4
  "description": "Build Powerful ⚡ Web Apps with Ease",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",