Compare commits

..
Author SHA1 Message Date
bendtherules 8c019a5fd2 TODO - COntinue FiberNode selection with css dom selection 2019-09-12 13:55:28 +05:30
bendtherules be7ec5d869 TODO - Query helper also for CLass/Function 2019-09-12 13:53:03 +05:30
bendtherules 6bb43e34e2 TODO - Add CSS, props 2019-09-12 13:51:12 +05:30
bendtherules d630d21b23 TODO - Mark some done 2019-09-12 13:47:49 +05:30
bendtherules 693dd69d32 findNode - Add findNodesByComponentName and findAllNodesByComponentName 2019-09-12 13:46:33 +05:30
bendtherules f01ae4fb2a TODO - Write test for traverseConfig changes 2019-09-11 17:02:53 +05:30
bendtherules 1ef5941a9e findNode* - Support traverseConfig 2019-09-11 16:54:53 +05:30
bendtherules e7e969cf65 traverse - Support traverseConfig 2019-09-11 16:54:32 +05:30
bendtherules 8326ec5bf7 traverseGenerator - Refactor config argument type to separate interface 2019-09-11 16:50:00 +05:30
bendtherules 0bc8c1af99 traverseGenerator - Add option to skip traversing siblings for first node
Which is usually expected, when we think of it as a recursive traversal
2019-09-11 16:18:40 +05:30
bendtherules aced1be6e8 Rewrite traverse.traverse using traverseGenerator 2019-09-11 15:13:21 +05:30
bendtherules 492e69f4dd traverse - Arrange functions in file 2019-09-11 14:58:13 +05:30
bendtherules 94ab7112f7 traverse - Fix prettier formatting 2019-09-11 14:50:28 +05:30
bendtherules 808ed790f3 jsdoc - Add spearator between examples of a function 2019-09-11 14:48:50 +05:30
bendtherules 817242dd25 traverseGenerator - Mark properties in yield object optional 2019-09-11 08:58:17 +05:30
bendtherules 827b282064 ts - Fix vscode version to workspace ts version 2019-09-11 08:57:12 +05:30
bendtherules c71b9ad531 Doc - Add doc for traverseGenerator with example 2019-09-11 08:55:13 +05:30
bendtherules 01e6932cd5 Docs - Update built docs 2019-09-09 18:41:32 +05:30
bendtherules 215153c516 Docs - Add doc for traverse.traverse method 2019-09-09 18:41:13 +05:30
bendtherules fd6dad21ad TODO - rewrite find using generators 2019-09-09 18:30:36 +05:30
bendtherules 30b1bfefea Docs - Update built docs 2019-09-09 18:20:17 +05:30
bendtherules e870a92e4b TODO - Skip sibling 2019-09-09 18:20:02 +05:30
bendtherules 6cffc96d60 Docs - In findNode, move exmaples above note section 2019-09-09 18:19:30 +05:30
bendtherules 4824828b51 Docs - Update built docs 2019-09-09 18:16:42 +05:30
bendtherules 5a2e7f1375 Docs - In findNode, fix example tag code blocks 2019-09-09 18:16:04 +05:30
bendtherules 977a376cad Docs - Update built docs 2019-09-09 17:43:58 +05:30
bendtherules 21231fcb11 Docs - Added for findNode methods 2019-09-09 17:41:58 +05:30
bendtherules b09af700c9 TODO - All optional root node in method params 2019-09-09 16:16:46 +05:30
15 changed files with 348 additions and 140 deletions
-29
View File
@@ -1,35 +1,6 @@
language: node_js language: node_js
matrix:
include:
- name: "react 16.0.x"
env: REACT_V=react@16.0.x REACT_DOM_V=react-dom@16.0.x
- name: "react 16.1.x"
env: REACT_V=react@16.1.x REACT_DOM_V=react-dom@16.1.x
- name: "react 16.2.x"
env: REACT_V=react@16.2.x REACT_DOM_V=react-dom@16.2.x
- name: "react 16.3.x"
env: REACT_V=react@16.3.x REACT_DOM_V=react-dom@16.3.x
- name: "react 16.4.x"
env: REACT_V=react@16.4.x REACT_DOM_V=react-dom@16.4.x
- name: "react 16.5.x"
env: REACT_V=react@16.5.x REACT_DOM_V=react-dom@16.5.x
- name: "react 16.6.x"
env: REACT_V=react@16.6.x REACT_DOM_V=react-dom@16.6.x
- name: "react 16.7.x"
env: REACT_V=react@16.7.x REACT_DOM_V=react-dom@16.7.x
- name: "react 16.8.x"
env: REACT_V=react@16.8.x REACT_DOM_V=react-dom@16.8.x
- name: "react 16.9.x"
env: REACT_V=react@16.9.x REACT_DOM_V=react-dom@16.9.x
notifications: notifications:
email: false email: false
# Install reqd react and react-dom version for each matrix
before_script:
- echo $REACT_V $REACT_DOM_V # log react and react-dom versions
- npm i --no-save $REACT_V $REACT_DOM_V # install them
script: script:
- npm run test - npm run test
- npx codecov - npx codecov
+2 -1
View File
@@ -13,5 +13,6 @@
"javascriptreact", "javascriptreact",
"typescript", "typescript",
"typescriptreact" "typescriptreact"
] ],
"typescript.tsdk": "node_modules\\typescript\\lib"
} }
+8
View File
@@ -6,6 +6,7 @@
4. Build some demo 4. Build some demo
5. Add `findAllNodes` helpers which searches all usages of the components - by name or class 5. Add `findAllNodes` helpers which searches all usages of the components - by name or class
6. Allow using all methods without explicit root node. Find automatically, if not provided.
6. Fix getRootFiberNodeFromDOM and related helpers - 6. Fix getRootFiberNodeFromDOM and related helpers -
- .\_internalRoot is not present is 16.0.0 but present in 16.9.0 - .\_internalRoot is not present is 16.0.0 but present in 16.9.0
@@ -14,3 +15,10 @@
7. Make it work with older React versions 7. Make it work with older React versions
8. Make it work with non React-DOM renderers 8. Make it work with non React-DOM renderers
9. Add test - traverseGenerator - siblings were traversed earlier, not now. Check input config.
10. Find node by CSS (query language) - Make it work for Class/Function reference also
11. Allow easy way to continue FiberNode select with CSS selector for dom node (handling Fragments)
12. Helper and filter by props and state
+30
View File
@@ -80,6 +80,36 @@ For the minified production version, make sure you have already included:
- [`React`](https://unpkg.com/react/umd/react.production.min.js) - [`React`](https://unpkg.com/react/umd/react.production.min.js)
- [`ReactDOM`](https://unpkg.com/react-dom/umd/react-dom.production.min.js) - [`ReactDOM`](https://unpkg.com/react-dom/umd/react-dom.production.min.js)
## Overview
This package contains few utility functions which operate over react-fiber tree.
Overall characteristics are:
1. Only read-only operations
2. Support inversion of control
There are few categories of helpers, each with their variations:
1. Find node(s)
2. Traverse node
3. Others - Check node type, find root node, etc.
Little more info is present in docs section.
## Concerns and improvements
Currently, it assumes that nodes are created by `react 16.3+` with appropriate `react-dom`.
Because fiber nodes are internal to react and are supported by multiple renderers, this is an incorrect assumption to make. It should:
1. support diff versions of react (which have fiber node, but slight variations of it)
2. be renderer-agnostic (say, support react-fs-renderer) but with extra helpers for react-dom.
3. heavily tested with all these variations (to know when internals have changed).
## Docs
Docs are sparse at the moment. I plan on adding them soon.
Till then, the auto-generated (typedoc) docs available in [docs folder](./docs/globals.md) might be of some help.
## License ## License
MIT MIT
@@ -347,7 +347,7 @@ ___
**_reactRootContainer**: *object* **_reactRootContainer**: *object*
*Defined in [mocked-types/index.ts:4](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L4)* *Defined in [mocked-types/index.ts:4](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L4)*
#### Type declaration: #### Type declaration:
@@ -24,7 +24,7 @@
**child**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null* **child**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null*
*Defined in [mocked-types/index.ts:28](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L28)* *Defined in [mocked-types/index.ts:28](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L28)*
___ ___
@@ -32,7 +32,7 @@ ___
**elementType**: *`ComponentClass`* **elementType**: *`ComponentClass`*
*Defined in [mocked-types/index.ts:31](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L31)* *Defined in [mocked-types/index.ts:31](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L31)*
___ ___
@@ -40,7 +40,7 @@ ___
**sibling**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null* **sibling**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null*
*Defined in [mocked-types/index.ts:29](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L29)* *Defined in [mocked-types/index.ts:29](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L29)*
___ ___
@@ -48,7 +48,7 @@ ___
**stateNode**: *`Component`* **stateNode**: *`Component`*
*Defined in [mocked-types/index.ts:34](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L34)* *Defined in [mocked-types/index.ts:34](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L34)*
___ ___
@@ -56,4 +56,4 @@ ___
**type**: *`ComponentClass`* **type**: *`ComponentClass`*
*Defined in [mocked-types/index.ts:32](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L32)* *Defined in [mocked-types/index.ts:32](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L32)*
@@ -24,7 +24,7 @@
**child**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null* **child**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null*
*Defined in [mocked-types/index.ts:18](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L18)* *Defined in [mocked-types/index.ts:18](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L18)*
___ ___
@@ -32,7 +32,7 @@ ___
**elementType**: *`FunctionComponent`* **elementType**: *`FunctionComponent`*
*Defined in [mocked-types/index.ts:21](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L21)* *Defined in [mocked-types/index.ts:21](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L21)*
___ ___
@@ -40,7 +40,7 @@ ___
**sibling**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null* **sibling**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null*
*Defined in [mocked-types/index.ts:19](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L19)* *Defined in [mocked-types/index.ts:19](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L19)*
___ ___
@@ -48,7 +48,7 @@ ___
**stateNode**: *null* **stateNode**: *null*
*Defined in [mocked-types/index.ts:24](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L24)* *Defined in [mocked-types/index.ts:24](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L24)*
___ ___
@@ -56,4 +56,4 @@ ___
**type**: *`FunctionComponent`* **type**: *`FunctionComponent`*
*Defined in [mocked-types/index.ts:22](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L22)* *Defined in [mocked-types/index.ts:22](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L22)*
@@ -24,9 +24,9 @@
**child**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null* **child**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null*
*Defined in [mocked-types/index.ts:38](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L38)* *Defined in [mocked-types/index.ts:38](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L38)*
*Defined in [mocked-types/index.ts:48](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L48)* *Defined in [mocked-types/index.ts:48](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L48)*
___ ___
@@ -34,9 +34,9 @@ ___
**elementType**: *keyof IntrinsicElements* **elementType**: *keyof IntrinsicElements*
*Defined in [mocked-types/index.ts:41](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L41)* *Defined in [mocked-types/index.ts:41](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L41)*
*Defined in [mocked-types/index.ts:51](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L51)* *Defined in [mocked-types/index.ts:51](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L51)*
___ ___
@@ -44,9 +44,9 @@ ___
**sibling**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null* **sibling**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null*
*Defined in [mocked-types/index.ts:39](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L39)* *Defined in [mocked-types/index.ts:39](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L39)*
*Defined in [mocked-types/index.ts:49](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L49)* *Defined in [mocked-types/index.ts:49](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L49)*
___ ___
@@ -54,9 +54,9 @@ ___
**stateNode**: *`HTMLElement`* **stateNode**: *`HTMLElement`*
*Defined in [mocked-types/index.ts:44](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L44)* *Defined in [mocked-types/index.ts:44](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L44)*
*Defined in [mocked-types/index.ts:54](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L54)* *Defined in [mocked-types/index.ts:54](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L54)*
___ ___
@@ -64,6 +64,6 @@ ___
**type**: *keyof IntrinsicElements* **type**: *keyof IntrinsicElements*
*Defined in [mocked-types/index.ts:42](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L42)* *Defined in [mocked-types/index.ts:42](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L42)*
*Defined in [mocked-types/index.ts:52](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L52)* *Defined in [mocked-types/index.ts:52](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L52)*
@@ -24,7 +24,7 @@
**child**: *null* **child**: *null*
*Defined in [mocked-types/index.ts:58](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L58)* *Defined in [mocked-types/index.ts:58](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L58)*
___ ___
@@ -32,7 +32,7 @@ ___
**elementType**: *null* **elementType**: *null*
*Defined in [mocked-types/index.ts:61](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L61)* *Defined in [mocked-types/index.ts:61](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L61)*
___ ___
@@ -40,7 +40,7 @@ ___
**sibling**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null* **sibling**: *[FiberNode](../modules/_mocked_types_index_.md#fibernode) | null*
*Defined in [mocked-types/index.ts:59](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L59)* *Defined in [mocked-types/index.ts:59](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L59)*
___ ___
@@ -48,7 +48,7 @@ ___
**stateNode**: *`Text`* **stateNode**: *`Text`*
*Defined in [mocked-types/index.ts:64](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L64)* *Defined in [mocked-types/index.ts:64](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L64)*
___ ___
@@ -56,4 +56,4 @@ ___
**type**: *null* **type**: *null*
*Defined in [mocked-types/index.ts:62](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L62)* *Defined in [mocked-types/index.ts:62](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L62)*
+48 -3
View File
@@ -18,7 +18,23 @@
**findNodeByComponent**(`node`: [FiberNode](_mocked_types_index_.md#fibernode) | null, `expectedClassOrFunction`: `React.ComponentType`): *[FiberNode](_mocked_types_index_.md#fibernode) | null* **findNodeByComponent**(`node`: [FiberNode](_mocked_types_index_.md#fibernode) | null, `expectedClassOrFunction`: `React.ComponentType`): *[FiberNode](_mocked_types_index_.md#fibernode) | null*
*Defined in [findNode.ts:32](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/findNode.ts#L32)* *Defined in [findNode.ts:67](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/findNode.ts#L67)*
Find node by component (i.e. class or function by reference), till first match.
Matches against class and function by reference.
Returns null if no match is found.
**`example`**
```js
// returns FiberNode for first usage of AccordionMenu
findNodeByComponent(startNode, AccordionMenu);
```
**`note`** Medium chance of collision, medium data access needed.
This is safer than findNodeByComponentName, as different components with the same name won't collide.
But, two instances of the same component will still collide.
Needs access to component class or function.
**Parameters:** **Parameters:**
@@ -35,7 +51,22 @@ ___
**findNodeByComponentName**(`node`: [FiberNode](_mocked_types_index_.md#fibernode) | null, `expectedName`: string): *[FiberNode](_mocked_types_index_.md#fibernode) | null* **findNodeByComponentName**(`node`: [FiberNode](_mocked_types_index_.md#fibernode) | null, `expectedName`: string): *[FiberNode](_mocked_types_index_.md#fibernode) | null*
*Defined in [findNode.ts:4](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/findNode.ts#L4)* *Defined in [findNode.ts:21](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/findNode.ts#L21)*
Find node by component name, till first match.
Matches against class and function name, doesn't match html-like nodes.
Returns null if no match is found.
**`example`**
```js
// returns FiberNode for first usage of 'AccordionMenu'
findNodeByComponentName(startNode, "AccordionMenu");
```
**`note`** Highest chance of collision, least data access needed.
Different components with same name will collide.
Needs access to component name.
**Parameters:** **Parameters:**
@@ -52,7 +83,21 @@ ___
**findNodeByComponentRef**(`node`: [FiberNode](_mocked_types_index_.md#fibernode) | null, `expectedClassInstance`: `Component`): *[FiberNode](_mocked_types_index_.md#fibernode) | null* **findNodeByComponentRef**(`node`: [FiberNode](_mocked_types_index_.md#fibernode) | null, `expectedClassInstance`: `Component`): *[FiberNode](_mocked_types_index_.md#fibernode) | null*
*Defined in [findNode.ts:63](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/findNode.ts#L63)* *Defined in [findNode.ts:114](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/findNode.ts#L114)*
Find node by component instance ref, till first match.
Matches against class instances by reference.
Returns null if no match is found.
**`example`**
```js
// menuRef=createRef(); <AccordionMenu ref={menuRef}>
findNodeByComponentRef(startNode, menuRef.current);
```
**`note`** Least chance of collision, maximum data access needed.
Needs access to component instance (through React ref usually).
**Parameters:** **Parameters:**
+2 -2
View File
@@ -25,7 +25,7 @@
Ƭ **FiberNode**: *[FiberNodeForComponentClass](../interfaces/_mocked_types_index_.fibernodeforcomponentclass.md) | [FiberNodeForFunctionComponent](../interfaces/_mocked_types_index_.fibernodeforfunctioncomponent.md) | [FiberNodeForInstrinsicElement](../interfaces/_mocked_types_index_.fibernodeforinstrinsicelement.md) | [FiberNodeForTextNode](../interfaces/_mocked_types_index_.fibernodefortextnode.md)* Ƭ **FiberNode**: *[FiberNodeForComponentClass](../interfaces/_mocked_types_index_.fibernodeforcomponentclass.md) | [FiberNodeForFunctionComponent](../interfaces/_mocked_types_index_.fibernodeforfunctioncomponent.md) | [FiberNodeForInstrinsicElement](../interfaces/_mocked_types_index_.fibernodeforinstrinsicelement.md) | [FiberNodeForTextNode](../interfaces/_mocked_types_index_.fibernodefortextnode.md)*
*Defined in [mocked-types/index.ts:11](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L11)* *Defined in [mocked-types/index.ts:11](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L11)*
___ ___
@@ -33,4 +33,4 @@ ___
Ƭ **FiberNodeisHTMLLike**: *[FiberNodeForInstrinsicElement](../interfaces/_mocked_types_index_.fibernodeforinstrinsicelement.md) | [FiberNodeForTextNode](../interfaces/_mocked_types_index_.fibernodefortextnode.md)* Ƭ **FiberNodeisHTMLLike**: *[FiberNodeForInstrinsicElement](../interfaces/_mocked_types_index_.fibernodeforinstrinsicelement.md) | [FiberNodeForTextNode](../interfaces/_mocked_types_index_.fibernodefortextnode.md)*
*Defined in [mocked-types/index.ts:67](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/mocked-types/index.ts#L67)* *Defined in [mocked-types/index.ts:67](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/mocked-types/index.ts#L67)*
+14 -2
View File
@@ -17,7 +17,19 @@
**traverse**(`node`: [FiberNode](_mocked_types_index_.md#fibernode), `fn`: function): *void* **traverse**(`node`: [FiberNode](_mocked_types_index_.md#fibernode), `fn`: function): *void*
*Defined in [traverse.ts:4](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/traverse.ts#L4)* *Defined in [traverse.ts:19](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/traverse.ts#L19)*
Traverse nodes recursively in depth-first manner, starting from a start node.
This is the default and basic traversal method, which covers basic use cases.
You can't do advanced things like change the order of traversal, skip or cancel traversal after any node, etc.
For more advanced usecases, see [traverseGenerator](_traverse_.md#traversegenerator)
**`example`**
```js
// calls fn for each node inside startNode
traverse(startNode, fn);
```
**Parameters:** **Parameters:**
@@ -41,7 +53,7 @@ ___
**traverseGenerator**(`node`: [FiberNode](_mocked_types_index_.md#fibernode), `__namedParameters`: object): *`IterableIterator<FiberNode>`* **traverseGenerator**(`node`: [FiberNode](_mocked_types_index_.md#fibernode), `__namedParameters`: object): *`IterableIterator<FiberNode>`*
*Defined in [traverse.ts:15](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/traverse.ts#L15)* *Defined in [traverse.ts:30](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/traverse.ts#L30)*
**Parameters:** **Parameters:**
+9 -9
View File
@@ -24,7 +24,7 @@
**doesElementContainRootFiberNode**(`element`: `Element`): *boolean* **doesElementContainRootFiberNode**(`element`: `Element`): *boolean*
*Defined in [utils.ts:65](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L65)* *Defined in [utils.ts:65](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L65)*
**Parameters:** **Parameters:**
@@ -40,7 +40,7 @@ ___
**getRootFiberNodeFromDOM**(`startElement?`: [Element](../interfaces/_mocked_types_index_.fibernodedomcontainer.md#element)): *[FiberNode](_mocked_types_index_.md#fibernode) | null* **getRootFiberNodeFromDOM**(`startElement?`: [Element](../interfaces/_mocked_types_index_.fibernodedomcontainer.md#element)): *[FiberNode](_mocked_types_index_.md#fibernode) | null*
*Defined in [utils.ts:82](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L82)* *Defined in [utils.ts:82](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L82)*
Util to find root React Fiber node from html DOM tree. Util to find root React Fiber node from html DOM tree.
Returns null, if not found.SHould be called after ReactDOM.render is finished. Returns null, if not found.SHould be called after ReactDOM.render is finished.
@@ -59,7 +59,7 @@ ___
**isConstructorComponentClass**(`ctr`: `React.ElementType` | null): *boolean* **isConstructorComponentClass**(`ctr`: `React.ElementType` | null): *boolean*
*Defined in [utils.ts:42](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L42)* *Defined in [utils.ts:42](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L42)*
**Parameters:** **Parameters:**
@@ -75,7 +75,7 @@ ___
**isConstructorFunctionComponent**(`ctr`: `React.ElementType` | null): *boolean* **isConstructorFunctionComponent**(`ctr`: `React.ElementType` | null): *boolean*
*Defined in [utils.ts:59](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L59)* *Defined in [utils.ts:59](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L59)*
**Parameters:** **Parameters:**
@@ -91,7 +91,7 @@ ___
**isConstructorHtmlLike**(`ctr`: `React.ElementType` | null): *boolean* **isConstructorHtmlLike**(`ctr`: `React.ElementType` | null): *boolean*
*Defined in [utils.ts:33](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L33)* *Defined in [utils.ts:33](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L33)*
**Parameters:** **Parameters:**
@@ -107,7 +107,7 @@ ___
**isNodeComponentClass**(`node`: [FiberNode](_mocked_types_index_.md#fibernode)): *boolean* **isNodeComponentClass**(`node`: [FiberNode](_mocked_types_index_.md#fibernode)): *boolean*
*Defined in [utils.ts:27](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L27)* *Defined in [utils.ts:27](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L27)*
**Parameters:** **Parameters:**
@@ -123,7 +123,7 @@ ___
**isNodeFunctionComponent**(`node`: [FiberNode](_mocked_types_index_.md#fibernode)): *boolean* **isNodeFunctionComponent**(`node`: [FiberNode](_mocked_types_index_.md#fibernode)): *boolean*
*Defined in [utils.ts:21](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L21)* *Defined in [utils.ts:21](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L21)*
**Parameters:** **Parameters:**
@@ -139,7 +139,7 @@ ___
**isNodeHtmlLike**(`node`: [FiberNode](_mocked_types_index_.md#fibernode)): *boolean* **isNodeHtmlLike**(`node`: [FiberNode](_mocked_types_index_.md#fibernode)): *boolean*
*Defined in [utils.ts:11](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L11)* *Defined in [utils.ts:11](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L11)*
**Parameters:** **Parameters:**
@@ -155,7 +155,7 @@ ___
**isNodeNotHtmlLike**(`node`: [FiberNode](_mocked_types_index_.md#fibernode)): *boolean* **isNodeNotHtmlLike**(`node`: [FiberNode](_mocked_types_index_.md#fibernode)): *boolean*
*Defined in [utils.ts:15](https://github.com/bendtherules/react-fiber-traverse/blob/18ea2e7/src/utils.ts#L15)* *Defined in [utils.ts:15](https://github.com/bendtherules/react-fiber-traverse/blob/fd6dad2/src/utils.ts#L15)*
**Parameters:** **Parameters:**
+108 -52
View File
@@ -1,94 +1,150 @@
import { FiberNode } from "./mocked-types"; import { FiberNode } from "./mocked-types";
import { traverseGenerator, TTraverseConfig } from "./traverse";
import { isNodeNotHtmlLike } from "./utils"; import { isNodeNotHtmlLike } from "./utils";
/**
* Find node by component name, till first match.
*
* Matches against class and function name, doesn't match html-like nodes.
* Returns null if no match is found.
*
* @example
* ```js
* // returns FiberNode for first usage of 'AccordionMenu'
* findNodeByComponentName(startNode, "AccordionMenu");
* ```
*
* @note Highest chance of collision, least data access needed.
* Different components with same name will collide.
* Needs access to component name.
*
*/
function findNodeByComponentName( function findNodeByComponentName(
node: FiberNode | null, node: FiberNode | null,
expectedName: string expectedName: string,
traverseConfig?: TTraverseConfig
): FiberNode | null { ): FiberNode | null {
if (node === null) { if (node === null) {
return null; return null;
} }
if (isNodeNotHtmlLike(node) && node.type.name === expectedName) { const nodeIterator = traverseGenerator(node, traverseConfig);
return node; for (const tmpNode of nodeIterator) {
} if (isNodeNotHtmlLike(tmpNode) && tmpNode.type.name === expectedName) {
return tmpNode;
{
const returnVal = findNodeByComponentName(node.child, expectedName);
if (returnVal !== null) {
return returnVal;
}
}
{
const returnVal = findNodeByComponentName(node.sibling, expectedName);
if (returnVal !== null) {
return returnVal;
} }
} }
return null; return null;
} }
function* findNodesByComponentName(
node: FiberNode | null,
expectedName: string,
traverseConfig?: TTraverseConfig
): IterableIterator<FiberNode> {
if (node === null) {
return null;
}
const nodeIterator = traverseGenerator(node, traverseConfig);
for (const tmpNode of nodeIterator) {
if (isNodeNotHtmlLike(tmpNode) && tmpNode.type.name === expectedName) {
yield tmpNode;
}
}
}
function findAllNodesByComponentName(
node: FiberNode | null,
expectedName: string,
traverseConfig?: TTraverseConfig
): Array<FiberNode> {
return [...findNodesByComponentName(node, expectedName, traverseConfig)];
}
/**
* Find node by component (i.e. class or function by reference), till first match.
*
* Matches against class and function by reference.
* Returns null if no match is found.
*
* @example
* ```js
* // returns FiberNode for first usage of AccordionMenu
* findNodeByComponent(startNode, AccordionMenu);
* ```
*
* @note Medium chance of collision, medium data access needed.
* This is safer than findNodeByComponentName, as different components with the same name won't collide.
* But, two instances of the same component will still collide.
* Needs access to component class or function.
*
*/
function findNodeByComponent( function findNodeByComponent(
node: FiberNode | null, node: FiberNode | null,
expectedClassOrFunction: React.ComponentType expectedClassOrFunction: React.ComponentType,
traverseConfig?: TTraverseConfig
): FiberNode | null { ): FiberNode | null {
if (node === null) { if (node === null) {
return null; return null;
} }
if (isNodeNotHtmlLike(node) && node.type === expectedClassOrFunction) { const nodeIterator = traverseGenerator(node, traverseConfig);
return node; for (const tmpNode of nodeIterator) {
} if (
isNodeNotHtmlLike(tmpNode) &&
{ tmpNode.type === expectedClassOrFunction
const returnVal = findNodeByComponent(node.child, expectedClassOrFunction); ) {
if (returnVal !== null) { return tmpNode;
return returnVal;
}
}
{
const returnVal = findNodeByComponent(
node.sibling,
expectedClassOrFunction
);
if (returnVal !== null) {
return returnVal;
} }
} }
return null; return null;
} }
/**
* Find node by component instance ref, till first match.
*
* Matches against class instances by reference.
* Returns null if no match is found.
*
* @example
* ```js
* // menuRef=createRef(); <AccordionMenu ref={menuRef}>
* findNodeByComponentRef(startNode, menuRef.current);
* ```
*
* @note Least chance of collision, maximum data access needed.
* Needs access to component instance (through React ref usually).
*
*/
function findNodeByComponentRef( function findNodeByComponentRef(
node: FiberNode | null, node: FiberNode | null,
expectedClassInstance: React.Component expectedClassInstance: React.Component,
traverseConfig?: TTraverseConfig
): FiberNode | null { ): FiberNode | null {
if (node === null) { if (node === null) {
return null; return null;
} }
if (isNodeNotHtmlLike(node) && node.stateNode === expectedClassInstance) { const nodeIterator = traverseGenerator(node, traverseConfig);
return node; for (const tmpNode of nodeIterator) {
} if (
isNodeNotHtmlLike(tmpNode) &&
{ tmpNode.stateNode === expectedClassInstance
const returnVal = findNodeByComponentRef(node.child, expectedClassInstance); ) {
if (returnVal !== null) { return tmpNode;
return returnVal;
}
}
{
const returnVal = findNodeByComponentRef(
node.sibling,
expectedClassInstance
);
if (returnVal !== null) {
return returnVal;
} }
} }
return null; return null;
} }
export { findNodeByComponentName, findNodeByComponent, findNodeByComponentRef }; export {
findNodeByComponentName,
findNodesByComponentName,
findAllNodesByComponentName,
findNodeByComponent,
findNodeByComponentRef
};
+101 -16
View File
@@ -1,29 +1,83 @@
// import { isNodeSimple } from './utils'; // import { isNodeSimple } from './utils';
import { FiberNode } from "./mocked-types"; import { FiberNode } from "./mocked-types";
function traverse(node: FiberNode, fn: (node: FiberNode) => any) { interface TTraverseConfig {
fn.call(null, node); order?: Array<"self" | "child" | "sibling">;
skipSiblingForStartNode?: boolean;
if (node.child !== null) {
traverse(node.child, fn);
}
if (node.sibling !== null) {
traverse(node.sibling, fn);
}
} }
/**
* Traverse nodes recursively using generators.
*
* This is the advanced traverse function, which can be used used
* to write other variants of traversal and find.
*
* Type signature for generator.next first argument is `{ skipChild?: boolean; skipSibling?: boolean } | void `
* Throw any error into the generator to finish the generator and let it cleanup its internals.
*
* It allows inversion of control -
* so, application code can decide to
* 1. change order of traversal,
* 2. skip some elements,
* 3. cancel traversal mid-way.
*
* @example
* ```js
* // Basic use (for-of)
*
* const nodeIterator = traverseGenerator(rootNode);
* for (const node of nodeIterator) {
* // do something with each node here
* }
* ```
* ------
*
* @example
* ```js
* // Breadth-first
*
* // note the order below
* const nodeIterator = traverseGenerator(rootNode, ["self", "sibling", "child"]);
* // rest - same as above
* ```
* -----
*
* @example
* ```js
* // Get first 3 nodes and then stop the generator
*
* const nodeIterator = traverseGenerator(rootNode);
*
* var count = 0;
* var next;
* while (
* count < 3 &&
* !(next = nodeIterator.next()).done
* ) {
* count++;
* const node = next.value;
* // do something with each node here
* }
*
* // Finish generator, to prevent memory leak
* nodeIterator.throw(new Error());
* ```
* -----
*
*/
function* traverseGenerator( function* traverseGenerator(
node: FiberNode, node: FiberNode,
{ {
order = ["self", "child", "sibling"] order = ["self", "child", "sibling"],
}: { order?: Array<"self" | "child" | "sibling"> } = {} skipSiblingForStartNode = true
}: TTraverseConfig = {}
): IterableIterator<FiberNode> { ): IterableIterator<FiberNode> {
let skipChild = false, let skipChild = false,
skipSibling = false; skipSibling = skipSiblingForStartNode;
function* traverseSelf() { function* traverseSelf() {
const controlInput: const controlInput:
| { skipChild: boolean; skipSibling: boolean } | { skipChild?: boolean; skipSibling?: boolean }
| undefined = yield node; | undefined = yield node;
if (controlInput !== undefined) { if (controlInput !== undefined) {
@@ -34,14 +88,20 @@ function* traverseGenerator(
function* traverseChild() { function* traverseChild() {
if (!skipChild && node.child !== null) { if (!skipChild && node.child !== null) {
const nextNode = node.child; const nextNode = node.child;
yield* traverseGenerator(nextNode, { order }); yield* traverseGenerator(nextNode, {
order,
skipSiblingForStartNode: false
});
} }
} }
function* traverseSibling() { function* traverseSibling() {
if (!skipSibling && node.sibling !== null) { if (!skipSibling && node.sibling !== null) {
const nextNode = node.sibling; const nextNode = node.sibling;
yield* traverseGenerator(nextNode, { order }); yield* traverseGenerator(nextNode, {
order,
skipSiblingForStartNode: false
});
} }
} }
@@ -62,4 +122,29 @@ function* traverseGenerator(
} }
} }
export { traverse, traverseGenerator }; /**
* Traverse nodes recursively in depth-first manner, starting from a start node.
*
* This is the default and basic traversal function, which covers basic use cases.
* You can't do advanced things like change the order of traversal, skip or cancel traversal after any node, etc.
* For more advanced usecases, see {@link traverseGenerator}
*
* @example
* ```js
* // calls fn for each node inside startNode
* traverse(startNode, fn);
* ```
*
*/
function traverse(
node: FiberNode,
fn: (node: FiberNode) => any,
traverseConfig?: TTraverseConfig
) {
const nodeIterator = traverseGenerator(node, traverseConfig);
for (const tmpNode of nodeIterator) {
fn.call(null, tmpNode);
}
}
export { traverse, traverseGenerator, TTraverseConfig };