cradova 3.9.0 → 3.10.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.js CHANGED
@@ -503,18 +503,18 @@ class cradovaEvent {
503
503
  window.CradovaEvent = new cradovaEvent;
504
504
 
505
505
  class Store {
506
- _data;
506
+ $_internal_data;
507
507
  constructor(data, notifier) {
508
- this._data = data;
509
- for (const key in this._data) {
510
- if (this._data.hasOwnProperty(key)) {
508
+ this.$_internal_data = data;
509
+ for (const key in this.$_internal_data) {
510
+ if (this.$_internal_data.hasOwnProperty(key)) {
511
511
  Object.defineProperty(this, key, {
512
512
  get() {
513
- return this._data[key];
513
+ return this.$_internal_data[key];
514
514
  },
515
515
  set(value) {
516
+ this.$_internal_data[key] = value;
516
517
  notifier(key, value);
517
- this._data[key] = value;
518
518
  },
519
519
  enumerable: true,
520
520
  configurable: true
@@ -522,39 +522,22 @@ class Store {
522
522
  }
523
523
  }
524
524
  }
525
- _set(key, value) {
526
- this._data[key] = value;
525
+ _set(data) {
526
+ this.$_internal_data = data;
527
+ return Object.keys(this.$_internal_data);
527
528
  }
528
529
  }
529
530
 
530
531
  class List2 {
531
532
  _data;
532
533
  _dirtyIndices;
533
- _subscribers;
534
534
  notifier;
535
535
  constructor(initialData, notifier) {
536
536
  this._data = initialData || [];
537
537
  this._dirtyIndices = new Set;
538
538
  this.notifier = notifier;
539
- this._subscribers = {
540
- dataChanged: [],
541
- itemUpdated: []
542
- };
543
539
  this._dirtyIndices.add("all");
544
540
  }
545
- _publish(eventType, payload) {
546
- const subs = this._subscribers[eventType];
547
- if (subs) {
548
- for (let i2 = 0;i2 < subs.length; i2++) {
549
- subs[i2](payload);
550
- }
551
- }
552
- }
553
- _subscribe(eventType, callback) {
554
- if (this._subscribers[eventType]) {
555
- this._subscribers[eventType].push(callback);
556
- }
557
- }
558
541
  get items() {
559
542
  return {
560
543
  [Symbol.iterator]: () => {
@@ -579,7 +562,6 @@ class List2 {
579
562
  this._data[index] = newItemData;
580
563
  this._dirtyIndices.add(index);
581
564
  this.notifier("itemUpdated", { index, newItemData });
582
- this._publish("itemUpdated", { index, newItemData });
583
565
  }
584
566
  }
585
567
  push(itemData, index) {
@@ -589,30 +571,28 @@ class List2 {
589
571
  this._data.splice(index, 0, itemData);
590
572
  this._dirtyIndices.add("all");
591
573
  this.notifier("dataChanged", { type: "add", index });
592
- this._publish("dataChanged", { type: "add", index });
593
574
  }
594
575
  remove(index, count = 1) {
595
576
  if (index >= 0 && index < this._data.length && count > 0) {
596
577
  this._data.splice(index, count);
597
578
  this._dirtyIndices.add("all");
598
- this._publish("dataChanged", { type: "remove", index });
579
+ this.notifier("dataChanged", { type: "remove", index });
599
580
  }
600
581
  }
601
- set(newData) {
582
+ _set(newData) {
602
583
  this._data = newData || [];
603
584
  this._dirtyIndices.clear();
604
585
  this._dirtyIndices.add("all");
605
- this.notifier("dataChanged", { type: "reset" });
606
- this._publish("dataChanged", { type: "reset" });
586
+ return ["dataChanged"];
607
587
  }
608
- isDirty(index = "all") {
588
+ _isDirty(index = "all") {
609
589
  if (this._dirtyIndices.has(index)) {
610
590
  this._dirtyIndices.delete(index);
611
591
  return true;
612
592
  }
613
593
  return false;
614
594
  }
615
- clearAllDirty() {
595
+ _clearAllDirty() {
616
596
  this._dirtyIndices.clear();
617
597
  }
618
598
  }
@@ -620,65 +600,66 @@ class List2 {
620
600
  class Signal {
621
601
  pn;
622
602
  subs = {};
603
+ isList = false;
623
604
  listening_subs = {};
624
- store = {};
625
- list = [];
605
+ store;
626
606
  passers;
627
- constructor({
628
- store = {},
629
- list = []
630
- }, props) {
631
- this.store = new Store(store, (key, value) => {
632
- this.publish(key, value);
633
- });
607
+ constructor(initial, props) {
608
+ if (!initial || typeof initial !== "object") {
609
+ throw new Error("Initial signal value must be an array or object");
610
+ }
611
+ if (!Array.isArray(initial)) {
612
+ this.store = new Store(initial, (key) => {
613
+ this.publish(key);
614
+ });
615
+ } else {
616
+ this.isList = true;
617
+ this.store = new List2(initial, (eventType) => {
618
+ this.publish(eventType);
619
+ });
620
+ }
634
621
  this.subs = {};
635
- this.list = new List2(list, (eventType, value) => {
636
- this.publish(eventType, value);
637
- });
638
622
  if (props && props.persistName) {
639
623
  this.pn = props.persistName;
640
624
  const key = localStorage.getItem(props.persistName);
641
625
  if (key && key !== "undefined") {
642
- this.store = new Store(JSON.parse(key), (key2, value) => {
643
- this.publish(key2, value);
644
- });
645
- }
646
- if (typeof store === "object") {
647
- for (const key2 in store) {
648
- if (!Object.prototype.hasOwnProperty.call(this.store, key2)) {
649
- this.store["_set"](key2, store[key2]);
650
- }
626
+ const restored = JSON.parse(key);
627
+ if (!Array.isArray(restored)) {
628
+ this.store = new Store(restored, (key2) => {
629
+ this.publish(key2);
630
+ });
631
+ } else {
632
+ this.isList = true;
633
+ this.store = new List2(restored, (eventType) => {
634
+ this.publish(eventType);
635
+ });
651
636
  }
652
637
  }
653
638
  }
654
639
  }
655
- publish(eventName, data) {
656
- const subs = this.subs[eventName] || [];
657
- subs.forEach((c) => {
640
+ publish(eventName) {
641
+ this.subs[eventName]?.forEach((c) => {
658
642
  funcManager.recall(c);
659
643
  });
660
- const subs2 = this.listening_subs[eventName];
661
- if (subs2) {
662
- for (const fn of subs2) {
663
- fn({ [eventName]: data });
664
- }
665
- }
644
+ this.listening_subs[eventName]?.forEach((c) => {
645
+ c(this.store);
646
+ });
666
647
  if (this.pn) {
667
- localStorage.setItem(this.pn, JSON.stringify(this.store));
648
+ localStorage.setItem(this.pn, JSON.stringify(this.isList ? this.store.items : this.store.$_internal_data));
668
649
  }
669
650
  }
670
- batch(events) {
651
+ set(NEW) {
671
652
  const s = new Set;
653
+ const events = this.store._set(NEW);
672
654
  const s2 = new Set;
673
- for (const [eventName, data] of Object.entries(events)) {
674
- this.store["_set"](eventName, data);
675
- const subs = this.subs[eventName];
655
+ for (const event of events) {
656
+ const subs = this.subs[event];
676
657
  if (subs) {
677
658
  subs.forEach((c) => {
678
659
  s.add(c);
679
660
  });
680
661
  }
681
- const subs2 = this.listening_subs[eventName];
662
+ const subs2 = this.listening_subs[event];
682
663
  if (subs2) {
683
664
  for (const fn of subs2) {
684
665
  s2.add(fn);
@@ -691,7 +672,7 @@ class Signal {
691
672
  for (const fn of s2.values())
692
673
  fn(events);
693
674
  if (this.pn) {
694
- localStorage.setItem(this.pn, JSON.stringify(this.store));
675
+ localStorage.setItem(this.pn, JSON.stringify(this.isList ? this.store.items : this.store.$_internal_data));
695
676
  }
696
677
  }
697
678
  subscribe(eventName, comp) {
@@ -737,6 +718,35 @@ class Signal {
737
718
  }
738
719
  this.listening_subs[eventName].push(listener);
739
720
  }
721
+ computed(eventName, element) {
722
+ let el = element(this.store);
723
+ if (el === undefined || !(el instanceof HTMLElement)) {
724
+ console.error(` ✘ Cradova err: ${String(element)} is not a valid element or function`);
725
+ return;
726
+ }
727
+ const listener = () => {
728
+ const newEl = element(this.store);
729
+ if (newEl === undefined || !(newEl instanceof HTMLElement)) {
730
+ console.error(` ✘ Cradova err: ${String(element)} is not a valid element or function`);
731
+ return;
732
+ }
733
+ listener.element.insertAdjacentElement("beforebegin", newEl);
734
+ listener.element.remove();
735
+ listener.element = newEl;
736
+ };
737
+ 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] = [];
746
+ }
747
+ this.listening_subs[eventName].push(listener);
748
+ return el;
749
+ }
740
750
  get pass() {
741
751
  if (this.passers) {
742
752
  return this.passers;
@@ -1038,10 +1048,10 @@ class VirtualList {
1038
1048
  this.renderScheduled = false;
1039
1049
  this.container = container;
1040
1050
  this.scheduleRender();
1041
- this.dataStore.list._subscribe("dataChanged", () => {
1051
+ this.dataStore.listen("dataChanged", () => {
1042
1052
  this.scheduleRender();
1043
1053
  });
1044
- this.dataStore.list._subscribe("itemUpdated", () => {
1054
+ this.dataStore.listen("itemUpdated", () => {
1045
1055
  this.scheduleRender();
1046
1056
  });
1047
1057
  }
@@ -1052,11 +1062,11 @@ class VirtualList {
1052
1062
  requestAnimationFrame(this.render.bind(this));
1053
1063
  }
1054
1064
  render() {
1055
- const loop2 = Math.max(this.dataStore.list.length, this.container.children.length);
1056
- const needsFullRender = this.dataStore.list.isDirty();
1065
+ const loop2 = Math.max(this.dataStore.store.length, this.container.children.length);
1066
+ const needsFullRender = this.dataStore.store._isDirty();
1057
1067
  for (let i2 = 0;i2 < loop2; i2++) {
1058
- if (needsFullRender || this.dataStore.list.isDirty(i2)) {
1059
- const dataItem = this.dataStore.list.get(i2);
1068
+ if (needsFullRender || this.dataStore.store._isDirty(i2)) {
1069
+ const dataItem = this.dataStore.store.get(i2);
1060
1070
  const newDOM = this.renderItem(dataItem, i2);
1061
1071
  const oldDOM = this.container.children[i2];
1062
1072
  if (newDOM instanceof HTMLElement) {
@@ -1077,7 +1087,7 @@ class VirtualList {
1077
1087
  }
1078
1088
  }
1079
1089
  if (needsFullRender) {
1080
- this.dataStore.list.clearAllDirty();
1090
+ this.dataStore.store._clearAllDirty();
1081
1091
  }
1082
1092
  this.renderScheduled = false;
1083
1093
  }
@@ -1,4 +1,4 @@
1
- import type { browserPageType, Comp, CradovaPageType } from "./types.js";
1
+ import type { browserPageType, Comp, CradovaPageType, VJS_params_TYPE } 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);
@@ -9,7 +9,6 @@ declare class List<Type extends any[]> {
9
9
  update(index: number, newItemData: Type[number]): void;
10
10
  push(itemData: Type[number], index?: number): void;
11
11
  remove(index: number, count?: number): void;
12
- set(newData: Type): void;
13
12
  }
14
13
  /**
15
14
  * Cradova Signal
@@ -21,17 +20,14 @@ declare class List<Type extends any[]> {
21
20
  * - persist changes to localStorage
22
21
  * @constructor initial: Record<string, any>, props: {persist}
23
22
  */
24
- export declare class Signal<StoreType extends Record<string, any>, ListType extends any[]> {
23
+ export declare class Signal<Type = any> {
25
24
  private pn?;
26
25
  private subs;
26
+ private isList;
27
27
  private listening_subs;
28
- store: StoreType;
29
- list: List<ListType>;
30
- passers?: Record<keyof StoreType, [string, Signal<StoreType, ListType>]>;
31
- constructor({ store, list, }: {
32
- store?: StoreType;
33
- list?: ListType;
34
- }, props?: {
28
+ store: Type extends Array<any> ? List<Type> : Type extends Record<string, any> ? Type : never;
29
+ passers?: Record<keyof Type, [string, Signal<Type>]>;
30
+ constructor(initial: Type, props?: {
35
31
  persistName?: string | undefined;
36
32
  });
37
33
  /**
@@ -39,7 +35,7 @@ export declare class Signal<StoreType extends Record<string, any>, ListType exte
39
35
  * ----
40
36
  * fires actions if any available
41
37
  */
42
- batch(events: Partial<StoreType>): void;
38
+ set(NEW: Type): void;
43
39
  /**
44
40
  * Cradova Signal
45
41
  * ----
@@ -48,7 +44,7 @@ export declare class Signal<StoreType extends Record<string, any>, ListType exte
48
44
  * @param name of event.
49
45
  * @param Comp component to bind to.
50
46
  */
51
- subscribe<T extends keyof StoreType>(eventName: T | "dataChanged" | "itemUpdated" | T[], comp: Comp | ((this: Comp) => HTMLDivElement)): void;
47
+ subscribe<T extends keyof Type>(eventName: T | "dataChanged" | "itemUpdated" | T[], comp: Comp | ((this: Comp) => HTMLDivElement)): void;
52
48
  /**
53
49
  * Cradova Signal
54
50
  * ----
@@ -57,13 +53,14 @@ export declare class Signal<StoreType extends Record<string, any>, ListType exte
57
53
  * @param name of event.
58
54
  * @param callback function to call.
59
55
  */
60
- listen<T extends keyof StoreType>(eventName: T | "dataChanged" | "itemUpdated" | T[], listener: (data: Partial<StoreType>) => void): void;
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;
61
58
  /**
62
59
  * Cradova Signal
63
60
  * ----
64
61
  * subscribe an element to an event
65
62
  */
66
- get pass(): Record<keyof StoreType, [string, Signal<any, any>]>;
63
+ get pass(): Record<keyof Type, [string, Signal<any>]>;
67
64
  /**
68
65
  * Cradova Signal
69
66
  * ----
@@ -164,6 +161,6 @@ export declare class __raw_ref<T = unknown> {
164
161
  bind(name: string): [__raw_ref<T>, string];
165
162
  }
166
163
  export declare class VirtualList {
167
- constructor(container: HTMLElement, dataStore: Signal<any, any[]>, renderItemFunction: (item: any, index: number) => HTMLElement);
164
+ constructor(container: HTMLElement, dataStore: Signal<any[]>, renderItemFunction: (item: any, index: number) => HTMLElement);
168
165
  }
169
166
  export {};
@@ -34,7 +34,7 @@ export declare const funcManager: {
34
34
  cleanupEffects(component: Comp): void;
35
35
  unmount(component: Comp): void;
36
36
  };
37
- export declare const List: <T>(signal: Signal<any, T[]>, item: (item: T) => HTMLElement, options?: {
37
+ export declare const List: <T>(signal: Signal<T[]>, item: (item: T) => HTMLElement, options?: {
38
38
  className?: string;
39
39
  id?: string;
40
40
  style?: Partial<CSS.Properties>;
@@ -8,8 +8,10 @@ interface Attributes<E extends HTMLElement> {
8
8
  [key: `aria-${string}`]: string | undefined;
9
9
  [key: `on${string}`]: ((this: E, event: Event) => void) | undefined;
10
10
  }
11
- type StandardElementEventNames<E extends HTMLElement> = Extract<keyof E, `on${string}`>;
12
- export type VJS_params_TYPE<E extends HTMLElement> = (undefined | undefined[] | string | string[] | HTMLElement | HTMLElement[] | DocumentFragment | DocumentFragment[] | (() => HTMLElement) | (() => HTMLElement)[] | [string, Signal<any, any[]>] | (Attributes<E> & Omit<Partial<E>, keyof Attributes<E> | StandardElementEventNames<E>>))[];
11
+ type StandardEvents<E extends HTMLElement> = {
12
+ [key in keyof E]: E[key] extends (this: E, event: Event) => void ? key : never;
13
+ }[keyof E];
14
+ export type VJS_params_TYPE<E extends HTMLElement> = (undefined | undefined[] | string | string[] | HTMLElement | HTMLElement[] | DocumentFragment | DocumentFragment[] | (() => HTMLElement) | (() => HTMLElement)[] | [string, Signal<any>] | VJS_params_TYPE<E> | VJS_params_TYPE<E>[] | (Attributes<E> & Omit<Partial<E>, keyof Attributes<E> | StandardEvents<E>>))[];
13
15
  export type CradovaPageType = {
14
16
  /**
15
17
  * Cradova page
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cradova",
3
- "version": "3.9.0",
3
+ "version": "3.10.0",
4
4
  "description": "Build Powerful ⚡ Web Apps with Ease",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",