@faiwer/react 0.8.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.
- package/README.md +90 -0
- package/dist/core/actions/applyAction.d.ts +11 -0
- package/dist/core/actions/applyAction.d.ts.map +1 -0
- package/dist/core/actions/applyAction.js +35 -0
- package/dist/core/actions/applyAction.js.map +1 -0
- package/dist/core/actions/createComment.action.d.ts +7 -0
- package/dist/core/actions/createComment.action.d.ts.map +1 -0
- package/dist/core/actions/createComment.action.js +20 -0
- package/dist/core/actions/createComment.action.js.map +1 -0
- package/dist/core/actions/createTag.action.d.ts +10 -0
- package/dist/core/actions/createTag.action.d.ts.map +1 -0
- package/dist/core/actions/createTag.action.js +27 -0
- package/dist/core/actions/createTag.action.js.map +1 -0
- package/dist/core/actions/createText.action.d.ts +6 -0
- package/dist/core/actions/createText.action.d.ts.map +1 -0
- package/dist/core/actions/createText.action.js +16 -0
- package/dist/core/actions/createText.action.js.map +1 -0
- package/dist/core/actions/helpers.d.ts +43 -0
- package/dist/core/actions/helpers.d.ts.map +1 -0
- package/dist/core/actions/helpers.js +141 -0
- package/dist/core/actions/helpers.js.map +1 -0
- package/dist/core/actions/relayout.action.d.ts +20 -0
- package/dist/core/actions/relayout.action.d.ts.map +1 -0
- package/dist/core/actions/relayout.action.js +113 -0
- package/dist/core/actions/relayout.action.js.map +1 -0
- package/dist/core/actions/remove.action.d.ts +7 -0
- package/dist/core/actions/remove.action.d.ts.map +1 -0
- package/dist/core/actions/remove.action.js +64 -0
- package/dist/core/actions/remove.action.js.map +1 -0
- package/dist/core/actions/replace.action.d.ts +18 -0
- package/dist/core/actions/replace.action.d.ts.map +1 -0
- package/dist/core/actions/replace.action.js +57 -0
- package/dist/core/actions/replace.action.js.map +1 -0
- package/dist/core/actions/setAttr.action.d.ts +9 -0
- package/dist/core/actions/setAttr.action.d.ts.map +1 -0
- package/dist/core/actions/setAttr.action.js +62 -0
- package/dist/core/actions/setAttr.action.js.map +1 -0
- package/dist/core/actions/setProps.action.d.ts +8 -0
- package/dist/core/actions/setProps.action.d.ts.map +1 -0
- package/dist/core/actions/setProps.action.js +13 -0
- package/dist/core/actions/setProps.action.js.map +1 -0
- package/dist/core/actions/setRef.action.d.ts +11 -0
- package/dist/core/actions/setRef.action.d.ts.map +1 -0
- package/dist/core/actions/setRef.action.js +38 -0
- package/dist/core/actions/setRef.action.js.map +1 -0
- package/dist/core/actions/setText.action.d.ts +7 -0
- package/dist/core/actions/setText.action.d.ts.map +1 -0
- package/dist/core/actions/setText.action.js +12 -0
- package/dist/core/actions/setText.action.js.map +1 -0
- package/dist/core/compact.d.ts +38 -0
- package/dist/core/compact.d.ts.map +1 -0
- package/dist/core/compact.js +112 -0
- package/dist/core/compact.js.map +1 -0
- package/dist/core/components.d.ts +32 -0
- package/dist/core/components.d.ts.map +1 -0
- package/dist/core/components.js +57 -0
- package/dist/core/components.js.map +1 -0
- package/dist/core/createElement.d.ts +47 -0
- package/dist/core/createElement.d.ts.map +1 -0
- package/dist/core/createElement.js +73 -0
- package/dist/core/createElement.js.map +1 -0
- package/dist/core/createRoot.d.ts +13 -0
- package/dist/core/createRoot.d.ts.map +1 -0
- package/dist/core/createRoot.js +33 -0
- package/dist/core/createRoot.js.map +1 -0
- package/dist/core/reactNodeToFiberNode.d.ts +8 -0
- package/dist/core/reactNodeToFiberNode.d.ts.map +1 -0
- package/dist/core/reactNodeToFiberNode.js +132 -0
- package/dist/core/reactNodeToFiberNode.js.map +1 -0
- package/dist/core/reconciliation/app.d.ts +5 -0
- package/dist/core/reconciliation/app.d.ts.map +1 -0
- package/dist/core/reconciliation/app.js +20 -0
- package/dist/core/reconciliation/app.js.map +1 -0
- package/dist/core/reconciliation/applyActions.d.ts +8 -0
- package/dist/core/reconciliation/applyActions.d.ts.map +1 -0
- package/dist/core/reconciliation/applyActions.js +12 -0
- package/dist/core/reconciliation/applyActions.js.map +1 -0
- package/dist/core/reconciliation/collect/fromApp.d.ts +9 -0
- package/dist/core/reconciliation/collect/fromApp.d.ts.map +1 -0
- package/dist/core/reconciliation/collect/fromApp.js +39 -0
- package/dist/core/reconciliation/collect/fromApp.js.map +1 -0
- package/dist/core/reconciliation/collect/fromChildrenPair.d.ts +9 -0
- package/dist/core/reconciliation/collect/fromChildrenPair.d.ts.map +1 -0
- package/dist/core/reconciliation/collect/fromChildrenPair.js +127 -0
- package/dist/core/reconciliation/collect/fromChildrenPair.js.map +1 -0
- package/dist/core/reconciliation/collect/fromComponent.d.ts +10 -0
- package/dist/core/reconciliation/collect/fromComponent.d.ts.map +1 -0
- package/dist/core/reconciliation/collect/fromComponent.js +22 -0
- package/dist/core/reconciliation/collect/fromComponent.js.map +1 -0
- package/dist/core/reconciliation/collect/fromFiberPair.d.ts +9 -0
- package/dist/core/reconciliation/collect/fromFiberPair.d.ts.map +1 -0
- package/dist/core/reconciliation/collect/fromFiberPair.js +125 -0
- package/dist/core/reconciliation/collect/fromFiberPair.js.map +1 -0
- package/dist/core/reconciliation/collect/fromNewFiber.d.ts +7 -0
- package/dist/core/reconciliation/collect/fromNewFiber.d.ts.map +1 -0
- package/dist/core/reconciliation/collect/fromNewFiber.js +45 -0
- package/dist/core/reconciliation/collect/fromNewFiber.js.map +1 -0
- package/dist/core/reconciliation/comments.d.ts +3 -0
- package/dist/core/reconciliation/comments.d.ts.map +1 -0
- package/dist/core/reconciliation/comments.js +3 -0
- package/dist/core/reconciliation/comments.js.map +1 -0
- package/dist/core/reconciliation/compare/areFiberNodesEq.d.ts +7 -0
- package/dist/core/reconciliation/compare/areFiberNodesEq.d.ts.map +1 -0
- package/dist/core/reconciliation/compare/areFiberNodesEq.js +14 -0
- package/dist/core/reconciliation/compare/areFiberNodesEq.js.map +1 -0
- package/dist/core/reconciliation/compare/areFiberPropsEq.d.ts +7 -0
- package/dist/core/reconciliation/compare/areFiberPropsEq.d.ts.map +1 -0
- package/dist/core/reconciliation/compare/areFiberPropsEq.js +18 -0
- package/dist/core/reconciliation/compare/areFiberPropsEq.js.map +1 -0
- package/dist/core/reconciliation/effects.d.ts +14 -0
- package/dist/core/reconciliation/effects.d.ts.map +1 -0
- package/dist/core/reconciliation/effects.js +26 -0
- package/dist/core/reconciliation/effects.js.map +1 -0
- package/dist/core/reconciliation/fibers.d.ts +35 -0
- package/dist/core/reconciliation/fibers.d.ts.map +1 -0
- package/dist/core/reconciliation/fibers.js +51 -0
- package/dist/core/reconciliation/fibers.js.map +1 -0
- package/dist/core/reconciliation/invalidateFiber.d.ts +8 -0
- package/dist/core/reconciliation/invalidateFiber.d.ts.map +1 -0
- package/dist/core/reconciliation/invalidateFiber.js +28 -0
- package/dist/core/reconciliation/invalidateFiber.js.map +1 -0
- package/dist/core/reconciliation/mount.d.ts +7 -0
- package/dist/core/reconciliation/mount.d.ts.map +1 -0
- package/dist/core/reconciliation/mount.js +53 -0
- package/dist/core/reconciliation/mount.js.map +1 -0
- package/dist/core/reconciliation/postCommit.d.ts +11 -0
- package/dist/core/reconciliation/postCommit.d.ts.map +1 -0
- package/dist/core/reconciliation/postCommit.js +47 -0
- package/dist/core/reconciliation/postCommit.js.map +1 -0
- package/dist/core/reconciliation/render.d.ts +11 -0
- package/dist/core/reconciliation/render.d.ts.map +1 -0
- package/dist/core/reconciliation/render.js +35 -0
- package/dist/core/reconciliation/render.js.map +1 -0
- package/dist/core/reconciliation/runFiberComponents.d.ts +10 -0
- package/dist/core/reconciliation/runFiberComponents.d.ts.map +1 -0
- package/dist/core/reconciliation/runFiberComponents.js +37 -0
- package/dist/core/reconciliation/runFiberComponents.js.map +1 -0
- package/dist/core/reconciliation/typeGuards.d.ts +12 -0
- package/dist/core/reconciliation/typeGuards.d.ts.map +1 -0
- package/dist/core/reconciliation/typeGuards.js +32 -0
- package/dist/core/reconciliation/typeGuards.js.map +1 -0
- package/dist/core/reconciliation/validateTree.d.ts +6 -0
- package/dist/core/reconciliation/validateTree.d.ts.map +1 -0
- package/dist/core/reconciliation/validateTree.js +48 -0
- package/dist/core/reconciliation/validateTree.js.map +1 -0
- package/dist/hooks/helpers.d.ts +19 -0
- package/dist/hooks/helpers.d.ts.map +1 -0
- package/dist/hooks/helpers.js +40 -0
- package/dist/hooks/helpers.js.map +1 -0
- package/dist/hooks/index.d.ts +9 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +9 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useCallback.d.ts +2 -0
- package/dist/hooks/useCallback.d.ts.map +1 -0
- package/dist/hooks/useCallback.js +5 -0
- package/dist/hooks/useCallback.js.map +1 -0
- package/dist/hooks/useContext.d.ts +37 -0
- package/dist/hooks/useContext.d.ts.map +1 -0
- package/dist/hooks/useContext.js +101 -0
- package/dist/hooks/useContext.js.map +1 -0
- package/dist/hooks/useEffect.d.ts +48 -0
- package/dist/hooks/useEffect.d.ts.map +1 -0
- package/dist/hooks/useEffect.js +100 -0
- package/dist/hooks/useEffect.js.map +1 -0
- package/dist/hooks/useId.d.ts +2 -0
- package/dist/hooks/useId.d.ts.map +1 -0
- package/dist/hooks/useId.js +10 -0
- package/dist/hooks/useId.js.map +1 -0
- package/dist/hooks/useMemo.d.ts +20 -0
- package/dist/hooks/useMemo.d.ts.map +1 -0
- package/dist/hooks/useMemo.js +33 -0
- package/dist/hooks/useMemo.js.map +1 -0
- package/dist/hooks/useRef.d.ts +4 -0
- package/dist/hooks/useRef.d.ts.map +1 -0
- package/dist/hooks/useRef.js +9 -0
- package/dist/hooks/useRef.js.map +1 -0
- package/dist/hooks/useStableCallback.d.ts +45 -0
- package/dist/hooks/useStableCallback.d.ts.map +1 -0
- package/dist/hooks/useStableCallback.js +66 -0
- package/dist/hooks/useStableCallback.js.map +1 -0
- package/dist/hooks/useState.d.ts +15 -0
- package/dist/hooks/useState.d.ts.map +1 -0
- package/dist/hooks/useState.js +39 -0
- package/dist/hooks/useState.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +6 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +7 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +31 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +32 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/testing.d.ts +8 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +10 -0
- package/dist/testing.js.map +1 -0
- package/dist/types/actions.d.ts +53 -0
- package/dist/types/actions.d.ts.map +1 -0
- package/dist/types/actions.js +2 -0
- package/dist/types/actions.js.map +1 -0
- package/dist/types/app.d.ts +74 -0
- package/dist/types/app.d.ts.map +1 -0
- package/dist/types/app.js +2 -0
- package/dist/types/app.js.map +1 -0
- package/dist/types/component.d.ts +11 -0
- package/dist/types/component.d.ts.map +1 -0
- package/dist/types/component.js +2 -0
- package/dist/types/component.js.map +1 -0
- package/dist/types/context.d.ts +28 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +2 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/core.d.ts +51 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +2 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/dom.d.ts +48 -0
- package/dist/types/dom.d.ts.map +1 -0
- package/dist/types/dom.js +2 -0
- package/dist/types/dom.js.map +1 -0
- package/dist/types/fiber.d.ts +169 -0
- package/dist/types/fiber.d.ts.map +1 -0
- package/dist/types/fiber.js +2 -0
- package/dist/types/fiber.js.map +1 -0
- package/dist/types/hooks.d.ts +47 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/hooks.js +2 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/refs.d.ts +19 -0
- package/dist/types/refs.d.ts.map +1 -0
- package/dist/types/refs.js +2 -0
- package/dist/types/refs.js.map +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +7 -0
- package/dist/utils.js.map +1 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
## What is it?
|
|
2
|
+
|
|
3
|
+
A naive React implementation. Why? What's wrong with the existing one? Nothing. I just wanted to implement it from scratch by myself. It can be used as a drop-in replacement for some simple React apps. May require some trivial changes, though.
|
|
4
|
+
|
|
5
|
+
## It supports
|
|
6
|
+
|
|
7
|
+
- JSX
|
|
8
|
+
- Functional components
|
|
9
|
+
- Hooks:
|
|
10
|
+
- `useState`
|
|
11
|
+
- `useRef`
|
|
12
|
+
- `useMemo`, `useCallback`
|
|
13
|
+
- `useStableCallback` (better version of `useEffectEvent`)
|
|
14
|
+
- `useLayoutEffect`, `useEffect` (improved versions)
|
|
15
|
+
- `useId`
|
|
16
|
+
- `useContext`
|
|
17
|
+
- Tag-based refs
|
|
18
|
+
- Context
|
|
19
|
+
- Portals
|
|
20
|
+
- Fragments
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
- `npm i --save @faiwer/react`
|
|
25
|
+
- Update your `tsconfig.json`:
|
|
26
|
+
```json
|
|
27
|
+
"compilerOptions": {
|
|
28
|
+
"jsx": "react-jsx",
|
|
29
|
+
"jsxImportSource": "@faiwer/react"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Usage
|
|
34
|
+
|
|
35
|
+
To mount an app:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
const container = document.getElementById('root');
|
|
39
|
+
createRoot(container).render(<App />);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## TODO
|
|
43
|
+
|
|
44
|
+
- 1st line
|
|
45
|
+
- Support tag-`style` attribute
|
|
46
|
+
- Events:
|
|
47
|
+
- "capture"-kind of events
|
|
48
|
+
- camelCase events
|
|
49
|
+
- custom `onChange` like in ReactDOM
|
|
50
|
+
- Error handling
|
|
51
|
+
- Direct component refs, `forwardRef`, `useImperativeHandle`
|
|
52
|
+
- 2nd line
|
|
53
|
+
- prepare an NPM-package
|
|
54
|
+
- 3rd line
|
|
55
|
+
- `RunComponent` is not pure. Some hooks change the state during the rendering phase. Fix it.
|
|
56
|
+
- `useReducer`
|
|
57
|
+
|
|
58
|
+
## It does NOT support
|
|
59
|
+
|
|
60
|
+
… and probably never will:
|
|
61
|
+
|
|
62
|
+
- Class Components
|
|
63
|
+
- Synthetic events
|
|
64
|
+
- Portals:
|
|
65
|
+
- Event bubbling from portals
|
|
66
|
+
- Rendering multiple portals in the same DOM node
|
|
67
|
+
- `memo` (because components are memoized by default)
|
|
68
|
+
- Some less popular tools
|
|
69
|
+
- `useInsertionEffect`
|
|
70
|
+
- `useOptimistic` (could be polyfilled)
|
|
71
|
+
- `useDeferredValue` (could be polyfilled)
|
|
72
|
+
- `useDebugValue` (dev tools are not supported)
|
|
73
|
+
- `<StrictMode/>`.
|
|
74
|
+
- `<Profiler/>`.
|
|
75
|
+
- `preconnect`, `prefetchDNS`, `preinit`, `preinitModule`, `preload`, `preloadModule`
|
|
76
|
+
- Modern stuff:
|
|
77
|
+
- `useTransition`, `startTransition`
|
|
78
|
+
- `<Suspense/>`, `lazy`.
|
|
79
|
+
- Form-based hooks (like `useActionState`, `useFormStatus`)
|
|
80
|
+
- React Dev Tools. Just take a look at `__REACT_DEVTOOLS_GLOBAL_HOOK__`, it's huge. E.g., it has `reactDevtoolsAgent`, a class with 20-30 methods…
|
|
81
|
+
- `flushSync` (not supported by the engine)
|
|
82
|
+
- SSR
|
|
83
|
+
|
|
84
|
+
## Major differences
|
|
85
|
+
|
|
86
|
+
- It renders HTML-comment for nullable nodes and some fragments. Why? It helps a lot to keep the reconciliation algorithm simple. Took this idea from Angular.
|
|
87
|
+
- No synthetic events. I don't see any reason to implement them.
|
|
88
|
+
- All components are memoized by default. Why not?
|
|
89
|
+
- No custom DOM-related code. This library is supposed to be simple and silly. Whereas React-DOM lib is huge.
|
|
90
|
+
- No modern fiber-driven stuff like `<Suspense>`, `cacheSignal`, or `use`. Too much work. It took React many years to cook it well :)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Action } from '../../types/actions';
|
|
2
|
+
/**
|
|
3
|
+
* The commit phase of the rendering process contains two parts:
|
|
4
|
+
* - Applying DOM changes
|
|
5
|
+
* - Running effects
|
|
6
|
+
*
|
|
7
|
+
* DOM changes are described in actions. This function applies the given action
|
|
8
|
+
* to the DOM and updates the bound fiber node accordingly.
|
|
9
|
+
*/
|
|
10
|
+
export declare const applyAction: (action: Action) => void;
|
|
11
|
+
//# sourceMappingURL=applyAction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyAction.d.ts","sourceRoot":"","sources":["../../../src/core/actions/applyAction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAYzD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,0BAGvB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createTagAction } from './createTag.action';
|
|
2
|
+
import { createTextAction } from './createText.action';
|
|
3
|
+
import { createCommentAction } from './createComment.action';
|
|
4
|
+
import { setPropsAction } from './setProps.action';
|
|
5
|
+
import { setRefAction } from './setRef.action';
|
|
6
|
+
import { setAttrAction } from './setAttr.action';
|
|
7
|
+
import { setTextAction } from './setText.action';
|
|
8
|
+
import { removeAction } from './remove.action';
|
|
9
|
+
import { replaceAction } from './replace.action';
|
|
10
|
+
import { relayoutAction } from './relayout.action';
|
|
11
|
+
/**
|
|
12
|
+
* The commit phase of the rendering process contains two parts:
|
|
13
|
+
* - Applying DOM changes
|
|
14
|
+
* - Running effects
|
|
15
|
+
*
|
|
16
|
+
* DOM changes are described in actions. This function applies the given action
|
|
17
|
+
* to the DOM and updates the bound fiber node accordingly.
|
|
18
|
+
*/
|
|
19
|
+
export const applyAction = (action) => {
|
|
20
|
+
// @ts-ignore -- too complex type.
|
|
21
|
+
actionHandlers[action.type](action.fiber, action);
|
|
22
|
+
};
|
|
23
|
+
const actionHandlers = {
|
|
24
|
+
CreateTag: createTagAction,
|
|
25
|
+
CreateText: createTextAction,
|
|
26
|
+
CreateComment: createCommentAction,
|
|
27
|
+
SetProps: setPropsAction,
|
|
28
|
+
SetRef: setRefAction,
|
|
29
|
+
SetAttr: setAttrAction,
|
|
30
|
+
SetText: setTextAction,
|
|
31
|
+
Remove: removeAction,
|
|
32
|
+
Replace: replaceAction,
|
|
33
|
+
Relayout: relayoutAction,
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=applyAction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyAction.js","sourceRoot":"","sources":["../../../src/core/actions/applyAction.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAc,EAAQ,EAAE,CAAC;IACnD,kCAAkC;IAClC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAa,CAAC,CAAC;AAAA,CAC1D,CAAC;AAEF,MAAM,cAAc,GAKhB;IACF,SAAS,EAAE,eAAe;IAC1B,UAAU,EAAE,gBAAgB;IAC5B,aAAa,EAAE,mBAAmB;IAClC,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,aAAa;IACtB,OAAO,EAAE,aAAa;IACtB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,cAAc;CACzB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FiberNode } from '../../types';
|
|
2
|
+
import type { CreateCommentAction } from '../../types/actions';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new comment DOM node (<!--r:${mode}:${fiber.id}-->).
|
|
5
|
+
*/
|
|
6
|
+
export declare function createCommentAction(fiber: FiberNode, { mode }: CreateCommentAction): void;
|
|
7
|
+
//# sourceMappingURL=createComment.action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createComment.action.d.ts","sourceRoot":"","sources":["../../../src/core/actions/createComment.action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAKtE;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,EAChB,EAAE,IAAI,EAAE,EAAE,mBAAmB,QAc9B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getParentElement } from './helpers';
|
|
2
|
+
import { tryToCompactNode } from '../compact';
|
|
3
|
+
import { buildComment } from '../reconciliation/comments';
|
|
4
|
+
/**
|
|
5
|
+
* Creates a new comment DOM node (<!--r:${mode}:${fiber.id}-->).
|
|
6
|
+
*/
|
|
7
|
+
export function createCommentAction(fiber, { mode }) {
|
|
8
|
+
// Only two scenarios lead here:
|
|
9
|
+
// - First render of a fragment or component. The parent's element is a
|
|
10
|
+
// comment `r:begin:{id}`
|
|
11
|
+
// - Render of a portal. The parent element is the portal target node.
|
|
12
|
+
fiber.element = buildComment(mode, fiber.id);
|
|
13
|
+
getParentElement(fiber).appendChild(fiber.element);
|
|
14
|
+
if (mode === 'end') {
|
|
15
|
+
// All children are added. If the current fiber is the only child, we can
|
|
16
|
+
// compact the parent node: "<!--begin-->child<!--end-->" -> "child".
|
|
17
|
+
tryToCompactNode(fiber);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=createComment.action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createComment.action.js","sourceRoot":"","sources":["../../../src/core/actions/createComment.action.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAgB,EAChB,EAAE,IAAI,EAAuB,EAC7B;IACA,gCAAgC;IAChC,uEAAuE;IACvE,2BAA2B;IAC3B,sEAAsE;IACtE,KAAK,CAAC,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7C,gBAAgB,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,yEAAyE;QACzE,qEAAqE;QACrE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;AAAA,CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FiberNode } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Handles two scenarios:
|
|
4
|
+
* - Creates a <!--r:portal:id--> comment for portal fibers
|
|
5
|
+
* - Creates a new tag DOM element for tag fibers
|
|
6
|
+
*
|
|
7
|
+
* This doesn't create child nodes or set attributes/event handlers.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createTagAction(fiber: FiberNode): void;
|
|
10
|
+
//# sourceMappingURL=createTag.action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTag.action.d.ts","sourceRoot":"","sources":["../../../src/core/actions/createTag.action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIpD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAgBtD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getParentElement } from './helpers';
|
|
2
|
+
import { applyAction } from './applyAction';
|
|
3
|
+
/**
|
|
4
|
+
* Handles two scenarios:
|
|
5
|
+
* - Creates a <!--r:portal:id--> comment for portal fibers
|
|
6
|
+
* - Creates a new tag DOM element for tag fibers
|
|
7
|
+
*
|
|
8
|
+
* This doesn't create child nodes or set attributes/event handlers.
|
|
9
|
+
*/
|
|
10
|
+
export function createTagAction(fiber) {
|
|
11
|
+
if (fiber.type !== 'tag') {
|
|
12
|
+
throw new Error(`createTagAction supports only tag-fiber-nodes.`);
|
|
13
|
+
}
|
|
14
|
+
if (fiber.data instanceof HTMLElement) {
|
|
15
|
+
// This is a portal, not a regular tag. We shouldn't create it since it
|
|
16
|
+
// already exists outside the app's DOM subtree. Instead, create a
|
|
17
|
+
// <!--r:portal:id--> comment node.
|
|
18
|
+
applyAction({ type: 'CreateComment', fiber, mode: 'portal' });
|
|
19
|
+
}
|
|
20
|
+
else if (fiber.tag !== 'root') {
|
|
21
|
+
// 'root' is a special case - it's the node where the app is mounted.
|
|
22
|
+
const tag = document.createElement(fiber.tag);
|
|
23
|
+
fiber.element = tag;
|
|
24
|
+
getParentElement(fiber).appendChild(fiber.element);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=createTag.action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTag.action.js","sourceRoot":"","sources":["../../../src/core/actions/createTag.action.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAAgB,EAAQ;IACtD,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,YAAY,WAAW,EAAE,CAAC;QACtC,uEAAuE;QACvE,kEAAkE;QAClE,mCAAmC;QACnC,WAAW,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;SAAM,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC;QAChC,qEAAqE;QACrE,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9C,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;QACpB,gBAAgB,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;AAAA,CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createText.action.d.ts","sourceRoot":"","sources":["../../../src/core/actions/createText.action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGpD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,QAWhD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getParentElement } from './helpers';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new text DOM node.
|
|
4
|
+
*/
|
|
5
|
+
export function createTextAction(fiber) {
|
|
6
|
+
if (fiber.type !== 'text') {
|
|
7
|
+
throw new Error(`Can't apply CreateText for a ${fiber.type} node`);
|
|
8
|
+
}
|
|
9
|
+
// Only two scenarios lead here:
|
|
10
|
+
// - First render of a fragment or component. The parent's element is
|
|
11
|
+
// a comment `r:begin:{id}`
|
|
12
|
+
// - Render of a portal. The parent element is the portal target node.
|
|
13
|
+
fiber.element = new Text(fiber.props.text);
|
|
14
|
+
getParentElement(fiber).appendChild(fiber.element);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=createText.action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createText.action.js","sourceRoot":"","sources":["../../../src/core/actions/createText.action.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAgB,EAAE;IACjD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC;IACrE,CAAC;IAED,gCAAgC;IAChC,qEAAqE;IACrE,6BAA6B;IAC7B,sEAAsE;IACtE,KAAK,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3C,gBAAgB,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAAA,CACpD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DomNode, FiberNode, Ref, RefSetter } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Determines if a prop name represents an event handler by checking if it
|
|
4
|
+
* starts with "on". This follows React's convention where any prop beginning
|
|
5
|
+
* with "on" is treated as an event listener rather than a regular DOM
|
|
6
|
+
* attribute.
|
|
7
|
+
*
|
|
8
|
+
* While HTML technically allows non-event attributes starting with "on", no
|
|
9
|
+
* such attributes could be found in practice. React filters out all "on*" props
|
|
10
|
+
* as event handlers, and this implementation follows the same pattern for
|
|
11
|
+
* consistency.
|
|
12
|
+
*/
|
|
13
|
+
export declare const isEventName: (name: string) => boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Returns the DOM container for the given fiber node. This isn't always the
|
|
16
|
+
* direct parent's element since the parent might be a compact node or a
|
|
17
|
+
* fragment-like range (<!--begin|end-->), or it could be a portal node.
|
|
18
|
+
*/
|
|
19
|
+
export declare const getParentElement: (fiber: FiberNode) => Element;
|
|
20
|
+
/**
|
|
21
|
+
* Finds the anchor node for attaching other nodes. There are two scenarios:
|
|
22
|
+
* 1) [element, null] - the new node should be added to the beginning of the
|
|
23
|
+
* element;
|
|
24
|
+
* 2) [element, child] - the new node should be added right after `child`.
|
|
25
|
+
*/
|
|
26
|
+
export declare const getAnchor: (fiber: FiberNode) => [Element, Node | null];
|
|
27
|
+
/**
|
|
28
|
+
* Returns all direct DOM nodes associated with the given fiber. This isn't
|
|
29
|
+
* always a single node since components and fragments may be in expanded state
|
|
30
|
+
* (<!--begin--> + content + <!--end-->).
|
|
31
|
+
*/
|
|
32
|
+
export declare const getFiberDomNodes: (fiber: FiberNode) => DomNode[];
|
|
33
|
+
/**
|
|
34
|
+
* When a node leaves the DOM tree, we need to update all associated ref
|
|
35
|
+
* objects and ref handlers.
|
|
36
|
+
*/
|
|
37
|
+
export declare const unsetRef: <T>(ref: Ref<T | null> | RefSetter<T | null>) => void;
|
|
38
|
+
/**
|
|
39
|
+
* To help avoid memory leaks, this method removes fiber properties that
|
|
40
|
+
* can hold references to other objects.
|
|
41
|
+
*/
|
|
42
|
+
export declare const emptyFiberNode: (fiber: FiberNode) => void;
|
|
43
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/core/actions/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAM7E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,2BAAmD,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,+BAa5B,CAAC;AA6BF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,8CAiCrB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,iCAwB5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,mDAMzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,4BAQ1B,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { nullthrows } from '../../utils';
|
|
2
|
+
import { isBeginOf, isCompactNone, isCompactSingleChild } from '../compact';
|
|
3
|
+
import { NULL_FIBER } from '../reconciliation/fibers';
|
|
4
|
+
import { buildCommentText } from '../reconciliation/comments';
|
|
5
|
+
/**
|
|
6
|
+
* Determines if a prop name represents an event handler by checking if it
|
|
7
|
+
* starts with "on". This follows React's convention where any prop beginning
|
|
8
|
+
* with "on" is treated as an event listener rather than a regular DOM
|
|
9
|
+
* attribute.
|
|
10
|
+
*
|
|
11
|
+
* While HTML technically allows non-event attributes starting with "on", no
|
|
12
|
+
* such attributes could be found in practice. React filters out all "on*" props
|
|
13
|
+
* as event handlers, and this implementation follows the same pattern for
|
|
14
|
+
* consistency.
|
|
15
|
+
*/
|
|
16
|
+
export const isEventName = (name) => name.startsWith('on');
|
|
17
|
+
/**
|
|
18
|
+
* Returns the DOM container for the given fiber node. This isn't always the
|
|
19
|
+
* direct parent's element since the parent might be a compact node or a
|
|
20
|
+
* fragment-like range (<!--begin|end-->), or it could be a portal node.
|
|
21
|
+
*/
|
|
22
|
+
export const getParentElement = (fiber) => {
|
|
23
|
+
while (fiber.parent.type === 'component' ||
|
|
24
|
+
fiber.parent.type === 'fragment') {
|
|
25
|
+
fiber = fiber.parent; // Has to be "tag".
|
|
26
|
+
}
|
|
27
|
+
if (fiber.parent.data instanceof HTMLElement) {
|
|
28
|
+
return fiber.parent.data; // Portal.
|
|
29
|
+
}
|
|
30
|
+
return nullthrows(fiber.parent?.element);
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Finds the !--begin comment for the given !--end comment.
|
|
34
|
+
*/
|
|
35
|
+
const getBeginComment = (fiber) => {
|
|
36
|
+
let node = asComment(fiber.element).previousSibling;
|
|
37
|
+
const text = buildCommentText('begin', fiber.id);
|
|
38
|
+
while (!(node instanceof Comment) || node.textContent !== text)
|
|
39
|
+
node = nullthrows(node.previousSibling);
|
|
40
|
+
return node;
|
|
41
|
+
};
|
|
42
|
+
const asElement = (node) => {
|
|
43
|
+
if (!(node instanceof Element)) {
|
|
44
|
+
throw new Error(`node is not element`);
|
|
45
|
+
}
|
|
46
|
+
return node;
|
|
47
|
+
};
|
|
48
|
+
const asComment = (node) => {
|
|
49
|
+
if (!(node instanceof Comment)) {
|
|
50
|
+
throw new Error(`node is not comment`);
|
|
51
|
+
}
|
|
52
|
+
return node;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Finds the anchor node for attaching other nodes. There are two scenarios:
|
|
56
|
+
* 1) [element, null] - the new node should be added to the beginning of the
|
|
57
|
+
* element;
|
|
58
|
+
* 2) [element, child] - the new node should be added right after `child`.
|
|
59
|
+
*/
|
|
60
|
+
export const getAnchor = (fiber) => {
|
|
61
|
+
if (fiber.type === 'tag') {
|
|
62
|
+
return [
|
|
63
|
+
asElement(fiber.data instanceof HTMLElement
|
|
64
|
+
? fiber.data // Portal's `element` is !--r:portal
|
|
65
|
+
: fiber.element),
|
|
66
|
+
null,
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
if (fiber.type === 'component' || fiber.type === 'fragment') {
|
|
70
|
+
if (isCompactSingleChild(fiber)) {
|
|
71
|
+
throw new Error(`Solo-compact fibers cannot be used as an anchor`);
|
|
72
|
+
}
|
|
73
|
+
if (isCompactNone(fiber)) {
|
|
74
|
+
throw new Error(`Cannot use !--empty node as an anchor`);
|
|
75
|
+
}
|
|
76
|
+
// E.g.
|
|
77
|
+
// <div>
|
|
78
|
+
// <something/>
|
|
79
|
+
// <!--r:begin:1--> // a component or a fragment
|
|
80
|
+
// … // the content of the `fiber`
|
|
81
|
+
// <!--r:end:1-->
|
|
82
|
+
// <something/>
|
|
83
|
+
return [getParentElement(fiber), getBeginComment(fiber)];
|
|
84
|
+
}
|
|
85
|
+
// "text" & "null" types cannot contain children.
|
|
86
|
+
throw new Error(`Unsupported anchor type: ${fiber.type}`);
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Returns all direct DOM nodes associated with the given fiber. This isn't
|
|
90
|
+
* always a single node since components and fragments may be in expanded state
|
|
91
|
+
* (<!--begin--> + content + <!--end-->).
|
|
92
|
+
*/
|
|
93
|
+
export const getFiberDomNodes = (fiber) => {
|
|
94
|
+
switch (fiber.type) {
|
|
95
|
+
case 'component':
|
|
96
|
+
case 'fragment': {
|
|
97
|
+
if (isCompactSingleChild(fiber) || isCompactNone(fiber)) {
|
|
98
|
+
return [fiber.element];
|
|
99
|
+
}
|
|
100
|
+
// Collect [!--begin, …content, !--end]:
|
|
101
|
+
const list = [nullthrows(fiber.element)];
|
|
102
|
+
let prev = nullthrows(list[0].previousSibling);
|
|
103
|
+
while (prev && !isBeginOf(prev, fiber)) {
|
|
104
|
+
list.push(prev);
|
|
105
|
+
prev = nullthrows(prev.previousSibling);
|
|
106
|
+
}
|
|
107
|
+
list.push(prev);
|
|
108
|
+
return list.reverse();
|
|
109
|
+
}
|
|
110
|
+
case 'null':
|
|
111
|
+
case 'tag':
|
|
112
|
+
case 'text':
|
|
113
|
+
return [nullthrows(fiber.element)];
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* When a node leaves the DOM tree, we need to update all associated ref
|
|
118
|
+
* objects and ref handlers.
|
|
119
|
+
*/
|
|
120
|
+
export const unsetRef = (ref) => {
|
|
121
|
+
if (typeof ref === 'function') {
|
|
122
|
+
ref(null);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
ref.current = null;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* To help avoid memory leaks, this method removes fiber properties that
|
|
130
|
+
* can hold references to other objects.
|
|
131
|
+
*/
|
|
132
|
+
export const emptyFiberNode = (fiber) => {
|
|
133
|
+
fiber.data = null;
|
|
134
|
+
fiber.element = null;
|
|
135
|
+
fiber.component = null;
|
|
136
|
+
fiber.children = [];
|
|
137
|
+
fiber.props = null;
|
|
138
|
+
fiber.ref = null;
|
|
139
|
+
fiber.parent = NULL_FIBER;
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/core/actions/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FiberNode } from '../../types';
|
|
2
|
+
import type { RelayoutAction } from '../../types/actions';
|
|
3
|
+
/**
|
|
4
|
+
* Handles fiber tree layout updates when children have been modified. This
|
|
5
|
+
* action is triggered when:
|
|
6
|
+
* - A direct child was removed or replaced
|
|
7
|
+
* - Child order changed (for keyed children)
|
|
8
|
+
* - A new child was added
|
|
9
|
+
*
|
|
10
|
+
* The relayout process:
|
|
11
|
+
* - Moves new children from temporary containers (`<x-container/>`) to their
|
|
12
|
+
* final DOM position
|
|
13
|
+
* - Repositions existing children to match the new order
|
|
14
|
+
* - Updates the fiber's children array to reflect the new structure
|
|
15
|
+
*
|
|
16
|
+
* Note: This action only handles positioning and insertion. All node removals
|
|
17
|
+
* must be completed before this action runs.
|
|
18
|
+
*/
|
|
19
|
+
export declare function relayoutAction(fiber: FiberNode, { before, after }: RelayoutAction): void;
|
|
20
|
+
//# sourceMappingURL=relayout.action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relayout.action.d.ts","sourceRoot":"","sources":["../../../src/core/actions/relayout.action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAUjE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,EAChB,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,cAAc,QAuClC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { isCompactNone, isCompactSingleChild, tryToCompactNode, unwrapCompactFiber, } from '../compact';
|
|
2
|
+
import { getAnchor, getFiberDomNodes } from './helpers';
|
|
3
|
+
import { nullthrows } from '../../utils';
|
|
4
|
+
/**
|
|
5
|
+
* Handles fiber tree layout updates when children have been modified. This
|
|
6
|
+
* action is triggered when:
|
|
7
|
+
* - A direct child was removed or replaced
|
|
8
|
+
* - Child order changed (for keyed children)
|
|
9
|
+
* - A new child was added
|
|
10
|
+
*
|
|
11
|
+
* The relayout process:
|
|
12
|
+
* - Moves new children from temporary containers (`<x-container/>`) to their
|
|
13
|
+
* final DOM position
|
|
14
|
+
* - Repositions existing children to match the new order
|
|
15
|
+
* - Updates the fiber's children array to reflect the new structure
|
|
16
|
+
*
|
|
17
|
+
* Note: This action only handles positioning and insertion. All node removals
|
|
18
|
+
* must be completed before this action runs.
|
|
19
|
+
*/
|
|
20
|
+
export function relayoutAction(fiber, { before, after }) {
|
|
21
|
+
if (after.size > 0) {
|
|
22
|
+
// If `fiber` is in compact mode we may need to unwrap it.
|
|
23
|
+
expandFiberWhenNeeded(fiber, after);
|
|
24
|
+
}
|
|
25
|
+
if (after.size > 0) {
|
|
26
|
+
// Determine what can be used as a starting point for inserting new children.
|
|
27
|
+
// If `prev` is `null`, new nodes should be added to the beginning.
|
|
28
|
+
// Otherwise, add them right after the `prev` node.
|
|
29
|
+
let [container, prev] = getAnchor(fiber);
|
|
30
|
+
for (const [key, r] of after) {
|
|
31
|
+
const l = before.get(key);
|
|
32
|
+
if (!l) {
|
|
33
|
+
// No nodes from `left` correlate with this node from `right`.
|
|
34
|
+
// Consider it a brand new node and put it at the current position.
|
|
35
|
+
prev = insertNewFiber(fiber, container, prev, r.fiber);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Keep DOM nodes from the previous render. Any requested updates for
|
|
39
|
+
// them are already applied, but we might need to reposition them
|
|
40
|
+
// within their parent.
|
|
41
|
+
prev = repositionFiberWhenNeeded(l.fiber, container, prev);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Replace fiber.children with fibers from the `after` set.
|
|
46
|
+
// Skip any nodes whose keys exist in `before`, since those are either
|
|
47
|
+
// unchanged or already updated (their `after` entries served only as
|
|
48
|
+
// references for the update process).
|
|
49
|
+
fiber.children = [...after.keys()].map((key) => nullthrows(before.get(key) ?? after.get(key)).fiber);
|
|
50
|
+
// If `fiber` has 0 or 1 DOM children, we can remove <!--begin|end--> brackets.
|
|
51
|
+
tryToCompactNode(fiber);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* If the given fiber (a container) is in the compact mode we might need to
|
|
55
|
+
* unwrap it.
|
|
56
|
+
*/
|
|
57
|
+
const expandFiberWhenNeeded = (fiber, after) => {
|
|
58
|
+
if (isCompactNone(fiber)) {
|
|
59
|
+
// Case 1: it's <!--empty-->. It can't have children, so fix it.
|
|
60
|
+
unwrapCompactFiber(fiber);
|
|
61
|
+
}
|
|
62
|
+
else if (isCompactSingleChild(fiber)) {
|
|
63
|
+
if (after.size > 1) {
|
|
64
|
+
// Case 2: It's in "single child" mode. Fix it to support multiple children.
|
|
65
|
+
unwrapCompactFiber(fiber);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
throw new Error(`Invalid state: "remove" action didn't unwrap the parent container node during deletion of the only child`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Puts the given `child` DOM nodes into the `parent`'s DOM area at the anchor
|
|
74
|
+
* position (`container` + `prev`). Updates the `child`'s parent node.
|
|
75
|
+
*/
|
|
76
|
+
const insertNewFiber = (parent, container, prev, child) => {
|
|
77
|
+
const newChildren = [...child.parent.element.childNodes];
|
|
78
|
+
if (!prev) {
|
|
79
|
+
container.prepend(...newChildren);
|
|
80
|
+
prev = nullthrows(newChildren.at(-1));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
for (const n of newChildren) {
|
|
84
|
+
container.insertBefore(n, prev.nextSibling);
|
|
85
|
+
prev = n;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
child.parent = parent; // <x-container/> -> real parent.
|
|
89
|
+
return prev;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Repositioning is needed in such situations:
|
|
93
|
+
* - before: <a/><b/><c key="c"/> -> <c key="c"/><a/><b/>.
|
|
94
|
+
*/
|
|
95
|
+
const repositionFiberWhenNeeded = (fiber, container, prev) => {
|
|
96
|
+
const nodes = getFiberDomNodes(fiber);
|
|
97
|
+
if (nodes[0].previousSibling !== prev) {
|
|
98
|
+
for (const n of nodes) {
|
|
99
|
+
if (!prev) {
|
|
100
|
+
// Couldn't find a way to test this, because even without this move the
|
|
101
|
+
// following `repositionFiberWhenNeeded` will heal this gap. Anyway,
|
|
102
|
+
// it seems right to keep it.
|
|
103
|
+
container.prepend(n);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
container.insertBefore(n, prev.nextSibling);
|
|
107
|
+
}
|
|
108
|
+
prev = n;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return nullthrows(fiber.element);
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=relayout.action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relayout.action.js","sourceRoot":"","sources":["../../../src/core/actions/relayout.action.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAgB,EAChB,EAAE,MAAM,EAAE,KAAK,EAAkB,EACjC;IACA,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACnB,0DAA0D;QAC1D,qBAAqB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACnB,6EAA6E;QAC7E,mEAAmE;QACnE,mDAAmD;QACnD,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAEzC,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAE1B,IAAI,CAAC,CAAC,EAAE,CAAC;gBACP,8DAA8D;gBAC9D,mEAAmE;gBACnE,IAAI,GAAG,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACzD,CAAC;iBAAM,CAAC;gBACN,qEAAqE;gBACrE,iEAAiE;gBACjE,uBAAuB;gBACvB,IAAI,GAAG,yBAAyB,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,sEAAsE;IACtE,qEAAqE;IACrE,sCAAsC;IACtC,KAAK,CAAC,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CACpC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAC7D,CAAC;IAEF,+EAA+E;IAC/E,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAAA,CACzB;AAED;;;GAGG;AACH,MAAM,qBAAqB,GAAG,CAAC,KAAgB,EAAE,KAAe,EAAQ,EAAE,CAAC;IACzE,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,gEAAgE;QAChE,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;SAAM,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACnB,4EAA4E;YAC5E,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb,0GAA0G,CAC3G,CAAC;QACJ,CAAC;IACH,CAAC;AAAA,CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,cAAc,GAAG,CACrB,MAAiB,EACjB,SAAkB,EAClB,IAAiB,EACjB,KAAgB,EACV,EAAE,CAAC;IACT,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,OAAQ,CAAC,UAAU,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,SAAS,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC;QAClC,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YAC5C,IAAI,GAAG,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,iCAAiC;IAExD,OAAO,IAAI,CAAC;AAAA,CACb,CAAC;AAEF;;;GAGG;AACH,MAAM,yBAAyB,GAAG,CAChC,KAAgB,EAChB,SAAkB,EAClB,IAAiB,EACX,EAAE,CAAC;IACT,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,uEAAuE;gBACvE,oEAAoE;gBACpE,6BAA6B;gBAC7B,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YAC9C,CAAC;YACD,IAAI,GAAG,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAAA,CAClC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FiberNode } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* This action can be called directly (<div/> -> []), or indirectly (<div/> ->
|
|
4
|
+
* false) from the replace action. `replaced` is `true` in the 2nd scenario.
|
|
5
|
+
*/
|
|
6
|
+
export declare function removeAction(fiber: FiberNode): void;
|
|
7
|
+
//# sourceMappingURL=remove.action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove.action.d.ts","sourceRoot":"","sources":["../../../src/core/actions/remove.action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EAEV,MAAM,oBAAoB,CAAC;AAK5B;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,QAkC5C"}
|