1 | import * as React from "react";
|
2 | import {
|
3 | SealedInitialState,
|
4 | useSealedState,
|
5 | } from "reakit-utils/useSealedState";
|
6 | import {
|
7 | useCompositeState,
|
8 | CompositeState,
|
9 | CompositeActions,
|
10 | CompositeInitialState,
|
11 | } from "../Composite/CompositeState";
|
12 |
|
13 | export type TabState = CompositeState & {
|
14 | |
15 |
|
16 |
|
17 | selectedId?: TabState["currentId"];
|
18 | |
19 |
|
20 |
|
21 | panels: TabState["items"];
|
22 | |
23 |
|
24 |
|
25 | manual: boolean;
|
26 | };
|
27 |
|
28 | export type TabActions = CompositeActions & {
|
29 | |
30 |
|
31 |
|
32 | select: TabActions["move"];
|
33 | |
34 |
|
35 |
|
36 | setSelectedId: TabActions["setCurrentId"];
|
37 | |
38 |
|
39 |
|
40 | registerPanel: TabActions["registerItem"];
|
41 | |
42 |
|
43 |
|
44 | unregisterPanel: TabActions["unregisterItem"];
|
45 | };
|
46 |
|
47 | export type TabInitialState = CompositeInitialState &
|
48 | Partial<Pick<TabState, "selectedId" | "manual">>;
|
49 |
|
50 | export type TabStateReturn = TabState & TabActions;
|
51 |
|
52 | export function useTabState(
|
53 | initialState: SealedInitialState<TabInitialState> = {}
|
54 | ): TabStateReturn {
|
55 | const {
|
56 | selectedId: initialSelectedId,
|
57 | loop = true,
|
58 | manual = false,
|
59 | ...sealed
|
60 | } = useSealedState(initialState);
|
61 |
|
62 | const composite = useCompositeState({
|
63 | loop,
|
64 | currentId: initialSelectedId,
|
65 | ...sealed,
|
66 | });
|
67 | const panels = useCompositeState();
|
68 | const [selectedId, setSelectedId] = React.useState(initialSelectedId);
|
69 |
|
70 | const select = React.useCallback(
|
71 | (id: string) => {
|
72 | composite.move(id);
|
73 | setSelectedId(id);
|
74 | },
|
75 | [composite.move]
|
76 | );
|
77 |
|
78 |
|
79 |
|
80 | React.useEffect(() => {
|
81 | if (selectedId === null) return;
|
82 | const selectedItem = composite.items.find((item) => item.id === selectedId);
|
83 | if (selectedItem) return;
|
84 | if (composite.currentId) {
|
85 | setSelectedId(composite.currentId);
|
86 | }
|
87 | }, [selectedId, composite.items, composite.currentId]);
|
88 |
|
89 | return {
|
90 | ...composite,
|
91 | selectedId,
|
92 | panels: panels.items,
|
93 | manual,
|
94 | select,
|
95 | setSelectedId,
|
96 | registerPanel: React.useCallback((panel) => panels.registerItem(panel), [
|
97 | panels.registerItem,
|
98 | ]),
|
99 | unregisterPanel: React.useCallback((id) => panels.unregisterItem(id), [
|
100 | panels.unregisterItem,
|
101 | ]),
|
102 | };
|
103 | }
|