feat(lib/utils): add react and trees
This commit is contained in:
parent
ca94e6122b
commit
75154b77e8
3 changed files with 77 additions and 2 deletions
|
|
@ -18,11 +18,17 @@
|
|||
"./logger": {
|
||||
"default": "./src/logger.ts"
|
||||
},
|
||||
"./objects": {
|
||||
"default": "./src/objects.ts"
|
||||
},
|
||||
"./proxy": {
|
||||
"default": "./src/proxy.ts"
|
||||
},
|
||||
"./objects": {
|
||||
"default": "./src/objects.ts"
|
||||
"./react": {
|
||||
"default": "./src/react.ts"
|
||||
},
|
||||
"./trees": {
|
||||
"default": "./src/trees.ts"
|
||||
},
|
||||
"./types": {
|
||||
"types": "./src/types.ts"
|
||||
|
|
|
|||
23
lib/utils/src/react.ts
Normal file
23
lib/utils/src/react.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { React } from '@revenge-mod/react'
|
||||
|
||||
import { type SearchFilter, findInTree } from './trees'
|
||||
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
export function useIsFirstRender() {
|
||||
let firstRender = false
|
||||
|
||||
React.useEffect(() => {
|
||||
firstRender = true
|
||||
}, [])
|
||||
|
||||
return firstRender
|
||||
}
|
||||
|
||||
const ReactFiberWalkable = new Set(['props', 'children', 'child', 'sibling'])
|
||||
|
||||
export function findInReactFiber(tree: Extract<ReactNode, { props: unknown }>, filter: SearchFilter): any {
|
||||
return findInTree(tree, filter, {
|
||||
walkable: ReactFiberWalkable,
|
||||
})
|
||||
}
|
||||
46
lib/utils/src/trees.ts
Normal file
46
lib/utils/src/trees.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
export type SearchTree = Record<string, any>
|
||||
export type SearchFilter = (tree: SearchTree) => boolean
|
||||
|
||||
export interface FindInTreeOptions {
|
||||
/**
|
||||
* A set of keys to search for in the tree.
|
||||
*/
|
||||
walkable?: Set<string>
|
||||
/**
|
||||
* A set of keys to ignore when searching the tree.
|
||||
*/
|
||||
ignore?: Set<string>
|
||||
/**
|
||||
* The maximum depth to search in the tree.
|
||||
*
|
||||
* @default 100
|
||||
*/
|
||||
maxDepth?: number
|
||||
}
|
||||
|
||||
export function findInTree(tree: SearchTree, filter: SearchFilter, opts?: FindInTreeOptions): any | undefined {
|
||||
type StackItem = [node: any, depth: number]
|
||||
const stack: StackItem[] = [[tree, 0]]
|
||||
const maxDepth = opts?.maxDepth ?? 100
|
||||
|
||||
while (stack.length > 0) {
|
||||
const [node, depth] = stack.pop()!
|
||||
if (depth > maxDepth || !node) continue
|
||||
|
||||
if (filter(node)) return node
|
||||
|
||||
const isArray = Array.isArray(node)
|
||||
const keys = isArray ? node : Object.keys(node)
|
||||
|
||||
for (const key of keys) {
|
||||
const item = isArray ? key : node[key]
|
||||
|
||||
if (typeof item !== 'object' || item == null) continue
|
||||
|
||||
if (!isArray && opts?.walkable?.size && !opts.walkable?.has(key)) continue
|
||||
if (!isArray && opts?.ignore?.has(key)) continue
|
||||
|
||||
stack.push([item, depth + 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue