valyrian.js 7.2.12 → 8.0.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.
Files changed (168) hide show
  1. package/README.md +6 -6
  2. package/dist/flux-store/index.d.ts +32 -0
  3. package/dist/flux-store/index.d.ts.map +1 -0
  4. package/dist/flux-store/index.js +267 -0
  5. package/dist/flux-store/index.js.map +7 -0
  6. package/dist/flux-store/index.min.js +1 -0
  7. package/dist/flux-store/index.min.js.map +1 -0
  8. package/dist/flux-store/index.mjs +246 -0
  9. package/dist/flux-store/index.mjs.map +7 -0
  10. package/dist/hooks/index.d.ts.map +1 -1
  11. package/dist/hooks/index.js +35 -51
  12. package/dist/hooks/index.js.map +3 -3
  13. package/dist/hooks/index.min.js +1 -0
  14. package/dist/hooks/index.min.js.map +1 -0
  15. package/dist/hooks/index.mjs +36 -52
  16. package/dist/hooks/index.mjs.map +3 -3
  17. package/dist/index.d.ts +18 -14
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +107 -88
  20. package/dist/index.js.map +3 -3
  21. package/dist/index.min.js +1 -1
  22. package/dist/index.min.js.map +1 -1
  23. package/dist/index.mjs +107 -88
  24. package/dist/index.mjs.map +3 -3
  25. package/dist/native-store/index.d.ts +14 -0
  26. package/dist/native-store/index.d.ts.map +1 -0
  27. package/dist/native-store/index.js +103 -0
  28. package/dist/native-store/index.js.map +7 -0
  29. package/dist/native-store/index.min.js +1 -0
  30. package/dist/native-store/index.min.js.map +1 -0
  31. package/dist/native-store/index.mjs +82 -0
  32. package/dist/native-store/index.mjs.map +7 -0
  33. package/dist/node/index.d.ts +1 -1
  34. package/dist/node/index.d.ts.map +1 -1
  35. package/dist/node/index.js +125 -10
  36. package/dist/node/index.js.map +4 -4
  37. package/dist/node/index.mjs +125 -10
  38. package/dist/node/index.mjs.map +4 -4
  39. package/dist/node/node.sw.js +152 -0
  40. package/dist/node/utils/icons.d.ts +4 -5
  41. package/dist/node/utils/icons.d.ts.map +1 -1
  42. package/dist/node/utils/inline.d.ts +1 -1
  43. package/dist/node/utils/inline.d.ts.map +1 -1
  44. package/dist/node/utils/node.sw.js +152 -0
  45. package/dist/node/utils/session-storage.d.ts +22 -0
  46. package/dist/node/utils/session-storage.d.ts.map +1 -0
  47. package/dist/node/utils/sw.d.ts.map +1 -1
  48. package/dist/node/utils/tree-adapter.d.ts +5 -1
  49. package/dist/node/utils/tree-adapter.d.ts.map +1 -1
  50. package/dist/pulse-store/index.d.ts +16 -0
  51. package/dist/pulse-store/index.d.ts.map +1 -0
  52. package/dist/pulse-store/index.js +143 -0
  53. package/dist/pulse-store/index.js.map +7 -0
  54. package/dist/pulse-store/index.min.js +1 -0
  55. package/dist/pulse-store/index.min.js.map +1 -0
  56. package/dist/pulse-store/index.mjs +122 -0
  57. package/dist/pulse-store/index.mjs.map +7 -0
  58. package/dist/request/index.d.ts +11 -11
  59. package/dist/request/index.d.ts.map +1 -1
  60. package/dist/request/index.js +63 -84
  61. package/dist/request/index.js.map +2 -2
  62. package/dist/request/index.min.js +1 -0
  63. package/dist/request/index.min.js.map +1 -0
  64. package/dist/request/index.mjs +63 -84
  65. package/dist/request/index.mjs.map +2 -2
  66. package/dist/router/index.d.ts +36 -33
  67. package/dist/router/index.d.ts.map +1 -1
  68. package/dist/router/index.js +247 -96
  69. package/dist/router/index.js.map +3 -3
  70. package/dist/router/index.min.js +1 -0
  71. package/dist/router/index.min.js.map +1 -0
  72. package/dist/router/index.mjs +247 -96
  73. package/dist/router/index.mjs.map +3 -3
  74. package/dist/signals/index.d.ts +6 -0
  75. package/dist/signals/index.d.ts.map +1 -0
  76. package/dist/signals/index.js +92 -0
  77. package/dist/signals/index.js.map +7 -0
  78. package/dist/signals/index.min.js +1 -0
  79. package/dist/signals/index.min.js.map +1 -0
  80. package/dist/signals/index.mjs +71 -0
  81. package/dist/signals/index.mjs.map +7 -0
  82. package/dist/suspense/index.d.ts +6 -0
  83. package/dist/suspense/index.d.ts.map +1 -0
  84. package/dist/suspense/index.js +67 -0
  85. package/dist/suspense/index.js.map +7 -0
  86. package/dist/suspense/index.min.js +1 -0
  87. package/dist/suspense/index.min.js.map +1 -0
  88. package/dist/suspense/index.mjs +46 -0
  89. package/dist/suspense/index.mjs.map +7 -0
  90. package/dist/sw/index.min.js +1 -0
  91. package/dist/sw/index.min.js.map +1 -0
  92. package/dist/translate/index.d.ts +19 -0
  93. package/dist/translate/index.d.ts.map +1 -0
  94. package/dist/translate/index.js +150 -0
  95. package/dist/translate/index.js.map +7 -0
  96. package/dist/translate/index.min.js +1 -0
  97. package/dist/translate/index.min.js.map +1 -0
  98. package/dist/translate/index.mjs +129 -0
  99. package/dist/translate/index.mjs.map +7 -0
  100. package/dist/tsconfig.tsbuildinfo +1 -1
  101. package/dist/utils/deep-freeze.d.ts +3 -0
  102. package/dist/utils/deep-freeze.d.ts.map +1 -0
  103. package/dist/utils/getter-setter.d.ts +3 -0
  104. package/dist/utils/getter-setter.d.ts.map +1 -0
  105. package/dist/utils/has-changed.d.ts +2 -0
  106. package/dist/utils/has-changed.d.ts.map +1 -0
  107. package/dist/utils/index.d.ts +4 -0
  108. package/dist/utils/index.d.ts.map +1 -0
  109. package/dist/utils/index.js +138 -0
  110. package/dist/utils/index.js.map +7 -0
  111. package/dist/utils/index.min.js +1 -0
  112. package/dist/utils/index.min.js.map +1 -0
  113. package/dist/utils/index.mjs +115 -0
  114. package/dist/utils/index.mjs.map +7 -0
  115. package/lib/flux-store/index.ts +312 -0
  116. package/lib/hooks/index.ts +39 -57
  117. package/lib/index.ts +135 -118
  118. package/lib/native-store/index.ts +106 -0
  119. package/lib/node/index.ts +3 -1
  120. package/lib/node/utils/icons.ts +4 -4
  121. package/lib/node/utils/inline.ts +2 -0
  122. package/lib/node/utils/node.sw.js +152 -0
  123. package/lib/node/utils/session-storage.ts +117 -0
  124. package/lib/node/utils/sw.ts +34 -10
  125. package/lib/node/utils/tree-adapter.ts +19 -1
  126. package/lib/pulse-store/index.ts +188 -0
  127. package/lib/request/index.ts +92 -122
  128. package/lib/router/index.ts +353 -164
  129. package/lib/signals/index.ts +98 -0
  130. package/lib/suspense/index.ts +57 -0
  131. package/lib/translate/index.ts +156 -0
  132. package/lib/utils/deep-freeze.ts +54 -0
  133. package/lib/utils/getter-setter.ts +40 -0
  134. package/lib/utils/has-changed.ts +43 -0
  135. package/lib/utils/index.ts +3 -0
  136. package/package.json +40 -57
  137. package/tsconfig.json +5 -4
  138. package/dist/dataset/index.d.ts +0 -24
  139. package/dist/dataset/index.d.ts.map +0 -1
  140. package/dist/dataset/index.js +0 -178
  141. package/dist/dataset/index.js.map +0 -7
  142. package/dist/dataset/index.mjs +0 -157
  143. package/dist/dataset/index.mjs.map +0 -7
  144. package/dist/node/node.sw.tpl +0 -133
  145. package/dist/node/utils/node.sw.tpl +0 -133
  146. package/dist/proxy-signal/index.d.ts +0 -23
  147. package/dist/proxy-signal/index.d.ts.map +0 -1
  148. package/dist/proxy-signal/index.js +0 -138
  149. package/dist/proxy-signal/index.js.map +0 -7
  150. package/dist/proxy-signal/index.mjs +0 -117
  151. package/dist/proxy-signal/index.mjs.map +0 -7
  152. package/dist/signal/index.d.ts +0 -9
  153. package/dist/signal/index.d.ts.map +0 -1
  154. package/dist/signal/index.js +0 -76
  155. package/dist/signal/index.js.map +0 -7
  156. package/dist/signal/index.mjs +0 -55
  157. package/dist/signal/index.mjs.map +0 -7
  158. package/dist/store/index.d.ts +0 -16
  159. package/dist/store/index.d.ts.map +0 -1
  160. package/dist/store/index.js +0 -93
  161. package/dist/store/index.js.map +0 -7
  162. package/dist/store/index.mjs +0 -72
  163. package/dist/store/index.mjs.map +0 -7
  164. package/lib/dataset/index.ts +0 -193
  165. package/lib/node/utils/node.sw.tpl +0 -133
  166. package/lib/proxy-signal/index.ts +0 -187
  167. package/lib/signal/index.ts +0 -86
  168. package/lib/store/index.ts +0 -101
package/lib/index.ts CHANGED
@@ -1,25 +1,25 @@
1
- /* eslint-disable sonarjs/cognitive-complexity */
1
+ /* eslint-disable */
2
2
  declare global {
3
- // eslint-disable-next-line vars-on-top, no-var, no-unused-vars
4
3
  var document: Document;
5
- // eslint-disable-next-line no-unused-vars
6
4
  namespace JSX {
7
- // eslint-disable-next-line no-unused-vars, no-use-before-define
8
5
  interface IntrinsicElements extends DefaultRecord {}
6
+ type Element = ReturnType<
7
+ typeof v | ((...args: any) => string | number | null | undefined | boolean | Promise<any>)
8
+ >;
9
+ type ComponentReturnType = string | number | null | undefined | boolean | Element | Element[];
9
10
  }
10
11
  }
11
12
 
12
13
  interface DefaultRecord extends Record<string | number | symbol, any> {}
13
14
 
14
- export interface VnodeProperties extends DefaultRecord {
15
+ export interface Properties extends DefaultRecord {
15
16
  key?: string | number;
16
17
  }
17
18
 
18
19
  export interface DomElement extends Element, DefaultRecord {}
19
20
 
20
21
  export interface Component extends DefaultRecord {
21
- // eslint-disable-next-line no-unused-vars, no-use-before-define
22
- (props: VnodeProperties, children: any[]): Vnode | any;
22
+ (props: Properties, children: any[]): Vnode | any;
23
23
  }
24
24
 
25
25
  export interface POJOComponent extends DefaultRecord {
@@ -28,32 +28,24 @@ export interface POJOComponent extends DefaultRecord {
28
28
 
29
29
  export type ValyrianComponent = Component | POJOComponent;
30
30
 
31
- // eslint-disable-next-line no-use-before-define
32
31
  export interface VnodeComponentInterface extends Vnode {
33
32
  tag: ValyrianComponent;
34
33
  }
35
34
 
36
- // eslint-disable-next-line no-use-before-define
37
35
  export interface Children extends Array<Vnode | VnodeComponentInterface | ValyrianComponent | any> {}
38
36
 
39
37
  export interface Directive {
40
- // eslint-disable-next-line no-unused-vars, no-use-before-define
41
- (value: any, vnode: VnodeWithDom, oldProps: VnodeProperties | null): void | boolean;
38
+ (value: any, vnode: VnodeWithDom, oldProps: Properties | null): false | void | any;
42
39
  }
43
40
 
44
41
  export const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node);
45
42
 
46
43
  export class Vnode {
47
44
  constructor(
48
- // eslint-disable-next-line no-unused-vars
49
45
  public tag: string | Component | POJOComponent,
50
- // eslint-disable-next-line no-unused-vars
51
- public props: null | VnodeProperties,
52
- // eslint-disable-next-line no-unused-vars
46
+ public props: null | Properties,
53
47
  public children: Children,
54
- // eslint-disable-next-line no-unused-vars
55
48
  public dom?: DomElement,
56
- // eslint-disable-next-line no-unused-vars
57
49
  public isSVG?: boolean
58
50
  ) {}
59
51
  }
@@ -61,31 +53,34 @@ export class Vnode {
61
53
  export interface VnodeWithDom extends Vnode {
62
54
  tag: string;
63
55
  dom: DomElement;
64
- props: VnodeProperties;
56
+ props: Properties;
65
57
  }
66
58
 
59
+ export const isPOJOComponent = (component: unknown): component is POJOComponent =>
60
+ Boolean(component && typeof component === "object" && "view" in component);
61
+
67
62
  export const isComponent = (component: unknown): component is Component =>
68
- Boolean(typeof component === "function" || (component && typeof component === "object" && "view" in component));
63
+ Boolean(typeof component === "function" || isPOJOComponent(component));
69
64
  export const isVnode = (object?: unknown): object is Vnode => object instanceof Vnode;
70
65
 
71
66
  export const isVnodeComponent = (object?: unknown): object is VnodeComponentInterface => {
72
67
  return isVnode(object) && isComponent(object.tag);
73
68
  };
74
69
 
75
- export function v(tagOrComponent: string | Component, props: VnodeProperties, ...children: Children) {
70
+ export function v(tagOrComponent: string | ValyrianComponent, props: Properties | null, ...children: Children) {
76
71
  return new Vnode(tagOrComponent, props, children);
77
72
  }
78
73
 
79
- v.fragment = (_: VnodeProperties, ...children: Children) => children;
74
+ v.fragment = (_: Properties, ...children: Children) => children;
80
75
 
81
- export function domToVnode(dom: any): VnodeWithDom | void {
76
+ export function hidrateDomToVnode(dom: any): VnodeWithDom | void {
82
77
  if (dom.nodeType === 3) {
83
78
  return dom.nodeValue;
84
79
  }
85
80
 
86
81
  if (dom.nodeType === 1) {
87
82
  const tag = dom.nodeName.toLowerCase();
88
- const props = {} as VnodeProperties;
83
+ const props = {} as Properties;
89
84
  const children = [] as Children;
90
85
 
91
86
  for (let i = 0, l = dom.childNodes.length; i < l; i++) {
@@ -93,7 +88,7 @@ export function domToVnode(dom: any): VnodeWithDom | void {
93
88
  if (childDom.nodeType === 3) {
94
89
  children.push(childDom.nodeValue);
95
90
  } else if (childDom.nodeType === 1) {
96
- const childVnode = domToVnode(childDom);
91
+ const childVnode = hidrateDomToVnode(childDom);
97
92
  children.push(childVnode);
98
93
  }
99
94
  }
@@ -104,14 +99,17 @@ export function domToVnode(dom: any): VnodeWithDom | void {
104
99
  props[attr.nodeName] = attr.nodeValue;
105
100
  }
106
101
 
107
- return new Vnode(tag, props, children, dom, tag === "svg") as VnodeWithDom;
102
+ const vnode = new Vnode(tag, props, children);
103
+ vnode.dom = dom;
104
+ vnode.isSVG = tag === "svg";
105
+ return vnode as VnodeWithDom;
108
106
  }
109
107
  }
110
108
 
111
109
  export function trust(htmlString: string) {
112
110
  const div = document.createElement("div");
113
111
  div.innerHTML = htmlString.trim();
114
- return Array.from(div.childNodes).map(domToVnode);
112
+ return Array.from(div.childNodes).map(hidrateDomToVnode);
115
113
  }
116
114
 
117
115
  let mainComponent: VnodeComponentInterface | null = null;
@@ -155,24 +153,17 @@ const callSet = (set: Set<Function>) => {
155
153
  set.clear();
156
154
  };
157
155
 
158
- const handleVIf = (shouldRender: boolean): Directive => {
159
- return (value, vnode) => {
160
- const bool = shouldRender !== Boolean(value);
161
- if (bool) {
156
+ export const directives: Record<string, Directive> = {
157
+ "v-if": (value, vnode) => {
158
+ if (!Boolean(value)) {
162
159
  const parentNode = vnode.dom?.parentNode;
163
160
  if (parentNode) {
164
- const newdom = document.createTextNode("");
165
- parentNode.replaceChild(newdom, vnode.dom);
161
+ parentNode.replaceChild(document.createTextNode(""), vnode.dom);
166
162
  }
167
163
 
168
164
  return false;
169
165
  }
170
- };
171
- };
172
-
173
- export const directives: Record<string, Directive> = {
174
- "v-if": handleVIf(true),
175
- "v-unless": handleVIf(false),
166
+ },
176
167
 
177
168
  "v-show": (value, vnode) => {
178
169
  const bool = Boolean(value);
@@ -184,19 +175,23 @@ export const directives: Record<string, Directive> = {
184
175
  },
185
176
 
186
177
  "v-html": (value, vnode) => {
187
- vnode.children = [trust(value as string)];
178
+ vnode.children = trust(value as string);
188
179
  },
189
180
 
190
181
  // The "v-model" directive binds the value of an input element to a model property
191
- "v-model": (val, vnode) => {
182
+ "v-model": (model, vnode) => {
192
183
  // eslint-disable-next-line prefer-const
193
- let [model, property, event]: any[] = val as any[];
184
+ if ("name" in vnode.props === false) {
185
+ return;
186
+ }
187
+
194
188
  let value;
189
+ const property = vnode.props.name;
190
+ let event = "oninput";
191
+
195
192
  // This function updates the model property when the input element's value changes
196
193
  let handler = (e: Event) => (model[property] = (e.target as DomElement & Record<string, any>).value);
197
194
  if (vnode.tag === "input") {
198
- // If the element is an input, use the "input" event by default
199
- event = event || "oninput";
200
195
  // Depending on the type of input element, use a different handler function
201
196
  switch (vnode.props.type) {
202
197
  case "checkbox": {
@@ -247,7 +242,7 @@ export const directives: Record<string, Directive> = {
247
242
  }
248
243
  } else if (vnode.tag === "select") {
249
244
  // If the element is a select element, use the "click" event by default
250
- event = event || "onclick";
245
+ event = "onclick";
251
246
  if (vnode.props.multiple) {
252
247
  // If the select element allows multiple selections, update the model property with an array of selected values
253
248
  handler = (e: Event & Record<string, any>) => {
@@ -283,8 +278,6 @@ export const directives: Record<string, Directive> = {
283
278
  });
284
279
  }
285
280
  } else if (vnode.tag === "textarea") {
286
- // If the element is a textarea, use the "input" event by default
287
- event = event || "oninput";
288
281
  // Set the textarea's content to the value of the model property
289
282
  vnode.children = [model[property]];
290
283
  }
@@ -380,6 +373,10 @@ export function directive(name: string, directive: Directive) {
380
373
  reservedProps.add(directiveName);
381
374
  }
382
375
 
376
+ export function setPropNameReserved(name: string) {
377
+ reservedProps.add(name);
378
+ }
379
+
383
380
  const eventListenerNames = new Set<string>();
384
381
 
385
382
  function eventListener(e: Event) {
@@ -408,6 +405,7 @@ function sharedSetAttribute(name: string, value: any, newVnode: VnodeWithDom): v
408
405
  const newVnodeDom = newVnode.dom;
409
406
  if (typeof value === "function") {
410
407
  if (!eventListenerNames.has(name)) {
408
+ // We attach the delegated event listener to the main vnode dom element, which is the root of the component
411
409
  (mainVnode as VnodeWithDom).dom.addEventListener(name.slice(2), eventListener);
412
410
  eventListenerNames.add(name);
413
411
  }
@@ -433,87 +431,103 @@ export function setAttribute(name: string, value: any, newVnode: VnodeWithDom):
433
431
  }
434
432
  }
435
433
 
436
- function removeAttributes(vnode: VnodeWithDom, oldProps: VnodeProperties | null): void {
437
- if (!oldProps) {
438
- return;
439
- }
440
-
441
- const vnodeDom = vnode.dom;
442
- const vnodeProps = vnode.props;
443
-
444
- for (const name in oldProps) {
445
- if (name in vnodeProps === false && !eventListenerNames.has(name) && !reservedProps.has(name)) {
446
- if (name in vnodeDom) {
447
- vnodeDom[name] = null;
448
- } else {
449
- vnodeDom.removeAttribute(name);
434
+ export function updateAttributes(newVnode: VnodeWithDom, oldProps: Properties | null): void {
435
+ const vnodeDom = newVnode.dom;
436
+ const vnodeProps = newVnode.props;
437
+
438
+ if (oldProps) {
439
+ for (const name in oldProps) {
440
+ if (name in vnodeProps === false && !eventListenerNames.has(name) && !reservedProps.has(name)) {
441
+ if (name in vnodeDom) {
442
+ vnodeDom[name] = null;
443
+ } else {
444
+ vnodeDom.removeAttribute(name);
445
+ }
450
446
  }
451
447
  }
452
448
  }
453
- }
454
449
 
455
- function addProperties(vnode: VnodeWithDom, oldProps: VnodeProperties | null) {
456
- const vnodeProps = vnode.props;
457
450
  for (const name in vnodeProps) {
458
451
  if (directives[name]) {
459
- if (directives[name](vnodeProps[name], vnode, oldProps) === false) {
452
+ if (directives[name](vnodeProps[name], newVnode, oldProps) === false) {
460
453
  break;
461
454
  }
462
455
  continue;
463
456
  }
464
457
 
465
- if (reservedProps.has(name)) {
466
- continue;
458
+ if (!reservedProps.has(name)) {
459
+ sharedSetAttribute(name, vnodeProps[name], newVnode);
467
460
  }
468
-
469
- sharedSetAttribute(name, vnodeProps[name], vnode);
470
461
  }
471
462
  }
472
463
 
473
- export function updateAttributes(newVnode: VnodeWithDom, oldProps: VnodeProperties | null): void {
474
- removeAttributes(newVnode, oldProps);
475
- addProperties(newVnode, oldProps);
476
- }
477
-
478
464
  export function createElement(tag: string, isSVG: boolean): DomElement {
479
465
  return isSVG
480
466
  ? document.createElementNS("http://www.w3.org/2000/svg", tag)
481
467
  : (document.createElement(tag) as DomElement);
482
468
  }
483
469
 
484
- function flatTree(newVnode: VnodeWithDom, children: Children) {
470
+ function flatTree(newVnode: VnodeWithDom) {
485
471
  current.vnode = newVnode;
472
+
473
+ if ("v-for" in newVnode.props) {
474
+ const children = [];
475
+ const set = newVnode.props["v-for"];
476
+ const l = set.length;
477
+ const callback = newVnode.children[0];
478
+
479
+ for (let i = 0; i < l; i++) {
480
+ const newChild = callback(set[i], i);
481
+ if (newChild instanceof Vnode) {
482
+ newChild.props = newChild.props || {};
483
+ newChild.isSVG = newVnode.isSVG || newChild.tag === "svg";
484
+ }
485
+ children[i] = newChild;
486
+ }
487
+
488
+ return children;
489
+ }
490
+
486
491
  let i = 0;
492
+ const originalChildren = newVnode.children;
493
+ let children = originalChildren;
487
494
 
488
495
  while (i < children.length) {
489
496
  const newChild = children[i];
490
497
 
491
498
  if (newChild == null) {
499
+ if (children === originalChildren) {
500
+ children = [...originalChildren];
501
+ }
492
502
  children.splice(i, 1);
493
503
  continue;
494
504
  }
495
505
 
496
506
  if (Array.isArray(newChild)) {
507
+ if (children === originalChildren) {
508
+ children = [...originalChildren];
509
+ }
497
510
  children.splice(i, 1, ...newChild);
498
511
  continue;
499
512
  }
500
513
 
501
514
  if (newChild instanceof Vnode) {
502
- if (newChild.props === null) {
503
- newChild.props = {};
504
- }
515
+ newChild.props = newChild.props || {};
516
+ newChild.isSVG = newVnode.isSVG || newChild.tag === "svg";
505
517
 
506
518
  if (typeof newChild.tag !== "string") {
507
- const component = newChild.tag;
519
+ if (children === originalChildren) {
520
+ children = [...originalChildren];
521
+ }
508
522
 
509
- current.component = newChild.tag;
510
- children[i] = ("view" in component ? component.view : component).bind(component)(
523
+ const component = (current.component = newChild.tag);
524
+
525
+ children[i] = (isPOJOComponent(component) ? component.view : component).bind(component)(
511
526
  newChild.props,
512
527
  newChild.children
513
528
  );
529
+
514
530
  continue;
515
- } else {
516
- newChild.isSVG = newVnode.isSVG || newChild.tag === "svg";
517
531
  }
518
532
  }
519
533
 
@@ -523,22 +537,6 @@ function flatTree(newVnode: VnodeWithDom, children: Children) {
523
537
  return children;
524
538
  }
525
539
 
526
- function handleVFor(newVnode: VnodeWithDom) {
527
- if ("v-for" in newVnode.props) {
528
- const set = newVnode.props["v-for"];
529
- const children = [];
530
- const callback = newVnode.children[0];
531
- children.length = set.length;
532
-
533
- for (let i = 0, l = set.length; i < l; i++) {
534
- children[i] = callback(set[i], i);
535
- }
536
-
537
- return children;
538
- }
539
- return [...newVnode.children];
540
- }
541
-
542
540
  function createNewElement(newChild: VnodeWithDom, newVnode: VnodeWithDom, oldChild: DomElement | null) {
543
541
  const dom = createElement(newChild.tag, newChild.isSVG as boolean);
544
542
  if (oldChild) {
@@ -547,14 +545,14 @@ function createNewElement(newChild: VnodeWithDom, newVnode: VnodeWithDom, oldChi
547
545
  newVnode.dom.appendChild(dom);
548
546
  }
549
547
  newChild.dom = dom;
550
- addProperties(newChild, null);
548
+ updateAttributes(newChild, null);
551
549
  newChild.dom.props = newChild.props;
552
550
  if ("v-text" in newChild.props) {
553
551
  newChild.dom.textContent = newChild.props["v-text"];
554
552
  return;
555
553
  }
556
554
 
557
- const children = flatTree(newChild, handleVFor(newChild));
555
+ const children = flatTree(newChild);
558
556
  if (children.length === 0) {
559
557
  newChild.dom.textContent = "";
560
558
  return;
@@ -625,8 +623,8 @@ function patchKeyed(newVnode: VnodeWithDom, children: Children) {
625
623
  }
626
624
 
627
625
  // eslint-disable-next-line complexity
628
- export function patch(newVnode: VnodeWithDom): void {
629
- const children = flatTree(newVnode, handleVFor(newVnode));
626
+ function patch(newVnode: VnodeWithDom): void {
627
+ const children = flatTree(newVnode);
630
628
 
631
629
  const dom = newVnode.dom;
632
630
 
@@ -661,23 +659,29 @@ export function patch(newVnode: VnodeWithDom): void {
661
659
  }
662
660
 
663
661
  for (let i = 0; i < childrenLength; i++) {
662
+ const newChild = children[i] as VnodeWithDom;
663
+ const isText = newChild instanceof Vnode === false;
664
664
  const oldChild = oldDomChildren[i];
665
- const newChild = children[i];
666
665
 
667
666
  if (!oldChild) {
668
- createNewElement(newChild, newVnode, null);
667
+ if (isText) {
668
+ newVnode.dom.appendChild(document.createTextNode(newChild as unknown as string));
669
+ continue;
670
+ }
671
+
672
+ createNewElement(newChild as VnodeWithDom, newVnode, null);
669
673
  continue;
670
674
  }
671
675
 
672
- if (newChild instanceof Vnode === false) {
676
+ if (isText) {
673
677
  if (oldChild.nodeType !== 3) {
674
- newVnode.dom.replaceChild(document.createTextNode(newChild), oldChild);
678
+ newVnode.dom.replaceChild(document.createTextNode(newChild as unknown as string), oldChild);
675
679
  continue;
676
680
  }
677
681
 
678
682
  // eslint-disable-next-line eqeqeq
679
- if (oldChild.nodeValue != newChild) {
680
- oldChild.nodeValue = newChild;
683
+ if (oldChild.nodeValue != (newChild as unknown as string)) {
684
+ oldChild.nodeValue = newChild as unknown as string;
681
685
  }
682
686
  continue;
683
687
  }
@@ -700,7 +704,7 @@ export function patch(newVnode: VnodeWithDom): void {
700
704
  }
701
705
 
702
706
  newChild.dom = oldChild;
703
- updateAttributes(newChild as VnodeWithDom, oldChild.props || null);
707
+ updateAttributes(newChild, oldChild.props || null);
704
708
  oldChild.props = newChild.props;
705
709
  if ("v-text" in newChild.props) {
706
710
  // eslint-disable-next-line eqeqeq
@@ -725,16 +729,27 @@ export function updateVnode(vnode: VnodeWithDom): string | void {
725
729
  isMounted = true;
726
730
  current.vnode = null;
727
731
  current.component = null;
728
- if (isNodeJs) {
729
- return vnode.dom.innerHTML;
730
- }
731
732
  }
732
733
 
733
- export function update(): void | string {
734
+ export function update(): string {
734
735
  if (mainVnode) {
735
736
  mainVnode.children = [mainComponent];
736
- return updateVnode(mainVnode);
737
+ updateVnode(mainVnode as VnodeWithDom);
738
+ if (isNodeJs) {
739
+ return mainVnode.dom.innerHTML;
740
+ }
737
741
  }
742
+ return "";
743
+ }
744
+
745
+ let debouncedUpdateTimeout: any;
746
+
747
+ const clearDebouncedUpdateMethod = isNodeJs ? clearTimeout : cancelAnimationFrame;
748
+ const setDebouncedUpdateMethod = isNodeJs ? () => setTimeout(update, 5) : () => requestAnimationFrame(update);
749
+
750
+ export function debouncedUpdate() {
751
+ clearDebouncedUpdateMethod(debouncedUpdateTimeout);
752
+ debouncedUpdateTimeout = setDebouncedUpdateMethod();
738
753
  }
739
754
 
740
755
  export function unmount() {
@@ -755,20 +770,22 @@ export function unmount() {
755
770
  current.event = null;
756
771
  return result;
757
772
  }
773
+
774
+ return "";
758
775
  }
759
776
 
760
- export function mount(dom: string | DomElement, component: any) {
777
+ export function mount(dom: string | DomElement, component: ValyrianComponent | VnodeComponentInterface | any) {
761
778
  const container =
762
779
  typeof dom === "string" ? (isNodeJs ? createElement(dom, dom === "svg") : document.querySelector(dom)) : dom;
763
780
 
764
781
  if (isComponent(component)) {
765
- mainComponent = new Vnode(component, {}, []) as VnodeComponentInterface;
782
+ mainComponent = v(component, {}, []) as VnodeComponentInterface;
766
783
  } else if (isVnodeComponent(component)) {
767
784
  mainComponent = component;
768
785
  } else {
769
- mainComponent = new Vnode(() => component, {}, []) as VnodeComponentInterface;
786
+ mainComponent = v(() => component, {}, []) as VnodeComponentInterface;
770
787
  }
771
788
 
772
- mainVnode = domToVnode(container) as VnodeWithDom;
789
+ mainVnode = hidrateDomToVnode(container) as VnodeWithDom;
773
790
  return update();
774
791
  }
@@ -0,0 +1,106 @@
1
+ import { isNodeJs } from "valyrian.js";
2
+
3
+ /* eslint-disable no-console */
4
+ export enum StorageType {
5
+ // eslint-disable-next-line no-unused-vars
6
+ Session = "session",
7
+ // eslint-disable-next-line no-unused-vars
8
+ Local = "local"
9
+ }
10
+
11
+ export interface NativeStorageInterface {
12
+ state: Record<string, any>;
13
+ // eslint-disable-next-line no-unused-vars
14
+ set(key: string, value: any): void;
15
+ // eslint-disable-next-line no-unused-vars
16
+ get(key: string): any;
17
+ // eslint-disable-next-line no-unused-vars
18
+ delete(key: string): void;
19
+ load(): void;
20
+ clear(): void;
21
+ }
22
+
23
+ const ids = new Set<string>();
24
+
25
+ function getStorage(storageType: StorageType) {
26
+ if (isNodeJs && typeof localStorage === "undefined") {
27
+ throw new Error(
28
+ `localStorage and sessionStorage are not available in Node.js, to use it in your project, you need to "import "valyrian.js/node"`
29
+ );
30
+ }
31
+ return storageType === StorageType.Session ? sessionStorage : localStorage;
32
+ }
33
+
34
+ export function createNativeStore<T>(
35
+ key: string,
36
+ definition: Record<string, any> = {},
37
+ storageType: StorageType = StorageType.Local,
38
+ reuseIfExist = false
39
+ ): NativeStorageInterface & T {
40
+ const nativeStore = getStorage(storageType);
41
+
42
+ if (ids.has(key)) {
43
+ if (reuseIfExist) {
44
+ // eslint-disable-next-line no-console
45
+ console.warn(`Store with key ${key} already exists and will be reused`);
46
+ } else {
47
+ throw new Error(`Store with key ${key} already exists`);
48
+ }
49
+ }
50
+ ids.add(key);
51
+
52
+ const id = key;
53
+
54
+ const Store: NativeStorageInterface = {
55
+ state: {},
56
+ set(key, value) {
57
+ try {
58
+ this.state[key] = value;
59
+ nativeStore.setItem(id, JSON.stringify(this.state));
60
+ } catch (e) {
61
+ console.error("Error setting item in storage:", e);
62
+ }
63
+ },
64
+ get(key) {
65
+ if (Object.keys(this.state).length === 0) {
66
+ this.load();
67
+ }
68
+ return this.state[key];
69
+ },
70
+ delete(key) {
71
+ try {
72
+ Reflect.deleteProperty(this.state, key);
73
+ nativeStore.setItem(id, JSON.stringify(this.state));
74
+ } catch (e) {
75
+ console.error("Error deleting item in storage:", e);
76
+ }
77
+ },
78
+ load() {
79
+ try {
80
+ const state = nativeStore.getItem(id);
81
+ if (!state) {
82
+ this.state = {};
83
+ nativeStore.setItem(id, JSON.stringify(this.state));
84
+ return;
85
+ }
86
+ this.state = JSON.parse(state);
87
+ } catch (e) {
88
+ console.error("Error loading state from storage:", e);
89
+ this.state = {};
90
+ }
91
+ },
92
+ clear() {
93
+ try {
94
+ this.state = {};
95
+ nativeStore.removeItem(id);
96
+ } catch (e) {
97
+ console.error("Error clearing storage:", e);
98
+ }
99
+ },
100
+ ...definition
101
+ };
102
+
103
+ Store.load();
104
+
105
+ return Store as NativeStorageInterface & T;
106
+ }
package/lib/node/index.ts CHANGED
@@ -2,13 +2,15 @@ import { document, domToHtml, domToHyperscript, htmlToDom, htmlToHyperscript } f
2
2
  import { mount, unmount } from "valyrian.js";
3
3
 
4
4
  import FormData from "form-data";
5
- // import fetch from "node-fetch";
6
5
  import { icons } from "./utils/icons";
7
6
  import { inline } from "./utils/inline";
8
7
  import { sw } from "./utils/sw";
8
+ import { SessionStorage } from "./utils/session-storage";
9
9
 
10
10
  global.FormData = FormData as any;
11
11
  global.document = document as any;
12
+ global.sessionStorage = new SessionStorage();
13
+ global.localStorage = new SessionStorage();
12
14
 
13
15
  function render(...args: any[]) {
14
16
  const Component = () => args;
@@ -1,7 +1,7 @@
1
1
  import fs from "fs";
2
2
  import { htmlToHyperscript } from "./tree-adapter";
3
3
 
4
- interface IconsOptions {
4
+ export interface IconsOptions {
5
5
  iconsPath: string | null;
6
6
  linksViewPath: string | null;
7
7
  logging: boolean;
@@ -12,12 +12,12 @@ interface IconsOptions {
12
12
  appDescription?: string;
13
13
  developerName?: string;
14
14
  developerURL?: string;
15
- dir?: "auto" | "ltr" | "rtl";
15
+ dir?: "auto" | "ltr" | "rtl" | string;
16
16
  lang?: string;
17
17
  background?: string;
18
18
  theme_color?: string;
19
- display?: "browser" | "standalone";
20
- orientation?: "any" | "portrait" | "landscape";
19
+ display?: "browser" | "standalone" | string;
20
+ orientation?: "any" | "portrait" | "landscape" | string;
21
21
  start_url?: string;
22
22
  version?: string;
23
23
  icons: {
@@ -126,6 +126,8 @@ export async function inline(
126
126
  } else if (typeof file === "object" && "raw" in file) {
127
127
  return { map: null, ...file };
128
128
  }
129
+
130
+ throw new Error(`Unknown file type: ${file}`);
129
131
  }
130
132
 
131
133
  inline.uncss = async function (