@ng-native/router 0.7.0 → 0.8.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.
@@ -47,10 +47,19 @@ export declare class NativeBack {
47
47
  popToRoot(): Promise<boolean>;
48
48
  /**
49
49
  * Take the screens under the top of the innermost stack in front that has any off it, leaving
50
- * the top one: a reset to the url already showing, which the router skips. False when no stack
51
- * in front had any.
50
+ * the top one: a reset that lands on the screen already on top, which no stack activates
51
+ * anything for. False when no stack in front had any.
52
52
  */
53
53
  resetToTop(): boolean;
54
+ /** The id of the last navigation a stack put a screen on top for. */
55
+ private lastStacked;
56
+ /** A stack put a screen on top, a new one or one it kept, for the navigation with that id. */
57
+ stacked(navigation: number | undefined): void;
58
+ /**
59
+ * Whether a stack put a screen on top for the navigation with that id. One that put none left
60
+ * the screen on top where it was, as a navigation to it with another query does.
61
+ */
62
+ stackedIn(navigation: number): boolean;
54
63
  /** Pop the innermost stack in front that has a screen at `url` below its top, down to it. */
55
64
  popTo(url: string): Promise<boolean>;
56
65
  /**
@@ -71,12 +71,26 @@ export class NativeBack {
71
71
  }
72
72
  /**
73
73
  * Take the screens under the top of the innermost stack in front that has any off it, leaving
74
- * the top one: a reset to the url already showing, which the router skips. False when no stack
75
- * in front had any.
74
+ * the top one: a reset that lands on the screen already on top, which no stack activates
75
+ * anything for. False when no stack in front had any.
76
76
  */
77
77
  resetToTop() {
78
78
  return [...this.stacks].reverse().some((stack) => stack.showing() && stack.dropUnderTop());
79
79
  }
80
+ /** The id of the last navigation a stack put a screen on top for. */
81
+ lastStacked;
82
+ /** A stack put a screen on top, a new one or one it kept, for the navigation with that id. */
83
+ stacked(navigation) {
84
+ if (navigation !== undefined)
85
+ this.lastStacked = navigation;
86
+ }
87
+ /**
88
+ * Whether a stack put a screen on top for the navigation with that id. One that put none left
89
+ * the screen on top where it was, as a navigation to it with another query does.
90
+ */
91
+ stackedIn(navigation) {
92
+ return this.lastStacked === navigation;
93
+ }
80
94
  /** Pop the innermost stack in front that has a screen at `url` below its top, down to it. */
81
95
  popTo(url) {
82
96
  for (const stack of [...this.stacks].reverse()) {
@@ -1 +1 @@
1
- {"version":3,"file":"native-back.js","sourceRoot":"","sources":["../src/native-back.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Who answers a back: Android's hardware button, and `NativeNavigation.back()`.\n *\n * Every outlet offers an answer, and the one in front takes it. Each answer is also handed to\n * `HardwareBack` directly, where React Native asks the newest first. An outlet always subscribes\n * after the outlet it sits inside, so that order runs from the innermost outlet out, and a\n * screen's own handler, subscribed after its outlet, still outranks it. `back()` asks the outlets\n * in that same order, without the screens' own handlers: those are for the button.\n *\n * Newest first is not enough on its own. A stack in a tab behind the one in front, or under a\n * screen pushed over the whole tab bar, is still subscribed, so each answer first checks that\n * its outlet is showing what the router is showing.\n */\nimport { Service, inject } from '@angular/core';\nimport type { ActivatedRoute, Router } from '@angular/router';\nimport { HardwareBack } from '@ng-native/device';\n\n/** What a stack offers `NativeNavigation` beyond a back: going down it several screens at once. */\nexport interface PoppableStack {\n /** Whether this stack is part of what the router shows now. */\n showing(): boolean;\n /** Pop to its first screen, or null when it is showing only that one. */\n popToRoot(): Promise<boolean> | null;\n /** Pop to the screen showing `url`, or null when no screen below the top shows it. */\n popTo(url: string): Promise<boolean> | null;\n /** Take every screen under the top off at once, or false when it is showing only that one. */\n dropUnderTop(): boolean;\n}\n\n/**\n * What a tab bar offers `NativeNavigation` for a push into one of its tabs from outside it. A tab\n * nobody has opened has no stack yet, and a page pushed into it would be the stack's first\n * screen, with nothing under it to go back to.\n */\nexport interface TabBar {\n /** The url of the tab `url` is a page inside, when that tab has not been opened. */\n unopenedTabOf(url: string): string | null;\n /** Whether `url` is a tab other than the one in front, or a page inside one. */\n behind(url: string): boolean;\n}\n\n@Service()\nexport class NativeBack {\n private readonly hardwareBack = inject(HardwareBack);\n /** Oldest first, as `HardwareBack` holds them. */\n private readonly answers: BackAnswer[] = [];\n /** Oldest first, and so outermost first, as the answers are. */\n private readonly stacks: PoppableStack[] = [];\n\n /** Oldest first. */\n private readonly tabBars: TabBar[] = [];\n\n /** Offer a tab bar's unopened tabs to a push into one. Returns an unsubscribe. */\n addTabBar(bar: TabBar): () => void {\n this.tabBars.push(bar);\n return () => {\n const index = this.tabBars.indexOf(bar);\n if (index !== -1) this.tabBars.splice(index, 1);\n };\n }\n\n /** The url of the unopened tab `url` is a page inside, or null: see `TabBar`. */\n unopenedTabOf(url: string): string | null {\n for (const bar of this.tabBars) {\n const root = bar.unopenedTabOf(url);\n if (root) return root;\n }\n return null;\n }\n\n /** Whether `url` belongs to a tab that is not the one in front. */\n inTabBehind(url: string): boolean {\n return this.tabBars.some((bar) => bar.behind(url));\n }\n\n /**\n * Whether the app's own stack takes a page presented over whatever is showing. Set by the root\n * stack outlet for as long as there is one: see `presented-route.ts`.\n */\n presents = false;\n\n /** Offer a stack for popping several screens at once. Returns an unsubscribe. */\n addStack(stack: PoppableStack): () => void {\n this.stacks.push(stack);\n return () => {\n const index = this.stacks.indexOf(stack);\n if (index !== -1) this.stacks.splice(index, 1);\n };\n }\n\n /** Pop the innermost stack in front that is deeper than one screen, to its first. */\n popToRoot(): Promise<boolean> {\n for (const stack of [...this.stacks].reverse()) {\n if (!stack.showing()) continue;\n const popped = stack.popToRoot();\n if (popped) return popped;\n }\n return Promise.resolve(false);\n }\n\n /**\n * Take the screens under the top of the innermost stack in front that has any off it, leaving\n * the top one: a reset to the url already showing, which the router skips. False when no stack\n * in front had any.\n */\n resetToTop(): boolean {\n return [...this.stacks].reverse().some((stack) => stack.showing() && stack.dropUnderTop());\n }\n\n /** Pop the innermost stack in front that has a screen at `url` below its top, down to it. */\n popTo(url: string): Promise<boolean> {\n for (const stack of [...this.stacks].reverse()) {\n if (!stack.showing()) continue;\n const popped = stack.popTo(url);\n if (popped) return popped;\n }\n return Promise.resolve(false);\n }\n\n /**\n * Offer an outlet's answer to a back. It returns whether it took the back, and false lets the\n * next one out try. Returns an unsubscribe.\n */\n handle(answer: BackAnswer): () => void {\n this.answers.push(answer);\n const stop = this.hardwareBack.handle(() => answer('button'));\n return () => {\n stop();\n const index = this.answers.indexOf(answer);\n if (index !== -1) this.answers.splice(index, 1);\n };\n }\n\n /** Go back as the button would, innermost outlet first. False when none had anywhere to go. */\n back(): boolean {\n return [...this.answers].reverse().some((answer) => answer('app'));\n }\n}\n\n/**\n * An outlet's answer to a back, told where it came from: Android's button, which is the platform's\n * own dismissal and a screen may refuse, or the app's `NativeNavigation.back()`, which it may not.\n */\nexport type BackAnswer = (from: 'button' | 'app') => boolean;\n\n/**\n * Whether a route is part of what the router shows now, rather than a subtree the reuse strategy\n * detached and is keeping for later: a tab behind, or a screen covered by one pushed over it.\n */\nexport function isShowing(router: Router, route: ActivatedRoute | null): boolean {\n if (!route) return false;\n const visit = (node: ActivatedRoute): boolean => node === route || node.children.some(visit);\n return visit(router.routerState.root);\n}\n"]}
1
+ {"version":3,"file":"native-back.js","sourceRoot":"","sources":["../src/native-back.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Who answers a back: Android's hardware button, and `NativeNavigation.back()`.\n *\n * Every outlet offers an answer, and the one in front takes it. Each answer is also handed to\n * `HardwareBack` directly, where React Native asks the newest first. An outlet always subscribes\n * after the outlet it sits inside, so that order runs from the innermost outlet out, and a\n * screen's own handler, subscribed after its outlet, still outranks it. `back()` asks the outlets\n * in that same order, without the screens' own handlers: those are for the button.\n *\n * Newest first is not enough on its own. A stack in a tab behind the one in front, or under a\n * screen pushed over the whole tab bar, is still subscribed, so each answer first checks that\n * its outlet is showing what the router is showing.\n */\nimport { Service, inject } from '@angular/core';\nimport type { ActivatedRoute, Router } from '@angular/router';\nimport { HardwareBack } from '@ng-native/device';\n\n/** What a stack offers `NativeNavigation` beyond a back: going down it several screens at once. */\nexport interface PoppableStack {\n /** Whether this stack is part of what the router shows now. */\n showing(): boolean;\n /** Pop to its first screen, or null when it is showing only that one. */\n popToRoot(): Promise<boolean> | null;\n /** Pop to the screen showing `url`, or null when no screen below the top shows it. */\n popTo(url: string): Promise<boolean> | null;\n /** Take every screen under the top off at once, or false when it is showing only that one. */\n dropUnderTop(): boolean;\n}\n\n/**\n * What a tab bar offers `NativeNavigation` for a push into one of its tabs from outside it. A tab\n * nobody has opened has no stack yet, and a page pushed into it would be the stack's first\n * screen, with nothing under it to go back to.\n */\nexport interface TabBar {\n /** The url of the tab `url` is a page inside, when that tab has not been opened. */\n unopenedTabOf(url: string): string | null;\n /** Whether `url` is a tab other than the one in front, or a page inside one. */\n behind(url: string): boolean;\n}\n\n@Service()\nexport class NativeBack {\n private readonly hardwareBack = inject(HardwareBack);\n /** Oldest first, as `HardwareBack` holds them. */\n private readonly answers: BackAnswer[] = [];\n /** Oldest first, and so outermost first, as the answers are. */\n private readonly stacks: PoppableStack[] = [];\n\n /** Oldest first. */\n private readonly tabBars: TabBar[] = [];\n\n /** Offer a tab bar's unopened tabs to a push into one. Returns an unsubscribe. */\n addTabBar(bar: TabBar): () => void {\n this.tabBars.push(bar);\n return () => {\n const index = this.tabBars.indexOf(bar);\n if (index !== -1) this.tabBars.splice(index, 1);\n };\n }\n\n /** The url of the unopened tab `url` is a page inside, or null: see `TabBar`. */\n unopenedTabOf(url: string): string | null {\n for (const bar of this.tabBars) {\n const root = bar.unopenedTabOf(url);\n if (root) return root;\n }\n return null;\n }\n\n /** Whether `url` belongs to a tab that is not the one in front. */\n inTabBehind(url: string): boolean {\n return this.tabBars.some((bar) => bar.behind(url));\n }\n\n /**\n * Whether the app's own stack takes a page presented over whatever is showing. Set by the root\n * stack outlet for as long as there is one: see `presented-route.ts`.\n */\n presents = false;\n\n /** Offer a stack for popping several screens at once. Returns an unsubscribe. */\n addStack(stack: PoppableStack): () => void {\n this.stacks.push(stack);\n return () => {\n const index = this.stacks.indexOf(stack);\n if (index !== -1) this.stacks.splice(index, 1);\n };\n }\n\n /** Pop the innermost stack in front that is deeper than one screen, to its first. */\n popToRoot(): Promise<boolean> {\n for (const stack of [...this.stacks].reverse()) {\n if (!stack.showing()) continue;\n const popped = stack.popToRoot();\n if (popped) return popped;\n }\n return Promise.resolve(false);\n }\n\n /**\n * Take the screens under the top of the innermost stack in front that has any off it, leaving\n * the top one: a reset that lands on the screen already on top, which no stack activates\n * anything for. False when no stack in front had any.\n */\n resetToTop(): boolean {\n return [...this.stacks].reverse().some((stack) => stack.showing() && stack.dropUnderTop());\n }\n\n /** The id of the last navigation a stack put a screen on top for. */\n private lastStacked: number | undefined;\n\n /** A stack put a screen on top, a new one or one it kept, for the navigation with that id. */\n stacked(navigation: number | undefined): void {\n if (navigation !== undefined) this.lastStacked = navigation;\n }\n\n /**\n * Whether a stack put a screen on top for the navigation with that id. One that put none left\n * the screen on top where it was, as a navigation to it with another query does.\n */\n stackedIn(navigation: number): boolean {\n return this.lastStacked === navigation;\n }\n\n /** Pop the innermost stack in front that has a screen at `url` below its top, down to it. */\n popTo(url: string): Promise<boolean> {\n for (const stack of [...this.stacks].reverse()) {\n if (!stack.showing()) continue;\n const popped = stack.popTo(url);\n if (popped) return popped;\n }\n return Promise.resolve(false);\n }\n\n /**\n * Offer an outlet's answer to a back. It returns whether it took the back, and false lets the\n * next one out try. Returns an unsubscribe.\n */\n handle(answer: BackAnswer): () => void {\n this.answers.push(answer);\n const stop = this.hardwareBack.handle(() => answer('button'));\n return () => {\n stop();\n const index = this.answers.indexOf(answer);\n if (index !== -1) this.answers.splice(index, 1);\n };\n }\n\n /** Go back as the button would, innermost outlet first. False when none had anywhere to go. */\n back(): boolean {\n return [...this.answers].reverse().some((answer) => answer('app'));\n }\n}\n\n/**\n * An outlet's answer to a back, told where it came from: Android's button, which is the platform's\n * own dismissal and a screen may refuse, or the app's `NativeNavigation.back()`, which it may not.\n */\nexport type BackAnswer = (from: 'button' | 'app') => boolean;\n\n/**\n * Whether a route is part of what the router shows now, rather than a subtree the reuse strategy\n * detached and is keeping for later: a tab behind, or a screen covered by one pushed over it.\n */\nexport function isShowing(router: Router, route: ActivatedRoute | null): boolean {\n if (!route) return false;\n const visit = (node: ActivatedRoute): boolean => node === route || node.children.some(visit);\n return visit(router.routerState.root);\n}\n"]}
@@ -29,8 +29,9 @@ export declare function navigationIntent(router: object, navigation: Pick<Naviga
29
29
  * Hand a navigation's intent on to the one its guard redirects it to. The router schedules that
30
30
  * navigation as soon as it has reported the cancel, so it takes the next id.
31
31
  *
32
- * A reset to the url already showing, its own or the one a guard sends it to, is one the router
33
- * skips: no outlet activates anything for it, so the stack is reset here, to the screen on top.
32
+ * A reset that lands on the screen already on top, its own url or the one a redirect sends it to,
33
+ * is one no outlet activates anything for: the router skips the url already showing, and reuses
34
+ * the screen for another url of it. So the stack is reset here, to the screen on top.
34
35
  */
35
36
  export declare function carryIntentAcrossRedirects(): void;
36
37
  export declare class NativeNavigation {
@@ -54,8 +54,9 @@ export function navigationIntent(router, navigation) {
54
54
  * Hand a navigation's intent on to the one its guard redirects it to. The router schedules that
55
55
  * navigation as soon as it has reported the cancel, so it takes the next id.
56
56
  *
57
- * A reset to the url already showing, its own or the one a guard sends it to, is one the router
58
- * skips: no outlet activates anything for it, so the stack is reset here, to the screen on top.
57
+ * A reset that lands on the screen already on top, its own url or the one a redirect sends it to,
58
+ * is one no outlet activates anything for: the router skips the url already showing, and reuses
59
+ * the screen for another url of it. So the stack is reset here, to the screen on top.
59
60
  */
60
61
  export function carryIntentAcrossRedirects() {
61
62
  const router = inject(Router);
@@ -65,9 +66,7 @@ export function carryIntentAcrossRedirects() {
65
66
  carryPast(router, event.id);
66
67
  return;
67
68
  }
68
- if (event instanceof NavigationSkipped &&
69
- event.code === NavigationSkippedCode.IgnoredSameUrlNavigation &&
70
- intentAt(router, event.id)?.stack === 'reset') {
69
+ if (keptTop(event, outlets) && intentAt(router, event.id)?.stack === 'reset') {
71
70
  outlets.resetToTop();
72
71
  }
73
72
  if (ended(event) && redirected.get(router)?.id === event.id)
@@ -75,6 +74,17 @@ export function carryIntentAcrossRedirects() {
75
74
  });
76
75
  inject(DestroyRef).onDestroy(() => events.unsubscribe());
77
76
  }
77
+ /**
78
+ * Whether the navigation `event` ends left the screen on top where it was: one the router skipped
79
+ * for the url already showing, or one no stack put a screen on top for, such as a url with another
80
+ * query, or one a redirect sends to the page on top.
81
+ */
82
+ function keptTop(event, outlets) {
83
+ if (event instanceof NavigationSkipped) {
84
+ return event.code === NavigationSkippedCode.IgnoredSameUrlNavigation;
85
+ }
86
+ return event instanceof NavigationEnd && !outlets.stackedIn(event.id);
87
+ }
78
88
  /** The intent of the navigation in progress, when it is the one with `id`. */
79
89
  function intentAt(router, id) {
80
90
  const navigation = router.currentNavigation();
@@ -1 +1 @@
1
- {"version":3,"file":"native-navigation.js","sourceRoot":"","sources":["../src/native-navigation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The typed facade over `Router` for the intents a URL cannot express (ADR 0003).\n *\n * Angular's `Router` stays the single source of truth: each of these is a line over\n * `router.navigate`, setting `replaceUrl` and a presentation on `NavigationExtras.state`. Deep\n * links, guards and resolvers keep working because it is still the Router, and because state\n * rides in history a back restores the presentation the screen was opened with.\n *\n * A navigation service that owns the stack was rejected: it either re-implements guards,\n * resolvers and deep linking, or it drifts from the URL, and once the stack is not derived from\n * router state the two can disagree.\n *\n * No decorators, so tests can import it at runtime and so it can be provided with `useClass`,\n * exactly as `NativePlatformLocation` and `NativeStackReuseStrategy` are.\n */\nimport { DestroyRef, inject } from '@angular/core';\nimport {\n NavigationCancel,\n NavigationCancellationCode,\n NavigationEnd,\n NavigationError,\n NavigationSkipped,\n NavigationSkippedCode,\n Router,\n type Navigation,\n type NavigationExtras,\n} from '@angular/router';\nimport { NativeBack } from './native-back.ts';\nimport type { ScreenPresentation, StackPresentation } from './screen-presentation.ts';\nimport { leavingPresented, presentedCommands } from './presented-route.ts';\n\n/** What `Router` takes: a url string, or the array form with segments and params. */\nexport type NavigationCommands = string | readonly unknown[];\n\n/**\n * Where the intent rides. `NavigationExtras.state` is the app's own object, so ours sits under\n * one reserved key rather than spread through it.\n */\nexport const NATIVE_INTENT = 'ɵnativeStack';\n\n/** What a navigation asks the outlet to do with the stack, over and above rendering the route. */\nexport interface NativeIntent {\n /** `replace` drops the screen it supersedes; `reset` empties the stack first. */\n readonly stack?: 'push' | 'replace' | 'reset';\n readonly presentation?: ScreenPresentation;\n}\n\nexport interface NativeNavigationOptions extends NavigationExtras {\n /** How the screen arrives: presentation, animation, gesture and sheet props. */\n presentation?: ScreenPresentation;\n}\n\nexport interface PresentOptions extends NativeNavigationOptions {\n /** Shorthand for `presentation.stackPresentation`. Defaults to `modal`. */\n as?: StackPresentation;\n}\n\n/** A url string up to its query or fragment. */\nconst pathOf = (url: string): string => url.split(/[?#]/, 1)[0]!;\n\n/** Read the intent off a navigation's state, if it carries one. */\nexport function intentOf(state: unknown): NativeIntent | null {\n if (!state || typeof state !== 'object') return null;\n const intent = (state as Record<string, unknown>)[NATIVE_INTENT];\n return intent && typeof intent === 'object' ? (intent as NativeIntent) : null;\n}\n\n/**\n * The intent of a navigation a guard redirected, for the navigation the redirect starts.\n *\n * The router starts a new navigation for a guard's `UrlTree`, keeping `replaceUrl` but not\n * `state`, so a reset to a page that sends a signed-out user to sign in would push the sign-in\n * page over the stack it was meant to clear. Held for that one navigation by its id, which no\n * later navigation shares.\n */\nconst redirected = new WeakMap<object, { readonly id: number; readonly intent: NativeIntent }>();\n\n/** What a navigation asks of the stack: its own intent, or the one it was redirected from. */\nexport function navigationIntent(\n router: object,\n navigation: Pick<Navigation, 'id' | 'extras'> | null | undefined,\n): NativeIntent | null {\n if (!navigation) return null;\n const own = intentOf(navigation.extras.state);\n if (own) return own;\n const carried = redirected.get(router);\n return carried?.id === navigation.id ? carried.intent : null;\n}\n\n/**\n * Hand a navigation's intent on to the one its guard redirects it to. The router schedules that\n * navigation as soon as it has reported the cancel, so it takes the next id.\n *\n * A reset to the url already showing, its own or the one a guard sends it to, is one the router\n * skips: no outlet activates anything for it, so the stack is reset here, to the screen on top.\n */\nexport function carryIntentAcrossRedirects(): void {\n const router = inject(Router);\n const outlets = inject(NativeBack);\n const events = router.events.subscribe((event) => {\n if (event instanceof NavigationCancel && event.code === NavigationCancellationCode.Redirect) {\n carryPast(router, event.id);\n return;\n }\n if (\n event instanceof NavigationSkipped &&\n event.code === NavigationSkippedCode.IgnoredSameUrlNavigation &&\n intentAt(router, event.id)?.stack === 'reset'\n ) {\n outlets.resetToTop();\n }\n if (ended(event) && redirected.get(router)?.id === event.id) redirected.delete(router);\n });\n inject(DestroyRef).onDestroy(() => events.unsubscribe());\n}\n\n/** The intent of the navigation in progress, when it is the one with `id`. */\nfunction intentAt(router: Router, id: number): NativeIntent | null {\n const navigation = router.currentNavigation();\n return navigation?.id === id ? navigationIntent(router, navigation) : null;\n}\n\n/** Hold the intent of the navigation a guard redirected for the one the redirect starts. */\nfunction carryPast(router: Router, id: number): void {\n const intent = intentAt(router, id);\n if (intent) redirected.set(router, { id: id + 1, intent });\n else redirected.delete(router);\n}\n\n/** Whether the event is the last a navigation reports. */\nfunction ended(event: unknown): event is { readonly id: number } {\n return (\n event instanceof NavigationEnd ||\n event instanceof NavigationCancel ||\n event instanceof NavigationError ||\n event instanceof NavigationSkipped\n );\n}\n\nexport class NativeNavigation {\n private readonly router = inject(Router);\n private readonly outlets = inject(NativeBack);\n\n /**\n * Push a new screen onto the stack. The plain case, and what `nativeRouterLink` does.\n *\n * From a presented screen the new one is presented the same way, over it, since a pushed\n * screen would slide in under it; `presentation` says otherwise, `stackAnimation` and all.\n */\n push(commands: NavigationCommands, options: NativeNavigationOptions = {}): Promise<boolean> {\n return this.go(commands, options, { stack: 'push' });\n }\n\n /**\n * Swap the current screen for another. The history entry is replaced too, so a back from the\n * new screen goes where a back from the old one would have.\n */\n replace(commands: NavigationCommands, options: NavigationExtras = {}): Promise<boolean> {\n return this.go(commands, { ...options, replaceUrl: true }, { stack: 'replace' });\n }\n\n /**\n * Present a screen over the stack rather than pushing into it: a modal, or a sheet.\n *\n * `present('/filters', { as: 'formSheet', presentation: { sheetAllowedDetents: [0.5, 1] } })`.\n *\n * A presented screen is put on screen outside the stack's navigation controller, so it has no\n * native header and no automatic safe-area insets: it needs its own way out, and its own\n * `safe-area-view`. A sheet can also be dragged away, but `fullScreenModal` cannot, and with\n * `gestureEnabled: false` neither can.\n */\n present(commands: NavigationCommands, options: PresentOptions = {}): Promise<boolean> {\n const { as = 'modal', presentation, ...extras } = options;\n const intent: NativeIntent = {\n stack: 'push',\n presentation: { stackPresentation: as, ...presentation },\n };\n // Asked at once, and only waited for when the page is another tab's: finding its route may\n // load a lazy one.\n const over = this.overTheTabInFront(commands, extras);\n if (!over) return this.go(commands, extras, intent);\n return over.then((found) =>\n this.go(found?.commands ?? commands, found?.extras ?? extras, intent),\n );\n }\n\n /**\n * Replace the whole stack with one screen, the way signing out or finishing onboarding does.\n * Every screen below is destroyed, so there is nothing to go back to.\n */\n reset(commands: NavigationCommands, options: NavigationExtras = {}): Promise<boolean> {\n return this.go(commands, { ...options, replaceUrl: true }, { stack: 'reset' });\n }\n\n /**\n * Go back exactly as the Android back button does: pop the stack in front, or at the root of a\n * tab's stack, go to the first tab. Not one entry back through history, which after a trip to\n * another tab is that tab. At the root of the app there is nowhere to go, and this does nothing.\n */\n back(): void {\n // Optional call: a test that stands a plain object in for the router has no such signal.\n if (!this.router.currentNavigation?.()) {\n this.outlets.back();\n return;\n }\n // Asked while a navigation is still putting its screen up: a page that leaves as it appears,\n // from an effect in its constructor. No stack has that screen to pop yet, so the back waits\n // for the navigation, and goes nowhere if the navigation does not arrive.\n if (this.backWaiting) return;\n this.backWaiting = this.router.events.subscribe((event) => {\n const ended = event instanceof NavigationEnd;\n if (!ended && !(event instanceof NavigationCancel) && !(event instanceof NavigationError)) {\n return;\n }\n this.backWaiting?.unsubscribe();\n this.backWaiting = null;\n if (ended) this.outlets.back();\n });\n }\n\n /** The wait of a back asked for mid-navigation, so two asked for in one are one. */\n private backWaiting: { unsubscribe(): void } | null = null;\n\n /**\n * Pop straight back to the screen at `commands`, taking every screen above it off the stack at\n * once - `popToViewController`. The screen is the one already there, with its state, not a new\n * one. Resolves false, doing nothing, when no screen below the top of a stack in front is\n * showing that url; a push is the way to a screen that is not there.\n */\n popTo(commands: NavigationCommands): Promise<boolean> {\n const tree =\n typeof commands === 'string'\n ? this.router.parseUrl(commands)\n : this.router.createUrlTree([...commands]);\n return this.outlets.popTo(this.router.serializeUrl(tree));\n }\n\n /**\n * Pop the stack in front to its first screen - `popToRootViewController`. Inside a tab, that is\n * the tab's first screen; the screens below keep their state. Resolves false at the root already.\n */\n popToRoot(): Promise<boolean> {\n return this.outlets.popToRoot();\n }\n\n private go(\n commands: NavigationCommands,\n options: NativeNavigationOptions,\n intent: NativeIntent,\n ): Promise<boolean> {\n const { presentation, state, ...extras } = options;\n const full: NativeIntent = presentation\n ? { ...intent, presentation: { ...intent.presentation, ...presentation } }\n : intent;\n\n const navigate = () => {\n const list = typeof commands === 'string' ? [pathOf(commands)] : [...commands];\n const all = {\n ...extras,\n ...(typeof commands === 'string' ? this.queryOf(commands, extras) : {}),\n state: { ...(state as object), [NATIVE_INTENT]: full },\n };\n const leaving = leavingPresented(this.router, list, all);\n return leaving ? this.router.navigateByUrl(leaving, all) : this.router.navigate(list, all);\n };\n // A screen stacked on the first one waits for it. Navigating while the router's first\n // navigation is still running - a lazily loaded root waiting on its import - cancels that\n // navigation, and the app opens on this screen with nothing beneath it. A reset replaces the\n // stack anyway, so it goes at once.\n const start = () => this.underTabRoot(commands, extras, full, navigate);\n return intent.stack !== 'reset' && this.firstNavigationRunning()\n ? this.firstNavigation().then(start)\n : start();\n }\n\n /**\n * A push into a tab nobody has opened goes to the tab first, so its stack has the tab's own\n * first screen under the page, and a back from the page lands there: what a tab bar with a\n * navigation controller per tab does. Without it the page is the stack's only screen, and the\n * same push leaves a different stack behind depending on whether the tab was ever tapped. A\n * presented screen goes where it is asked, and a replace or a reset has nothing to keep.\n */\n private underTabRoot(\n commands: NavigationCommands,\n extras: NavigationExtras,\n intent: NativeIntent,\n navigate: () => Promise<boolean>,\n ): Promise<boolean> {\n if (intent.stack !== 'push' || intent.presentation) return navigate();\n const tab = this.outlets.unopenedTabOf(this.pathFor(commands, extras));\n if (!tab) return navigate();\n return this.router.navigateByUrl(tab).then((arrived) => (arrived ? navigate() : false));\n }\n\n /** The path the commands lead to, without its query and fragment. */\n private pathFor(commands: NavigationCommands, extras: NavigationExtras): string {\n const url =\n typeof commands === 'string'\n ? commands\n : this.router.serializeUrl(this.router.createUrlTree([...commands], extras));\n return pathOf(url);\n }\n\n /**\n * A page of a tab that is not in front, presented over the one that is: its url would select\n * its own tab and show it there, so it goes to the root's presented outlet instead, where the\n * app's own stack shows it over everything. See `presented-route.ts`. Null for a page of the\n * tab in front, or of no tab, which is presented where its url puts it.\n */\n private overTheTabInFront(\n commands: NavigationCommands,\n extras: NavigationExtras,\n ): Promise<{ commands: unknown[]; extras: NavigationExtras } | null> | null {\n if (!this.outlets.presents) return null;\n const path = this.pathFor(commands, extras);\n if (!this.outlets.inTabBehind(path)) return null;\n const query = typeof commands === 'string' ? this.queryOf(commands, extras) : {};\n return presentedCommands(this.router, path).then(\n (presented) =>\n presented && { commands: presented, extras: { ...extras, ...query, relativeTo: null } },\n );\n }\n\n /**\n * The query and fragment written into a url string, as the extras `navigate` takes them: it\n * reads a string command as one path segment, and would encode a `?` into it. Extras given\n * alongside win over the ones in the string.\n */\n private queryOf(url: string, extras: NavigationExtras): NavigationExtras {\n const cut = url.search(/[?#]/);\n if (cut < 0) return {};\n const { queryParams, fragment } = this.router.parseUrl(url.slice(cut));\n return {\n queryParams: { ...queryParams, ...extras.queryParams },\n fragment: extras.fragment ?? fragment ?? undefined,\n };\n }\n\n private firstNavigationRunning(): boolean {\n const router = this.router as Partial<Router>;\n return router.navigated === false && !!router.currentNavigation?.();\n }\n\n private firstNavigation(): Promise<void> {\n return new Promise((resolve) => {\n const events = this.router.events.subscribe((event) => {\n if (\n event instanceof NavigationEnd ||\n event instanceof NavigationCancel ||\n event instanceof NavigationError\n ) {\n events.unsubscribe();\n resolve();\n }\n });\n });\n }\n}\n"]}
1
+ {"version":3,"file":"native-navigation.js","sourceRoot":"","sources":["../src/native-navigation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The typed facade over `Router` for the intents a URL cannot express (ADR 0003).\n *\n * Angular's `Router` stays the single source of truth: each of these is a line over\n * `router.navigate`, setting `replaceUrl` and a presentation on `NavigationExtras.state`. Deep\n * links, guards and resolvers keep working because it is still the Router, and because state\n * rides in history a back restores the presentation the screen was opened with.\n *\n * A navigation service that owns the stack was rejected: it either re-implements guards,\n * resolvers and deep linking, or it drifts from the URL, and once the stack is not derived from\n * router state the two can disagree.\n *\n * No decorators, so tests can import it at runtime and so it can be provided with `useClass`,\n * exactly as `NativePlatformLocation` and `NativeStackReuseStrategy` are.\n */\nimport { DestroyRef, inject } from '@angular/core';\nimport {\n NavigationCancel,\n NavigationCancellationCode,\n NavigationEnd,\n NavigationError,\n NavigationSkipped,\n NavigationSkippedCode,\n Router,\n type Navigation,\n type NavigationExtras,\n} from '@angular/router';\nimport { NativeBack } from './native-back.ts';\nimport type { ScreenPresentation, StackPresentation } from './screen-presentation.ts';\nimport { leavingPresented, presentedCommands } from './presented-route.ts';\n\n/** What `Router` takes: a url string, or the array form with segments and params. */\nexport type NavigationCommands = string | readonly unknown[];\n\n/**\n * Where the intent rides. `NavigationExtras.state` is the app's own object, so ours sits under\n * one reserved key rather than spread through it.\n */\nexport const NATIVE_INTENT = 'ɵnativeStack';\n\n/** What a navigation asks the outlet to do with the stack, over and above rendering the route. */\nexport interface NativeIntent {\n /** `replace` drops the screen it supersedes; `reset` empties the stack first. */\n readonly stack?: 'push' | 'replace' | 'reset';\n readonly presentation?: ScreenPresentation;\n}\n\nexport interface NativeNavigationOptions extends NavigationExtras {\n /** How the screen arrives: presentation, animation, gesture and sheet props. */\n presentation?: ScreenPresentation;\n}\n\nexport interface PresentOptions extends NativeNavigationOptions {\n /** Shorthand for `presentation.stackPresentation`. Defaults to `modal`. */\n as?: StackPresentation;\n}\n\n/** A url string up to its query or fragment. */\nconst pathOf = (url: string): string => url.split(/[?#]/, 1)[0]!;\n\n/** Read the intent off a navigation's state, if it carries one. */\nexport function intentOf(state: unknown): NativeIntent | null {\n if (!state || typeof state !== 'object') return null;\n const intent = (state as Record<string, unknown>)[NATIVE_INTENT];\n return intent && typeof intent === 'object' ? (intent as NativeIntent) : null;\n}\n\n/**\n * The intent of a navigation a guard redirected, for the navigation the redirect starts.\n *\n * The router starts a new navigation for a guard's `UrlTree`, keeping `replaceUrl` but not\n * `state`, so a reset to a page that sends a signed-out user to sign in would push the sign-in\n * page over the stack it was meant to clear. Held for that one navigation by its id, which no\n * later navigation shares.\n */\nconst redirected = new WeakMap<object, { readonly id: number; readonly intent: NativeIntent }>();\n\n/** What a navigation asks of the stack: its own intent, or the one it was redirected from. */\nexport function navigationIntent(\n router: object,\n navigation: Pick<Navigation, 'id' | 'extras'> | null | undefined,\n): NativeIntent | null {\n if (!navigation) return null;\n const own = intentOf(navigation.extras.state);\n if (own) return own;\n const carried = redirected.get(router);\n return carried?.id === navigation.id ? carried.intent : null;\n}\n\n/**\n * Hand a navigation's intent on to the one its guard redirects it to. The router schedules that\n * navigation as soon as it has reported the cancel, so it takes the next id.\n *\n * A reset that lands on the screen already on top, its own url or the one a redirect sends it to,\n * is one no outlet activates anything for: the router skips the url already showing, and reuses\n * the screen for another url of it. So the stack is reset here, to the screen on top.\n */\nexport function carryIntentAcrossRedirects(): void {\n const router = inject(Router);\n const outlets = inject(NativeBack);\n const events = router.events.subscribe((event) => {\n if (event instanceof NavigationCancel && event.code === NavigationCancellationCode.Redirect) {\n carryPast(router, event.id);\n return;\n }\n if (keptTop(event, outlets) && intentAt(router, event.id)?.stack === 'reset') {\n outlets.resetToTop();\n }\n if (ended(event) && redirected.get(router)?.id === event.id) redirected.delete(router);\n });\n inject(DestroyRef).onDestroy(() => events.unsubscribe());\n}\n\n/**\n * Whether the navigation `event` ends left the screen on top where it was: one the router skipped\n * for the url already showing, or one no stack put a screen on top for, such as a url with another\n * query, or one a redirect sends to the page on top.\n */\nfunction keptTop(event: unknown, outlets: NativeBack): event is { readonly id: number } {\n if (event instanceof NavigationSkipped) {\n return event.code === NavigationSkippedCode.IgnoredSameUrlNavigation;\n }\n return event instanceof NavigationEnd && !outlets.stackedIn(event.id);\n}\n\n/** The intent of the navigation in progress, when it is the one with `id`. */\nfunction intentAt(router: Router, id: number): NativeIntent | null {\n const navigation = router.currentNavigation();\n return navigation?.id === id ? navigationIntent(router, navigation) : null;\n}\n\n/** Hold the intent of the navigation a guard redirected for the one the redirect starts. */\nfunction carryPast(router: Router, id: number): void {\n const intent = intentAt(router, id);\n if (intent) redirected.set(router, { id: id + 1, intent });\n else redirected.delete(router);\n}\n\n/** Whether the event is the last a navigation reports. */\nfunction ended(event: unknown): event is { readonly id: number } {\n return (\n event instanceof NavigationEnd ||\n event instanceof NavigationCancel ||\n event instanceof NavigationError ||\n event instanceof NavigationSkipped\n );\n}\n\nexport class NativeNavigation {\n private readonly router = inject(Router);\n private readonly outlets = inject(NativeBack);\n\n /**\n * Push a new screen onto the stack. The plain case, and what `nativeRouterLink` does.\n *\n * From a presented screen the new one is presented the same way, over it, since a pushed\n * screen would slide in under it; `presentation` says otherwise, `stackAnimation` and all.\n */\n push(commands: NavigationCommands, options: NativeNavigationOptions = {}): Promise<boolean> {\n return this.go(commands, options, { stack: 'push' });\n }\n\n /**\n * Swap the current screen for another. The history entry is replaced too, so a back from the\n * new screen goes where a back from the old one would have.\n */\n replace(commands: NavigationCommands, options: NavigationExtras = {}): Promise<boolean> {\n return this.go(commands, { ...options, replaceUrl: true }, { stack: 'replace' });\n }\n\n /**\n * Present a screen over the stack rather than pushing into it: a modal, or a sheet.\n *\n * `present('/filters', { as: 'formSheet', presentation: { sheetAllowedDetents: [0.5, 1] } })`.\n *\n * A presented screen is put on screen outside the stack's navigation controller, so it has no\n * native header and no automatic safe-area insets: it needs its own way out, and its own\n * `safe-area-view`. A sheet can also be dragged away, but `fullScreenModal` cannot, and with\n * `gestureEnabled: false` neither can.\n */\n present(commands: NavigationCommands, options: PresentOptions = {}): Promise<boolean> {\n const { as = 'modal', presentation, ...extras } = options;\n const intent: NativeIntent = {\n stack: 'push',\n presentation: { stackPresentation: as, ...presentation },\n };\n // Asked at once, and only waited for when the page is another tab's: finding its route may\n // load a lazy one.\n const over = this.overTheTabInFront(commands, extras);\n if (!over) return this.go(commands, extras, intent);\n return over.then((found) =>\n this.go(found?.commands ?? commands, found?.extras ?? extras, intent),\n );\n }\n\n /**\n * Replace the whole stack with one screen, the way signing out or finishing onboarding does.\n * Every screen below is destroyed, so there is nothing to go back to.\n */\n reset(commands: NavigationCommands, options: NavigationExtras = {}): Promise<boolean> {\n return this.go(commands, { ...options, replaceUrl: true }, { stack: 'reset' });\n }\n\n /**\n * Go back exactly as the Android back button does: pop the stack in front, or at the root of a\n * tab's stack, go to the first tab. Not one entry back through history, which after a trip to\n * another tab is that tab. At the root of the app there is nowhere to go, and this does nothing.\n */\n back(): void {\n // Optional call: a test that stands a plain object in for the router has no such signal.\n if (!this.router.currentNavigation?.()) {\n this.outlets.back();\n return;\n }\n // Asked while a navigation is still putting its screen up: a page that leaves as it appears,\n // from an effect in its constructor. No stack has that screen to pop yet, so the back waits\n // for the navigation, and goes nowhere if the navigation does not arrive.\n if (this.backWaiting) return;\n this.backWaiting = this.router.events.subscribe((event) => {\n const ended = event instanceof NavigationEnd;\n if (!ended && !(event instanceof NavigationCancel) && !(event instanceof NavigationError)) {\n return;\n }\n this.backWaiting?.unsubscribe();\n this.backWaiting = null;\n if (ended) this.outlets.back();\n });\n }\n\n /** The wait of a back asked for mid-navigation, so two asked for in one are one. */\n private backWaiting: { unsubscribe(): void } | null = null;\n\n /**\n * Pop straight back to the screen at `commands`, taking every screen above it off the stack at\n * once - `popToViewController`. The screen is the one already there, with its state, not a new\n * one. Resolves false, doing nothing, when no screen below the top of a stack in front is\n * showing that url; a push is the way to a screen that is not there.\n */\n popTo(commands: NavigationCommands): Promise<boolean> {\n const tree =\n typeof commands === 'string'\n ? this.router.parseUrl(commands)\n : this.router.createUrlTree([...commands]);\n return this.outlets.popTo(this.router.serializeUrl(tree));\n }\n\n /**\n * Pop the stack in front to its first screen - `popToRootViewController`. Inside a tab, that is\n * the tab's first screen; the screens below keep their state. Resolves false at the root already.\n */\n popToRoot(): Promise<boolean> {\n return this.outlets.popToRoot();\n }\n\n private go(\n commands: NavigationCommands,\n options: NativeNavigationOptions,\n intent: NativeIntent,\n ): Promise<boolean> {\n const { presentation, state, ...extras } = options;\n const full: NativeIntent = presentation\n ? { ...intent, presentation: { ...intent.presentation, ...presentation } }\n : intent;\n\n const navigate = () => {\n const list = typeof commands === 'string' ? [pathOf(commands)] : [...commands];\n const all = {\n ...extras,\n ...(typeof commands === 'string' ? this.queryOf(commands, extras) : {}),\n state: { ...(state as object), [NATIVE_INTENT]: full },\n };\n const leaving = leavingPresented(this.router, list, all);\n return leaving ? this.router.navigateByUrl(leaving, all) : this.router.navigate(list, all);\n };\n // A screen stacked on the first one waits for it. Navigating while the router's first\n // navigation is still running - a lazily loaded root waiting on its import - cancels that\n // navigation, and the app opens on this screen with nothing beneath it. A reset replaces the\n // stack anyway, so it goes at once.\n const start = () => this.underTabRoot(commands, extras, full, navigate);\n return intent.stack !== 'reset' && this.firstNavigationRunning()\n ? this.firstNavigation().then(start)\n : start();\n }\n\n /**\n * A push into a tab nobody has opened goes to the tab first, so its stack has the tab's own\n * first screen under the page, and a back from the page lands there: what a tab bar with a\n * navigation controller per tab does. Without it the page is the stack's only screen, and the\n * same push leaves a different stack behind depending on whether the tab was ever tapped. A\n * presented screen goes where it is asked, and a replace or a reset has nothing to keep.\n */\n private underTabRoot(\n commands: NavigationCommands,\n extras: NavigationExtras,\n intent: NativeIntent,\n navigate: () => Promise<boolean>,\n ): Promise<boolean> {\n if (intent.stack !== 'push' || intent.presentation) return navigate();\n const tab = this.outlets.unopenedTabOf(this.pathFor(commands, extras));\n if (!tab) return navigate();\n return this.router.navigateByUrl(tab).then((arrived) => (arrived ? navigate() : false));\n }\n\n /** The path the commands lead to, without its query and fragment. */\n private pathFor(commands: NavigationCommands, extras: NavigationExtras): string {\n const url =\n typeof commands === 'string'\n ? commands\n : this.router.serializeUrl(this.router.createUrlTree([...commands], extras));\n return pathOf(url);\n }\n\n /**\n * A page of a tab that is not in front, presented over the one that is: its url would select\n * its own tab and show it there, so it goes to the root's presented outlet instead, where the\n * app's own stack shows it over everything. See `presented-route.ts`. Null for a page of the\n * tab in front, or of no tab, which is presented where its url puts it.\n */\n private overTheTabInFront(\n commands: NavigationCommands,\n extras: NavigationExtras,\n ): Promise<{ commands: unknown[]; extras: NavigationExtras } | null> | null {\n if (!this.outlets.presents) return null;\n const path = this.pathFor(commands, extras);\n if (!this.outlets.inTabBehind(path)) return null;\n const query = typeof commands === 'string' ? this.queryOf(commands, extras) : {};\n return presentedCommands(this.router, path).then(\n (presented) =>\n presented && { commands: presented, extras: { ...extras, ...query, relativeTo: null } },\n );\n }\n\n /**\n * The query and fragment written into a url string, as the extras `navigate` takes them: it\n * reads a string command as one path segment, and would encode a `?` into it. Extras given\n * alongside win over the ones in the string.\n */\n private queryOf(url: string, extras: NavigationExtras): NavigationExtras {\n const cut = url.search(/[?#]/);\n if (cut < 0) return {};\n const { queryParams, fragment } = this.router.parseUrl(url.slice(cut));\n return {\n queryParams: { ...queryParams, ...extras.queryParams },\n fragment: extras.fragment ?? fragment ?? undefined,\n };\n }\n\n private firstNavigationRunning(): boolean {\n const router = this.router as Partial<Router>;\n return router.navigated === false && !!router.currentNavigation?.();\n }\n\n private firstNavigation(): Promise<void> {\n return new Promise((resolve) => {\n const events = this.router.events.subscribe((event) => {\n if (\n event instanceof NavigationEnd ||\n event instanceof NavigationCancel ||\n event instanceof NavigationError\n ) {\n events.unsubscribe();\n resolve();\n }\n });\n });\n }\n}\n"]}
@@ -42,6 +42,7 @@ export declare class NativeStackOutlet implements RouterOutletContract, OnInit {
42
42
  /** For a refused back to reach the screen as native's own report would. */
43
43
  private readonly engine;
44
44
  private readonly errors;
45
+ private readonly back;
45
46
  /** The screen this stack sits in, when it is a stack inside a page of another. */
46
47
  private readonly holder;
47
48
  /** What the holder's own `preventNativeDismiss` was, while this stack's top screen refuses. */
@@ -76,6 +76,7 @@ export class NativeStackOutlet {
76
76
  /** For a refused back to reach the screen as native's own report would. */
77
77
  engine = inject(HostEngine, { optional: true });
78
78
  errors = inject(ErrorHandler);
79
+ back = inject(NativeBack);
79
80
  /** The screen this stack sits in, when it is a stack inside a page of another. */
80
81
  holder = inject(HOLDING_SCREEN, { optional: true });
81
82
  /** What the holder's own `preventNativeDismiss` was, while this stack's top screen refuses. */
@@ -100,7 +101,7 @@ export class NativeStackOutlet {
100
101
  // Not yet verified on a device: whether react-native-screens' own Android back handling
101
102
  // (`nativeBackButtonDismissalEnabled`) also pops the screen, which would make one press pop
102
103
  // twice. If a back press ever skips a screen on Android, look here first.
103
- const back = inject(NativeBack);
104
+ const back = this.back;
104
105
  const unsubscribeBack = back.handle((from) => from === 'button' && this.refusesButton() ? true : this.goBack());
105
106
  const unsubscribeStack = back.addStack({
106
107
  showing: () => this.isShowing(),
@@ -307,6 +308,7 @@ export class NativeStackOutlet {
307
308
  // on the screen: put the stack's fill back over it. Per-key, through `setStyle`, so whatever
308
309
  // else the page's style set - a background colour, say - still merges and stays.
309
310
  this.fillScreen(screen);
311
+ this.back.stacked(navigation);
310
312
  if (intent?.stack === 'reset')
311
313
  this.supersede(this.entries.slice(), navigation);
312
314
  else if (intent?.stack === 'replace' && this.top)
@@ -425,6 +427,7 @@ export class NativeStackOutlet {
425
427
  entry.unbind();
426
428
  entry.unbind = this.bindInputs(ref, route);
427
429
  }
430
+ this.back.stacked(this.navigationId());
428
431
  // Resume change detection for the screen the user is coming back to.
429
432
  ref.hostView.reattach();
430
433
  }
@@ -1 +1 @@
1
- {"version":3,"file":"native-stack-outlet.js","sourceRoot":"","sources":["../src/native-stack-outlet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A `RouterOutlet` that renders a native stack instead of swapping one view for another.\n *\n * The outlet's host element *is* the `RNSScreenStack`, and each activated route's component is\n * created directly on its own `screen` child rather than on a wrapper view inside it (ADR 0004).\n * The screens below the top stay mounted, which is what keeps a pushed-away screen's native\n * state alive: its scroll offset, its text cursor, its keyboard focus.\n *\n * Push and pop are inferred from the calls the router already makes. With a reuse strategy that\n * detaches, navigating forward is `detach()` then `activateWith()`, and navigating back is\n * `detach()` then `attach(ref)` with a ref we handed out earlier. Finding that ref in our own\n * stack is what identifies a pop, so nothing here needs to consult the URL.\n *\n * Note `activityState` is set once, to active, and never lowered. `Screen.tsx` throws on any\n * decrease while `isNativeStack`, because a native stack decides what is visible from the order\n * of its children rather than from a per-screen flag. Toggling that flag is for `ScreenContainer`\n * (tabs), where every screen is mounted at once.\n */\nimport {\n ApplicationRef,\n Component,\n DestroyRef,\n ElementRef,\n ErrorHandler,\n HostAttributeToken,\n InjectionToken,\n Injector,\n Renderer2,\n afterEveryRender,\n computed,\n createComponent,\n inject,\n signal,\n type ComponentRef,\n type EnvironmentInjector,\n type OnInit,\n type Type,\n type WritableSignal,\n} from '@angular/core';\nimport {\n ActivatedRoute,\n ChildrenOutletContexts,\n NavigationCancel,\n NavigationEnd,\n NavigationError,\n PRIMARY_OUTLET,\n Router,\n createUrlTreeFromSnapshot,\n type Data,\n type RouterOutletContract,\n} from '@angular/router';\nimport { Location, PlatformLocation } from '@angular/common';\nimport { SCREEN_IN_FRONT } from '@ng-native/device';\nimport { bindRouteInputs } from './bind-route-inputs.ts';\nimport { NativeBack, isShowing } from './native-back.ts';\nimport { navigationIntent, type NativeIntent } from './native-navigation.ts';\nimport { NativePlatformLocation } from './native-platform-location.ts';\nimport { PRESENTED, withoutPresented } from './presented-route.ts';\nimport { markScreenRoute } from './tab-routes.ts';\nimport { IN_TAB } from './in-tab.ts';\nimport { ownHost } from './own-host.ts';\nimport { SCREEN_HEADER } from './screen-header.ts';\nimport { HostEngine, type EngineNode } from '@ng-native/fabric';\nimport type { ScreenPresentation } from './screen-presentation.ts';\nimport { ActivityState } from './screens.ts';\n\ninterface StackEntry {\n route: ActivatedRoute;\n ref: ComponentRef<unknown>;\n /** The `screen` element this entry's component lives inside. */\n screen: unknown;\n /** True while the router is holding this ref for a later `attach`. */\n detached: boolean;\n /** Stops feeding route params into the component's inputs. */\n unbind: () => void;\n /** How the screen was put on screen, for a push from it to follow. */\n presentation?: ScreenPresentation;\n /** The navigation that put this screen on the stack, until that navigation ends. */\n activatedIn?: number;\n /** The navigation that covered this screen, until that navigation ends. */\n detachedIn?: number;\n /** Whether this screen is the one in front, for what it holds: see `SCREEN_IN_FRONT`. */\n inFront: WritableSignal<boolean>;\n}\n\n/**\n * The last navigation, per router, whose presentation an outlet has already given a screen.\n *\n * Presenting a route that is a stack of its own activates two outlets in one navigation: the one\n * the route is presented in, and the one inside it that shows the route's first child. Only the\n * first is presented; the second is the first screen of a stack inside a presented screen, and a\n * push inside that stack must see it as a pushed screen, not one to present over.\n */\nconst presented = new WeakMap<object, number>();\n\n/** What every screen needs to fill the stack, the same five keys RNSScreen itself expects. */\nconst FILL = { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 } as const;\n\n/** A swipe-back area with no limit on any edge. */\nconst UNLIMITED_SWIPE = { start: -1, end: -1, top: -1, bottom: -1 } as const;\n\n/**\n * The screen a page lives in, for a stack inside that page. A presented screen with a header is\n * such a stack, and the page that knows whether to refuse a dismissal is a screen inside it, where\n * the screen a swipe down dismisses is this one.\n */\nconst HOLDING_SCREEN = new InjectionToken<HoldingScreen>('ng-native.router.holding-screen');\n\ninterface HoldingScreen {\n readonly screen: unknown;\n /**\n * Told when a stack inside the screen changes what the screen refuses, so the stack the screen\n * is in can pass that on in turn, in the same render: its own look came before this one.\n */\n refusalChanged(): void;\n}\n\n/** Whether a screen refuses a native dismissal, as its page bound it. */\nconst refuses = (screen: unknown): boolean =>\n (screen as Partial<EngineNode> | undefined)?.props?.['preventNativeDismiss'] === true;\n\n/** The native engine's `dispatchEvent`, as Fabric calls it. */\ntype NativeDispatch = (node: unknown, topLevelType: string, nativeEvent: unknown) => void;\n\n@Component({\n selector: 'native-stack-outlet',\n template: '',\n host: { '[style]': 'fill' },\n})\nexport class NativeStackOutlet implements RouterOutletContract, OnInit {\n /**\n * Named outlets work exactly as on the web: `<native-stack-outlet name=\"list\" />` is filled by\n * routes with `outlet: 'list'`. The default is the primary one. Read once, as the router's own\n * outlet reads it, since an outlet cannot change which contexts it is registered under.\n */\n readonly name = inject(new HostAttributeToken('name'), { optional: true }) ?? PRIMARY_OUTLET;\n\n readonly supportsBindingToComponentInputs = true;\n\n private readonly parentContexts = inject(ChildrenOutletContexts);\n private readonly renderer = inject(Renderer2);\n private readonly applicationRef = inject(ApplicationRef);\n private readonly injector = inject(Injector);\n private readonly host = inject(ElementRef);\n private readonly location = inject(Location);\n private readonly history = inject(PlatformLocation);\n /**\n * Only for the intent a navigation carries. Optional so the outlet can be exercised through\n * `RouterOutletContract` directly, which is how its own tests drive it.\n */\n private readonly router = inject(Router, { optional: true });\n /** For a refused back to reach the screen as native's own report would. */\n private readonly engine = inject(HostEngine, { optional: true });\n\n private readonly errors = inject(ErrorHandler);\n /** The screen this stack sits in, when it is a stack inside a page of another. */\n private readonly holder = inject(HOLDING_SCREEN, { optional: true });\n /** What the holder's own `preventNativeDismiss` was, while this stack's top screen refuses. */\n private held: { own: unknown } | null = null;\n\n private readonly entries: StackEntry[] = [];\n /**\n * The screens a replace or a reset supersedes, kept until the navigation that supersedes them\n * succeeds: one that fails leaves the stack as it was.\n */\n private superseded: { entries: StackEntry[]; navigation: number } | null = null;\n\n protected readonly fill = { flex: 1 };\n\n constructor() {\n ownHost(this.host.nativeElement);\n // Ours, not a prop of the native stack.\n delete (this.host.nativeElement as { props: Record<string, unknown> }).props['name'];\n this.parentContexts.onChildOutletCreated(this.name, this);\n\n // Android's back button, and `NativeNavigation.back()`. Declining at the bottom of the stack\n // is deliberate: the outlet this one sits in gets its turn, and when none takes it the\n // platform backgrounds the app, which is what a user expects, rather than the app swallowing\n // the press and appearing stuck.\n //\n // Not yet verified on a device: whether react-native-screens' own Android back handling\n // (`nativeBackButtonDismissalEnabled`) also pops the screen, which would make one press pop\n // twice. If a back press ever skips a screen on Android, look here first.\n const back = inject(NativeBack);\n const unsubscribeBack = back.handle((from) =>\n from === 'button' && this.refusesButton() ? true : this.goBack(),\n );\n const unsubscribeStack = back.addStack({\n showing: () => this.isShowing(),\n popToRoot: () => (this.entries.length > 1 ? this.popToEntry(0) : null),\n popTo: (url) => {\n const index = this.entries.findIndex((entry) => this.urlOf(entry) === url);\n return index !== -1 && index < this.entries.length - 1 ? this.popToEntry(index) : null;\n },\n dropUnderTop: () => {\n if (this.entries.length < 2) return false;\n for (const entry of this.entries.slice(0, -1)) this.remove(entry);\n return true;\n },\n });\n // Optional for the same reason as the router: the outlet's own tests stand one in without it.\n const navigations = this.router?.events?.subscribe((event) => {\n if (event instanceof NavigationEnd) this.settle(event.id);\n else if (event instanceof NavigationError) this.rollBack(event.id);\n });\n\n const unhold = this.holder ? this.holdRefusals(this.holder) : undefined;\n const unpresent = this.takePresentedPages(back);\n const unleave = inject(IN_TAB, { optional: true })?.onLeave(() => this.dismissPresented());\n\n inject(DestroyRef).onDestroy(() => {\n unleave?.();\n unhold?.();\n unpresent?.();\n unsubscribeBack();\n unsubscribeStack();\n navigations?.unsubscribe();\n for (const entry of this.entries) {\n entry.unbind();\n entry.ref.destroy();\n }\n this.entries.length = 0;\n this.parentContexts.onChildOutletDestroyed(this.name);\n });\n }\n\n /** The page presented over everything, while there is one. See `presented-route.ts`. */\n private presentedPage: (StackEntry & { stopBack(): void }) | null = null;\n\n /**\n * The app's own stack, the one in the root component, is also the root's presented outlet: a\n * page of a tab that is not in front is shown here, as a screen over the bar and everything in\n * it. One page at a time, which the router sees to, and never kept: it is dismissed.\n */\n private takePresentedPages(back: NativeBack): (() => void) | undefined {\n const router = this.router;\n const root = inject(ActivatedRoute, { optional: true });\n if (!router?.routerState || this.name !== PRIMARY_OUTLET || root !== router.routerState.root) {\n return undefined;\n }\n const page = () => this.presentedPage;\n const outlet: RouterOutletContract = {\n supportsBindingToComponentInputs: true,\n get isActivated() {\n return page() !== null;\n },\n get component() {\n return (page()?.ref.instance as Object | undefined) ?? null;\n },\n get activatedRoute() {\n return page()?.route ?? null;\n },\n get activatedRouteData() {\n return page()?.route.snapshot.data ?? {};\n },\n activateWith: (route, environmentInjector) =>\n this.presentPage(route, environmentInjector, back),\n deactivate: () => this.dropPresentedPage(),\n detach: () => {\n throw new Error('[angular-native] a presented page is dismissed, not detached');\n },\n attach: () => {\n throw new Error('[angular-native] a presented page is not kept to attach again');\n },\n };\n this.parentContexts.onChildOutletCreated(PRESENTED, outlet);\n back.presents = true;\n return () => {\n back.presents = false;\n this.dropPresentedPage();\n this.parentContexts.onChildOutletDestroyed(PRESENTED);\n };\n }\n\n private presentPage(\n route: ActivatedRoute,\n environmentInjector: EnvironmentInjector,\n back: NativeBack,\n ): void {\n const component = (route.component ?? route.snapshot.component) as Type<unknown> | null;\n if (!component) throw new Error('[angular-native] route has no component to present');\n const presentation = this.claimPresentation(this.currentIntent()) ?? {\n stackPresentation: 'modal',\n };\n const screen = this.createScreen(presentation, () => this.dismissPresentedPage());\n const inFront = signal(true);\n const { ref, unbind } = this.createPage(\n component,\n route,\n environmentInjector,\n screen,\n inFront,\n PRESENTED,\n );\n this.fillScreen(screen);\n // Subscribed now, so it is the newest answer and the first asked: a back dismisses the page\n // before it pops anything in the tab under it.\n const stopBack = back.handle(() => this.dismissPresentedPage());\n this.presentedPage = {\n route,\n ref,\n screen,\n detached: false,\n unbind,\n presentation,\n inFront,\n stopBack,\n };\n }\n\n /** The router left the presented page: take it off the stack. */\n private dropPresentedPage(): void {\n const page = this.presentedPage;\n if (!page) return;\n this.presentedPage = null;\n page.stopBack();\n this.drop(page);\n }\n\n /**\n * Take the router off the presented page, for a back or for a sheet the user swiped away: one\n * entry back where that is the url without the page, and otherwise a navigation to that url in\n * place of this entry, since something under the page was navigated while it was up.\n */\n private dismissPresentedPage(): boolean {\n if (!this.presentedPage || !this.router) return false;\n const without = withoutPresented(this.router, this.router.url);\n if (this.historyUrl(-1) === without) this.location.historyGo(-1);\n else void this.router.navigateByUrl(without, { replaceUrl: true });\n return true;\n }\n\n /** The screens currently in the stack, oldest first. Exposed for tests. */\n get depth(): number {\n return this.entries.length;\n }\n\n ngOnInit(): void {\n this.activateCurrentRoute();\n }\n\n /**\n * The route the router is already on, for an outlet created after the navigation that reached\n * it: one held behind a condition until a session or a database is ready. The router activates\n * an outlet as a navigation ends, and that one ended with no outlet to activate, so the outlet\n * takes the route from its context as it arrives, as Angular's own `RouterOutlet` does.\n */\n private activateCurrentRoute(): void {\n if (this.isActivated) return;\n const context = this.parentContexts.getContext(this.name);\n if (!context?.route) return;\n if (context.attachRef) this.attach(context.attachRef, context.route);\n else this.activateWith(context.route, context.injector);\n }\n\n // --- RouterOutletContract ----------------------------------------------\n\n get isActivated(): boolean {\n return this.top !== undefined && !this.top.detached;\n }\n\n get component(): Object | null {\n return this.top && !this.top.detached ? (this.top.ref.instance as Object) : null;\n }\n\n get activatedRoute(): ActivatedRoute | null {\n return this.top && !this.top.detached ? this.top.route : null;\n }\n\n get activatedRouteData(): Data {\n return this.activatedRoute?.snapshot.data ?? {};\n }\n\n /** The input binder reads this to bind route params to component inputs. */\n get activatedComponentRef(): ComponentRef<unknown> | null {\n return this.top?.ref ?? null;\n }\n\n activateWith(route: ActivatedRoute, environmentInjector: EnvironmentInjector): void {\n const component = (route.component ?? route.snapshot.component) as Type<unknown> | null;\n if (!component) {\n throw new Error('[angular-native] route has no component to activate');\n }\n // Whatever a stack shows is a screen, children or not, and must survive being covered.\n if (route.snapshot.routeConfig) markScreenRoute(route.snapshot.routeConfig);\n\n // What kind of navigation this is, over and above which route it lands on: a replace\n // supersedes the screen below rather than stacking on it, and a reset empties the stack.\n // Everything else leaves the screens below mounted, so their native state survives the trip.\n const intent = this.currentIntent();\n const navigation = this.navigationId();\n const presentation = this.presentationFor(intent);\n //\n // The screen is the page's host element, so its props are set before the component exists\n // and the component's own host bindings land on top of them. Style bindings merge key by\n // key, so a page styling itself keeps the absolute fill the stack lays out with - except for\n // `position` and the four insets, which a page naming them writes over outright rather than\n // merging into. Those five are re-asserted below, after the page's own change detection has\n // run, so the outlet's positioning always wins whatever a page's host style says.\n const screen = this.createScreen(presentation);\n const inFront = signal(true);\n const { ref, unbind } = this.createPage(component, route, environmentInjector, screen, inFront);\n // The page's own host style, including any `position` or inset it declared, has now landed\n // on the screen: put the stack's fill back over it. Per-key, through `setStyle`, so whatever\n // else the page's style set - a background colour, say - still merges and stays.\n this.fillScreen(screen);\n\n if (intent?.stack === 'reset') this.supersede(this.entries.slice(), navigation);\n else if (intent?.stack === 'replace' && this.top) this.supersede([this.top], navigation);\n this.entries.push({\n route,\n ref,\n screen,\n detached: false,\n unbind,\n presentation,\n activatedIn: navigation,\n inFront,\n });\n }\n\n /**\n * The page's component, created on its screen and rendered once.\n *\n * A page that throws on that first render fails the navigation, and nothing of it may stay: a\n * half-made screen left on the stack is one the router does not know about, with a component\n * still running on it. So its component is destroyed, its screen taken off the stack, the\n * screen it was pushed from given back its change detection, and the error handed to the\n * app's `ErrorHandler` before the router fails the navigation with it.\n */\n private createPage(\n component: Type<unknown>,\n route: ActivatedRoute,\n environmentInjector: EnvironmentInjector,\n screen: unknown,\n inFront: WritableSignal<boolean>,\n outlet = this.name,\n ): { ref: ComponentRef<unknown>; unbind: () => void } {\n let ref: ComponentRef<unknown> | undefined;\n let unbind: (() => void) | undefined;\n try {\n ref = createComponent(component, {\n environmentInjector,\n elementInjector: this.outletInjector(route, inFront, screen, outlet),\n hostElement: screen as Element,\n });\n this.applicationRef.attachView(ref.hostView);\n // Route params onto inputs before the first change detection, not after: a required input\n // read in the template throws NG0950 if it is still unset when the page first renders.\n unbind = this.bindInputs(ref, route);\n // Before anything can commit. Creating the page's nodes dirties the tree, which schedules a\n // commit of its own - and that commit would capture the page with its elements created and\n // its bindings not yet applied. On iOS the props catch up a frame later and nobody sees it;\n // on Android the flattening decision is made from the props a view is created with, so a\n // content wrapper that arrives without its `collapsable: false` is flattened for good and\n // its children end up parented to a scroll view that allows exactly one.\n ref.changeDetectorRef.detectChanges();\n return { ref, unbind };\n } catch (error) {\n unbind?.();\n ref?.destroy();\n this.removeScreen(screen);\n this.uncover();\n this.errors.handleError(error);\n throw error;\n }\n }\n\n /**\n * Take the screen in front off the stack, when there is one: nothing once the router has\n * detached it, as Angular's own outlet does nothing then. A route with no component of its own,\n * a `loadChildren` wrapper or a group, has the router detach the page under it and then\n * deactivate this same outlet, and that page is a screen pushed from, still to come back to.\n */\n deactivate(): void {\n if (!this.isActivated) return;\n this.drop(this.entries.pop()!);\n }\n\n /**\n * Hand the live `ComponentRef` back to the router without destroying it. The screen stays\n * mounted, so the component keeps running and its native views keep their state.\n */\n detach(): ComponentRef<unknown> {\n const entry = this.top;\n if (!entry) throw new Error('[angular-native] outlet is not activated, nothing to detach');\n entry.detached = true;\n entry.detachedIn = this.navigationId();\n entry.inFront.set(false);\n // `ChangeDetectorRef.detach`, not `ApplicationRef.detachView`. The latter calls\n // `renderDetachView` and pulls the view's nodes out of the tree, which is exactly what we\n // are trying to avoid: the screen would vanish from the stack the moment we pushed past it.\n // This stops change detection for an off-screen screen while leaving it mounted.\n entry.ref.hostView.detach();\n return entry.ref;\n }\n\n /**\n * Re-attach a previously detached ref. If we still hold it, everything stacked above it is a\n * screen the user has navigated back past, so those are destroyed: that is the pop.\n */\n attach(ref: ComponentRef<unknown>, route: ActivatedRoute): void {\n const index = this.entries.findIndex((entry) => entry.ref === ref);\n\n if (index === -1) {\n // Not ours: the router is restoring a ref detached by a different outlet instance. Its\n // host element is already a screen, complete with the `dismissed` listener that outlet\n // registered, so it is re-parented rather than rebuilt.\n const screen = ref.location.nativeElement;\n this.renderer.appendChild(this.host.nativeElement, screen);\n this.entries.push({\n route,\n ref,\n screen,\n detached: false,\n unbind: this.bindInputs(ref, route),\n // What it was given is its first outlet's; this one has no say over that screen's.\n inFront: signal(true),\n });\n this.applicationRef.attachView(ref.hostView);\n } else {\n for (const above of this.entries.splice(index + 1)) this.drop(above);\n const entry = this.entries[index]!;\n entry.detached = false;\n entry.inFront.set(true);\n entry.route = route;\n // The route object is new even when the url is not, so the inputs follow the new one.\n entry.unbind();\n entry.unbind = this.bindInputs(ref, route);\n }\n\n // Resume change detection for the screen the user is coming back to.\n ref.hostView.reattach();\n }\n\n // --- native stack -------------------------------------------------------\n\n /**\n * Route params onto the page's inputs, but only in an app that asked for it with\n * `withComponentInputBinding()`, which is the only time Angular's own outlet binds them. Read\n * per screen rather than once, for a test that stands the router in.\n */\n private bindInputs(ref: ComponentRef<unknown>, route: ActivatedRoute): () => void {\n return this.router?.componentInputBindingEnabled ? bindRouteInputs(ref, route) : () => {};\n }\n\n private get top(): StackEntry | undefined {\n return this.entries[this.entries.length - 1];\n }\n\n /**\n * What the navigation asked for, if it asked for anything. Read here rather than remembered,\n * because the router is mid-navigation for exactly as long as an activation takes.\n */\n private currentIntent(): NativeIntent | null {\n return this.router ? navigationIntent(this.router, this.router.getCurrentNavigation()) : null;\n }\n\n /**\n * How the screen a navigation activates is put on screen.\n *\n * A push on top of a presented screen is presented the same way. `RNSScreenStack` pushes a push\n * screen that follows a modal onto the navigation controller under the modal, so the router\n * would be on the new route while the modal stayed in front, and the modal's own way out would\n * first pop a screen nobody could see. A presentation the navigation names itself wins, and a\n * reset starts a stack with nothing to follow. A presented screen that is a stack of its own is\n * where a push to one of its children goes instead, inside it.\n */\n private presentationFor(intent: NativeIntent | null): ScreenPresentation | undefined {\n const own = this.claimPresentation(intent);\n const covering = this.top?.presentation?.stackPresentation;\n if (intent?.stack === 'reset' || !covering || covering === 'push' || own?.stackPresentation) {\n return own;\n }\n return { ...own, stackPresentation: covering };\n }\n\n /** The navigation's own presentation, unless an outlet further out already presented it. */\n private claimPresentation(intent: NativeIntent | null): ScreenPresentation | undefined {\n if (!intent?.presentation) return undefined;\n const id = this.router?.getCurrentNavigation()?.id;\n if (id === undefined) return intent.presentation;\n if (presented.get(this.router!) === id) return undefined;\n presented.set(this.router!, id);\n return intent.presentation;\n }\n\n /** Take a screen out for good: its bindings, its component, and its native view. */\n private drop(entry: StackEntry): void {\n entry.unbind();\n entry.ref.destroy();\n this.removeScreen(entry.screen);\n }\n\n /**\n * Take off the lowest screen presented rather than pushed, and every screen over it, for a tab\n * that has gone behind another: see `IN_TAB`. Answers the url of the screen left on top, or null\n * when nothing was presented.\n */\n private dismissPresented(): string | null {\n const index = this.entries.findIndex(\n (entry, at) => at > 0 && (entry.presentation?.stackPresentation ?? 'push') !== 'push',\n );\n if (index === -1) return null;\n for (const entry of this.entries.splice(index)) this.drop(entry);\n return this.router ? this.urlOf(this.entries[index - 1]!) : null;\n }\n\n /** Take one entry out of the stack, wherever it is, and drop it. */\n private remove(entry: StackEntry): void {\n const index = this.entries.indexOf(entry);\n if (index === -1) return;\n this.entries.splice(index, 1);\n this.drop(entry);\n }\n\n // --- a navigation's outcome ----------------------------------------------\n\n /** The id of the navigation in progress, when there is a router to say. */\n private navigationId(): number | undefined {\n return this.router?.getCurrentNavigation()?.id;\n }\n\n /**\n * Take out the screens a replace or a reset supersedes once its navigation has succeeded, or\n * at once when there is no navigation to wait for. A replaced screen has already been detached\n * by the router, and with `replaceUrl` its history entry is gone too, so nothing will attach it\n * again; the reuse strategy notices the ref is destroyed and drops its handle.\n */\n private supersede(entries: StackEntry[], navigation: number | undefined): void {\n if (navigation === undefined) {\n for (const entry of entries) this.remove(entry);\n return;\n }\n this.superseded = { entries, navigation };\n }\n\n /** A navigation succeeded: what it superseded goes, and what it did is no longer undoable. */\n private settle(navigation: number): void {\n if (this.superseded?.navigation === navigation) {\n for (const entry of this.superseded.entries) this.remove(entry);\n this.superseded = null;\n }\n for (const entry of this.entries) {\n if (entry.activatedIn === navigation) entry.activatedIn = undefined;\n if (entry.detachedIn === navigation) entry.detachedIn = undefined;\n }\n }\n\n /**\n * A navigation failed, so the router is back where it started: undo what it did here too.\n *\n * The screen that threw has already gone (`createPage`), but a screen this outlet activated for\n * the same navigation has not when the one that threw is further in, the first screen of a\n * stack inside it. That one goes, with everything in it, and the screen it covered carries on.\n */\n private rollBack(navigation: number): void {\n if (this.superseded?.navigation === navigation) this.superseded = null;\n for (const entry of this.entries.filter((candidate) => candidate.activatedIn === navigation)) {\n this.remove(entry);\n }\n this.uncover(navigation);\n }\n\n /**\n * Give the top screen back its change detection when the router covered it for a navigation\n * that is not going to happen: the one given, or the one in progress.\n */\n private uncover(navigation = this.navigationId()): void {\n const top = this.top;\n if (!top?.detached || top.detachedIn !== navigation) return;\n top.detached = false;\n top.detachedIn = undefined;\n top.inFront.set(true);\n top.ref.hostView.reattach();\n }\n\n /**\n * `position: absolute` and the four insets, through `setStyle` rather than one `setProperty`\n * so each key merges into whatever style is already on the screen instead of replacing it -\n * the same merge a page's own host style gets, just asserted last so the stack's layout wins.\n */\n private fillScreen(screen: unknown): void {\n for (const [key, value] of Object.entries(FILL)) {\n this.renderer.setStyle(screen as Element, key, value);\n }\n }\n\n private createScreen(\n presentation?: ScreenPresentation,\n dismissed = (count: number) => this.onNativeDismiss(count),\n ): unknown {\n const screen = ownHost(this.renderer.createElement('screen'));\n this.fillScreen(screen);\n // Set once and never lowered: see the note at the top of this file.\n this.renderer.setProperty(screen, 'activityState', ActivityState.Active);\n // A swipe-back or an Android back button pops the screen natively and only then tells JS.\n // Without this the native stack and the router disagree from that moment on: the screen is\n // gone but the URL still points at it, so the next navigation starts from the wrong place.\n this.renderer.listen(\n screen,\n 'dismissed',\n (event: { nativeEvent?: { dismissCount?: number } }) =>\n dismissed(event?.nativeEvent?.dismissCount ?? 1),\n );\n // Every key is a prop `RNSScreen` already declares, spelled the way the codegen spec spells\n // it, so this forwards rather than translates. Set before the screen joins the stack: the\n // native side reads the presentation as it mounts.\n for (const [prop, value] of Object.entries(presentation ?? {})) {\n if (value !== undefined) this.renderer.setProperty(screen, prop, value);\n }\n // Except this one, which is a struct with no default: an edge left out is 0 natively, and\n // `RNSScreenStack` refuses a swipe-back that starts beyond 0 points. -1 is no limit, which is\n // what `Screen.tsx` sends for every edge not given.\n this.renderer.setProperty(screen, 'gestureResponseDistance', {\n ...UNLIMITED_SWIPE,\n ...presentation?.gestureResponseDistance,\n });\n\n this.renderer.appendChild(this.host.nativeElement, screen);\n return screen;\n }\n\n /**\n * Follow a pop the user already made. `historyGo`, not `back()`, because iOS coalesces a long\n * swipe into a single event with a count.\n *\n * Only ever fires for a native dismissal: verified on device that a pop this outlet drives\n * itself emits `willAppear`/`appear` for the screen below but no `dismissed`, so there is no\n * double-pop to guard against.\n *\n * The gesture itself is unverified by tooling: idb cannot synthesise a `UIScreenEdgePan` that\n * UIKit accepts, so this path was reasoned from the events rather than driven end to end.\n */\n private onNativeDismiss(count: number): void {\n this.popBy(Math.max(1, count));\n }\n\n /**\n * A back, from the button or `NativeNavigation`: pop the top screen, as long as there is one\n * below it and this stack is the one the user is looking at. A stack in a tab behind, or under\n * a screen pushed over the tab bar, is still subscribed, and the newest one would otherwise\n * answer for the stack in front.\n */\n /**\n * Android's Back button is the platform's own dismissal there, and react-native-screens leaves\n * it to JS: its Android screen ignores `preventNativeDismiss`. So a top screen that sets it\n * refuses the press here, as iOS refuses a swipe, and hears `nativeDismissCancelled` the same\n * way, through the engine, as if native had sent it.\n */\n private refusesButton(): boolean {\n if (this.entries.length < 2 || !this.isShowing()) return false;\n const screen = this.top!.screen as EngineNode;\n if (screen.props['preventNativeDismiss'] !== true) return false;\n // The native engine's own entry point for an event, the one Fabric calls. Not on\n // `HostEngine`, because only a native host has a screen to refuse with.\n const native = this.engine as { dispatchEvent?: NativeDispatch } | null;\n native?.dispatchEvent?.(screen, 'topNativeDismissCancelled', { dismissCount: 1 });\n return true;\n }\n\n /**\n * Passes the top screen's refusal to the screen this stack sits in, and that screen's report of\n * an attempt back to the top screen: the swipe that dismisses a presented stack is on the\n * screen holding it, which the page inside cannot bind.\n *\n * Read after every render, since the refusal is a host binding of whatever page is on top.\n */\n private holdRefusals(holder: HoldingScreen): () => void {\n const render = afterEveryRender(() => this.holdRefusal(holder));\n const unlisten = this.renderer.listen(\n holder.screen,\n 'nativeDismissCancelled',\n (event: { nativeEvent?: unknown }) => {\n // The stack can have lost its last screen with the refusal not yet released.\n const top = this.top;\n if (!this.held || !top) return;\n const native = this.engine as { dispatchEvent?: NativeDispatch } | null;\n const report = event?.nativeEvent ?? { dismissCount: 1 };\n native?.dispatchEvent?.(top.screen, 'topNativeDismissCancelled', report);\n },\n );\n return () => {\n render.destroy();\n unlisten();\n this.release(holder);\n };\n }\n\n private holdRefusal(holder: HoldingScreen): void {\n // A stack in a tab behind is inside the same screen, and has no say in it.\n if (!refuses(this.top?.screen) || !this.isShowing()) return this.release(holder);\n if (refuses(holder.screen)) return;\n // ponytail: the holder's own binding is read when the top screen starts refusing. One that\n // turns true while it does is put back as it was then; bind the refusal in one of the two.\n this.held = { own: (holder.screen as EngineNode).props?.['preventNativeDismiss'] };\n this.renderer.setProperty(holder.screen, 'preventNativeDismiss', true);\n holder.refusalChanged();\n }\n\n /** The holder's own answer again, once the top screen no longer refuses. */\n private release(holder: HoldingScreen): void {\n if (!this.held) return;\n this.renderer.setProperty(holder.screen, 'preventNativeDismiss', this.held.own ?? false);\n this.held = null;\n holder.refusalChanged();\n }\n\n private goBack(): boolean {\n if (this.entries.length < 2 || !this.isShowing()) return false;\n this.popBy(1);\n return true;\n }\n\n /** Whether the top screen is part of what the router shows now. Assumed without a router. */\n private isShowing(): boolean {\n if (!this.router) return true;\n return this.isActivated && isShowing(this.router, this.top!.route);\n }\n\n /**\n * Take the router to the screen `steps` below the top, whether native already popped it or it\n * is about to be popped because the router arrives there.\n */\n private popBy(steps: number): void {\n const below = this.entries[this.entries.length - 1 - steps];\n const url = below && this.router ? this.urlOf(below) : null;\n // Usually the entry that far back is the screen the pop revealed, and going back through\n // history keeps it tidy. Not always: a stack inside a tab shares history with the other tabs,\n // so after a trip to one and back the entry behind the top screen is that other tab, and\n // going back would switch tab rather than pop. Then the router is sent to the revealed\n // screen instead, replacing the entry of the one that is gone.\n const behind = this.historyUrl(-steps);\n if (!url || behind === undefined || behind === url) {\n this.location.historyGo(-steps);\n return;\n }\n void this.router!.navigateByUrl(url, { replaceUrl: true });\n }\n\n /**\n * Take the router down to the screen at `index`, popping every screen above it together.\n * Through history when the entries behind are these screens, so going back from there keeps\n * working one screen at a time; otherwise by a navigation to it that replaces the entry, as\n * `popBy` does when a tab's history interleaves.\n */\n private popToEntry(index: number): Promise<boolean> {\n const url = this.urlOf(this.entries[index]!);\n const steps = this.entries.length - 1 - index;\n if (this.historyUrl(-steps) === url) {\n const arrived = this.nextNavigation();\n this.location.historyGo(-steps);\n return arrived;\n }\n return this.router!.navigateByUrl(url, { replaceUrl: true });\n }\n\n /** Whether the navigation that happens next succeeds. */\n private nextNavigation(): Promise<boolean> {\n return new Promise((resolve) => {\n const events = this.router!.events.subscribe((event) => {\n if (event instanceof NavigationEnd) resolve(true);\n else if (event instanceof NavigationError || event instanceof NavigationCancel) {\n resolve(false);\n } else return;\n events.unsubscribe();\n });\n });\n }\n\n /** The url a screen was showing when it was covered, rebuilt from its own route snapshot. */\n private urlOf(entry: StackEntry): string {\n const snapshot = entry.route.snapshot;\n const tree = createUrlTreeFromSnapshot(snapshot, [], snapshot.queryParams, snapshot.fragment);\n return this.router!.serializeUrl(tree);\n }\n\n /**\n * The url of the history entry `offset` away, normalised the way the router writes it: null past\n * the start of history, and undefined when the history is not ours to read, so the pop has to go\n * through it blind.\n */\n private historyUrl(offset: number): string | null | undefined {\n if (!(this.history instanceof NativePlatformLocation)) return undefined;\n const url = this.history.ɵurlAt(offset);\n return url === null ? null : this.router!.serializeUrl(this.router!.parseUrl(url));\n }\n\n private removeScreen(screen: unknown): void {\n this.renderer.removeChild(this.host.nativeElement, screen);\n }\n\n /**\n * What a page is created with: its route, its screen, the outlet contexts its own outlets\n * register in, and whether its screen is in front - which is this screen's own say and, for a stack inside a\n * screen of another, that screen's too.\n */\n private outletInjector(\n route: ActivatedRoute,\n inFront: WritableSignal<boolean>,\n screen: unknown,\n outlet = this.name,\n ): Injector {\n const outer = this.injector.get(SCREEN_IN_FRONT);\n return Injector.create({\n parent: this.injector,\n providers: [\n { provide: SCREEN_IN_FRONT, useValue: computed(() => outer() && inFront()) },\n {\n provide: HOLDING_SCREEN,\n useValue: {\n screen,\n refusalChanged: () => this.holder && this.holdRefusal(this.holder),\n } satisfies HoldingScreen,\n },\n { provide: ActivatedRoute, useValue: route },\n { provide: SCREEN_HEADER, useValue: signal(false) },\n {\n provide: ChildrenOutletContexts,\n useValue: this.parentContexts.getOrCreateContext(outlet).children,\n },\n ],\n });\n }\n}\n"]}
1
+ {"version":3,"file":"native-stack-outlet.js","sourceRoot":"","sources":["../src/native-stack-outlet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A `RouterOutlet` that renders a native stack instead of swapping one view for another.\n *\n * The outlet's host element *is* the `RNSScreenStack`, and each activated route's component is\n * created directly on its own `screen` child rather than on a wrapper view inside it (ADR 0004).\n * The screens below the top stay mounted, which is what keeps a pushed-away screen's native\n * state alive: its scroll offset, its text cursor, its keyboard focus.\n *\n * Push and pop are inferred from the calls the router already makes. With a reuse strategy that\n * detaches, navigating forward is `detach()` then `activateWith()`, and navigating back is\n * `detach()` then `attach(ref)` with a ref we handed out earlier. Finding that ref in our own\n * stack is what identifies a pop, so nothing here needs to consult the URL.\n *\n * Note `activityState` is set once, to active, and never lowered. `Screen.tsx` throws on any\n * decrease while `isNativeStack`, because a native stack decides what is visible from the order\n * of its children rather than from a per-screen flag. Toggling that flag is for `ScreenContainer`\n * (tabs), where every screen is mounted at once.\n */\nimport {\n ApplicationRef,\n Component,\n DestroyRef,\n ElementRef,\n ErrorHandler,\n HostAttributeToken,\n InjectionToken,\n Injector,\n Renderer2,\n afterEveryRender,\n computed,\n createComponent,\n inject,\n signal,\n type ComponentRef,\n type EnvironmentInjector,\n type OnInit,\n type Type,\n type WritableSignal,\n} from '@angular/core';\nimport {\n ActivatedRoute,\n ChildrenOutletContexts,\n NavigationCancel,\n NavigationEnd,\n NavigationError,\n PRIMARY_OUTLET,\n Router,\n createUrlTreeFromSnapshot,\n type Data,\n type RouterOutletContract,\n} from '@angular/router';\nimport { Location, PlatformLocation } from '@angular/common';\nimport { SCREEN_IN_FRONT } from '@ng-native/device';\nimport { bindRouteInputs } from './bind-route-inputs.ts';\nimport { NativeBack, isShowing } from './native-back.ts';\nimport { navigationIntent, type NativeIntent } from './native-navigation.ts';\nimport { NativePlatformLocation } from './native-platform-location.ts';\nimport { PRESENTED, withoutPresented } from './presented-route.ts';\nimport { markScreenRoute } from './tab-routes.ts';\nimport { IN_TAB } from './in-tab.ts';\nimport { ownHost } from './own-host.ts';\nimport { SCREEN_HEADER } from './screen-header.ts';\nimport { HostEngine, type EngineNode } from '@ng-native/fabric';\nimport type { ScreenPresentation } from './screen-presentation.ts';\nimport { ActivityState } from './screens.ts';\n\ninterface StackEntry {\n route: ActivatedRoute;\n ref: ComponentRef<unknown>;\n /** The `screen` element this entry's component lives inside. */\n screen: unknown;\n /** True while the router is holding this ref for a later `attach`. */\n detached: boolean;\n /** Stops feeding route params into the component's inputs. */\n unbind: () => void;\n /** How the screen was put on screen, for a push from it to follow. */\n presentation?: ScreenPresentation;\n /** The navigation that put this screen on the stack, until that navigation ends. */\n activatedIn?: number;\n /** The navigation that covered this screen, until that navigation ends. */\n detachedIn?: number;\n /** Whether this screen is the one in front, for what it holds: see `SCREEN_IN_FRONT`. */\n inFront: WritableSignal<boolean>;\n}\n\n/**\n * The last navigation, per router, whose presentation an outlet has already given a screen.\n *\n * Presenting a route that is a stack of its own activates two outlets in one navigation: the one\n * the route is presented in, and the one inside it that shows the route's first child. Only the\n * first is presented; the second is the first screen of a stack inside a presented screen, and a\n * push inside that stack must see it as a pushed screen, not one to present over.\n */\nconst presented = new WeakMap<object, number>();\n\n/** What every screen needs to fill the stack, the same five keys RNSScreen itself expects. */\nconst FILL = { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 } as const;\n\n/** A swipe-back area with no limit on any edge. */\nconst UNLIMITED_SWIPE = { start: -1, end: -1, top: -1, bottom: -1 } as const;\n\n/**\n * The screen a page lives in, for a stack inside that page. A presented screen with a header is\n * such a stack, and the page that knows whether to refuse a dismissal is a screen inside it, where\n * the screen a swipe down dismisses is this one.\n */\nconst HOLDING_SCREEN = new InjectionToken<HoldingScreen>('ng-native.router.holding-screen');\n\ninterface HoldingScreen {\n readonly screen: unknown;\n /**\n * Told when a stack inside the screen changes what the screen refuses, so the stack the screen\n * is in can pass that on in turn, in the same render: its own look came before this one.\n */\n refusalChanged(): void;\n}\n\n/** Whether a screen refuses a native dismissal, as its page bound it. */\nconst refuses = (screen: unknown): boolean =>\n (screen as Partial<EngineNode> | undefined)?.props?.['preventNativeDismiss'] === true;\n\n/** The native engine's `dispatchEvent`, as Fabric calls it. */\ntype NativeDispatch = (node: unknown, topLevelType: string, nativeEvent: unknown) => void;\n\n@Component({\n selector: 'native-stack-outlet',\n template: '',\n host: { '[style]': 'fill' },\n})\nexport class NativeStackOutlet implements RouterOutletContract, OnInit {\n /**\n * Named outlets work exactly as on the web: `<native-stack-outlet name=\"list\" />` is filled by\n * routes with `outlet: 'list'`. The default is the primary one. Read once, as the router's own\n * outlet reads it, since an outlet cannot change which contexts it is registered under.\n */\n readonly name = inject(new HostAttributeToken('name'), { optional: true }) ?? PRIMARY_OUTLET;\n\n readonly supportsBindingToComponentInputs = true;\n\n private readonly parentContexts = inject(ChildrenOutletContexts);\n private readonly renderer = inject(Renderer2);\n private readonly applicationRef = inject(ApplicationRef);\n private readonly injector = inject(Injector);\n private readonly host = inject(ElementRef);\n private readonly location = inject(Location);\n private readonly history = inject(PlatformLocation);\n /**\n * Only for the intent a navigation carries. Optional so the outlet can be exercised through\n * `RouterOutletContract` directly, which is how its own tests drive it.\n */\n private readonly router = inject(Router, { optional: true });\n /** For a refused back to reach the screen as native's own report would. */\n private readonly engine = inject(HostEngine, { optional: true });\n\n private readonly errors = inject(ErrorHandler);\n private readonly back = inject(NativeBack);\n /** The screen this stack sits in, when it is a stack inside a page of another. */\n private readonly holder = inject(HOLDING_SCREEN, { optional: true });\n /** What the holder's own `preventNativeDismiss` was, while this stack's top screen refuses. */\n private held: { own: unknown } | null = null;\n\n private readonly entries: StackEntry[] = [];\n /**\n * The screens a replace or a reset supersedes, kept until the navigation that supersedes them\n * succeeds: one that fails leaves the stack as it was.\n */\n private superseded: { entries: StackEntry[]; navigation: number } | null = null;\n\n protected readonly fill = { flex: 1 };\n\n constructor() {\n ownHost(this.host.nativeElement);\n // Ours, not a prop of the native stack.\n delete (this.host.nativeElement as { props: Record<string, unknown> }).props['name'];\n this.parentContexts.onChildOutletCreated(this.name, this);\n\n // Android's back button, and `NativeNavigation.back()`. Declining at the bottom of the stack\n // is deliberate: the outlet this one sits in gets its turn, and when none takes it the\n // platform backgrounds the app, which is what a user expects, rather than the app swallowing\n // the press and appearing stuck.\n //\n // Not yet verified on a device: whether react-native-screens' own Android back handling\n // (`nativeBackButtonDismissalEnabled`) also pops the screen, which would make one press pop\n // twice. If a back press ever skips a screen on Android, look here first.\n const back = this.back;\n const unsubscribeBack = back.handle((from) =>\n from === 'button' && this.refusesButton() ? true : this.goBack(),\n );\n const unsubscribeStack = back.addStack({\n showing: () => this.isShowing(),\n popToRoot: () => (this.entries.length > 1 ? this.popToEntry(0) : null),\n popTo: (url) => {\n const index = this.entries.findIndex((entry) => this.urlOf(entry) === url);\n return index !== -1 && index < this.entries.length - 1 ? this.popToEntry(index) : null;\n },\n dropUnderTop: () => {\n if (this.entries.length < 2) return false;\n for (const entry of this.entries.slice(0, -1)) this.remove(entry);\n return true;\n },\n });\n // Optional for the same reason as the router: the outlet's own tests stand one in without it.\n const navigations = this.router?.events?.subscribe((event) => {\n if (event instanceof NavigationEnd) this.settle(event.id);\n else if (event instanceof NavigationError) this.rollBack(event.id);\n });\n\n const unhold = this.holder ? this.holdRefusals(this.holder) : undefined;\n const unpresent = this.takePresentedPages(back);\n const unleave = inject(IN_TAB, { optional: true })?.onLeave(() => this.dismissPresented());\n\n inject(DestroyRef).onDestroy(() => {\n unleave?.();\n unhold?.();\n unpresent?.();\n unsubscribeBack();\n unsubscribeStack();\n navigations?.unsubscribe();\n for (const entry of this.entries) {\n entry.unbind();\n entry.ref.destroy();\n }\n this.entries.length = 0;\n this.parentContexts.onChildOutletDestroyed(this.name);\n });\n }\n\n /** The page presented over everything, while there is one. See `presented-route.ts`. */\n private presentedPage: (StackEntry & { stopBack(): void }) | null = null;\n\n /**\n * The app's own stack, the one in the root component, is also the root's presented outlet: a\n * page of a tab that is not in front is shown here, as a screen over the bar and everything in\n * it. One page at a time, which the router sees to, and never kept: it is dismissed.\n */\n private takePresentedPages(back: NativeBack): (() => void) | undefined {\n const router = this.router;\n const root = inject(ActivatedRoute, { optional: true });\n if (!router?.routerState || this.name !== PRIMARY_OUTLET || root !== router.routerState.root) {\n return undefined;\n }\n const page = () => this.presentedPage;\n const outlet: RouterOutletContract = {\n supportsBindingToComponentInputs: true,\n get isActivated() {\n return page() !== null;\n },\n get component() {\n return (page()?.ref.instance as Object | undefined) ?? null;\n },\n get activatedRoute() {\n return page()?.route ?? null;\n },\n get activatedRouteData() {\n return page()?.route.snapshot.data ?? {};\n },\n activateWith: (route, environmentInjector) =>\n this.presentPage(route, environmentInjector, back),\n deactivate: () => this.dropPresentedPage(),\n detach: () => {\n throw new Error('[angular-native] a presented page is dismissed, not detached');\n },\n attach: () => {\n throw new Error('[angular-native] a presented page is not kept to attach again');\n },\n };\n this.parentContexts.onChildOutletCreated(PRESENTED, outlet);\n back.presents = true;\n return () => {\n back.presents = false;\n this.dropPresentedPage();\n this.parentContexts.onChildOutletDestroyed(PRESENTED);\n };\n }\n\n private presentPage(\n route: ActivatedRoute,\n environmentInjector: EnvironmentInjector,\n back: NativeBack,\n ): void {\n const component = (route.component ?? route.snapshot.component) as Type<unknown> | null;\n if (!component) throw new Error('[angular-native] route has no component to present');\n const presentation = this.claimPresentation(this.currentIntent()) ?? {\n stackPresentation: 'modal',\n };\n const screen = this.createScreen(presentation, () => this.dismissPresentedPage());\n const inFront = signal(true);\n const { ref, unbind } = this.createPage(\n component,\n route,\n environmentInjector,\n screen,\n inFront,\n PRESENTED,\n );\n this.fillScreen(screen);\n // Subscribed now, so it is the newest answer and the first asked: a back dismisses the page\n // before it pops anything in the tab under it.\n const stopBack = back.handle(() => this.dismissPresentedPage());\n this.presentedPage = {\n route,\n ref,\n screen,\n detached: false,\n unbind,\n presentation,\n inFront,\n stopBack,\n };\n }\n\n /** The router left the presented page: take it off the stack. */\n private dropPresentedPage(): void {\n const page = this.presentedPage;\n if (!page) return;\n this.presentedPage = null;\n page.stopBack();\n this.drop(page);\n }\n\n /**\n * Take the router off the presented page, for a back or for a sheet the user swiped away: one\n * entry back where that is the url without the page, and otherwise a navigation to that url in\n * place of this entry, since something under the page was navigated while it was up.\n */\n private dismissPresentedPage(): boolean {\n if (!this.presentedPage || !this.router) return false;\n const without = withoutPresented(this.router, this.router.url);\n if (this.historyUrl(-1) === without) this.location.historyGo(-1);\n else void this.router.navigateByUrl(without, { replaceUrl: true });\n return true;\n }\n\n /** The screens currently in the stack, oldest first. Exposed for tests. */\n get depth(): number {\n return this.entries.length;\n }\n\n ngOnInit(): void {\n this.activateCurrentRoute();\n }\n\n /**\n * The route the router is already on, for an outlet created after the navigation that reached\n * it: one held behind a condition until a session or a database is ready. The router activates\n * an outlet as a navigation ends, and that one ended with no outlet to activate, so the outlet\n * takes the route from its context as it arrives, as Angular's own `RouterOutlet` does.\n */\n private activateCurrentRoute(): void {\n if (this.isActivated) return;\n const context = this.parentContexts.getContext(this.name);\n if (!context?.route) return;\n if (context.attachRef) this.attach(context.attachRef, context.route);\n else this.activateWith(context.route, context.injector);\n }\n\n // --- RouterOutletContract ----------------------------------------------\n\n get isActivated(): boolean {\n return this.top !== undefined && !this.top.detached;\n }\n\n get component(): Object | null {\n return this.top && !this.top.detached ? (this.top.ref.instance as Object) : null;\n }\n\n get activatedRoute(): ActivatedRoute | null {\n return this.top && !this.top.detached ? this.top.route : null;\n }\n\n get activatedRouteData(): Data {\n return this.activatedRoute?.snapshot.data ?? {};\n }\n\n /** The input binder reads this to bind route params to component inputs. */\n get activatedComponentRef(): ComponentRef<unknown> | null {\n return this.top?.ref ?? null;\n }\n\n activateWith(route: ActivatedRoute, environmentInjector: EnvironmentInjector): void {\n const component = (route.component ?? route.snapshot.component) as Type<unknown> | null;\n if (!component) {\n throw new Error('[angular-native] route has no component to activate');\n }\n // Whatever a stack shows is a screen, children or not, and must survive being covered.\n if (route.snapshot.routeConfig) markScreenRoute(route.snapshot.routeConfig);\n\n // What kind of navigation this is, over and above which route it lands on: a replace\n // supersedes the screen below rather than stacking on it, and a reset empties the stack.\n // Everything else leaves the screens below mounted, so their native state survives the trip.\n const intent = this.currentIntent();\n const navigation = this.navigationId();\n const presentation = this.presentationFor(intent);\n //\n // The screen is the page's host element, so its props are set before the component exists\n // and the component's own host bindings land on top of them. Style bindings merge key by\n // key, so a page styling itself keeps the absolute fill the stack lays out with - except for\n // `position` and the four insets, which a page naming them writes over outright rather than\n // merging into. Those five are re-asserted below, after the page's own change detection has\n // run, so the outlet's positioning always wins whatever a page's host style says.\n const screen = this.createScreen(presentation);\n const inFront = signal(true);\n const { ref, unbind } = this.createPage(component, route, environmentInjector, screen, inFront);\n // The page's own host style, including any `position` or inset it declared, has now landed\n // on the screen: put the stack's fill back over it. Per-key, through `setStyle`, so whatever\n // else the page's style set - a background colour, say - still merges and stays.\n this.fillScreen(screen);\n\n this.back.stacked(navigation);\n if (intent?.stack === 'reset') this.supersede(this.entries.slice(), navigation);\n else if (intent?.stack === 'replace' && this.top) this.supersede([this.top], navigation);\n this.entries.push({\n route,\n ref,\n screen,\n detached: false,\n unbind,\n presentation,\n activatedIn: navigation,\n inFront,\n });\n }\n\n /**\n * The page's component, created on its screen and rendered once.\n *\n * A page that throws on that first render fails the navigation, and nothing of it may stay: a\n * half-made screen left on the stack is one the router does not know about, with a component\n * still running on it. So its component is destroyed, its screen taken off the stack, the\n * screen it was pushed from given back its change detection, and the error handed to the\n * app's `ErrorHandler` before the router fails the navigation with it.\n */\n private createPage(\n component: Type<unknown>,\n route: ActivatedRoute,\n environmentInjector: EnvironmentInjector,\n screen: unknown,\n inFront: WritableSignal<boolean>,\n outlet = this.name,\n ): { ref: ComponentRef<unknown>; unbind: () => void } {\n let ref: ComponentRef<unknown> | undefined;\n let unbind: (() => void) | undefined;\n try {\n ref = createComponent(component, {\n environmentInjector,\n elementInjector: this.outletInjector(route, inFront, screen, outlet),\n hostElement: screen as Element,\n });\n this.applicationRef.attachView(ref.hostView);\n // Route params onto inputs before the first change detection, not after: a required input\n // read in the template throws NG0950 if it is still unset when the page first renders.\n unbind = this.bindInputs(ref, route);\n // Before anything can commit. Creating the page's nodes dirties the tree, which schedules a\n // commit of its own - and that commit would capture the page with its elements created and\n // its bindings not yet applied. On iOS the props catch up a frame later and nobody sees it;\n // on Android the flattening decision is made from the props a view is created with, so a\n // content wrapper that arrives without its `collapsable: false` is flattened for good and\n // its children end up parented to a scroll view that allows exactly one.\n ref.changeDetectorRef.detectChanges();\n return { ref, unbind };\n } catch (error) {\n unbind?.();\n ref?.destroy();\n this.removeScreen(screen);\n this.uncover();\n this.errors.handleError(error);\n throw error;\n }\n }\n\n /**\n * Take the screen in front off the stack, when there is one: nothing once the router has\n * detached it, as Angular's own outlet does nothing then. A route with no component of its own,\n * a `loadChildren` wrapper or a group, has the router detach the page under it and then\n * deactivate this same outlet, and that page is a screen pushed from, still to come back to.\n */\n deactivate(): void {\n if (!this.isActivated) return;\n this.drop(this.entries.pop()!);\n }\n\n /**\n * Hand the live `ComponentRef` back to the router without destroying it. The screen stays\n * mounted, so the component keeps running and its native views keep their state.\n */\n detach(): ComponentRef<unknown> {\n const entry = this.top;\n if (!entry) throw new Error('[angular-native] outlet is not activated, nothing to detach');\n entry.detached = true;\n entry.detachedIn = this.navigationId();\n entry.inFront.set(false);\n // `ChangeDetectorRef.detach`, not `ApplicationRef.detachView`. The latter calls\n // `renderDetachView` and pulls the view's nodes out of the tree, which is exactly what we\n // are trying to avoid: the screen would vanish from the stack the moment we pushed past it.\n // This stops change detection for an off-screen screen while leaving it mounted.\n entry.ref.hostView.detach();\n return entry.ref;\n }\n\n /**\n * Re-attach a previously detached ref. If we still hold it, everything stacked above it is a\n * screen the user has navigated back past, so those are destroyed: that is the pop.\n */\n attach(ref: ComponentRef<unknown>, route: ActivatedRoute): void {\n const index = this.entries.findIndex((entry) => entry.ref === ref);\n\n if (index === -1) {\n // Not ours: the router is restoring a ref detached by a different outlet instance. Its\n // host element is already a screen, complete with the `dismissed` listener that outlet\n // registered, so it is re-parented rather than rebuilt.\n const screen = ref.location.nativeElement;\n this.renderer.appendChild(this.host.nativeElement, screen);\n this.entries.push({\n route,\n ref,\n screen,\n detached: false,\n unbind: this.bindInputs(ref, route),\n // What it was given is its first outlet's; this one has no say over that screen's.\n inFront: signal(true),\n });\n this.applicationRef.attachView(ref.hostView);\n } else {\n for (const above of this.entries.splice(index + 1)) this.drop(above);\n const entry = this.entries[index]!;\n entry.detached = false;\n entry.inFront.set(true);\n entry.route = route;\n // The route object is new even when the url is not, so the inputs follow the new one.\n entry.unbind();\n entry.unbind = this.bindInputs(ref, route);\n }\n\n this.back.stacked(this.navigationId());\n // Resume change detection for the screen the user is coming back to.\n ref.hostView.reattach();\n }\n\n // --- native stack -------------------------------------------------------\n\n /**\n * Route params onto the page's inputs, but only in an app that asked for it with\n * `withComponentInputBinding()`, which is the only time Angular's own outlet binds them. Read\n * per screen rather than once, for a test that stands the router in.\n */\n private bindInputs(ref: ComponentRef<unknown>, route: ActivatedRoute): () => void {\n return this.router?.componentInputBindingEnabled ? bindRouteInputs(ref, route) : () => {};\n }\n\n private get top(): StackEntry | undefined {\n return this.entries[this.entries.length - 1];\n }\n\n /**\n * What the navigation asked for, if it asked for anything. Read here rather than remembered,\n * because the router is mid-navigation for exactly as long as an activation takes.\n */\n private currentIntent(): NativeIntent | null {\n return this.router ? navigationIntent(this.router, this.router.getCurrentNavigation()) : null;\n }\n\n /**\n * How the screen a navigation activates is put on screen.\n *\n * A push on top of a presented screen is presented the same way. `RNSScreenStack` pushes a push\n * screen that follows a modal onto the navigation controller under the modal, so the router\n * would be on the new route while the modal stayed in front, and the modal's own way out would\n * first pop a screen nobody could see. A presentation the navigation names itself wins, and a\n * reset starts a stack with nothing to follow. A presented screen that is a stack of its own is\n * where a push to one of its children goes instead, inside it.\n */\n private presentationFor(intent: NativeIntent | null): ScreenPresentation | undefined {\n const own = this.claimPresentation(intent);\n const covering = this.top?.presentation?.stackPresentation;\n if (intent?.stack === 'reset' || !covering || covering === 'push' || own?.stackPresentation) {\n return own;\n }\n return { ...own, stackPresentation: covering };\n }\n\n /** The navigation's own presentation, unless an outlet further out already presented it. */\n private claimPresentation(intent: NativeIntent | null): ScreenPresentation | undefined {\n if (!intent?.presentation) return undefined;\n const id = this.router?.getCurrentNavigation()?.id;\n if (id === undefined) return intent.presentation;\n if (presented.get(this.router!) === id) return undefined;\n presented.set(this.router!, id);\n return intent.presentation;\n }\n\n /** Take a screen out for good: its bindings, its component, and its native view. */\n private drop(entry: StackEntry): void {\n entry.unbind();\n entry.ref.destroy();\n this.removeScreen(entry.screen);\n }\n\n /**\n * Take off the lowest screen presented rather than pushed, and every screen over it, for a tab\n * that has gone behind another: see `IN_TAB`. Answers the url of the screen left on top, or null\n * when nothing was presented.\n */\n private dismissPresented(): string | null {\n const index = this.entries.findIndex(\n (entry, at) => at > 0 && (entry.presentation?.stackPresentation ?? 'push') !== 'push',\n );\n if (index === -1) return null;\n for (const entry of this.entries.splice(index)) this.drop(entry);\n return this.router ? this.urlOf(this.entries[index - 1]!) : null;\n }\n\n /** Take one entry out of the stack, wherever it is, and drop it. */\n private remove(entry: StackEntry): void {\n const index = this.entries.indexOf(entry);\n if (index === -1) return;\n this.entries.splice(index, 1);\n this.drop(entry);\n }\n\n // --- a navigation's outcome ----------------------------------------------\n\n /** The id of the navigation in progress, when there is a router to say. */\n private navigationId(): number | undefined {\n return this.router?.getCurrentNavigation()?.id;\n }\n\n /**\n * Take out the screens a replace or a reset supersedes once its navigation has succeeded, or\n * at once when there is no navigation to wait for. A replaced screen has already been detached\n * by the router, and with `replaceUrl` its history entry is gone too, so nothing will attach it\n * again; the reuse strategy notices the ref is destroyed and drops its handle.\n */\n private supersede(entries: StackEntry[], navigation: number | undefined): void {\n if (navigation === undefined) {\n for (const entry of entries) this.remove(entry);\n return;\n }\n this.superseded = { entries, navigation };\n }\n\n /** A navigation succeeded: what it superseded goes, and what it did is no longer undoable. */\n private settle(navigation: number): void {\n if (this.superseded?.navigation === navigation) {\n for (const entry of this.superseded.entries) this.remove(entry);\n this.superseded = null;\n }\n for (const entry of this.entries) {\n if (entry.activatedIn === navigation) entry.activatedIn = undefined;\n if (entry.detachedIn === navigation) entry.detachedIn = undefined;\n }\n }\n\n /**\n * A navigation failed, so the router is back where it started: undo what it did here too.\n *\n * The screen that threw has already gone (`createPage`), but a screen this outlet activated for\n * the same navigation has not when the one that threw is further in, the first screen of a\n * stack inside it. That one goes, with everything in it, and the screen it covered carries on.\n */\n private rollBack(navigation: number): void {\n if (this.superseded?.navigation === navigation) this.superseded = null;\n for (const entry of this.entries.filter((candidate) => candidate.activatedIn === navigation)) {\n this.remove(entry);\n }\n this.uncover(navigation);\n }\n\n /**\n * Give the top screen back its change detection when the router covered it for a navigation\n * that is not going to happen: the one given, or the one in progress.\n */\n private uncover(navigation = this.navigationId()): void {\n const top = this.top;\n if (!top?.detached || top.detachedIn !== navigation) return;\n top.detached = false;\n top.detachedIn = undefined;\n top.inFront.set(true);\n top.ref.hostView.reattach();\n }\n\n /**\n * `position: absolute` and the four insets, through `setStyle` rather than one `setProperty`\n * so each key merges into whatever style is already on the screen instead of replacing it -\n * the same merge a page's own host style gets, just asserted last so the stack's layout wins.\n */\n private fillScreen(screen: unknown): void {\n for (const [key, value] of Object.entries(FILL)) {\n this.renderer.setStyle(screen as Element, key, value);\n }\n }\n\n private createScreen(\n presentation?: ScreenPresentation,\n dismissed = (count: number) => this.onNativeDismiss(count),\n ): unknown {\n const screen = ownHost(this.renderer.createElement('screen'));\n this.fillScreen(screen);\n // Set once and never lowered: see the note at the top of this file.\n this.renderer.setProperty(screen, 'activityState', ActivityState.Active);\n // A swipe-back or an Android back button pops the screen natively and only then tells JS.\n // Without this the native stack and the router disagree from that moment on: the screen is\n // gone but the URL still points at it, so the next navigation starts from the wrong place.\n this.renderer.listen(\n screen,\n 'dismissed',\n (event: { nativeEvent?: { dismissCount?: number } }) =>\n dismissed(event?.nativeEvent?.dismissCount ?? 1),\n );\n // Every key is a prop `RNSScreen` already declares, spelled the way the codegen spec spells\n // it, so this forwards rather than translates. Set before the screen joins the stack: the\n // native side reads the presentation as it mounts.\n for (const [prop, value] of Object.entries(presentation ?? {})) {\n if (value !== undefined) this.renderer.setProperty(screen, prop, value);\n }\n // Except this one, which is a struct with no default: an edge left out is 0 natively, and\n // `RNSScreenStack` refuses a swipe-back that starts beyond 0 points. -1 is no limit, which is\n // what `Screen.tsx` sends for every edge not given.\n this.renderer.setProperty(screen, 'gestureResponseDistance', {\n ...UNLIMITED_SWIPE,\n ...presentation?.gestureResponseDistance,\n });\n\n this.renderer.appendChild(this.host.nativeElement, screen);\n return screen;\n }\n\n /**\n * Follow a pop the user already made. `historyGo`, not `back()`, because iOS coalesces a long\n * swipe into a single event with a count.\n *\n * Only ever fires for a native dismissal: verified on device that a pop this outlet drives\n * itself emits `willAppear`/`appear` for the screen below but no `dismissed`, so there is no\n * double-pop to guard against.\n *\n * The gesture itself is unverified by tooling: idb cannot synthesise a `UIScreenEdgePan` that\n * UIKit accepts, so this path was reasoned from the events rather than driven end to end.\n */\n private onNativeDismiss(count: number): void {\n this.popBy(Math.max(1, count));\n }\n\n /**\n * A back, from the button or `NativeNavigation`: pop the top screen, as long as there is one\n * below it and this stack is the one the user is looking at. A stack in a tab behind, or under\n * a screen pushed over the tab bar, is still subscribed, and the newest one would otherwise\n * answer for the stack in front.\n */\n /**\n * Android's Back button is the platform's own dismissal there, and react-native-screens leaves\n * it to JS: its Android screen ignores `preventNativeDismiss`. So a top screen that sets it\n * refuses the press here, as iOS refuses a swipe, and hears `nativeDismissCancelled` the same\n * way, through the engine, as if native had sent it.\n */\n private refusesButton(): boolean {\n if (this.entries.length < 2 || !this.isShowing()) return false;\n const screen = this.top!.screen as EngineNode;\n if (screen.props['preventNativeDismiss'] !== true) return false;\n // The native engine's own entry point for an event, the one Fabric calls. Not on\n // `HostEngine`, because only a native host has a screen to refuse with.\n const native = this.engine as { dispatchEvent?: NativeDispatch } | null;\n native?.dispatchEvent?.(screen, 'topNativeDismissCancelled', { dismissCount: 1 });\n return true;\n }\n\n /**\n * Passes the top screen's refusal to the screen this stack sits in, and that screen's report of\n * an attempt back to the top screen: the swipe that dismisses a presented stack is on the\n * screen holding it, which the page inside cannot bind.\n *\n * Read after every render, since the refusal is a host binding of whatever page is on top.\n */\n private holdRefusals(holder: HoldingScreen): () => void {\n const render = afterEveryRender(() => this.holdRefusal(holder));\n const unlisten = this.renderer.listen(\n holder.screen,\n 'nativeDismissCancelled',\n (event: { nativeEvent?: unknown }) => {\n // The stack can have lost its last screen with the refusal not yet released.\n const top = this.top;\n if (!this.held || !top) return;\n const native = this.engine as { dispatchEvent?: NativeDispatch } | null;\n const report = event?.nativeEvent ?? { dismissCount: 1 };\n native?.dispatchEvent?.(top.screen, 'topNativeDismissCancelled', report);\n },\n );\n return () => {\n render.destroy();\n unlisten();\n this.release(holder);\n };\n }\n\n private holdRefusal(holder: HoldingScreen): void {\n // A stack in a tab behind is inside the same screen, and has no say in it.\n if (!refuses(this.top?.screen) || !this.isShowing()) return this.release(holder);\n if (refuses(holder.screen)) return;\n // ponytail: the holder's own binding is read when the top screen starts refusing. One that\n // turns true while it does is put back as it was then; bind the refusal in one of the two.\n this.held = { own: (holder.screen as EngineNode).props?.['preventNativeDismiss'] };\n this.renderer.setProperty(holder.screen, 'preventNativeDismiss', true);\n holder.refusalChanged();\n }\n\n /** The holder's own answer again, once the top screen no longer refuses. */\n private release(holder: HoldingScreen): void {\n if (!this.held) return;\n this.renderer.setProperty(holder.screen, 'preventNativeDismiss', this.held.own ?? false);\n this.held = null;\n holder.refusalChanged();\n }\n\n private goBack(): boolean {\n if (this.entries.length < 2 || !this.isShowing()) return false;\n this.popBy(1);\n return true;\n }\n\n /** Whether the top screen is part of what the router shows now. Assumed without a router. */\n private isShowing(): boolean {\n if (!this.router) return true;\n return this.isActivated && isShowing(this.router, this.top!.route);\n }\n\n /**\n * Take the router to the screen `steps` below the top, whether native already popped it or it\n * is about to be popped because the router arrives there.\n */\n private popBy(steps: number): void {\n const below = this.entries[this.entries.length - 1 - steps];\n const url = below && this.router ? this.urlOf(below) : null;\n // Usually the entry that far back is the screen the pop revealed, and going back through\n // history keeps it tidy. Not always: a stack inside a tab shares history with the other tabs,\n // so after a trip to one and back the entry behind the top screen is that other tab, and\n // going back would switch tab rather than pop. Then the router is sent to the revealed\n // screen instead, replacing the entry of the one that is gone.\n const behind = this.historyUrl(-steps);\n if (!url || behind === undefined || behind === url) {\n this.location.historyGo(-steps);\n return;\n }\n void this.router!.navigateByUrl(url, { replaceUrl: true });\n }\n\n /**\n * Take the router down to the screen at `index`, popping every screen above it together.\n * Through history when the entries behind are these screens, so going back from there keeps\n * working one screen at a time; otherwise by a navigation to it that replaces the entry, as\n * `popBy` does when a tab's history interleaves.\n */\n private popToEntry(index: number): Promise<boolean> {\n const url = this.urlOf(this.entries[index]!);\n const steps = this.entries.length - 1 - index;\n if (this.historyUrl(-steps) === url) {\n const arrived = this.nextNavigation();\n this.location.historyGo(-steps);\n return arrived;\n }\n return this.router!.navigateByUrl(url, { replaceUrl: true });\n }\n\n /** Whether the navigation that happens next succeeds. */\n private nextNavigation(): Promise<boolean> {\n return new Promise((resolve) => {\n const events = this.router!.events.subscribe((event) => {\n if (event instanceof NavigationEnd) resolve(true);\n else if (event instanceof NavigationError || event instanceof NavigationCancel) {\n resolve(false);\n } else return;\n events.unsubscribe();\n });\n });\n }\n\n /** The url a screen was showing when it was covered, rebuilt from its own route snapshot. */\n private urlOf(entry: StackEntry): string {\n const snapshot = entry.route.snapshot;\n const tree = createUrlTreeFromSnapshot(snapshot, [], snapshot.queryParams, snapshot.fragment);\n return this.router!.serializeUrl(tree);\n }\n\n /**\n * The url of the history entry `offset` away, normalised the way the router writes it: null past\n * the start of history, and undefined when the history is not ours to read, so the pop has to go\n * through it blind.\n */\n private historyUrl(offset: number): string | null | undefined {\n if (!(this.history instanceof NativePlatformLocation)) return undefined;\n const url = this.history.ɵurlAt(offset);\n return url === null ? null : this.router!.serializeUrl(this.router!.parseUrl(url));\n }\n\n private removeScreen(screen: unknown): void {\n this.renderer.removeChild(this.host.nativeElement, screen);\n }\n\n /**\n * What a page is created with: its route, its screen, the outlet contexts its own outlets\n * register in, and whether its screen is in front - which is this screen's own say and, for a stack inside a\n * screen of another, that screen's too.\n */\n private outletInjector(\n route: ActivatedRoute,\n inFront: WritableSignal<boolean>,\n screen: unknown,\n outlet = this.name,\n ): Injector {\n const outer = this.injector.get(SCREEN_IN_FRONT);\n return Injector.create({\n parent: this.injector,\n providers: [\n { provide: SCREEN_IN_FRONT, useValue: computed(() => outer() && inFront()) },\n {\n provide: HOLDING_SCREEN,\n useValue: {\n screen,\n refusalChanged: () => this.holder && this.holdRefusal(this.holder),\n } satisfies HoldingScreen,\n },\n { provide: ActivatedRoute, useValue: route },\n { provide: SCREEN_HEADER, useValue: signal(false) },\n {\n provide: ChildrenOutletContexts,\n useValue: this.parentContexts.getOrCreateContext(outlet).children,\n },\n ],\n });\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  /**
2
- * A screen's bottom toolbar, iOS only: the bar a navigation controller floats over the content
3
- * and the tab bar, where Mail has its filter, its search field and its compose button.
2
+ * A screen's bottom toolbar, iOS only: the bar a navigation controller floats over the content at
3
+ * the bottom of a screen, where Mail has its filter, its search field and its compose button.
4
4
  *
5
5
  * ```html
6
6
  * <native-toolbar>
@@ -17,6 +17,11 @@
17
17
  *
18
18
  * It needs iOS 18. Written anywhere in a screen's page, it is that screen's toolbar, and it goes
19
19
  * when the element does. A presented screen has no navigation controller, so no toolbar either.
20
+ *
21
+ * For a screen with no tab bar. From iOS 26, UIKit draws the toolbar of a stack inside a tab bar on
22
+ * the tab bar's row and behind it, where only the ends of it show. In a tab, a screen's actions go
23
+ * in its header, as a `native-header-item` at the `left` or the `right`, and its search in the
24
+ * header's search field, or in a tab of its own: `<native-tab systemItem="search">`.
20
25
  */
21
26
  import { Component, DestroyRef, ElementRef, inject, input, output } from '@angular/core';
22
27
  import { HostEngine } from '@ng-native/fabric';
@@ -1 +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"]}
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 at\n * the bottom of a screen, 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 *\n * For a screen with no tab bar. From iOS 26, UIKit draws the toolbar of a stack inside a tab bar on\n * the tab bar's row and behind it, where only the ends of it show. In a tab, a screen's actions go\n * in its header, as a `native-header-item` at the `left` or the `right`, and its search in the\n * header's search field, or in a tab of its own: `<native-tab systemItem=\"search\">`.\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-native/router",
3
- "version": "0.7.0",
3
+ "version": "0.8.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.7.0",
21
- "@ng-native/fabric": "0.7.0"
20
+ "@ng-native/device": "0.8.0",
21
+ "@ng-native/fabric": "0.8.0"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "@angular/common": "^22.0.0",