Files
react/components/utils/collections.ts
witt bb575498fe chore: release v1.8.0 (#367)
* feat(snippet): add custom symbol and toast

* docs(snippet): add docs for custom symbol and toast

* fix(snippet): default toast type as normal type

* test(snippet): add custom symbol and toast

* docs(snippet): add enum type of APIs

* docs(toast): add normal-types

* chore: release v1.8.0-canary.1

* feat(modal): optimize the animation of layer

* test: update snapshots

* chore: release v1.8.0-canary.2

* docs: format import statement

* feat(modal): optimize the max width, height and alignment of layer

* test: update snapshots

* chore: release v1.8.0-canary.3

* Button (#319)

* feat(button): center the icon if the button is empty

* test(button): add testcase for icon only

* docs(button): add example for icon only

* chore: release v1.8.0-canary.4

* fix(snippet): remove space when the symbol is empty (#325)

* fix(snippet): remove space when the symbol is empty

style(snippet): remove unnecessary escape symbols

* fix(snippet): ignore spaces in symbol

style: fix lint warning

* chore: release v1.8.0-canary.5

* feat(tabs): sync the label and set value to required (#334)

* feat(tabs): sync the label and set value to required

* test(tabs): add testcase for label sync

* docs(tabs): update value to required

* feat(modal): use Button to reconstrust Modal.Action (#332)

* feat(modal): use Button to reconstrust Modal.Action

* docs(modal): add example for action loading

* test: update snapshots

* chore: release v1.8.0-canary.6

* fix(input): always synchronize external value and ignore changes (#336)

* fix(input): always synchronize external value and ignore changes

* feat(input): support imperative API to update

* fix(textarea): imperative api same as input (#341)

* feat(dropdown): allow dropdown to set the specified container (#344)

* feat(dropdown): allow dropdown to set the specified container

* test(modal): update snapshots

* docs(select): add example for custom popup container

* fix(dropdown): fix type of getPopupContainer

* test(dropdown): add testcase for specified container rendering

* chore: release v1.8.0-canary.7

* fix(link): fix hard-coded background color (#347)

* style(description): fix title font-weight (#348)

* docs(link): fix duplicate examples (#346)

* style(popover-item): the whole item should be clickable when using with link (#345)

* fix(modal): fix type of Modal.Action (#351)

* chore: release v1.8.0-canary.8

* feat(modal): lock tab action inside modal (#354)

* feat(button): add style to focus buttons

* feat(collections): add util function

* feat(modal): lock tab action inside modal

* test(modal): add tests for modal focus

* test: update style of button

* fix(table): fix column's props are not tracked (#362)

* chore: release v1.8.0-canary.9

* fix(table): children of column should be kept in sync (#364)

* chore: release v1.8.0-canary.10

Co-authored-by: Augusto <augustoconti10@gmail.com>
Co-authored-by: yqrashawn <namy.19@gmail.com>
Co-authored-by: Zhao Lei <firede@firede.us>
2020-08-14 16:59:49 +08:00

127 lines
3.6 KiB
TypeScript

import React, { ReactNode } from 'react'
export const getId = () => {
return Math.random().toString(32).slice(2, 10)
}
export const hasChild = (children: ReactNode | undefined, child: React.ElementType): boolean => {
const types = React.Children.map(children, item => {
if (!React.isValidElement(item)) return null
return item.type
})
return (types || []).includes(child)
}
export const pickChild = (
children: ReactNode | undefined,
targetChild: React.ElementType,
): [ReactNode | undefined, ReactNode | undefined] => {
let target: ReactNode[] = []
const withoutTargetChildren = React.Children.map(children, item => {
if (!React.isValidElement(item)) return item
if (item.type === targetChild) {
target.push(item)
return null
}
return item
})
const targetChildren = target.length >= 0 ? target : undefined
return [withoutTargetChildren, targetChildren]
}
export const pickChildByProps = (
children: ReactNode | undefined,
key: string,
value: any,
): [ReactNode | undefined, ReactNode | undefined] => {
let target: ReactNode[] = []
const isArray = Array.isArray(value)
const withoutPropChildren = React.Children.map(children, item => {
if (!React.isValidElement(item)) return null
if (!item.props) return item
if (isArray) {
if (value.includes(item.props[key])) {
target.push(item)
return null
}
return item
}
if (item.props[key] === value) {
target.push(item)
return null
}
return item
})
const targetChildren = target.length >= 0 ? target : undefined
return [withoutPropChildren, targetChildren]
}
export const pickChildrenFirst = (children: ReactNode | undefined): ReactNode | undefined => {
return React.Children.toArray(children)[0]
}
export const setChildrenProps = (
children: ReactNode | undefined,
props: object = {},
targetComponents: Array<React.ElementType> = [],
): ReactNode | undefined => {
if (React.Children.count(children) === 0) return []
const allowAll = targetComponents.length === 0
const clone = (child: React.ReactElement, props = {}) => React.cloneElement(child, props)
return React.Children.map(children, item => {
if (!React.isValidElement(item)) return item
if (allowAll) return clone(item, props)
const isAllowed = targetComponents.find(child => child === item.type)
if (isAllowed) return clone(item, props)
return item
})
}
export const setChildrenIndex = (
children: ReactNode | undefined,
targetComponents: Array<React.ElementType> = [],
): ReactNode | undefined => {
if (React.Children.count(children) === 0) return []
const allowAll = targetComponents.length === 0
const clone = (child: React.ReactElement, props = {}) => React.cloneElement(child, props)
let index = 0
return React.Children.map(children, item => {
if (!React.isValidElement(item)) return item
index = index + 1
if (allowAll) return clone(item, { index })
const isAllowed = targetComponents.find(child => child === item.type)
if (isAllowed) return clone(item, { index })
index = index - 1
return item
})
}
export const getReactNode = (node?: React.ReactNode | (() => React.ReactNode)): React.ReactNode => {
if (!node) return null
if (typeof node !== 'function') return node
return (node as () => React.ReactNode)()
}
export const isChildElement = (
parent: Element | null | undefined,
child: Element | null | undefined,
): boolean => {
if (!parent || !child) return false
let node: (Node & ParentNode) | null = child
while (node) {
if (node === parent) return true
node = node.parentNode
}
return false
}