@ng-native/router 0.17.0 → 0.18.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/dist/discard-failed-entries.d.ts +11 -0
- package/dist/discard-failed-entries.js +48 -0
- package/dist/discard-failed-entries.js.map +1 -0
- package/dist/in-tab.d.ts +9 -1
- package/dist/in-tab.js +2 -0
- package/dist/in-tab.js.map +1 -1
- package/dist/native-back.d.ts +21 -1
- package/dist/native-back.js +94 -3
- package/dist/native-back.js.map +1 -1
- package/dist/native-header.d.ts +8 -1
- package/dist/native-header.js +18 -4
- package/dist/native-header.js.map +1 -1
- package/dist/native-navigation.d.ts +10 -2
- package/dist/native-navigation.js +45 -9
- package/dist/native-navigation.js.map +1 -1
- package/dist/native-platform-location.d.ts +42 -0
- package/dist/native-platform-location.js +66 -0
- package/dist/native-platform-location.js.map +1 -1
- package/dist/native-stack-outlet.d.ts +83 -0
- package/dist/native-stack-outlet.js +245 -19
- package/dist/native-stack-outlet.js.map +1 -1
- package/dist/native-stack-reuse-strategy.d.ts +34 -0
- package/dist/native-stack-reuse-strategy.js +119 -7
- package/dist/native-stack-reuse-strategy.js.map +1 -1
- package/dist/native-tab.d.ts +8 -6
- package/dist/native-tab.js +23 -2
- package/dist/native-tab.js.map +1 -1
- package/dist/native-tabs-outlet.d.ts +9 -3
- package/dist/native-tabs-outlet.js +21 -4
- package/dist/native-tabs-outlet.js.map +1 -1
- package/dist/popping-to.d.ts +8 -0
- package/dist/popping-to.js +2 -0
- package/dist/popping-to.js.map +1 -0
- package/dist/presented-route.js +12 -10
- package/dist/presented-route.js.map +1 -1
- package/dist/provide-native-router.js +4 -0
- package/dist/provide-native-router.js.map +1 -1
- package/dist/screen-header.d.ts +5 -3
- package/dist/screen-header.js +5 -3
- package/dist/screen-header.js.map +1 -1
- package/dist/screen-presentation.d.ts +5 -0
- package/dist/screen-presentation.js.map +1 -1
- package/dist/screen-safe-area-view.d.ts +6 -1
- package/dist/screen-safe-area-view.js +12 -4
- package/dist/screen-safe-area-view.js.map +1 -1
- package/dist/screens-version.d.ts +12 -0
- package/dist/screens-version.js +20 -0
- package/dist/screens-version.js.map +1 -0
- package/dist/screens.js +3 -0
- package/dist/screens.js.map +1 -1
- package/dist/url-commands.d.ts +24 -0
- package/dist/url-commands.js +102 -0
- package/dist/url-commands.js.map +1 -0
- package/package.json +3 -3
|
@@ -5,7 +5,12 @@ export declare class ScreenSafeAreaView {
|
|
|
5
5
|
constructor();
|
|
6
6
|
/** Whether the screen has a bar the page starts below. See `screen-header.ts`. */
|
|
7
7
|
private readonly header;
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Whether the top under such a bar is the screen's to inset already: Android's view, which the
|
|
10
|
+
* page starts below, and iOS 26 and later, where the stack commits the page in a view that
|
|
11
|
+
* insets it (`insetContent` in `native-stack-outlet.ts`) and a second would count the bar twice.
|
|
12
|
+
*/
|
|
13
|
+
private readonly topTaken;
|
|
9
14
|
/** Which edges to inset. Absent insets all four. */
|
|
10
15
|
readonly edges: import("@angular/core").InputSignal<readonly ScreenSafeAreaEdge[] | undefined>;
|
|
11
16
|
/**
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
*
|
|
24
24
|
* Android's bar is above the page rather than over it, and its view insets the top by the status
|
|
25
25
|
* bar all the same. So under a header that is shown and not translucent the top edge is left
|
|
26
|
-
* alone there, and the page starts under the bar as it does on iOS.
|
|
26
|
+
* alone there, and the page starts under the bar as it does on iOS. On iOS 26 and later the stack
|
|
27
|
+
* already commits a page in a view that insets it below such a bar, so the top edge is left alone
|
|
28
|
+
* there too, rather than counting the bar twice.
|
|
27
29
|
*
|
|
28
30
|
* **The insets are applied as margin, not padding.** Whatever is beneath the inset shows through
|
|
29
31
|
* it, so a panel whose background has to reach the edge of the screen puts that background on a
|
|
@@ -34,6 +36,7 @@
|
|
|
34
36
|
* insets by nothing.
|
|
35
37
|
*/
|
|
36
38
|
import { Component, ElementRef, computed, inject, input } from '@angular/core';
|
|
39
|
+
import { OS_VERSION } from '@ng-native/device';
|
|
37
40
|
import { nativePlatform } from '@ng-native/fabric';
|
|
38
41
|
import { ownHost } from "./own-host.js";
|
|
39
42
|
import { SCREEN_HEADER } from "./screen-header.js";
|
|
@@ -45,7 +48,13 @@ export class ScreenSafeAreaView {
|
|
|
45
48
|
}
|
|
46
49
|
/** Whether the screen has a bar the page starts below. See `screen-header.ts`. */
|
|
47
50
|
header = inject(SCREEN_HEADER, { optional: true });
|
|
48
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Whether the top under such a bar is the screen's to inset already: Android's view, which the
|
|
53
|
+
* page starts below, and iOS 26 and later, where the stack commits the page in a view that
|
|
54
|
+
* insets it (`insetContent` in `native-stack-outlet.ts`) and a second would count the bar twice.
|
|
55
|
+
*/
|
|
56
|
+
topTaken = nativePlatform() === 'android' ||
|
|
57
|
+
(nativePlatform() === 'ios' && (inject(OS_VERSION) ?? 0) >= 26);
|
|
49
58
|
/** Which edges to inset. Absent insets all four. */
|
|
50
59
|
edges = input(/* @ts-ignore */
|
|
51
60
|
...(ngDevMode ? [undefined, { debugName: "edges" }] : /* istanbul ignore next */ []));
|
|
@@ -55,8 +64,7 @@ export class ScreenSafeAreaView {
|
|
|
55
64
|
*/
|
|
56
65
|
resolvedEdges = computed(() => {
|
|
57
66
|
const edges = this.edges() ?? ALL;
|
|
58
|
-
|
|
59
|
-
const covered = this.android && this.header?.() ? 'top' : null;
|
|
67
|
+
const covered = this.topTaken && this.header?.() ? 'top' : null;
|
|
60
68
|
return Object.fromEntries(ALL.map((edge) => [edge, edge !== covered && edges.includes(edge)]));
|
|
61
69
|
}, /* @ts-ignore */
|
|
62
70
|
...(ngDevMode ? [{ debugName: "resolvedEdges" }] : /* istanbul ignore next */ []));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen-safe-area-view.js","sourceRoot":"","sources":["../src/screen-safe-area-view.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"screen-safe-area-view.js","sourceRoot":"","sources":["../src/screen-safe-area-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAmB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;;AAKnD,MAAM,GAAG,GAAkC,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAO9E,MAAM,OAAO,kBAAkB;IAC7B;QACE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,aAA2B,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5E,CAAC;IAED,kFAAkF;IACjE,MAAM,GAAG,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE;;;;OAIG;IACc,QAAQ,GACvB,cAAc,EAAE,KAAK,SAAS;QAC9B,CAAC,cAAc,EAAE,KAAK,KAAK,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAElE,oDAAoD;IAC3C,KAAK,GAAG,KAAK;yFAAiC,CAAC;IAExD;;;OAGG;IACgB,aAAa,GAAG,QAAQ,CAAC,GAAG,EAAE;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAChE,OAAO,MAAM,CAAC,WAAW,CACvB,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAC7B,CAAC;IAC3C,CAAC;sFAAC,CAAC;uGA7BQ,kBAAkB;2FAAlB,kBAAkB,2QAHnB,gBAAgB;;2FAGf,kBAAkB;kBAL9B,SAAS;mBAAC;oBACT,QAAQ,EAAE,uBAAuB;oBACjC,QAAQ,EAAE,gBAAgB;oBAC1B,IAAI,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE;iBACvC","sourcesContent":["/**\n * A view that keeps its content clear of whatever covers the screen it is in: a translucent\n * navigation bar and the search bar under it, the tab bar, the home indicator and the system bars.\n *\n * ```html\n * <native-header title=\"Planner\" />\n * <screen-safe-area-view [edges]=\"['top']\" style=\"flex: 1\">\n * <view class=\"controls\">…</view>\n * <scroll-view>…</scroll-view>\n * </screen-safe-area-view>\n * ```\n *\n * `<safe-area-view>` cannot do this. Its insets come from the nearest `<safe-area-provider>`,\n * which sits at the root of the app, above every bar, and so measures only the window's own\n * unsafe areas: a page under a Liquid Glass header starts behind the bar, and anything pinned to\n * the bottom of a tab ends up under the tab bar.\n *\n * This is react-native-screens' own `RNSSafeAreaView`, which asks the screen it is in instead.\n * On iOS that is the screen's `safeAreaInsets`, which UIKit extends by a translucent navigation\n * bar and by the tab bar, floating or not, on top of the status bar and the home indicator. On\n * Android it is the larger of the bottom navigation bar's height and the system bars. Both follow\n * the bars as they change, rotate, or are hidden.\n *\n * Android's bar is above the page rather than over it, and its view insets the top by the status\n * bar all the same. So under a header that is shown and not translucent the top edge is left\n * alone there, and the page starts under the bar as it does on iOS. On iOS 26 and later the stack\n * already commits a page in a view that insets it below such a bar, so the top edge is left alone\n * there too, rather than counting the bar twice.\n *\n * **The insets are applied as margin, not padding.** Whatever is beneath the inset shows through\n * it, so a panel whose background has to reach the edge of the screen puts that background on a\n * parent and this inside it: the parent grows by the margin and paints behind the bar, and the\n * content ends where the bar begins.\n *\n * It has to be inside a screen: a page of a stack, or a tab. On iOS, with no screen above it, it\n * insets by nothing.\n */\nimport { Component, ElementRef, computed, inject, input } from '@angular/core';\nimport { OS_VERSION } from '@ng-native/device';\nimport { nativePlatform, type EngineNode } from '@ng-native/fabric';\nimport { ownHost } from './own-host.ts';\nimport { SCREEN_HEADER } from './screen-header.ts';\n\n/** The edges of the screen. */\nexport type ScreenSafeAreaEdge = 'top' | 'right' | 'bottom' | 'left';\n\nconst ALL: readonly ScreenSafeAreaEdge[] = ['top', 'right', 'bottom', 'left'];\n\n@Component({\n selector: 'screen-safe-area-view',\n template: '<ng-content />',\n host: { '[edges]': 'resolvedEdges()' },\n})\nexport class ScreenSafeAreaView {\n constructor() {\n ownHost(inject(ElementRef).nativeElement as EngineNode, this.constructor);\n }\n\n /** Whether the screen has a bar the page starts below. See `screen-header.ts`. */\n private readonly header = inject(SCREEN_HEADER, { optional: true });\n /**\n * Whether the top under such a bar is the screen's to inset already: Android's view, which the\n * page starts below, and iOS 26 and later, where the stack commits the page in a view that\n * insets it (`insetContent` in `native-stack-outlet.ts`) and a second would count the bar twice.\n */\n private readonly topTaken =\n nativePlatform() === 'android' ||\n (nativePlatform() === 'ios' && (inject(OS_VERSION) ?? 0) >= 26);\n\n /** Which edges to inset. Absent insets all four. */\n readonly edges = input<readonly ScreenSafeAreaEdge[]>();\n\n /**\n * Native takes all four edges every time, as booleans; a partial record leaves the missing\n * ones at whatever they were.\n */\n protected readonly resolvedEdges = computed(() => {\n const edges = this.edges() ?? ALL;\n const covered = this.topTaken && this.header?.() ? 'top' : null;\n return Object.fromEntries(\n ALL.map((edge) => [edge, edge !== covered && edges.includes(edge)]),\n ) as Record<ScreenSafeAreaEdge, boolean>;\n });\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
/**
|
|
3
|
+
* The app's react-native-screens version, from its own package. Its native half is built from the
|
|
4
|
+
* same package, and Expo pins the version Expo Go carries, so this is the version native reads
|
|
5
|
+
* props with. A token so that a test can stand in another.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SCREENS_VERSION: InjectionToken<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Whether react-native-screens `version` takes a template tab icon only as an `image` with a
|
|
10
|
+
* `template` rendering mode, as 4.29 and later do. Earlier releases take `iconType: 'template'`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function screensReadsRenderingModes(version: string): boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import screensPackage from 'react-native-screens/package.json' with { type: 'json' };
|
|
3
|
+
/**
|
|
4
|
+
* The app's react-native-screens version, from its own package. Its native half is built from the
|
|
5
|
+
* same package, and Expo pins the version Expo Go carries, so this is the version native reads
|
|
6
|
+
* props with. A token so that a test can stand in another.
|
|
7
|
+
*/
|
|
8
|
+
export const SCREENS_VERSION = new InjectionToken('SCREENS_VERSION', {
|
|
9
|
+
providedIn: 'root',
|
|
10
|
+
factory: () => screensPackage.version,
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* Whether react-native-screens `version` takes a template tab icon only as an `image` with a
|
|
14
|
+
* `template` rendering mode, as 4.29 and later do. Earlier releases take `iconType: 'template'`.
|
|
15
|
+
*/
|
|
16
|
+
export function screensReadsRenderingModes(version) {
|
|
17
|
+
const [major = 0, minor = 0] = version.split('.').map(Number);
|
|
18
|
+
return major > 4 || (major === 4 && minor >= 29);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=screens-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screens-version.js","sourceRoot":"","sources":["../src/screens-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,cAAc,MAAM,mCAAmC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAErF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,cAAc,CAAS,iBAAiB,EAAE;IAC3E,UAAU,EAAE,MAAM;IAClB,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO;CACtC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe;IACxD,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9D,OAAO,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import { InjectionToken } from '@angular/core';\nimport screensPackage from 'react-native-screens/package.json' with { type: 'json' };\n\n/**\n * The app's react-native-screens version, from its own package. Its native half is built from the\n * same package, and Expo pins the version Expo Go carries, so this is the version native reads\n * props with. A token so that a test can stand in another.\n */\nexport const SCREENS_VERSION = new InjectionToken<string>('SCREENS_VERSION', {\n providedIn: 'root',\n factory: () => screensPackage.version,\n});\n\n/**\n * Whether react-native-screens `version` takes a template tab icon only as an `image` with a\n * `template` rendering mode, as 4.29 and later do. Earlier releases take `iconType: 'template'`.\n */\nexport function screensReadsRenderingModes(version: string): boolean {\n const [major = 0, minor = 0] = version.split('.').map(Number);\n return major > 4 || (major === 4 && minor >= 29);\n}\n"]}
|
package/dist/screens.js
CHANGED
|
@@ -40,6 +40,9 @@ export const SCREEN_VIEW_NAMES = {
|
|
|
40
40
|
'RNSScreenStackHeaderSubview',
|
|
41
41
|
{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center' },
|
|
42
42
|
],
|
|
43
|
+
// What a stack page's content commits in on iOS 26 and later, where the screen runs under the
|
|
44
|
+
// navigation bar: see `insetContent` in `native-stack-outlet.ts`. The fill is `SafeAreaView.tsx`'s.
|
|
45
|
+
'screen-content': ['RNSSafeAreaView', { flex: 1 }],
|
|
43
46
|
// Insets by what the screen it is in says is covered: a translucent navigation bar, and the tab
|
|
44
47
|
// bar. See `screen-safe-area-view.ts`. The same name on both platforms.
|
|
45
48
|
'screen-safe-area-view': ['RNSSafeAreaView'],
|
package/dist/screens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screens.js","sourceRoot":"","sources":["../src/screens.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * react-native-screens, driven directly.\n *\n * The native half of navigation already exists as codegen'd Fabric components. We register their\n * names and drive them with `createNode`; their React components are unreachable (hooks) and\n * `react-navigation` is not a dependency.\n *\n * No decorators here on purpose: tests import these at runtime, and Node's type stripping\n * refuses decorators.\n */\nimport { registerHoist, registerViewName } from '@ng-native/fabric';\n\n/**\n * Element name -> codegen'd Fabric component name, and the base style that component's React\n * wrapper would have applied in JS. Element names are lowercase, because the compiler silently\n * empties a template containing a capitalized one.\n *\n * The header's styles are `ScreenStackHeaderConfig.tsx`'s own, and the absolute positioning is\n * load-bearing: without it the config view takes part in the screen's flex layout and every page\n * renders a header's height too far down. `alignItems` is iOS-only there; it is harmless on\n * Android, where the native side lays the bar out itself.\n */\nexport const SCREEN_VIEW_NAMES: Record<string, [viewName: string, defaults?: object]> = {\n // NativeStackOutlet's own host element is the stack.\n 'native-stack-outlet': ['RNSScreenStack'],\n // Created by the outlet, one per activated route; nobody writes this in a template.\n screen: ['RNSScreen'],\n 'native-header': [\n 'RNSScreenStackHeaderConfig',\n {\n position: 'absolute',\n width: '100%',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n ],\n // Placed in a `<native-header-item type=\"searchBar\">`, as react-native-screens places its own.\n 'native-search-bar': ['RNSSearchBar'],\n 'native-header-item': [\n 'RNSScreenStackHeaderSubview',\n { flexDirection: 'row', alignItems: 'center', justifyContent: 'center' },\n ],\n // Insets by what the screen it is in says is covered: a translucent navigation bar, and the tab\n // bar. See `screen-safe-area-view.ts`. The same name on both platforms.\n 'screen-safe-area-view': ['RNSSafeAreaView'],\n 'tab-safe-area-view': ['RNSSafeAreaView'],\n};\n\n/**\n * The tabs half, which react-native-screens names per platform rather than sharing one component:\n * `RNSTabsHostIOS` wraps a `UITabBarController`, `RNSTabsHostAndroid` a bottom navigation bar,\n * and their props differ enough that the codegen specs are separate files.\n *\n * The fills are `TabsHost.ios.tsx`'s and `TabsScreen.ios.tsx`'s own. A tab screen is positioned\n * absolutely because it is one of several occupying the same space, only one of which is visible.\n */\nconst TAB_VIEW_NAMES: Record<string, [ios: string, android: string, defaults?: object]> = {\n 'native-tabs-outlet': [\n 'RNSTabsHostIOS',\n 'RNSTabsHostAndroid',\n { flex: 1, width: '100%', height: '100%' },\n ],\n 'native-tab': [\n 'RNSTabsScreenIOS',\n 'RNSTabsScreenAndroid',\n { position: 'absolute', flex: 1, width: '100%', height: '100%' },\n ],\n};\n\n/**\n * How visible a screen is. The native stack keeps every screen mounted and reads this rather\n * than adding and removing views, which is what preserves a pushed-away screen's native state.\n *\n * `Screen.tsx` throws if this ever *decreases* while in a native stack, so a screen goes\n * 0 -> 2 on push and is removed outright on pop rather than walked back down.\n */\nexport const ActivityState = {\n /** Off screen, and a candidate for freezing. */\n Inactive: 0,\n /** Mid transition: on screen but not the target. */\n Transitioning: 1,\n /** The screen the user is on. */\n Active: 2,\n} as const;\n\nexport type ActivityStateValue = (typeof ActivityState)[keyof typeof ActivityState];\n\n/**\n * The Fabric name of one of `ExpoRouterToolbarModule`'s views, as `requireNativeView` in\n * `expo-modules-core` computes it. Expo Go runs many projects in one binary and names every view\n * after the one it is running; a build of the app's own has no such suffix.\n *\n * `@ng-native/expo` derives the same name for its own views. The Angular-facing packages do not\n * import each other, and this is three lines.\n */\nfunction expoRouterToolbarView(view: string): string {\n const identifier = (globalThis as { expo?: { __expo_app_identifier__?: string } }).expo\n ?.__expo_app_identifier__;\n return `ViewManagerAdapter_ExpoRouterToolbarModule_${view}${identifier ? `_${identifier}` : ''}`;\n}\n\n/**\n * Ask React Native for react-native-screens' native module, which is what makes it.\n *\n * `ScreensModule` on Android installs, as it is made, the listener that starts a removed screen's\n * transition before its views are unmounted: without it a sheet is emptied and then slides away,\n * and a popped screen leaves as a blank one. React Native makes a module when JavaScript first\n * asks, and react-native-screens asks as its own JavaScript is imported (`fabric/\n * NativeScreensModule`), none of which is imported here. Through the two globals React Native's\n * own `TurboModuleRegistry` reads, in its order, so nothing of React Native is imported either:\n * the second is the only one there is without the bridge.\n */\nfunction loadScreensModule(): void {\n const host = globalThis as {\n __turboModuleProxy?: (name: string) => unknown;\n nativeModuleProxy?: Record<string, unknown>;\n };\n void (host.__turboModuleProxy?.('RNSModule') ?? host.nativeModuleProxy?.['RNSModule']);\n}\n\n/**\n * Call once at startup, before the first navigation.\n *\n * The app must also have `react-native-screens` installed so the native side registers these\n * components; this only teaches the engine the element-to-view-name mapping. A name the native\n * side does not know renders as `UnimplementedNativeView`, not an error. None of its JavaScript\n * is imported - Expo Go happens to bundle the native half, which is why the canary worked before\n * it declared the dependency at all, and why an app that forgets it fails only once it ships.\n */\nexport function registerScreenComponents(): void {\n loadScreensModule();\n for (const [element, [viewName, defaults]] of Object.entries(SCREEN_VIEW_NAMES)) {\n registerViewName(element, viewName, defaults as Record<string, unknown> | undefined);\n }\n // By platform, chosen when the view is looked up: this runs as the app's config is imported,\n // before its `main.ts` has reported the platform.\n // A window of its own on iOS; see `full-window-overlay.ts`. Its fill is the component's.\n registerViewName('full-window-overlay', { ios: 'RNSFullWindowOverlay', android: 'RCTView' });\n for (const [element, [ios, android, defaults]] of Object.entries(TAB_VIEW_NAMES)) {\n registerViewName(element, { ios, android }, defaults as Record<string, unknown>);\n }\n // A screen's bottom toolbar is Expo Router's, which react-native-screens has none of: see\n // `native-toolbar.ts`. Android has no such bar, so the elements are plain views there.\n registerViewName('native-toolbar', {\n ios: expoRouterToolbarView('RouterToolbarHostView'),\n android: 'RCTView',\n });\n registerViewName('native-toolbar-item', {\n ios: expoRouterToolbarView('RouterToolbarItemView'),\n android: 'RCTView',\n });\n // `findHeaderConfig` in `RNSScreen.mm` looks at the screen's direct children and no deeper, so\n // a header a page wrote inside a `safe-area-view` or a component of its own commits beside it.\n // Nothing in `RNSScreen.mm` updates the bar when its config is unmounted, so a header an `@if`\n // takes away leaves a config behind that hides the bar, and one that comes back adopts it.\n // A tab's page with no stack has no screen of its own: past its tab is the screen holding the\n // whole tab bar, so its header stops at the tab.\n registerHoist('native-header', 'screen', { standIn: { hidden: true }, stopAt: ['native-tab'] });\n // The toolbar host is a view of its own, absolute and out of the layout, that finds its screen\n // through its superviews. Written ahead of a page's scroll view it would be the screen's first\n // subview, where UIKit looks for the scroll view a large title collapses against.\n registerHoist('native-toolbar', 'screen');\n // The header config takes header items and nothing else, so one written inside a component of\n // the header commits as the config's child, not inside the component's view.\n registerHoist('native-header-item', 'native-header', { only: true });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"screens.js","sourceRoot":"","sources":["../src/screens.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * react-native-screens, driven directly.\n *\n * The native half of navigation already exists as codegen'd Fabric components. We register their\n * names and drive them with `createNode`; their React components are unreachable (hooks) and\n * `react-navigation` is not a dependency.\n *\n * No decorators here on purpose: tests import these at runtime, and Node's type stripping\n * refuses decorators.\n */\nimport { registerHoist, registerViewName } from '@ng-native/fabric';\n\n/**\n * Element name -> codegen'd Fabric component name, and the base style that component's React\n * wrapper would have applied in JS. Element names are lowercase, because the compiler silently\n * empties a template containing a capitalized one.\n *\n * The header's styles are `ScreenStackHeaderConfig.tsx`'s own, and the absolute positioning is\n * load-bearing: without it the config view takes part in the screen's flex layout and every page\n * renders a header's height too far down. `alignItems` is iOS-only there; it is harmless on\n * Android, where the native side lays the bar out itself.\n */\nexport const SCREEN_VIEW_NAMES: Record<string, [viewName: string, defaults?: object]> = {\n // NativeStackOutlet's own host element is the stack.\n 'native-stack-outlet': ['RNSScreenStack'],\n // Created by the outlet, one per activated route; nobody writes this in a template.\n screen: ['RNSScreen'],\n 'native-header': [\n 'RNSScreenStackHeaderConfig',\n {\n position: 'absolute',\n width: '100%',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n ],\n // Placed in a `<native-header-item type=\"searchBar\">`, as react-native-screens places its own.\n 'native-search-bar': ['RNSSearchBar'],\n 'native-header-item': [\n 'RNSScreenStackHeaderSubview',\n { flexDirection: 'row', alignItems: 'center', justifyContent: 'center' },\n ],\n // What a stack page's content commits in on iOS 26 and later, where the screen runs under the\n // navigation bar: see `insetContent` in `native-stack-outlet.ts`. The fill is `SafeAreaView.tsx`'s.\n 'screen-content': ['RNSSafeAreaView', { flex: 1 }],\n // Insets by what the screen it is in says is covered: a translucent navigation bar, and the tab\n // bar. See `screen-safe-area-view.ts`. The same name on both platforms.\n 'screen-safe-area-view': ['RNSSafeAreaView'],\n 'tab-safe-area-view': ['RNSSafeAreaView'],\n};\n\n/**\n * The tabs half, which react-native-screens names per platform rather than sharing one component:\n * `RNSTabsHostIOS` wraps a `UITabBarController`, `RNSTabsHostAndroid` a bottom navigation bar,\n * and their props differ enough that the codegen specs are separate files.\n *\n * The fills are `TabsHost.ios.tsx`'s and `TabsScreen.ios.tsx`'s own. A tab screen is positioned\n * absolutely because it is one of several occupying the same space, only one of which is visible.\n */\nconst TAB_VIEW_NAMES: Record<string, [ios: string, android: string, defaults?: object]> = {\n 'native-tabs-outlet': [\n 'RNSTabsHostIOS',\n 'RNSTabsHostAndroid',\n { flex: 1, width: '100%', height: '100%' },\n ],\n 'native-tab': [\n 'RNSTabsScreenIOS',\n 'RNSTabsScreenAndroid',\n { position: 'absolute', flex: 1, width: '100%', height: '100%' },\n ],\n};\n\n/**\n * How visible a screen is. The native stack keeps every screen mounted and reads this rather\n * than adding and removing views, which is what preserves a pushed-away screen's native state.\n *\n * `Screen.tsx` throws if this ever *decreases* while in a native stack, so a screen goes\n * 0 -> 2 on push and is removed outright on pop rather than walked back down.\n */\nexport const ActivityState = {\n /** Off screen, and a candidate for freezing. */\n Inactive: 0,\n /** Mid transition: on screen but not the target. */\n Transitioning: 1,\n /** The screen the user is on. */\n Active: 2,\n} as const;\n\nexport type ActivityStateValue = (typeof ActivityState)[keyof typeof ActivityState];\n\n/**\n * The Fabric name of one of `ExpoRouterToolbarModule`'s views, as `requireNativeView` in\n * `expo-modules-core` computes it. Expo Go runs many projects in one binary and names every view\n * after the one it is running; a build of the app's own has no such suffix.\n *\n * `@ng-native/expo` derives the same name for its own views. The Angular-facing packages do not\n * import each other, and this is three lines.\n */\nfunction expoRouterToolbarView(view: string): string {\n const identifier = (globalThis as { expo?: { __expo_app_identifier__?: string } }).expo\n ?.__expo_app_identifier__;\n return `ViewManagerAdapter_ExpoRouterToolbarModule_${view}${identifier ? `_${identifier}` : ''}`;\n}\n\n/**\n * Ask React Native for react-native-screens' native module, which is what makes it.\n *\n * `ScreensModule` on Android installs, as it is made, the listener that starts a removed screen's\n * transition before its views are unmounted: without it a sheet is emptied and then slides away,\n * and a popped screen leaves as a blank one. React Native makes a module when JavaScript first\n * asks, and react-native-screens asks as its own JavaScript is imported (`fabric/\n * NativeScreensModule`), none of which is imported here. Through the two globals React Native's\n * own `TurboModuleRegistry` reads, in its order, so nothing of React Native is imported either:\n * the second is the only one there is without the bridge.\n */\nfunction loadScreensModule(): void {\n const host = globalThis as {\n __turboModuleProxy?: (name: string) => unknown;\n nativeModuleProxy?: Record<string, unknown>;\n };\n void (host.__turboModuleProxy?.('RNSModule') ?? host.nativeModuleProxy?.['RNSModule']);\n}\n\n/**\n * Call once at startup, before the first navigation.\n *\n * The app must also have `react-native-screens` installed so the native side registers these\n * components; this only teaches the engine the element-to-view-name mapping. A name the native\n * side does not know renders as `UnimplementedNativeView`, not an error. None of its JavaScript\n * is imported - Expo Go happens to bundle the native half, which is why the canary worked before\n * it declared the dependency at all, and why an app that forgets it fails only once it ships.\n */\nexport function registerScreenComponents(): void {\n loadScreensModule();\n for (const [element, [viewName, defaults]] of Object.entries(SCREEN_VIEW_NAMES)) {\n registerViewName(element, viewName, defaults as Record<string, unknown> | undefined);\n }\n // By platform, chosen when the view is looked up: this runs as the app's config is imported,\n // before its `main.ts` has reported the platform.\n // A window of its own on iOS; see `full-window-overlay.ts`. Its fill is the component's.\n registerViewName('full-window-overlay', { ios: 'RNSFullWindowOverlay', android: 'RCTView' });\n for (const [element, [ios, android, defaults]] of Object.entries(TAB_VIEW_NAMES)) {\n registerViewName(element, { ios, android }, defaults as Record<string, unknown>);\n }\n // A screen's bottom toolbar is Expo Router's, which react-native-screens has none of: see\n // `native-toolbar.ts`. Android has no such bar, so the elements are plain views there.\n registerViewName('native-toolbar', {\n ios: expoRouterToolbarView('RouterToolbarHostView'),\n android: 'RCTView',\n });\n registerViewName('native-toolbar-item', {\n ios: expoRouterToolbarView('RouterToolbarItemView'),\n android: 'RCTView',\n });\n // `findHeaderConfig` in `RNSScreen.mm` looks at the screen's direct children and no deeper, so\n // a header a page wrote inside a `safe-area-view` or a component of its own commits beside it.\n // Nothing in `RNSScreen.mm` updates the bar when its config is unmounted, so a header an `@if`\n // takes away leaves a config behind that hides the bar, and one that comes back adopts it.\n // A tab's page with no stack has no screen of its own: past its tab is the screen holding the\n // whole tab bar, so its header stops at the tab.\n registerHoist('native-header', 'screen', { standIn: { hidden: true }, stopAt: ['native-tab'] });\n // The toolbar host is a view of its own, absolute and out of the layout, that finds its screen\n // through its superviews. Written ahead of a page's scroll view it would be the screen's first\n // subview, where UIKit looks for the scroll view a large title collapses against.\n registerHoist('native-toolbar', 'screen');\n // The header config takes header items and nothing else, so one written inside a component of\n // the header commits as the config's child, not inside the component's view.\n registerHoist('native-header-item', 'native-header', { only: true });\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A url string as the commands `Router.navigate()` takes.
|
|
3
|
+
*
|
|
4
|
+
* `navigate` reads a string command as segment text: it escapes the url's escapes a second time,
|
|
5
|
+
* keeps a `;` as part of the segment and writes a named outlet's brackets into the path.
|
|
6
|
+
* `navigateByUrl` and `popTo` parse the string instead, and these commands say what they read.
|
|
7
|
+
*/
|
|
8
|
+
import { UrlSegment, type Router, type UrlTree } from '@angular/router';
|
|
9
|
+
/** One segment as commands: its decoded path, then its matrix parameters if it has any. */
|
|
10
|
+
export declare function segmentCommands(segment: UrlSegment): unknown[];
|
|
11
|
+
/** Whether a path has a matrix parameter `segmentCommands` leaves out. */
|
|
12
|
+
export declare function hasCommandKeyParameters(router: Router, path: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* `tree`, the one `path`'s commands made, with the parameters of the segments written in `path`
|
|
15
|
+
* as written. They are the last segments of `outlet`, under whatever a relative path went up from.
|
|
16
|
+
*/
|
|
17
|
+
export declare function withWrittenParameters(router: Router, tree: UrlTree, path: string, outlet?: string): UrlTree;
|
|
18
|
+
/** The segments of a path's primary outlet, down through every level, decoded. */
|
|
19
|
+
export declare function primarySegments(router: Router, path: string): UrlSegment[];
|
|
20
|
+
/**
|
|
21
|
+
* The commands for a url string's path, its query and fragment already cut off. An empty path is
|
|
22
|
+
* the root, as `navigateByUrl('?q=1')` reads it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function urlCommands(router: Router, path: string): unknown[];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A url string as the commands `Router.navigate()` takes.
|
|
3
|
+
*
|
|
4
|
+
* `navigate` reads a string command as segment text: it escapes the url's escapes a second time,
|
|
5
|
+
* keeps a `;` as part of the segment and writes a named outlet's brackets into the path.
|
|
6
|
+
* `navigateByUrl` and `popTo` parse the string instead, and these commands say what they read.
|
|
7
|
+
*/
|
|
8
|
+
import { PRIMARY_OUTLET, UrlSegment, } from '@angular/router';
|
|
9
|
+
/**
|
|
10
|
+
* Matrix parameter names `navigate` reads as a command rather than as parameters, with no way to
|
|
11
|
+
* escape them. A segment's parameters go in without them, and `withWrittenParameters` puts them
|
|
12
|
+
* back on the tree the commands make.
|
|
13
|
+
*/
|
|
14
|
+
const COMMAND_KEYS = ['outlets', 'segmentPath'];
|
|
15
|
+
/** One segment as commands: its decoded path, then its matrix parameters if it has any. */
|
|
16
|
+
export function segmentCommands(segment) {
|
|
17
|
+
const parameters = Object.fromEntries(Object.entries(segment.parameters).filter(([name]) => !COMMAND_KEYS.includes(name)));
|
|
18
|
+
return Object.keys(parameters).length > 0 ? [segment.path, parameters] : [segment.path];
|
|
19
|
+
}
|
|
20
|
+
/** Whether a path has a matrix parameter `segmentCommands` leaves out. */
|
|
21
|
+
export function hasCommandKeyParameters(router, path) {
|
|
22
|
+
return primarySegments(router, path).some((segment) => COMMAND_KEYS.some((name) => name in segment.parameters));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* `tree`, the one `path`'s commands made, with the parameters of the segments written in `path`
|
|
26
|
+
* as written. They are the last segments of `outlet`, under whatever a relative path went up from.
|
|
27
|
+
*/
|
|
28
|
+
export function withWrittenParameters(router, tree, path, outlet = PRIMARY_OUTLET) {
|
|
29
|
+
const written = primarySegments(router, path).slice(dotsWritten(path));
|
|
30
|
+
const places = [];
|
|
31
|
+
let group = tree.root.children[outlet];
|
|
32
|
+
while (group) {
|
|
33
|
+
group.segments.forEach((_, index) => places.push({ group: group, index }));
|
|
34
|
+
group = group.children[PRIMARY_OUTLET];
|
|
35
|
+
}
|
|
36
|
+
const start = places.length - written.length;
|
|
37
|
+
written.forEach((segment, i) => {
|
|
38
|
+
const place = places[start + i];
|
|
39
|
+
if (!place)
|
|
40
|
+
return;
|
|
41
|
+
const current = place.group.segments[place.index];
|
|
42
|
+
place.group.segments[place.index] = new UrlSegment(current.path, segment.parameters);
|
|
43
|
+
});
|
|
44
|
+
return tree;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* How many `.` and `..` a relative path starts with, counted in the string as written: a decoded
|
|
48
|
+
* `%2E%2E` is a segment.
|
|
49
|
+
*/
|
|
50
|
+
function dotsWritten(path) {
|
|
51
|
+
if (path === '' || path.startsWith('/'))
|
|
52
|
+
return 0;
|
|
53
|
+
const parts = path.split('/');
|
|
54
|
+
const written = parts.findIndex((part) => part !== '.' && part !== '..');
|
|
55
|
+
return written < 0 ? parts.length : written;
|
|
56
|
+
}
|
|
57
|
+
/** The segments of a path's primary outlet, down through every level, decoded. */
|
|
58
|
+
export function primarySegments(router, path) {
|
|
59
|
+
const segments = [];
|
|
60
|
+
let group = router.parseUrl(path).root;
|
|
61
|
+
while (group) {
|
|
62
|
+
segments.push(...group.segments);
|
|
63
|
+
group = group.children[PRIMARY_OUTLET];
|
|
64
|
+
}
|
|
65
|
+
return segments;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The commands for a url string's path, its query and fragment already cut off. An empty path is
|
|
69
|
+
* the root, as `navigateByUrl('?q=1')` reads it.
|
|
70
|
+
*/
|
|
71
|
+
export function urlCommands(router, path) {
|
|
72
|
+
if (path === '' || path.startsWith('/')) {
|
|
73
|
+
return ['/', ...groupCommands(router.parseUrl(path).root)];
|
|
74
|
+
}
|
|
75
|
+
const list = groupCommands(router.parseUrl(path).root);
|
|
76
|
+
// `navigate` splits its first command on `/` and reads `.` and `..` there, and only there. So the
|
|
77
|
+
// dots written as dots go into it together, `['../..', 'x']`, where `['..', '..', 'x']` would look
|
|
78
|
+
// for a segment named `..`.
|
|
79
|
+
const up = dotsWritten(path);
|
|
80
|
+
if (up > 0)
|
|
81
|
+
return [list.slice(0, up).join('/'), ...list.slice(up)];
|
|
82
|
+
// A first segment the url escaped, `a%2Fb` or `%2E%2E`, stays one segment, as `segmentPath`.
|
|
83
|
+
const [first] = list;
|
|
84
|
+
if (typeof first === 'string' && (first.includes('/') || first === '.' || first === '..')) {
|
|
85
|
+
list[0] = { segmentPath: first };
|
|
86
|
+
}
|
|
87
|
+
return list;
|
|
88
|
+
}
|
|
89
|
+
function groupCommands(group) {
|
|
90
|
+
const list = group.segments.flatMap(segmentCommands);
|
|
91
|
+
const outlets = Object.entries(group.children);
|
|
92
|
+
if (outlets.length === 0)
|
|
93
|
+
return list;
|
|
94
|
+
if (outlets.length === 1 && outlets[0][0] === PRIMARY_OUTLET) {
|
|
95
|
+
return [...list, ...groupCommands(outlets[0][1])];
|
|
96
|
+
}
|
|
97
|
+
return [
|
|
98
|
+
...list,
|
|
99
|
+
{ outlets: Object.fromEntries(outlets.map(([name, child]) => [name, groupCommands(child)])) },
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=url-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-commands.js","sourceRoot":"","sources":["../src/url-commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A url string as the commands `Router.navigate()` takes.\n *\n * `navigate` reads a string command as segment text: it escapes the url's escapes a second time,\n * keeps a `;` as part of the segment and writes a named outlet's brackets into the path.\n * `navigateByUrl` and `popTo` parse the string instead, and these commands say what they read.\n */\nimport {\n PRIMARY_OUTLET,\n UrlSegment,\n type Router,\n type UrlSegmentGroup,\n type UrlTree,\n} from '@angular/router';\n\n/**\n * Matrix parameter names `navigate` reads as a command rather than as parameters, with no way to\n * escape them. A segment's parameters go in without them, and `withWrittenParameters` puts them\n * back on the tree the commands make.\n */\nconst COMMAND_KEYS = ['outlets', 'segmentPath'];\n\n/** One segment as commands: its decoded path, then its matrix parameters if it has any. */\nexport function segmentCommands(segment: UrlSegment): unknown[] {\n const parameters = Object.fromEntries(\n Object.entries(segment.parameters).filter(([name]) => !COMMAND_KEYS.includes(name)),\n );\n return Object.keys(parameters).length > 0 ? [segment.path, parameters] : [segment.path];\n}\n\n/** Whether a path has a matrix parameter `segmentCommands` leaves out. */\nexport function hasCommandKeyParameters(router: Router, path: string): boolean {\n return primarySegments(router, path).some((segment) =>\n COMMAND_KEYS.some((name) => name in segment.parameters),\n );\n}\n\n/**\n * `tree`, the one `path`'s commands made, with the parameters of the segments written in `path`\n * as written. They are the last segments of `outlet`, under whatever a relative path went up from.\n */\nexport function withWrittenParameters(\n router: Router,\n tree: UrlTree,\n path: string,\n outlet: string = PRIMARY_OUTLET,\n): UrlTree {\n const written = primarySegments(router, path).slice(dotsWritten(path));\n const places: { group: UrlSegmentGroup; index: number }[] = [];\n let group: UrlSegmentGroup | undefined = tree.root.children[outlet];\n while (group) {\n group.segments.forEach((_, index) => places.push({ group: group!, index }));\n group = group.children[PRIMARY_OUTLET];\n }\n const start = places.length - written.length;\n written.forEach((segment, i) => {\n const place = places[start + i];\n if (!place) return;\n const current = place.group.segments[place.index]!;\n place.group.segments[place.index] = new UrlSegment(current.path, segment.parameters);\n });\n return tree;\n}\n\n/**\n * How many `.` and `..` a relative path starts with, counted in the string as written: a decoded\n * `%2E%2E` is a segment.\n */\nfunction dotsWritten(path: string): number {\n if (path === '' || path.startsWith('/')) return 0;\n const parts = path.split('/');\n const written = parts.findIndex((part) => part !== '.' && part !== '..');\n return written < 0 ? parts.length : written;\n}\n\n/** The segments of a path's primary outlet, down through every level, decoded. */\nexport function primarySegments(router: Router, path: string): UrlSegment[] {\n const segments: UrlSegment[] = [];\n let group: UrlSegmentGroup | undefined = router.parseUrl(path).root;\n while (group) {\n segments.push(...group.segments);\n group = group.children[PRIMARY_OUTLET];\n }\n return segments;\n}\n\n/**\n * The commands for a url string's path, its query and fragment already cut off. An empty path is\n * the root, as `navigateByUrl('?q=1')` reads it.\n */\nexport function urlCommands(router: Router, path: string): unknown[] {\n if (path === '' || path.startsWith('/')) {\n return ['/', ...groupCommands(router.parseUrl(path).root)];\n }\n const list = groupCommands(router.parseUrl(path).root);\n // `navigate` splits its first command on `/` and reads `.` and `..` there, and only there. So the\n // dots written as dots go into it together, `['../..', 'x']`, where `['..', '..', 'x']` would look\n // for a segment named `..`.\n const up = dotsWritten(path);\n if (up > 0) return [list.slice(0, up).join('/'), ...list.slice(up)];\n // A first segment the url escaped, `a%2Fb` or `%2E%2E`, stays one segment, as `segmentPath`.\n const [first] = list;\n if (typeof first === 'string' && (first.includes('/') || first === '.' || first === '..')) {\n list[0] = { segmentPath: first };\n }\n return list;\n}\n\nfunction groupCommands(group: UrlSegmentGroup): unknown[] {\n const list = group.segments.flatMap(segmentCommands);\n const outlets = Object.entries(group.children);\n if (outlets.length === 0) return list;\n if (outlets.length === 1 && outlets[0]![0] === PRIMARY_OUTLET) {\n return [...list, ...groupCommands(outlets[0]![1])];\n }\n return [\n ...list,\n { outlets: Object.fromEntries(outlets.map(([name, child]) => [name, groupCommands(child)])) },\n ];\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-native/router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "@angular/router over native navigation for Angular Native: stack and tab outlets, native headers and links.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"type": "module",
|
|
18
18
|
"main": "dist/index.js",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@ng-native/device": "0.
|
|
21
|
-
"@ng-native/fabric": "0.
|
|
20
|
+
"@ng-native/device": "0.18.0",
|
|
21
|
+
"@ng-native/fabric": "0.18.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"@angular/common": "^22.0.0",
|