@ng-native/router 0.0.1 → 0.1.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +74 -1
  3. package/dist/bind-route-inputs.d.ts +20 -0
  4. package/dist/bind-route-inputs.js +52 -0
  5. package/dist/bind-route-inputs.js.map +1 -0
  6. package/dist/full-window-overlay.d.ts +16 -0
  7. package/dist/full-window-overlay.js +52 -0
  8. package/dist/full-window-overlay.js.map +1 -0
  9. package/dist/index.d.ts +26 -0
  10. package/dist/index.js +27 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/native-back.d.ts +38 -0
  13. package/dist/native-back.js +88 -0
  14. package/dist/native-back.js.map +1 -0
  15. package/dist/native-bar-defaults.d.ts +50 -0
  16. package/dist/native-bar-defaults.js +17 -0
  17. package/dist/native-bar-defaults.js.map +1 -0
  18. package/dist/native-header-item.d.ts +12 -0
  19. package/dist/native-header-item.js +40 -0
  20. package/dist/native-header-item.js.map +1 -0
  21. package/dist/native-header-palette.d.ts +45 -0
  22. package/dist/native-header-palette.js +42 -0
  23. package/dist/native-header-palette.js.map +1 -0
  24. package/dist/native-header.d.ts +103 -0
  25. package/dist/native-header.js +204 -0
  26. package/dist/native-header.js.map +1 -0
  27. package/dist/native-links.d.ts +30 -0
  28. package/dist/native-links.js +40 -0
  29. package/dist/native-links.js.map +1 -0
  30. package/dist/native-navigation.d.ts +84 -0
  31. package/dist/native-navigation.js +153 -0
  32. package/dist/native-navigation.js.map +1 -0
  33. package/dist/native-platform-location.d.ts +62 -0
  34. package/dist/native-platform-location.js +110 -0
  35. package/dist/native-platform-location.js.map +1 -0
  36. package/dist/native-router-link.d.ts +14 -0
  37. package/dist/native-router-link.js +51 -0
  38. package/dist/native-router-link.js.map +1 -0
  39. package/dist/native-search-bar.d.ts +44 -0
  40. package/dist/native-search-bar.js +132 -0
  41. package/dist/native-search-bar.js.map +1 -0
  42. package/dist/native-stack-outlet.d.ts +195 -0
  43. package/dist/native-stack-outlet.js +564 -0
  44. package/dist/native-stack-outlet.js.map +1 -0
  45. package/dist/native-stack-reuse-strategy.d.ts +57 -0
  46. package/dist/native-stack-reuse-strategy.js +126 -0
  47. package/dist/native-stack-reuse-strategy.js.map +1 -0
  48. package/dist/native-tab.d.ts +147 -0
  49. package/dist/native-tab.js +209 -0
  50. package/dist/native-tab.js.map +1 -0
  51. package/dist/native-tabs-outlet.d.ts +138 -0
  52. package/dist/native-tabs-outlet.js +408 -0
  53. package/dist/native-tabs-outlet.js.map +1 -0
  54. package/dist/own-host.d.ts +6 -0
  55. package/dist/own-host.js +28 -0
  56. package/dist/own-host.js.map +1 -0
  57. package/dist/provide-native-router.d.ts +41 -0
  58. package/dist/provide-native-router.js +151 -0
  59. package/dist/provide-native-router.js.map +1 -0
  60. package/dist/screen-presentation.d.ts +69 -0
  61. package/dist/screen-presentation.js +10 -0
  62. package/dist/screen-presentation.js.map +1 -0
  63. package/dist/screens.d.ts +37 -0
  64. package/dist/screens.js +108 -0
  65. package/dist/screens.js.map +1 -0
  66. package/dist/tab-routes.d.ts +16 -0
  67. package/dist/tab-routes.js +24 -0
  68. package/dist/tab-routes.js.map +1 -0
  69. package/dist/tab-safe-area-view.d.ts +15 -0
  70. package/dist/tab-safe-area-view.js +63 -0
  71. package/dist/tab-safe-area-view.js.map +1 -0
  72. package/dist/transforms.d.ts +2 -0
  73. package/dist/transforms.js +13 -0
  74. package/dist/transforms.js.map +1 -0
  75. package/package.json +59 -3
@@ -0,0 +1,132 @@
1
+ /**
2
+ * The navigation bar's search field: react-native-screens' `RNSSearchBar`, the UISearchController
3
+ * iOS puts under a large title. Place it in the header's search slot:
4
+ *
5
+ * ```html
6
+ * <native-header title="Properties" [largeTitle]="true">
7
+ * <native-header-item type="searchBar">
8
+ * <native-search-bar placeholder="Search" [(query)]="query" />
9
+ * </native-header-item>
10
+ * </native-header>
11
+ * ```
12
+ *
13
+ * The text is a two-way `query`: what a list filter wants. Typing updates it, and a query set from
14
+ * code - a recent search tapped, a suggestion taken - is put in the field, as a controlled text
15
+ * input's value is. `(search)` is the keyboard's search key, with the text; `(cancel)` the Cancel
16
+ * button; `(searchFocus)` and `(searchBlur)` the field taking and leaving the keyboard, which is when
17
+ * a suggestions list comes and goes. `focus()`, `blur()`, `clear()` and `cancelSearch()` do those
18
+ * from code.
19
+ *
20
+ * ponytail: react-native-screens has no scope bar and no search tokens; a scope is a segmented
21
+ * control under the header, and a token is text.
22
+ */
23
+ import { Component, DestroyRef, ElementRef, afterRenderEffect, inject, input, model, output, untracked, } from '@angular/core';
24
+ import { HostEngine } from '@ng-native/fabric';
25
+ import { ownHost } from "./own-host.js";
26
+ import { optionalBoolean } from "./transforms.js";
27
+ import * as i0 from "@angular/core";
28
+ export class NativeSearchBar {
29
+ query = model('', /* @ts-ignore */
30
+ ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
31
+ placeholder = input(/* @ts-ignore */
32
+ ...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
33
+ /** Scroll the field away with the content, as iOS lists do by default. */
34
+ hideWhenScrolling = input(undefined, { ...(ngDevMode ? { debugName: "hideWhenScrolling" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
35
+ cancelButtonText = input(/* @ts-ignore */
36
+ ...(ngDevMode ? [undefined, { debugName: "cancelButtonText" }] : /* istanbul ignore next */ []));
37
+ /**
38
+ * Where iOS puts the field. `automatic` lets iOS 26 fold it into a toolbar, which a presented
39
+ * sheet does not have, so there it shows nowhere; `stacked` keeps it under the title.
40
+ */
41
+ placement = input(/* @ts-ignore */
42
+ ...(ngDevMode ? [undefined, { debugName: "placement" }] : /* istanbul ignore next */ []));
43
+ /** iOS 26: whether `automatic` may move the field into the toolbar. */
44
+ allowToolbarIntegration = input(undefined, { ...(ngDevMode ? { debugName: "allowToolbarIntegration" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
45
+ autoCapitalize = input(/* @ts-ignore */
46
+ ...(ngDevMode ? [undefined, { debugName: "autoCapitalize" }] : /* istanbul ignore next */ []));
47
+ /** Dim the content behind the field while it is being typed in. */
48
+ obscureBackground = input(undefined, { ...(ngDevMode ? { debugName: "obscureBackground" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
49
+ /** Hide the navigation bar while the field is being typed in. */
50
+ hideNavigationBar = input(undefined, { ...(ngDevMode ? { debugName: "hideNavigationBar" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
51
+ tintColor = input(/* @ts-ignore */
52
+ ...(ngDevMode ? [undefined, { debugName: "tintColor" }] : /* istanbul ignore next */ []));
53
+ textColor = input(/* @ts-ignore */
54
+ ...(ngDevMode ? [undefined, { debugName: "textColor" }] : /* istanbul ignore next */ []));
55
+ /** The keyboard's search key was pressed, with the text in the field. */
56
+ search = output();
57
+ /** The Cancel button was pressed. */
58
+ cancel = output();
59
+ searchFocus = output();
60
+ searchBlur = output();
61
+ node = inject(ElementRef).nativeElement;
62
+ engine = this.node.host ?? inject(HostEngine);
63
+ /** What the field last said it holds, to tell a query set from code from the field's echo. */
64
+ fieldText = '';
65
+ constructor() {
66
+ ownHost(this.node, NativeSearchBar);
67
+ const listen = (event, handle) => this.engine.setEventListener(this.node, event, (raw) => handle(raw?.nativeEvent ?? {}));
68
+ const stops = [
69
+ listen('topSearchButtonPress', ({ text }) => this.search.emit(String(text ?? this.query()))),
70
+ listen('topCancelButtonPress', () => this.cancel.emit()),
71
+ listen('topSearchFocus', () => this.searchFocus.emit()),
72
+ listen('topSearchBlur', () => this.searchBlur.emit()),
73
+ ];
74
+ inject(DestroyRef).onDestroy(() => stops.forEach((stop) => stop()));
75
+ // A query that is not what the field holds was set from code: put it in the field. After the
76
+ // render, so a query the page starts with reaches a field that has been committed.
77
+ afterRenderEffect({
78
+ write: () => {
79
+ const query = this.query();
80
+ untracked(() => {
81
+ if (query === this.fieldText)
82
+ return;
83
+ this.fieldText = query;
84
+ this.engine.dispatchCommand(this.node, 'setText', [query]);
85
+ });
86
+ },
87
+ });
88
+ }
89
+ focus() {
90
+ this.engine.dispatchCommand(this.node, 'focus');
91
+ }
92
+ blur() {
93
+ this.engine.dispatchCommand(this.node, 'blur');
94
+ }
95
+ /** Empty the field, and the query with it. */
96
+ clear() {
97
+ this.fieldText = '';
98
+ this.query.set('');
99
+ this.engine.dispatchCommand(this.node, 'clearText');
100
+ }
101
+ /** Close the search, as the Cancel button does. */
102
+ cancelSearch() {
103
+ this.engine.dispatchCommand(this.node, 'cancelSearch');
104
+ }
105
+ onNativeText(text) {
106
+ this.fieldText = text;
107
+ this.query.set(text);
108
+ }
109
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: NativeSearchBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
110
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: NativeSearchBar, isStandalone: true, selector: "native-search-bar", inputs: { query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hideWhenScrolling: { classPropertyName: "hideWhenScrolling", publicName: "hideWhenScrolling", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonText: { classPropertyName: "cancelButtonText", publicName: "cancelButtonText", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, allowToolbarIntegration: { classPropertyName: "allowToolbarIntegration", publicName: "allowToolbarIntegration", isSignal: true, isRequired: false, transformFunction: null }, autoCapitalize: { classPropertyName: "autoCapitalize", publicName: "autoCapitalize", isSignal: true, isRequired: false, transformFunction: null }, obscureBackground: { classPropertyName: "obscureBackground", publicName: "obscureBackground", isSignal: true, isRequired: false, transformFunction: null }, hideNavigationBar: { classPropertyName: "hideNavigationBar", publicName: "hideNavigationBar", isSignal: true, isRequired: false, transformFunction: null }, tintColor: { classPropertyName: "tintColor", publicName: "tintColor", isSignal: true, isRequired: false, transformFunction: null }, textColor: { classPropertyName: "textColor", publicName: "textColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { query: "queryChange", search: "search", cancel: "cancel", searchFocus: "searchFocus", searchBlur: "searchBlur" }, host: { listeners: { "changeText": "onNativeText($event?.nativeEvent?.text ?? \"\")" }, properties: { "placeholder": "placeholder()", "hideWhenScrolling": "hideWhenScrolling()", "cancelButtonText": "cancelButtonText()", "placement": "placement()", "allowToolbarIntegration": "allowToolbarIntegration()", "autoCapitalize": "autoCapitalize()", "obscureBackground": "obscureBackground() === undefined ? undefined : String(obscureBackground())", "hideNavigationBar": "hideNavigationBar() === undefined ? undefined : String(hideNavigationBar())", "tintColor": "tintColor()", "textColor": "textColor()" } }, ngImport: i0, template: '', isInline: true });
111
+ }
112
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: NativeSearchBar, decorators: [{
113
+ type: Component,
114
+ args: [{
115
+ selector: 'native-search-bar',
116
+ template: '',
117
+ host: {
118
+ '[placeholder]': 'placeholder()',
119
+ '[hideWhenScrolling]': 'hideWhenScrolling()',
120
+ '[cancelButtonText]': 'cancelButtonText()',
121
+ '[placement]': 'placement()',
122
+ '[allowToolbarIntegration]': 'allowToolbarIntegration()',
123
+ '[autoCapitalize]': 'autoCapitalize()',
124
+ '[obscureBackground]': 'obscureBackground() === undefined ? undefined : String(obscureBackground())',
125
+ '[hideNavigationBar]': 'hideNavigationBar() === undefined ? undefined : String(hideNavigationBar())',
126
+ '[tintColor]': 'tintColor()',
127
+ '[textColor]': 'textColor()',
128
+ '(changeText)': 'onNativeText($event?.nativeEvent?.text ?? "")',
129
+ },
130
+ }]
131
+ }], ctorParameters: () => [], propDecorators: { query: [{ type: i0.Input, args: [{ isSignal: true, alias: "query", required: false }] }, { type: i0.Output, args: ["queryChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hideWhenScrolling: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenScrolling", required: false }] }], cancelButtonText: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonText", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], allowToolbarIntegration: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowToolbarIntegration", required: false }] }], autoCapitalize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCapitalize", required: false }] }], obscureBackground: [{ type: i0.Input, args: [{ isSignal: true, alias: "obscureBackground", required: false }] }], hideNavigationBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideNavigationBar", required: false }] }], tintColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "tintColor", required: false }] }], textColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "textColor", required: false }] }], search: [{ type: i0.Output, args: ["search"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], searchFocus: [{ type: i0.Output, args: ["searchFocus"] }], searchBlur: [{ type: i0.Output, args: ["searchBlur"] }] } });
132
+ //# sourceMappingURL=native-search-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-search-bar.js","sourceRoot":"","sources":["../src/native-search-bar.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The navigation bar's search field: react-native-screens' `RNSSearchBar`, the UISearchController\n * iOS puts under a large title. Place it in the header's search slot:\n *\n * ```html\n * <native-header title=\"Properties\" [largeTitle]=\"true\">\n * <native-header-item type=\"searchBar\">\n * <native-search-bar placeholder=\"Search\" [(query)]=\"query\" />\n * </native-header-item>\n * </native-header>\n * ```\n *\n * The text is a two-way `query`: what a list filter wants. Typing updates it, and a query set from\n * code - a recent search tapped, a suggestion taken - is put in the field, as a controlled text\n * input's value is. `(search)` is the keyboard's search key, with the text; `(cancel)` the Cancel\n * button; `(searchFocus)` and `(searchBlur)` the field taking and leaving the keyboard, which is when\n * a suggestions list comes and goes. `focus()`, `blur()`, `clear()` and `cancelSearch()` do those\n * from code.\n *\n * ponytail: react-native-screens has no scope bar and no search tokens; a scope is a segmented\n * control under the header, and a token is text.\n */\nimport {\n Component,\n DestroyRef,\n ElementRef,\n afterRenderEffect,\n inject,\n input,\n model,\n output,\n untracked,\n} from '@angular/core';\nimport { type EngineNode, HostEngine, type NativeSyntheticEvent } from '@ng-native/fabric';\nimport { ownHost } from './own-host.ts';\nimport { optionalBoolean } from './transforms.ts';\n\n/** react-native-screens' placements for the navigation bar's search field. */\nexport type SearchBarPlacement =\n 'automatic' | 'inline' | 'stacked' | 'integrated' | 'integratedButton' | 'integratedCentered';\n\n@Component({\n selector: 'native-search-bar',\n template: '',\n host: {\n '[placeholder]': 'placeholder()',\n '[hideWhenScrolling]': 'hideWhenScrolling()',\n '[cancelButtonText]': 'cancelButtonText()',\n '[placement]': 'placement()',\n '[allowToolbarIntegration]': 'allowToolbarIntegration()',\n '[autoCapitalize]': 'autoCapitalize()',\n '[obscureBackground]':\n 'obscureBackground() === undefined ? undefined : String(obscureBackground())',\n '[hideNavigationBar]':\n 'hideNavigationBar() === undefined ? undefined : String(hideNavigationBar())',\n '[tintColor]': 'tintColor()',\n '[textColor]': 'textColor()',\n '(changeText)': 'onNativeText($event?.nativeEvent?.text ?? \"\")',\n },\n})\nexport class NativeSearchBar {\n readonly query = model('');\n readonly placeholder = input<string>();\n /** Scroll the field away with the content, as iOS lists do by default. */\n readonly hideWhenScrolling = input(undefined, { transform: optionalBoolean });\n readonly cancelButtonText = input<string>();\n /**\n * Where iOS puts the field. `automatic` lets iOS 26 fold it into a toolbar, which a presented\n * sheet does not have, so there it shows nowhere; `stacked` keeps it under the title.\n */\n readonly placement = input<SearchBarPlacement>();\n /** iOS 26: whether `automatic` may move the field into the toolbar. */\n readonly allowToolbarIntegration = input(undefined, { transform: optionalBoolean });\n readonly autoCapitalize = input<\n 'systemDefault' | 'none' | 'words' | 'sentences' | 'characters'\n >();\n /** Dim the content behind the field while it is being typed in. */\n readonly obscureBackground = input(undefined, { transform: optionalBoolean });\n /** Hide the navigation bar while the field is being typed in. */\n readonly hideNavigationBar = input(undefined, { transform: optionalBoolean });\n readonly tintColor = input<string>();\n readonly textColor = input<string>();\n\n /** The keyboard's search key was pressed, with the text in the field. */\n readonly search = output<string>();\n /** The Cancel button was pressed. */\n readonly cancel = output<void>();\n readonly searchFocus = output<void>();\n readonly searchBlur = output<void>();\n\n private readonly node = inject(ElementRef).nativeElement as EngineNode;\n private readonly engine = this.node.host ?? inject(HostEngine);\n /** What the field last said it holds, to tell a query set from code from the field's echo. */\n private fieldText = '';\n\n constructor() {\n ownHost(this.node, NativeSearchBar);\n const listen = (event: string, handle: (payload: Record<string, unknown>) => void) =>\n this.engine.setEventListener(this.node, event, (raw) =>\n handle((raw as NativeSyntheticEvent<Record<string, unknown>>)?.nativeEvent ?? {}),\n );\n const stops = [\n listen('topSearchButtonPress', ({ text }) => this.search.emit(String(text ?? this.query()))),\n listen('topCancelButtonPress', () => this.cancel.emit()),\n listen('topSearchFocus', () => this.searchFocus.emit()),\n listen('topSearchBlur', () => this.searchBlur.emit()),\n ];\n inject(DestroyRef).onDestroy(() => stops.forEach((stop) => stop()));\n // A query that is not what the field holds was set from code: put it in the field. After the\n // render, so a query the page starts with reaches a field that has been committed.\n afterRenderEffect({\n write: () => {\n const query = this.query();\n untracked(() => {\n if (query === this.fieldText) return;\n this.fieldText = query;\n this.engine.dispatchCommand(this.node, 'setText', [query]);\n });\n },\n });\n }\n\n focus(): void {\n this.engine.dispatchCommand(this.node, 'focus');\n }\n\n blur(): void {\n this.engine.dispatchCommand(this.node, 'blur');\n }\n\n /** Empty the field, and the query with it. */\n clear(): void {\n this.fieldText = '';\n this.query.set('');\n this.engine.dispatchCommand(this.node, 'clearText');\n }\n\n /** Close the search, as the Cancel button does. */\n cancelSearch(): void {\n this.engine.dispatchCommand(this.node, 'cancelSearch');\n }\n\n protected onNativeText(text: string): void {\n this.fieldText = text;\n this.query.set(text);\n }\n}\n"]}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * A `RouterOutlet` that renders a native stack instead of swapping one view for another.
3
+ *
4
+ * The outlet's host element *is* the `RNSScreenStack`, and each activated route's component is
5
+ * created directly on its own `screen` child rather than on a wrapper view inside it (ADR 0004).
6
+ * The screens below the top stay mounted, which is what keeps a pushed-away screen's native
7
+ * state alive: its scroll offset, its text cursor, its keyboard focus.
8
+ *
9
+ * Push and pop are inferred from the calls the router already makes. With a reuse strategy that
10
+ * detaches, navigating forward is `detach()` then `activateWith()`, and navigating back is
11
+ * `detach()` then `attach(ref)` with a ref we handed out earlier. Finding that ref in our own
12
+ * stack is what identifies a pop, so nothing here needs to consult the URL.
13
+ *
14
+ * Note `activityState` is set once, to active, and never lowered. `Screen.tsx` throws on any
15
+ * decrease while `isNativeStack`, because a native stack decides what is visible from the order
16
+ * of its children rather than from a per-screen flag. Toggling that flag is for `ScreenContainer`
17
+ * (tabs), where every screen is mounted at once.
18
+ */
19
+ import { type ComponentRef, type EnvironmentInjector } from '@angular/core';
20
+ import { ActivatedRoute, type Data, type RouterOutletContract } from '@angular/router';
21
+ import * as i0 from "@angular/core";
22
+ export declare class NativeStackOutlet implements RouterOutletContract {
23
+ /**
24
+ * Named outlets work exactly as on the web: `<native-stack-outlet name="list" />` is filled by
25
+ * routes with `outlet: 'list'`. The default is the primary one. Read once, as the router's own
26
+ * outlet reads it, since an outlet cannot change which contexts it is registered under.
27
+ */
28
+ readonly name: string;
29
+ readonly supportsBindingToComponentInputs = true;
30
+ private readonly parentContexts;
31
+ private readonly renderer;
32
+ private readonly applicationRef;
33
+ private readonly injector;
34
+ private readonly host;
35
+ private readonly location;
36
+ private readonly history;
37
+ /**
38
+ * Only for the intent a navigation carries. Optional so the outlet can be exercised through
39
+ * `RouterOutletContract` directly, which is how its own tests drive it.
40
+ */
41
+ private readonly router;
42
+ private readonly errors;
43
+ private readonly entries;
44
+ /**
45
+ * The screens a replace or a reset supersedes, kept until the navigation that supersedes them
46
+ * succeeds: one that fails leaves the stack as it was.
47
+ */
48
+ private superseded;
49
+ protected readonly fill: {
50
+ flex: number;
51
+ };
52
+ constructor();
53
+ /** The screens currently in the stack, oldest first. Exposed for tests. */
54
+ get depth(): number;
55
+ get isActivated(): boolean;
56
+ get component(): Object | null;
57
+ get activatedRoute(): ActivatedRoute | null;
58
+ get activatedRouteData(): Data;
59
+ /** The input binder reads this to bind route params to component inputs. */
60
+ get activatedComponentRef(): ComponentRef<unknown> | null;
61
+ activateWith(route: ActivatedRoute, environmentInjector: EnvironmentInjector): void;
62
+ /**
63
+ * The page's component, created on its screen and rendered once.
64
+ *
65
+ * A page that throws on that first render fails the navigation, and nothing of it may stay: a
66
+ * half-made screen left on the stack is one the router does not know about, with a component
67
+ * still running on it. So its component is destroyed, its screen taken off the stack, the
68
+ * screen it was pushed from given back its change detection, and the error handed to the
69
+ * app's `ErrorHandler` before the router fails the navigation with it.
70
+ */
71
+ private createPage;
72
+ deactivate(): void;
73
+ /**
74
+ * Hand the live `ComponentRef` back to the router without destroying it. The screen stays
75
+ * mounted, so the component keeps running and its native views keep their state.
76
+ */
77
+ detach(): ComponentRef<unknown>;
78
+ /**
79
+ * Re-attach a previously detached ref. If we still hold it, everything stacked above it is a
80
+ * screen the user has navigated back past, so those are destroyed: that is the pop.
81
+ */
82
+ attach(ref: ComponentRef<unknown>, route: ActivatedRoute): void;
83
+ /**
84
+ * Route params onto the page's inputs, but only in an app that asked for it with
85
+ * `withComponentInputBinding()`, which is the only time Angular's own outlet binds them. Read
86
+ * per screen rather than once, for a test that stands the router in.
87
+ */
88
+ private bindInputs;
89
+ private get top();
90
+ /**
91
+ * What the navigation asked for, if it asked for anything. Read here rather than remembered,
92
+ * because the router is mid-navigation for exactly as long as an activation takes.
93
+ */
94
+ private currentIntent;
95
+ /**
96
+ * How the screen a navigation activates is put on screen.
97
+ *
98
+ * A push on top of a presented screen is presented the same way. `RNSScreenStack` pushes a push
99
+ * screen that follows a modal onto the navigation controller under the modal, so the router
100
+ * would be on the new route while the modal stayed in front, and the modal's own way out would
101
+ * first pop a screen nobody could see. A presentation the navigation names itself wins, and a
102
+ * reset starts a stack with nothing to follow. A presented screen that is a stack of its own is
103
+ * where a push to one of its children goes instead, inside it.
104
+ */
105
+ private presentationFor;
106
+ /** The navigation's own presentation, unless an outlet further out already presented it. */
107
+ private claimPresentation;
108
+ /** Take a screen out for good: its bindings, its component, and its native view. */
109
+ private drop;
110
+ /** Take one entry out of the stack, wherever it is, and drop it. */
111
+ private remove;
112
+ /** The id of the navigation in progress, when there is a router to say. */
113
+ private navigationId;
114
+ /**
115
+ * Take out the screens a replace or a reset supersedes once its navigation has succeeded, or
116
+ * at once when there is no navigation to wait for. A replaced screen has already been detached
117
+ * by the router, and with `replaceUrl` its history entry is gone too, so nothing will attach it
118
+ * again; the reuse strategy notices the ref is destroyed and drops its handle.
119
+ */
120
+ private supersede;
121
+ /** A navigation succeeded: what it superseded goes, and what it did is no longer undoable. */
122
+ private settle;
123
+ /**
124
+ * A navigation failed, so the router is back where it started: undo what it did here too.
125
+ *
126
+ * The screen that threw has already gone (`createPage`), but a screen this outlet activated for
127
+ * the same navigation has not when the one that threw is further in, the first screen of a
128
+ * stack inside it. That one goes, with everything in it, and the screen it covered carries on.
129
+ */
130
+ private rollBack;
131
+ /**
132
+ * Give the top screen back its change detection when the router covered it for a navigation
133
+ * that is not going to happen: the one given, or the one in progress.
134
+ */
135
+ private uncover;
136
+ /**
137
+ * `position: absolute` and the four insets, through `setStyle` rather than one `setProperty`
138
+ * so each key merges into whatever style is already on the screen instead of replacing it -
139
+ * the same merge a page's own host style gets, just asserted last so the stack's layout wins.
140
+ */
141
+ private fillScreen;
142
+ private createScreen;
143
+ /**
144
+ * Follow a pop the user already made. `historyGo`, not `back()`, because iOS coalesces a long
145
+ * swipe into a single event with a count.
146
+ *
147
+ * Only ever fires for a native dismissal: verified on device that a pop this outlet drives
148
+ * itself emits `willAppear`/`appear` for the screen below but no `dismissed`, so there is no
149
+ * double-pop to guard against.
150
+ *
151
+ * The gesture itself is unverified by tooling: idb cannot synthesise a `UIScreenEdgePan` that
152
+ * UIKit accepts, so this path was reasoned from the events rather than driven end to end.
153
+ */
154
+ private onNativeDismiss;
155
+ /**
156
+ * A back, from the button or `NativeNavigation`: pop the top screen, as long as there is one
157
+ * below it and this stack is the one the user is looking at. A stack in a tab behind, or under
158
+ * a screen pushed over the tab bar, is still subscribed, and the newest one would otherwise
159
+ * answer for the stack in front.
160
+ */
161
+ private goBack;
162
+ /** Whether the top screen is part of what the router shows now. Assumed without a router. */
163
+ private isShowing;
164
+ /**
165
+ * Take the router to the screen `steps` below the top, whether native already popped it or it
166
+ * is about to be popped because the router arrives there.
167
+ */
168
+ private popBy;
169
+ /**
170
+ * Take the router down to the screen at `index`, popping every screen above it together.
171
+ * Through history when the entries behind are these screens, so going back from there keeps
172
+ * working one screen at a time; otherwise by a navigation to it that replaces the entry, as
173
+ * `popBy` does when a tab's history interleaves.
174
+ */
175
+ private popToEntry;
176
+ /** Whether the navigation that happens next succeeds. */
177
+ private nextNavigation;
178
+ /** The url a screen was showing when it was covered, rebuilt from its own route snapshot. */
179
+ private urlOf;
180
+ /**
181
+ * The url of the history entry `offset` away, normalised the way the router writes it: null past
182
+ * the start of history, and undefined when the history is not ours to read, so the pop has to go
183
+ * through it blind.
184
+ */
185
+ private historyUrl;
186
+ private removeScreen;
187
+ /**
188
+ * What a page is created with: its route, the outlet contexts its own outlets register in, and
189
+ * whether its screen is in front - which is this screen's own say and, for a stack inside a
190
+ * screen of another, that screen's too.
191
+ */
192
+ private outletInjector;
193
+ static ɵfac: i0.ɵɵFactoryDeclaration<NativeStackOutlet, never>;
194
+ static ɵcmp: i0.ɵɵComponentDeclaration<NativeStackOutlet, "native-stack-outlet", never, {}, {}, never, never, true, never>;
195
+ }