@ng-native/router 0.6.0 → 0.7.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/file-routes.js +18 -6
- package/dist/file-routes.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/native-back.d.ts +8 -0
- package/dist/native-back.js +8 -0
- package/dist/native-back.js.map +1 -1
- package/dist/native-navigation.d.ts +11 -1
- package/dist/native-navigation.js +66 -2
- package/dist/native-navigation.js.map +1 -1
- package/dist/native-router-link.js +8 -6
- package/dist/native-router-link.js.map +1 -1
- package/dist/native-stack-outlet.js +9 -2
- package/dist/native-stack-outlet.js.map +1 -1
- package/dist/native-stack-reuse-strategy.js +5 -4
- package/dist/native-stack-reuse-strategy.js.map +1 -1
- package/dist/native-toolbar.d.ts +39 -0
- package/dist/native-toolbar.js +108 -0
- package/dist/native-toolbar.js.map +1 -0
- package/dist/provide-native-router.js +2 -1
- package/dist/provide-native-router.js.map +1 -1
- package/dist/screens.js +23 -0
- package/dist/screens.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-toolbar.js","sourceRoot":"","sources":["../src/native-toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A screen's bottom toolbar, iOS only: the bar a navigation controller floats over the content\n * and the tab bar, where Mail has its filter, its search field and its compose button.\n *\n * ```html\n * <native-toolbar>\n * <native-toolbar-item systemImageName=\"line.3.horizontal.decrease\" (press)=\"filter()\" />\n * <native-toolbar-item type=\"searchBar\" />\n * <native-toolbar-item systemImageName=\"square.and.pencil\" (press)=\"compose()\" />\n * </native-toolbar>\n * ```\n *\n * react-native-screens has no toolbar, so these commit as Expo Router's native toolbar views,\n * `ExpoRouterToolbarModule`'s: the host finds the react-native-screens screen it is inside, gives\n * its view controller the items and shows the toolbar. An app that uses them installs\n * `expo-router` for that native half; none of its JavaScript is imported. Expo Go has it built in.\n *\n * It needs iOS 18. Written anywhere in a screen's page, it is that screen's toolbar, and it goes\n * when the element does. A presented screen has no navigation controller, so no toolbar either.\n */\nimport { Component, DestroyRef, ElementRef, inject, input, output } from '@angular/core';\nimport { type EngineNode, HostEngine } from '@ng-native/fabric';\nimport { ownHost } from './own-host.ts';\nimport { optionalBoolean, optionalNumber } from './transforms.ts';\n\n@Component({\n selector: 'native-toolbar',\n template: '<ng-content />',\n // Out of the screen's layout, as Expo Router's own wrapper styles it: the items are bar button\n // items, which the host hands to the screen rather than draws.\n host: {\n '[style.position]': '\"absolute\"',\n '[style.top]': '0',\n '[style.left]': '0',\n '[style.width]': '1',\n '[style.height]': '1',\n },\n})\nexport class NativeToolbar {\n constructor() {\n ownHost(inject(ElementRef).nativeElement as EngineNode, this.constructor);\n }\n}\n\n/**\n * What a toolbar item is. Unset, a button. `fluidSpacer` takes all the room there is, which\n * pushes what follows to the trailing edge, and `fixedSpacer` is a gap of `width` points.\n * `searchBar` is where the screen's `native-search-bar` goes when iOS 26 integrates it into the\n * toolbar, so buttons can sit either side of it.\n */\nexport type ToolbarItemType = 'normal' | 'fixedSpacer' | 'fluidSpacer' | 'searchBar';\n\n/** The identifier native keys each item by. Any text will do, as long as no two items share it. */\nlet created = 0;\n\n@Component({\n selector: 'native-toolbar-item',\n template: '',\n host: {\n '[identifier]': 'identifier',\n '[type]': 'type()',\n '[title]': 'title()',\n '[systemImageName]': 'systemImageName()',\n '[tintColor]': 'tintColor()',\n '[barButtonItemStyle]': 'barButtonItemStyle()',\n '[hidesSharedBackground]': 'hidesSharedBackground()',\n '[sharesBackground]': 'sharesBackground()',\n '[width]': 'width()',\n '[hidden]': 'hidden()',\n '[disabled]': 'disabled()',\n '[accessibilityLabel]': 'accessibilityLabel()',\n },\n})\nexport class NativeToolbarItem {\n readonly type = input<ToolbarItemType>();\n readonly title = input<string>();\n /** An SF Symbol name. */\n readonly systemImageName = input<string>();\n readonly tintColor = input<string>();\n /** `prominent` is the filled style iOS 26 gives a screen's main action. */\n readonly barButtonItemStyle = input<'plain' | 'prominent'>();\n /** iOS 26: draw this item with no glass behind it. */\n readonly hidesSharedBackground = input(undefined, { transform: optionalBoolean });\n /** iOS 26: whether this item shares its glass with the items beside it, which it does unset. */\n readonly sharesBackground = input(undefined, { transform: optionalBoolean });\n /** The width of a `fixedSpacer`, in points. */\n readonly width = input(undefined, { transform: optionalNumber });\n /** Leave the item out of the toolbar while keeping its place among the others. */\n readonly hidden = input(undefined, { transform: optionalBoolean });\n readonly disabled = input(undefined, { transform: optionalBoolean });\n /** What a screen reader says for a button with a symbol and no title. */\n readonly accessibilityLabel = input<string>();\n\n /** The button was tapped. */\n readonly press = output<void>();\n\n protected readonly identifier = `native-toolbar-item-${created++}`;\n\n constructor() {\n const node = ownHost(inject(ElementRef).nativeElement as EngineNode, NativeToolbarItem);\n const engine = node.host ?? inject(HostEngine);\n inject(DestroyRef).onDestroy(\n engine.setEventListener(node, 'topSelected', () => this.press.emit()),\n );\n }\n}\n"]}
|
|
@@ -18,7 +18,7 @@ import { DestroyRef, ErrorHandler, computed, inject, makeEnvironmentProviders, p
|
|
|
18
18
|
import { ColorScheme, DeepLinks } from '@ng-native/device';
|
|
19
19
|
import { NATIVE_HEADER_DEFAULTS, NATIVE_TAB_DEFAULTS, } from "./native-bar-defaults.js";
|
|
20
20
|
import { followLink, linkAncestry } from "./native-links.js";
|
|
21
|
-
import { NATIVE_INTENT, NativeNavigation, intentOf } from "./native-navigation.js";
|
|
21
|
+
import { NATIVE_INTENT, NativeNavigation, carryIntentAcrossRedirects, intentOf, } from "./native-navigation.js";
|
|
22
22
|
import { NativePlatformLocation } from "./native-platform-location.js";
|
|
23
23
|
import { NativeStackReuseStrategy } from "./native-stack-reuse-strategy.js";
|
|
24
24
|
import { ROUTE_PARKING } from "./route-parking.js";
|
|
@@ -90,6 +90,7 @@ function nativeProviders(parentOf) {
|
|
|
90
90
|
// Without this the router never detaches, so a pushed-away screen is destroyed and rebuilt.
|
|
91
91
|
{ provide: RouteReuseStrategy, useClass: NativeStackReuseStrategy },
|
|
92
92
|
NativeNavigation,
|
|
93
|
+
provideEnvironmentInitializer(carryIntentAcrossRedirects),
|
|
93
94
|
provideEnvironmentInitializer(keepHistoryAcrossReloads),
|
|
94
95
|
];
|
|
95
96
|
if (!parentOf) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provide-native-router.js","sourceRoot":"","sources":["../src/provide-native-router.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Angular's Router, on native navigation: `provideRouter` and the native pieces under it, in one\n * call.\n *\n * `provideNativeRouter(routes, withComponentInputBinding())` takes the same routes and the same\n * router features as `provideRouter` - it calls it - and adds what native needs on top: a\n * `PlatformLocation` over an in-memory history, a `RouteReuseStrategy` that detaches a pushed-away\n * screen instead of destroying it, and `NativeNavigation`. Those come after `provideRouter`'s own\n * providers, so they win over the web defaults without the app having to order anything.\n *\n * Deep links and Android's back button come from `@ng-native/device` and need no wiring: off a\n * device both report nothing, and navigation works either way. The native options - `withLinkParent`,\n * `withHeaderDefaults` and `withTabDefaults` - are passed like any other feature.\n */\nimport { PlatformLocation } from '@angular/common';\nimport {\n NavigationCancel,\n NavigationEnd,\n NavigationError,\n RouteReuseStrategy,\n Router,\n provideRouter,\n type RouterFeatures,\n type Routes,\n} from '@angular/router';\nimport {\n DestroyRef,\n ErrorHandler,\n computed,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n type EnvironmentProviders,\n type InjectionToken,\n type Provider,\n type Signal,\n} from '@angular/core';\nimport { ColorScheme, DeepLinks, type Scheme } from '@ng-native/device';\nimport {\n NATIVE_HEADER_DEFAULTS,\n NATIVE_TAB_DEFAULTS,\n type HeaderDefaults,\n type SchemeDefaults,\n type TabDefaults,\n} from './native-bar-defaults.ts';\nimport { followLink, linkAncestry, type LinkParent } from './native-links.ts';\nimport { NATIVE_INTENT, NativeNavigation, intentOf } from './native-navigation.ts';\nimport { NativePlatformLocation } from './native-platform-location.ts';\nimport { NativeStackReuseStrategy } from './native-stack-reuse-strategy.ts';\nimport { ROUTE_PARKING, type ParkedPage } from './route-parking.ts';\nimport { registerScreenComponents } from './screens.ts';\n\n/** A native-only router option, passed to `provideNativeRouter` beside Angular's own features. */\nexport interface NativeRouterFeature {\n readonly ɵnativeRouter: { readonly linkParent?: LinkParent; readonly providers?: Provider[] };\n}\n\n/**\n * The page a deep link opens on top of, or null to open it alone. Without it a link to\n * `/settings/notifications` opens that page with no Back. See native-links.ts.\n */\nexport function withLinkParent(parentOf: LinkParent): NativeRouterFeature {\n return { ɵnativeRouter: { linkParent: parentOf } };\n}\n\n/**\n * How every `<native-header>` looks when it does not say: its colours, blur, shadow, fonts and\n * light or dark style. A header's own binding always wins.\n *\n * ```ts\n * provideNativeRouter(\n * routes,\n * withHeaderDefaults((scheme) => ({\n * backgroundColor: scheme === 'dark' ? '#101014' : '#f4f4f7',\n * titleColor: scheme === 'dark' ? '#ffffff' : '#101014',\n * color: '#3b6ef5',\n * })),\n * );\n * ```\n *\n * Colours it leaves out still come from `NATIVE_HEADER_PALETTE`.\n */\nexport function withHeaderDefaults(defaults: SchemeDefaults<HeaderDefaults>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [bySchemeProvider(NATIVE_HEADER_DEFAULTS, defaults)] } };\n}\n\n/**\n * How every `<native-tabs-outlet>` and `<native-tab>` looks when it does not say: the tint, the\n * background behind the tabs, the light or dark style, and each tab's bar appearance. An outlet's\n * or a tab's own binding always wins.\n */\nexport function withTabDefaults(defaults: SchemeDefaults<TabDefaults>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [bySchemeProvider(NATIVE_TAB_DEFAULTS, defaults)] } };\n}\n\n/** One signal for the whole app, rather than every bar calling the function again. */\nfunction bySchemeProvider<T>(\n token: InjectionToken<Signal<T>>,\n defaults: SchemeDefaults<T>,\n): Provider {\n return {\n provide: token,\n useFactory: () => {\n if (typeof defaults !== 'function') return computed(() => defaults);\n const scheme = inject(ColorScheme);\n return computed(() => (defaults as (scheme: Scheme) => T)(scheme.current()));\n },\n };\n}\n\nfunction isNative(feature: RouterFeatures | NativeRouterFeature): feature is NativeRouterFeature {\n return 'ɵnativeRouter' in feature;\n}\n\nexport function provideNativeRouter(\n routes: Routes,\n ...features: (RouterFeatures | NativeRouterFeature)[]\n): EnvironmentProviders {\n const angular = features.filter((feature): feature is RouterFeatures => !isNative(feature));\n const native = features.filter(isNative).map((feature) => feature.ɵnativeRouter);\n const parentOf = native.find((feature) => feature.linkParent)?.linkParent;\n return makeEnvironmentProviders([\n provideRouter(routes, ...angular),\n ...nativeProviders(parentOf),\n ...native.flatMap((feature) => feature.providers ?? []),\n ]);\n}\n\nfunction nativeProviders(parentOf: LinkParent | undefined): (Provider | EnvironmentProviders)[] {\n // The engine needs the element-to-view-name mapping before the first navigation renders.\n registerScreenComponents();\n\n const shared = [\n // Without this the router never detaches, so a pushed-away screen is destroyed and rebuilt.\n { provide: RouteReuseStrategy, useClass: NativeStackReuseStrategy },\n NativeNavigation,\n provideEnvironmentInitializer(keepHistoryAcrossReloads),\n ];\n if (!parentOf) {\n return [\n {\n provide: PlatformLocation,\n useFactory: () => new NativePlatformLocation(inject(DeepLinks)),\n },\n ...shared,\n ];\n }\n\n return [\n {\n provide: PlatformLocation,\n // The app launches on the page the link belongs under; the link follows once it is shown.\n // Links while running go through the router below rather than straight into history.\n useFactory: () => {\n const initial = inject(DeepLinks).initialUrl();\n return new NativePlatformLocation({\n initialUrl: () => (initial && linkAncestry(initial, parentOf)[0]) || initial,\n subscribe: () => () => {},\n });\n },\n },\n provideEnvironmentInitializer(() => {\n const router = inject(Router);\n const links = inject(DeepLinks);\n const errors = inject(ErrorHandler);\n // A link nobody awaits: a page that fails to load is reported, as a tab tap's is, rather\n // than left as an unhandled rejection. The app's navigation error handler hears it too.\n const follow = (url: string) =>\n followLink(router, url, parentOf).catch((error: unknown) => errors.handleError(error));\n const initial = links.initialUrl();\n if (initial && parentOf(initial)) {\n const first = router.events.subscribe((event) => {\n if (!(event instanceof NavigationEnd)) return;\n first.unsubscribe();\n void follow(initial);\n });\n }\n // A launch link arrives the way any other does, once `getInitialURL()` settles, which is\n // usually while the router's first navigation is still going: following it then cancels that\n // navigation, and the app opens with no root screen under the link. So links wait for it.\n const settled = new Promise<void>((resolve) => {\n if (router.navigated) return resolve();\n const first = router.events.subscribe((event) => {\n if (!isEnd(event)) return;\n first.unsubscribe();\n resolve();\n });\n });\n links.subscribe((url) => void settled.then(() => follow(url)));\n }),\n ...shared,\n ];\n}\n\n/**\n * A history without its round trips: each page once, reached the way it last was. An app that went\n * from one tab to another and back has a history three entries long and is one page deep, and the\n * app that comes back has no use for the detour: gone through at the speed of a reload, the tab\n * bar is still on its way to the second tab when the third navigation asks for the first.\n */\nfunction direct(pages: ParkedPage[]): ParkedPage[] {\n const route: ParkedPage[] = [];\n for (const page of pages) {\n const before = route.findIndex((one) => one.url === page.url);\n if (before !== -1) route.length = before;\n route.push(page);\n }\n return route;\n}\n\ndeclare const __DEV__: boolean | undefined;\n\n/** A push's animation, with room to spare: 350ms on iOS, about the same on Android. */\nconst PUSH_SETTLES = 450;\n\n/**\n * In development, come back from a reload on the page it left: see `route-parking.ts`.\n *\n * The history a reload left is gone through again once the first navigation has ended, as a\n * launch link is and for the same reason. The hook is what `mount`'s reload waits on.\n */\nfunction keepHistoryAcrossReloads(): void {\n // The bare identifier, so a release build folds the rest away.\n if (typeof __DEV__ === 'undefined' || !__DEV__) return;\n const parking = inject(ROUTE_PARKING);\n if (!parking) return;\n const router = inject(Router);\n const history = inject(PlatformLocation);\n const errors = inject(ErrorHandler);\n const scope = globalThis as {\n __angularNativePark?: () => Promise<void>;\n __angularNativeRestoring?: Promise<void>;\n };\n // A page keeps how it was presented, a sheet or a modal, and nothing else of its navigation:\n // a replace has already happened to the history, and an app's own state may not survive JSON.\n const pages = (): ParkedPage[] =>\n history instanceof NativePlatformLocation\n ? history.ɵpages().map(({ url, state }) => {\n const presentation = intentOf(state)?.presentation;\n return presentation ? { url, presentation } : { url };\n })\n : [{ url: router.url }];\n const park = () => parking.park(direct(pages()));\n scope.__angularNativePark = park;\n\n // `mount` keeps the app out of sight until this settles, so the pages arrive unseen.\n const restoring = parking\n .collect()\n .then(async (parked) => {\n if (!parked) return;\n await new Promise<void>((resolve) => {\n if (router.navigated) return resolve();\n const first = router.events.subscribe((event) => {\n if (!isEnd(event)) return;\n first.unsubscribe();\n resolve();\n });\n });\n let moved = false;\n for (const { url, presentation } of parked) {\n if (url === router.url) continue;\n const state = presentation && { [NATIVE_INTENT]: { stack: 'push', presentation } };\n moved = (await router.navigateByUrl(url, { state })) || moved;\n }\n // The last page is still sliding in when its navigation ends.\n if (moved) await new Promise((resolve) => setTimeout(resolve, PUSH_SETTLES));\n })\n .catch((error: unknown) => errors.handleError(error));\n scope.__angularNativeRestoring = restoring;\n inject(DestroyRef).onDestroy(() => {\n if (scope.__angularNativePark === park) delete scope.__angularNativePark;\n if (scope.__angularNativeRestoring === restoring) delete scope.__angularNativeRestoring;\n });\n}\n\n/** A navigation's last event, whichever way it went. */\nfunction isEnd(event: unknown): boolean {\n return (\n event instanceof NavigationEnd ||\n event instanceof NavigationCancel ||\n event instanceof NavigationError\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"provide-native-router.js","sourceRoot":"","sources":["../src/provide-native-router.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Angular's Router, on native navigation: `provideRouter` and the native pieces under it, in one\n * call.\n *\n * `provideNativeRouter(routes, withComponentInputBinding())` takes the same routes and the same\n * router features as `provideRouter` - it calls it - and adds what native needs on top: a\n * `PlatformLocation` over an in-memory history, a `RouteReuseStrategy` that detaches a pushed-away\n * screen instead of destroying it, and `NativeNavigation`. Those come after `provideRouter`'s own\n * providers, so they win over the web defaults without the app having to order anything.\n *\n * Deep links and Android's back button come from `@ng-native/device` and need no wiring: off a\n * device both report nothing, and navigation works either way. The native options - `withLinkParent`,\n * `withHeaderDefaults` and `withTabDefaults` - are passed like any other feature.\n */\nimport { PlatformLocation } from '@angular/common';\nimport {\n NavigationCancel,\n NavigationEnd,\n NavigationError,\n RouteReuseStrategy,\n Router,\n provideRouter,\n type RouterFeatures,\n type Routes,\n} from '@angular/router';\nimport {\n DestroyRef,\n ErrorHandler,\n computed,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n type EnvironmentProviders,\n type InjectionToken,\n type Provider,\n type Signal,\n} from '@angular/core';\nimport { ColorScheme, DeepLinks, type Scheme } from '@ng-native/device';\nimport {\n NATIVE_HEADER_DEFAULTS,\n NATIVE_TAB_DEFAULTS,\n type HeaderDefaults,\n type SchemeDefaults,\n type TabDefaults,\n} from './native-bar-defaults.ts';\nimport { followLink, linkAncestry, type LinkParent } from './native-links.ts';\nimport {\n NATIVE_INTENT,\n NativeNavigation,\n carryIntentAcrossRedirects,\n intentOf,\n} from './native-navigation.ts';\nimport { NativePlatformLocation } from './native-platform-location.ts';\nimport { NativeStackReuseStrategy } from './native-stack-reuse-strategy.ts';\nimport { ROUTE_PARKING, type ParkedPage } from './route-parking.ts';\nimport { registerScreenComponents } from './screens.ts';\n\n/** A native-only router option, passed to `provideNativeRouter` beside Angular's own features. */\nexport interface NativeRouterFeature {\n readonly ɵnativeRouter: { readonly linkParent?: LinkParent; readonly providers?: Provider[] };\n}\n\n/**\n * The page a deep link opens on top of, or null to open it alone. Without it a link to\n * `/settings/notifications` opens that page with no Back. See native-links.ts.\n */\nexport function withLinkParent(parentOf: LinkParent): NativeRouterFeature {\n return { ɵnativeRouter: { linkParent: parentOf } };\n}\n\n/**\n * How every `<native-header>` looks when it does not say: its colours, blur, shadow, fonts and\n * light or dark style. A header's own binding always wins.\n *\n * ```ts\n * provideNativeRouter(\n * routes,\n * withHeaderDefaults((scheme) => ({\n * backgroundColor: scheme === 'dark' ? '#101014' : '#f4f4f7',\n * titleColor: scheme === 'dark' ? '#ffffff' : '#101014',\n * color: '#3b6ef5',\n * })),\n * );\n * ```\n *\n * Colours it leaves out still come from `NATIVE_HEADER_PALETTE`.\n */\nexport function withHeaderDefaults(defaults: SchemeDefaults<HeaderDefaults>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [bySchemeProvider(NATIVE_HEADER_DEFAULTS, defaults)] } };\n}\n\n/**\n * How every `<native-tabs-outlet>` and `<native-tab>` looks when it does not say: the tint, the\n * background behind the tabs, the light or dark style, and each tab's bar appearance. An outlet's\n * or a tab's own binding always wins.\n */\nexport function withTabDefaults(defaults: SchemeDefaults<TabDefaults>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [bySchemeProvider(NATIVE_TAB_DEFAULTS, defaults)] } };\n}\n\n/** One signal for the whole app, rather than every bar calling the function again. */\nfunction bySchemeProvider<T>(\n token: InjectionToken<Signal<T>>,\n defaults: SchemeDefaults<T>,\n): Provider {\n return {\n provide: token,\n useFactory: () => {\n if (typeof defaults !== 'function') return computed(() => defaults);\n const scheme = inject(ColorScheme);\n return computed(() => (defaults as (scheme: Scheme) => T)(scheme.current()));\n },\n };\n}\n\nfunction isNative(feature: RouterFeatures | NativeRouterFeature): feature is NativeRouterFeature {\n return 'ɵnativeRouter' in feature;\n}\n\nexport function provideNativeRouter(\n routes: Routes,\n ...features: (RouterFeatures | NativeRouterFeature)[]\n): EnvironmentProviders {\n const angular = features.filter((feature): feature is RouterFeatures => !isNative(feature));\n const native = features.filter(isNative).map((feature) => feature.ɵnativeRouter);\n const parentOf = native.find((feature) => feature.linkParent)?.linkParent;\n return makeEnvironmentProviders([\n provideRouter(routes, ...angular),\n ...nativeProviders(parentOf),\n ...native.flatMap((feature) => feature.providers ?? []),\n ]);\n}\n\nfunction nativeProviders(parentOf: LinkParent | undefined): (Provider | EnvironmentProviders)[] {\n // The engine needs the element-to-view-name mapping before the first navigation renders.\n registerScreenComponents();\n\n const shared = [\n // Without this the router never detaches, so a pushed-away screen is destroyed and rebuilt.\n { provide: RouteReuseStrategy, useClass: NativeStackReuseStrategy },\n NativeNavigation,\n provideEnvironmentInitializer(carryIntentAcrossRedirects),\n provideEnvironmentInitializer(keepHistoryAcrossReloads),\n ];\n if (!parentOf) {\n return [\n {\n provide: PlatformLocation,\n useFactory: () => new NativePlatformLocation(inject(DeepLinks)),\n },\n ...shared,\n ];\n }\n\n return [\n {\n provide: PlatformLocation,\n // The app launches on the page the link belongs under; the link follows once it is shown.\n // Links while running go through the router below rather than straight into history.\n useFactory: () => {\n const initial = inject(DeepLinks).initialUrl();\n return new NativePlatformLocation({\n initialUrl: () => (initial && linkAncestry(initial, parentOf)[0]) || initial,\n subscribe: () => () => {},\n });\n },\n },\n provideEnvironmentInitializer(() => {\n const router = inject(Router);\n const links = inject(DeepLinks);\n const errors = inject(ErrorHandler);\n // A link nobody awaits: a page that fails to load is reported, as a tab tap's is, rather\n // than left as an unhandled rejection. The app's navigation error handler hears it too.\n const follow = (url: string) =>\n followLink(router, url, parentOf).catch((error: unknown) => errors.handleError(error));\n const initial = links.initialUrl();\n if (initial && parentOf(initial)) {\n const first = router.events.subscribe((event) => {\n if (!(event instanceof NavigationEnd)) return;\n first.unsubscribe();\n void follow(initial);\n });\n }\n // A launch link arrives the way any other does, once `getInitialURL()` settles, which is\n // usually while the router's first navigation is still going: following it then cancels that\n // navigation, and the app opens with no root screen under the link. So links wait for it.\n const settled = new Promise<void>((resolve) => {\n if (router.navigated) return resolve();\n const first = router.events.subscribe((event) => {\n if (!isEnd(event)) return;\n first.unsubscribe();\n resolve();\n });\n });\n links.subscribe((url) => void settled.then(() => follow(url)));\n }),\n ...shared,\n ];\n}\n\n/**\n * A history without its round trips: each page once, reached the way it last was. An app that went\n * from one tab to another and back has a history three entries long and is one page deep, and the\n * app that comes back has no use for the detour: gone through at the speed of a reload, the tab\n * bar is still on its way to the second tab when the third navigation asks for the first.\n */\nfunction direct(pages: ParkedPage[]): ParkedPage[] {\n const route: ParkedPage[] = [];\n for (const page of pages) {\n const before = route.findIndex((one) => one.url === page.url);\n if (before !== -1) route.length = before;\n route.push(page);\n }\n return route;\n}\n\ndeclare const __DEV__: boolean | undefined;\n\n/** A push's animation, with room to spare: 350ms on iOS, about the same on Android. */\nconst PUSH_SETTLES = 450;\n\n/**\n * In development, come back from a reload on the page it left: see `route-parking.ts`.\n *\n * The history a reload left is gone through again once the first navigation has ended, as a\n * launch link is and for the same reason. The hook is what `mount`'s reload waits on.\n */\nfunction keepHistoryAcrossReloads(): void {\n // The bare identifier, so a release build folds the rest away.\n if (typeof __DEV__ === 'undefined' || !__DEV__) return;\n const parking = inject(ROUTE_PARKING);\n if (!parking) return;\n const router = inject(Router);\n const history = inject(PlatformLocation);\n const errors = inject(ErrorHandler);\n const scope = globalThis as {\n __angularNativePark?: () => Promise<void>;\n __angularNativeRestoring?: Promise<void>;\n };\n // A page keeps how it was presented, a sheet or a modal, and nothing else of its navigation:\n // a replace has already happened to the history, and an app's own state may not survive JSON.\n const pages = (): ParkedPage[] =>\n history instanceof NativePlatformLocation\n ? history.ɵpages().map(({ url, state }) => {\n const presentation = intentOf(state)?.presentation;\n return presentation ? { url, presentation } : { url };\n })\n : [{ url: router.url }];\n const park = () => parking.park(direct(pages()));\n scope.__angularNativePark = park;\n\n // `mount` keeps the app out of sight until this settles, so the pages arrive unseen.\n const restoring = parking\n .collect()\n .then(async (parked) => {\n if (!parked) return;\n await new Promise<void>((resolve) => {\n if (router.navigated) return resolve();\n const first = router.events.subscribe((event) => {\n if (!isEnd(event)) return;\n first.unsubscribe();\n resolve();\n });\n });\n let moved = false;\n for (const { url, presentation } of parked) {\n if (url === router.url) continue;\n const state = presentation && { [NATIVE_INTENT]: { stack: 'push', presentation } };\n moved = (await router.navigateByUrl(url, { state })) || moved;\n }\n // The last page is still sliding in when its navigation ends.\n if (moved) await new Promise((resolve) => setTimeout(resolve, PUSH_SETTLES));\n })\n .catch((error: unknown) => errors.handleError(error));\n scope.__angularNativeRestoring = restoring;\n inject(DestroyRef).onDestroy(() => {\n if (scope.__angularNativePark === park) delete scope.__angularNativePark;\n if (scope.__angularNativeRestoring === restoring) delete scope.__angularNativeRestoring;\n });\n}\n\n/** A navigation's last event, whichever way it went. */\nfunction isEnd(event: unknown): boolean {\n return (\n event instanceof NavigationEnd ||\n event instanceof NavigationCancel ||\n event instanceof NavigationError\n );\n}\n"]}
|
package/dist/screens.js
CHANGED
|
@@ -80,6 +80,19 @@ export const ActivityState = {
|
|
|
80
80
|
/** The screen the user is on. */
|
|
81
81
|
Active: 2,
|
|
82
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* The Fabric name of one of `ExpoRouterToolbarModule`'s views, as `requireNativeView` in
|
|
85
|
+
* `expo-modules-core` computes it. Expo Go runs many projects in one binary and names every view
|
|
86
|
+
* after the one it is running; a build of the app's own has no such suffix.
|
|
87
|
+
*
|
|
88
|
+
* `@ng-native/expo` derives the same name for its own views. The Angular-facing packages do not
|
|
89
|
+
* import each other, and this is three lines.
|
|
90
|
+
*/
|
|
91
|
+
function expoRouterToolbarView(view) {
|
|
92
|
+
const identifier = globalThis.expo
|
|
93
|
+
?.__expo_app_identifier__;
|
|
94
|
+
return `ViewManagerAdapter_ExpoRouterToolbarModule_${view}${identifier ? `_${identifier}` : ''}`;
|
|
95
|
+
}
|
|
83
96
|
/**
|
|
84
97
|
* Call once at startup, before the first navigation.
|
|
85
98
|
*
|
|
@@ -100,6 +113,16 @@ export function registerScreenComponents() {
|
|
|
100
113
|
for (const [element, [ios, android, defaults]] of Object.entries(TAB_VIEW_NAMES)) {
|
|
101
114
|
registerViewName(element, { ios, android }, defaults);
|
|
102
115
|
}
|
|
116
|
+
// A screen's bottom toolbar is Expo Router's, which react-native-screens has none of: see
|
|
117
|
+
// `native-toolbar.ts`. Android has no such bar, so the elements are plain views there.
|
|
118
|
+
registerViewName('native-toolbar', {
|
|
119
|
+
ios: expoRouterToolbarView('RouterToolbarHostView'),
|
|
120
|
+
android: 'RCTView',
|
|
121
|
+
});
|
|
122
|
+
registerViewName('native-toolbar-item', {
|
|
123
|
+
ios: expoRouterToolbarView('RouterToolbarItemView'),
|
|
124
|
+
android: 'RCTView',
|
|
125
|
+
});
|
|
103
126
|
// `findHeaderConfig` in `RNSScreen.mm` looks at the screen's direct children and no deeper, so
|
|
104
127
|
// a header a page wrote inside a `safe-area-view` or a component of its own commits beside it.
|
|
105
128
|
// Nothing in `RNSScreen.mm` updates the bar when its config is unmounted, so a header an `@if`
|
package/dist/screens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screens.js","sourceRoot":"","sources":["../src/screens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEpE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA0D;IACtF,qDAAqD;IACrD,qBAAqB,EAAE,CAAC,gBAAgB,CAAC;IACzC,oFAAoF;IACpF,MAAM,EAAE,CAAC,WAAW,CAAC;IACrB,eAAe,EAAE;QACf,4BAA4B;QAC5B;YACE,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,MAAM;YACb,aAAa,EAAE,KAAK;YACpB,cAAc,EAAE,eAAe;YAC/B,UAAU,EAAE,QAAQ;SACrB;KACF;IACD,+FAA+F;IAC/F,mBAAmB,EAAE,CAAC,cAAc,CAAC;IACrC,oBAAoB,EAAE;QACpB,6BAA6B;QAC7B,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE;KACzE;IACD,gGAAgG;IAChG,wEAAwE;IACxE,uBAAuB,EAAE,CAAC,iBAAiB,CAAC;IAC5C,oBAAoB,EAAE,CAAC,iBAAiB,CAAC;CAC1C,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,cAAc,GAAsE;IACxF,oBAAoB,EAAE;QACpB,gBAAgB;QAChB,oBAAoB;QACpB,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;KAC3C;IACD,YAAY,EAAE;QACZ,kBAAkB;QAClB,sBAAsB;QACtB,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;KACjE;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,gDAAgD;IAChD,QAAQ,EAAE,CAAC;IACX,oDAAoD;IACpD,aAAa,EAAE,CAAC;IAChB,iCAAiC;IACjC,MAAM,EAAE,CAAC;CACD,CAAC;AAIX;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB;IACtC,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAChF,gBAAgB,CAAC,OAAO,EAAE,QAAQ,EAAE,QAA+C,CAAC,CAAC;IACvF,CAAC;IACD,6FAA6F;IAC7F,kDAAkD;IAClD,yFAAyF;IACzF,gBAAgB,CAAC,qBAAqB,EAAE,EAAE,GAAG,EAAE,sBAAsB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7F,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QACjF,gBAAgB,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,QAAmC,CAAC,CAAC;IACnF,CAAC;IACD,+FAA+F;IAC/F,+FAA+F;IAC/F,+FAA+F;IAC/F,2FAA2F;IAC3F,aAAa,CAAC,eAAe,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AAC1E,CAAC","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 * 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 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 // `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 registerHoist('native-header', 'screen', { standIn: { hidden: 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 // 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 * 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 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 registerHoist('native-header', 'screen', { standIn: { hidden: true } });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-native/router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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.7.0",
|
|
21
|
+
"@ng-native/fabric": "0.7.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"@angular/common": "^22.0.0",
|