-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseValidateChildren.ts
More file actions
73 lines (63 loc) · 2.22 KB
/
useValidateChildren.ts
File metadata and controls
73 lines (63 loc) · 2.22 KB
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
import {
Children,
Fragment,
isValidElement,
type PropsWithChildren,
type ReactNode,
useEffect
} from 'react';
import type { DualScrollSyncItem } from '@/components/DualScrollSync/DualScrollSync.types';
import { DualScrollSyncContent } from '@/components/DualScrollSync/DualScrollSyncContent';
import type { DualScrollSyncContentSectionProps } from '@/components/DualScrollSync/DualScrollSyncContentSection';
import { DualScrollSyncNav } from '@/components/DualScrollSync/DualScrollSyncNav';
import type { DualScrollSyncNavItemProps } from '@/components/DualScrollSync/DualScrollSyncNavItem';
interface UseValidateChildrenProps {
items?: DualScrollSyncItem[];
children: ReactNode;
}
export const useValidateChildren = ({ items, children }: UseValidateChildrenProps) => {
useEffect(() => {
if (items) return;
const navKeys = new Set<string>();
const contentKeys = new Set<string>();
const collectNavKeys = (node: ReactNode) => {
if (isValidElement<DualScrollSyncNavItemProps>(node) && node.props.sectionKey) {
navKeys.add(node.props.sectionKey);
}
};
const collectContentKeys = (node: ReactNode) => {
if (isValidElement<DualScrollSyncContentSectionProps>(node) && node.props.sectionKey) {
contentKeys.add(node.props.sectionKey);
}
};
const visit = (node: ReactNode) => {
Children.forEach(node, (child) => {
if (!isValidElement(child)) return;
switch (child.type) {
case Fragment:
visit((child.props as PropsWithChildren).children);
break;
case DualScrollSyncNav:
Children.forEach((child.props as PropsWithChildren).children, collectNavKeys);
break;
case DualScrollSyncContent:
Children.forEach((child.props as PropsWithChildren).children, collectContentKeys);
break;
default:
if ((child.props as PropsWithChildren)?.children) {
visit((child.props as PropsWithChildren).children);
}
}
});
};
visit(children);
for (const key of navKeys) {
if (contentKeys.has(key)) continue;
console.warn(`[DualScrollSync] Missing ContentSection for "${key}"`);
}
for (const key of contentKeys) {
if (navKeys.has(key)) continue;
console.warn(`[DualScrollSync] Missing NavItem for "${key}"`);
}
}, [children, items]);
};