@symbiote-native/navigation 2.1.0 → 2.2.0
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 +42 -12
- package/build/angular/drawer/index.js +23 -9
- package/build/angular/index.d.ts +4 -4
- package/build/angular/injectors/inject-navigation.js +1 -1
- package/build/angular/navigation-scope.directive.js +1 -1
- package/build/angular/search-bar-ref.directive.js +1 -1
- package/build/angular/stack/index.js +20 -6
- package/build/angular/tabs/index.js +21 -7
- package/build/core/drawer-options/index.js +19 -5
- package/build/core/drawer-router-state/index.js +8 -2
- package/build/core/guards.js +3 -1
- package/build/core/header-bar-buttons.js +14 -4
- package/build/core/index.d.ts +4 -4
- package/build/core/index.js +2 -2
- package/build/core/navigator-state/index.js +12 -4
- package/build/core/render-drawer.js +4 -1
- package/build/core/render-stack.js +13 -4
- package/build/core/screen-options.js +1 -1
- package/build/core/search-bar-commands.js +1 -1
- package/build/core/state-persistence/index.js +6 -2
- package/build/core/tab-router-state/index.js +8 -2
- package/build/react/drawer/index.js +36 -13
- package/build/react/index.d.ts +7 -7
- package/build/react/index.js +2 -2
- package/build/react/stack/index.js +34 -8
- package/build/react/tabs/index.js +14 -4
- package/build/solid/drawer/index.d.ts +22 -0
- package/build/solid/drawer/index.js +394 -0
- package/build/solid/drawer-screen-props.d.ts +13 -0
- package/build/solid/drawer-screen-props.js +2 -0
- package/build/solid/host.d.ts +2 -0
- package/build/solid/host.js +23 -0
- package/build/solid/index.d.ts +19 -0
- package/build/solid/index.js +24 -0
- package/build/solid/linking.d.ts +3 -0
- package/build/solid/linking.js +55 -0
- package/build/solid/navigation-context.d.ts +13 -0
- package/build/solid/navigation-context.js +37 -0
- package/build/solid/primitives/create-focus-effect.d.ts +1 -0
- package/build/solid/primitives/create-focus-effect.js +30 -0
- package/build/solid/primitives/create-is-focused.d.ts +2 -0
- package/build/solid/primitives/create-is-focused.js +31 -0
- package/build/solid/primitives/create-navigation-state.d.ts +3 -0
- package/build/solid/primitives/create-navigation-state.js +30 -0
- package/build/solid/primitives/index.d.ts +12 -0
- package/build/solid/primitives/index.js +8 -0
- package/build/solid/primitives/use-drawer-navigation.d.ts +5 -0
- package/build/solid/primitives/use-drawer-navigation.js +15 -0
- package/build/solid/primitives/use-navigation.d.ts +8 -0
- package/build/solid/primitives/use-navigation.js +23 -0
- package/build/solid/primitives/use-route.d.ts +3 -0
- package/build/solid/primitives/use-route.js +14 -0
- package/build/solid/primitives/use-stack-navigation.d.ts +5 -0
- package/build/solid/primitives/use-stack-navigation.js +19 -0
- package/build/solid/primitives/use-tab-navigation.d.ts +5 -0
- package/build/solid/primitives/use-tab-navigation.js +15 -0
- package/build/solid/screen-props.d.ts +19 -0
- package/build/solid/screen-props.js +9 -0
- package/build/solid/screen-registry.d.ts +31 -0
- package/build/solid/screen-registry.js +86 -0
- package/build/solid/screen.d.ts +6 -0
- package/build/solid/screen.js +69 -0
- package/build/solid/stack/index.d.ts +15 -0
- package/build/solid/stack/index.js +348 -0
- package/build/solid/tab-screen-props.d.ts +13 -0
- package/build/solid/tab-screen-props.js +3 -0
- package/build/solid/tabs/index.d.ts +14 -0
- package/build/solid/tabs/index.js +228 -0
- package/build/svelte/descriptor-subtree.js +3 -1
- package/build/svelte/drawer/index.svelte +163 -25
- package/build/svelte/drawer-screen.svelte +2 -1
- package/build/svelte/index.d.ts +3 -3
- package/build/svelte/navigation-scope.svelte +4 -1
- package/build/svelte/runes/use-navigation.svelte.js +5 -1
- package/build/svelte/stack/index.svelte +43 -6
- package/build/svelte/stack/stack-screen.svelte +66 -9
- package/build/svelte/tabs/index.svelte +42 -20
- package/build/vue/composables/use-navigation.js +5 -1
- package/build/vue/drawer/index.js +30 -8
- package/build/vue/index.d.ts +3 -3
- package/build/vue/navigation-context.js +1 -1
- package/build/vue/stack/index.js +17 -6
- package/build/vue/tabs/index.js +18 -5
- package/build-ngc/angular/drawer/index.js +31 -11
- package/build-ngc/angular/drawer/index.js.map +1 -1
- package/build-ngc/angular/index.d.ts +4 -4
- package/build-ngc/angular/index.js.map +1 -1
- package/build-ngc/angular/injectors/inject-focus-effect.js.map +1 -1
- package/build-ngc/angular/injectors/inject-is-focused.js.map +1 -1
- package/build-ngc/angular/injectors/inject-navigation-state.js.map +1 -1
- package/build-ngc/angular/injectors/inject-navigation.js +1 -1
- package/build-ngc/angular/injectors/inject-navigation.js.map +1 -1
- package/build-ngc/angular/linking.js.map +1 -1
- package/build-ngc/angular/navigation-context.service.js.map +1 -1
- package/build-ngc/angular/navigation-scope.directive.js +1 -1
- package/build-ngc/angular/navigation-scope.directive.js.map +1 -1
- package/build-ngc/angular/screen.directive.js.map +1 -1
- package/build-ngc/angular/search-bar-ref.directive.js +1 -1
- package/build-ngc/angular/search-bar-ref.directive.js.map +1 -1
- package/build-ngc/angular/stack/index.js +26 -8
- package/build-ngc/angular/stack/index.js.map +1 -1
- package/build-ngc/angular/tab-screen.directive.js.map +1 -1
- package/build-ngc/angular/tabs/index.js +21 -7
- package/build-ngc/angular/tabs/index.js.map +1 -1
- package/build-ngc/core/constants.js.map +1 -1
- package/build-ngc/core/drawer-options/index.js +19 -5
- package/build-ngc/core/drawer-options/index.js.map +1 -1
- package/build-ngc/core/drawer-router-state/index.js +8 -2
- package/build-ngc/core/drawer-router-state/index.js.map +1 -1
- package/build-ngc/core/guards.js +3 -1
- package/build-ngc/core/guards.js.map +1 -1
- package/build-ngc/core/header-bar-buttons.js +14 -4
- package/build-ngc/core/header-bar-buttons.js.map +1 -1
- package/build-ngc/core/index.d.ts +4 -4
- package/build-ngc/core/index.js +2 -2
- package/build-ngc/core/index.js.map +1 -1
- package/build-ngc/core/linking-config/index.js.map +1 -1
- package/build-ngc/core/navigation-events/index.js.map +1 -1
- package/build-ngc/core/navigator-handles/index.js.map +1 -1
- package/build-ngc/core/navigator-state/index.js +12 -4
- package/build-ngc/core/navigator-state/index.js.map +1 -1
- package/build-ngc/core/render-drawer.js +4 -1
- package/build-ngc/core/render-drawer.js.map +1 -1
- package/build-ngc/core/render-stack.js +13 -4
- package/build-ngc/core/render-stack.js.map +1 -1
- package/build-ngc/core/render-tabs.js.map +1 -1
- package/build-ngc/core/screen-options.js +1 -1
- package/build-ngc/core/screen-options.js.map +1 -1
- package/build-ngc/core/search-bar-commands.js +1 -1
- package/build-ngc/core/search-bar-commands.js.map +1 -1
- package/build-ngc/core/stack-router-state/index.js.map +1 -1
- package/build-ngc/core/state-persistence/index.js +6 -2
- package/build-ngc/core/state-persistence/index.js.map +1 -1
- package/build-ngc/core/tab-router-state/index.js +8 -2
- package/build-ngc/core/tab-router-state/index.js.map +1 -1
- package/package.json +23 -9
- package/src/angular/drawer/index.ts +69 -25
- package/src/angular/index.ts +20 -4
- package/src/angular/injectors/inject-focus-effect.ts +8 -2
- package/src/angular/injectors/inject-is-focused.ts +6 -4
- package/src/angular/injectors/inject-navigation-state.ts +7 -4
- package/src/angular/injectors/inject-navigation.ts +12 -3
- package/src/angular/linking.ts +4 -1
- package/src/angular/navigation-context.service.ts +5 -2
- package/src/angular/navigation-scope.directive.ts +6 -2
- package/src/angular/screen.directive.ts +13 -3
- package/src/angular/search-bar-ref.directive.ts +10 -2
- package/src/angular/stack/index.ts +68 -22
- package/src/angular/tab-screen.directive.ts +3 -1
- package/src/angular/tabs/index.ts +36 -12
- package/src/core/constants.ts +6 -3
- package/src/core/drawer-options/index.ts +40 -13
- package/src/core/drawer-router-state/index.ts +11 -3
- package/src/core/guards.ts +3 -1
- package/src/core/header-bar-buttons.ts +41 -12
- package/src/core/index.ts +18 -4
- package/src/core/linking-config/index.ts +31 -10
- package/src/core/navigation-events/index.ts +8 -2
- package/src/core/navigator-handles/index.ts +8 -3
- package/src/core/navigator-props.ts +13 -4
- package/src/core/navigator-state/index.ts +24 -7
- package/src/core/render-drawer.ts +24 -9
- package/src/core/render-stack.ts +52 -13
- package/src/core/render-tabs.ts +24 -6
- package/src/core/screen-options.ts +15 -5
- package/src/core/search-bar-commands.ts +12 -3
- package/src/core/stack-router-state/index.ts +5 -2
- package/src/core/state-persistence/index.ts +13 -3
- package/src/core/tab-router-state/index.ts +10 -3
- package/src/react/drawer/index.ts +408 -344
- package/src/react/drawer-screen.ts +8 -2
- package/src/react/hooks/use-focus-effect.ts +8 -2
- package/src/react/hooks/use-is-focused.ts +6 -2
- package/src/react/hooks/use-navigation.ts +8 -2
- package/src/react/index.ts +37 -7
- package/src/react/linking.ts +4 -1
- package/src/react/navigation-context.ts +6 -2
- package/src/react/screen.ts +12 -3
- package/src/react/stack/index.ts +294 -231
- package/src/react/tab-screen.ts +3 -1
- package/src/react/tabs/index.ts +188 -158
- package/src/solid/drawer/index.ts +570 -0
- package/src/solid/drawer-screen-props.ts +24 -0
- package/src/solid/host.ts +29 -0
- package/src/solid/index.ts +87 -0
- package/src/solid/linking.ts +74 -0
- package/src/solid/navigation-context.ts +56 -0
- package/src/solid/primitives/create-focus-effect.ts +41 -0
- package/src/solid/primitives/create-is-focused.ts +41 -0
- package/src/solid/primitives/create-navigation-state.ts +44 -0
- package/src/solid/primitives/index.ts +12 -0
- package/src/solid/primitives/use-drawer-navigation.ts +25 -0
- package/src/solid/primitives/use-navigation.ts +44 -0
- package/src/solid/primitives/use-route.ts +18 -0
- package/src/solid/primitives/use-stack-navigation.ts +29 -0
- package/src/solid/primitives/use-tab-navigation.ts +25 -0
- package/src/solid/screen-props.ts +51 -0
- package/src/solid/screen-registry.ts +159 -0
- package/src/solid/screen.ts +80 -0
- package/src/solid/stack/index.ts +528 -0
- package/src/solid/tab-screen-props.ts +21 -0
- package/src/solid/tabs/index.ts +327 -0
- package/src/svelte/attachments.ts +3 -1
- package/src/svelte/descriptor-subtree.ts +3 -1
- package/src/svelte/drawer/index.svelte +163 -25
- package/src/svelte/drawer-screen-props.ts +8 -2
- package/src/svelte/drawer-screen.svelte +2 -1
- package/src/svelte/fabric-tree.test-helper.ts +37 -3
- package/src/svelte/index.ts +15 -3
- package/src/svelte/linking.svelte.ts +11 -5
- package/src/svelte/navigation-scope.svelte +4 -1
- package/src/svelte/runes/use-drawer-navigation.svelte.ts +3 -1
- package/src/svelte/runes/use-focus-effect.svelte.ts +8 -2
- package/src/svelte/runes/use-navigation-state.svelte.ts +3 -1
- package/src/svelte/runes/use-navigation.svelte.ts +13 -3
- package/src/svelte/runes/use-stack-navigation.svelte.ts +3 -1
- package/src/svelte/screen-props.ts +7 -2
- package/src/svelte/screen-registry.ts +9 -3
- package/src/svelte/stack/index.svelte +43 -6
- package/src/svelte/stack/stack-screen.svelte +66 -9
- package/src/svelte/svelte-compile.test-helper.ts +16 -12
- package/src/svelte/tab-screen-props.ts +3 -1
- package/src/svelte/tabs/index.svelte +42 -20
- package/src/vue/composables/use-navigation-state.ts +7 -4
- package/src/vue/composables/use-navigation.ts +13 -3
- package/src/vue/drawer/index.ts +122 -36
- package/src/vue/drawer-screen.ts +12 -5
- package/src/vue/index.ts +15 -3
- package/src/vue/linking.ts +7 -2
- package/src/vue/navigation-context.ts +17 -5
- package/src/vue/screen.ts +7 -2
- package/src/vue/stack/index.ts +82 -34
- package/src/vue/tab-screen.ts +3 -1
- package/src/vue/tabs/index.ts +51 -13
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import { el } from '@symbiote-native/components';
|
|
12
12
|
import { HEADER_ON_PRESS_BAR_BUTTON_ITEM, HEADER_ON_PRESS_BAR_BUTTON_MENU_ITEM, RNS_MODAL_SCREEN_VIEW_NAME, RNS_SCREEN_STACK_HEADER_CONFIG_VIEW_NAME, RNS_SCREEN_STACK_HEADER_SUBVIEW_VIEW_NAME, RNS_SCREEN_VIEW_NAME, RNS_SEARCH_BAR_VIEW_NAME, SEARCH_BAR_ON_BLUR, SEARCH_BAR_ON_CANCEL_BUTTON_PRESS, SEARCH_BAR_ON_CHANGE_TEXT, SEARCH_BAR_ON_CLOSE, SEARCH_BAR_ON_FOCUS, SEARCH_BAR_ON_OPEN, SEARCH_BAR_ON_SEARCH_BUTTON_PRESS, STACK_DEFAULT_ANIMATION, STACK_DEFAULT_PRESENTATION, } from './constants.js';
|
|
13
13
|
import { computeActivityState } from './navigator-state/index.js';
|
|
14
|
-
import { resolveHeaderConfigView, resolveScreenView, resolveSearchBarView } from './screen-options.js';
|
|
14
|
+
import { resolveHeaderConfigView, resolveScreenView, resolveSearchBarView, } from './screen-options.js';
|
|
15
15
|
// Mirrors react-native-screens' ScreenStackItem.tsx (getPositioningStyle): a formSheet's content
|
|
16
16
|
// wrapper does not get `flex: 1`. RNSScreen.mm's updateBounds pushes the sheet's live native size
|
|
17
17
|
// into Fabric's shadow state on every frame of a detent drag, and a `bottom: 0`-pinned wrapper
|
|
@@ -65,7 +65,9 @@ export function resolveScreenViewName(stackPresentation, isAndroid) {
|
|
|
65
65
|
stackPresentation === 'push' ||
|
|
66
66
|
stackPresentation === 'containedModal' ||
|
|
67
67
|
stackPresentation === 'containedTransparentModal';
|
|
68
|
-
return isPlainPresentation
|
|
68
|
+
return isPlainPresentation
|
|
69
|
+
? RNS_SCREEN_VIEW_NAME
|
|
70
|
+
: RNS_MODAL_SCREEN_VIEW_NAME;
|
|
69
71
|
}
|
|
70
72
|
export function resolveScreenContentWrapperStyle(stackPresentation, headerHidden, headerTranslucent, isAndroid) {
|
|
71
73
|
let baseStyles;
|
|
@@ -96,13 +98,20 @@ export function resolveScreenContentWrapperStyle(stackPresentation, headerHidden
|
|
|
96
98
|
export function isHeaderInModal(stackPresentation, headerHidden, isAndroid) {
|
|
97
99
|
if (isAndroid)
|
|
98
100
|
return false;
|
|
99
|
-
return (stackPresentation ?? STACK_DEFAULT_PRESENTATION) !== 'push' &&
|
|
101
|
+
return ((stackPresentation ?? STACK_DEFAULT_PRESENTATION) !== 'push' &&
|
|
102
|
+
!headerHidden);
|
|
100
103
|
}
|
|
101
104
|
// Inner-modal wrapper styles for isHeaderInModal: the inner RNSScreenStack fills its outer
|
|
102
105
|
// RNSScreen, and the inner RNSScreen fills the stack absolutely on all four edges. This mirrors
|
|
103
106
|
// react-native-screens' own `styles.container` / `StyleSheet.absoluteFill` for this exact pair.
|
|
104
107
|
const HEADER_IN_MODAL_STACK_STYLE = { flex: 1 };
|
|
105
|
-
const HEADER_IN_MODAL_SCREEN_STYLE = {
|
|
108
|
+
const HEADER_IN_MODAL_SCREEN_STYLE = {
|
|
109
|
+
position: 'absolute',
|
|
110
|
+
top: 0,
|
|
111
|
+
start: 0,
|
|
112
|
+
end: 0,
|
|
113
|
+
bottom: 0,
|
|
114
|
+
};
|
|
106
115
|
export function resolveHeaderInModalStackStyle() {
|
|
107
116
|
return HEADER_IN_MODAL_STACK_STYLE;
|
|
108
117
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// The header bar-button payload+dispatch cluster (id-tagging, onPress lookup) lives in
|
|
8
8
|
// header-bar-buttons.ts - self-contained, consumed here only as a black box by
|
|
9
9
|
// resolveHeaderConfigView.
|
|
10
|
-
import { buildHeaderBarButtonDispatch, prepareHeaderBarButtonItems } from './header-bar-buttons.js';
|
|
10
|
+
import { buildHeaderBarButtonDispatch, prepareHeaderBarButtonItems, } from './header-bar-buttons.js';
|
|
11
11
|
// These sentinels must be kept in sync with react-native-screens' native side - they are RNS's
|
|
12
12
|
// own compat values for the 'fitToContents'/'large'/'medium'/'all' legacy presets, replicated
|
|
13
13
|
// here because we drive RNSScreen directly (no react-native-screens JS component in the path).
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// buildScrollViewHandle exactly (same lazy-getter shape); the adapter supplies the node getter
|
|
6
6
|
// and its own framework-specific ref field (see react/screen.ts's IReactSearchBarOptions - the
|
|
7
7
|
// ref itself is per-adapter, same split as IPressableProps).
|
|
8
|
-
import { dispatchViewCommand, dlog } from '@symbiote-native/engine';
|
|
8
|
+
import { dispatchViewCommand, dlog, } from '@symbiote-native/engine';
|
|
9
9
|
// dispatchViewCommand itself dlogs a "node not committed" skip; this null case (the ref never
|
|
10
10
|
// attached to a live RNSSearchBar at all - e.g. the header's search bar isn't mounted, or a
|
|
11
11
|
// stale handle outlived its screen) was the one unlogged gap, silently indistinguishable from
|
|
@@ -7,10 +7,14 @@ import { isRecord } from '../guards.js';
|
|
|
7
7
|
// params: undefined}`, and JSON.stringify drops undefined-valued keys - a JSON round trip of a
|
|
8
8
|
// perfectly valid route legitimately arrives here without a `params` key at all.
|
|
9
9
|
function isRoute(value) {
|
|
10
|
-
return isRecord(value) &&
|
|
10
|
+
return (isRecord(value) &&
|
|
11
|
+
typeof value.key === 'string' &&
|
|
12
|
+
typeof value.name === 'string');
|
|
11
13
|
}
|
|
12
14
|
function isNavigatorState(value) {
|
|
13
|
-
return isRecord(value) &&
|
|
15
|
+
return (isRecord(value) &&
|
|
16
|
+
Array.isArray(value.routes) &&
|
|
17
|
+
value.routes.every(isRoute));
|
|
14
18
|
}
|
|
15
19
|
export function serializeNavigatorState(state) {
|
|
16
20
|
return state;
|
|
@@ -49,7 +49,10 @@ export function tabRouterReducer(state, action) {
|
|
|
49
49
|
}
|
|
50
50
|
const target = state.routes[index];
|
|
51
51
|
const routes = state.routes.slice();
|
|
52
|
-
routes[index] = {
|
|
52
|
+
routes[index] = {
|
|
53
|
+
...target,
|
|
54
|
+
params: mergeParams(target.params, action.params),
|
|
55
|
+
};
|
|
53
56
|
return { ...state, index, routes };
|
|
54
57
|
}
|
|
55
58
|
case 'setParams': {
|
|
@@ -58,7 +61,10 @@ export function tabRouterReducer(state, action) {
|
|
|
58
61
|
return state;
|
|
59
62
|
const target = state.routes[index];
|
|
60
63
|
const routes = state.routes.slice();
|
|
61
|
-
routes[index] = {
|
|
64
|
+
routes[index] = {
|
|
65
|
+
...target,
|
|
66
|
+
params: mergeParams(target.params, action.params),
|
|
67
|
+
};
|
|
62
68
|
return { ...state, routes };
|
|
63
69
|
}
|
|
64
70
|
default:
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
// @symbiote-native/engine), which is sufficient for a solid drawer but NOT byte-for-byte parity -
|
|
16
16
|
// see the explicit gap list at the bottom of this file.
|
|
17
17
|
import { createElement, forwardRef, isValidElement, useCallback, useContext, useEffect, useId, useImperativeHandle, useMemo, useReducer, useRef, } from 'react';
|
|
18
|
-
import { Animated, PanResponder, useWindowDimensions } from '@symbiote-native/react';
|
|
19
|
-
import { dlog } from '@symbiote-native/engine';
|
|
18
|
+
import { Animated, PanResponder, useWindowDimensions, } from '@symbiote-native/react';
|
|
19
|
+
import { dlog, } from '@symbiote-native/engine';
|
|
20
20
|
import { DRAWER_DEFAULT_OVERLAY_COLOR, NAVIGATION_EVENT_BLUR, NAVIGATION_EVENT_FOCUS, createInitialDrawerRouterState, createNavigationEmitter, drawerChildOrder, drawerRouterReducer, isDrawerAnimated, renderDrawer, resolveDragProgress, resolveDrawerGeometry, resolveDrawerSlotInterpolation, resolveSwipeIntent, shouldClaimDrawerSwipe, } from '../../core/index.js';
|
|
21
21
|
import { collectRegistry } from '../collect-registry.js';
|
|
22
22
|
import { NavigationContext } from '../navigation-context.js';
|
|
@@ -25,7 +25,9 @@ function isDrawerScreenElement(child) {
|
|
|
25
25
|
return isValidElement(child) && child.type === DrawerScreen;
|
|
26
26
|
}
|
|
27
27
|
function resolveDrawerScreenOptions(entry, optionsArgs, screenOptions) {
|
|
28
|
-
const own = typeof entry.options === 'function'
|
|
28
|
+
const own = typeof entry.options === 'function'
|
|
29
|
+
? entry.options(optionsArgs)
|
|
30
|
+
: entry.options;
|
|
29
31
|
return { ...screenOptions, ...own };
|
|
30
32
|
}
|
|
31
33
|
const DRAWER_SNAP_DURATION = 250;
|
|
@@ -148,12 +150,24 @@ const DrawerImpl = forwardRef((props, forwardedRef) => {
|
|
|
148
150
|
})).current;
|
|
149
151
|
const animated = isDrawerAnimated(options);
|
|
150
152
|
const geometry = useMemo(() => resolveDrawerGeometry(options), [options.drawerType, options.drawerPosition, options.drawerWidth]);
|
|
151
|
-
const panelSlot = animated
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
153
|
+
const panelSlot = animated
|
|
154
|
+
? resolveDrawerSlotInterpolation(geometry, 'panel')
|
|
155
|
+
: undefined;
|
|
156
|
+
const contentSlot = animated
|
|
157
|
+
? resolveDrawerSlotInterpolation(geometry, 'content')
|
|
158
|
+
: undefined;
|
|
159
|
+
const overlaySlot = animated
|
|
160
|
+
? resolveDrawerSlotInterpolation(geometry, 'overlay')
|
|
161
|
+
: undefined;
|
|
162
|
+
const panelTranslateX = panelSlot
|
|
163
|
+
? progress.interpolate(panelSlot.translateX)
|
|
164
|
+
: undefined;
|
|
165
|
+
const contentTranslateX = contentSlot
|
|
166
|
+
? progress.interpolate(contentSlot.translateX)
|
|
167
|
+
: undefined;
|
|
168
|
+
const overlayOpacity = overlaySlot
|
|
169
|
+
? progress.interpolate(overlaySlot.opacity)
|
|
170
|
+
: undefined;
|
|
157
171
|
// The overlay is a full-screen absolutely-positioned sibling BELOW content in paint order
|
|
158
172
|
// (see render-drawer.ts's drawerChildOrder) - for 'front' that's fine since content never moves,
|
|
159
173
|
// but for 'slide' content itself translates away by contentTranslateX, and without following it
|
|
@@ -161,9 +175,13 @@ const DrawerImpl = forwardRef((props, forwardedRef) => {
|
|
|
161
175
|
// underneath instead of just the content sliver it's meant to dim. Tying overlay to the SAME
|
|
162
176
|
// translateX as content keeps it registered exactly under content, wherever content actually is
|
|
163
177
|
// (resolveDrawerSlotInterpolation's 'overlay' overload returns that same content delta).
|
|
164
|
-
const overlayTranslateX = overlaySlot
|
|
178
|
+
const overlayTranslateX = overlaySlot
|
|
179
|
+
? progress.interpolate(overlaySlot.translateX)
|
|
180
|
+
: undefined;
|
|
165
181
|
const focusedRoute = state.routes[state.index];
|
|
166
|
-
const focusedEntry = focusedRoute
|
|
182
|
+
const focusedEntry = focusedRoute
|
|
183
|
+
? registry.get(focusedRoute.name)
|
|
184
|
+
: undefined;
|
|
167
185
|
if (focusedRoute && !focusedEntry) {
|
|
168
186
|
dlog(`Drawer: no screen registered for route name "${focusedRoute.name}"`);
|
|
169
187
|
}
|
|
@@ -250,8 +268,13 @@ const DrawerImpl = forwardRef((props, forwardedRef) => {
|
|
|
250
268
|
: { transform: [{ translateX: contentTranslateX }] },
|
|
251
269
|
overlay: overlayOpacity === undefined
|
|
252
270
|
? undefined
|
|
253
|
-
: {
|
|
254
|
-
|
|
271
|
+
: {
|
|
272
|
+
opacity: overlayOpacity,
|
|
273
|
+
transform: [{ translateX: overlayTranslateX }],
|
|
274
|
+
},
|
|
275
|
+
panel: panelTranslateX === undefined
|
|
276
|
+
? undefined
|
|
277
|
+
: { transform: [{ translateX: panelTranslateX }] },
|
|
255
278
|
};
|
|
256
279
|
function renderSlot(slot) {
|
|
257
280
|
const descriptor = slots.get(slot);
|
package/build/react/index.d.ts
CHANGED
|
@@ -2,14 +2,14 @@ import '../register';
|
|
|
2
2
|
export { Stack } from './stack';
|
|
3
3
|
export type { INavigatorHandle, IStackProps } from './stack';
|
|
4
4
|
export { Screen } from './screen';
|
|
5
|
-
export type { IScreenOptionsArgs, IScreenOptionsResolver, IScreenProps } from './screen';
|
|
6
|
-
export type { IScreenOptions, IStackAnimation, IStackPresentation } from '../core';
|
|
7
|
-
export { useNavigation, useRoute, useIsFocused, useFocusEffect, useNavigationState } from './hooks';
|
|
5
|
+
export type { IScreenOptionsArgs, IScreenOptionsResolver, IScreenProps, } from './screen';
|
|
6
|
+
export type { IScreenOptions, IStackAnimation, IStackPresentation, } from '../core';
|
|
7
|
+
export { useNavigation, useRoute, useIsFocused, useFocusEffect, useNavigationState, } from './hooks';
|
|
8
8
|
export type { INavigationHandle } from './hooks';
|
|
9
|
-
export { useStackNavigation, useTabNavigation, useDrawerNavigation } from './hooks';
|
|
9
|
+
export { useStackNavigation, useTabNavigation, useDrawerNavigation, } from './hooks';
|
|
10
10
|
export type { IStackNavigationHandle, ITabNavigationHandle, IDrawerNavigationHandle, } from './hooks';
|
|
11
11
|
export { NavigationContext } from './navigation-context';
|
|
12
|
-
export type { INavigationContextValue, IAnyNavigatorHandle } from './navigation-context';
|
|
12
|
+
export type { INavigationContextValue, IAnyNavigatorHandle, } from './navigation-context';
|
|
13
13
|
export { useLinkingIntegration } from './linking';
|
|
14
14
|
export type { ILinkingConfig, IScreenLinkingConfig } from '../core';
|
|
15
15
|
export { Tab } from './tabs';
|
|
@@ -18,7 +18,7 @@ export { TabScreen } from './tab-screen';
|
|
|
18
18
|
export type { ITabScreenOptionsArgs, ITabScreenOptionsResolver, ITabScreenProps, } from './tab-screen';
|
|
19
19
|
export type { ITabOptions, ITabBarIcon } from '../core';
|
|
20
20
|
export { Drawer } from './drawer';
|
|
21
|
-
export type { IDrawerNavigatorHandle, IDrawerProps, IDrawerDescriptorMap } from './drawer';
|
|
21
|
+
export type { IDrawerNavigatorHandle, IDrawerProps, IDrawerDescriptorMap, } from './drawer';
|
|
22
22
|
export { DrawerScreen } from './drawer-screen';
|
|
23
23
|
export type { IDrawerScreenOptionsArgs, IDrawerScreenOptionsResolver, IDrawerScreenProps, } from './drawer-screen';
|
|
24
|
-
export type { IDrawerOptions, IDrawerScreenOptions, IDrawerType, IDrawerPosition } from '../core';
|
|
24
|
+
export type { IDrawerOptions, IDrawerScreenOptions, IDrawerType, IDrawerPosition, } from '../core';
|
package/build/react/index.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
import '../register';
|
|
6
6
|
export { Stack } from './stack/index.js';
|
|
7
7
|
export { Screen } from './screen.js';
|
|
8
|
-
export { useNavigation, useRoute, useIsFocused, useFocusEffect, useNavigationState } from './hooks/index.js';
|
|
9
|
-
export { useStackNavigation, useTabNavigation, useDrawerNavigation } from './hooks/index.js';
|
|
8
|
+
export { useNavigation, useRoute, useIsFocused, useFocusEffect, useNavigationState, } from './hooks/index.js';
|
|
9
|
+
export { useStackNavigation, useTabNavigation, useDrawerNavigation, } from './hooks/index.js';
|
|
10
10
|
export { NavigationContext } from './navigation-context.js';
|
|
11
11
|
export { useLinkingIntegration } from './linking.js';
|
|
12
12
|
// Tab: the bottom-tabs navigator, a PURE-JS UI (no react-native-screens views involved, so no
|
|
@@ -18,12 +18,16 @@ import { Screen } from '../screen.js';
|
|
|
18
18
|
// backTitleVisible defaults to `true` on both platforms per the codegen spec's own default
|
|
19
19
|
// (CT.WithDefault<boolean, 'true'>) - no ios/android divergence in v1 scope, so a single constant
|
|
20
20
|
// stands in for the per-platform injection point ISliderPlatform-style adapters use elsewhere.
|
|
21
|
-
const NAVIGATOR_PLATFORM = {
|
|
21
|
+
const NAVIGATOR_PLATFORM = {
|
|
22
|
+
defaultHeaderBackTitleVisible: true,
|
|
23
|
+
};
|
|
22
24
|
function isScreenElement(child) {
|
|
23
25
|
return isValidElement(child) && child.type === Screen;
|
|
24
26
|
}
|
|
25
27
|
function resolveScreenOptions(entry, optionsArgs, screenOptions) {
|
|
26
|
-
const own = typeof entry.options === 'function'
|
|
28
|
+
const own = typeof entry.options === 'function'
|
|
29
|
+
? entry.options(optionsArgs)
|
|
30
|
+
: entry.options;
|
|
27
31
|
return { ...screenOptions, ...own };
|
|
28
32
|
}
|
|
29
33
|
const StackImpl = forwardRef((props, forwardedRef) => {
|
|
@@ -51,14 +55,22 @@ const StackImpl = forwardRef((props, forwardedRef) => {
|
|
|
51
55
|
}, [emitters]);
|
|
52
56
|
const createRoute = useCallback((name, params) => {
|
|
53
57
|
routeSequence.current += 1;
|
|
54
|
-
return {
|
|
58
|
+
return {
|
|
59
|
+
key: `${routeIdPrefix}-${name}-${routeSequence.current}`,
|
|
60
|
+
name,
|
|
61
|
+
params,
|
|
62
|
+
};
|
|
55
63
|
}, [routeIdPrefix]);
|
|
56
64
|
const registeredNames = useMemo(() => [...registry.keys()], [registry]);
|
|
57
65
|
const [dispatchedState, dispatch] = useReducer(navigatorReducer, undefined, () => {
|
|
58
66
|
const initialRouteName = props.initialRouteName ?? registry.keys().next().value;
|
|
59
67
|
if (initialRouteName === undefined) {
|
|
60
68
|
dlog('Stack: no <Stack.Screen> children registered');
|
|
61
|
-
return createInitialNavigatorState({
|
|
69
|
+
return createInitialNavigatorState({
|
|
70
|
+
key: routeIdPrefix,
|
|
71
|
+
name: '',
|
|
72
|
+
params: undefined,
|
|
73
|
+
});
|
|
62
74
|
}
|
|
63
75
|
return createInitialNavigatorState(createRoute(initialRouteName, registry.get(initialRouteName)?.initialParams));
|
|
64
76
|
});
|
|
@@ -112,7 +124,10 @@ const StackImpl = forwardRef((props, forwardedRef) => {
|
|
|
112
124
|
dlog(`Stack: no screen registered for route name "${route.name}"`);
|
|
113
125
|
return null;
|
|
114
126
|
}
|
|
115
|
-
const screenOptionsArgs = {
|
|
127
|
+
const screenOptionsArgs = {
|
|
128
|
+
route,
|
|
129
|
+
navigation: handle,
|
|
130
|
+
};
|
|
116
131
|
const mergedOptions = resolveScreenOptions(entry, screenOptionsArgs, props.screenOptions);
|
|
117
132
|
const activityState = computeActivityState(index, state.routes.length);
|
|
118
133
|
// Investigation instrumentation (flicker-on-focus bug): fires on EVERY Stack render, not just
|
|
@@ -166,7 +181,8 @@ const StackImpl = forwardRef((props, forwardedRef) => {
|
|
|
166
181
|
const appRef = searchBarOptions.ref;
|
|
167
182
|
if (!appRef)
|
|
168
183
|
return;
|
|
169
|
-
appRef.current =
|
|
184
|
+
appRef.current =
|
|
185
|
+
node === null ? null : buildSearchBarHandle(() => node);
|
|
170
186
|
},
|
|
171
187
|
}
|
|
172
188
|
: undefined,
|
|
@@ -188,7 +204,14 @@ const StackImpl = forwardRef((props, forwardedRef) => {
|
|
|
188
204
|
// sizing (see RNS_SCREEN_CONTENT_WRAPPER_VIEW_NAME's comment in core/constants.ts). A
|
|
189
205
|
// `push` screen doesn't need it, but a `formSheet` one is otherwise left with no content
|
|
190
206
|
// ever attached natively.
|
|
191
|
-
const content = createElement(RNS_SCREEN_CONTENT_WRAPPER_VIEW_NAME, plan.contentWrapperProps, createElement(NavigationContext.Provider, {
|
|
207
|
+
const content = createElement(RNS_SCREEN_CONTENT_WRAPPER_VIEW_NAME, plan.contentWrapperProps, createElement(NavigationContext.Provider, {
|
|
208
|
+
value: {
|
|
209
|
+
route,
|
|
210
|
+
navigation: handle,
|
|
211
|
+
emitter: routeEmitter,
|
|
212
|
+
parent: ambientContext,
|
|
213
|
+
},
|
|
214
|
+
}, createElement(entry.component)));
|
|
192
215
|
// react-native-screens' own Screen.tsx swaps in a DIFFERENT Fabric component
|
|
193
216
|
// ('RNSModalScreen') for a modally-presented screen - its native updateLayoutMetrics: relies on
|
|
194
217
|
// this exact class to know it must NOT apply Yoga's computed frame (see resolveScreenViewName's
|
|
@@ -205,7 +228,10 @@ const StackImpl = forwardRef((props, forwardedRef) => {
|
|
|
205
228
|
// RNSScreen.mm treats an unset/inactive nested screen as not yet pushed, leaving it
|
|
206
229
|
// parked at its pre-push transition position (off past the bottom edge) instead of
|
|
207
230
|
// its real, presented frame.
|
|
208
|
-
{
|
|
231
|
+
{
|
|
232
|
+
style: plan.innerScreenStyle,
|
|
233
|
+
activityState: plan.activityState,
|
|
234
|
+
}, descriptorToReact(plan.headerConfig), content)))
|
|
209
235
|
: createElement(plan.screenViewName, { key: route.key, ...plan.screenProps }, descriptorToReact(plan.headerConfig), content);
|
|
210
236
|
});
|
|
211
237
|
return createElement(RNS_SCREEN_STACK_VIEW_NAME, stackProps, ...children);
|
|
@@ -17,7 +17,9 @@ function isTabScreenElement(child) {
|
|
|
17
17
|
return isValidElement(child) && child.type === TabScreen;
|
|
18
18
|
}
|
|
19
19
|
function resolveTabOptions(entry, optionsArgs, screenOptions) {
|
|
20
|
-
const own = typeof entry.options === 'function'
|
|
20
|
+
const own = typeof entry.options === 'function'
|
|
21
|
+
? entry.options(optionsArgs)
|
|
22
|
+
: entry.options;
|
|
21
23
|
return { ...screenOptions, ...own };
|
|
22
24
|
}
|
|
23
25
|
const TAB_CONTENT_STYLE = { flex: 1 };
|
|
@@ -41,7 +43,9 @@ const TabImpl = forwardRef((props, forwardedRef) => {
|
|
|
41
43
|
// than staying frozen at whatever the first render saw. `null` means no marker had registered
|
|
42
44
|
// yet: seeding an empty list would resolve initialRouteName against nothing and lose it, so the
|
|
43
45
|
// state stays derived until either a marker arrives or something dispatches.
|
|
44
|
-
const [storedState, setStoredState] = useState(() => routes.length === 0
|
|
46
|
+
const [storedState, setStoredState] = useState(() => routes.length === 0
|
|
47
|
+
? null
|
|
48
|
+
: createInitialTabState(routes, props.initialRouteName));
|
|
45
49
|
const resolveState = useCallback((stored) => stored === null
|
|
46
50
|
? createInitialTabState(routes, props.initialRouteName)
|
|
47
51
|
: reconcileTabRoutes(stored, routes), [routes, props.initialRouteName]);
|
|
@@ -84,11 +88,17 @@ const TabImpl = forwardRef((props, forwardedRef) => {
|
|
|
84
88
|
},
|
|
85
89
|
};
|
|
86
90
|
});
|
|
87
|
-
const focusedEntry = focusedRoute
|
|
91
|
+
const focusedEntry = focusedRoute
|
|
92
|
+
? registry.get(focusedRoute.name)
|
|
93
|
+
: undefined;
|
|
88
94
|
const focusedOptions = focusedEntry && focusedRoute
|
|
89
95
|
? resolveTabOptions(focusedEntry, { route: focusedRoute, navigation: handle }, props.screenOptions)
|
|
90
96
|
: props.screenOptions;
|
|
91
|
-
const tabBar = descriptorToReact(renderTabBar({
|
|
97
|
+
const tabBar = descriptorToReact(renderTabBar({
|
|
98
|
+
items,
|
|
99
|
+
style: focusedOptions?.tabBarStyle,
|
|
100
|
+
passthrough: {},
|
|
101
|
+
}));
|
|
92
102
|
// Only the focused route's screen is ever mounted (unlike Stack, which keeps every pushed route
|
|
93
103
|
// alive), so a fresh emitter per focus change is sufficient - no per-route emitter map to prune,
|
|
94
104
|
// because the previous screen's whole subtree (and any listeners it registered) is torn down by
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Accessor } from 'solid-js';
|
|
2
|
+
import type { JSX } from '@symbiote-native/solid/jsx-runtime';
|
|
3
|
+
import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
|
|
4
|
+
import type { IDrawerDescriptorMap, IDrawerNavigatorHandle, IDrawerOptions, IDrawerRouterState } from '../../core';
|
|
5
|
+
import { DrawerScreen } from '../screen';
|
|
6
|
+
export type { IDrawerNavigatorHandle, IDrawerDescriptorMap } from '../../core';
|
|
7
|
+
export type IDrawerContentSlotProps = {
|
|
8
|
+
state: IDrawerRouterState;
|
|
9
|
+
descriptors: IDrawerDescriptorMap;
|
|
10
|
+
navigation: IDrawerNavigatorHandle;
|
|
11
|
+
};
|
|
12
|
+
export type IDrawerProps = IDrawerOptions & {
|
|
13
|
+
initialRouteName?: string;
|
|
14
|
+
drawerStyle?: IStyleProp<IViewStyle>;
|
|
15
|
+
drawerContent?: (props: Accessor<IDrawerContentSlotProps>) => JSX.Element;
|
|
16
|
+
ref?: (handle: IDrawerNavigatorHandle) => void;
|
|
17
|
+
children?: JSX.Element;
|
|
18
|
+
};
|
|
19
|
+
declare function DrawerImpl(props: IDrawerProps): JSX.Element;
|
|
20
|
+
export declare const Drawer: typeof DrawerImpl & {
|
|
21
|
+
Screen: typeof DrawerScreen;
|
|
22
|
+
};
|