onejs-core 0.3.5

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 (63) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/workflows/jsr.yml +19 -0
  3. package/.prettierrc +5 -0
  4. package/3rdparty/preact/LICENSE +21 -0
  5. package/3rdparty/preact/clone-element.ts +45 -0
  6. package/3rdparty/preact/compat/Children.ts +21 -0
  7. package/3rdparty/preact/compat/forwardRef.ts +49 -0
  8. package/3rdparty/preact/compat/index.ts +3 -0
  9. package/3rdparty/preact/compat/memo.ts +34 -0
  10. package/3rdparty/preact/compat/util.ts +38 -0
  11. package/3rdparty/preact/component.ts +235 -0
  12. package/3rdparty/preact/constants.ts +3 -0
  13. package/3rdparty/preact/create-context.ts +71 -0
  14. package/3rdparty/preact/create-element.ts +98 -0
  15. package/3rdparty/preact/diff/catch-error.ts +40 -0
  16. package/3rdparty/preact/diff/children.ts +355 -0
  17. package/3rdparty/preact/diff/index.ts +563 -0
  18. package/3rdparty/preact/diff/props.ts +174 -0
  19. package/3rdparty/preact/hooks/index.ts +536 -0
  20. package/3rdparty/preact/hooks/internal.d.ts +85 -0
  21. package/3rdparty/preact/hooks.d.ts +145 -0
  22. package/3rdparty/preact/index.ts +13 -0
  23. package/3rdparty/preact/internal.d.ts +155 -0
  24. package/3rdparty/preact/jsx-runtime/index.ts +80 -0
  25. package/3rdparty/preact/jsx.d.ts +1008 -0
  26. package/3rdparty/preact/options.ts +16 -0
  27. package/3rdparty/preact/preact.d.ts +317 -0
  28. package/3rdparty/preact/render.ts +76 -0
  29. package/3rdparty/preact/signals/index.ts +443 -0
  30. package/3rdparty/preact/signals/internal.d.ts +36 -0
  31. package/3rdparty/preact/signals-core/index.ts +663 -0
  32. package/3rdparty/preact/style.d.ts +205 -0
  33. package/3rdparty/preact/util.ts +29 -0
  34. package/@DO_NOT_CHANGE.txt +3 -0
  35. package/README.md +33 -0
  36. package/definitions/app.d.ts +52048 -0
  37. package/definitions/augments.d.ts +16 -0
  38. package/definitions/globals.d.ts +34 -0
  39. package/definitions/index.d.ts +9 -0
  40. package/definitions/jsx.d.ts +517 -0
  41. package/definitions/modules.d.ts +29 -0
  42. package/definitions/onejs.d.ts +164 -0
  43. package/definitions/preact.jsx.d.ts +7 -0
  44. package/definitions/proto-overrides.d.ts +13 -0
  45. package/definitions/puerts.d.ts +31 -0
  46. package/definitions/unity-engine.d.ts +23 -0
  47. package/hooks/eventful.ts +56 -0
  48. package/import-transform.mjs +42 -0
  49. package/index.ts +44 -0
  50. package/jsr.json +10 -0
  51. package/onejs-tw-config.cjs +188 -0
  52. package/package.json +9 -0
  53. package/preloads/inject.ts +44 -0
  54. package/styling/index.tsx +80 -0
  55. package/styling/utils/generateAlphabeticName.ts +21 -0
  56. package/styling/utils/generateComponentId.ts +6 -0
  57. package/styling/utils/hash.ts +46 -0
  58. package/switch.cjs +185 -0
  59. package/uss-transform-plugin.cjs +83 -0
  60. package/utils/color-palettes.ts +3 -0
  61. package/utils/color-parser.ts +249 -0
  62. package/utils/float-parser.ts +31 -0
  63. package/utils/index.ts +12 -0
@@ -0,0 +1,174 @@
1
+ import { IS_NON_DIMENSIONAL } from '../constants'
2
+ import options from '../options'
3
+
4
+ /**
5
+ * Diff the old and new properties of a VNode and apply changes to the DOM node
6
+ * @param {import('../internal').PreactElement} dom The DOM node to apply
7
+ * changes to
8
+ * @param {object} newProps The new props
9
+ * @param {object} oldProps The old props
10
+ * @param {boolean} isSvg Whether or not this node is an SVG node
11
+ * @param {boolean} hydrate Whether or not we are in hydration mode
12
+ */
13
+ export function diffProps(dom, newProps, oldProps, isSvg, hydrate) {
14
+ let i;
15
+
16
+ for (i in oldProps) {
17
+ if (i !== 'children' && i !== 'key' && !(i in newProps)) {
18
+ setProperty(dom, i, null, oldProps[i], isSvg);
19
+ }
20
+ }
21
+
22
+ for (i in newProps) {
23
+ if (
24
+ (!hydrate || typeof newProps[i] == 'function') &&
25
+ i !== 'children' &&
26
+ i !== 'key' &&
27
+ i !== 'value' &&
28
+ i !== 'checked' &&
29
+ oldProps[i] !== newProps[i]
30
+ ) {
31
+ setProperty(dom, i, newProps[i], oldProps[i], isSvg);
32
+ }
33
+ }
34
+ }
35
+
36
+ function setStyle(style, key, value) {
37
+ if (key[0] === '-') {
38
+ style.setProperty(key, value);
39
+ } else if (value == null) {
40
+ style[key] = null;
41
+ } else if (typeof value != 'number' || IS_NON_DIMENSIONAL.test(key)) {
42
+ style[key] = value;
43
+ } else {
44
+ style[key] = value + 'px';
45
+ }
46
+
47
+ // styleProcessors[key](style, value)
48
+ // globalThis.__setStyleProperty(style.GetVEStyle(), key, value)
49
+ }
50
+
51
+ /**
52
+ * Set a property value on a DOM node
53
+ * @param {import('../internal').PreactElement} dom The DOM node to modify
54
+ * @param {string} name The name of the property to set
55
+ * @param {*} value The value to set the property to
56
+ * @param {*} oldValue The old value the property had
57
+ * @param {boolean} isSvg Whether or not this DOM node is an SVG node or not
58
+ */
59
+ export function setProperty(dom, name, value, oldValue, isSvg) {
60
+ let useCapture;
61
+
62
+ o: if (name === 'style') {
63
+ if (typeof value == 'string') {
64
+ dom.style.cssText = value;
65
+ } else {
66
+ if (typeof oldValue == 'string') {
67
+ dom.style.cssText = oldValue = '';
68
+ }
69
+
70
+ if (oldValue) {
71
+ for (name in oldValue) {
72
+ if (!(value && name in value)) {
73
+ setStyle(dom.style, name, '');
74
+ }
75
+ }
76
+ }
77
+
78
+ if (value) {
79
+ for (name in value) {
80
+ if (!oldValue || value[name] !== oldValue[name]) {
81
+ setStyle(dom.style, name, value[name]);
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ // Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6
88
+ else if (name[0] === 'o' && name[1] === 'n') {
89
+ useCapture = name !== (name = name.replace(/Capture$/, ''));
90
+
91
+ // Infer correct casing for DOM built-in events:
92
+ if (name.toLowerCase() in dom) name = name.toLowerCase().slice(2);
93
+ else name = name.slice(2);
94
+
95
+ if (!dom._listeners) dom._listeners = {};
96
+ // dom._listeners[name + useCapture] = value;
97
+ dom._addToListeners(name + useCapture, value)
98
+
99
+ if (value) {
100
+ if (!oldValue) {
101
+ const handler = useCapture ? eventProxyCapture : eventProxy;
102
+ dom.addEventListener(name, handler.bind(dom), useCapture);
103
+ // dom.addEventListener(name, value, useCapture);
104
+ }
105
+ } else {
106
+ const handler = useCapture ? eventProxyCapture : eventProxy;
107
+ dom.removeEventListener(name, handler.bind(dom), useCapture);
108
+ // dom.removeEventListener(name, value, useCapture);
109
+ }
110
+ } else if (name !== 'dangerouslySetInnerHTML') {
111
+ if (isSvg) {
112
+ // Normalize incorrect prop usage for SVG:
113
+ // - xlink:href / xlinkHref --> href (xlink:href was removed from SVG and isn't needed)
114
+ // - className --> class
115
+ name = name.replace(/xlink(H|:h)/, 'h').replace(/sName$/, 's');
116
+ } else if (
117
+ name !== 'width' &&
118
+ name !== 'height' &&
119
+ name !== 'href' &&
120
+ name !== 'list' &&
121
+ name !== 'form' &&
122
+ // Default value in browsers is `-1` and an empty string is
123
+ // cast to `0` instead
124
+ name !== 'tabIndex' &&
125
+ name !== 'download' &&
126
+ name !== 'rowSpan' &&
127
+ name !== 'colSpan' &&
128
+ name in dom
129
+ ) {
130
+ try {
131
+ // dom[name] = value == null ? '' : value;
132
+ dom.setAttribute(name, value == null ? null : value); // MODDED
133
+ // labelled break is 1b smaller here than a return statement (sorry)
134
+ break o;
135
+ } catch (e) { }
136
+ }
137
+
138
+ // ARIA-attributes have a different notion of boolean values.
139
+ // The value `false` is different from the attribute not
140
+ // existing on the DOM, so we can't remove it. For non-boolean
141
+ // ARIA-attributes we could treat false as a removal, but the
142
+ // amount of exceptions would cost us too many bytes. On top of
143
+ // that other VDOM frameworks also always stringify `false`.
144
+
145
+ if (name == "disabled") { // MODDED
146
+ dom.setAttribute(name, value);
147
+ } else if (value != null && (value !== false || name[4] === '-')) {
148
+ dom.setAttribute(name, value);
149
+ } else {
150
+ dom.removeAttribute(name);
151
+ }
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Proxy an event to hooked event handlers
157
+ * @param {Event} e The event object from the browser
158
+ * @private
159
+ */
160
+ function eventProxy(e) {
161
+ let eventName = e.GetType().Name.replace("Event", "")
162
+ eventName = eventName === "Change`1" ? "ValueChanged" : eventName
163
+ // this.CallListener(eventName + false, options.event ? options.event(e) : e)
164
+ // this._listeners[eventName + false](options.event ? options.event(e) : e);
165
+ this._callListener(eventName + false, options.event ? options.event(e) : e);
166
+ }
167
+
168
+ function eventProxyCapture(e) {
169
+ let eventName = e.GetType().Name.replace("Event", "")
170
+ eventName = eventName === "Change`1" ? "ValueChanged" : eventName
171
+ // this.CallListener(eventName + true, options.event ? options.event(e) : e)
172
+ // this._listeners[eventName + true](options.event ? options.event(e) : e);
173
+ this._callListener(eventName + true, options.event ? options.event(e) : e);
174
+ }
@@ -0,0 +1,536 @@
1
+ import { Fragment, 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: any[] = [];
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
+ // if (
31
+ // typeof vnode.type === 'function' &&
32
+ // !vnode._mask &&
33
+ // vnode.type !== Fragment
34
+ // ) {
35
+ // vnode._mask =
36
+ // (vnode._parent && vnode._parent._mask ? vnode._parent._mask : '') +
37
+ // (vnode._parent && vnode._parent._children
38
+ // ? vnode._parent._children.indexOf(vnode)
39
+ // : 0);
40
+ // } else if (!vnode._mask) {
41
+ // vnode._mask =
42
+ // vnode._parent && vnode._parent._mask ? vnode._parent._mask : '';
43
+ // }
44
+
45
+ currentComponent = null;
46
+ if (oldBeforeDiff) oldBeforeDiff(vnode);
47
+ };
48
+
49
+ options._render = vnode => {
50
+ if (oldBeforeRender) oldBeforeRender(vnode);
51
+
52
+ currentComponent = vnode._component;
53
+ currentIndex = 0;
54
+
55
+ const hooks = currentComponent.__hooks;
56
+ if (hooks) {
57
+ if (previousComponent === currentComponent) {
58
+ hooks._pendingEffects = [];
59
+ currentComponent._renderCallbacks = [];
60
+ hooks._list.forEach(hookItem => {
61
+ if (hookItem._nextValue) {
62
+ hookItem._value = hookItem._nextValue;
63
+ }
64
+ hookItem._pendingValue = EMPTY;
65
+ hookItem._nextValue = hookItem._pendingArgs = undefined;
66
+ });
67
+ } else {
68
+ hooks._pendingEffects.forEach(invokeCleanup);
69
+ hooks._pendingEffects.forEach(invokeEffect);
70
+ hooks._pendingEffects = [];
71
+ }
72
+ }
73
+ previousComponent = currentComponent;
74
+ };
75
+
76
+ options.diffed = vnode => {
77
+ if (oldAfterDiff) oldAfterDiff(vnode);
78
+
79
+ const c = vnode._component;
80
+ if (c && c.__hooks) {
81
+ if (c.__hooks._pendingEffects.length) afterPaint(afterPaintEffects.push(c));
82
+ c.__hooks._list.forEach(hookItem => {
83
+ if (hookItem._pendingArgs) {
84
+ hookItem._args = hookItem._pendingArgs;
85
+ }
86
+ if (hookItem._pendingValue !== EMPTY) {
87
+ hookItem._value = hookItem._pendingValue;
88
+ }
89
+ hookItem._pendingArgs = undefined;
90
+ hookItem._pendingValue = EMPTY;
91
+ });
92
+ }
93
+ previousComponent = currentComponent = null;
94
+ };
95
+
96
+ options._commit = (vnode, commitQueue) => {
97
+ commitQueue.some(component => {
98
+ try {
99
+ component._renderCallbacks.forEach(invokeCleanup);
100
+ component._renderCallbacks = component._renderCallbacks.filter(cb =>
101
+ cb._value ? invokeEffect(cb) : true
102
+ );
103
+ } catch (e) {
104
+ commitQueue.some(c => {
105
+ if (c._renderCallbacks) c._renderCallbacks = [];
106
+ });
107
+ commitQueue = [];
108
+ options._catchError(e, component._vnode);
109
+ }
110
+ });
111
+
112
+ if (oldCommit) oldCommit(vnode, commitQueue);
113
+ };
114
+
115
+ options.unmount = vnode => {
116
+ if (oldBeforeUnmount) oldBeforeUnmount(vnode);
117
+
118
+ const c = vnode._component;
119
+ if (c && c.__hooks) {
120
+ let hasErrored;
121
+ c.__hooks._list.forEach(s => {
122
+ try {
123
+ invokeCleanup(s);
124
+ } catch (e) {
125
+ hasErrored = e;
126
+ }
127
+ });
128
+ c.__hooks = undefined;
129
+ if (hasErrored) options._catchError(hasErrored, c._vnode);
130
+ }
131
+ };
132
+
133
+ /**
134
+ * Get a hook's state from the currentComponent
135
+ * @param {number} index The index of the hook to get
136
+ * @param {number} type The index of the hook to get
137
+ * @returns {any}
138
+ */
139
+ function getHookState(index, type) {
140
+ if (options._hook) {
141
+ options._hook(currentComponent, index, currentHook || type);
142
+ }
143
+ currentHook = 0;
144
+
145
+ // Largely inspired by:
146
+ // * https://github.com/michael-klein/funcy.js/blob/f6be73468e6ec46b0ff5aa3cc4c9baf72a29025a/src/hooks/core_hooks.mjs
147
+ // * https://github.com/michael-klein/funcy.js/blob/650beaa58c43c33a74820a3c98b3c7079cf2e333/src/renderer.mjs
148
+ // Other implementations to look at:
149
+ // * https://codesandbox.io/s/mnox05qp8
150
+ const hooks =
151
+ currentComponent.__hooks ||
152
+ (currentComponent.__hooks = {
153
+ _list: [],
154
+ _pendingEffects: []
155
+ });
156
+
157
+ if (index >= hooks._list.length) {
158
+ hooks._list.push({ _pendingValue: EMPTY });
159
+ }
160
+ return hooks._list[index];
161
+ }
162
+
163
+ /**
164
+ * @param {import('./index').StateUpdater<any>} [initialState]
165
+ */
166
+ export function useState(initialState?) {
167
+ currentHook = 1;
168
+ return useReducer(invokeOrReturn, initialState);
169
+ }
170
+
171
+ /**
172
+ * @param {import('./index').Reducer<any, any>} reducer
173
+ * @param {import('./index').StateUpdater<any>} initialState
174
+ * @param {(initialState: any) => void} [init]
175
+ * @returns {[ any, (state: any) => void ]}
176
+ */
177
+ export function useReducer(reducer, initialState, init?) {
178
+ /** @type {import('./internal').ReducerHookState} */
179
+ const hookState = getHookState(currentIndex++, 2);
180
+ hookState._reducer = reducer;
181
+ if (typeof hookState._component === "undefined" || hookState._component === null) { // MODDED
182
+ hookState._value = [
183
+ !init ? invokeOrReturn(undefined, initialState) : init(initialState),
184
+
185
+ action => {
186
+ const currentValue = hookState._nextValue
187
+ ? hookState._nextValue[0]
188
+ : hookState._value[0];
189
+ const nextValue = hookState._reducer(currentValue, action);
190
+
191
+ if (currentValue !== nextValue) {
192
+ hookState._nextValue = [nextValue, hookState._value[1]];
193
+ hookState._component.setState({});
194
+ }
195
+ }
196
+ ];
197
+
198
+ hookState._component = currentComponent;
199
+
200
+ if (!currentComponent._hasScuFromHooks) {
201
+ currentComponent._hasScuFromHooks = true;
202
+ let prevScu = currentComponent.shouldComponentUpdate;
203
+ const prevCWU = currentComponent.componentWillUpdate;
204
+
205
+ // If we're dealing with a forced update `shouldComponentUpdate` will
206
+ // not be called. But we use that to update the hook values, so we
207
+ // need to call it.
208
+ currentComponent.componentWillUpdate = function (p, s, c) {
209
+ if (this._force) {
210
+ let tmp = prevScu;
211
+ // Clear to avoid other sCU hooks from being called
212
+ prevScu = undefined;
213
+ updateHookState(p, s, c);
214
+ prevScu = tmp;
215
+ }
216
+
217
+ if (prevCWU) prevCWU.call(this, p, s, c);
218
+ };
219
+
220
+ // This SCU has the purpose of bailing out after repeated updates
221
+ // to stateful hooks.
222
+ // we store the next value in _nextValue[0] and keep doing that for all
223
+ // state setters, if we have next states and
224
+ // all next states within a component end up being equal to their original state
225
+ // we are safe to bail out for this specific component.
226
+ /**
227
+ *
228
+ * @type {import('./internal').Component["shouldComponentUpdate"]}
229
+ */
230
+ // @ts-ignore - We don't use TS to downtranspile
231
+ // eslint-disable-next-line no-inner-declarations
232
+ function updateHookState(p, s, c) {
233
+ if (typeof hookState._component.__hooks == "undefined" || hookState._component.__hooks === null) return true;
234
+
235
+ const stateHooks = hookState._component.__hooks._list.filter(
236
+ x => x._component
237
+ );
238
+ const allHooksEmpty = stateHooks.every(x => typeof x._nextValue == "undefined" || x._nextValue === null);
239
+ // When we have no updated hooks in the component we invoke the previous SCU or
240
+ // traverse the VDOM tree further.
241
+ if (allHooksEmpty) {
242
+ return prevScu ? prevScu.call(this, p, s, c) : true;
243
+ }
244
+
245
+ // We check whether we have components with a nextValue set that
246
+ // have values that aren't equal to one another this pushes
247
+ // us to update further down the tree
248
+ let shouldUpdate = false;
249
+ stateHooks.forEach(hookItem => {
250
+ if (hookItem._nextValue) {
251
+ const currentValue = hookItem._value[0];
252
+ hookItem._value = hookItem._nextValue;
253
+ hookItem._nextValue = undefined;
254
+ if (currentValue !== hookItem._value[0]) shouldUpdate = true;
255
+ }
256
+ });
257
+
258
+ return shouldUpdate || hookState._component.props !== p
259
+ ? prevScu
260
+ ? prevScu.call(this, p, s, c)
261
+ : true
262
+ : false;
263
+ }
264
+
265
+ currentComponent.shouldComponentUpdate = updateHookState;
266
+ }
267
+ }
268
+
269
+ return hookState._nextValue || hookState._value;
270
+ }
271
+
272
+ /**
273
+ * @param {import('./internal').Effect} callback
274
+ * @param {any[]} args
275
+ */
276
+ export function useEffect(callback, args) {
277
+ /** @type {import('./internal').EffectHookState} */
278
+ const state = getHookState(currentIndex++, 3);
279
+ if (!options._skipEffects && argsChanged(state._args, args)) {
280
+ state._value = callback;
281
+ state._pendingArgs = args;
282
+
283
+ currentComponent.__hooks._pendingEffects.push(state);
284
+ }
285
+ }
286
+
287
+ /**
288
+ * @param {import('./internal').Effect} callback
289
+ * @param {any[]} args
290
+ */
291
+ export function useLayoutEffect(callback, args) {
292
+ /** @type {import('./internal').EffectHookState} */
293
+ const state = getHookState(currentIndex++, 4);
294
+ if (!options._skipEffects && argsChanged(state._args, args)) {
295
+ state._value = callback;
296
+ state._pendingArgs = args;
297
+
298
+ currentComponent._renderCallbacks.push(state);
299
+ }
300
+ }
301
+
302
+ export function useRef(initialValue) {
303
+ currentHook = 5;
304
+ return useMemo(() => ({ current: initialValue }), []);
305
+ }
306
+
307
+ /**
308
+ * @param {object} ref
309
+ * @param {() => object} createHandle
310
+ * @param {any[]} args
311
+ */
312
+ export function useImperativeHandle(ref, createHandle, args) {
313
+ currentHook = 6;
314
+ useLayoutEffect(
315
+ () => {
316
+ if (typeof ref == 'function') {
317
+ ref(createHandle());
318
+ return () => ref(null);
319
+ } else if (ref) {
320
+ ref.current = createHandle();
321
+ return () => (ref.current = null);
322
+ }
323
+ },
324
+ args == null ? args : args.concat(ref)
325
+ );
326
+ }
327
+
328
+ /**
329
+ * @param {() => any} factory
330
+ * @param {any[]} args
331
+ */
332
+ export function useMemo(factory, args) {
333
+ /** @type {import('./internal').MemoHookState} */
334
+ const state = getHookState(currentIndex++, 7);
335
+ if (argsChanged(state._args, args)) {
336
+ state._pendingValue = factory();
337
+ state._pendingArgs = args;
338
+ state._factory = factory;
339
+ return state._pendingValue;
340
+ }
341
+
342
+ return state._value;
343
+ }
344
+
345
+ /**
346
+ * @param {() => void} callback
347
+ * @param {any[]} args
348
+ */
349
+ export function useCallback(callback, args) {
350
+ currentHook = 8;
351
+ return useMemo(() => callback, args);
352
+ }
353
+
354
+ /**
355
+ * @param {import('./internal').PreactContext} context
356
+ */
357
+ export function useContext(context) {
358
+ const provider = currentComponent.context[context._id];
359
+ // We could skip this call here, but than we'd not call
360
+ // `options._hook`. We need to do that in order to make
361
+ // the devtools aware of this hook.
362
+ /** @type {import('./internal').ContextHookState} */
363
+ const state = getHookState(currentIndex++, 9);
364
+ // The devtools needs access to the context object to
365
+ // be able to pull of the default value when no provider
366
+ // is present in the tree.
367
+ state._context = context;
368
+ if (typeof provider == "undefined" || provider === null) return context._defaultValue;
369
+ // This is probably not safe to convert to "!"
370
+ if (state._value == null) {
371
+ state._value = true;
372
+ provider.sub(currentComponent);
373
+ }
374
+ return provider.props.value;
375
+ }
376
+
377
+ /**
378
+ * Display a custom label for a custom hook for the devtools panel
379
+ * @type {<T>(value: T, cb?: (value: T) => string | number) => void}
380
+ */
381
+ export function useDebugValue(value, formatter) {
382
+ if (options.useDebugValue) {
383
+ options.useDebugValue(formatter ? formatter(value) : value);
384
+ }
385
+ }
386
+
387
+ /**
388
+ * @param {(error: any, errorInfo: import('preact').ErrorInfo) => void} cb
389
+ */
390
+ export function useErrorBoundary(cb) {
391
+ /** @type {import('./internal').ErrorBoundaryHookState} */
392
+ const state = getHookState(currentIndex++, 10);
393
+ const errState = useState();
394
+ state._value = cb;
395
+ if (!currentComponent.componentDidCatch) {
396
+ currentComponent.componentDidCatch = (err, errorInfo) => {
397
+ if (state._value) state._value(err, errorInfo);
398
+ errState[1](err);
399
+ };
400
+ }
401
+ return [
402
+ errState[0],
403
+ () => {
404
+ errState[1](undefined);
405
+ }
406
+ ];
407
+ }
408
+
409
+ export function useId() {
410
+ const state = getHookState(currentIndex++, 11);
411
+ if (!state._value) {
412
+ // Grab either the root node or the nearest async boundary node.
413
+ /** @type {import('./internal.d').VNode} */
414
+ let root = currentComponent._vnode;
415
+ while (root !== null && !root._mask && root._parent !== null) {
416
+ root = root._parent;
417
+ }
418
+
419
+ let mask = root._mask || (root._mask = [0, 0]);
420
+ state._value = 'P' + mask[0] + '-' + mask[1]++;
421
+ }
422
+
423
+ return state._value;
424
+ }
425
+ /**
426
+ * After paint effects consumer.
427
+ */
428
+ function flushAfterPaintEffects() {
429
+ let component;
430
+ while ((component = afterPaintEffects.shift())) {
431
+ if (!component._parentDom || typeof component.__hooks == "undefined" || component.__hooks === null) continue; // MODDED
432
+ try {
433
+ component.__hooks._pendingEffects.forEach(invokeCleanup);
434
+ component.__hooks._pendingEffects.forEach(invokeEffect);
435
+ component.__hooks._pendingEffects = [];
436
+ } catch (e) {
437
+ component.__hooks._pendingEffects = [];
438
+ options._catchError(e, component._vnode);
439
+ }
440
+ }
441
+ }
442
+
443
+ // globalThis.requestAnimationFrame = function (callback) {
444
+ // return setTimeout(callback)
445
+ // } as any
446
+
447
+ // globalThis.cancelAnimationFrame = function (id) {
448
+ // clearTimeout(id)
449
+ // } as any
450
+
451
+ let HAS_RAF = typeof requestAnimationFrame == 'function';
452
+
453
+ /**
454
+ * Schedule a callback to be invoked after the browser has a chance to paint a new frame.
455
+ * Do this by combining requestAnimationFrame (rAF) + setTimeout to invoke a callback after
456
+ * the next browser frame.
457
+ *
458
+ * Also, schedule a timeout in parallel to the the rAF to ensure the callback is invoked
459
+ * even if RAF doesn't fire (for example if the browser tab is not visible)
460
+ *
461
+ * @param {() => void} callback
462
+ */
463
+ function afterNextFrame(callback) {
464
+ const done = () => {
465
+ clearTimeout(timeout);
466
+ if (HAS_RAF) cancelAnimationFrame(raf);
467
+ setTimeout(callback);
468
+ };
469
+ const timeout = setTimeout(done, RAF_TIMEOUT);
470
+
471
+ let raf;
472
+ if (HAS_RAF) {
473
+ raf = requestAnimationFrame(done);
474
+ }
475
+ }
476
+
477
+ // Note: if someone used options.debounceRendering = requestAnimationFrame,
478
+ // then effects will ALWAYS run on the NEXT frame instead of the current one, incurring a ~16ms delay.
479
+ // Perhaps this is not such a big deal.
480
+ /**
481
+ * Schedule afterPaintEffects flush after the browser paints
482
+ * @param {number} newQueueLength
483
+ */
484
+ function afterPaint(newQueueLength) {
485
+ if (newQueueLength === 1 || prevRaf !== options.requestAnimationFrame) {
486
+ prevRaf = options.requestAnimationFrame;
487
+ (prevRaf || afterNextFrame)(flushAfterPaintEffects);
488
+ }
489
+ }
490
+
491
+ options.debounceRendering = requestAnimationFrame // ADDED
492
+ options.requestAnimationFrame = requestAnimationFrame // ADDED
493
+
494
+ /**
495
+ * @param {import('./internal').EffectHookState} hook
496
+ */
497
+ function invokeCleanup(hook) {
498
+ // A hook cleanup can introduce a call to render which creates a new root, this will call options.vnode
499
+ // and move the currentComponent away.
500
+ const comp = currentComponent;
501
+ let cleanup = hook._cleanup;
502
+ if (typeof cleanup == 'function') {
503
+ hook._cleanup = undefined;
504
+ cleanup();
505
+ }
506
+
507
+ currentComponent = comp;
508
+ }
509
+
510
+ /**
511
+ * Invoke a Hook's effect
512
+ * @param {import('./internal').EffectHookState} hook
513
+ */
514
+ function invokeEffect(hook) {
515
+ // A hook call can introduce a call to render which creates a new root, this will call options.vnode
516
+ // and move the currentComponent away.
517
+ const comp = currentComponent;
518
+ hook._cleanup = hook._value();
519
+ currentComponent = comp;
520
+ }
521
+
522
+ /**
523
+ * @param {any[]} oldArgs
524
+ * @param {any[]} newArgs
525
+ */
526
+ function argsChanged(oldArgs, newArgs) {
527
+ return (
528
+ !oldArgs ||
529
+ oldArgs.length !== newArgs.length ||
530
+ Array.isArray(newArgs) && newArgs.some((arg, index) => arg !== oldArgs[index]) // MODDED
531
+ );
532
+ }
533
+
534
+ function invokeOrReturn(arg, f) {
535
+ return typeof f == 'function' ? f(arg) : f;
536
+ }