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.
- package/.gitattributes +2 -0
- package/.github/workflows/jsr.yml +19 -0
- package/.prettierrc +5 -0
- package/3rdparty/preact/LICENSE +21 -0
- package/3rdparty/preact/clone-element.ts +45 -0
- package/3rdparty/preact/compat/Children.ts +21 -0
- package/3rdparty/preact/compat/forwardRef.ts +49 -0
- package/3rdparty/preact/compat/index.ts +3 -0
- package/3rdparty/preact/compat/memo.ts +34 -0
- package/3rdparty/preact/compat/util.ts +38 -0
- package/3rdparty/preact/component.ts +235 -0
- package/3rdparty/preact/constants.ts +3 -0
- package/3rdparty/preact/create-context.ts +71 -0
- package/3rdparty/preact/create-element.ts +98 -0
- package/3rdparty/preact/diff/catch-error.ts +40 -0
- package/3rdparty/preact/diff/children.ts +355 -0
- package/3rdparty/preact/diff/index.ts +563 -0
- package/3rdparty/preact/diff/props.ts +174 -0
- package/3rdparty/preact/hooks/index.ts +536 -0
- package/3rdparty/preact/hooks/internal.d.ts +85 -0
- package/3rdparty/preact/hooks.d.ts +145 -0
- package/3rdparty/preact/index.ts +13 -0
- package/3rdparty/preact/internal.d.ts +155 -0
- package/3rdparty/preact/jsx-runtime/index.ts +80 -0
- package/3rdparty/preact/jsx.d.ts +1008 -0
- package/3rdparty/preact/options.ts +16 -0
- package/3rdparty/preact/preact.d.ts +317 -0
- package/3rdparty/preact/render.ts +76 -0
- package/3rdparty/preact/signals/index.ts +443 -0
- package/3rdparty/preact/signals/internal.d.ts +36 -0
- package/3rdparty/preact/signals-core/index.ts +663 -0
- package/3rdparty/preact/style.d.ts +205 -0
- package/3rdparty/preact/util.ts +29 -0
- package/@DO_NOT_CHANGE.txt +3 -0
- package/README.md +33 -0
- package/definitions/app.d.ts +52048 -0
- package/definitions/augments.d.ts +16 -0
- package/definitions/globals.d.ts +34 -0
- package/definitions/index.d.ts +9 -0
- package/definitions/jsx.d.ts +517 -0
- package/definitions/modules.d.ts +29 -0
- package/definitions/onejs.d.ts +164 -0
- package/definitions/preact.jsx.d.ts +7 -0
- package/definitions/proto-overrides.d.ts +13 -0
- package/definitions/puerts.d.ts +31 -0
- package/definitions/unity-engine.d.ts +23 -0
- package/hooks/eventful.ts +56 -0
- package/import-transform.mjs +42 -0
- package/index.ts +44 -0
- package/jsr.json +10 -0
- package/onejs-tw-config.cjs +188 -0
- package/package.json +9 -0
- package/preloads/inject.ts +44 -0
- package/styling/index.tsx +80 -0
- package/styling/utils/generateAlphabeticName.ts +21 -0
- package/styling/utils/generateComponentId.ts +6 -0
- package/styling/utils/hash.ts +46 -0
- package/switch.cjs +185 -0
- package/uss-transform-plugin.cjs +83 -0
- package/utils/color-palettes.ts +3 -0
- package/utils/color-parser.ts +249 -0
- package/utils/float-parser.ts +31 -0
- package/utils/index.ts +12 -0
package/.gitattributes
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# name: Publish
|
|
2
|
+
# on:
|
|
3
|
+
# push:
|
|
4
|
+
# branches:
|
|
5
|
+
# - main
|
|
6
|
+
|
|
7
|
+
# jobs:
|
|
8
|
+
# publish:
|
|
9
|
+
# runs-on: ubuntu-latest
|
|
10
|
+
|
|
11
|
+
# permissions:
|
|
12
|
+
# contents: read
|
|
13
|
+
# id-token: write
|
|
14
|
+
|
|
15
|
+
# steps:
|
|
16
|
+
# - uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
# - name: Publish package
|
|
19
|
+
# run: npx jsr publish
|
package/.prettierrc
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2015-present Jason Miller
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { assign, slice } from './util';
|
|
2
|
+
import { createVNode } from './create-element';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Clones the given VNode, optionally adding attributes/props and replacing its children.
|
|
6
|
+
* @param {import('./internal').VNode} vnode The virtual DOM element to clone
|
|
7
|
+
* @param {object} props Attributes/props to add when cloning
|
|
8
|
+
* @param {Array<import('./internal').ComponentChildren>} rest Any additional arguments will be used as replacement children.
|
|
9
|
+
* @returns {import('./internal').VNode}
|
|
10
|
+
*/
|
|
11
|
+
export function cloneElement(vnode, props, children) {
|
|
12
|
+
let normalizedProps = assign({}, vnode.props),
|
|
13
|
+
key,
|
|
14
|
+
ref,
|
|
15
|
+
i;
|
|
16
|
+
|
|
17
|
+
let defaultProps;
|
|
18
|
+
|
|
19
|
+
if (vnode.type && vnode.type.defaultProps) {
|
|
20
|
+
defaultProps = vnode.type.defaultProps;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
for (i in props) {
|
|
24
|
+
if (i == 'key') key = props[i];
|
|
25
|
+
else if (i == 'ref') ref = props[i];
|
|
26
|
+
else if (props[i] === undefined && defaultProps !== undefined) {
|
|
27
|
+
normalizedProps[i] = defaultProps[i];
|
|
28
|
+
} else {
|
|
29
|
+
normalizedProps[i] = props[i];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (arguments.length > 2) {
|
|
34
|
+
normalizedProps.children =
|
|
35
|
+
arguments.length > 3 ? slice.call(arguments, 2) : children;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return createVNode(
|
|
39
|
+
vnode.type,
|
|
40
|
+
normalizedProps,
|
|
41
|
+
key || vnode.key,
|
|
42
|
+
ref || vnode.ref,
|
|
43
|
+
null
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { toChildArray } from 'preact';
|
|
2
|
+
|
|
3
|
+
const mapFn = (children, fn) => {
|
|
4
|
+
if (children == null) return null;
|
|
5
|
+
return toChildArray(toChildArray(children).map(fn));
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// This API is completely unnecessary for Preact, so it's basically passthrough.
|
|
9
|
+
export const Children = {
|
|
10
|
+
map: mapFn,
|
|
11
|
+
forEach: mapFn,
|
|
12
|
+
count(children) {
|
|
13
|
+
return children ? toChildArray(children).length : 0;
|
|
14
|
+
},
|
|
15
|
+
only(children) {
|
|
16
|
+
const normalized = toChildArray(children);
|
|
17
|
+
if (normalized.length !== 1) throw 'Children.only';
|
|
18
|
+
return normalized[0];
|
|
19
|
+
},
|
|
20
|
+
toArray: toChildArray
|
|
21
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ComponentChild, FunctionalComponent, options, Ref } from 'preact'
|
|
2
|
+
import { assign } from './util'
|
|
3
|
+
|
|
4
|
+
let oldDiffHook = (options as any)._diff;
|
|
5
|
+
(options as any)._diff = vnode => {
|
|
6
|
+
if (vnode.type && vnode.type._forwarded && vnode.ref) {
|
|
7
|
+
vnode.props.ref = vnode.ref;
|
|
8
|
+
vnode.ref = null;
|
|
9
|
+
}
|
|
10
|
+
if (oldDiffHook) oldDiffHook(vnode);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const REACT_FORWARD_SYMBOL =
|
|
14
|
+
(typeof Symbol != 'undefined' &&
|
|
15
|
+
Symbol.for &&
|
|
16
|
+
Symbol.for('react.forward_ref')) ||
|
|
17
|
+
0xf47;
|
|
18
|
+
|
|
19
|
+
interface ForwardFn<P = {}, T = any> {
|
|
20
|
+
(props: P, ref: Ref<T>): ComponentChild;
|
|
21
|
+
displayName?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Pass ref down to a child. This is mainly used in libraries with HOCs that
|
|
26
|
+
* wrap components. Using `forwardRef` there is an easy way to get a reference
|
|
27
|
+
* of the wrapped component instead of one of the wrapper itself.
|
|
28
|
+
* @param {import('./index').ForwardFn} fn
|
|
29
|
+
* @returns {import('./internal').FunctionComponent}
|
|
30
|
+
*/
|
|
31
|
+
export function forwardRef<R, P = {}>(fn: ForwardFn<P, R>): FunctionalComponent<Omit<P, 'ref'> & { ref?: Ref<R> }> {
|
|
32
|
+
function Forwarded(props) {
|
|
33
|
+
let clone = assign({}, props);
|
|
34
|
+
delete clone.ref;
|
|
35
|
+
return fn(clone, props.ref || null);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// mobx-react checks for this being present
|
|
39
|
+
Forwarded.$$typeof = REACT_FORWARD_SYMBOL;
|
|
40
|
+
// mobx-react heavily relies on implementation details.
|
|
41
|
+
// It expects an object here with a `render` property,
|
|
42
|
+
// and prototype.render will fail. Without this
|
|
43
|
+
// mobx-react throws.
|
|
44
|
+
Forwarded.render = Forwarded;
|
|
45
|
+
|
|
46
|
+
Forwarded.prototype.isReactComponent = Forwarded._forwarded = true;
|
|
47
|
+
Forwarded.displayName = 'ForwardRef(' + (fn.displayName || fn.name) + ')';
|
|
48
|
+
return Forwarded as any;
|
|
49
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FunctionComponent, createElement } from 'preact';
|
|
2
|
+
import { shallowDiffers } from './util';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Memoize a component, so that it only updates when the props actually have
|
|
6
|
+
* changed. This was previously known as `React.pure`.
|
|
7
|
+
*/
|
|
8
|
+
export function memo<P = {}>(
|
|
9
|
+
c: FunctionComponent<P>,
|
|
10
|
+
comparer?: (prev: P, next: P) => boolean
|
|
11
|
+
): FunctionComponent<P> {
|
|
12
|
+
function shouldUpdate(nextProps) {
|
|
13
|
+
let ref = this.props.ref;
|
|
14
|
+
let updateRef = ref == nextProps.ref;
|
|
15
|
+
if (!updateRef && ref) {
|
|
16
|
+
ref.call ? ref(null) : (ref.current = null);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!comparer) {
|
|
20
|
+
return shallowDiffers(this.props, nextProps);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return !comparer(this.props, nextProps) || !updateRef;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function Memoed(props) {
|
|
27
|
+
this.shouldComponentUpdate = shouldUpdate;
|
|
28
|
+
return createElement(c, props);
|
|
29
|
+
}
|
|
30
|
+
Memoed.displayName = 'Memo(' + (c.displayName || c.name) + ')';
|
|
31
|
+
Memoed.prototype.isReactComponent = true;
|
|
32
|
+
Memoed._forwarded = true;
|
|
33
|
+
return Memoed;
|
|
34
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assign properties from `props` to `obj`
|
|
3
|
+
* @template O, P The obj and props types
|
|
4
|
+
* @param {O} obj The object to copy properties to
|
|
5
|
+
* @param {P} props The object to copy properties from
|
|
6
|
+
* @returns {O & P}
|
|
7
|
+
*/
|
|
8
|
+
export function assign(obj, props) {
|
|
9
|
+
for (let i in props) obj[i] = props[i];
|
|
10
|
+
return /** @type {O & P} */ (obj);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Check if two objects have a different shape
|
|
15
|
+
* @param {object} a
|
|
16
|
+
* @param {object} b
|
|
17
|
+
* @returns {boolean}
|
|
18
|
+
*/
|
|
19
|
+
export function shallowDiffers(a, b) {
|
|
20
|
+
for (let i in a) if (i !== '__source' && !(i in b)) return true;
|
|
21
|
+
for (let i in b) if (i !== '__source' && a[i] !== b[i]) return true;
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function removeNode(node) {
|
|
26
|
+
let parentNode = node.parentNode;
|
|
27
|
+
if (parentNode) parentNode.removeChild(node);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Check if two values are the same value
|
|
32
|
+
* @param {*} x
|
|
33
|
+
* @param {*} y
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
export function is(x, y) {
|
|
37
|
+
return (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y);
|
|
38
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { assign } from './util';
|
|
2
|
+
import { diff, commitRoot } from './diff/index';
|
|
3
|
+
import options from './options';
|
|
4
|
+
import { Fragment } from './create-element';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Base Component class. Provides `setState()` and `forceUpdate()`, which
|
|
8
|
+
* trigger rendering
|
|
9
|
+
* @param {object} props The initial component props
|
|
10
|
+
* @param {object} context The initial context from parent components'
|
|
11
|
+
* getChildContext
|
|
12
|
+
*/
|
|
13
|
+
export function Component(props, context) {
|
|
14
|
+
this.props = props;
|
|
15
|
+
this.context = context;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Update component state and schedule a re-render.
|
|
20
|
+
* @this {import('./internal').Component}
|
|
21
|
+
* @param {object | ((s: object, p: object) => object)} update A hash of state
|
|
22
|
+
* properties to update with new values or a function that given the current
|
|
23
|
+
* state and props returns a new partial state
|
|
24
|
+
* @param {() => void} [callback] A function to be called once component state is
|
|
25
|
+
* updated
|
|
26
|
+
*/
|
|
27
|
+
Component.prototype.setState = function (update, callback) {
|
|
28
|
+
// only clone state when copying to nextState the first time.
|
|
29
|
+
let s;
|
|
30
|
+
if (this._nextState != null && this._nextState !== this.state) {
|
|
31
|
+
s = this._nextState;
|
|
32
|
+
} else {
|
|
33
|
+
s = this._nextState = assign({}, this.state);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (typeof update == 'function') {
|
|
37
|
+
// Some libraries like `immer` mark the current state as readonly,
|
|
38
|
+
// preventing us from mutating it, so we need to clone it. See #2716
|
|
39
|
+
update = update(assign({}, s), this.props);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (update) {
|
|
43
|
+
assign(s, update);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Skip update if updater function returned null
|
|
47
|
+
if (update == null) return;
|
|
48
|
+
|
|
49
|
+
if (this._vnode) {
|
|
50
|
+
if (callback) this._renderCallbacks.push(callback);
|
|
51
|
+
enqueueRender(this);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Immediately perform a synchronous re-render of the component
|
|
57
|
+
* @this {import('./internal').Component}
|
|
58
|
+
* @param {() => void} [callback] A function to be called after component is
|
|
59
|
+
* re-rendered
|
|
60
|
+
*/
|
|
61
|
+
Component.prototype.forceUpdate = function (callback) {
|
|
62
|
+
if (this._vnode) {
|
|
63
|
+
// Set render mode so that we can differentiate where the render request
|
|
64
|
+
// is coming from. We need this because forceUpdate should never call
|
|
65
|
+
// shouldComponentUpdate
|
|
66
|
+
this._force = true;
|
|
67
|
+
if (callback) this._renderCallbacks.push(callback);
|
|
68
|
+
enqueueRender(this);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Accepts `props` and `state`, and returns a new Virtual DOM tree to build.
|
|
74
|
+
* Virtual DOM is generally constructed via [JSX](http://jasonformat.com/wtf-is-jsx).
|
|
75
|
+
* @param {object} props Props (eg: JSX attributes) received from parent
|
|
76
|
+
* element/component
|
|
77
|
+
* @param {object} state The component's current state
|
|
78
|
+
* @param {object} context Context object, as returned by the nearest
|
|
79
|
+
* ancestor's `getChildContext()`
|
|
80
|
+
* @returns {import('./index').ComponentChildren | void}
|
|
81
|
+
*/
|
|
82
|
+
Component.prototype.render = Fragment;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {import('./internal').VNode} vnode
|
|
86
|
+
* @param {number | null} [childIndex]
|
|
87
|
+
*/
|
|
88
|
+
export function getDomSibling(vnode, childIndex?) {
|
|
89
|
+
if (childIndex == null) {
|
|
90
|
+
// Use childIndex==null as a signal to resume the search from the vnode's sibling
|
|
91
|
+
return vnode._parent
|
|
92
|
+
? getDomSibling(vnode._parent, vnode._parent._children.indexOf(vnode) + 1)
|
|
93
|
+
: null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let sibling;
|
|
97
|
+
for (; childIndex < vnode._children.length; childIndex++) {
|
|
98
|
+
sibling = vnode._children[childIndex];
|
|
99
|
+
|
|
100
|
+
if (sibling !== null && typeof sibling !== "undefined" && sibling._dom !== null) { // MODDED
|
|
101
|
+
// Since updateParentDomPointers keeps _dom pointer correct,
|
|
102
|
+
// we can rely on _dom to tell us if this subtree contains a
|
|
103
|
+
// rendered DOM node, and what the first rendered DOM node is
|
|
104
|
+
return sibling._dom;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// If we get here, we have not found a DOM node in this vnode's children.
|
|
109
|
+
// We must resume from this vnode's sibling (in it's parent _children array)
|
|
110
|
+
// Only climb up and search the parent if we aren't searching through a DOM
|
|
111
|
+
// VNode (meaning we reached the DOM parent of the original vnode that began
|
|
112
|
+
// the search)
|
|
113
|
+
return typeof vnode.type == 'function' ? getDomSibling(vnode) : null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Trigger in-place re-rendering of a component.
|
|
118
|
+
* @param {import('./internal').Component} component The component to rerender
|
|
119
|
+
*/
|
|
120
|
+
function renderComponent(component) {
|
|
121
|
+
let vnode = component._vnode,
|
|
122
|
+
oldDom = vnode._dom,
|
|
123
|
+
parentDom = component._parentDom;
|
|
124
|
+
|
|
125
|
+
if (parentDom) {
|
|
126
|
+
let commitQueue = [];
|
|
127
|
+
const oldVNode = assign({}, vnode);
|
|
128
|
+
oldVNode._original = vnode._original + 1;
|
|
129
|
+
|
|
130
|
+
diff(
|
|
131
|
+
parentDom,
|
|
132
|
+
vnode,
|
|
133
|
+
oldVNode,
|
|
134
|
+
component._globalContext,
|
|
135
|
+
parentDom.ownerSVGElement !== undefined,
|
|
136
|
+
vnode._hydrating != null ? [oldDom] : null,
|
|
137
|
+
commitQueue,
|
|
138
|
+
oldDom == null ? getDomSibling(vnode) : oldDom,
|
|
139
|
+
vnode._hydrating
|
|
140
|
+
);
|
|
141
|
+
commitRoot(commitQueue, vnode);
|
|
142
|
+
|
|
143
|
+
if (vnode._dom !== oldDom) { // MODDED
|
|
144
|
+
// parentDom.removeChild(oldDom) // MODDED
|
|
145
|
+
updateParentDomPointers(vnode);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param {import('./internal').VNode} vnode
|
|
152
|
+
*/
|
|
153
|
+
function updateParentDomPointers(vnode) {
|
|
154
|
+
if ((vnode = vnode._parent) !== null && vnode._component !== null) {
|
|
155
|
+
vnode._dom = vnode._component.base = null;
|
|
156
|
+
for (let i = 0; i < vnode._children.length; i++) {
|
|
157
|
+
let child = vnode._children[i];
|
|
158
|
+
if (child !== null && child._dom !== null) {
|
|
159
|
+
vnode._dom = vnode._component.base = child._dom;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return updateParentDomPointers(vnode);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The render queue
|
|
170
|
+
* @type {Array<import('./internal').Component>}
|
|
171
|
+
*/
|
|
172
|
+
let rerenderQueue: any[] = [];
|
|
173
|
+
|
|
174
|
+
/*
|
|
175
|
+
* The value of `Component.debounce` must asynchronously invoke the passed in callback. It is
|
|
176
|
+
* important that contributors to Preact can consistently reason about what calls to `setState`, etc.
|
|
177
|
+
* do, and when their effects will be applied. See the links below for some further reading on designing
|
|
178
|
+
* asynchronous APIs.
|
|
179
|
+
* * [Designing APIs for Asynchrony](https://blog.izs.me/2013/08/designing-apis-for-asynchrony)
|
|
180
|
+
* * [Callbacks synchronous and asynchronous](https://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/)
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
let prevDebounce;
|
|
184
|
+
|
|
185
|
+
// MODDED
|
|
186
|
+
// const defer =
|
|
187
|
+
// typeof Promise == 'function'
|
|
188
|
+
// ? Promise.prototype.then.bind(Promise.resolve())
|
|
189
|
+
// : setTimeout;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Enqueue a rerender of a component
|
|
193
|
+
* @param {import('./internal').Component} c The component to rerender
|
|
194
|
+
*/
|
|
195
|
+
export function enqueueRender(c) {
|
|
196
|
+
if (
|
|
197
|
+
(!c._dirty &&
|
|
198
|
+
(c._dirty = true) &&
|
|
199
|
+
rerenderQueue.push(c) &&
|
|
200
|
+
!process._rerenderCount++) ||
|
|
201
|
+
prevDebounce !== options.debounceRendering
|
|
202
|
+
) {
|
|
203
|
+
prevDebounce = options.debounceRendering;
|
|
204
|
+
(prevDebounce || setTimeout)(process);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @param {import('./internal').Component} a
|
|
210
|
+
* @param {import('./internal').Component} b
|
|
211
|
+
*/
|
|
212
|
+
const depthSort = (a, b) => a._vnode._depth - b._vnode._depth;
|
|
213
|
+
|
|
214
|
+
/** Flush the render queue by rerendering all queued components */
|
|
215
|
+
function process() {
|
|
216
|
+
let c;
|
|
217
|
+
rerenderQueue.sort(depthSort);
|
|
218
|
+
// Don't update `renderCount` yet. Keep its value non-zero to prevent unnecessary
|
|
219
|
+
// process() calls from getting scheduled while `queue` is still being consumed.
|
|
220
|
+
while ((c = rerenderQueue.shift())) {
|
|
221
|
+
if (c._dirty) {
|
|
222
|
+
let renderQueueLength = rerenderQueue.length;
|
|
223
|
+
renderComponent(c);
|
|
224
|
+
if (rerenderQueue.length > renderQueueLength) {
|
|
225
|
+
// When i.e. rerendering a provider additional new items can be injected, we want to
|
|
226
|
+
// keep the order from top to bottom with those new items so we can handle them in a
|
|
227
|
+
// single pass
|
|
228
|
+
rerenderQueue.sort(depthSort);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
process._rerenderCount = 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
process._rerenderCount = 0;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { enqueueRender } from './component';
|
|
2
|
+
|
|
3
|
+
export let i = 0;
|
|
4
|
+
|
|
5
|
+
export function createContext(defaultValue, contextId) {
|
|
6
|
+
contextId = '__cC' + i++;
|
|
7
|
+
|
|
8
|
+
const context: any = {
|
|
9
|
+
_id: contextId,
|
|
10
|
+
_defaultValue: defaultValue,
|
|
11
|
+
/** @type {import('./internal').FunctionComponent} */
|
|
12
|
+
Consumer(props, contextValue) {
|
|
13
|
+
// return props.children(
|
|
14
|
+
// context[contextId] ? context[contextId].props.value : defaultValue
|
|
15
|
+
// );
|
|
16
|
+
return props.children(contextValue);
|
|
17
|
+
},
|
|
18
|
+
/** @type {import('./internal').FunctionComponent} */
|
|
19
|
+
Provider(props) {
|
|
20
|
+
if (!this.getChildContext) {
|
|
21
|
+
let subs: any[] = [];
|
|
22
|
+
let ctx = {};
|
|
23
|
+
ctx[contextId] = this;
|
|
24
|
+
|
|
25
|
+
this.getChildContext = () => ctx;
|
|
26
|
+
|
|
27
|
+
this.shouldComponentUpdate = function(_props) {
|
|
28
|
+
if (this.props.value !== _props.value) {
|
|
29
|
+
// I think the forced value propagation here was only needed when `options.debounceRendering` was being bypassed:
|
|
30
|
+
// https://github.com/preactjs/preact/commit/4d339fb803bea09e9f198abf38ca1bf8ea4b7771#diff-54682ce380935a717e41b8bfc54737f6R358
|
|
31
|
+
// In those cases though, even with the value corrected, we're double-rendering all nodes.
|
|
32
|
+
// It might be better to just tell folks not to use force-sync mode.
|
|
33
|
+
// Currently, using `useContext()` in a class component will overwrite its `this.context` value.
|
|
34
|
+
// subs.some(c => {
|
|
35
|
+
// c.context = _props.value;
|
|
36
|
+
// enqueueRender(c);
|
|
37
|
+
// });
|
|
38
|
+
|
|
39
|
+
// subs.some(c => {
|
|
40
|
+
// c.context[contextId] = _props.value;
|
|
41
|
+
// enqueueRender(c);
|
|
42
|
+
// });
|
|
43
|
+
subs.some((c: any) => {
|
|
44
|
+
c._force = true;
|
|
45
|
+
enqueueRender(c);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
this.sub = (c: any) => {
|
|
51
|
+
subs.push(c);
|
|
52
|
+
let old = c.componentWillUnmount;
|
|
53
|
+
c.componentWillUnmount = () => {
|
|
54
|
+
subs.splice(subs.indexOf(c), 1);
|
|
55
|
+
if (old) old.call(c);
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return props.children;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Devtools needs access to the context object when it
|
|
65
|
+
// encounters a Provider. This is necessary to support
|
|
66
|
+
// setting `displayName` on the context object instead
|
|
67
|
+
// of on the component itself. See:
|
|
68
|
+
// https://reactjs.org/docs/context.html#contextdisplayname
|
|
69
|
+
|
|
70
|
+
return (context.Provider._contextRef = context.Consumer.contextType = context);
|
|
71
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { slice } from './util';
|
|
2
|
+
import options from './options';
|
|
3
|
+
|
|
4
|
+
let vnodeId = 0;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Create an virtual node (used for JSX)
|
|
8
|
+
* @param {import('./internal').VNode["type"]} type The node name or Component
|
|
9
|
+
* constructor for this virtual node
|
|
10
|
+
* @param {object | null | undefined} [props] The properties of the virtual node
|
|
11
|
+
* @param {Array<import('.').ComponentChildren>} [children] The children of the virtual node
|
|
12
|
+
* @returns {import('./internal').VNode}
|
|
13
|
+
*/
|
|
14
|
+
export function createElement(type, props, children) {
|
|
15
|
+
let normalizedProps: any = {},
|
|
16
|
+
key,
|
|
17
|
+
ref,
|
|
18
|
+
i;
|
|
19
|
+
for (i in props) {
|
|
20
|
+
if (i == 'key') key = props[i];
|
|
21
|
+
else if (i == 'ref') ref = props[i];
|
|
22
|
+
else normalizedProps[i] = props[i];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (arguments.length > 2) {
|
|
26
|
+
normalizedProps.children =
|
|
27
|
+
arguments.length > 3 ? slice.call(arguments, 2) : children;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// If a Component VNode, check for and apply defaultProps
|
|
31
|
+
// Note: type may be undefined in development, must never error here.
|
|
32
|
+
if (typeof type == 'function' && type.defaultProps != null) {
|
|
33
|
+
for (i in type.defaultProps) {
|
|
34
|
+
if (normalizedProps[i] === undefined) {
|
|
35
|
+
normalizedProps[i] = type.defaultProps[i];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return createVNode(type, normalizedProps, key, ref, null);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create a VNode (used internally by Preact)
|
|
45
|
+
* @param {import('./internal').VNode["type"]} type The node name or Component
|
|
46
|
+
* Constructor for this virtual node
|
|
47
|
+
* @param {object | string | number | null} props The properties of this virtual node.
|
|
48
|
+
* If this virtual node represents a text node, this is the text of the node (string or number).
|
|
49
|
+
* @param {string | number | null} key The key for this virtual node, used when
|
|
50
|
+
* diffing it against its children
|
|
51
|
+
* @param {import('./internal').VNode["ref"]} ref The ref property that will
|
|
52
|
+
* receive a reference to its created child
|
|
53
|
+
* @returns {import('./internal').VNode}
|
|
54
|
+
*/
|
|
55
|
+
export function createVNode(type, props, key, ref, original) {
|
|
56
|
+
// V8 seems to be better at detecting type shapes if the object is allocated from the same call site
|
|
57
|
+
// Do not inline into createElement and coerceToVNode!
|
|
58
|
+
const vnode = {
|
|
59
|
+
type,
|
|
60
|
+
props,
|
|
61
|
+
key,
|
|
62
|
+
ref,
|
|
63
|
+
_children: null,
|
|
64
|
+
_parent: null,
|
|
65
|
+
_depth: 0,
|
|
66
|
+
_dom: null,
|
|
67
|
+
// _nextDom must be initialized to undefined b/c it will eventually
|
|
68
|
+
// be set to dom.nextSibling which can return `null` and it is important
|
|
69
|
+
// to be able to distinguish between an uninitialized _nextDom and
|
|
70
|
+
// a _nextDom that has been set to `null`
|
|
71
|
+
_nextDom: undefined,
|
|
72
|
+
_component: null,
|
|
73
|
+
_hydrating: null,
|
|
74
|
+
constructor: undefined,
|
|
75
|
+
_original: original == null ? ++vnodeId : original
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Only invoke the vnode hook if this was *not* a direct copy:
|
|
79
|
+
if (original == null && options.vnode != null) options.vnode(vnode);
|
|
80
|
+
|
|
81
|
+
return vnode;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function createRef() {
|
|
85
|
+
return { current: null };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function Fragment(props) {
|
|
89
|
+
return props.children;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Check if a the argument is a valid Preact VNode.
|
|
94
|
+
* @param {*} vnode
|
|
95
|
+
* @returns {vnode is import('./internal').VNode}
|
|
96
|
+
*/
|
|
97
|
+
export const isValidElement = vnode =>
|
|
98
|
+
vnode != null && vnode.constructor === undefined;
|