@gtkx/navigation 2.0.0-beta.11 → 2.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/drawer/create-drawer-navigator.d.ts +3 -1
- package/dist/drawer/create-drawer-navigator.d.ts.map +1 -1
- package/dist/drawer/create-drawer-navigator.js +10 -10
- package/dist/drawer/create-drawer-navigator.js.map +1 -1
- package/dist/drawer/drawer-item-list.d.ts.map +1 -1
- package/dist/drawer/drawer-item-list.js +3 -2
- package/dist/drawer/drawer-item-list.js.map +1 -1
- package/dist/drawer/drawer-router.d.ts.map +1 -1
- package/dist/drawer/drawer-router.js.map +1 -1
- package/dist/drawer/drawer-status.d.ts.map +1 -1
- package/dist/drawer/drawer-view.d.ts.map +1 -1
- package/dist/drawer/drawer-view.js +6 -6
- package/dist/drawer/drawer-view.js.map +1 -1
- package/dist/drawer/types.d.ts +2 -0
- package/dist/drawer/types.d.ts.map +1 -1
- package/dist/drawer/types.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/shared/header-bar.d.ts.map +1 -1
- package/dist/shared/header-bar.js +2 -2
- package/dist/shared/header-bar.js.map +1 -1
- package/dist/shared/routes.d.ts.map +1 -1
- package/dist/shared/scene-page.d.ts +3 -1
- package/dist/shared/scene-page.d.ts.map +1 -1
- package/dist/shared/scene-page.js +4 -7
- package/dist/shared/scene-page.js.map +1 -1
- package/dist/shared/use-has-loaded.d.ts +3 -0
- package/dist/shared/use-has-loaded.d.ts.map +1 -0
- package/dist/shared/use-has-loaded.js +10 -0
- package/dist/shared/use-has-loaded.js.map +1 -0
- package/dist/shared/use-pop-to-top-on-blur.d.ts.map +1 -1
- package/dist/split-view/create-split-view-navigator.d.ts +7 -2
- package/dist/split-view/create-split-view-navigator.d.ts.map +1 -1
- package/dist/split-view/create-split-view-navigator.js +2 -6
- package/dist/split-view/create-split-view-navigator.js.map +1 -1
- package/dist/split-view/split-view-collapsed.d.ts +11 -0
- package/dist/split-view/split-view-collapsed.d.ts.map +1 -0
- package/dist/split-view/split-view-collapsed.js +17 -0
- package/dist/split-view/split-view-collapsed.js.map +1 -0
- package/dist/split-view/split-view.d.ts.map +1 -1
- package/dist/split-view/split-view.js +41 -20
- package/dist/split-view/split-view.js.map +1 -1
- package/dist/split-view/types.d.ts +9 -2
- package/dist/split-view/types.d.ts.map +1 -1
- package/dist/split-view/types.js.map +1 -1
- package/dist/stack/create-stack-navigator.d.ts +3 -1
- package/dist/stack/create-stack-navigator.d.ts.map +1 -1
- package/dist/stack/create-stack-navigator.js +0 -1
- package/dist/stack/create-stack-navigator.js.map +1 -1
- package/dist/stack/stack-pages.d.ts.map +1 -1
- package/dist/stack/stack-pages.js +3 -5
- package/dist/stack/stack-pages.js.map +1 -1
- package/dist/stack/stack-view.d.ts.map +1 -1
- package/dist/stack/stack-view.js +6 -14
- package/dist/stack/stack-view.js.map +1 -1
- package/dist/stack/sync-navigation-stack.d.ts.map +1 -1
- package/dist/stack/types.d.ts.map +1 -1
- package/dist/stack/types.js.map +1 -1
- package/dist/tab-view/create-tab-view-navigator.d.ts +32 -0
- package/dist/tab-view/create-tab-view-navigator.d.ts.map +1 -0
- package/dist/tab-view/create-tab-view-navigator.js +21 -0
- package/dist/tab-view/create-tab-view-navigator.js.map +1 -0
- package/dist/tab-view/page-registry.d.ts +34 -0
- package/dist/tab-view/page-registry.d.ts.map +1 -0
- package/dist/tab-view/page-registry.js +70 -0
- package/dist/tab-view/page-registry.js.map +1 -0
- package/dist/tab-view/tab-view-host.d.ts +25 -0
- package/dist/tab-view/tab-view-host.d.ts.map +1 -0
- package/dist/tab-view/tab-view-host.js +284 -0
- package/dist/tab-view/tab-view-host.js.map +1 -0
- package/dist/tab-view/tab-view-router.d.ts +34 -0
- package/dist/tab-view/tab-view-router.d.ts.map +1 -0
- package/dist/tab-view/tab-view-router.js +359 -0
- package/dist/tab-view/tab-view-router.js.map +1 -0
- package/dist/tab-view/types.d.ts +240 -0
- package/dist/tab-view/types.d.ts.map +1 -0
- package/dist/tab-view/types.js +2 -0
- package/dist/tab-view/types.js.map +1 -0
- package/dist/tabs/create-tab-navigator.d.ts +3 -1
- package/dist/tabs/create-tab-navigator.d.ts.map +1 -1
- package/dist/tabs/create-tab-navigator.js +0 -1
- package/dist/tabs/create-tab-navigator.js.map +1 -1
- package/dist/tabs/tab-view.d.ts.map +1 -1
- package/dist/tabs/tab-view.js +5 -7
- package/dist/tabs/tab-view.js.map +1 -1
- package/dist/tabs/types.d.ts +2 -0
- package/dist/tabs/types.d.ts.map +1 -1
- package/dist/tabs/types.js.map +1 -1
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +2 -2
- package/dist/theme.js.map +1 -1
- package/package.json +9 -19
- package/src/drawer/create-drawer-navigator.tsx +23 -11
- package/src/drawer/drawer-item-list.tsx +16 -12
- package/src/drawer/drawer-router.ts +4 -2
- package/src/drawer/drawer-view.tsx +18 -18
- package/src/drawer/types.ts +6 -3
- package/src/index.ts +31 -5
- package/src/shared/header-bar.tsx +2 -2
- package/src/shared/scene-page.tsx +7 -8
- package/src/shared/use-has-loaded.ts +13 -0
- package/src/split-view/create-split-view-navigator.tsx +16 -1
- package/src/split-view/split-view-collapsed.ts +21 -0
- package/src/split-view/split-view.tsx +102 -49
- package/src/split-view/types.ts +13 -5
- package/src/stack/create-stack-navigator.tsx +11 -1
- package/src/stack/stack-pages.ts +14 -12
- package/src/stack/stack-view.tsx +10 -16
- package/src/stack/types.ts +4 -3
- package/src/tab-view/create-tab-view-navigator.tsx +122 -0
- package/src/tab-view/page-registry.ts +139 -0
- package/src/tab-view/tab-view-host.tsx +474 -0
- package/src/tab-view/tab-view-router.ts +528 -0
- package/src/tab-view/types.ts +291 -0
- package/src/tabs/create-tab-navigator.tsx +11 -1
- package/src/tabs/tab-view.tsx +28 -22
- package/src/tabs/types.ts +6 -3
- package/src/theme.ts +2 -3
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import type * as Adw from "@gtkx/gi/adw";
|
|
2
|
+
import type * as Gio from "@gtkx/gi/gio";
|
|
3
|
+
import type * as GObject from "@gtkx/gi/gobject";
|
|
4
|
+
import type { AdwTabDropProps } from "@gtkx/react/internal";
|
|
5
|
+
import type {
|
|
6
|
+
DefaultNavigatorOptions,
|
|
7
|
+
Descriptor,
|
|
8
|
+
NavigationHelpers,
|
|
9
|
+
NavigationProp,
|
|
10
|
+
NavigationState,
|
|
11
|
+
ParamListBase,
|
|
12
|
+
RouteProp,
|
|
13
|
+
} from "@react-navigation/core";
|
|
14
|
+
import type { ReactNode } from "react";
|
|
15
|
+
import type { HeaderOptions } from "../shared/types.js";
|
|
16
|
+
|
|
17
|
+
/** Navigation state of a tab view navigator. Pinned routes come first in `routes`, in `pinnedKeys` order. */
|
|
18
|
+
type TabViewNavigationState<ParamList extends ParamListBase> = NavigationState<ParamList> & {
|
|
19
|
+
/** Type of the router, in this case `tabview`. */
|
|
20
|
+
type: "tabview";
|
|
21
|
+
/** Keys of the pinned routes. */
|
|
22
|
+
pinnedKeys: string[];
|
|
23
|
+
/** Key of the tab each tab was opened from, by route key. */
|
|
24
|
+
parents: Record<string, string>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Options accepted when opening a tab. */
|
|
28
|
+
type TabViewOpenOptions = {
|
|
29
|
+
/** Key of the tab the new one is opened from; the new tab follows that tab and its descendants, which are selected again when it closes. */
|
|
30
|
+
parent?: string;
|
|
31
|
+
/** Whether the new tab is selected; defaults to `true`. */
|
|
32
|
+
select?: boolean;
|
|
33
|
+
/** Position among the unpinned tabs; defaults to the end. */
|
|
34
|
+
position?: number;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** Actions specific to the tab view router. */
|
|
38
|
+
type TabViewActionType =
|
|
39
|
+
| {
|
|
40
|
+
type: "OPEN_TAB";
|
|
41
|
+
payload: {
|
|
42
|
+
name: string;
|
|
43
|
+
params?: object;
|
|
44
|
+
key?: string;
|
|
45
|
+
parent?: string;
|
|
46
|
+
select?: boolean;
|
|
47
|
+
position?: number;
|
|
48
|
+
pinned?: boolean;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
| { type: "CLOSE_TAB"; payload: { key?: string } }
|
|
52
|
+
| { type: "CLOSE_OTHER_TABS"; payload: { key?: string } }
|
|
53
|
+
| { type: "CLOSE_TABS_BEFORE"; payload: { key?: string } }
|
|
54
|
+
| { type: "CLOSE_TABS_AFTER"; payload: { key?: string } }
|
|
55
|
+
| { type: "SELECT_TAB"; payload: { key: string } }
|
|
56
|
+
| { type: "REORDER_TAB"; payload: { key: string; position: number } }
|
|
57
|
+
| { type: "PIN_TAB"; payload: { key: string; pinned: boolean } };
|
|
58
|
+
|
|
59
|
+
/** Action helpers added to the navigation object of tab view screens. Keys default to the selected tab. */
|
|
60
|
+
type TabViewActionHelpers<ParamList extends ParamListBase> = {
|
|
61
|
+
/** Opens a new tab for a screen, or selects the open tab whose `getId` matches. */
|
|
62
|
+
openTab<RouteName extends keyof ParamList>(
|
|
63
|
+
name: RouteName,
|
|
64
|
+
params?: ParamList[RouteName],
|
|
65
|
+
options?: TabViewOpenOptions,
|
|
66
|
+
): void;
|
|
67
|
+
/** Closes a tab. Closing the last tab is left to the parent navigator or `onUnhandledAction`. */
|
|
68
|
+
closeTab(key?: string): void;
|
|
69
|
+
/** Closes every unpinned tab except one. */
|
|
70
|
+
closeOtherTabs(key?: string): void;
|
|
71
|
+
/** Closes the unpinned tabs before one. */
|
|
72
|
+
closeTabsBefore(key?: string): void;
|
|
73
|
+
/** Closes the unpinned tabs after one. */
|
|
74
|
+
closeTabsAfter(key?: string): void;
|
|
75
|
+
/** Selects a tab. */
|
|
76
|
+
selectTab(key: string): void;
|
|
77
|
+
/** Moves a tab within its pinned or unpinned group. */
|
|
78
|
+
reorderTab(key: string, position: number): void;
|
|
79
|
+
/** Pins a tab, moving it after the other pinned tabs, or unpins it, moving it before the unpinned tabs. */
|
|
80
|
+
pinTab(key: string, pinned: boolean): void;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/** Events the tab view navigator emits on top of React Navigation's core events. */
|
|
84
|
+
type TabViewNavigationEventMap = {
|
|
85
|
+
/** The user selected a tab natively. */
|
|
86
|
+
tabPress: {
|
|
87
|
+
/** No payload. */
|
|
88
|
+
data: undefined;
|
|
89
|
+
/** Calling `preventDefault` keeps the current tab. */
|
|
90
|
+
canPreventDefault: true;
|
|
91
|
+
};
|
|
92
|
+
/** The user activated the tab's indicator icon. */
|
|
93
|
+
indicatorActivated: {
|
|
94
|
+
/** No payload. */
|
|
95
|
+
data: undefined;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/** An icon given by theme name or as a `Gio.Icon`. */
|
|
100
|
+
type TabViewIcon = string | Gio.Icon;
|
|
101
|
+
|
|
102
|
+
/** Per-screen options of the tab view navigator. */
|
|
103
|
+
type TabViewNavigationOptions = HeaderOptions & {
|
|
104
|
+
/** Renders a custom top bar instead of the default `AdwHeaderBar`. */
|
|
105
|
+
header?: (props: TabViewHeaderProps) => ReactNode;
|
|
106
|
+
/** Icon shown in the tab; `null` shows the view's default icon. */
|
|
107
|
+
icon?: TabViewIcon | null;
|
|
108
|
+
/** Tooltip of the tab; supports Pango markup. */
|
|
109
|
+
tooltip?: string;
|
|
110
|
+
/** Search keyword for the tab overview. */
|
|
111
|
+
keyword?: string;
|
|
112
|
+
/** Whether the tab shows a loading spinner instead of its icon. */
|
|
113
|
+
loading?: boolean;
|
|
114
|
+
/** Whether the tab is highlighted as needing attention. */
|
|
115
|
+
needsAttention?: boolean;
|
|
116
|
+
/** Indicator icon shown at the end of the tab. */
|
|
117
|
+
indicatorIcon?: TabViewIcon | null;
|
|
118
|
+
/** Whether clicking the indicator emits `indicatorActivated`. */
|
|
119
|
+
indicatorActivatable?: boolean;
|
|
120
|
+
/** Tooltip of the indicator icon; supports Pango markup. */
|
|
121
|
+
indicatorTooltip?: string;
|
|
122
|
+
/** Whether the overview thumbnail stays live while the tab is not selected. */
|
|
123
|
+
liveThumbnail?: boolean;
|
|
124
|
+
/** Horizontal alignment of the overview thumbnail, from 0 to 1. */
|
|
125
|
+
thumbnailXalign?: number;
|
|
126
|
+
/** Vertical alignment of the overview thumbnail, from 0 to 1. */
|
|
127
|
+
thumbnailYalign?: number;
|
|
128
|
+
/** Whether the screen mounts on first selection instead of as soon as the tab opens; defaults to `true`. */
|
|
129
|
+
lazy?: boolean;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/** The screen a new tab opens, as returned by the overview's `onCreateTab`. */
|
|
133
|
+
type TabViewTarget = {
|
|
134
|
+
/** Name of the screen to open. */
|
|
135
|
+
name: string;
|
|
136
|
+
/** Params of the new tab. */
|
|
137
|
+
params?: object;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/** Settings of the `AdwTabOverview` rendered around the view. */
|
|
141
|
+
type TabViewOverviewConfig = {
|
|
142
|
+
/**
|
|
143
|
+
* Whether the overview is open. When given, the overview follows it: the user opening or closing the overview
|
|
144
|
+
* calls `onOpenChange`, and a value the app does not update is restored. Leave it out to let the overview open
|
|
145
|
+
* and close on its own.
|
|
146
|
+
*/
|
|
147
|
+
open?: boolean;
|
|
148
|
+
/** Called when the overview opens or closes natively. */
|
|
149
|
+
onOpenChange?: (open: boolean) => void;
|
|
150
|
+
/** Whether the overview shows a new tab button; defaults to `false`. */
|
|
151
|
+
enableNewTab?: boolean;
|
|
152
|
+
/** Whether the overview offers search; defaults to `true`. */
|
|
153
|
+
enableSearch?: boolean;
|
|
154
|
+
/** Returns the screen the new tab button opens. */
|
|
155
|
+
onCreateTab?: () => TabViewTarget;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** Additional drop target of the tab bar and overview. */
|
|
159
|
+
type TabViewExtraDropTarget = NonNullable<AdwTabDropProps["extraDropTarget"]>;
|
|
160
|
+
|
|
161
|
+
/** Props of the tab view navigator beyond the options every navigator shares. */
|
|
162
|
+
type TabViewNavigationConfig = {
|
|
163
|
+
/** A view created before the navigator renders, such as one returned from a `create-window` handler. */
|
|
164
|
+
view?: Adw.TabView;
|
|
165
|
+
/** Whether the tab bar renders; defaults to `true`. */
|
|
166
|
+
tabBarVisible?: boolean;
|
|
167
|
+
/** Whether the tab bar hides with a single tab; defaults to `true`. */
|
|
168
|
+
tabBarAutohide?: boolean;
|
|
169
|
+
/** Whether tabs expand to fill the bar; defaults to `true`. */
|
|
170
|
+
tabBarExpand?: boolean;
|
|
171
|
+
/** Whether close buttons sit at the start of tabs; defaults to `false`. */
|
|
172
|
+
tabBarInverted?: boolean;
|
|
173
|
+
/** Renders an `AdwTabOverview` around the view. */
|
|
174
|
+
overview?: TabViewOverviewConfig;
|
|
175
|
+
/** An existing menu model to use as the tabs' context menu. Use `renderMenu` to declare the menu in JSX instead. */
|
|
176
|
+
menuModel?: Gio.MenuModel | null;
|
|
177
|
+
/**
|
|
178
|
+
* Renders the tabs' context menu. Attach `ref` to a `GMenu`, or to any menu model element, anywhere in the
|
|
179
|
+
* returned tree; the navigator renders the tree outside the widget hierarchy and uses that model. A navigator
|
|
180
|
+
* given both `renderMenu` and a `menuModel` throws.
|
|
181
|
+
*/
|
|
182
|
+
renderMenu?: (ref: (menu: Gio.MenuModel | null) => void) => ReactNode;
|
|
183
|
+
/** Additional content accepted by drops on tabs. */
|
|
184
|
+
extraDropTarget?: TabViewExtraDropTarget | null;
|
|
185
|
+
/** Handles content dropped on a tab; returns whether the drop was accepted. */
|
|
186
|
+
onExtraDragDrop?: (route: RouteProp<ParamListBase>, value: GObject.Value) => boolean;
|
|
187
|
+
/** Returns the view of a new window when a tab is dragged out of this one. */
|
|
188
|
+
onCreateWindow?: () => Adw.TabView | null;
|
|
189
|
+
/** Called with the tab whose context menu opens, or `null` when it closes, after the chosen menu action has run. */
|
|
190
|
+
onSetupMenu?: (route: RouteProp<ParamListBase> | null) => void;
|
|
191
|
+
/** Keyboard shortcuts the view handles. */
|
|
192
|
+
shortcuts?: Adw.TabViewShortcuts;
|
|
193
|
+
/** Icon of tabs without an `icon` option. */
|
|
194
|
+
defaultIcon?: TabViewIcon | null;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/** Options of the tab view router. */
|
|
198
|
+
type TabViewRouterOptions = {
|
|
199
|
+
/** Screen of the tab opened when the view starts empty; defaults to the first screen. */
|
|
200
|
+
initialRouteName?: string;
|
|
201
|
+
/**
|
|
202
|
+
* Whether closing the last tab replaces it with a new tab of the initial route, instead of leaving that close
|
|
203
|
+
* unhandled for a parent navigator or the container's `onUnhandledAction`. Use it for a tab view inside a section
|
|
204
|
+
* of the app rather than a window of its own; defaults to `false`.
|
|
205
|
+
*/
|
|
206
|
+
replaceLastTab?: boolean;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/** Navigation object of a tab view screen. */
|
|
210
|
+
type TabViewNavigationProp<
|
|
211
|
+
ParamList extends ParamListBase,
|
|
212
|
+
RouteName extends keyof ParamList = keyof ParamList,
|
|
213
|
+
NavigatorID extends string | undefined = undefined,
|
|
214
|
+
> = NavigationProp<
|
|
215
|
+
ParamList,
|
|
216
|
+
RouteName,
|
|
217
|
+
NavigatorID,
|
|
218
|
+
TabViewNavigationState<ParamList>,
|
|
219
|
+
TabViewNavigationOptions,
|
|
220
|
+
TabViewNavigationEventMap
|
|
221
|
+
> &
|
|
222
|
+
TabViewActionHelpers<ParamList>;
|
|
223
|
+
|
|
224
|
+
/** Props a tab view screen component receives. */
|
|
225
|
+
type TabViewScreenProps<
|
|
226
|
+
ParamList extends ParamListBase,
|
|
227
|
+
RouteName extends keyof ParamList = keyof ParamList,
|
|
228
|
+
NavigatorID extends string | undefined = undefined,
|
|
229
|
+
> = {
|
|
230
|
+
/** Navigation object of the screen. */
|
|
231
|
+
navigation: TabViewNavigationProp<ParamList, RouteName, NavigatorID>;
|
|
232
|
+
/** The route the screen renders. */
|
|
233
|
+
route: RouteProp<ParamList, RouteName>;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/** Arguments of a custom tab view `header` renderer. */
|
|
237
|
+
type TabViewHeaderProps = {
|
|
238
|
+
/** The selected route. */
|
|
239
|
+
route: RouteProp<ParamListBase>;
|
|
240
|
+
/** Navigation object of the selected route. */
|
|
241
|
+
navigation: TabViewNavigationProp<ParamListBase>;
|
|
242
|
+
/** Resolved options of the selected route. */
|
|
243
|
+
options: TabViewNavigationOptions;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/** Navigation helpers of the tab view navigator itself. */
|
|
247
|
+
type TabViewNavigationHelpers = NavigationHelpers<ParamListBase, TabViewNavigationEventMap> &
|
|
248
|
+
TabViewActionHelpers<ParamListBase>;
|
|
249
|
+
|
|
250
|
+
/** Descriptor of one tab view route. */
|
|
251
|
+
type TabViewDescriptor = Descriptor<
|
|
252
|
+
TabViewNavigationOptions,
|
|
253
|
+
TabViewNavigationProp<ParamListBase>,
|
|
254
|
+
RouteProp<ParamListBase>
|
|
255
|
+
>;
|
|
256
|
+
/** Descriptors of the tab view routes, keyed by route key. */
|
|
257
|
+
type TabViewDescriptorMap = Record<string, TabViewDescriptor>;
|
|
258
|
+
|
|
259
|
+
/** Props of the tab view `Navigator` component. */
|
|
260
|
+
type TabViewNavigatorProps = DefaultNavigatorOptions<
|
|
261
|
+
ParamListBase,
|
|
262
|
+
string | undefined,
|
|
263
|
+
TabViewNavigationState<ParamListBase>,
|
|
264
|
+
TabViewNavigationOptions,
|
|
265
|
+
TabViewNavigationEventMap,
|
|
266
|
+
TabViewNavigationProp<ParamListBase>
|
|
267
|
+
> &
|
|
268
|
+
TabViewRouterOptions &
|
|
269
|
+
TabViewNavigationConfig;
|
|
270
|
+
|
|
271
|
+
export type {
|
|
272
|
+
TabViewActionHelpers,
|
|
273
|
+
TabViewActionType,
|
|
274
|
+
TabViewDescriptor,
|
|
275
|
+
TabViewDescriptorMap,
|
|
276
|
+
TabViewExtraDropTarget,
|
|
277
|
+
TabViewHeaderProps,
|
|
278
|
+
TabViewIcon,
|
|
279
|
+
TabViewNavigationConfig,
|
|
280
|
+
TabViewNavigationEventMap,
|
|
281
|
+
TabViewNavigationHelpers,
|
|
282
|
+
TabViewNavigationOptions,
|
|
283
|
+
TabViewNavigationProp,
|
|
284
|
+
TabViewNavigationState,
|
|
285
|
+
TabViewNavigatorProps,
|
|
286
|
+
TabViewOpenOptions,
|
|
287
|
+
TabViewOverviewConfig,
|
|
288
|
+
TabViewRouterOptions,
|
|
289
|
+
TabViewScreenProps,
|
|
290
|
+
TabViewTarget,
|
|
291
|
+
};
|
|
@@ -59,7 +59,17 @@ function createTabNavigator<
|
|
|
59
59
|
const ParamList extends ParamListBase,
|
|
60
60
|
const NavigatorID extends string | undefined = string | undefined,
|
|
61
61
|
const TypeBag extends NavigatorTypeBagBase = TabTypeBag<ParamList, NavigatorID>,
|
|
62
|
-
|
|
62
|
+
>(): TypedNavigator<TypeBag, undefined>;
|
|
63
|
+
/** Creates a tab navigator rendered with `AdwViewStack` and an `AdwViewSwitcher`. */
|
|
64
|
+
function createTabNavigator<
|
|
65
|
+
const ParamList extends ParamListBase,
|
|
66
|
+
const NavigatorID extends string | undefined = string | undefined,
|
|
67
|
+
const TypeBag extends NavigatorTypeBagBase = TabTypeBag<ParamList, NavigatorID>,
|
|
68
|
+
const Config extends StaticConfig<TypeBag> = StaticConfig<TypeBag>,
|
|
69
|
+
>(config: Config): TypedNavigator<TypeBag, Config>;
|
|
70
|
+
function createTabNavigator<
|
|
71
|
+
const TypeBag extends NavigatorTypeBagBase,
|
|
72
|
+
const Config extends StaticConfig<TypeBag> | undefined,
|
|
63
73
|
>(config?: Config): TypedNavigator<TypeBag, Config> {
|
|
64
74
|
return createNavigatorFactory(TabNavigator)(config) as TypedNavigator<TypeBag, Config>;
|
|
65
75
|
}
|
package/src/tabs/tab-view.tsx
CHANGED
|
@@ -23,25 +23,29 @@ type TabHeaderProps = {
|
|
|
23
23
|
|
|
24
24
|
type TabPageProps = {
|
|
25
25
|
descriptor: TabDescriptor;
|
|
26
|
+
isFocused: boolean;
|
|
26
27
|
isLoaded: boolean;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
const useTabSelection = (navigation: TabNavigationHelpers): ((name: string | null) => void) =>
|
|
30
|
-
useCallback(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
useCallback(
|
|
32
|
+
(name: string | null) => {
|
|
33
|
+
const current = navigation.getState();
|
|
34
|
+
const focusedKey = getFocusedRoute(current).key;
|
|
35
|
+
const route = current.routes.find((candidate) => candidate.key === name);
|
|
36
|
+
|
|
37
|
+
if (route === undefined || route.key === focusedKey) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const event = navigation.emit({ type: "tabPress", target: route.key, canPreventDefault: true });
|
|
42
|
+
|
|
43
|
+
if (!event.defaultPrevented) {
|
|
44
|
+
navigation.dispatch({ ...CommonActions.navigate(route.name, route.params), target: current.key });
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
[navigation],
|
|
48
|
+
);
|
|
45
49
|
|
|
46
50
|
const defaultTabHeader = ({ descriptor, viewSwitcher }: TabHeaderProps): ReactElement => (
|
|
47
51
|
<HeaderBar
|
|
@@ -67,16 +71,18 @@ const TabHeader = (props: TabHeaderProps): ReactNode => {
|
|
|
67
71
|
);
|
|
68
72
|
};
|
|
69
73
|
|
|
70
|
-
const TabPage = ({ descriptor, isLoaded }: TabPageProps): ReactNode => {
|
|
74
|
+
const TabPage = ({ descriptor, isFocused, isLoaded }: TabPageProps): ReactNode => {
|
|
71
75
|
const { route, options } = descriptor;
|
|
72
76
|
|
|
73
77
|
return (
|
|
74
78
|
<ScenePage
|
|
75
79
|
name={route.key}
|
|
76
80
|
title={options.tabBarLabel ?? options.title ?? route.name}
|
|
81
|
+
useUnderline={options.useUnderline}
|
|
77
82
|
iconName={options.tabBarIcon}
|
|
78
83
|
badgeNumber={options.tabBarBadge}
|
|
79
84
|
needsAttention={options.needsAttention}
|
|
85
|
+
isFocused={isFocused}
|
|
80
86
|
isLoaded={isLoaded || options.lazy === false}
|
|
81
87
|
render={() => descriptor.render()}
|
|
82
88
|
/>
|
|
@@ -89,19 +95,18 @@ const TabView = ({ state, navigation, descriptors, tabBarPosition = "top" }: Tab
|
|
|
89
95
|
const descriptor = requireDescriptor(descriptors, focused.key);
|
|
90
96
|
const onVisibleChildChanged = useTabSelection(navigation);
|
|
91
97
|
|
|
92
|
-
const viewSwitcher =
|
|
93
|
-
? undefined
|
|
94
|
-
: <AdwViewSwitcher stack={stack} policy={Adw.ViewSwitcherPolicy.WIDE} />;
|
|
98
|
+
const viewSwitcher =
|
|
99
|
+
stack === null ? undefined : <AdwViewSwitcher stack={stack} policy={Adw.ViewSwitcherPolicy.WIDE} />;
|
|
95
100
|
|
|
96
101
|
const hasSwitcherBar = tabBarPosition === "bottom" && stack !== null;
|
|
97
102
|
usePopToTopOnBlur(state, descriptors, navigation);
|
|
98
103
|
|
|
99
104
|
return (
|
|
100
105
|
<AdwToolbarView
|
|
101
|
-
|
|
106
|
+
top={
|
|
102
107
|
<TabHeader descriptor={descriptor} viewSwitcher={tabBarPosition === "top" ? viewSwitcher : undefined} />
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
}
|
|
109
|
+
bottom={hasSwitcherBar ? <AdwViewSwitcherBar stack={stack} reveal /> : undefined}
|
|
105
110
|
>
|
|
106
111
|
<AdwViewStack
|
|
107
112
|
ref={setStack}
|
|
@@ -113,6 +118,7 @@ const TabView = ({ state, navigation, descriptors, tabBarPosition = "top" }: Tab
|
|
|
113
118
|
<TabPage
|
|
114
119
|
key={route.key}
|
|
115
120
|
descriptor={requireDescriptor(descriptors, route.key)}
|
|
121
|
+
isFocused={route.key === focused.key}
|
|
116
122
|
isLoaded={route.key === focused.key || state.preloadedRouteKeys.includes(route.key)}
|
|
117
123
|
/>
|
|
118
124
|
))}
|
package/src/tabs/types.ts
CHANGED
|
@@ -29,6 +29,8 @@ type TabNavigationOptions = HeaderOptions & {
|
|
|
29
29
|
header?: (props: TabHeaderProps) => ReactNode;
|
|
30
30
|
/** Label shown in the view switcher; defaults to `title`, then to the route name. */
|
|
31
31
|
tabBarLabel?: string;
|
|
32
|
+
/** Whether underscores in the tab label indicate mnemonics; defaults to `false`. */
|
|
33
|
+
useUnderline?: boolean;
|
|
32
34
|
/** Icon name shown in the view switcher. */
|
|
33
35
|
tabBarIcon?: string;
|
|
34
36
|
/** Badge number shown in the view switcher; `0` hides the badge. */
|
|
@@ -61,7 +63,8 @@ type TabNavigationProp<
|
|
|
61
63
|
TabNavigationState<ParamList>,
|
|
62
64
|
TabNavigationOptions,
|
|
63
65
|
TabNavigationEventMap
|
|
64
|
-
> &
|
|
66
|
+
> &
|
|
67
|
+
TabActionHelpers<ParamList>;
|
|
65
68
|
|
|
66
69
|
/** Props a tab screen component receives. */
|
|
67
70
|
type TabScreenProps<
|
|
@@ -103,8 +106,8 @@ type TabNavigatorProps = DefaultNavigatorOptions<
|
|
|
103
106
|
TabNavigationEventMap,
|
|
104
107
|
TabNavigationProp<ParamListBase>
|
|
105
108
|
> &
|
|
106
|
-
TabRouterOptions &
|
|
107
|
-
TabNavigationConfig;
|
|
109
|
+
TabRouterOptions &
|
|
110
|
+
TabNavigationConfig;
|
|
108
111
|
|
|
109
112
|
export type {
|
|
110
113
|
TabDescriptor,
|
package/src/theme.ts
CHANGED
|
@@ -11,7 +11,6 @@ type AdwaitaTheme = {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
declare module "@react-navigation/core" {
|
|
14
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
15
14
|
interface Theme extends AdwaitaTheme {}
|
|
16
15
|
}
|
|
17
16
|
|
|
@@ -22,8 +21,8 @@ const DarkTheme: AdwaitaTheme = { dark: true, highContrast: false };
|
|
|
22
21
|
|
|
23
22
|
const useAdwaitaTheme = (): AdwaitaTheme => {
|
|
24
23
|
const manager = Adw.StyleManager.getDefault();
|
|
25
|
-
const isDark = useProperty(manager, "dark")
|
|
26
|
-
const isHighContrast = useProperty(manager, "highContrast")
|
|
24
|
+
const isDark = useProperty(manager, "dark");
|
|
25
|
+
const isHighContrast = useProperty(manager, "highContrast");
|
|
27
26
|
|
|
28
27
|
return useMemo(() => ({ dark: isDark, highContrast: isHighContrast }), [isDark, isHighContrast]);
|
|
29
28
|
};
|