valyrian.js 7.2.11 → 8.0.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.
Files changed (165) 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 +258 -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 +237 -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 +42 -75
  12. package/dist/hooks/index.js.map +2 -2
  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 +43 -76
  16. package/dist/hooks/index.mjs.map +2 -2
  17. package/dist/index.d.ts +52 -54
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +397 -328
  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 +397 -328
  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.map +1 -1
  34. package/dist/node/index.js +223 -86
  35. package/dist/node/index.js.map +4 -4
  36. package/dist/node/index.mjs +223 -86
  37. package/dist/node/index.mjs.map +4 -4
  38. package/dist/node/node.sw.js +152 -0
  39. package/dist/node/utils/inline.d.ts.map +1 -1
  40. package/dist/node/utils/node.sw.js +152 -0
  41. package/dist/node/utils/session-storage.d.ts +22 -0
  42. package/dist/node/utils/session-storage.d.ts.map +1 -0
  43. package/dist/node/utils/sw.d.ts.map +1 -1
  44. package/dist/node/utils/tree-adapter.d.ts +9 -0
  45. package/dist/node/utils/tree-adapter.d.ts.map +1 -1
  46. package/dist/pulse-store/index.d.ts +13 -0
  47. package/dist/pulse-store/index.d.ts.map +1 -0
  48. package/dist/pulse-store/index.js +143 -0
  49. package/dist/pulse-store/index.js.map +7 -0
  50. package/dist/pulse-store/index.min.js +1 -0
  51. package/dist/pulse-store/index.min.js.map +1 -0
  52. package/dist/pulse-store/index.mjs +122 -0
  53. package/dist/pulse-store/index.mjs.map +7 -0
  54. package/dist/request/index.d.ts.map +1 -1
  55. package/dist/request/index.js +68 -89
  56. package/dist/request/index.js.map +2 -2
  57. package/dist/request/index.min.js +1 -0
  58. package/dist/request/index.min.js.map +1 -0
  59. package/dist/request/index.mjs +68 -89
  60. package/dist/request/index.mjs.map +2 -2
  61. package/dist/router/index.d.ts +32 -31
  62. package/dist/router/index.d.ts.map +1 -1
  63. package/dist/router/index.js +256 -104
  64. package/dist/router/index.js.map +3 -3
  65. package/dist/router/index.min.js +1 -0
  66. package/dist/router/index.min.js.map +1 -0
  67. package/dist/router/index.mjs +256 -104
  68. package/dist/router/index.mjs.map +3 -3
  69. package/dist/signals/index.d.ts +6 -0
  70. package/dist/signals/index.d.ts.map +1 -0
  71. package/dist/signals/index.js +92 -0
  72. package/dist/signals/index.js.map +7 -0
  73. package/dist/signals/index.min.js +1 -0
  74. package/dist/signals/index.min.js.map +1 -0
  75. package/dist/signals/index.mjs +71 -0
  76. package/dist/signals/index.mjs.map +7 -0
  77. package/dist/suspense/index.d.ts +6 -0
  78. package/dist/suspense/index.d.ts.map +1 -0
  79. package/dist/suspense/index.js +67 -0
  80. package/dist/suspense/index.js.map +7 -0
  81. package/dist/suspense/index.min.js +1 -0
  82. package/dist/suspense/index.min.js.map +1 -0
  83. package/dist/suspense/index.mjs +46 -0
  84. package/dist/suspense/index.mjs.map +7 -0
  85. package/dist/sw/index.min.js +1 -0
  86. package/dist/sw/index.min.js.map +1 -0
  87. package/dist/translate/index.d.ts +19 -0
  88. package/dist/translate/index.d.ts.map +1 -0
  89. package/dist/translate/index.js +150 -0
  90. package/dist/translate/index.js.map +7 -0
  91. package/dist/translate/index.min.js +1 -0
  92. package/dist/translate/index.min.js.map +1 -0
  93. package/dist/translate/index.mjs +129 -0
  94. package/dist/translate/index.mjs.map +7 -0
  95. package/dist/tsconfig.tsbuildinfo +1 -1
  96. package/dist/utils/deep-freeze.d.ts +3 -0
  97. package/dist/utils/deep-freeze.d.ts.map +1 -0
  98. package/dist/utils/getter-setter.d.ts +3 -0
  99. package/dist/utils/getter-setter.d.ts.map +1 -0
  100. package/dist/utils/has-changed.d.ts +2 -0
  101. package/dist/utils/has-changed.d.ts.map +1 -0
  102. package/dist/utils/index.d.ts +4 -0
  103. package/dist/utils/index.d.ts.map +1 -0
  104. package/dist/utils/index.js +138 -0
  105. package/dist/utils/index.js.map +7 -0
  106. package/dist/utils/index.min.js +1 -0
  107. package/dist/utils/index.min.js.map +1 -0
  108. package/dist/utils/index.mjs +115 -0
  109. package/dist/utils/index.mjs.map +7 -0
  110. package/lib/flux-store/index.ts +301 -0
  111. package/lib/hooks/index.ts +52 -101
  112. package/lib/index.ts +479 -719
  113. package/lib/native-store/index.ts +106 -0
  114. package/lib/node/index.ts +5 -3
  115. package/lib/node/utils/icons.ts +5 -5
  116. package/lib/node/utils/inline.ts +17 -17
  117. package/lib/node/utils/node.sw.js +152 -0
  118. package/lib/node/utils/session-storage.ts +117 -0
  119. package/lib/node/utils/sw.ts +35 -11
  120. package/lib/node/utils/tree-adapter.ts +99 -52
  121. package/lib/pulse-store/index.ts +181 -0
  122. package/lib/request/index.ts +86 -116
  123. package/lib/router/index.ts +358 -170
  124. package/lib/signals/index.ts +98 -0
  125. package/lib/suspense/index.ts +57 -0
  126. package/lib/translate/index.ts +156 -0
  127. package/lib/utils/deep-freeze.ts +54 -0
  128. package/lib/utils/getter-setter.ts +40 -0
  129. package/lib/utils/has-changed.ts +43 -0
  130. package/lib/utils/index.ts +3 -0
  131. package/package.json +38 -50
  132. package/tsconfig.json +1 -1
  133. package/dist/dataset/index.d.ts +0 -24
  134. package/dist/dataset/index.d.ts.map +0 -1
  135. package/dist/dataset/index.js +0 -178
  136. package/dist/dataset/index.js.map +0 -7
  137. package/dist/dataset/index.mjs +0 -157
  138. package/dist/dataset/index.mjs.map +0 -7
  139. package/dist/node/node.sw.tpl +0 -133
  140. package/dist/node/utils/node.sw.tpl +0 -133
  141. package/dist/proxy-signal/index.d.ts +0 -23
  142. package/dist/proxy-signal/index.d.ts.map +0 -1
  143. package/dist/proxy-signal/index.js +0 -138
  144. package/dist/proxy-signal/index.js.map +0 -7
  145. package/dist/proxy-signal/index.mjs +0 -117
  146. package/dist/proxy-signal/index.mjs.map +0 -7
  147. package/dist/signal/index.d.ts +0 -20
  148. package/dist/signal/index.d.ts.map +0 -1
  149. package/dist/signal/index.js +0 -95
  150. package/dist/signal/index.js.map +0 -7
  151. package/dist/signal/index.mjs +0 -74
  152. package/dist/signal/index.mjs.map +0 -7
  153. package/dist/store/index.d.ts +0 -16
  154. package/dist/store/index.d.ts.map +0 -1
  155. package/dist/store/index.js +0 -93
  156. package/dist/store/index.js.map +0 -7
  157. package/dist/store/index.mjs +0 -72
  158. package/dist/store/index.mjs.map +0 -7
  159. package/lib/dataset/index.ts +0 -193
  160. package/lib/index.d.ts +0 -0
  161. package/lib/interfaces.ts.bak +0 -141
  162. package/lib/node/utils/node.sw.tpl +0 -133
  163. package/lib/proxy-signal/index.ts +0 -187
  164. package/lib/signal/index.ts +0 -161
  165. package/lib/store/index.ts +0 -101
@@ -0,0 +1,301 @@
1
+ import { debouncedUpdate } from "valyrian.js";
2
+ import { deepCloneUnfreeze, deepFreeze } from "valyrian.js/utils";
3
+
4
+ interface StoreOptions {
5
+ state?: Record<string, any> | (() => Record<string, any>);
6
+ // eslint-disable-next-line no-unused-vars
7
+ mutations?: Record<string, (state: Record<string, any>, ...args: any[]) => void>;
8
+ // eslint-disable-next-line no-unused-vars, no-use-before-define
9
+ actions?: Record<string, (store: FluxStore, ...args: any[]) => any>;
10
+ getters?: Record<
11
+ string,
12
+ // eslint-disable-next-line no-unused-vars
13
+ (state: Record<string, any>, getters: Record<string, any>, globalState?: any, globalGetters?: any) => any
14
+ >;
15
+ modules?: Record<string, StoreOptions>;
16
+ shouldFreeze?: boolean;
17
+ namespace?: string;
18
+ // eslint-disable-next-line no-use-before-define
19
+ rootStore?: FluxStore;
20
+ }
21
+
22
+ // This is the store entity
23
+ export class FluxStore {
24
+ public state: Record<string, any>;
25
+ public getters: Record<string, any>;
26
+ private init: {
27
+ frozen: boolean;
28
+ plugins: Function[];
29
+ // eslint-disable-next-line no-use-before-define
30
+ modules: Record<string, FluxStore>;
31
+ childModuleNamespaces: string[];
32
+ listeners: Record<string, Function[]>;
33
+ getters: StoreOptions["getters"];
34
+ mutations: StoreOptions["mutations"];
35
+ actions: StoreOptions["actions"];
36
+ };
37
+ // eslint-disable-next-line no-use-before-define
38
+ public rootStore: FluxStore | null;
39
+ public namespace: string | null;
40
+
41
+ // eslint-disable-next-line sonarjs/cognitive-complexity
42
+ constructor({
43
+ state = {},
44
+ mutations = {},
45
+ actions = {},
46
+ getters = {},
47
+ modules = {},
48
+ shouldFreeze = true,
49
+ namespace,
50
+ rootStore
51
+ }: StoreOptions = {}) {
52
+ // Initialize the localState for this store
53
+ const localState = typeof state === "function" ? state() : state;
54
+
55
+ // We create a proxy for the state
56
+ this.state = new Proxy(localState || {}, {
57
+ // Every time we try to access a property from the state we try to deep freeze the property
58
+ // to prevent direct modifications to the state
59
+ get: (state, prop: string) => {
60
+ if ((this.rootStore || this).init.modules[prop]) {
61
+ return state[prop];
62
+ }
63
+ if (shouldFreeze) {
64
+ // We are accessing a property from outside the store
65
+ if (this.init.frozen) {
66
+ return deepFreeze(state[prop]);
67
+ }
68
+
69
+ // We are accessing a property from inside the store
70
+ // So we need to unfreeze the state
71
+ const newState = deepCloneUnfreeze(state);
72
+ for (const key of Reflect.ownKeys(newState)) {
73
+ localState[key] = newState[key];
74
+ }
75
+ }
76
+ return state[prop];
77
+ },
78
+ // If the user tries to set directly it will throw an error, only if we have unfrozen the state via commit
79
+ // this will proceed to set the value
80
+ set: (state, prop: string, value: any) => {
81
+ this.isUnfrozen();
82
+ const old = state[prop];
83
+ state[prop] = value;
84
+ if (this.namespace) {
85
+ prop = `${this.namespace}.${prop}`;
86
+ }
87
+ (this.rootStore || this).trigger("set", prop, value, old);
88
+ return true;
89
+ },
90
+ // If the user tries to delete directly it will throw an error, only if we have unfrozen the state via commit
91
+ // this will proceed to delete the property
92
+ deleteProperty: (state, prop: string) => {
93
+ this.isUnfrozen();
94
+ const old = state[prop];
95
+ Reflect.deleteProperty(state, prop);
96
+ if (this.namespace) {
97
+ prop = `${this.namespace}.${prop}`;
98
+ }
99
+ (this.rootStore || this).trigger("delete", prop, old);
100
+ return true;
101
+ }
102
+ });
103
+
104
+ // If this is a store been attached to another store
105
+ // this will have the rootStore for future reference
106
+ this.rootStore = rootStore || null;
107
+
108
+ // If this is a store been attached to another store
109
+ // this will have the namespace attached
110
+ this.namespace = namespace || null;
111
+
112
+ // We initialize the store with the initial values
113
+ this.init = {
114
+ frozen: true,
115
+ plugins: [],
116
+ modules: {},
117
+ childModuleNamespaces: Object.keys(modules || {}),
118
+ listeners: {
119
+ set: [],
120
+ delete: [],
121
+ beforecommit: [],
122
+ commit: [],
123
+ beforedispatch: [],
124
+ dispatch: [],
125
+ getter: [],
126
+ addlistener: [],
127
+ removelistener: [],
128
+ plugin: [],
129
+ registerModule: [],
130
+ unregisterModule: []
131
+ },
132
+ getters: getters || {},
133
+ mutations: mutations || {},
134
+ actions: actions || {}
135
+ };
136
+
137
+ // We create a proxy for the getters
138
+ this.getters = new Proxy(getters || {}, {
139
+ // When we try to get a property of the getter we will call the original
140
+ // getter method passing the state as first argument and the other getters as second
141
+ // if we try to get a non existent getter it will fail silently as if
142
+ // we were trying to get an undefined property
143
+ get: (getters, getter: string) => {
144
+ try {
145
+ const { store, key } = this.getStore(this, getter);
146
+ if (store instanceof FluxStore && store.init.getters![key]) {
147
+ const value = store.init.getters![key](store.state, store.getters, this.state, this.getters);
148
+ if (this.namespace) {
149
+ getter = `${this.namespace}.${getter}`;
150
+ }
151
+ (this.rootStore || this).trigger("getter", getter, value);
152
+ return value;
153
+ }
154
+ } catch (error) {
155
+ return;
156
+ }
157
+ }
158
+ });
159
+
160
+ // Finally we attach the initial modules
161
+ if (modules) {
162
+ Object.keys(modules).forEach((namespace) => {
163
+ const n = this.namespace ? `${this.namespace}.${namespace}` : namespace;
164
+ (this.rootStore || this).registerModule(n, modules[namespace]);
165
+ });
166
+ }
167
+ }
168
+
169
+ private keyExists(objectname: string, object: Record<string, any>, key: string) {
170
+ if (!object[key]) {
171
+ throw new Error(`The ${objectname} "${key}" does not exists.`);
172
+ }
173
+ }
174
+
175
+ private isFunction(type: string, callback: Function) {
176
+ if (typeof callback !== "function") {
177
+ throw new Error(`You need to provide a valid function as ${type}.`);
178
+ }
179
+ }
180
+
181
+ // Giving a dot based namespace this method will be used to find the module to be called
182
+ private getStore(store: FluxStore, namespace: string) {
183
+ let key = namespace;
184
+ if (key.indexOf(".") > -1) {
185
+ const parts = key.split(".");
186
+ key = parts.pop()!;
187
+ const moduleName = parts.join(".");
188
+ this.keyExists("module", store.init.modules, moduleName);
189
+ store = store.init.modules[moduleName];
190
+ }
191
+ return {
192
+ store,
193
+ key
194
+ };
195
+ }
196
+
197
+ private isUnfrozen() {
198
+ if (this.init.frozen) {
199
+ throw new Error("You need to commit a mutation to change the state");
200
+ }
201
+ }
202
+
203
+ // This method unfroze the state and process a mutation
204
+ public commit(mutation: string, ...args: any[]) {
205
+ const { store, key } = this.getStore(this, mutation);
206
+ this.keyExists("mutation", store.init.mutations!, key);
207
+ store.init.frozen = false;
208
+ this.trigger("beforecommit", mutation, ...args);
209
+ store.init.mutations![key](store.state, ...args);
210
+ this.trigger("commit", mutation, ...args);
211
+ store.init.frozen = true;
212
+
213
+ // We call the debounced update to notify the changes
214
+ debouncedUpdate();
215
+ }
216
+
217
+ // This method will dispatch an action
218
+ public async dispatch(action: string, ...args: any[]): Promise<any> {
219
+ const { store, key } = this.getStore(this, action);
220
+ this.keyExists("action", store.init.actions!, key);
221
+ this.trigger("beforedispatch", action, ...args);
222
+ try {
223
+ const result = await store.init.actions![key](store, ...args);
224
+ this.trigger("dispatch", action, ...args);
225
+ return result;
226
+ } finally {
227
+ debouncedUpdate();
228
+ }
229
+ }
230
+
231
+ // This method will trigger an event
232
+ public trigger(event: string, ...args: any[]) {
233
+ this.init.listeners[event].forEach((callback) => callback(this, ...args));
234
+ }
235
+
236
+ // This method will add a listener to the store
237
+ public on(event: string, listener: Function) {
238
+ this.isFunction("listener", listener);
239
+ this.keyExists("event", this.init.listeners, event);
240
+ if (this.init.listeners[event].indexOf(listener) === -1) {
241
+ this.init.listeners[event].push(listener);
242
+ this.trigger("addlistener", event, listener);
243
+ }
244
+ return () => this.off(event, listener);
245
+ }
246
+
247
+ // Remove a listener from the store
248
+ public off(event: string, listener: Function) {
249
+ this.isFunction("listener", listener);
250
+ this.keyExists("event", this.init.listeners, event);
251
+ const index = this.init.listeners[event].indexOf(listener);
252
+ if (index > -1) {
253
+ this.init.listeners[event].splice(index, 1);
254
+ this.trigger("removelistener", event, listener);
255
+ }
256
+ }
257
+
258
+ // This method will add a plugin to the store
259
+ public use(plugin: Function, ...options: any[]) {
260
+ this.isFunction("plugin", plugin);
261
+ if (this.init.plugins.indexOf(plugin) === -1) {
262
+ plugin(this, ...options);
263
+ this.init.plugins.push(plugin);
264
+ this.trigger("plugin", plugin, ...options);
265
+ }
266
+ }
267
+
268
+ // This method will register a module to the store
269
+ public registerModule(namespace: string, module: StoreOptions) {
270
+ const rootStore = this;
271
+ if (rootStore.init.modules[namespace]) {
272
+ throw new Error(`A module with the namespace "${namespace}" is already registered.`);
273
+ }
274
+ const newStore = new FluxStore({ ...module, rootStore, namespace });
275
+ rootStore.init.frozen = false;
276
+ rootStore.init.modules[namespace] = newStore;
277
+ rootStore.state[namespace] = newStore.state;
278
+ rootStore.init.frozen = true;
279
+ rootStore.trigger("registerModule", namespace, module, newStore);
280
+
281
+ // We call the debounced update to notify the changes
282
+ debouncedUpdate();
283
+ }
284
+
285
+ // This method will unregister a module from the store
286
+ public unregisterModule(namespace: string) {
287
+ const rootStore = this;
288
+ const store = rootStore.init.modules[namespace];
289
+ if (store) {
290
+ store.init.childModuleNamespaces.forEach((n) => rootStore.unregisterModule(`${namespace}.${n}`));
291
+ rootStore.init.frozen = false;
292
+ Reflect.deleteProperty(rootStore.init.modules, namespace);
293
+ Reflect.deleteProperty(rootStore.state, namespace);
294
+ rootStore.init.frozen = true;
295
+ rootStore.trigger("unregisterModule", namespace, store);
296
+
297
+ // We call the debounced update to notify the changes
298
+ debouncedUpdate();
299
+ }
300
+ }
301
+ }
@@ -1,10 +1,5 @@
1
- import { Component, POJOComponent, VnodeWithDom, current, directive, onCleanup, onUnmount, update } from "valyrian.js";
2
-
3
- interface CurrentOnPatch {
4
- component: Component | POJOComponent;
5
- vnode: VnodeWithDom;
6
- oldVnode: VnodeWithDom;
7
- }
1
+ import { Component, POJOComponent, current, directive, onCleanup, onUnmount, debouncedUpdate } from "valyrian.js";
2
+ import { hasChanged } from "valyrian.js/utils";
8
3
 
9
4
  export type Hook = any;
10
5
 
@@ -26,6 +21,13 @@ export interface CreateHook {
26
21
  (HookDefinition: HookDefinition): (...args: any[]) => any;
27
22
  }
28
23
 
24
+ type HookCalls = {
25
+ hooks: Hook[];
26
+ hook_calls: number;
27
+ };
28
+
29
+ const componentToHooksWeakMap = new WeakMap<Component | POJOComponent, HookCalls>();
30
+
29
31
  export const createHook = function createHook({
30
32
  onCreate,
31
33
  onUpdate: onUpdateHook,
@@ -34,91 +36,49 @@ export const createHook = function createHook({
34
36
  returnValue
35
37
  }: HookDefinition): Hook {
36
38
  return (...args: any[]) => {
37
- let { component, vnode } = current as CurrentOnPatch;
38
-
39
- let hook: any = null;
40
-
41
- if (vnode) {
42
- // Init the components array for the current vnode
43
- if (!vnode.components) {
44
- vnode.components = [];
45
- }
46
-
47
- if (vnode.components.indexOf(component) === -1) {
48
- vnode.hook_calls = -1;
49
- vnode.components.push(component);
50
- if (!component.hooks) {
51
- component.hooks = [];
52
- onUnmount(() => Reflect.deleteProperty(component, "hooks"));
53
- }
54
- }
39
+ const component = current.component as Component | POJOComponent;
40
+ let HookCalls = componentToHooksWeakMap.get(component);
55
41
 
56
- hook = component.hooks[++vnode.hook_calls];
42
+ if (!HookCalls) {
43
+ HookCalls = { hooks: [], hook_calls: -1 };
44
+ componentToHooksWeakMap.set(component, HookCalls);
45
+ onUnmount(() => componentToHooksWeakMap.delete(component));
57
46
  }
58
47
 
59
- // If the hook doesn't exist, create it
60
- if (!hook) {
61
- // create a new hook
62
- hook = onCreate(...args);
63
-
64
- if (vnode) {
65
- // Add the hook to the component
66
- component.hooks.push(hook);
67
- }
48
+ onCleanup(() => ((HookCalls as HookCalls).hook_calls = -1));
68
49
 
69
- // if we have a onRemove hook, add it to the onUnmount set
70
- if (onRemove) {
71
- // Add the hook to the onRemove array
72
- onUnmount(() => onRemove(hook));
73
- }
50
+ let hook = HookCalls.hooks[++HookCalls.hook_calls];
51
+ if (hook) {
52
+ onUpdateHook?.(hook, ...args);
74
53
  } else {
75
- if (onUpdateHook) {
76
- onUpdateHook(hook, ...args);
77
- }
78
- }
79
-
80
- // If we have an onCleanup function, add it to the cleanup set
81
- if (onCleanupHook) {
82
- // Add the hook to the onCleanup set
83
- onCleanup(() => onCleanupHook(hook));
84
- }
85
-
86
- // If we have a returnValue function, call it and return the result instead of the hook
87
- if (returnValue) {
88
- return returnValue(hook);
54
+ hook = onCreate(...args);
55
+ HookCalls.hooks.push(hook);
56
+ onRemove && onUnmount(() => onRemove(hook));
89
57
  }
90
58
 
91
- // Return the hook
92
- return hook;
59
+ onCleanupHook && onCleanup(() => onCleanupHook(hook));
60
+ return returnValue ? returnValue(hook) : hook;
93
61
  };
94
62
  } as unknown as CreateHook;
95
63
 
96
- let updateTimeout: any;
97
- function delayedUpdate() {
98
- clearTimeout(updateTimeout);
99
- updateTimeout = setTimeout(update);
100
- }
101
-
102
64
  // Use state hook
103
65
  export const useState = createHook({
104
66
  onCreate: (value) => {
67
+ let state = value;
105
68
  function get() {
106
- return value;
69
+ return state;
107
70
  }
108
- get.value = value;
109
- get.toJSON = get.valueOf = get;
110
- get.toString = () => `${value}`;
111
71
 
112
72
  function set(newValue: any) {
113
- // Prevent default event if it exists
114
- if (current.event) {
73
+ if (current.event && !current.event.defaultPrevented) {
115
74
  current.event.preventDefault();
116
75
  }
117
76
 
118
- if (value !== newValue) {
119
- value = newValue;
120
- get.value = newValue;
121
- delayedUpdate();
77
+ const resolvedValue = typeof newValue === "function" ? newValue(state) : newValue;
78
+
79
+ if (hasChanged(state, resolvedValue)) {
80
+ state = resolvedValue;
81
+ debouncedUpdate();
122
82
  }
123
83
  }
124
84
 
@@ -126,10 +86,9 @@ export const useState = createHook({
126
86
  }
127
87
  });
128
88
 
129
- // Effect hook
130
89
  export const useEffect = createHook({
131
90
  onCreate: (effect: Function, changes: any[]) => {
132
- let hook: {
91
+ const hook: {
133
92
  effect: Function;
134
93
  prev: any[];
135
94
  onRemove?: Function;
@@ -157,18 +116,18 @@ export const useEffect = createHook({
157
116
  return;
158
117
  }
159
118
 
119
+ if (Array.isArray(changes) && changes.length === 0) {
120
+ // Si las dependencias son un array vacío, no se debe volver a ejecutar.
121
+ return;
122
+ }
123
+
160
124
  // on update if there are changes
161
- if (Array.isArray(changes)) {
162
- for (let i = 0, l = changes.length; i < l; i++) {
163
- if (changes[i] !== hook.prev[i]) {
164
- hook.prev = changes;
165
- if (typeof hook.onCleanup === "function") {
166
- hook.onCleanup();
167
- }
168
- hook.onCleanup = hook.effect();
169
- return;
170
- }
125
+ if (Array.isArray(changes) && hasChanged(hook.prev, changes)) {
126
+ hook.prev = changes;
127
+ if (typeof hook.onCleanup === "function") {
128
+ hook.onCleanup();
171
129
  }
130
+ hook.onCleanup = hook.effect();
172
131
  }
173
132
  },
174
133
  onRemove: (hook) => {
@@ -192,18 +151,15 @@ export const useRef = createHook({
192
151
 
193
152
  export const useCallback = createHook({
194
153
  onCreate: (callback, changes) => {
195
- callback();
196
154
  return { callback, changes };
197
155
  },
198
156
  onUpdate: (hook, callback, changes) => {
199
- for (let i = 0, l = changes.length; i < l; i++) {
200
- if (changes[i] !== hook.changes[i]) {
201
- hook.changes = changes;
202
- hook.callback();
203
- return;
204
- }
157
+ if (hasChanged(hook.changes, changes)) {
158
+ hook.changes = changes;
159
+ hook.callback = callback;
205
160
  }
206
- }
161
+ },
162
+ returnValue: (hook) => hook.callback
207
163
  });
208
164
 
209
165
  export const useMemo = createHook({
@@ -211,15 +167,10 @@ export const useMemo = createHook({
211
167
  return { callback, changes, value: callback() };
212
168
  },
213
169
  onUpdate: (hook, callback, changes) => {
214
- for (let i = 0, l = changes.length; i < l; i++) {
215
- if (changes[i] !== hook.changes[i]) {
216
- hook.changes = changes;
217
- hook.value = callback();
218
- return;
219
- }
170
+ if (hasChanged(hook.changes, changes)) {
171
+ hook.changes = changes;
172
+ hook.value = callback();
220
173
  }
221
174
  },
222
- returnValue: (hook) => {
223
- return hook.value;
224
- }
175
+ returnValue: (hook) => hook.value
225
176
  });