-
Notifications
You must be signed in to change notification settings - Fork 4k
/
hook.js
113 lines (91 loc) · 2.63 KB
/
hook.js
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
103
104
105
106
107
108
109
110
111
112
113
/**
* WordPress dependencies
*/
import { useEffect, useMemo, useRef, useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import * as styles from '../styles';
import { useContextSystem } from '../../ui/context';
import { useCx } from '../../utils/hooks/use-cx';
export function useToolsPanel( props ) {
const { className, resetAll, ...otherProps } = useContextSystem(
props,
'ToolsPanel'
);
const cx = useCx();
const classes = useMemo( () => {
return cx( styles.ToolsPanel, className );
}, [ className ] );
const isResetting = useRef( false );
useEffect( () => {
if ( isResetting.current ) {
isResetting.current = false;
}
} );
// Allow panel items to register themselves.
const [ panelItems, setPanelItems ] = useState( [] );
const registerPanelItem = ( item ) => {
setPanelItems( ( items ) => [ ...items, item ] );
};
// Panels need to deregister on unmount to avoid orphans in menu state.
// This is an issue when panel items are being injected via SlotFills.
const deregisterPanelItem = ( label ) => {
setPanelItems( ( items ) =>
items.filter( ( item ) => item.label !== label )
);
};
// Manage and share display state of menu items representing child controls.
const [ menuItems, setMenuItems ] = useState( {} );
const getResetAllFilters = () => {
const filters = [];
panelItems.forEach( ( item ) => {
if ( item.resetAllFilter ) {
filters.push( item.resetAllFilter );
}
} );
return filters;
};
// Setup menuItems state as panel items register themselves.
useEffect( () => {
const items = {};
panelItems.forEach( ( { hasValue, isShownByDefault, label } ) => {
items[ label ] = isShownByDefault || hasValue();
} );
setMenuItems( items );
}, [ panelItems ] );
// Toggle the checked state of a menu item which is then used to determine
// display of the item within the panel.
const toggleItem = ( label ) => {
setMenuItems( {
...menuItems,
[ label ]: ! menuItems[ label ],
} );
};
// Resets display of children and executes resetAll callback if available.
const resetAllItems = () => {
if ( typeof resetAll === 'function' ) {
isResetting.current = true;
resetAll( getResetAllFilters() );
}
// Turn off display of all non-default items.
const resetMenuItems = {};
panelItems.forEach( ( { label, isShownByDefault } ) => {
resetMenuItems[ label ] = !! isShownByDefault;
} );
setMenuItems( resetMenuItems );
};
const panelContext = {
menuItems,
registerPanelItem,
deregisterPanelItem,
isResetting: isResetting.current,
};
return {
...otherProps,
panelContext,
resetAllItems,
toggleItem,
className: classes,
};
}