Skip to content

Commit

Permalink
feat(internal-utils): add deepFind internal util
Browse files Browse the repository at this point in the history
Add deepFind internal util
  • Loading branch information
acd02 committed Mar 14, 2024
1 parent b94a686 commit 597d534
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/utils/internal-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { tw } from './tw'
export { makeVariants } from './variants'
export * as VariantTypes from './variants/types'
export * as variantConstants from './variants/constants'
export { deepFind } from './react-children-utilities/deepFind'
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { ReactNode } from 'react'
import { Children, isValidElement } from 'react'

import { hasComplexChildren } from './hasComplexChildren'

// from https://github.com/fernandopasik/react-children-utilities
function deepFind(
children: ReactNode | ReactNode[],
deepFindFn: (child: ReactNode, index?: number, children?: ReactNode[]) => boolean
): ReactNode | undefined {
// eslint-disable-next-line @typescript-eslint/init-declarations
let found

Children.toArray(children).find((child: ReactNode, index: number, findChildren: ReactNode[]) => {
if (deepFindFn(child, index, findChildren)) {
found = child

return true
}

if (isValidElement(child) && hasComplexChildren(child)) {
// Find inside the child that has children
found = deepFind(child.props.children, deepFindFn)

return typeof found !== 'undefined'
}

return false
})

return found
}

export { deepFind }
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { ReactElement, ReactNode } from 'react'
import { isValidElement } from 'react'

function hasChildren(
element: ReactNode
): element is ReactElement<{ children: ReactNode | ReactNode[] }> {
return isValidElement<{ children?: ReactNode[] }>(element) && Boolean(element.props.children)
}

export { hasChildren }
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { ReactElement, ReactNode } from 'react'
import { Children, isValidElement } from 'react'

import { hasChildren } from './hasChildren'

function hasComplexChildren(
element: ReactNode
): element is ReactElement<{ children: ReactNode | ReactNode[] }> {
return (
isValidElement(element) &&
hasChildren(element) &&
Children.toArray(element.props.children).reduce(
(response: boolean, child: ReactNode): boolean => response || isValidElement(child),
false
)
)
}

export { hasComplexChildren }

0 comments on commit 597d534

Please sign in to comment.