/
MenuContext.tsx
102 lines (84 loc) · 2.28 KB
/
MenuContext.tsx
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import * as React from 'react';
import type { CSSMotionProps } from 'rc-motion';
import useMemo from 'rc-util/lib/hooks/useMemo';
import isEqual from 'rc-util/lib/isEqual';
import type {
BuiltinPlacements,
MenuClickEventHandler,
MenuKey,
MenuMode,
RenderIconType,
TriggerSubMenuAction,
} from '../interface';
export interface MenuContextProps {
prefixCls: string;
rootClassName?: string;
openKeys: MenuKey[];
rtl?: boolean;
// Mode
mode: MenuMode;
// Disabled
disabled?: boolean;
// Used for overflow only. Prevent hidden node trigger open
overflowDisabled?: boolean;
// Active
activeKey: MenuKey;
onActive: (key: MenuKey) => void;
onInactive: (key: MenuKey) => void;
// Selection
selectedKeys: MenuKey[];
// Level
inlineIndent: number;
// Motion
motion?: CSSMotionProps;
defaultMotions?: Partial<{ [key in MenuMode | 'other']: CSSMotionProps }>;
// Popup
subMenuOpenDelay: number;
subMenuCloseDelay: number;
forceSubMenuRender?: boolean;
builtinPlacements?: BuiltinPlacements;
triggerSubMenuAction?: TriggerSubMenuAction;
// Icon
itemIcon?: RenderIconType;
expandIcon?: RenderIconType;
// Function
onItemClick: MenuClickEventHandler;
onOpenChange: (key: MenuKey, open: boolean) => void;
getPopupContainer: (node: HTMLElement) => HTMLElement;
}
export const MenuContext = React.createContext<MenuContextProps>(null);
function mergeProps(
origin: MenuContextProps,
target: Partial<MenuContextProps>,
): MenuContextProps {
const clone = { ...origin };
Object.keys(target).forEach(key => {
const value = target[key];
if (value !== undefined) {
clone[key] = value;
}
});
return clone;
}
export interface InheritableContextProps extends Partial<MenuContextProps> {
children?: React.ReactNode;
locked?: boolean;
}
export default function InheritableContextProvider({
children,
locked,
...restProps
}: InheritableContextProps) {
const context = React.useContext(MenuContext);
const inheritableContext = useMemo(
() => mergeProps(context, restProps),
[context, restProps],
(prev, next) =>
!locked && (prev[0] !== next[0] || !isEqual(prev[1], next[1], true)),
);
return (
<MenuContext.Provider value={inheritableContext}>
{children}
</MenuContext.Provider>
);
}