@gtkx/navigation 0.0.1
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 +174 -0
- package/dist/drawer/create-drawer-navigator.d.ts +30 -0
- package/dist/drawer/create-drawer-navigator.d.ts.map +1 -0
- package/dist/drawer/create-drawer-navigator.js +36 -0
- package/dist/drawer/create-drawer-navigator.js.map +1 -0
- package/dist/drawer/drawer-collapsed-context.d.ts +4 -0
- package/dist/drawer/drawer-collapsed-context.d.ts.map +1 -0
- package/dist/drawer/drawer-collapsed-context.js +4 -0
- package/dist/drawer/drawer-collapsed-context.js.map +1 -0
- package/dist/drawer/drawer-item-list.d.ts +6 -0
- package/dist/drawer/drawer-item-list.d.ts.map +1 -0
- package/dist/drawer/drawer-item-list.js +40 -0
- package/dist/drawer/drawer-item-list.js.map +1 -0
- package/dist/drawer/drawer-router.d.ts +5 -0
- package/dist/drawer/drawer-router.d.ts.map +1 -0
- package/dist/drawer/drawer-router.js +49 -0
- package/dist/drawer/drawer-router.js.map +1 -0
- package/dist/drawer/drawer-status.d.ts +4 -0
- package/dist/drawer/drawer-status.d.ts.map +1 -0
- package/dist/drawer/drawer-status.js +11 -0
- package/dist/drawer/drawer-status.js.map +1 -0
- package/dist/drawer/drawer-view.d.ts +11 -0
- package/dist/drawer/drawer-view.d.ts.map +1 -0
- package/dist/drawer/drawer-view.js +67 -0
- package/dist/drawer/drawer-view.js.map +1 -0
- package/dist/drawer/types.d.ts +80 -0
- package/dist/drawer/types.d.ts.map +1 -0
- package/dist/drawer/types.js +2 -0
- package/dist/drawer/types.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/navigation-container.d.ts +15 -0
- package/dist/navigation-container.d.ts.map +1 -0
- package/dist/navigation-container.js +11 -0
- package/dist/navigation-container.js.map +1 -0
- package/dist/shared/header-bar.d.ts +11 -0
- package/dist/shared/header-bar.d.ts.map +1 -0
- package/dist/shared/header-bar.js +11 -0
- package/dist/shared/header-bar.js.map +1 -0
- package/dist/shared/routes.d.ts +6 -0
- package/dist/shared/routes.d.ts.map +1 -0
- package/dist/shared/routes.js +16 -0
- package/dist/shared/routes.js.map +1 -0
- package/dist/shared/scene-page.d.ts +13 -0
- package/dist/shared/scene-page.d.ts.map +1 -0
- package/dist/shared/scene-page.js +5 -0
- package/dist/shared/scene-page.js.map +1 -0
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/shared/use-loaded-routes.d.ts +3 -0
- package/dist/shared/use-loaded-routes.d.ts.map +1 -0
- package/dist/shared/use-loaded-routes.js +11 -0
- package/dist/shared/use-loaded-routes.js.map +1 -0
- package/dist/shared/use-pop-to-top-on-blur.d.ts +10 -0
- package/dist/shared/use-pop-to-top-on-blur.d.ts.map +1 -0
- package/dist/shared/use-pop-to-top-on-blur.js +27 -0
- package/dist/shared/use-pop-to-top-on-blur.js.map +1 -0
- package/dist/split-view/create-split-view-navigator.d.ts +33 -0
- package/dist/split-view/create-split-view-navigator.d.ts.map +1 -0
- package/dist/split-view/create-split-view-navigator.js +20 -0
- package/dist/split-view/create-split-view-navigator.js.map +1 -0
- package/dist/split-view/split-view-router.d.ts +5 -0
- package/dist/split-view/split-view-router.d.ts.map +1 -0
- package/dist/split-view/split-view-router.js +42 -0
- package/dist/split-view/split-view-router.js.map +1 -0
- package/dist/split-view/split-view.d.ts +12 -0
- package/dist/split-view/split-view.d.ts.map +1 -0
- package/dist/split-view/split-view.js +62 -0
- package/dist/split-view/split-view.js.map +1 -0
- package/dist/split-view/types.d.ts +43 -0
- package/dist/split-view/types.d.ts.map +1 -0
- package/dist/split-view/types.js +2 -0
- package/dist/split-view/types.js.map +1 -0
- package/dist/stack/create-stack-navigator.d.ts +30 -0
- package/dist/stack/create-stack-navigator.d.ts.map +1 -0
- package/dist/stack/create-stack-navigator.js +16 -0
- package/dist/stack/create-stack-navigator.js.map +1 -0
- package/dist/stack/stack-pages.d.ts +11 -0
- package/dist/stack/stack-pages.d.ts.map +1 -0
- package/dist/stack/stack-pages.js +80 -0
- package/dist/stack/stack-pages.js.map +1 -0
- package/dist/stack/stack-view.d.ts +14 -0
- package/dist/stack/stack-view.d.ts.map +1 -0
- package/dist/stack/stack-view.js +101 -0
- package/dist/stack/stack-view.js.map +1 -0
- package/dist/stack/sync-navigation-stack.d.ts +7 -0
- package/dist/stack/sync-navigation-stack.d.ts.map +1 -0
- package/dist/stack/sync-navigation-stack.js +69 -0
- package/dist/stack/sync-navigation-stack.js.map +1 -0
- package/dist/stack/types.d.ts +72 -0
- package/dist/stack/types.d.ts.map +1 -0
- package/dist/stack/types.js +2 -0
- package/dist/stack/types.js.map +1 -0
- package/dist/static-navigation.d.ts +13 -0
- package/dist/static-navigation.d.ts.map +1 -0
- package/dist/static-navigation.js +10 -0
- package/dist/static-navigation.js.map +1 -0
- package/dist/tabs/create-tab-navigator.d.ts +30 -0
- package/dist/tabs/create-tab-navigator.d.ts.map +1 -0
- package/dist/tabs/create-tab-navigator.js +16 -0
- package/dist/tabs/create-tab-navigator.js.map +1 -0
- package/dist/tabs/tab-view.d.ts +11 -0
- package/dist/tabs/tab-view.d.ts.map +1 -0
- package/dist/tabs/tab-view.js +52 -0
- package/dist/tabs/tab-view.js.map +1 -0
- package/dist/tabs/types.d.ts +67 -0
- package/dist/tabs/types.d.ts.map +1 -0
- package/dist/tabs/types.js +2 -0
- package/dist/tabs/types.js.map +1 -0
- package/dist/theme.d.ts +18 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +15 -0
- package/dist/theme.js.map +1 -0
- package/package.json +71 -0
- package/src/drawer/create-drawer-navigator.tsx +123 -0
- package/src/drawer/drawer-collapsed-context.ts +5 -0
- package/src/drawer/drawer-item-list.tsx +74 -0
- package/src/drawer/drawer-router.ts +90 -0
- package/src/drawer/drawer-status.ts +19 -0
- package/src/drawer/drawer-view.tsx +171 -0
- package/src/drawer/types.ts +142 -0
- package/src/index.ts +83 -0
- package/src/navigation-container.tsx +35 -0
- package/src/shared/header-bar.tsx +34 -0
- package/src/shared/routes.ts +25 -0
- package/src/shared/scene-page.tsx +27 -0
- package/src/shared/types.ts +17 -0
- package/src/shared/use-loaded-routes.ts +14 -0
- package/src/shared/use-pop-to-top-on-blur.ts +45 -0
- package/src/split-view/create-split-view-navigator.tsx +99 -0
- package/src/split-view/split-view-router.ts +73 -0
- package/src/split-view/split-view.tsx +137 -0
- package/src/split-view/types.ts +100 -0
- package/src/stack/create-stack-navigator.tsx +80 -0
- package/src/stack/stack-pages.ts +140 -0
- package/src/stack/stack-view.tsx +202 -0
- package/src/stack/sync-navigation-stack.ts +117 -0
- package/src/stack/types.ts +131 -0
- package/src/static-navigation.tsx +26 -0
- package/src/tabs/create-tab-navigator.tsx +69 -0
- package/src/tabs/tab-view.tsx +126 -0
- package/src/tabs/types.ts +120 -0
- package/src/theme.ts +31 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import * as Gdk from "@gtkx/gi/gdk";
|
|
3
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
4
|
+
import { AdwNavigationPage, AdwNavigationSplitView, AdwToolbarView } from "@gtkx/jsx/adw";
|
|
5
|
+
import { GtkEventControllerKey } from "@gtkx/jsx/gtk";
|
|
6
|
+
import { StackActions } from "@react-navigation/core";
|
|
7
|
+
import { useCallback, useRef } from "react";
|
|
8
|
+
import { HeaderBar } from "../shared/header-bar.js";
|
|
9
|
+
import { requireDescriptor } from "../shared/routes.js";
|
|
10
|
+
import { StackView } from "../stack/stack-view.js";
|
|
11
|
+
const PACK_TYPES = { start: Gtk.PackType.START, end: Gtk.PackType.END };
|
|
12
|
+
const CONTENT_TITLE = "Content";
|
|
13
|
+
const ESCAPE_KEYVAL = Gdk.KEY_Escape;
|
|
14
|
+
const hasContent = (state) => state.routes.length > 1;
|
|
15
|
+
const contentTitle = (state, descriptors) => {
|
|
16
|
+
const route = state.routes[state.index];
|
|
17
|
+
if (route === undefined || state.index === 0) {
|
|
18
|
+
return state.routeNames[1] ?? CONTENT_TITLE;
|
|
19
|
+
}
|
|
20
|
+
return descriptors[route.key]?.options.title ?? route.name;
|
|
21
|
+
};
|
|
22
|
+
const popContent = (navigation) => {
|
|
23
|
+
const state = navigation.getState();
|
|
24
|
+
navigation.dispatch({ ...StackActions.pop(state.routes.length - 1), target: state.key });
|
|
25
|
+
};
|
|
26
|
+
const settleShowContent = (viewRef, isShown, isSettled) => {
|
|
27
|
+
if (isSettled !== isShown && viewRef.current !== null) {
|
|
28
|
+
viewRef.current.setShowContent(isSettled);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const useContentSync = (viewRef, navigation) => useCallback((isShown) => {
|
|
32
|
+
if (isShown === null || isShown === hasContent(navigation.getState())) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!isShown) {
|
|
36
|
+
popContent(navigation);
|
|
37
|
+
}
|
|
38
|
+
settleShowContent(viewRef, isShown, hasContent(navigation.getState()));
|
|
39
|
+
}, [viewRef, navigation]);
|
|
40
|
+
const EscapeGuard = () => (_jsx(GtkEventControllerKey, { propagationPhase: Gtk.PropagationPhase.BUBBLE, onKeyPressed: (keyval) => keyval === ESCAPE_KEYVAL }));
|
|
41
|
+
const SidebarPage = ({ descriptor }) => {
|
|
42
|
+
const { route, options, navigation } = descriptor;
|
|
43
|
+
if (options.headerShown === false) {
|
|
44
|
+
return _jsx(AdwNavigationPage, { title: options.title ?? route.name, children: descriptor.render() });
|
|
45
|
+
}
|
|
46
|
+
const topBar = options.header === undefined
|
|
47
|
+
? _jsx(HeaderBar, { options: options, showBackButton: false })
|
|
48
|
+
: _jsx(_Fragment, { children: options.header({ route, navigation, options, back: undefined }) });
|
|
49
|
+
return (_jsx(AdwNavigationPage, { title: options.title ?? route.name, children: _jsx(AdwToolbarView, { topBar: topBar, children: descriptor.render() }) }));
|
|
50
|
+
};
|
|
51
|
+
const SplitView = (props) => {
|
|
52
|
+
const { state, navigation, descriptors, describe, contentPlaceholder } = props;
|
|
53
|
+
const { collapsed = false, sidebarPosition = "start", minSidebarWidth, maxSidebarWidth } = props;
|
|
54
|
+
const viewRef = useRef(null);
|
|
55
|
+
const onShowContentChanged = useContentSync(viewRef, navigation);
|
|
56
|
+
const sidebar = requireDescriptor(descriptors, state.routes[0]?.key ?? "");
|
|
57
|
+
return (_jsx(AdwNavigationSplitView, { ref: viewRef, collapsed: collapsed, showContent: hasContent(state), sidebarPosition: PACK_TYPES[sidebarPosition], minSidebarWidth: minSidebarWidth, maxSidebarWidth: maxSidebarWidth, sidebarWidthFraction: props.sidebarWidthFraction, onNotifyShowContent: onShowContentChanged, sidebar: _jsx(SidebarPage, { descriptor: sidebar }), children: _jsx(AdwNavigationPage, { title: contentTitle(state, descriptors), controllers: collapsed && props.popOnEscape === false ? _jsx(EscapeGuard, {}) : null, children: hasContent(state)
|
|
58
|
+
? (_jsx(StackView, { offset: 1, popOnEscape: props.popOnEscape, state: state, navigation: navigation, descriptors: descriptors, describe: describe }))
|
|
59
|
+
: _jsx(_Fragment, { children: contentPlaceholder }) }) }));
|
|
60
|
+
};
|
|
61
|
+
export { SplitView };
|
|
62
|
+
//# sourceMappingURL=split-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split-view.js","sourceRoot":"","sources":["../../src/split-view/split-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import type * as Adw from \"@gtkx/gi/adw\";\nimport type { ParamListBase, RouteProp, StackNavigationState } from \"@react-navigation/core\";\nimport type { ReactNode } from \"react\";\nimport * as Gdk from \"@gtkx/gi/gdk\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { AdwNavigationPage, AdwNavigationSplitView, AdwToolbarView } from \"@gtkx/jsx/adw\";\nimport { GtkEventControllerKey } from \"@gtkx/jsx/gtk\";\nimport { StackActions } from \"@react-navigation/core\";\nimport { useCallback, useRef } from \"react\";\nimport type {\n SplitViewDescriptor,\n SplitViewDescriptorMap,\n SplitViewNavigationConfig,\n SplitViewNavigationHelpers,\n} from \"./types.js\";\nimport { HeaderBar } from \"../shared/header-bar.js\";\nimport { requireDescriptor } from \"../shared/routes.js\";\nimport { StackView } from \"../stack/stack-view.js\";\n\ntype ViewRef = { current: Adw.NavigationSplitView | null };\n\ntype SplitViewProps = SplitViewNavigationConfig & {\n state: StackNavigationState<ParamListBase>;\n navigation: SplitViewNavigationHelpers;\n descriptors: SplitViewDescriptorMap;\n describe: (route: RouteProp<ParamListBase>, isPlaceholder: boolean) => SplitViewDescriptor;\n};\n\nconst PACK_TYPES = { start: Gtk.PackType.START, end: Gtk.PackType.END } as const;\nconst CONTENT_TITLE = \"Content\";\nconst ESCAPE_KEYVAL = Gdk.KEY_Escape;\n\nconst hasContent = (state: { routes: readonly unknown[] }): boolean => state.routes.length > 1;\n\nconst contentTitle = (state: StackNavigationState<ParamListBase>, descriptors: SplitViewDescriptorMap): string => {\n const route = state.routes[state.index];\n\n if (route === undefined || state.index === 0) {\n return state.routeNames[1] ?? CONTENT_TITLE;\n }\n\n return descriptors[route.key]?.options.title ?? route.name;\n};\n\nconst popContent = (navigation: SplitViewNavigationHelpers): void => {\n const state = navigation.getState();\n navigation.dispatch({ ...StackActions.pop(state.routes.length - 1), target: state.key });\n};\n\nconst settleShowContent = (viewRef: ViewRef, isShown: boolean, isSettled: boolean): void => {\n if (isSettled !== isShown && viewRef.current !== null) {\n viewRef.current.setShowContent(isSettled);\n }\n};\n\nconst useContentSync = (\n viewRef: ViewRef,\n navigation: SplitViewNavigationHelpers,\n): ((isShown: boolean | null) => void) =>\n useCallback((isShown: boolean | null) => {\n if (isShown === null || isShown === hasContent(navigation.getState())) {\n return;\n }\n\n if (!isShown) {\n popContent(navigation);\n }\n\n settleShowContent(viewRef, isShown, hasContent(navigation.getState()));\n }, [viewRef, navigation]);\n\nconst EscapeGuard = (): ReactNode => (\n <GtkEventControllerKey\n propagationPhase={Gtk.PropagationPhase.BUBBLE}\n onKeyPressed={(keyval) => keyval === ESCAPE_KEYVAL}\n />\n);\n\nconst SidebarPage = ({ descriptor }: { descriptor: SplitViewDescriptor }): ReactNode => {\n const { route, options, navigation } = descriptor;\n\n if (options.headerShown === false) {\n return <AdwNavigationPage title={options.title ?? route.name}>{descriptor.render()}</AdwNavigationPage>;\n }\n\n const topBar = options.header === undefined\n ? <HeaderBar options={options} showBackButton={false} />\n : <>{options.header({ route, navigation, options, back: undefined })}</>;\n\n return (\n <AdwNavigationPage title={options.title ?? route.name}>\n <AdwToolbarView topBar={topBar}>{descriptor.render()}</AdwToolbarView>\n </AdwNavigationPage>\n );\n};\n\nconst SplitView = (props: SplitViewProps): ReactNode => {\n const { state, navigation, descriptors, describe, contentPlaceholder } = props;\n const { collapsed = false, sidebarPosition = \"start\", minSidebarWidth, maxSidebarWidth } = props;\n const viewRef = useRef<Adw.NavigationSplitView | null>(null);\n const onShowContentChanged = useContentSync(viewRef, navigation);\n const sidebar = requireDescriptor(descriptors, state.routes[0]?.key ?? \"\");\n\n return (\n <AdwNavigationSplitView\n ref={viewRef}\n collapsed={collapsed}\n showContent={hasContent(state)}\n sidebarPosition={PACK_TYPES[sidebarPosition]}\n minSidebarWidth={minSidebarWidth}\n maxSidebarWidth={maxSidebarWidth}\n sidebarWidthFraction={props.sidebarWidthFraction}\n onNotifyShowContent={onShowContentChanged}\n sidebar={<SidebarPage descriptor={sidebar} />}\n >\n <AdwNavigationPage\n title={contentTitle(state, descriptors)}\n controllers={collapsed && props.popOnEscape === false ? <EscapeGuard /> : null}\n >\n {hasContent(state)\n ? (\n <StackView\n offset={1}\n popOnEscape={props.popOnEscape}\n state={state}\n navigation={navigation}\n descriptors={descriptors}\n describe={describe}\n />\n )\n : <>{contentPlaceholder}</>}\n </AdwNavigationPage>\n </AdwNavigationSplitView>\n );\n};\n\nexport { SplitView };\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DefaultNavigatorOptions, Descriptor, NavigationHelpers, NavigationProp, ParamListBase, RouteProp, StackActionHelpers, StackNavigationState, StackRouterOptions } from "@react-navigation/core";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type { StackNavigationEventMap, StackNavigationOptions } from "../stack/types.js";
|
|
4
|
+
/** Events the split view navigator emits: the stack's transition events, from the content pane. */
|
|
5
|
+
type SplitViewNavigationEventMap = StackNavigationEventMap;
|
|
6
|
+
/** Per-screen options of the split view navigator, the same ones a stack screen takes. */
|
|
7
|
+
type SplitViewNavigationOptions = StackNavigationOptions;
|
|
8
|
+
/** Navigation object of a split view screen. */
|
|
9
|
+
type SplitViewNavigationProp<ParamList extends ParamListBase, RouteName extends keyof ParamList = keyof ParamList, NavigatorID extends string | undefined = undefined> = NavigationProp<ParamList, RouteName, NavigatorID, StackNavigationState<ParamList>, SplitViewNavigationOptions, SplitViewNavigationEventMap> & StackActionHelpers<ParamList>;
|
|
10
|
+
/** Props a split view screen component receives. */
|
|
11
|
+
type SplitViewScreenProps<ParamList extends ParamListBase, RouteName extends keyof ParamList = keyof ParamList, NavigatorID extends string | undefined = undefined> = {
|
|
12
|
+
/** Navigation object of the screen. */
|
|
13
|
+
navigation: SplitViewNavigationProp<ParamList, RouteName, NavigatorID>;
|
|
14
|
+
/** The route the screen renders. */
|
|
15
|
+
route: RouteProp<ParamList, RouteName>;
|
|
16
|
+
};
|
|
17
|
+
/** Navigation helpers of the split view navigator itself. */
|
|
18
|
+
type SplitViewNavigationHelpers = NavigationHelpers<ParamListBase, SplitViewNavigationEventMap> & StackActionHelpers<ParamListBase>;
|
|
19
|
+
/** Descriptor of one split view route. */
|
|
20
|
+
type SplitViewDescriptor = Descriptor<SplitViewNavigationOptions, SplitViewNavigationProp<ParamListBase>, RouteProp<ParamListBase>>;
|
|
21
|
+
/** Descriptors of the split view routes, keyed by route key. */
|
|
22
|
+
type SplitViewDescriptorMap = Record<string, SplitViewDescriptor>;
|
|
23
|
+
/** Props of the split view navigator beyond the options every navigator shares. */
|
|
24
|
+
type SplitViewNavigationConfig = {
|
|
25
|
+
/** Whether the panes stack into one instead of sitting side by side; defaults to `false`. */
|
|
26
|
+
collapsed?: boolean;
|
|
27
|
+
/** Fills the content pane while no content route is open; defaults to nothing. */
|
|
28
|
+
contentPlaceholder?: ReactNode;
|
|
29
|
+
/** Which side the sidebar sits on; defaults to `"start"`. */
|
|
30
|
+
sidebarPosition?: "start" | "end";
|
|
31
|
+
/** Minimum sidebar width, in the unit libadwaita uses for the split view. */
|
|
32
|
+
minSidebarWidth?: number;
|
|
33
|
+
/** Maximum sidebar width, in the unit libadwaita uses for the split view. */
|
|
34
|
+
maxSidebarWidth?: number;
|
|
35
|
+
/** Preferred sidebar width as a fraction of the total width. */
|
|
36
|
+
sidebarWidthFraction?: number;
|
|
37
|
+
/** Whether pressing Escape pops the visible content page; defaults to `true`. */
|
|
38
|
+
popOnEscape?: boolean;
|
|
39
|
+
};
|
|
40
|
+
/** Props of the split view `Navigator` component. */
|
|
41
|
+
type SplitViewNavigatorProps = DefaultNavigatorOptions<ParamListBase, string | undefined, StackNavigationState<ParamListBase>, SplitViewNavigationOptions, SplitViewNavigationEventMap, SplitViewNavigationProp<ParamListBase>> & StackRouterOptions & SplitViewNavigationConfig;
|
|
42
|
+
export type { SplitViewDescriptor, SplitViewDescriptorMap, SplitViewNavigationConfig, SplitViewNavigationEventMap, SplitViewNavigationHelpers, SplitViewNavigationOptions, SplitViewNavigationProp, SplitViewNavigatorProps, SplitViewScreenProps, };
|
|
43
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/split-view/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEzF,mGAAmG;AACnG,KAAK,2BAA2B,GAAG,uBAAuB,CAAC;AAC3D,0FAA0F;AAC1F,KAAK,0BAA0B,GAAG,sBAAsB,CAAC;AAEzD,gDAAgD;AAChD,KAAK,uBAAuB,CACxB,SAAS,SAAS,aAAa,EAC/B,SAAS,SAAS,MAAM,SAAS,GAAG,MAAM,SAAS,EACnD,WAAW,SAAS,MAAM,GAAG,SAAS,GAAG,SAAS,IAClD,cAAc,CACd,SAAS,EACT,SAAS,EACT,WAAW,EACX,oBAAoB,CAAC,SAAS,CAAC,EAC/B,0BAA0B,EAC1B,2BAA2B,CAC9B,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAElC,oDAAoD;AACpD,KAAK,oBAAoB,CACrB,SAAS,SAAS,aAAa,EAC/B,SAAS,SAAS,MAAM,SAAS,GAAG,MAAM,SAAS,EACnD,WAAW,SAAS,MAAM,GAAG,SAAS,GAAG,SAAS,IAClD;IACA,uCAAuC;IACvC,UAAU,EAAE,uBAAuB,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACvE,oCAAoC;IACpC,KAAK,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;CAC1C,CAAC;AAEF,6DAA6D;AAC7D,KAAK,0BAA0B,GAAG,iBAAiB,CAAC,aAAa,EAAE,2BAA2B,CAAC,GAC3F,kBAAkB,CAAC,aAAa,CAAC,CAAC;AAEtC,0CAA0C;AAC1C,KAAK,mBAAmB,GAAG,UAAU,CACjC,0BAA0B,EAC1B,uBAAuB,CAAC,aAAa,CAAC,EACtC,SAAS,CAAC,aAAa,CAAC,CAC3B,CAAC;AAEF,gEAAgE;AAChE,KAAK,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAElE,mFAAmF;AACnF,KAAK,yBAAyB,GAAG;IAC7B,6FAA6F;IAC7F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kFAAkF;IAClF,kBAAkB,CAAC,EAAE,SAAS,CAAC;IAC/B,6DAA6D;IAC7D,eAAe,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAClC,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iFAAiF;IACjF,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,qDAAqD;AACrD,KAAK,uBAAuB,GAAG,uBAAuB,CAClD,aAAa,EACb,MAAM,GAAG,SAAS,EAClB,oBAAoB,CAAC,aAAa,CAAC,EACnC,0BAA0B,EAC1B,2BAA2B,EAC3B,uBAAuB,CAAC,aAAa,CAAC,CACzC,GACD,kBAAkB,GAClB,yBAAyB,CAAC;AAE1B,YAAY,EACR,mBAAmB,EACnB,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,EAC3B,0BAA0B,EAC1B,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,GACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/split-view/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n DefaultNavigatorOptions,\n Descriptor,\n NavigationHelpers,\n NavigationProp,\n ParamListBase,\n RouteProp,\n StackActionHelpers,\n StackNavigationState,\n StackRouterOptions,\n} from \"@react-navigation/core\";\nimport type { ReactNode } from \"react\";\nimport type { StackNavigationEventMap, StackNavigationOptions } from \"../stack/types.js\";\n\n/** Events the split view navigator emits: the stack's transition events, from the content pane. */\ntype SplitViewNavigationEventMap = StackNavigationEventMap;\n/** Per-screen options of the split view navigator, the same ones a stack screen takes. */\ntype SplitViewNavigationOptions = StackNavigationOptions;\n\n/** Navigation object of a split view screen. */\ntype SplitViewNavigationProp<\n ParamList extends ParamListBase,\n RouteName extends keyof ParamList = keyof ParamList,\n NavigatorID extends string | undefined = undefined,\n> = NavigationProp<\n ParamList,\n RouteName,\n NavigatorID,\n StackNavigationState<ParamList>,\n SplitViewNavigationOptions,\n SplitViewNavigationEventMap\n> & StackActionHelpers<ParamList>;\n\n/** Props a split view screen component receives. */\ntype SplitViewScreenProps<\n ParamList extends ParamListBase,\n RouteName extends keyof ParamList = keyof ParamList,\n NavigatorID extends string | undefined = undefined,\n> = {\n /** Navigation object of the screen. */\n navigation: SplitViewNavigationProp<ParamList, RouteName, NavigatorID>;\n /** The route the screen renders. */\n route: RouteProp<ParamList, RouteName>;\n};\n\n/** Navigation helpers of the split view navigator itself. */\ntype SplitViewNavigationHelpers = NavigationHelpers<ParamListBase, SplitViewNavigationEventMap> &\n StackActionHelpers<ParamListBase>;\n\n/** Descriptor of one split view route. */\ntype SplitViewDescriptor = Descriptor<\n SplitViewNavigationOptions,\n SplitViewNavigationProp<ParamListBase>,\n RouteProp<ParamListBase>\n>;\n\n/** Descriptors of the split view routes, keyed by route key. */\ntype SplitViewDescriptorMap = Record<string, SplitViewDescriptor>;\n\n/** Props of the split view navigator beyond the options every navigator shares. */\ntype SplitViewNavigationConfig = {\n /** Whether the panes stack into one instead of sitting side by side; defaults to `false`. */\n collapsed?: boolean;\n /** Fills the content pane while no content route is open; defaults to nothing. */\n contentPlaceholder?: ReactNode;\n /** Which side the sidebar sits on; defaults to `\"start\"`. */\n sidebarPosition?: \"start\" | \"end\";\n /** Minimum sidebar width, in the unit libadwaita uses for the split view. */\n minSidebarWidth?: number;\n /** Maximum sidebar width, in the unit libadwaita uses for the split view. */\n maxSidebarWidth?: number;\n /** Preferred sidebar width as a fraction of the total width. */\n sidebarWidthFraction?: number;\n /** Whether pressing Escape pops the visible content page; defaults to `true`. */\n popOnEscape?: boolean;\n};\n\n/** Props of the split view `Navigator` component. */\ntype SplitViewNavigatorProps = DefaultNavigatorOptions<\n ParamListBase,\n string | undefined,\n StackNavigationState<ParamListBase>,\n SplitViewNavigationOptions,\n SplitViewNavigationEventMap,\n SplitViewNavigationProp<ParamListBase>\n> &\nStackRouterOptions &\nSplitViewNavigationConfig;\n\nexport type {\n SplitViewDescriptor,\n SplitViewDescriptorMap,\n SplitViewNavigationConfig,\n SplitViewNavigationEventMap,\n SplitViewNavigationHelpers,\n SplitViewNavigationOptions,\n SplitViewNavigationProp,\n SplitViewNavigatorProps,\n SplitViewScreenProps,\n};\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { NavigatorTypeBagBase, ParamListBase, StackNavigationState, StaticConfig, StaticScreenFactory, TypedNavigator } from "@react-navigation/core";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type { StackNavigationEventMap, StackNavigationOptions, StackNavigationProp, StackNavigatorProps } from "./types.js";
|
|
4
|
+
/** Type bag describing the stack navigator to React Navigation's typed APIs. */
|
|
5
|
+
type StackTypeBag<ParamList extends ParamListBase = ParamListBase, NavigatorID extends string | undefined = string | undefined> = {
|
|
6
|
+
/** Route names and their params. */
|
|
7
|
+
ParamList: ParamList;
|
|
8
|
+
/** Optional navigator id. */
|
|
9
|
+
NavigatorID: NavigatorID;
|
|
10
|
+
/** Shape of the navigator state. */
|
|
11
|
+
State: StackNavigationState<ParamList>;
|
|
12
|
+
/** Per-screen options. */
|
|
13
|
+
ScreenOptions: StackNavigationOptions;
|
|
14
|
+
/** Events the navigator emits. */
|
|
15
|
+
EventMap: StackNavigationEventMap;
|
|
16
|
+
/** Navigation object per route. */
|
|
17
|
+
NavigationList: {
|
|
18
|
+
[RouteName in keyof ParamList]: StackNavigationProp<ParamList, RouteName, NavigatorID>;
|
|
19
|
+
};
|
|
20
|
+
/** The navigator component. */
|
|
21
|
+
Navigator: typeof StackNavigator;
|
|
22
|
+
};
|
|
23
|
+
/** Declares a typed screen of a stack navigator for the static configuration API. */
|
|
24
|
+
declare const createStackScreen: StaticScreenFactory<StackTypeBag>;
|
|
25
|
+
/** Renders the screens of a {@link createStackNavigator} as pages of an `AdwNavigationView`. */
|
|
26
|
+
declare function StackNavigator({ popOnEscape, ...options }: StackNavigatorProps): ReactNode;
|
|
27
|
+
/** Creates a stack navigator rendered with `AdwNavigationView`: pushes and pops animate like native Adwaita pages. */
|
|
28
|
+
declare function createStackNavigator<const ParamList extends ParamListBase, const NavigatorID extends string | undefined = string | undefined, const TypeBag extends NavigatorTypeBagBase = StackTypeBag<ParamList, NavigatorID>, const Config extends StaticConfig<TypeBag> | undefined = undefined>(config?: Config): TypedNavigator<TypeBag, Config>;
|
|
29
|
+
export { createStackNavigator, createStackScreen, StackNavigator, type StackTypeBag };
|
|
30
|
+
//# sourceMappingURL=create-stack-navigator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-stack-navigator.d.ts","sourceRoot":"","sources":["../../src/stack/create-stack-navigator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,oBAAoB,EACpB,aAAa,EAEb,oBAAoB,EAEpB,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EACR,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACtB,MAAM,YAAY,CAAC;AAGpB,gFAAgF;AAChF,KAAK,YAAY,CACb,SAAS,SAAS,aAAa,GAAG,aAAa,EAC/C,WAAW,SAAS,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,IAC3D;IACA,oCAAoC;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,6BAA6B;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,oCAAoC;IACpC,KAAK,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvC,0BAA0B;IAC1B,aAAa,EAAE,sBAAsB,CAAC;IACtC,kCAAkC;IAClC,QAAQ,EAAE,uBAAuB,CAAC;IAClC,mCAAmC;IACnC,cAAc,EAAE;SACX,SAAS,IAAI,MAAM,SAAS,GAAG,mBAAmB,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC;KACzF,CAAC;IACF,+BAA+B;IAC/B,SAAS,EAAE,OAAO,cAAc,CAAC;CACpC,CAAC;AAEF,qFAAqF;AACrF,QAAA,MAAM,iBAAiB,EAAE,mBAAmB,CAAC,YAAY,CAAuC,CAAC;AAEjG,gGAAgG;AAChG,iBAAS,cAAc,CAAC,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,EAAE,mBAAmB,GAAG,SAAS,CAoBnF;AAED,sHAAsH;AACtH,iBAAS,oBAAoB,CACzB,KAAK,CAAC,SAAS,SAAS,aAAa,EACrC,KAAK,CAAC,WAAW,SAAS,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,EACjE,KAAK,CAAC,OAAO,SAAS,oBAAoB,GAAG,YAAY,CAAC,SAAS,EAAE,WAAW,CAAC,EACjF,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,SAAS,EACpE,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAElD;AAED,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createNavigatorFactory, createScreenFactory, StackRouter, useNavigationBuilder } from "@react-navigation/core";
|
|
3
|
+
import { StackView } from "./stack-view.js";
|
|
4
|
+
/** Declares a typed screen of a stack navigator for the static configuration API. */
|
|
5
|
+
const createStackScreen = createScreenFactory();
|
|
6
|
+
/** Renders the screens of a {@link createStackNavigator} as pages of an `AdwNavigationView`. */
|
|
7
|
+
function StackNavigator({ popOnEscape, ...options }) {
|
|
8
|
+
const { state, describe, descriptors, navigation, NavigationContent } = useNavigationBuilder(StackRouter, options);
|
|
9
|
+
return (_jsx(NavigationContent, { children: _jsx(StackView, { popOnEscape: popOnEscape, state: state, navigation: navigation, descriptors: descriptors, describe: describe }) }));
|
|
10
|
+
}
|
|
11
|
+
/** Creates a stack navigator rendered with `AdwNavigationView`: pushes and pops animate like native Adwaita pages. */
|
|
12
|
+
function createStackNavigator(config) {
|
|
13
|
+
return createNavigatorFactory(StackNavigator)(config);
|
|
14
|
+
}
|
|
15
|
+
export { createStackNavigator, createStackScreen, StackNavigator };
|
|
16
|
+
//# sourceMappingURL=create-stack-navigator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-stack-navigator.js","sourceRoot":"","sources":["../../src/stack/create-stack-navigator.tsx"],"names":[],"mappings":";AAWA,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAOxH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAyB5C,qFAAqF;AACrF,MAAM,iBAAiB,GAAsC,mBAAmB,EAAgB,CAAC;AAEjG,gGAAgG;AAChG,SAAS,cAAc,CAAC,EAAE,WAAW,EAAE,GAAG,OAAO,EAAuB;IACpE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,GAAG,oBAAoB,CAM1F,WAAW,EAAE,OAAO,CAAC,CAAC;IAExB,OAAO,CACH,KAAC,iBAAiB,cACd,KAAC,SAAS,IACN,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,GACpB,GACc,CACvB,CAAC;AACN,CAAC;AAED,sHAAsH;AACtH,SAAS,oBAAoB,CAK3B,MAAe;IACb,OAAO,sBAAsB,CAAC,cAAc,CAAC,CAAC,MAAM,CAAoC,CAAC;AAC7F,CAAC;AAED,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,cAAc,EAAqB,CAAC","sourcesContent":["import type {\n NavigatorTypeBagBase,\n ParamListBase,\n StackActionHelpers,\n StackNavigationState,\n StackRouterOptions,\n StaticConfig,\n StaticScreenFactory,\n TypedNavigator,\n} from \"@react-navigation/core\";\nimport type { ReactNode } from \"react\";\nimport { createNavigatorFactory, createScreenFactory, StackRouter, useNavigationBuilder } from \"@react-navigation/core\";\nimport type {\n StackNavigationEventMap,\n StackNavigationOptions,\n StackNavigationProp,\n StackNavigatorProps,\n} from \"./types.js\";\nimport { StackView } from \"./stack-view.js\";\n\n/** Type bag describing the stack navigator to React Navigation's typed APIs. */\ntype StackTypeBag<\n ParamList extends ParamListBase = ParamListBase,\n NavigatorID extends string | undefined = string | undefined,\n> = {\n /** Route names and their params. */\n ParamList: ParamList;\n /** Optional navigator id. */\n NavigatorID: NavigatorID;\n /** Shape of the navigator state. */\n State: StackNavigationState<ParamList>;\n /** Per-screen options. */\n ScreenOptions: StackNavigationOptions;\n /** Events the navigator emits. */\n EventMap: StackNavigationEventMap;\n /** Navigation object per route. */\n NavigationList: {\n [RouteName in keyof ParamList]: StackNavigationProp<ParamList, RouteName, NavigatorID>;\n };\n /** The navigator component. */\n Navigator: typeof StackNavigator;\n};\n\n/** Declares a typed screen of a stack navigator for the static configuration API. */\nconst createStackScreen: StaticScreenFactory<StackTypeBag> = createScreenFactory<StackTypeBag>();\n\n/** Renders the screens of a {@link createStackNavigator} as pages of an `AdwNavigationView`. */\nfunction StackNavigator({ popOnEscape, ...options }: StackNavigatorProps): ReactNode {\n const { state, describe, descriptors, navigation, NavigationContent } = useNavigationBuilder<\n StackNavigationState<ParamListBase>,\n StackRouterOptions,\n StackActionHelpers<ParamListBase>,\n StackNavigationOptions,\n StackNavigationEventMap\n >(StackRouter, options);\n\n return (\n <NavigationContent>\n <StackView\n popOnEscape={popOnEscape}\n state={state}\n navigation={navigation}\n descriptors={descriptors}\n describe={describe}\n />\n </NavigationContent>\n );\n}\n\n/** Creates a stack navigator rendered with `AdwNavigationView`: pushes and pops animate like native Adwaita pages. */\nfunction createStackNavigator<\n const ParamList extends ParamListBase,\n const NavigatorID extends string | undefined = string | undefined,\n const TypeBag extends NavigatorTypeBagBase = StackTypeBag<ParamList, NavigatorID>,\n const Config extends StaticConfig<TypeBag> | undefined = undefined,\n>(config?: Config): TypedNavigator<TypeBag, Config> {\n return createNavigatorFactory(StackNavigator)(config) as TypedNavigator<TypeBag, Config>;\n}\n\nexport { createStackNavigator, createStackScreen, StackNavigator, type StackTypeBag };\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ParamListBase, RouteProp, StackNavigationState } from "@react-navigation/core";
|
|
2
|
+
import type { StackDescriptor, StackDescriptorMap } from "./types.js";
|
|
3
|
+
type StackState = StackNavigationState<ParamListBase>;
|
|
4
|
+
type Describe = (route: RouteProp<ParamListBase>, isPlaceholder: boolean) => StackDescriptor;
|
|
5
|
+
type StackPages = {
|
|
6
|
+
pages: readonly StackDescriptor[];
|
|
7
|
+
release: (key: string) => void;
|
|
8
|
+
};
|
|
9
|
+
declare const useStackPages: (state: StackState, descriptors: StackDescriptorMap, describe: Describe, offset: number) => StackPages;
|
|
10
|
+
export { type Describe, useStackPages };
|
|
11
|
+
//# sourceMappingURL=stack-pages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-pages.d.ts","sourceRoot":"","sources":["../../src/stack/stack-pages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE7F,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEtE,KAAK,UAAU,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;AACtD,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,OAAO,KAAK,eAAe,CAAC;AAS7F,KAAK,UAAU,GAAG;IACd,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAClC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC,CAAC;AAyFF,QAAA,MAAM,aAAa,GACf,OAAO,UAAU,EACjB,aAAa,kBAAkB,EAC/B,UAAU,QAAQ,EAClB,QAAQ,MAAM,KACf,UA0BF,CAAC;AAEF,OAAO,EAAE,KAAK,QAAQ,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
const getFocusedKey = (state, offset) => state.index < offset ? undefined : state.routes[state.index]?.key;
|
|
3
|
+
const mountedKeys = (state, offset) => [
|
|
4
|
+
...state.routes.slice(offset).map((route) => route.key),
|
|
5
|
+
...state.preloadedRoutes.map((route) => route.key),
|
|
6
|
+
];
|
|
7
|
+
const neededKeys = (state, closing, offset) => [
|
|
8
|
+
...mountedKeys(state, offset),
|
|
9
|
+
...Object.keys(closing),
|
|
10
|
+
];
|
|
11
|
+
const hasSameMembers = (left, right) => left.length === right.length && left.every((key) => right.includes(key));
|
|
12
|
+
const hasRefreshedFocus = (tracking, descriptors) => {
|
|
13
|
+
const { focusedKey } = tracking;
|
|
14
|
+
if (focusedKey === undefined) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const next = descriptors[focusedKey];
|
|
18
|
+
return next !== undefined && tracking.descriptors[focusedKey]?.route !== next.route;
|
|
19
|
+
};
|
|
20
|
+
const appendOrder = (previous, needed) => [
|
|
21
|
+
...previous.filter((key) => needed.includes(key)),
|
|
22
|
+
...needed.filter((key) => !previous.includes(key)),
|
|
23
|
+
];
|
|
24
|
+
const withoutKeys = (map, keys) => Object.fromEntries(Object.entries(map).filter(([key]) => !keys.includes(key)));
|
|
25
|
+
const nextClosing = (tracking, state, offset) => {
|
|
26
|
+
const mounted = mountedKeys(state, offset);
|
|
27
|
+
const kept = withoutKeys(tracking.closing, mounted);
|
|
28
|
+
const { focusedKey } = tracking;
|
|
29
|
+
if (focusedKey === undefined || mounted.includes(focusedKey)) {
|
|
30
|
+
return kept;
|
|
31
|
+
}
|
|
32
|
+
const descriptor = tracking.descriptors[focusedKey];
|
|
33
|
+
return descriptor === undefined ? kept : { ...kept, [focusedKey]: descriptor };
|
|
34
|
+
};
|
|
35
|
+
const advance = (tracking, state, descriptors, offset) => {
|
|
36
|
+
const closing = nextClosing(tracking, state, offset);
|
|
37
|
+
return {
|
|
38
|
+
order: appendOrder(tracking.order, neededKeys(state, closing, offset)),
|
|
39
|
+
focusedKey: getFocusedKey(state, offset),
|
|
40
|
+
descriptors,
|
|
41
|
+
closing,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const initialTracking = (state, descriptors, offset) => ({
|
|
45
|
+
order: neededKeys(state, {}, offset),
|
|
46
|
+
focusedKey: getFocusedKey(state, offset),
|
|
47
|
+
descriptors,
|
|
48
|
+
closing: {},
|
|
49
|
+
});
|
|
50
|
+
const resolvePage = (key, sources, describe) => {
|
|
51
|
+
const preloaded = sources.state.preloadedRoutes.find((route) => route.key === key);
|
|
52
|
+
if (preloaded !== undefined) {
|
|
53
|
+
return describe(preloaded, true);
|
|
54
|
+
}
|
|
55
|
+
return sources.descriptors[key] ?? sources.closing[key];
|
|
56
|
+
};
|
|
57
|
+
const useStackPages = (state, descriptors, describe, offset) => {
|
|
58
|
+
const [tracking, setTracking] = useState(() => initialTracking(state, descriptors, offset));
|
|
59
|
+
if (!hasSameMembers(tracking.order, neededKeys(state, tracking.closing, offset)) ||
|
|
60
|
+
tracking.focusedKey !== getFocusedKey(state, offset) ||
|
|
61
|
+
hasRefreshedFocus(tracking, descriptors)) {
|
|
62
|
+
setTracking(advance(tracking, state, descriptors, offset));
|
|
63
|
+
}
|
|
64
|
+
const release = useCallback((key) => {
|
|
65
|
+
setTracking((current) => (current.closing[key] === undefined
|
|
66
|
+
? current
|
|
67
|
+
: {
|
|
68
|
+
...current,
|
|
69
|
+
order: current.order.filter((entry) => entry !== key),
|
|
70
|
+
closing: withoutKeys(current.closing, [key]),
|
|
71
|
+
}));
|
|
72
|
+
}, []);
|
|
73
|
+
const sources = { state, descriptors, closing: tracking.closing };
|
|
74
|
+
const pages = tracking.order
|
|
75
|
+
.map((key) => resolvePage(key, sources, describe))
|
|
76
|
+
.filter((page) => page !== undefined);
|
|
77
|
+
return { pages, release };
|
|
78
|
+
};
|
|
79
|
+
export { useStackPages };
|
|
80
|
+
//# sourceMappingURL=stack-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-pages.js","sourceRoot":"","sources":["../../src/stack/stack-pages.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ParamListBase, RouteProp, StackNavigationState } from \"@react-navigation/core\";\nimport { useCallback, useState } from \"react\";\nimport type { StackDescriptor, StackDescriptorMap } from \"./types.js\";\n\ntype StackState = StackNavigationState<ParamListBase>;\ntype Describe = (route: RouteProp<ParamListBase>, isPlaceholder: boolean) => StackDescriptor;\n\ntype PageTracking = {\n order: readonly string[];\n focusedKey: string | undefined;\n descriptors: StackDescriptorMap;\n closing: StackDescriptorMap;\n};\n\ntype StackPages = {\n pages: readonly StackDescriptor[];\n release: (key: string) => void;\n};\n\nconst getFocusedKey = (state: StackState, offset: number): string | undefined =>\n state.index < offset ? undefined : state.routes[state.index]?.key;\n\nconst mountedKeys = (state: StackState, offset: number): string[] => [\n ...state.routes.slice(offset).map((route) => route.key),\n ...state.preloadedRoutes.map((route) => route.key),\n];\n\nconst neededKeys = (state: StackState, closing: StackDescriptorMap, offset: number): string[] => [\n ...mountedKeys(state, offset),\n ...Object.keys(closing),\n];\n\nconst hasSameMembers = (left: readonly string[], right: readonly string[]): boolean =>\n left.length === right.length && left.every((key) => right.includes(key));\n\nconst hasRefreshedFocus = (tracking: PageTracking, descriptors: StackDescriptorMap): boolean => {\n const { focusedKey } = tracking;\n\n if (focusedKey === undefined) {\n return false;\n }\n\n const next = descriptors[focusedKey];\n\n return next !== undefined && tracking.descriptors[focusedKey]?.route !== next.route;\n};\n\nconst appendOrder = (previous: readonly string[], needed: readonly string[]): string[] => [\n ...previous.filter((key) => needed.includes(key)),\n ...needed.filter((key) => !previous.includes(key)),\n];\n\nconst withoutKeys = (map: StackDescriptorMap, keys: readonly string[]): StackDescriptorMap =>\n Object.fromEntries(Object.entries(map).filter(([key]) => !keys.includes(key)));\n\nconst nextClosing = (tracking: PageTracking, state: StackState, offset: number): StackDescriptorMap => {\n const mounted = mountedKeys(state, offset);\n const kept = withoutKeys(tracking.closing, mounted);\n const { focusedKey } = tracking;\n\n if (focusedKey === undefined || mounted.includes(focusedKey)) {\n return kept;\n }\n\n const descriptor = tracking.descriptors[focusedKey];\n\n return descriptor === undefined ? kept : { ...kept, [focusedKey]: descriptor };\n};\n\nconst advance = (\n tracking: PageTracking,\n state: StackState,\n descriptors: StackDescriptorMap,\n offset: number,\n): PageTracking => {\n const closing = nextClosing(tracking, state, offset);\n\n return {\n order: appendOrder(tracking.order, neededKeys(state, closing, offset)),\n focusedKey: getFocusedKey(state, offset),\n descriptors,\n closing,\n };\n};\n\nconst initialTracking = (state: StackState, descriptors: StackDescriptorMap, offset: number): PageTracking => ({\n order: neededKeys(state, {}, offset),\n focusedKey: getFocusedKey(state, offset),\n descriptors,\n closing: {},\n});\n\nconst resolvePage = (\n key: string,\n sources: { state: StackState; descriptors: StackDescriptorMap; closing: StackDescriptorMap },\n describe: Describe,\n): StackDescriptor | undefined => {\n const preloaded = sources.state.preloadedRoutes.find((route) => route.key === key);\n\n if (preloaded !== undefined) {\n return describe(preloaded, true);\n }\n\n return sources.descriptors[key] ?? sources.closing[key];\n};\n\nconst useStackPages = (\n state: StackState,\n descriptors: StackDescriptorMap,\n describe: Describe,\n offset: number,\n): StackPages => {\n const [tracking, setTracking] = useState<PageTracking>(() => initialTracking(state, descriptors, offset));\n\n if (!hasSameMembers(tracking.order, neededKeys(state, tracking.closing, offset)) ||\n tracking.focusedKey !== getFocusedKey(state, offset) ||\n hasRefreshedFocus(tracking, descriptors)) {\n setTracking(advance(tracking, state, descriptors, offset));\n }\n\n const release = useCallback((key: string) => {\n setTracking((current) => (current.closing[key] === undefined\n ? current\n : {\n ...current,\n order: current.order.filter((entry) => entry !== key),\n closing: withoutKeys(current.closing, [key]),\n }));\n }, []);\n\n const sources = { state, descriptors, closing: tracking.closing };\n\n const pages = tracking.order\n .map((key) => resolvePage(key, sources, describe))\n .filter((page) => page !== undefined);\n\n return { pages, release };\n};\n\nexport { type Describe, useStackPages };\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ParamListBase, StackNavigationState } from "@react-navigation/core";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type { Describe } from "./stack-pages.js";
|
|
4
|
+
import type { StackDescriptorMap, StackNavigationConfig, StackNavigationHelpers } from "./types.js";
|
|
5
|
+
type StackViewProps = StackNavigationConfig & {
|
|
6
|
+
state: StackNavigationState<ParamListBase>;
|
|
7
|
+
navigation: StackNavigationHelpers;
|
|
8
|
+
descriptors: StackDescriptorMap;
|
|
9
|
+
describe: Describe;
|
|
10
|
+
offset?: number;
|
|
11
|
+
};
|
|
12
|
+
declare const StackView: (props: StackViewProps) => ReactNode;
|
|
13
|
+
export { StackView };
|
|
14
|
+
//# sourceMappingURL=stack-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-view.d.ts","sourceRoot":"","sources":["../../src/stack/stack-view.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,OAAO,CAAC;AAGlD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAER,kBAAkB,EAClB,qBAAqB,EAErB,sBAAsB,EAEzB,MAAM,YAAY,CAAC;AAQpB,KAAK,cAAc,GAAG,qBAAqB,GAAG;IAC1C,KAAK,EAAE,oBAAoB,CAAC,aAAa,CAAC,CAAC;IAC3C,UAAU,EAAE,sBAAsB,CAAC;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAsJF,QAAA,MAAM,SAAS,GAAI,OAAO,cAAc,KAAG,SAqB1C,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { AdwNavigationPage, AdwNavigationView, AdwToolbarView } from "@gtkx/jsx/adw";
|
|
3
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
4
|
+
import { HeaderBar } from "../shared/header-bar.js";
|
|
5
|
+
import { useStackPages } from "./stack-pages.js";
|
|
6
|
+
import { reconcilePoppedStack, syncNavigationStack } from "./sync-navigation-stack.js";
|
|
7
|
+
const previousDescriptor = (state, descriptors, key, offset) => {
|
|
8
|
+
const index = state.routes.findIndex((route) => route.key === key);
|
|
9
|
+
const previousKey = index > offset ? state.routes[index - 1]?.key : undefined;
|
|
10
|
+
return previousKey === undefined ? undefined : descriptors[previousKey];
|
|
11
|
+
};
|
|
12
|
+
const useLatest = (value) => {
|
|
13
|
+
const ref = useRef(value);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
ref.current = value;
|
|
16
|
+
}, [value]);
|
|
17
|
+
return ref;
|
|
18
|
+
};
|
|
19
|
+
const useTrackedOptions = (descriptors) => {
|
|
20
|
+
const optionsRef = useRef({});
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
for (const [key, descriptor] of Object.entries(descriptors)) {
|
|
23
|
+
optionsRef.current[key] = descriptor.options;
|
|
24
|
+
}
|
|
25
|
+
}, [descriptors]);
|
|
26
|
+
return optionsRef;
|
|
27
|
+
};
|
|
28
|
+
const useStackSync = (viewRef, state, options, offset) => {
|
|
29
|
+
const isInitialRef = useRef(true);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const view = viewRef.current;
|
|
32
|
+
if (view === null) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const desired = state.routes.slice(offset).map((route) => route.key);
|
|
36
|
+
syncNavigationStack(view, desired, options.current, isInitialRef.current);
|
|
37
|
+
isInitialRef.current = false;
|
|
38
|
+
}, [viewRef, state, options, offset]);
|
|
39
|
+
};
|
|
40
|
+
const usePoppedHandler = (viewRef, navigation, options, offset) => {
|
|
41
|
+
const navigationRef = useLatest(navigation);
|
|
42
|
+
const isScheduledRef = useRef(false);
|
|
43
|
+
return useCallback(() => {
|
|
44
|
+
if (isScheduledRef.current) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
isScheduledRef.current = true;
|
|
48
|
+
queueMicrotask(() => {
|
|
49
|
+
isScheduledRef.current = false;
|
|
50
|
+
const view = viewRef.current;
|
|
51
|
+
if (view !== null) {
|
|
52
|
+
reconcilePoppedStack(view, navigationRef.current, options.current, offset);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}, [viewRef, navigationRef, options, offset]);
|
|
56
|
+
};
|
|
57
|
+
const StackPageContent = ({ descriptor, previous }) => {
|
|
58
|
+
const { route, options, navigation } = descriptor;
|
|
59
|
+
if (options.headerShown === false) {
|
|
60
|
+
return descriptor.render();
|
|
61
|
+
}
|
|
62
|
+
const back = previous === undefined ? undefined : { title: previous.options.title ?? previous.route.name };
|
|
63
|
+
const topBar = options.header === undefined
|
|
64
|
+
? _jsx(HeaderBar, { options: options, showBackButton: options.headerBackVisible ?? true })
|
|
65
|
+
: _jsx(_Fragment, { children: options.header({ route, navigation, options, back }) });
|
|
66
|
+
return _jsx(AdwToolbarView, { topBar: topBar, children: descriptor.render() });
|
|
67
|
+
};
|
|
68
|
+
const StackPage = ({ descriptor, previous, navigation, onHidden }) => {
|
|
69
|
+
const { route, options } = descriptor;
|
|
70
|
+
const pageRef = useRef(null);
|
|
71
|
+
const emit = (type, isClosing) => {
|
|
72
|
+
navigation.emit({ type, data: { closing: isClosing }, target: route.key });
|
|
73
|
+
};
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
const page = pageRef.current;
|
|
76
|
+
if (page !== null && !page.getMapped()) {
|
|
77
|
+
onHidden(route.key);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return (_jsx(AdwNavigationPage, { ref: pageRef, tag: route.key, title: options.title ?? route.name, canPop: options.canPop ?? true, onShowing: () => {
|
|
81
|
+
emit("transitionStart", false);
|
|
82
|
+
}, onHiding: () => {
|
|
83
|
+
emit("transitionStart", true);
|
|
84
|
+
}, onShown: () => {
|
|
85
|
+
emit("transitionEnd", false);
|
|
86
|
+
}, onHidden: () => {
|
|
87
|
+
emit("transitionEnd", true);
|
|
88
|
+
onHidden(route.key);
|
|
89
|
+
}, children: _jsx(StackPageContent, { descriptor: descriptor, previous: previous }) }));
|
|
90
|
+
};
|
|
91
|
+
const StackView = (props) => {
|
|
92
|
+
const { state, navigation, descriptors, describe, popOnEscape, offset = 0 } = props;
|
|
93
|
+
const viewRef = useRef(null);
|
|
94
|
+
const options = useTrackedOptions(descriptors);
|
|
95
|
+
const { pages, release } = useStackPages(state, descriptors, describe, offset);
|
|
96
|
+
const onPopped = usePoppedHandler(viewRef, navigation, options, offset);
|
|
97
|
+
useStackSync(viewRef, state, options, offset);
|
|
98
|
+
return (_jsx(AdwNavigationView, { ref: viewRef, popOnEscape: popOnEscape ?? true, onPopped: onPopped, children: pages.map((descriptor) => (_jsx(StackPage, { descriptor: descriptor, previous: previousDescriptor(state, descriptors, descriptor.route.key, offset), navigation: navigation, onHidden: release }, descriptor.route.key))) }));
|
|
99
|
+
};
|
|
100
|
+
export { StackView };
|
|
101
|
+
//# sourceMappingURL=stack-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-view.js","sourceRoot":"","sources":["../../src/stack/stack-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import type * as Adw from \"@gtkx/gi/adw\";\nimport type { ParamListBase, StackNavigationState } from \"@react-navigation/core\";\nimport type { ReactNode, RefObject } from \"react\";\nimport { AdwNavigationPage, AdwNavigationView, AdwToolbarView } from \"@gtkx/jsx/adw\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport type { Describe } from \"./stack-pages.js\";\nimport type { OptionsByKey } from \"./sync-navigation-stack.js\";\nimport type {\n StackDescriptor,\n StackDescriptorMap,\n StackNavigationConfig,\n StackNavigationEventMap,\n StackNavigationHelpers,\n StackNavigationOptions,\n} from \"./types.js\";\nimport { HeaderBar } from \"../shared/header-bar.js\";\nimport { useStackPages } from \"./stack-pages.js\";\nimport { reconcilePoppedStack, syncNavigationStack } from \"./sync-navigation-stack.js\";\n\ntype ViewRef = RefObject<Adw.NavigationView | null>;\ntype MutableOptions = Record<string, StackNavigationOptions>;\n\ntype StackViewProps = StackNavigationConfig & {\n state: StackNavigationState<ParamListBase>;\n navigation: StackNavigationHelpers;\n descriptors: StackDescriptorMap;\n describe: Describe;\n offset?: number;\n};\n\ntype StackPageProps = {\n descriptor: StackDescriptor;\n previous?: StackDescriptor;\n navigation: StackNavigationHelpers;\n onHidden: (key: string) => void;\n};\n\ntype TransitionEvent = keyof StackNavigationEventMap;\n\nconst previousDescriptor = (\n state: StackNavigationState<ParamListBase>,\n descriptors: StackDescriptorMap,\n key: string,\n offset: number,\n): StackDescriptor | undefined => {\n const index = state.routes.findIndex((route) => route.key === key);\n const previousKey = index > offset ? state.routes[index - 1]?.key : undefined;\n\n return previousKey === undefined ? undefined : descriptors[previousKey];\n};\n\nconst useLatest = <T,>(value: T): RefObject<T> => {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n};\n\nconst useTrackedOptions = (descriptors: StackDescriptorMap): RefObject<MutableOptions> => {\n const optionsRef = useRef<MutableOptions>({});\n\n useEffect(() => {\n for (const [key, descriptor] of Object.entries(descriptors)) {\n optionsRef.current[key] = descriptor.options;\n }\n }, [descriptors]);\n\n return optionsRef;\n};\n\nconst useStackSync = (\n viewRef: ViewRef,\n state: StackNavigationState<ParamListBase>,\n options: RefObject<OptionsByKey>,\n offset: number,\n): void => {\n const isInitialRef = useRef(true);\n\n useEffect(() => {\n const view = viewRef.current;\n\n if (view === null) {\n return;\n }\n\n const desired = state.routes.slice(offset).map((route) => route.key);\n syncNavigationStack(view, desired, options.current, isInitialRef.current);\n isInitialRef.current = false;\n }, [viewRef, state, options, offset]);\n};\n\nconst usePoppedHandler = (\n viewRef: ViewRef,\n navigation: StackNavigationHelpers,\n options: RefObject<OptionsByKey>,\n offset: number,\n): (() => void) => {\n const navigationRef = useLatest(navigation);\n const isScheduledRef = useRef(false);\n\n return useCallback(() => {\n if (isScheduledRef.current) {\n return;\n }\n\n isScheduledRef.current = true;\n\n queueMicrotask(() => {\n isScheduledRef.current = false;\n const view = viewRef.current;\n\n if (view !== null) {\n reconcilePoppedStack(view, navigationRef.current, options.current, offset);\n }\n });\n }, [viewRef, navigationRef, options, offset]);\n};\n\nconst StackPageContent = ({ descriptor, previous }: Omit<StackPageProps, \"navigation\" | \"onHidden\">): ReactNode => {\n const { route, options, navigation } = descriptor;\n\n if (options.headerShown === false) {\n return descriptor.render();\n }\n\n const back = previous === undefined ? undefined : { title: previous.options.title ?? previous.route.name };\n\n const topBar = options.header === undefined\n ? <HeaderBar options={options} showBackButton={options.headerBackVisible ?? true} />\n : <>{options.header({ route, navigation, options, back })}</>;\n\n return <AdwToolbarView topBar={topBar}>{descriptor.render()}</AdwToolbarView>;\n};\n\nconst StackPage = ({ descriptor, previous, navigation, onHidden }: StackPageProps): ReactNode => {\n const { route, options } = descriptor;\n const pageRef = useRef<Adw.NavigationPage | null>(null);\n\n const emit = (type: TransitionEvent, isClosing: boolean): void => {\n navigation.emit({ type, data: { closing: isClosing }, target: route.key });\n };\n\n useEffect(() => {\n const page = pageRef.current;\n\n if (page !== null && !page.getMapped()) {\n onHidden(route.key);\n }\n });\n\n return (\n <AdwNavigationPage\n ref={pageRef}\n tag={route.key}\n title={options.title ?? route.name}\n canPop={options.canPop ?? true}\n onShowing={() => {\n emit(\"transitionStart\", false);\n }}\n onHiding={() => {\n emit(\"transitionStart\", true);\n }}\n onShown={() => {\n emit(\"transitionEnd\", false);\n }}\n onHidden={() => {\n emit(\"transitionEnd\", true);\n onHidden(route.key);\n }}\n >\n <StackPageContent descriptor={descriptor} previous={previous} />\n </AdwNavigationPage>\n );\n};\n\nconst StackView = (props: StackViewProps): ReactNode => {\n const { state, navigation, descriptors, describe, popOnEscape, offset = 0 } = props;\n const viewRef = useRef<Adw.NavigationView | null>(null);\n const options = useTrackedOptions(descriptors);\n const { pages, release } = useStackPages(state, descriptors, describe, offset);\n const onPopped = usePoppedHandler(viewRef, navigation, options, offset);\n useStackSync(viewRef, state, options, offset);\n\n return (\n <AdwNavigationView ref={viewRef} popOnEscape={popOnEscape ?? true} onPopped={onPopped}>\n {pages.map((descriptor) => (\n <StackPage\n key={descriptor.route.key}\n descriptor={descriptor}\n previous={previousDescriptor(state, descriptors, descriptor.route.key, offset)}\n navigation={navigation}\n onHidden={release}\n />\n ))}\n </AdwNavigationView>\n );\n};\n\nexport { StackView };\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as Adw from "@gtkx/gi/adw";
|
|
2
|
+
import type { StackNavigationHelpers, StackNavigationOptions } from "./types.js";
|
|
3
|
+
type OptionsByKey = Readonly<Record<string, StackNavigationOptions | undefined>>;
|
|
4
|
+
declare const syncNavigationStack: (view: Adw.NavigationView, desired: readonly string[], options: OptionsByKey, isInitial: boolean) => void;
|
|
5
|
+
declare const reconcilePoppedStack: (view: Adw.NavigationView, navigation: StackNavigationHelpers, options: OptionsByKey, offset: number) => void;
|
|
6
|
+
export { type OptionsByKey, reconcilePoppedStack, syncNavigationStack };
|
|
7
|
+
//# sourceMappingURL=sync-navigation-stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-navigation-stack.d.ts","sourceRoot":"","sources":["../../src/stack/sync-navigation-stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEjF,KAAK,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,GAAG,SAAS,CAAC,CAAC,CAAC;AAiEjF,QAAA,MAAM,mBAAmB,GACrB,MAAM,GAAG,CAAC,cAAc,EACxB,SAAS,SAAS,MAAM,EAAE,EAC1B,SAAS,YAAY,EACrB,WAAW,OAAO,KACnB,IAYF,CAAC;AAcF,QAAA,MAAM,oBAAoB,GACtB,MAAM,GAAG,CAAC,cAAc,EACxB,YAAY,sBAAsB,EAClC,SAAS,YAAY,EACrB,QAAQ,MAAM,KACf,IASF,CAAC;AAEF,OAAO,EAAE,KAAK,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as Adw from "@gtkx/gi/adw";
|
|
2
|
+
import { StackActions } from "@react-navigation/core";
|
|
3
|
+
const readNavigationStack = (view) => {
|
|
4
|
+
const model = view.getNavigationStack();
|
|
5
|
+
const count = model.getNItems();
|
|
6
|
+
const tags = [];
|
|
7
|
+
for (let index = 0; index < count; index += 1) {
|
|
8
|
+
const page = model.getItem(index);
|
|
9
|
+
const tag = page instanceof Adw.NavigationPage ? page.getTag() : null;
|
|
10
|
+
if (tag !== null) {
|
|
11
|
+
tags.push(tag);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return tags;
|
|
15
|
+
};
|
|
16
|
+
const isSameStack = (left, right) => left.length === right.length && left.every((tag, index) => right[index] === tag);
|
|
17
|
+
const isStrictPrefix = (prefix, list) => prefix.length < list.length && prefix.every((tag, index) => list[index] === tag);
|
|
18
|
+
const isAnimated = (options, key) => key === undefined || options[key]?.animation !== "none";
|
|
19
|
+
const pushOnto = (view, current, desired, options) => {
|
|
20
|
+
const base = desired.slice(0, -1);
|
|
21
|
+
const last = desired.at(-1);
|
|
22
|
+
if (!isSameStack(base, current)) {
|
|
23
|
+
view.replaceWithTags(base);
|
|
24
|
+
}
|
|
25
|
+
if (last !== undefined) {
|
|
26
|
+
view.setAnimateTransitions(isAnimated(options, last));
|
|
27
|
+
view.pushByTag(last);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const applyStackChange = (view, current, desired, options) => {
|
|
31
|
+
const last = desired.at(-1);
|
|
32
|
+
if (last !== undefined && isStrictPrefix(desired, current)) {
|
|
33
|
+
view.setAnimateTransitions(isAnimated(options, current.at(-1)));
|
|
34
|
+
view.popToTag(last);
|
|
35
|
+
}
|
|
36
|
+
else if (isStrictPrefix(current, desired)) {
|
|
37
|
+
pushOnto(view, current, desired, options);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
view.replaceWithTags([...desired]);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const syncNavigationStack = (view, desired, options, isInitial) => {
|
|
44
|
+
const current = readNavigationStack(view);
|
|
45
|
+
if (!isSameStack(current, desired)) {
|
|
46
|
+
if (isInitial) {
|
|
47
|
+
view.replaceWithTags([...desired]);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
applyStackChange(view, current, desired, options);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
view.setAnimateTransitions(isAnimated(options, desired.at(-1)));
|
|
54
|
+
};
|
|
55
|
+
const routeKeys = (state, offset) => state.routes.slice(offset).map((route) => route.key);
|
|
56
|
+
const popToActualStack = (navigation, actual, desired) => {
|
|
57
|
+
const state = navigation.getState();
|
|
58
|
+
navigation.dispatch({ ...StackActions.pop(desired.length - actual.length), target: state.key });
|
|
59
|
+
};
|
|
60
|
+
const reconcilePoppedStack = (view, navigation, options, offset) => {
|
|
61
|
+
const actual = readNavigationStack(view);
|
|
62
|
+
const desired = routeKeys(navigation.getState(), offset);
|
|
63
|
+
if (isStrictPrefix(actual, desired)) {
|
|
64
|
+
popToActualStack(navigation, actual, desired);
|
|
65
|
+
}
|
|
66
|
+
syncNavigationStack(view, routeKeys(navigation.getState(), offset), options, false);
|
|
67
|
+
};
|
|
68
|
+
export { reconcilePoppedStack, syncNavigationStack };
|
|
69
|
+
//# sourceMappingURL=sync-navigation-stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-navigation-stack.js","sourceRoot":"","sources":["../../src/stack/sync-navigation-stack.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Adw from \"@gtkx/gi/adw\";\nimport { StackActions } from \"@react-navigation/core\";\nimport type { StackNavigationHelpers, StackNavigationOptions } from \"./types.js\";\n\ntype OptionsByKey = Readonly<Record<string, StackNavigationOptions | undefined>>;\n\nconst readNavigationStack = (view: Adw.NavigationView): string[] => {\n const model = view.getNavigationStack();\n const count = model.getNItems();\n const tags: string[] = [];\n\n for (let index = 0; index < count; index += 1) {\n const page = model.getItem(index);\n const tag = page instanceof Adw.NavigationPage ? page.getTag() : null;\n\n if (tag !== null) {\n tags.push(tag);\n }\n }\n\n return tags;\n};\n\nconst isSameStack = (left: readonly string[], right: readonly string[]): boolean =>\n left.length === right.length && left.every((tag, index) => right[index] === tag);\n\nconst isStrictPrefix = (prefix: readonly string[], list: readonly string[]): boolean =>\n prefix.length < list.length && prefix.every((tag, index) => list[index] === tag);\n\nconst isAnimated = (options: OptionsByKey, key: string | undefined): boolean =>\n key === undefined || options[key]?.animation !== \"none\";\n\nconst pushOnto = (\n view: Adw.NavigationView,\n current: readonly string[],\n desired: readonly string[],\n options: OptionsByKey,\n): void => {\n const base = desired.slice(0, -1);\n const last = desired.at(-1);\n\n if (!isSameStack(base, current)) {\n view.replaceWithTags(base);\n }\n\n if (last !== undefined) {\n view.setAnimateTransitions(isAnimated(options, last));\n view.pushByTag(last);\n }\n};\n\nconst applyStackChange = (\n view: Adw.NavigationView,\n current: readonly string[],\n desired: readonly string[],\n options: OptionsByKey,\n): void => {\n const last = desired.at(-1);\n\n if (last !== undefined && isStrictPrefix(desired, current)) {\n view.setAnimateTransitions(isAnimated(options, current.at(-1)));\n view.popToTag(last);\n } else if (isStrictPrefix(current, desired)) {\n pushOnto(view, current, desired, options);\n } else {\n view.replaceWithTags([...desired]);\n }\n};\n\nconst syncNavigationStack = (\n view: Adw.NavigationView,\n desired: readonly string[],\n options: OptionsByKey,\n isInitial: boolean,\n): void => {\n const current = readNavigationStack(view);\n\n if (!isSameStack(current, desired)) {\n if (isInitial) {\n view.replaceWithTags([...desired]);\n } else {\n applyStackChange(view, current, desired, options);\n }\n }\n\n view.setAnimateTransitions(isAnimated(options, desired.at(-1)));\n};\n\nconst routeKeys = (state: { routes: readonly { key: string }[] }, offset: number): string[] =>\n state.routes.slice(offset).map((route) => route.key);\n\nconst popToActualStack = (\n navigation: StackNavigationHelpers,\n actual: readonly string[],\n desired: readonly string[],\n): void => {\n const state = navigation.getState();\n navigation.dispatch({ ...StackActions.pop(desired.length - actual.length), target: state.key });\n};\n\nconst reconcilePoppedStack = (\n view: Adw.NavigationView,\n navigation: StackNavigationHelpers,\n options: OptionsByKey,\n offset: number,\n): void => {\n const actual = readNavigationStack(view);\n const desired = routeKeys(navigation.getState(), offset);\n\n if (isStrictPrefix(actual, desired)) {\n popToActualStack(navigation, actual, desired);\n }\n\n syncNavigationStack(view, routeKeys(navigation.getState(), offset), options, false);\n};\n\nexport { type OptionsByKey, reconcilePoppedStack, syncNavigationStack };\n"]}
|