isomorfeus-preact 10.8.0 → 10.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/isomorfeus_preact/preact/function_component/api.rb +24 -0
  3. data/lib/preact/version.rb +1 -1
  4. data/node_modules/.package-lock.json +5 -7
  5. data/node_modules/preact/compat/dist/compat.js +2 -2
  6. data/node_modules/preact/compat/dist/compat.js.map +1 -1
  7. data/node_modules/preact/compat/dist/compat.mjs +2 -2
  8. data/node_modules/preact/compat/dist/compat.module.js +2 -2
  9. data/node_modules/preact/compat/dist/compat.module.js.map +1 -1
  10. data/node_modules/preact/compat/dist/compat.umd.js +2 -2
  11. data/node_modules/preact/compat/dist/compat.umd.js.map +1 -1
  12. data/node_modules/preact/compat/src/index.d.ts +164 -155
  13. data/node_modules/preact/compat/src/index.js +223 -187
  14. data/node_modules/preact/compat/src/render.js +238 -238
  15. data/node_modules/preact/debug/dist/debug.js +2 -2
  16. data/node_modules/preact/debug/dist/debug.js.map +1 -1
  17. data/node_modules/preact/debug/dist/debug.mjs +2 -2
  18. data/node_modules/preact/debug/dist/debug.module.js +2 -2
  19. data/node_modules/preact/debug/dist/debug.module.js.map +1 -1
  20. data/node_modules/preact/debug/dist/debug.umd.js +2 -2
  21. data/node_modules/preact/debug/dist/debug.umd.js.map +1 -1
  22. data/node_modules/preact/debug/src/debug.js +437 -444
  23. data/node_modules/preact/devtools/dist/devtools.js +2 -2
  24. data/node_modules/preact/devtools/dist/devtools.js.map +1 -1
  25. data/node_modules/preact/devtools/dist/devtools.mjs +2 -2
  26. data/node_modules/preact/devtools/dist/devtools.module.js +2 -2
  27. data/node_modules/preact/devtools/dist/devtools.module.js.map +1 -1
  28. data/node_modules/preact/devtools/dist/devtools.umd.js +2 -2
  29. data/node_modules/preact/devtools/dist/devtools.umd.js.map +1 -1
  30. data/node_modules/preact/devtools/src/devtools.js +10 -10
  31. data/node_modules/preact/hooks/dist/hooks.js +2 -2
  32. data/node_modules/preact/hooks/dist/hooks.js.map +1 -1
  33. data/node_modules/preact/hooks/dist/hooks.mjs +2 -2
  34. data/node_modules/preact/hooks/dist/hooks.module.js +2 -2
  35. data/node_modules/preact/hooks/dist/hooks.module.js.map +1 -1
  36. data/node_modules/preact/hooks/dist/hooks.umd.js +2 -2
  37. data/node_modules/preact/hooks/dist/hooks.umd.js.map +1 -1
  38. data/node_modules/preact/hooks/src/index.js +417 -404
  39. data/node_modules/preact/hooks/src/internal.d.ts +3 -0
  40. data/node_modules/preact/package.json +304 -304
  41. data/node_modules/preact/src/jsx.d.ts +1014 -1013
  42. data/package.json +1 -1
  43. metadata +4 -4
@@ -1,404 +1,417 @@
1
- import { options } from 'preact';
2
-
3
- /** @type {number} */
4
- let currentIndex;
5
-
6
- /** @type {import('./internal').Component} */
7
- let currentComponent;
8
-
9
- /** @type {import('./internal').Component} */
10
- let previousComponent;
11
-
12
- /** @type {number} */
13
- let currentHook = 0;
14
-
15
- /** @type {Array<import('./internal').Component>} */
16
- let afterPaintEffects = [];
17
-
18
- let oldBeforeDiff = options._diff;
19
- let oldBeforeRender = options._render;
20
- let oldAfterDiff = options.diffed;
21
- let oldCommit = options._commit;
22
- let oldBeforeUnmount = options.unmount;
23
-
24
- const RAF_TIMEOUT = 100;
25
- let prevRaf;
26
-
27
- options._diff = vnode => {
28
- currentComponent = null;
29
- if (oldBeforeDiff) oldBeforeDiff(vnode);
30
- };
31
-
32
- options._render = vnode => {
33
- if (oldBeforeRender) oldBeforeRender(vnode);
34
-
35
- currentComponent = vnode._component;
36
- currentIndex = 0;
37
-
38
- const hooks = currentComponent.__hooks;
39
- if (hooks) {
40
- if (previousComponent === currentComponent) {
41
- hooks._pendingEffects = [];
42
- currentComponent._renderCallbacks = [];
43
- hooks._list.forEach(hookItem => {
44
- if (hookItem._args) hookItem._args = undefined;
45
- });
46
- } else {
47
- hooks._pendingEffects.forEach(invokeCleanup);
48
- hooks._pendingEffects.forEach(invokeEffect);
49
- hooks._pendingEffects = [];
50
- }
51
- }
52
- previousComponent = currentComponent;
53
- };
54
-
55
- options.diffed = vnode => {
56
- if (oldAfterDiff) oldAfterDiff(vnode);
57
-
58
- const c = vnode._component;
59
- if (c && c.__hooks && c.__hooks._pendingEffects.length) {
60
- afterPaint(afterPaintEffects.push(c));
61
- }
62
- currentComponent = null;
63
- previousComponent = null;
64
- };
65
-
66
- options._commit = (vnode, commitQueue) => {
67
- commitQueue.some(component => {
68
- try {
69
- component._renderCallbacks.forEach(invokeCleanup);
70
- component._renderCallbacks = component._renderCallbacks.filter(cb =>
71
- cb._value ? invokeEffect(cb) : true
72
- );
73
- } catch (e) {
74
- commitQueue.some(c => {
75
- if (c._renderCallbacks) c._renderCallbacks = [];
76
- });
77
- commitQueue = [];
78
- options._catchError(e, component._vnode);
79
- }
80
- });
81
-
82
- if (oldCommit) oldCommit(vnode, commitQueue);
83
- };
84
-
85
- options.unmount = vnode => {
86
- if (oldBeforeUnmount) oldBeforeUnmount(vnode);
87
-
88
- const c = vnode._component;
89
- if (c && c.__hooks) {
90
- let hasErrored;
91
- c.__hooks._list.forEach(s => {
92
- try {
93
- invokeCleanup(s);
94
- } catch (e) {
95
- hasErrored = e;
96
- }
97
- });
98
- if (hasErrored) options._catchError(hasErrored, c._vnode);
99
- }
100
- };
101
-
102
- /**
103
- * Get a hook's state from the currentComponent
104
- * @param {number} index The index of the hook to get
105
- * @param {number} type The index of the hook to get
106
- * @returns {any}
107
- */
108
- function getHookState(index, type) {
109
- if (options._hook) {
110
- options._hook(currentComponent, index, currentHook || type);
111
- }
112
- currentHook = 0;
113
-
114
- // Largely inspired by:
115
- // * https://github.com/michael-klein/funcy.js/blob/f6be73468e6ec46b0ff5aa3cc4c9baf72a29025a/src/hooks/core_hooks.mjs
116
- // * https://github.com/michael-klein/funcy.js/blob/650beaa58c43c33a74820a3c98b3c7079cf2e333/src/renderer.mjs
117
- // Other implementations to look at:
118
- // * https://codesandbox.io/s/mnox05qp8
119
- const hooks =
120
- currentComponent.__hooks ||
121
- (currentComponent.__hooks = {
122
- _list: [],
123
- _pendingEffects: []
124
- });
125
-
126
- if (index >= hooks._list.length) {
127
- hooks._list.push({});
128
- }
129
- return hooks._list[index];
130
- }
131
-
132
- /**
133
- * @param {import('./index').StateUpdater<any>} [initialState]
134
- */
135
- export function useState(initialState) {
136
- currentHook = 1;
137
- return useReducer(invokeOrReturn, initialState);
138
- }
139
-
140
- /**
141
- * @param {import('./index').Reducer<any, any>} reducer
142
- * @param {import('./index').StateUpdater<any>} initialState
143
- * @param {(initialState: any) => void} [init]
144
- * @returns {[ any, (state: any) => void ]}
145
- */
146
- export function useReducer(reducer, initialState, init) {
147
- /** @type {import('./internal').ReducerHookState} */
148
- const hookState = getHookState(currentIndex++, 2);
149
- hookState._reducer = reducer;
150
- if (!hookState._component) {
151
- hookState._value = [
152
- !init ? invokeOrReturn(undefined, initialState) : init(initialState),
153
-
154
- action => {
155
- const nextValue = hookState._reducer(hookState._value[0], action);
156
- if (hookState._value[0] !== nextValue) {
157
- hookState._value = [nextValue, hookState._value[1]];
158
- hookState._component.setState({});
159
- }
160
- }
161
- ];
162
-
163
- hookState._component = currentComponent;
164
- }
165
-
166
- return hookState._value;
167
- }
168
-
169
- /**
170
- * @param {import('./internal').Effect} callback
171
- * @param {any[]} args
172
- */
173
- export function useEffect(callback, args) {
174
- /** @type {import('./internal').EffectHookState} */
175
- const state = getHookState(currentIndex++, 3);
176
- if (!options._skipEffects && argsChanged(state._args, args)) {
177
- state._value = callback;
178
- state._args = args;
179
-
180
- currentComponent.__hooks._pendingEffects.push(state);
181
- }
182
- }
183
-
184
- /**
185
- * @param {import('./internal').Effect} callback
186
- * @param {any[]} args
187
- */
188
- export function useLayoutEffect(callback, args) {
189
- /** @type {import('./internal').EffectHookState} */
190
- const state = getHookState(currentIndex++, 4);
191
- if (!options._skipEffects && argsChanged(state._args, args)) {
192
- state._value = callback;
193
- state._args = args;
194
-
195
- currentComponent._renderCallbacks.push(state);
196
- }
197
- }
198
-
199
- export function useRef(initialValue) {
200
- currentHook = 5;
201
- return useMemo(() => ({ current: initialValue }), []);
202
- }
203
-
204
- /**
205
- * @param {object} ref
206
- * @param {() => object} createHandle
207
- * @param {any[]} args
208
- */
209
- export function useImperativeHandle(ref, createHandle, args) {
210
- currentHook = 6;
211
- useLayoutEffect(
212
- () => {
213
- if (typeof ref == 'function') {
214
- ref(createHandle());
215
- return () => ref(null);
216
- } else if (ref) {
217
- ref.current = createHandle();
218
- return () => (ref.current = null);
219
- }
220
- },
221
- args == null ? args : args.concat(ref)
222
- );
223
- }
224
-
225
- /**
226
- * @param {() => any} factory
227
- * @param {any[]} args
228
- */
229
- export function useMemo(factory, args) {
230
- /** @type {import('./internal').MemoHookState} */
231
- const state = getHookState(currentIndex++, 7);
232
- if (argsChanged(state._args, args)) {
233
- state._value = factory();
234
- state._args = args;
235
- state._factory = factory;
236
- }
237
-
238
- return state._value;
239
- }
240
-
241
- /**
242
- * @param {() => void} callback
243
- * @param {any[]} args
244
- */
245
- export function useCallback(callback, args) {
246
- currentHook = 8;
247
- return useMemo(() => callback, args);
248
- }
249
-
250
- /**
251
- * @param {import('./internal').PreactContext} context
252
- */
253
- export function useContext(context) {
254
- const provider = currentComponent.context[context._id];
255
- // We could skip this call here, but than we'd not call
256
- // `options._hook`. We need to do that in order to make
257
- // the devtools aware of this hook.
258
- /** @type {import('./internal').ContextHookState} */
259
- const state = getHookState(currentIndex++, 9);
260
- // The devtools needs access to the context object to
261
- // be able to pull of the default value when no provider
262
- // is present in the tree.
263
- state._context = context;
264
- if (!provider) return context._defaultValue;
265
- // This is probably not safe to convert to "!"
266
- if (state._value == null) {
267
- state._value = true;
268
- provider.sub(currentComponent);
269
- }
270
- return provider.props.value;
271
- }
272
-
273
- /**
274
- * Display a custom label for a custom hook for the devtools panel
275
- * @type {<T>(value: T, cb?: (value: T) => string | number) => void}
276
- */
277
- export function useDebugValue(value, formatter) {
278
- if (options.useDebugValue) {
279
- options.useDebugValue(formatter ? formatter(value) : value);
280
- }
281
- }
282
-
283
- /**
284
- * @param {(error: any) => void} cb
285
- */
286
- export function useErrorBoundary(cb) {
287
- /** @type {import('./internal').ErrorBoundaryHookState} */
288
- const state = getHookState(currentIndex++, 10);
289
- const errState = useState();
290
- state._value = cb;
291
- if (!currentComponent.componentDidCatch) {
292
- currentComponent.componentDidCatch = err => {
293
- if (state._value) state._value(err);
294
- errState[1](err);
295
- };
296
- }
297
- return [
298
- errState[0],
299
- () => {
300
- errState[1](undefined);
301
- }
302
- ];
303
- }
304
-
305
- /**
306
- * After paint effects consumer.
307
- */
308
- function flushAfterPaintEffects() {
309
- let component;
310
- while ((component = afterPaintEffects.shift())) {
311
- if (!component._parentDom) continue;
312
- try {
313
- component.__hooks._pendingEffects.forEach(invokeCleanup);
314
- component.__hooks._pendingEffects.forEach(invokeEffect);
315
- component.__hooks._pendingEffects = [];
316
- } catch (e) {
317
- component.__hooks._pendingEffects = [];
318
- options._catchError(e, component._vnode);
319
- }
320
- }
321
- }
322
-
323
- let HAS_RAF = typeof requestAnimationFrame == 'function';
324
-
325
- /**
326
- * Schedule a callback to be invoked after the browser has a chance to paint a new frame.
327
- * Do this by combining requestAnimationFrame (rAF) + setTimeout to invoke a callback after
328
- * the next browser frame.
329
- *
330
- * Also, schedule a timeout in parallel to the the rAF to ensure the callback is invoked
331
- * even if RAF doesn't fire (for example if the browser tab is not visible)
332
- *
333
- * @param {() => void} callback
334
- */
335
- function afterNextFrame(callback) {
336
- const done = () => {
337
- clearTimeout(timeout);
338
- if (HAS_RAF) cancelAnimationFrame(raf);
339
- setTimeout(callback);
340
- };
341
- const timeout = setTimeout(done, RAF_TIMEOUT);
342
-
343
- let raf;
344
- if (HAS_RAF) {
345
- raf = requestAnimationFrame(done);
346
- }
347
- }
348
-
349
- // Note: if someone used options.debounceRendering = requestAnimationFrame,
350
- // then effects will ALWAYS run on the NEXT frame instead of the current one, incurring a ~16ms delay.
351
- // Perhaps this is not such a big deal.
352
- /**
353
- * Schedule afterPaintEffects flush after the browser paints
354
- * @param {number} newQueueLength
355
- */
356
- function afterPaint(newQueueLength) {
357
- if (newQueueLength === 1 || prevRaf !== options.requestAnimationFrame) {
358
- prevRaf = options.requestAnimationFrame;
359
- (prevRaf || afterNextFrame)(flushAfterPaintEffects);
360
- }
361
- }
362
-
363
- /**
364
- * @param {import('./internal').EffectHookState} hook
365
- */
366
- function invokeCleanup(hook) {
367
- // A hook cleanup can introduce a call to render which creates a new root, this will call options.vnode
368
- // and move the currentComponent away.
369
- const comp = currentComponent;
370
- let cleanup = hook._cleanup;
371
- if (typeof cleanup == 'function') {
372
- hook._cleanup = undefined;
373
- cleanup();
374
- }
375
- currentComponent = comp;
376
- }
377
-
378
- /**
379
- * Invoke a Hook's effect
380
- * @param {import('./internal').EffectHookState} hook
381
- */
382
- function invokeEffect(hook) {
383
- // A hook call can introduce a call to render which creates a new root, this will call options.vnode
384
- // and move the currentComponent away.
385
- const comp = currentComponent;
386
- hook._cleanup = hook._value();
387
- currentComponent = comp;
388
- }
389
-
390
- /**
391
- * @param {any[]} oldArgs
392
- * @param {any[]} newArgs
393
- */
394
- function argsChanged(oldArgs, newArgs) {
395
- return (
396
- !oldArgs ||
397
- oldArgs.length !== newArgs.length ||
398
- newArgs.some((arg, index) => arg !== oldArgs[index])
399
- );
400
- }
401
-
402
- function invokeOrReturn(arg, f) {
403
- return typeof f == 'function' ? f(arg) : f;
404
- }
1
+ import { options } from 'preact';
2
+
3
+ /** @type {number} */
4
+ let currentIndex;
5
+
6
+ /** @type {import('./internal').Component} */
7
+ let currentComponent;
8
+
9
+ /** @type {import('./internal').Component} */
10
+ let previousComponent;
11
+
12
+ /** @type {number} */
13
+ let currentHook = 0;
14
+
15
+ /** @type {Array<import('./internal').Component>} */
16
+ let afterPaintEffects = [];
17
+
18
+ let EMPTY = [];
19
+
20
+ let oldBeforeDiff = options._diff;
21
+ let oldBeforeRender = options._render;
22
+ let oldAfterDiff = options.diffed;
23
+ let oldCommit = options._commit;
24
+ let oldBeforeUnmount = options.unmount;
25
+
26
+ const RAF_TIMEOUT = 100;
27
+ let prevRaf;
28
+
29
+ options._diff = vnode => {
30
+ currentComponent = null;
31
+ if (oldBeforeDiff) oldBeforeDiff(vnode);
32
+ };
33
+
34
+ options._render = vnode => {
35
+ if (oldBeforeRender) oldBeforeRender(vnode);
36
+
37
+ currentComponent = vnode._component;
38
+ currentIndex = 0;
39
+
40
+ const hooks = currentComponent.__hooks;
41
+ if (hooks) {
42
+ if (previousComponent === currentComponent) {
43
+ hooks._pendingEffects = [];
44
+ currentComponent._renderCallbacks = [];
45
+ hooks._list.forEach(hookItem => {
46
+ hookItem._pendingValue = EMPTY;
47
+ hookItem._pendingArgs = undefined;
48
+ });
49
+ } else {
50
+ hooks._pendingEffects.forEach(invokeCleanup);
51
+ hooks._pendingEffects.forEach(invokeEffect);
52
+ hooks._pendingEffects = [];
53
+ }
54
+ }
55
+ previousComponent = currentComponent;
56
+ };
57
+
58
+ options.diffed = vnode => {
59
+ if (oldAfterDiff) oldAfterDiff(vnode);
60
+
61
+ const c = vnode._component;
62
+ if (c && c.__hooks) {
63
+ if (c.__hooks._pendingEffects.length) afterPaint(afterPaintEffects.push(c));
64
+ c.__hooks._list.forEach(hookItem => {
65
+ if (hookItem._pendingArgs) {
66
+ hookItem._args = hookItem._pendingArgs;
67
+ }
68
+ if (hookItem._pendingValue !== EMPTY) {
69
+ hookItem._value = hookItem._pendingValue;
70
+ }
71
+ hookItem._pendingArgs = undefined;
72
+ hookItem._pendingValue = EMPTY;
73
+ });
74
+ }
75
+ previousComponent = currentComponent = null;
76
+ };
77
+
78
+ options._commit = (vnode, commitQueue) => {
79
+ commitQueue.some(component => {
80
+ try {
81
+ component._renderCallbacks.forEach(invokeCleanup);
82
+ component._renderCallbacks = component._renderCallbacks.filter(cb =>
83
+ cb._value ? invokeEffect(cb) : true
84
+ );
85
+ } catch (e) {
86
+ commitQueue.some(c => {
87
+ if (c._renderCallbacks) c._renderCallbacks = [];
88
+ });
89
+ commitQueue = [];
90
+ options._catchError(e, component._vnode);
91
+ }
92
+ });
93
+
94
+ if (oldCommit) oldCommit(vnode, commitQueue);
95
+ };
96
+
97
+ options.unmount = vnode => {
98
+ if (oldBeforeUnmount) oldBeforeUnmount(vnode);
99
+
100
+ const c = vnode._component;
101
+ if (c && c.__hooks) {
102
+ let hasErrored;
103
+ c.__hooks._list.forEach(s => {
104
+ try {
105
+ invokeCleanup(s);
106
+ } catch (e) {
107
+ hasErrored = e;
108
+ }
109
+ });
110
+ if (hasErrored) options._catchError(hasErrored, c._vnode);
111
+ }
112
+ };
113
+
114
+ /**
115
+ * Get a hook's state from the currentComponent
116
+ * @param {number} index The index of the hook to get
117
+ * @param {number} type The index of the hook to get
118
+ * @returns {any}
119
+ */
120
+ function getHookState(index, type) {
121
+ if (options._hook) {
122
+ options._hook(currentComponent, index, currentHook || type);
123
+ }
124
+ currentHook = 0;
125
+
126
+ // Largely inspired by:
127
+ // * https://github.com/michael-klein/funcy.js/blob/f6be73468e6ec46b0ff5aa3cc4c9baf72a29025a/src/hooks/core_hooks.mjs
128
+ // * https://github.com/michael-klein/funcy.js/blob/650beaa58c43c33a74820a3c98b3c7079cf2e333/src/renderer.mjs
129
+ // Other implementations to look at:
130
+ // * https://codesandbox.io/s/mnox05qp8
131
+ const hooks =
132
+ currentComponent.__hooks ||
133
+ (currentComponent.__hooks = {
134
+ _list: [],
135
+ _pendingEffects: []
136
+ });
137
+
138
+ if (index >= hooks._list.length) {
139
+ hooks._list.push({ _pendingValue: EMPTY });
140
+ }
141
+ return hooks._list[index];
142
+ }
143
+
144
+ /**
145
+ * @param {import('./index').StateUpdater<any>} [initialState]
146
+ */
147
+ export function useState(initialState) {
148
+ currentHook = 1;
149
+ return useReducer(invokeOrReturn, initialState);
150
+ }
151
+
152
+ /**
153
+ * @param {import('./index').Reducer<any, any>} reducer
154
+ * @param {import('./index').StateUpdater<any>} initialState
155
+ * @param {(initialState: any) => void} [init]
156
+ * @returns {[ any, (state: any) => void ]}
157
+ */
158
+ export function useReducer(reducer, initialState, init) {
159
+ /** @type {import('./internal').ReducerHookState} */
160
+ const hookState = getHookState(currentIndex++, 2);
161
+ hookState._reducer = reducer;
162
+ if (!hookState._component) {
163
+ hookState._value = [
164
+ !init ? invokeOrReturn(undefined, initialState) : init(initialState),
165
+
166
+ action => {
167
+ const nextValue = hookState._reducer(hookState._value[0], action);
168
+ if (hookState._value[0] !== nextValue) {
169
+ hookState._value = [nextValue, hookState._value[1]];
170
+ hookState._component.setState({});
171
+ }
172
+ }
173
+ ];
174
+
175
+ hookState._component = currentComponent;
176
+ }
177
+
178
+ return hookState._value;
179
+ }
180
+
181
+ /**
182
+ * @param {import('./internal').Effect} callback
183
+ * @param {any[]} args
184
+ */
185
+ export function useEffect(callback, args) {
186
+ /** @type {import('./internal').EffectHookState} */
187
+ const state = getHookState(currentIndex++, 3);
188
+ if (!options._skipEffects && argsChanged(state._args, args)) {
189
+ state._value = callback;
190
+ state._pendingArgs = args;
191
+
192
+ currentComponent.__hooks._pendingEffects.push(state);
193
+ }
194
+ }
195
+
196
+ /**
197
+ * @param {import('./internal').Effect} callback
198
+ * @param {any[]} args
199
+ */
200
+ export function useLayoutEffect(callback, args) {
201
+ /** @type {import('./internal').EffectHookState} */
202
+ const state = getHookState(currentIndex++, 4);
203
+ if (!options._skipEffects && argsChanged(state._args, args)) {
204
+ state._value = callback;
205
+ state._pendingArgs = args;
206
+
207
+ currentComponent._renderCallbacks.push(state);
208
+ }
209
+ }
210
+
211
+ export function useRef(initialValue) {
212
+ currentHook = 5;
213
+ return useMemo(() => ({ current: initialValue }), []);
214
+ }
215
+
216
+ /**
217
+ * @param {object} ref
218
+ * @param {() => object} createHandle
219
+ * @param {any[]} args
220
+ */
221
+ export function useImperativeHandle(ref, createHandle, args) {
222
+ currentHook = 6;
223
+ useLayoutEffect(
224
+ () => {
225
+ if (typeof ref == 'function') {
226
+ ref(createHandle());
227
+ return () => ref(null);
228
+ } else if (ref) {
229
+ ref.current = createHandle();
230
+ return () => (ref.current = null);
231
+ }
232
+ },
233
+ args == null ? args : args.concat(ref)
234
+ );
235
+ }
236
+
237
+ /**
238
+ * @param {() => any} factory
239
+ * @param {any[]} args
240
+ */
241
+ export function useMemo(factory, args) {
242
+ /** @type {import('./internal').MemoHookState} */
243
+ const state = getHookState(currentIndex++, 7);
244
+ if (argsChanged(state._args, args)) {
245
+ state._pendingValue = factory();
246
+ state._pendingArgs = args;
247
+ state._factory = factory;
248
+ return state._pendingValue;
249
+ }
250
+
251
+ return state._value;
252
+ }
253
+
254
+ /**
255
+ * @param {() => void} callback
256
+ * @param {any[]} args
257
+ */
258
+ export function useCallback(callback, args) {
259
+ currentHook = 8;
260
+ return useMemo(() => callback, args);
261
+ }
262
+
263
+ /**
264
+ * @param {import('./internal').PreactContext} context
265
+ */
266
+ export function useContext(context) {
267
+ const provider = currentComponent.context[context._id];
268
+ // We could skip this call here, but than we'd not call
269
+ // `options._hook`. We need to do that in order to make
270
+ // the devtools aware of this hook.
271
+ /** @type {import('./internal').ContextHookState} */
272
+ const state = getHookState(currentIndex++, 9);
273
+ // The devtools needs access to the context object to
274
+ // be able to pull of the default value when no provider
275
+ // is present in the tree.
276
+ state._context = context;
277
+ if (!provider) return context._defaultValue;
278
+ // This is probably not safe to convert to "!"
279
+ if (state._value == null) {
280
+ state._value = true;
281
+ provider.sub(currentComponent);
282
+ }
283
+ return provider.props.value;
284
+ }
285
+
286
+ /**
287
+ * Display a custom label for a custom hook for the devtools panel
288
+ * @type {<T>(value: T, cb?: (value: T) => string | number) => void}
289
+ */
290
+ export function useDebugValue(value, formatter) {
291
+ if (options.useDebugValue) {
292
+ options.useDebugValue(formatter ? formatter(value) : value);
293
+ }
294
+ }
295
+
296
+ /**
297
+ * @param {(error: any) => void} cb
298
+ */
299
+ export function useErrorBoundary(cb) {
300
+ /** @type {import('./internal').ErrorBoundaryHookState} */
301
+ const state = getHookState(currentIndex++, 10);
302
+ const errState = useState();
303
+ state._value = cb;
304
+ if (!currentComponent.componentDidCatch) {
305
+ currentComponent.componentDidCatch = err => {
306
+ if (state._value) state._value(err);
307
+ errState[1](err);
308
+ };
309
+ }
310
+ return [
311
+ errState[0],
312
+ () => {
313
+ errState[1](undefined);
314
+ }
315
+ ];
316
+ }
317
+
318
+ /**
319
+ * After paint effects consumer.
320
+ */
321
+ function flushAfterPaintEffects() {
322
+ let component;
323
+ while ((component = afterPaintEffects.shift())) {
324
+ if (!component._parentDom) continue;
325
+ try {
326
+ component.__hooks._pendingEffects.forEach(invokeCleanup);
327
+ component.__hooks._pendingEffects.forEach(invokeEffect);
328
+ component.__hooks._pendingEffects = [];
329
+ } catch (e) {
330
+ component.__hooks._pendingEffects = [];
331
+ options._catchError(e, component._vnode);
332
+ }
333
+ }
334
+ }
335
+
336
+ let HAS_RAF = typeof requestAnimationFrame == 'function';
337
+
338
+ /**
339
+ * Schedule a callback to be invoked after the browser has a chance to paint a new frame.
340
+ * Do this by combining requestAnimationFrame (rAF) + setTimeout to invoke a callback after
341
+ * the next browser frame.
342
+ *
343
+ * Also, schedule a timeout in parallel to the the rAF to ensure the callback is invoked
344
+ * even if RAF doesn't fire (for example if the browser tab is not visible)
345
+ *
346
+ * @param {() => void} callback
347
+ */
348
+ function afterNextFrame(callback) {
349
+ const done = () => {
350
+ clearTimeout(timeout);
351
+ if (HAS_RAF) cancelAnimationFrame(raf);
352
+ setTimeout(callback);
353
+ };
354
+ const timeout = setTimeout(done, RAF_TIMEOUT);
355
+
356
+ let raf;
357
+ if (HAS_RAF) {
358
+ raf = requestAnimationFrame(done);
359
+ }
360
+ }
361
+
362
+ // Note: if someone used options.debounceRendering = requestAnimationFrame,
363
+ // then effects will ALWAYS run on the NEXT frame instead of the current one, incurring a ~16ms delay.
364
+ // Perhaps this is not such a big deal.
365
+ /**
366
+ * Schedule afterPaintEffects flush after the browser paints
367
+ * @param {number} newQueueLength
368
+ */
369
+ function afterPaint(newQueueLength) {
370
+ if (newQueueLength === 1 || prevRaf !== options.requestAnimationFrame) {
371
+ prevRaf = options.requestAnimationFrame;
372
+ (prevRaf || afterNextFrame)(flushAfterPaintEffects);
373
+ }
374
+ }
375
+
376
+ /**
377
+ * @param {import('./internal').EffectHookState} hook
378
+ */
379
+ function invokeCleanup(hook) {
380
+ // A hook cleanup can introduce a call to render which creates a new root, this will call options.vnode
381
+ // and move the currentComponent away.
382
+ const comp = currentComponent;
383
+ let cleanup = hook._cleanup;
384
+ if (typeof cleanup == 'function') {
385
+ hook._cleanup = undefined;
386
+ cleanup();
387
+ }
388
+ currentComponent = comp;
389
+ }
390
+
391
+ /**
392
+ * Invoke a Hook's effect
393
+ * @param {import('./internal').EffectHookState} hook
394
+ */
395
+ function invokeEffect(hook) {
396
+ // A hook call can introduce a call to render which creates a new root, this will call options.vnode
397
+ // and move the currentComponent away.
398
+ const comp = currentComponent;
399
+ hook._cleanup = hook._value();
400
+ currentComponent = comp;
401
+ }
402
+
403
+ /**
404
+ * @param {any[]} oldArgs
405
+ * @param {any[]} newArgs
406
+ */
407
+ function argsChanged(oldArgs, newArgs) {
408
+ return (
409
+ !oldArgs ||
410
+ oldArgs.length !== newArgs.length ||
411
+ newArgs.some((arg, index) => arg !== oldArgs[index])
412
+ );
413
+ }
414
+
415
+ function invokeOrReturn(arg, f) {
416
+ return typeof f == 'function' ? f(arg) : f;
417
+ }