Newer
Older
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
import React, {
createContext,
useMemo,
useEffect,
useContext,
useReducer,
} from 'react';
import { useSelector, useDispatch } from 'react-redux';
const SplitsExpandedContext = createContext(null);
export function useSplitsExpanded() {
const data = useContext(SplitsExpandedContext);
return useMemo(
() => ({
...data,
expanded: id =>
data.state.mode === 'collapse'
? !data.state.ids.has(id)
: data.state.ids.has(id),
}),
[data],
);
}
export function SplitsExpandedProvider({ children, initialMode = 'expand' }) {
const cachedState = useSelector(state => state.app.lastSplitState);
const reduxDispatch = useDispatch();
const [state, dispatch] = useReducer(
(state, action) => {
switch (action.type) {
case 'toggle-split': {
const ids = new Set([...state.ids]);
const { id } = action;
if (ids.has(id)) {
ids.delete(id);
} else {
ids.add(id);
}
return { ...state, ids };
}
case 'open-split': {
const ids = new Set([...state.ids]);
const { id } = action;
if (state.mode === 'collapse') {
ids.delete(id);
} else {
ids.add(id);
}
return { ...state, ids };
}
case 'set-mode': {
return {
...state,
mode: action.mode,
ids: new Set(),
transitionId: null,
};
}
case 'switch-mode':
if (state.transitionId != null) {
// You can only transition once at a time
return state;
}
return {
...state,
mode: state.mode === 'expand' ? 'collapse' : 'expand',
transitionId: action.id,
ids: new Set(),
};
case 'finish-switch-mode':
return { ...state, transitionId: null };
default:
throw new Error('Unknown action type: ' + action.type);
}
},
cachedState.current || { ids: new Set(), mode: initialMode },
);
useEffect(() => {
if (state.transitionId != null) {
// This timeout allows animations to finish
setTimeout(() => {
dispatch({ type: 'finish-switch-mode' });
}, 250);
}
}, [state.transitionId]);
useEffect(() => {
// In a finished state, cache the state
if (state.transitionId == null) {
reduxDispatch({ type: 'SET_LAST_SPLIT_STATE', splitState: state });
}
}, [reduxDispatch, state]);
const value = useMemo(() => ({ state, dispatch }), [state, dispatch]);
return (
<SplitsExpandedContext.Provider value={value}>
{children}
</SplitsExpandedContext.Provider>
);
}