1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
import {
Children,
cloneElement,
type FC,
Fragment,
isValidElement,
type ReactElement,
type ReactNode,
} from 'react';
export function getFragmentChildren(children: ReactNode) {
return (children as ReactElement)?.type === Fragment
? (children as ReactElement).props.children
: children;
}
export function isValidChild(child: ReactElement, types: FC | FC[]) {
if (!isValidElement(child)) {
return false;
}
return (Array.isArray(types) ? types : [types]).find(type => type === child.type);
}
export function mapChildren(
children: ReactNode,
handler: (child: ReactElement, index: number) => any,
) {
return Children.map(getFragmentChildren(children) as ReactElement[], (child, index) => {
if (!child?.props) {
return null;
}
return handler(child, index);
});
}
export function cloneChildren(
children: ReactNode,
handler: (child: ReactElement, index: number) => any,
options?: { validChildren?: any[]; onlyRenderValid?: boolean },
): ReactNode {
if (!children) {
return null;
}
const { validChildren, onlyRenderValid = false } = options || {};
return mapChildren(children, (child, index) => {
const invalid = validChildren && !isValidChild(child as ReactElement, validChildren);
if (onlyRenderValid && invalid) {
return null;
}
if (!invalid && isValidElement(child)) {
return cloneElement(child, handler(child, index));
}
return child;
});
}
export function renderChildren(
children: ReactNode | ((item: any, index: number, array: any) => ReactNode),
items: any[],
handler: (child: ReactElement, index: number) => object | undefined,
options?: { validChildren?: any[]; onlyRenderValid?: boolean },
): ReactNode {
if (typeof children === 'function' && items?.length > 0) {
return cloneChildren(items.map(children), handler, options);
}
return cloneChildren(getFragmentChildren(children as ReactNode), handler, options);
}
export function countChildren(children: ReactNode): number {
return Children.count(getFragmentChildren(children));
}
|