@ng-native/router 0.15.0 → 0.17.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.
@@ -10,13 +10,27 @@
10
10
  * Native bar button items would look truer to the platform and bring menus and system symbols
11
11
  * with them, but they are data rather than views; they are a later opt-in.
12
12
  */
13
- import { Component, ElementRef, computed, inject, input } from '@angular/core';
13
+ import { Component, ElementRef, computed, effect, inject, input } from '@angular/core';
14
+ import { HostEngine, nativePlatform } from '@ng-native/fabric';
14
15
  import { ownHost } from "./own-host.js";
15
16
  import { optionalBoolean } from "./transforms.js";
16
17
  import * as i0 from "@angular/core";
18
+ /**
19
+ * A title item's least size on iOS, under any the app gives it. react-native-screens makes the
20
+ * item the bar's title view at its Yoga size, and UIKit lays out no title view of 0 by 0, so a
21
+ * `ui-host` sized to its SwiftUI content, which has no size until it is laid out, stayed 0 by 0.
22
+ */
23
+ const TITLE_LEAST = { minWidth: 1, minHeight: 1 };
17
24
  export class NativeHeaderItem {
18
25
  constructor() {
19
- ownHost(inject(ElementRef).nativeElement, this.constructor);
26
+ const node = inject(ElementRef).nativeElement;
27
+ ownHost(node, this.constructor);
28
+ const engine = (node.engine ?? inject(HostEngine));
29
+ if (nativePlatform() === 'ios') {
30
+ effect(() => {
31
+ engine.setDefaultStyle?.(node, this.slot() === 'center' ? TITLE_LEAST : undefined);
32
+ });
33
+ }
20
34
  }
21
35
  /** Which slot to sit in. Native defaults to `left`. */
22
36
  type = input(/* @ts-ignore */
@@ -1 +1 @@
1
- {"version":3,"file":"native-header-item.js","sourceRoot":"","sources":["../src/native-header-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;;AAgBlD,MAAM,OAAO,gBAAgB;IAC3B;QACE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,aAA2B,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5E,CAAC;IAED,uDAAuD;IAC9C,IAAI,GAAG,KAAK;wFAAkB,CAAC;IAExC;;;;OAIG;IACgB,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;6EAAC,CAAC;IACH,+DAA+D;IACtD,qBAAqB,GAAG,KAAK,CAAC,SAAS,6FAAI,SAAS,EAAE,eAAe,GAAG,CAAC;uGAlBvE,gBAAgB;2FAAhB,gBAAgB,udANjB,gBAAgB;;2FAMf,gBAAgB;kBAR5B,SAAS;mBAAC;oBACT,QAAQ,EAAE,oBAAoB;oBAC9B,QAAQ,EAAE,gBAAgB;oBAC1B,IAAI,EAAE;wBACJ,QAAQ,EAAE,QAAQ;wBAClB,yBAAyB,EAAE,yBAAyB;qBACrD;iBACF","sourcesContent":["/**\n * Anything Angular can render, placed in one of the navigation bar's slots.\n *\n * Commits as `RNSScreenStackHeaderSubview`, whose `type` picks the slot. A `right` item is the\n * usual \"Done\" or \"Edit\" button; `back` replaces the chevron, which needs\n * `backButtonInCustomView` on the header; `searchBar` expects a search bar rather than\n * arbitrary content.\n *\n * Press handling is the responder system, so a `pressable` inside one works like anywhere else.\n * Native bar button items would look truer to the platform and bring menus and system symbols\n * with them, but they are data rather than views; they are a later opt-in.\n */\nimport { Component, ElementRef, computed, inject, input } from '@angular/core';\nimport type { EngineNode } from '@ng-native/fabric';\nimport { ownHost } from './own-host.ts';\nimport { optionalBoolean } from './transforms.ts';\n\n/**\n * The bar slots. `title` and `center` are the same place: iOS draws both as the title view, and\n * `title` is committed as `center`, the only spelling Android's header knows.\n */\nexport type HeaderItemType = 'back' | 'left' | 'center' | 'title' | 'right' | 'searchBar';\n\n@Component({\n selector: 'native-header-item',\n template: '<ng-content />',\n host: {\n '[type]': 'slot()',\n '[hidesSharedBackground]': 'hidesSharedBackground()',\n },\n})\nexport class NativeHeaderItem {\n constructor() {\n ownHost(inject(ElementRef).nativeElement as EngineNode, this.constructor);\n }\n\n /** Which slot to sit in. Native defaults to `left`. */\n readonly type = input<HeaderItemType>();\n\n /**\n * What reaches native. react-native-screens' spec lists `title`, and iOS takes it, but Android's\n * `ScreenStackHeaderSubviewManager` throws `Unknown type title` while mounting the item, which\n * takes the screen down with it: a page that worked on iOS crashed on Android as it opened.\n */\n protected readonly slot = computed(() => {\n const type = this.type();\n return type === 'title' ? 'center' : type;\n });\n /** Opt out of the bar's shared background behind this item. */\n readonly hidesSharedBackground = input(undefined, { transform: optionalBoolean });\n}\n"]}
1
+ {"version":3,"file":"native-header-item.js","sourceRoot":"","sources":["../src/native-header-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACvF,OAAO,EAAgC,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC7F,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;;AAQlD;;;;GAIG;AACH,MAAM,WAAW,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAW,CAAC;AAU3D,MAAM,OAAO,gBAAgB;IAC3B;QACE,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,aAA2B,CAAC;QAC5D,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,CAAC,CAAoB,CAAC;QACtE,IAAI,cAAc,EAAE,KAAK,KAAK,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,EAAE;gBACV,MAAM,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACrF,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,uDAAuD;IAC9C,IAAI,GAAG,KAAK;wFAAkB,CAAC;IAExC;;;;OAIG;IACgB,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;6EAAC,CAAC;IACH,+DAA+D;IACtD,qBAAqB,GAAG,KAAK,CAAC,SAAS,6FAAI,SAAS,EAAE,eAAe,GAAG,CAAC;uGAzBvE,gBAAgB;2FAAhB,gBAAgB,udANjB,gBAAgB;;2FAMf,gBAAgB;kBAR5B,SAAS;mBAAC;oBACT,QAAQ,EAAE,oBAAoB;oBAC9B,QAAQ,EAAE,gBAAgB;oBAC1B,IAAI,EAAE;wBACJ,QAAQ,EAAE,QAAQ;wBAClB,yBAAyB,EAAE,yBAAyB;qBACrD;iBACF","sourcesContent":["/**\n * Anything Angular can render, placed in one of the navigation bar's slots.\n *\n * Commits as `RNSScreenStackHeaderSubview`, whose `type` picks the slot. A `right` item is the\n * usual \"Done\" or \"Edit\" button; `back` replaces the chevron, which needs\n * `backButtonInCustomView` on the header; `searchBar` expects a search bar rather than\n * arbitrary content.\n *\n * Press handling is the responder system, so a `pressable` inside one works like anywhere else.\n * Native bar button items would look truer to the platform and bring menus and system symbols\n * with them, but they are data rather than views; they are a later opt-in.\n */\nimport { Component, ElementRef, computed, effect, inject, input } from '@angular/core';\nimport { type Engine, type EngineNode, HostEngine, nativePlatform } from '@ng-native/fabric';\nimport { ownHost } from './own-host.ts';\nimport { optionalBoolean } from './transforms.ts';\n\n/**\n * The bar slots. `title` and `center` are the same place: iOS draws both as the title view, and\n * `title` is committed as `center`, the only spelling Android's header knows.\n */\nexport type HeaderItemType = 'back' | 'left' | 'center' | 'title' | 'right' | 'searchBar';\n\n/**\n * A title item's least size on iOS, under any the app gives it. react-native-screens makes the\n * item the bar's title view at its Yoga size, and UIKit lays out no title view of 0 by 0, so a\n * `ui-host` sized to its SwiftUI content, which has no size until it is laid out, stayed 0 by 0.\n */\nconst TITLE_LEAST = { minWidth: 1, minHeight: 1 } as const;\n\n@Component({\n selector: 'native-header-item',\n template: '<ng-content />',\n host: {\n '[type]': 'slot()',\n '[hidesSharedBackground]': 'hidesSharedBackground()',\n },\n})\nexport class NativeHeaderItem {\n constructor() {\n const node = inject(ElementRef).nativeElement as EngineNode;\n ownHost(node, this.constructor);\n const engine = (node.engine ?? inject(HostEngine)) as Partial<Engine>;\n if (nativePlatform() === 'ios') {\n effect(() => {\n engine.setDefaultStyle?.(node, this.slot() === 'center' ? TITLE_LEAST : undefined);\n });\n }\n }\n\n /** Which slot to sit in. Native defaults to `left`. */\n readonly type = input<HeaderItemType>();\n\n /**\n * What reaches native. react-native-screens' spec lists `title`, and iOS takes it, but Android's\n * `ScreenStackHeaderSubviewManager` throws `Unknown type title` while mounting the item, which\n * takes the screen down with it: a page that worked on iOS crashed on Android as it opened.\n */\n protected readonly slot = computed(() => {\n const type = this.type();\n return type === 'title' ? 'center' : type;\n });\n /** Opt out of the bar's shared background behind this item. */\n readonly hidesSharedBackground = input(undefined, { transform: optionalBoolean });\n}\n"]}
@@ -19,7 +19,9 @@ export declare class NativeSearchBar {
19
19
  readonly obscureBackground: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
20
20
  /** Hide the navigation bar while the field is being typed in. */
21
21
  readonly hideNavigationBar: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
22
+ /** iOS: the cursor and the Cancel button. Android: the field's background. */
22
23
  readonly tintColor: import("@angular/core").InputSignal<string | undefined>;
24
+ /** The typed text. */
23
25
  readonly textColor: import("@angular/core").InputSignal<string | undefined>;
24
26
  /** The keyboard's search key was pressed, with the text in the field. */
25
27
  readonly search: import("@angular/core").OutputEmitterRef<string>;
@@ -18,7 +18,9 @@
18
18
  * from code.
19
19
  *
20
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.
21
+ * control under the header, and a token is text. Nor has its search bar a font prop on iOS or
22
+ * Android, so the field and placeholder stay in the system font; `<search-field>` from
23
+ * `@ng-native/expo/search-field` takes the font its CSS resolves to.
22
24
  */
23
25
  import { Component, DestroyRef, ElementRef, afterRenderEffect, inject, input, model, output, untracked, } from '@angular/core';
24
26
  import { HostEngine } from '@ng-native/fabric';
@@ -48,8 +50,10 @@ export class NativeSearchBar {
48
50
  obscureBackground = input(undefined, { ...(ngDevMode ? { debugName: "obscureBackground" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
49
51
  /** Hide the navigation bar while the field is being typed in. */
50
52
  hideNavigationBar = input(undefined, { ...(ngDevMode ? { debugName: "hideNavigationBar" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
53
+ /** iOS: the cursor and the Cancel button. Android: the field's background. */
51
54
  tintColor = input(/* @ts-ignore */
52
55
  ...(ngDevMode ? [undefined, { debugName: "tintColor" }] : /* istanbul ignore next */ []));
56
+ /** The typed text. */
53
57
  textColor = input(/* @ts-ignore */
54
58
  ...(ngDevMode ? [undefined, { debugName: "textColor" }] : /* istanbul ignore next */ []));
55
59
  /** The keyboard's search key was pressed, with the text in the field. */
@@ -59,7 +63,7 @@ export class NativeSearchBar {
59
63
  searchFocus = output();
60
64
  searchBlur = output();
61
65
  node = inject(ElementRef).nativeElement;
62
- engine = this.node.host ?? inject(HostEngine);
66
+ engine = this.node.engine ?? inject(HostEngine);
63
67
  /** What the field last said it holds, to tell a query set from code from the field's echo. */
64
68
  fieldText = '';
65
69
  constructor() {
@@ -1 +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"]}
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. Nor has its search bar a font prop on iOS or\n * Android, so the field and placeholder stay in the system font; `<search-field>` from\n * `@ng-native/expo/search-field` takes the font its CSS resolves to.\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 /** iOS: the cursor and the Cancel button. Android: the field's background. */\n readonly tintColor = input<string>();\n /** The typed text. */\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.engine ?? 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"]}
@@ -503,6 +503,11 @@ export class NativeTabsOutlet {
503
503
  if (!selection)
504
504
  return;
505
505
  this.provenance = selection.provenance;
506
+ // Native answering a request of ours is not a switch to follow. The router made the request,
507
+ // and an answer that arrives after a later request, such as a cold-start link's, names a tab
508
+ // the router has already left.
509
+ if (selection.actionOrigin === 'programmatic-js')
510
+ return;
506
511
  const entry = this.readTabs().find((tab) => screenKeyOf(tab.key) === selection.selectedScreenKey);
507
512
  if (!entry || (entry === this.selected && !this.tappedBack(selection)))
508
513
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"native-tabs-outlet.js","sourceRoot":"","sources":["../src/native-tabs-outlet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A `RouterOutlet` that renders a native tab bar: a `UITabBarController` on iOS, a bottom\n * navigation bar on Android.\n *\n * The outlet's host element *is* the tabs host, and each `<native-tab>` in its content is one\n * item and the screen behind it. An activated route's component is created on a child view of\n * the matching tab screen. The screen belongs to the tab declaration and must survive the route\n * component being destroyed; Angular removes a component's host node when it destroys the ref.\n *\n * ```html\n * <native-tabs-outlet>\n * <native-tab path=\"library\" title=\"Library\" sfSymbol=\"books.vertical.fill\" />\n * <native-tab path=\"inbox\" title=\"Inbox\" sfSymbol=\"tray\" [badge]=\"unread()\" />\n * </native-tabs-outlet>\n * ```\n *\n * **Native holds the selection, not us.** The tabs host owns its navigation state and reports\n * every change - a tap, or one we asked for - through `tabSelected`, carrying a `provenance`\n * number that increments per change. We send `navStateRequest` with the provenance of the last\n * state we acknowledged, which is how native tells a stale request from a current one when a tap\n * and a navigation cross in flight. The alternative, holding the selection in JS, means a tap is\n * only reflected after a round trip, and the bar lags the finger. See ADR 0006.\n *\n * **Each tab keeps its own screen mounted**, so switching away and back finds a tab exactly as it\n * was: its scroll offset, its text, and its own stack if it has one. That is the reuse strategy\n * detaching the tab's whole subtree rather than only its leaf.\n */\nimport {\n ApplicationRef,\n ChangeDetectorRef,\n Component,\n DestroyRef,\n ElementRef,\n ErrorHandler,\n Injector,\n Renderer2,\n computed,\n contentChildren,\n createComponent,\n effect,\n inject,\n input,\n signal,\n untracked,\n ViewContainerRef,\n type AfterContentInit,\n type ComponentRef,\n type EnvironmentInjector,\n type Type,\n type WritableSignal,\n} from '@angular/core';\nimport { SCREEN_IN_FRONT } from '@ng-native/device';\nimport {\n ActivatedRoute,\n ChildrenOutletContexts,\n NavigationEnd,\n PRIMARY_OUTLET,\n Router,\n type Data,\n type Route,\n type RouterOutletContract,\n} from '@angular/router';\nimport { bindRouteInputs } from './bind-route-inputs.ts';\nimport { NATIVE_TAB_DEFAULTS } from './native-bar-defaults.ts';\nimport { NativeBack, isShowing } from './native-back.ts';\nimport { optionalBoolean } from './transforms.ts';\nimport { NativeTab, screenKeyOf } from './native-tab.ts';\nimport { ownHost } from './own-host.ts';\nimport { markTabRoute } from './tab-routes.ts';\nimport { IN_TAB, type InTab } from './in-tab.ts';\nimport { taken, withoutPresented } from './presented-route.ts';\nimport { SVG_ICON_HOST } from './svg-icons.ts';\n\n/** A url without its query or fragment. */\nconst pathOnly = (url: string): string => url.split(/[?#]/, 1)[0]!;\n\n/**\n * Whether one of `routes` matches `segments`, whole or up to lazy children not loaded yet, which a\n * route that took a static segment of its own is taken to lead to. A parameter alone is not: it\n * takes any segment, pages outside the bar included, and its children may match none of the rest.\n */\nfunction reaches(routes: readonly Route[], segments: readonly string[]): boolean {\n return routes.some((route) => {\n const count = taken(route, segments);\n if (count === null) return false;\n const rest = segments.slice(count);\n if (rest.length === 0) return true;\n if (route.children) return reaches(route.children, rest);\n const named = route.path!.split('/').some((part) => part && !part.startsWith(':'));\n return named && route.loadChildren !== undefined;\n });\n}\n\ninterface TabEntry {\n /** The element in the bar now: an `@if` can take it away and bring another back. */\n tab: NativeTab;\n /** The key native identifies this tab by: its path, unique among the bar's items. */\n readonly key: string;\n /** The url this tab was last on, so returning to it returns where the user left. */\n url: string;\n ref: ComponentRef<unknown> | null;\n route: ActivatedRoute | null;\n detached: boolean;\n /** Stops feeding route params into the component's inputs. */\n unbind: () => void;\n /** Whether this tab is the one showing, for what its screens hold: see `SCREEN_IN_FRONT`. */\n readonly inFront: WritableSignal<boolean>;\n /** What the tab's stacks dismiss when another tab comes in front: see `IN_TAB`. */\n readonly leaving: Set<() => string | null>;\n}\n\n/** What `tabSelected` carries. Only these fields matter here; the rest is diagnostics. */\ninterface TabSelection {\n readonly selectedScreenKey: string;\n readonly provenance: number;\n /** `'user'` for a tap. Native reports the changes it was asked for too, under other names. */\n readonly actionOrigin?: string;\n /** Set when the user tapped the tab already in front, which is not a tap back. */\n readonly isRepeated?: boolean;\n}\n\n@Component({\n selector: 'native-tabs-outlet',\n template: '<ng-content />',\n providers: [{ provide: SVG_ICON_HOST, useFactory: () => inject(ViewContainerRef) }],\n host: {\n '[style]': 'fill',\n '[tabBarHidden]': 'barHidden()',\n '[tabBarTintColor]': 'tintColor() ?? defaults().tintColor',\n '[nativeContainerBackgroundColor]': 'backgroundColor() ?? defaults().backgroundColor',\n '[colorScheme]': 'colorScheme() ?? defaults().colorScheme',\n '[tabBarMinimizeBehavior]': 'minimizeBehavior()',\n '[tabBarControllerMode]': 'controllerMode()',\n '[tabBarRespectsIMEInsets]': 'respectsKeyboard()',\n },\n})\nexport class NativeTabsOutlet implements RouterOutletContract, AfterContentInit {\n name = 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 changeDetector = inject(ChangeDetectorRef);\n private readonly injector = inject(Injector);\n private readonly host = inject(ElementRef);\n private readonly route = inject(ActivatedRoute);\n /** Optional so the outlet can be driven through `RouterOutletContract` directly, as tests do. */\n private readonly router = inject(Router, { optional: true });\n private readonly errors = inject(ErrorHandler);\n /** What activation has reported already, so the failed navigation it causes is not reported again. */\n private readonly reported = new WeakSet<object>();\n /** The app's `withTabDefaults`, for whatever the outlet does not bind itself. */\n protected readonly defaults = inject(NATIVE_TAB_DEFAULTS);\n\n private readonly declared = contentChildren(NativeTab);\n private readonly entries: TabEntry[] = [];\n private selected: TabEntry | null = null;\n /** The provenance of the last state native told us about. Starts before native's first. */\n private provenance = 0;\n\n protected readonly fill = { flex: 1 };\n\n // --- the bar itself -----------------------------------------------------\n\n /** Hide the bar without unmounting the tabs, for a screen that wants the whole window. */\n readonly barHidden = input(undefined, { transform: optionalBoolean });\n /** The colour of the selected item. iOS. */\n readonly tintColor = input<string | number>();\n /** Behind the tabs, where a screen does not paint. */\n readonly backgroundColor = input<string | number>();\n /** Force the bar's light or dark appearance, whatever the app's is. */\n readonly colorScheme = input<'inherit' | 'light' | 'dark'>();\n /** iOS 26: let the bar shrink out of the way as content scrolls. */\n readonly minimizeBehavior = input<'automatic' | 'never' | 'onScrollDown' | 'onScrollUp'>();\n /** iOS: `tabSidebar` is the iPad layout, with the tabs down the side. */\n readonly controllerMode = input<'automatic' | 'tabBar' | 'tabSidebar'>();\n /** Android: keep the bar above the keyboard rather than behind it. */\n readonly respectsKeyboard = input(undefined, { transform: optionalBoolean });\n\n constructor() {\n ownHost(this.host.nativeElement);\n // In the constructor rather than a lifecycle hook: the router activates a child route as soon\n // as this component exists, which is before any hook has run.\n this.parentContexts.onChildOutletCreated(this.name, this);\n\n this.renderer.listen(\n this.host.nativeElement,\n 'tabSelected',\n (event: { nativeEvent?: TabSelection }) => this.onNativeSelect(event?.nativeEvent),\n );\n\n // An `@if` that takes a tab away and brings it back makes a new element: its page follows it\n // at once, since the tab may be the one showing, with no tap or navigation to read them on.\n effect(() => {\n this.declared();\n if (this.entries.length > 0) untracked(() => this.readTabs());\n });\n\n // A push inside a tab's own stack reuses the tab's route, so this outlet is never activated\n // for it; the router's navigation is the only sign. Without this, coming back to the tab\n // returns it to its root and pops the screens the user left it on.\n const following = this.router?.events?.subscribe((event) => {\n // Without a page presented over the bar, which is no part of where the tab is.\n if (event instanceof NavigationEnd) {\n this.follow(withoutPresented(this.router!, event.urlAfterRedirects));\n }\n });\n\n // Android's back button, and `NativeNavigation.back()`, once the stack in front, if the tab\n // has one, is at its root. Subscribed before any tab's own stack, so it is asked after them.\n const back = inject(NativeBack);\n const unsubscribeBack = back.handle(() => this.goBack());\n const unsubscribeBar = back.addTabBar({\n unopenedTabOf: (url) => this.unopenedTabOf(url),\n behind: (url) => this.behind(url),\n coveredAt: (url) => this.coveredAt(url),\n });\n\n inject(DestroyRef).onDestroy(() => {\n unsubscribeBack();\n unsubscribeBar();\n following?.unsubscribe();\n for (const entry of this.entries) {\n entry.unbind();\n entry.ref?.destroy();\n }\n this.entries.length = 0;\n // Only while it is this outlet's, as for a stack: see `NativeStackOutlet`.\n if (this.parentContexts.getContext(this.name)?.outlet === this) {\n this.parentContexts.onChildOutletDestroyed(this.name);\n }\n });\n }\n\n /** A bar nobody has navigated into yet still has to show a selected item. */\n ngAfterContentInit(): void {\n this.readTabs();\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, as `NativeStackOutlet` takes its own: a tab bar held behind a condition until a session\n * is ready. Once the tabs are read, since activating one needs to know which they are.\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 /** The tabs in the bar, in the order they were first in it. Exposed for tests. */\n get tabKeys(): string[] {\n return this.readTabs().map((entry) => entry.key);\n }\n\n /** Which tab native is showing. Exposed for tests. */\n get selectedKey(): string | null {\n return this.selected?.key ?? null;\n }\n\n // --- RouterOutletContract ----------------------------------------------\n\n get isActivated(): boolean {\n return this.selected?.ref != null && !this.selected.detached;\n }\n\n get component(): Object | null {\n return this.isActivated ? (this.selected!.ref!.instance as Object) : null;\n }\n\n get activatedRoute(): ActivatedRoute | null {\n return this.isActivated ? this.selected!.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.selected?.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 const entry = this.entryFor(route);\n\n // The tab screen is owned by <native-tab>, not by this route component. If the route uses\n // deactivate() rather than detach(), Angular removes the component host on destroy. Giving\n // the component its own child host keeps that removal from taking the tab bar item with it.\n const content = ownHost(this.renderer.createElement('view'));\n this.renderer.setStyle(content, 'flex', 1);\n this.renderer.appendChild(entry.tab.screen, content);\n\n let ref: ComponentRef<unknown> | undefined;\n try {\n ref = createComponent(component, {\n environmentInjector,\n elementInjector: this.outletInjector(route, entry),\n hostElement: content as Element,\n });\n this.applicationRef.attachView(ref.hostView);\n // Route params onto inputs before the first change detection, as the stack outlet does: a\n // required input still unset when the page first renders throws NG0950.\n entry.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 } catch (error) {\n this.abandon(entry, ref, content);\n this.errors.handleError(error);\n if (error !== null && typeof error === 'object') this.reported.add(error);\n throw error;\n }\n\n entry.ref = ref;\n entry.route = route;\n entry.detached = false;\n this.select(entry);\n }\n\n /**\n * Destroy the tab page in front: nothing once the router has detached it, as Angular's own\n * outlet does nothing then. A tab under a route with no component of its own, a `loadChildren`\n * wrapper or a group, has the router detach the page and then deactivate this same outlet, and\n * that page is the tab, kept for when it is selected again.\n */\n deactivate(): void {\n if (!this.isActivated) return;\n const entry = this.selected!;\n entry.unbind();\n entry.unbind = () => {};\n entry.ref!.destroy();\n entry.ref = null;\n entry.route = null;\n }\n\n /**\n * Hand the live `ComponentRef` back to the router. The tab's screen stays where it is with the\n * component still inside it, so the tab keeps running while another one is in front.\n */\n detach(): ComponentRef<unknown> {\n const entry = this.selected;\n if (!entry?.ref) throw new Error('[angular-native] outlet is not activated, nothing to detach');\n entry.detached = true;\n entry.inFront.set(false);\n // As in the stack outlet: stop change detection without unmounting the views.\n entry.ref.hostView.detach();\n return entry.ref;\n }\n\n attach(ref: ComponentRef<unknown>, route: ActivatedRoute): void {\n const entry = this.entryFor(route);\n\n // A ref from a previous instance of this outlet still lives on its old tab screen, which is\n // gone; re-parent it onto this one's rather than rebuild the tab.\n if (entry.ref !== ref) {\n this.renderer.appendChild(entry.tab.screen, ref.location.nativeElement);\n this.applicationRef.attachView(ref.hostView);\n entry.ref = ref;\n }\n\n entry.route = route;\n entry.detached = false;\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 ref.hostView.reattach();\n this.select(entry);\n }\n\n // --- native tabs --------------------------------------------------------\n\n /**\n * Undo a tab page that threw on its first render, which fails the navigation: its component\n * and its content view go, and the tab that was showing carries on, change detection and all.\n */\n private abandon(entry: TabEntry, ref: ComponentRef<unknown> | undefined, content: unknown): void {\n entry.unbind();\n entry.unbind = () => {};\n ref?.destroy();\n this.renderer.removeChild(entry.tab.screen, content);\n const showing = this.selected;\n if (showing?.detached && showing.ref) {\n showing.detached = false;\n showing.ref.hostView.reattach();\n }\n }\n\n /** Route params onto inputs only under `withComponentInputBinding()`, as in the stack outlet. */\n private bindInputs(ref: ComponentRef<unknown>, route: ActivatedRoute): () => void {\n return this.router?.componentInputBindingEnabled ? bindRouteInputs(ref, route) : () => {};\n }\n\n /**\n * Take the bar from the `<native-tab>` elements in the content, adding any that appeared since\n * the last read, as one an `@if` shows once a feature flag turns on, and following one that was\n * taken away and brought back.\n *\n * On demand rather than in a lifecycle hook, because the router activates a child route during\n * this component's creation, before any hook has run - but after the content nodes themselves\n * exist, which is all this needs.\n */\n private readTabs(): TabEntry[] {\n const first = this.entries.length === 0;\n const children = this.route.routeConfig?.children ?? [];\n for (const tab of this.declared()) {\n const key = tab.path();\n const known = this.entries.find((entry) => entry.key === key);\n if (known) {\n this.move(known, tab);\n continue;\n }\n this.entries.push({\n tab,\n key,\n url: '',\n ref: null,\n route: null,\n detached: false,\n unbind: () => {},\n inFront: signal(false),\n leaving: new Set(),\n });\n // The reuse strategy detaches a tab whole, and has only the route to go on.\n // A path can have multiple route configs selected by canMatch (for example an iPad split\n // layout and an iPhone stack). Mark every variant: the reuse strategy sees the config\n // Angular actually matched, which may not be the first one in the route array.\n for (const config of children) {\n if (config.path === key) markTabRoute(config);\n }\n }\n\n if (this.entries.length === 0) {\n throw new Error(\n '[angular-native] <native-tabs-outlet> has no tabs. Put a <native-tab path=\"...\"> ' +\n 'inside it for each child route the bar should reach.',\n );\n }\n // Before the first navigation nothing is selected, which is not a state a tab bar has.\n if (first) this.request(this.entries[0]!);\n return this.entries;\n }\n\n /**\n * Give an entry the `<native-tab>` now declared for its path, when that is not the one it was\n * read with: an `@if` that took the tab away and brought it back made a new element, with a new\n * screen. The page goes over to that screen as it is, so the tab comes back where it was left.\n */\n private move(entry: TabEntry, tab: NativeTab): void {\n if (entry.tab === tab) return;\n entry.tab = tab;\n if (entry.ref) this.renderer.appendChild(tab.screen, entry.ref.location.nativeElement);\n }\n\n /**\n * The tab `route` is the page of, by its path from this outlet's route down to it. A route with\n * no component above the page is part of that path: a `loadChildren` wrapper takes the tab's\n * path and leaves `''` to the page under it, and a group is a `''` of its own.\n */\n private entryFor(route: ActivatedRoute): TabEntry {\n const config = route.routeConfig ?? route.snapshot.routeConfig;\n const paths = [config?.path];\n for (let above = route.parent; above && !above.component; above = above.parent) {\n paths.unshift(above.routeConfig?.path);\n }\n const path = paths.filter(Boolean).join('/');\n const entry = this.readTabs().find((candidate) => candidate.key === path);\n if (!entry) {\n throw new Error(\n `[angular-native] no <native-tab> has path=\"${path}\". Every child route the bar can ` +\n `reach needs one, and its path is what native identifies the tab by.`,\n );\n }\n // Under a wrapper the page's config is not one of the children `readTabs` marked, and it is\n // the one the reuse strategy is asked to detach whole.\n if (config) markTabRoute(config);\n return entry;\n }\n\n /** Remember where this tab is, and tell native to show it. */\n private select(entry: TabEntry): void {\n const left = this.selected;\n if (left && left !== entry) this.leave(left);\n this.selected = entry;\n for (const other of this.entries) other.inFront.set(other === entry);\n entry.url = this.router?.url ?? entry.url;\n this.request(entry);\n }\n\n /**\n * Another tab came in front of `entry`: its stacks dismiss what they presented, and it is\n * remembered at the page beneath, where the outermost stack that dismissed something is left.\n */\n private leave(entry: TabEntry): void {\n let url: string | null = null;\n for (const dismiss of entry.leaving) {\n const beneath = dismiss();\n url ??= beneath;\n }\n if (url !== null) entry.url = url;\n }\n\n /**\n * A back with nothing left to pop inside the tab: go to the first tab, where it was left, which\n * is what a bottom navigation bar does on Android. From the first tab, decline, so the platform\n * leaves the app. The order tabs were visited in is not retraced, so a back never lands on a\n * tab the user did not expect. Not while the bar is covered by a screen pushed over it: that\n * screen's stack answers instead.\n */\n private goBack(): boolean {\n const first = this.entries[0];\n const selected = this.selected;\n if (!first || !selected || selected === first || !this.router) return false;\n if (!this.isActivated || !isShowing(this.router, selected.route)) return false;\n void this.router.navigateByUrl(this.urlOf(first));\n return true;\n }\n\n /** Keep the tab in front on the url it has reached, as long as the url is still inside it. */\n private follow(url: string): void {\n const entry = this.selected;\n if (entry && this.tabOf(url) === entry) entry.url = url;\n }\n\n /**\n * The url of the tab `url` is a page inside, when nothing has opened that tab: the tab's own\n * first screen, which a push into the tab from outside it shows first.\n */\n private unopenedTabOf(url: string): string | null {\n const entry = this.tabOf(url);\n if (!entry || entry.ref) return null;\n const root = this.pathOf(entry);\n return pathOnly(url) === root ? null : root;\n }\n\n /** Where the tab `url` is in was left, while a screen over the bar covers it. */\n private coveredAt(url: string): string | null {\n if (this.injector.get(SCREEN_IN_FRONT)()) return null;\n const entry = this.tabOf(url);\n return entry ? this.urlOf(entry) : null;\n }\n\n /** Whether `url` is a tab other than the one in front, or a page inside one. */\n private behind(url: string): boolean {\n const entry = this.tabOf(url);\n return entry !== null && entry !== this.selected;\n }\n\n /**\n * The tab `url` is in: the one with the longest url that starts it. A tab at `''` has the bar's\n * own url, which at the root starts every url, pages outside the bar included, so it takes only\n * a url its routes lead to, as far as they are loaded. A wildcard or a custom matcher is not\n * followed, as `taken` follows neither: a page only one of them shows is in no tab.\n */\n private tabOf(url: string): TabEntry | null {\n const path = pathOnly(url);\n let found: TabEntry | null = null;\n for (const entry of this.entries) {\n const root = this.pathOf(entry);\n const inside = path === root || path.startsWith(root.endsWith('/') ? root : `${root}/`);\n if (!inside || (found && this.pathOf(found).length >= root.length)) continue;\n if (!entry.key && !this.leadsInto(entry, path.slice(root.length))) continue;\n found = entry;\n }\n return found;\n }\n\n /** Whether the routes of the tab at `''` lead to `rest`, the path under the bar's own url. */\n private leadsInto(entry: TabEntry, rest: string): boolean {\n const segments = rest.split('/').filter(Boolean);\n const own = entry.route?.snapshot.routeConfig;\n const routes = own\n ? [own]\n : (this.route.routeConfig?.children ?? []).filter((config) => config.path === '');\n return segments.length === 0 || reaches(routes, segments);\n }\n\n private request(entry: TabEntry): void {\n this.renderer.setProperty(this.host.nativeElement, 'navStateRequest', {\n selectedScreenKey: screenKeyOf(entry.key),\n baseProvenance: this.provenance,\n });\n }\n\n /**\n * Native switched tab. Acknowledge the new state, then navigate: the router is authoritative\n * about what is on screen (ADR 0003), so the tap becomes a navigation to where that tab was,\n * and the activation that follows is what fills the tab in.\n */\n private onNativeSelect(selection: TabSelection | undefined): void {\n if (!selection) return;\n this.provenance = selection.provenance;\n\n const entry = this.readTabs().find(\n (tab) => screenKeyOf(tab.key) === selection.selectedScreenKey,\n );\n if (!entry || (entry === this.selected && !this.tappedBack(selection))) return;\n\n // Returning to a tab returns to the url it was last on, which is the whole point of keeping\n // it mounted. A tab never visited starts at its own path.\n // A navigation that fails is reported, unless activation reported it already: a page that\n // does not load, caught here, would otherwise leave nothing but a tab that will not open.\n void this.router?.navigateByUrl(this.urlOf(entry)).then(\n (arrived) => this.revertUnless(arrived),\n (error: unknown) => {\n if (error === null || typeof error !== 'object' || !this.reported.has(error)) {\n this.errors.handleError(error);\n }\n this.revertUnless(false);\n },\n );\n }\n\n /**\n * Whether the user tapped the tab in front while a navigation is running: back from the tab that\n * navigation is still loading, so the tab in front is where it is to end. A selection native\n * reports because the outlet asked for it is not a tap, and cancels nothing. Nor does a tap on\n * the tab already in front (native reports it as repeated): no other tab was tapped first, so a\n * navigation running then is one from code, or a push inside the tab, and is left to finish.\n */\n private tappedBack(selection: TabSelection): boolean {\n return (\n selection.actionOrigin === 'user' &&\n !selection.isRepeated &&\n !!this.router?.getCurrentNavigation()\n );\n }\n\n /**\n * Native switched tab before the router agreed to. When a guard refuses, or the navigation\n * fails, the router stays where it was and so must the bar, or it shows a tab nobody is on.\n * Not while another navigation is under way: that one superseded this, and its own activation\n * selects the tab it lands on.\n */\n private revertUnless(arrived: boolean): void {\n if (arrived || !this.selected || this.router?.getCurrentNavigation()) return;\n this.request(this.selected);\n // A failed navigation ends in a promise callback, which schedules no change detection, and a\n // prop reaches native only with the commit at the end of a pass. Without one the bar stayed\n // on the tab that failed until something else happened to render.\n this.changeDetector.markForCheck();\n }\n\n private urlOf(entry: TabEntry): string {\n return entry.url && this.tabOf(entry.url) === entry ? entry.url : this.pathOf(entry);\n }\n\n /** A tab's own url, from the outlet's route down. */\n private pathOf(entry: TabEntry): string {\n const parent = this.route.snapshot.pathFromRoot\n .flatMap((snapshot) => snapshot.url.map((segment) => segment.path))\n .join('/');\n return `/${[parent, entry.key].filter(Boolean).join('/')}`;\n }\n\n /**\n * As the stack outlet's: the route, the outlet contexts, and whether the tab is showing. And the\n * tab itself, for its stacks to hear when another comes in front.\n */\n private outletInjector(route: ActivatedRoute, entry: TabEntry): Injector {\n const outer = this.injector.get(SCREEN_IN_FRONT);\n const tab: InTab = {\n onLeave: (leave) => (entry.leaving.add(leave), () => entry.leaving.delete(leave)),\n };\n return Injector.create({\n parent: this.injector,\n providers: [\n { provide: SCREEN_IN_FRONT, useValue: computed(() => outer() && entry.inFront()) },\n { provide: IN_TAB, useValue: tab },\n { provide: ActivatedRoute, useValue: route },\n {\n provide: ChildrenOutletContexts,\n useValue: this.parentContexts.getOrCreateContext(this.name).children,\n },\n ],\n });\n }\n}\n"]}
1
+ {"version":3,"file":"native-tabs-outlet.js","sourceRoot":"","sources":["../src/native-tabs-outlet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A `RouterOutlet` that renders a native tab bar: a `UITabBarController` on iOS, a bottom\n * navigation bar on Android.\n *\n * The outlet's host element *is* the tabs host, and each `<native-tab>` in its content is one\n * item and the screen behind it. An activated route's component is created on a child view of\n * the matching tab screen. The screen belongs to the tab declaration and must survive the route\n * component being destroyed; Angular removes a component's host node when it destroys the ref.\n *\n * ```html\n * <native-tabs-outlet>\n * <native-tab path=\"library\" title=\"Library\" sfSymbol=\"books.vertical.fill\" />\n * <native-tab path=\"inbox\" title=\"Inbox\" sfSymbol=\"tray\" [badge]=\"unread()\" />\n * </native-tabs-outlet>\n * ```\n *\n * **Native holds the selection, not us.** The tabs host owns its navigation state and reports\n * every change - a tap, or one we asked for - through `tabSelected`, carrying a `provenance`\n * number that increments per change. We send `navStateRequest` with the provenance of the last\n * state we acknowledged, which is how native tells a stale request from a current one when a tap\n * and a navigation cross in flight. The alternative, holding the selection in JS, means a tap is\n * only reflected after a round trip, and the bar lags the finger. See ADR 0006.\n *\n * **Each tab keeps its own screen mounted**, so switching away and back finds a tab exactly as it\n * was: its scroll offset, its text, and its own stack if it has one. That is the reuse strategy\n * detaching the tab's whole subtree rather than only its leaf.\n */\nimport {\n ApplicationRef,\n ChangeDetectorRef,\n Component,\n DestroyRef,\n ElementRef,\n ErrorHandler,\n Injector,\n Renderer2,\n computed,\n contentChildren,\n createComponent,\n effect,\n inject,\n input,\n signal,\n untracked,\n ViewContainerRef,\n type AfterContentInit,\n type ComponentRef,\n type EnvironmentInjector,\n type Type,\n type WritableSignal,\n} from '@angular/core';\nimport { SCREEN_IN_FRONT } from '@ng-native/device';\nimport {\n ActivatedRoute,\n ChildrenOutletContexts,\n NavigationEnd,\n PRIMARY_OUTLET,\n Router,\n type Data,\n type Route,\n type RouterOutletContract,\n} from '@angular/router';\nimport { bindRouteInputs } from './bind-route-inputs.ts';\nimport { NATIVE_TAB_DEFAULTS } from './native-bar-defaults.ts';\nimport { NativeBack, isShowing } from './native-back.ts';\nimport { optionalBoolean } from './transforms.ts';\nimport { NativeTab, screenKeyOf } from './native-tab.ts';\nimport { ownHost } from './own-host.ts';\nimport { markTabRoute } from './tab-routes.ts';\nimport { IN_TAB, type InTab } from './in-tab.ts';\nimport { taken, withoutPresented } from './presented-route.ts';\nimport { SVG_ICON_HOST } from './svg-icons.ts';\n\n/** A url without its query or fragment. */\nconst pathOnly = (url: string): string => url.split(/[?#]/, 1)[0]!;\n\n/**\n * Whether one of `routes` matches `segments`, whole or up to lazy children not loaded yet, which a\n * route that took a static segment of its own is taken to lead to. A parameter alone is not: it\n * takes any segment, pages outside the bar included, and its children may match none of the rest.\n */\nfunction reaches(routes: readonly Route[], segments: readonly string[]): boolean {\n return routes.some((route) => {\n const count = taken(route, segments);\n if (count === null) return false;\n const rest = segments.slice(count);\n if (rest.length === 0) return true;\n if (route.children) return reaches(route.children, rest);\n const named = route.path!.split('/').some((part) => part && !part.startsWith(':'));\n return named && route.loadChildren !== undefined;\n });\n}\n\ninterface TabEntry {\n /** The element in the bar now: an `@if` can take it away and bring another back. */\n tab: NativeTab;\n /** The key native identifies this tab by: its path, unique among the bar's items. */\n readonly key: string;\n /** The url this tab was last on, so returning to it returns where the user left. */\n url: string;\n ref: ComponentRef<unknown> | null;\n route: ActivatedRoute | null;\n detached: boolean;\n /** Stops feeding route params into the component's inputs. */\n unbind: () => void;\n /** Whether this tab is the one showing, for what its screens hold: see `SCREEN_IN_FRONT`. */\n readonly inFront: WritableSignal<boolean>;\n /** What the tab's stacks dismiss when another tab comes in front: see `IN_TAB`. */\n readonly leaving: Set<() => string | null>;\n}\n\n/** What `tabSelected` carries. Only these fields matter here; the rest is diagnostics. */\ninterface TabSelection {\n readonly selectedScreenKey: string;\n readonly provenance: number;\n /** `'user'` for a tap. Native reports the changes it was asked for too, under other names. */\n readonly actionOrigin?: string;\n /** Set when the user tapped the tab already in front, which is not a tap back. */\n readonly isRepeated?: boolean;\n}\n\n@Component({\n selector: 'native-tabs-outlet',\n template: '<ng-content />',\n providers: [{ provide: SVG_ICON_HOST, useFactory: () => inject(ViewContainerRef) }],\n host: {\n '[style]': 'fill',\n '[tabBarHidden]': 'barHidden()',\n '[tabBarTintColor]': 'tintColor() ?? defaults().tintColor',\n '[nativeContainerBackgroundColor]': 'backgroundColor() ?? defaults().backgroundColor',\n '[colorScheme]': 'colorScheme() ?? defaults().colorScheme',\n '[tabBarMinimizeBehavior]': 'minimizeBehavior()',\n '[tabBarControllerMode]': 'controllerMode()',\n '[tabBarRespectsIMEInsets]': 'respectsKeyboard()',\n },\n})\nexport class NativeTabsOutlet implements RouterOutletContract, AfterContentInit {\n name = 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 changeDetector = inject(ChangeDetectorRef);\n private readonly injector = inject(Injector);\n private readonly host = inject(ElementRef);\n private readonly route = inject(ActivatedRoute);\n /** Optional so the outlet can be driven through `RouterOutletContract` directly, as tests do. */\n private readonly router = inject(Router, { optional: true });\n private readonly errors = inject(ErrorHandler);\n /** What activation has reported already, so the failed navigation it causes is not reported again. */\n private readonly reported = new WeakSet<object>();\n /** The app's `withTabDefaults`, for whatever the outlet does not bind itself. */\n protected readonly defaults = inject(NATIVE_TAB_DEFAULTS);\n\n private readonly declared = contentChildren(NativeTab);\n private readonly entries: TabEntry[] = [];\n private selected: TabEntry | null = null;\n /** The provenance of the last state native told us about. Starts before native's first. */\n private provenance = 0;\n\n protected readonly fill = { flex: 1 };\n\n // --- the bar itself -----------------------------------------------------\n\n /** Hide the bar without unmounting the tabs, for a screen that wants the whole window. */\n readonly barHidden = input(undefined, { transform: optionalBoolean });\n /** The colour of the selected item. iOS. */\n readonly tintColor = input<string | number>();\n /** Behind the tabs, where a screen does not paint. */\n readonly backgroundColor = input<string | number>();\n /** Force the bar's light or dark appearance, whatever the app's is. */\n readonly colorScheme = input<'inherit' | 'light' | 'dark'>();\n /** iOS 26: let the bar shrink out of the way as content scrolls. */\n readonly minimizeBehavior = input<'automatic' | 'never' | 'onScrollDown' | 'onScrollUp'>();\n /** iOS: `tabSidebar` is the iPad layout, with the tabs down the side. */\n readonly controllerMode = input<'automatic' | 'tabBar' | 'tabSidebar'>();\n /** Android: keep the bar above the keyboard rather than behind it. */\n readonly respectsKeyboard = input(undefined, { transform: optionalBoolean });\n\n constructor() {\n ownHost(this.host.nativeElement);\n // In the constructor rather than a lifecycle hook: the router activates a child route as soon\n // as this component exists, which is before any hook has run.\n this.parentContexts.onChildOutletCreated(this.name, this);\n\n this.renderer.listen(\n this.host.nativeElement,\n 'tabSelected',\n (event: { nativeEvent?: TabSelection }) => this.onNativeSelect(event?.nativeEvent),\n );\n\n // An `@if` that takes a tab away and brings it back makes a new element: its page follows it\n // at once, since the tab may be the one showing, with no tap or navigation to read them on.\n effect(() => {\n this.declared();\n if (this.entries.length > 0) untracked(() => this.readTabs());\n });\n\n // A push inside a tab's own stack reuses the tab's route, so this outlet is never activated\n // for it; the router's navigation is the only sign. Without this, coming back to the tab\n // returns it to its root and pops the screens the user left it on.\n const following = this.router?.events?.subscribe((event) => {\n // Without a page presented over the bar, which is no part of where the tab is.\n if (event instanceof NavigationEnd) {\n this.follow(withoutPresented(this.router!, event.urlAfterRedirects));\n }\n });\n\n // Android's back button, and `NativeNavigation.back()`, once the stack in front, if the tab\n // has one, is at its root. Subscribed before any tab's own stack, so it is asked after them.\n const back = inject(NativeBack);\n const unsubscribeBack = back.handle(() => this.goBack());\n const unsubscribeBar = back.addTabBar({\n unopenedTabOf: (url) => this.unopenedTabOf(url),\n behind: (url) => this.behind(url),\n coveredAt: (url) => this.coveredAt(url),\n });\n\n inject(DestroyRef).onDestroy(() => {\n unsubscribeBack();\n unsubscribeBar();\n following?.unsubscribe();\n for (const entry of this.entries) {\n entry.unbind();\n entry.ref?.destroy();\n }\n this.entries.length = 0;\n // Only while it is this outlet's, as for a stack: see `NativeStackOutlet`.\n if (this.parentContexts.getContext(this.name)?.outlet === this) {\n this.parentContexts.onChildOutletDestroyed(this.name);\n }\n });\n }\n\n /** A bar nobody has navigated into yet still has to show a selected item. */\n ngAfterContentInit(): void {\n this.readTabs();\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, as `NativeStackOutlet` takes its own: a tab bar held behind a condition until a session\n * is ready. Once the tabs are read, since activating one needs to know which they are.\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 /** The tabs in the bar, in the order they were first in it. Exposed for tests. */\n get tabKeys(): string[] {\n return this.readTabs().map((entry) => entry.key);\n }\n\n /** Which tab native is showing. Exposed for tests. */\n get selectedKey(): string | null {\n return this.selected?.key ?? null;\n }\n\n // --- RouterOutletContract ----------------------------------------------\n\n get isActivated(): boolean {\n return this.selected?.ref != null && !this.selected.detached;\n }\n\n get component(): Object | null {\n return this.isActivated ? (this.selected!.ref!.instance as Object) : null;\n }\n\n get activatedRoute(): ActivatedRoute | null {\n return this.isActivated ? this.selected!.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.selected?.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 const entry = this.entryFor(route);\n\n // The tab screen is owned by <native-tab>, not by this route component. If the route uses\n // deactivate() rather than detach(), Angular removes the component host on destroy. Giving\n // the component its own child host keeps that removal from taking the tab bar item with it.\n const content = ownHost(this.renderer.createElement('view'));\n this.renderer.setStyle(content, 'flex', 1);\n this.renderer.appendChild(entry.tab.screen, content);\n\n let ref: ComponentRef<unknown> | undefined;\n try {\n ref = createComponent(component, {\n environmentInjector,\n elementInjector: this.outletInjector(route, entry),\n hostElement: content as Element,\n });\n this.applicationRef.attachView(ref.hostView);\n // Route params onto inputs before the first change detection, as the stack outlet does: a\n // required input still unset when the page first renders throws NG0950.\n entry.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 } catch (error) {\n this.abandon(entry, ref, content);\n this.errors.handleError(error);\n if (error !== null && typeof error === 'object') this.reported.add(error);\n throw error;\n }\n\n entry.ref = ref;\n entry.route = route;\n entry.detached = false;\n this.select(entry);\n }\n\n /**\n * Destroy the tab page in front: nothing once the router has detached it, as Angular's own\n * outlet does nothing then. A tab under a route with no component of its own, a `loadChildren`\n * wrapper or a group, has the router detach the page and then deactivate this same outlet, and\n * that page is the tab, kept for when it is selected again.\n */\n deactivate(): void {\n if (!this.isActivated) return;\n const entry = this.selected!;\n entry.unbind();\n entry.unbind = () => {};\n entry.ref!.destroy();\n entry.ref = null;\n entry.route = null;\n }\n\n /**\n * Hand the live `ComponentRef` back to the router. The tab's screen stays where it is with the\n * component still inside it, so the tab keeps running while another one is in front.\n */\n detach(): ComponentRef<unknown> {\n const entry = this.selected;\n if (!entry?.ref) throw new Error('[angular-native] outlet is not activated, nothing to detach');\n entry.detached = true;\n entry.inFront.set(false);\n // As in the stack outlet: stop change detection without unmounting the views.\n entry.ref.hostView.detach();\n return entry.ref;\n }\n\n attach(ref: ComponentRef<unknown>, route: ActivatedRoute): void {\n const entry = this.entryFor(route);\n\n // A ref from a previous instance of this outlet still lives on its old tab screen, which is\n // gone; re-parent it onto this one's rather than rebuild the tab.\n if (entry.ref !== ref) {\n this.renderer.appendChild(entry.tab.screen, ref.location.nativeElement);\n this.applicationRef.attachView(ref.hostView);\n entry.ref = ref;\n }\n\n entry.route = route;\n entry.detached = false;\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 ref.hostView.reattach();\n this.select(entry);\n }\n\n // --- native tabs --------------------------------------------------------\n\n /**\n * Undo a tab page that threw on its first render, which fails the navigation: its component\n * and its content view go, and the tab that was showing carries on, change detection and all.\n */\n private abandon(entry: TabEntry, ref: ComponentRef<unknown> | undefined, content: unknown): void {\n entry.unbind();\n entry.unbind = () => {};\n ref?.destroy();\n this.renderer.removeChild(entry.tab.screen, content);\n const showing = this.selected;\n if (showing?.detached && showing.ref) {\n showing.detached = false;\n showing.ref.hostView.reattach();\n }\n }\n\n /** Route params onto inputs only under `withComponentInputBinding()`, as in the stack outlet. */\n private bindInputs(ref: ComponentRef<unknown>, route: ActivatedRoute): () => void {\n return this.router?.componentInputBindingEnabled ? bindRouteInputs(ref, route) : () => {};\n }\n\n /**\n * Take the bar from the `<native-tab>` elements in the content, adding any that appeared since\n * the last read, as one an `@if` shows once a feature flag turns on, and following one that was\n * taken away and brought back.\n *\n * On demand rather than in a lifecycle hook, because the router activates a child route during\n * this component's creation, before any hook has run - but after the content nodes themselves\n * exist, which is all this needs.\n */\n private readTabs(): TabEntry[] {\n const first = this.entries.length === 0;\n const children = this.route.routeConfig?.children ?? [];\n for (const tab of this.declared()) {\n const key = tab.path();\n const known = this.entries.find((entry) => entry.key === key);\n if (known) {\n this.move(known, tab);\n continue;\n }\n this.entries.push({\n tab,\n key,\n url: '',\n ref: null,\n route: null,\n detached: false,\n unbind: () => {},\n inFront: signal(false),\n leaving: new Set(),\n });\n // The reuse strategy detaches a tab whole, and has only the route to go on.\n // A path can have multiple route configs selected by canMatch (for example an iPad split\n // layout and an iPhone stack). Mark every variant: the reuse strategy sees the config\n // Angular actually matched, which may not be the first one in the route array.\n for (const config of children) {\n if (config.path === key) markTabRoute(config);\n }\n }\n\n if (this.entries.length === 0) {\n throw new Error(\n '[angular-native] <native-tabs-outlet> has no tabs. Put a <native-tab path=\"...\"> ' +\n 'inside it for each child route the bar should reach.',\n );\n }\n // Before the first navigation nothing is selected, which is not a state a tab bar has.\n if (first) this.request(this.entries[0]!);\n return this.entries;\n }\n\n /**\n * Give an entry the `<native-tab>` now declared for its path, when that is not the one it was\n * read with: an `@if` that took the tab away and brought it back made a new element, with a new\n * screen. The page goes over to that screen as it is, so the tab comes back where it was left.\n */\n private move(entry: TabEntry, tab: NativeTab): void {\n if (entry.tab === tab) return;\n entry.tab = tab;\n if (entry.ref) this.renderer.appendChild(tab.screen, entry.ref.location.nativeElement);\n }\n\n /**\n * The tab `route` is the page of, by its path from this outlet's route down to it. A route with\n * no component above the page is part of that path: a `loadChildren` wrapper takes the tab's\n * path and leaves `''` to the page under it, and a group is a `''` of its own.\n */\n private entryFor(route: ActivatedRoute): TabEntry {\n const config = route.routeConfig ?? route.snapshot.routeConfig;\n const paths = [config?.path];\n for (let above = route.parent; above && !above.component; above = above.parent) {\n paths.unshift(above.routeConfig?.path);\n }\n const path = paths.filter(Boolean).join('/');\n const entry = this.readTabs().find((candidate) => candidate.key === path);\n if (!entry) {\n throw new Error(\n `[angular-native] no <native-tab> has path=\"${path}\". Every child route the bar can ` +\n `reach needs one, and its path is what native identifies the tab by.`,\n );\n }\n // Under a wrapper the page's config is not one of the children `readTabs` marked, and it is\n // the one the reuse strategy is asked to detach whole.\n if (config) markTabRoute(config);\n return entry;\n }\n\n /** Remember where this tab is, and tell native to show it. */\n private select(entry: TabEntry): void {\n const left = this.selected;\n if (left && left !== entry) this.leave(left);\n this.selected = entry;\n for (const other of this.entries) other.inFront.set(other === entry);\n entry.url = this.router?.url ?? entry.url;\n this.request(entry);\n }\n\n /**\n * Another tab came in front of `entry`: its stacks dismiss what they presented, and it is\n * remembered at the page beneath, where the outermost stack that dismissed something is left.\n */\n private leave(entry: TabEntry): void {\n let url: string | null = null;\n for (const dismiss of entry.leaving) {\n const beneath = dismiss();\n url ??= beneath;\n }\n if (url !== null) entry.url = url;\n }\n\n /**\n * A back with nothing left to pop inside the tab: go to the first tab, where it was left, which\n * is what a bottom navigation bar does on Android. From the first tab, decline, so the platform\n * leaves the app. The order tabs were visited in is not retraced, so a back never lands on a\n * tab the user did not expect. Not while the bar is covered by a screen pushed over it: that\n * screen's stack answers instead.\n */\n private goBack(): boolean {\n const first = this.entries[0];\n const selected = this.selected;\n if (!first || !selected || selected === first || !this.router) return false;\n if (!this.isActivated || !isShowing(this.router, selected.route)) return false;\n void this.router.navigateByUrl(this.urlOf(first));\n return true;\n }\n\n /** Keep the tab in front on the url it has reached, as long as the url is still inside it. */\n private follow(url: string): void {\n const entry = this.selected;\n if (entry && this.tabOf(url) === entry) entry.url = url;\n }\n\n /**\n * The url of the tab `url` is a page inside, when nothing has opened that tab: the tab's own\n * first screen, which a push into the tab from outside it shows first.\n */\n private unopenedTabOf(url: string): string | null {\n const entry = this.tabOf(url);\n if (!entry || entry.ref) return null;\n const root = this.pathOf(entry);\n return pathOnly(url) === root ? null : root;\n }\n\n /** Where the tab `url` is in was left, while a screen over the bar covers it. */\n private coveredAt(url: string): string | null {\n if (this.injector.get(SCREEN_IN_FRONT)()) return null;\n const entry = this.tabOf(url);\n return entry ? this.urlOf(entry) : null;\n }\n\n /** Whether `url` is a tab other than the one in front, or a page inside one. */\n private behind(url: string): boolean {\n const entry = this.tabOf(url);\n return entry !== null && entry !== this.selected;\n }\n\n /**\n * The tab `url` is in: the one with the longest url that starts it. A tab at `''` has the bar's\n * own url, which at the root starts every url, pages outside the bar included, so it takes only\n * a url its routes lead to, as far as they are loaded. A wildcard or a custom matcher is not\n * followed, as `taken` follows neither: a page only one of them shows is in no tab.\n */\n private tabOf(url: string): TabEntry | null {\n const path = pathOnly(url);\n let found: TabEntry | null = null;\n for (const entry of this.entries) {\n const root = this.pathOf(entry);\n const inside = path === root || path.startsWith(root.endsWith('/') ? root : `${root}/`);\n if (!inside || (found && this.pathOf(found).length >= root.length)) continue;\n if (!entry.key && !this.leadsInto(entry, path.slice(root.length))) continue;\n found = entry;\n }\n return found;\n }\n\n /** Whether the routes of the tab at `''` lead to `rest`, the path under the bar's own url. */\n private leadsInto(entry: TabEntry, rest: string): boolean {\n const segments = rest.split('/').filter(Boolean);\n const own = entry.route?.snapshot.routeConfig;\n const routes = own\n ? [own]\n : (this.route.routeConfig?.children ?? []).filter((config) => config.path === '');\n return segments.length === 0 || reaches(routes, segments);\n }\n\n private request(entry: TabEntry): void {\n this.renderer.setProperty(this.host.nativeElement, 'navStateRequest', {\n selectedScreenKey: screenKeyOf(entry.key),\n baseProvenance: this.provenance,\n });\n }\n\n /**\n * Native switched tab. Acknowledge the new state, then navigate: the router is authoritative\n * about what is on screen (ADR 0003), so the tap becomes a navigation to where that tab was,\n * and the activation that follows is what fills the tab in.\n */\n private onNativeSelect(selection: TabSelection | undefined): void {\n if (!selection) return;\n this.provenance = selection.provenance;\n\n // Native answering a request of ours is not a switch to follow. The router made the request,\n // and an answer that arrives after a later request, such as a cold-start link's, names a tab\n // the router has already left.\n if (selection.actionOrigin === 'programmatic-js') return;\n\n const entry = this.readTabs().find(\n (tab) => screenKeyOf(tab.key) === selection.selectedScreenKey,\n );\n if (!entry || (entry === this.selected && !this.tappedBack(selection))) return;\n\n // Returning to a tab returns to the url it was last on, which is the whole point of keeping\n // it mounted. A tab never visited starts at its own path.\n // A navigation that fails is reported, unless activation reported it already: a page that\n // does not load, caught here, would otherwise leave nothing but a tab that will not open.\n void this.router?.navigateByUrl(this.urlOf(entry)).then(\n (arrived) => this.revertUnless(arrived),\n (error: unknown) => {\n if (error === null || typeof error !== 'object' || !this.reported.has(error)) {\n this.errors.handleError(error);\n }\n this.revertUnless(false);\n },\n );\n }\n\n /**\n * Whether the user tapped the tab in front while a navigation is running: back from the tab that\n * navigation is still loading, so the tab in front is where it is to end. A selection native\n * reports because the outlet asked for it is not a tap, and cancels nothing. Nor does a tap on\n * the tab already in front (native reports it as repeated): no other tab was tapped first, so a\n * navigation running then is one from code, or a push inside the tab, and is left to finish.\n */\n private tappedBack(selection: TabSelection): boolean {\n return (\n selection.actionOrigin === 'user' &&\n !selection.isRepeated &&\n !!this.router?.getCurrentNavigation()\n );\n }\n\n /**\n * Native switched tab before the router agreed to. When a guard refuses, or the navigation\n * fails, the router stays where it was and so must the bar, or it shows a tab nobody is on.\n * Not while another navigation is under way: that one superseded this, and its own activation\n * selects the tab it lands on.\n */\n private revertUnless(arrived: boolean): void {\n if (arrived || !this.selected || this.router?.getCurrentNavigation()) return;\n this.request(this.selected);\n // A failed navigation ends in a promise callback, which schedules no change detection, and a\n // prop reaches native only with the commit at the end of a pass. Without one the bar stayed\n // on the tab that failed until something else happened to render.\n this.changeDetector.markForCheck();\n }\n\n private urlOf(entry: TabEntry): string {\n return entry.url && this.tabOf(entry.url) === entry ? entry.url : this.pathOf(entry);\n }\n\n /** A tab's own url, from the outlet's route down. */\n private pathOf(entry: TabEntry): string {\n const parent = this.route.snapshot.pathFromRoot\n .flatMap((snapshot) => snapshot.url.map((segment) => segment.path))\n .join('/');\n return `/${[parent, entry.key].filter(Boolean).join('/')}`;\n }\n\n /**\n * As the stack outlet's: the route, the outlet contexts, and whether the tab is showing. And the\n * tab itself, for its stacks to hear when another comes in front.\n */\n private outletInjector(route: ActivatedRoute, entry: TabEntry): Injector {\n const outer = this.injector.get(SCREEN_IN_FRONT);\n const tab: InTab = {\n onLeave: (leave) => (entry.leaving.add(leave), () => entry.leaving.delete(leave)),\n };\n return Injector.create({\n parent: this.injector,\n providers: [\n { provide: SCREEN_IN_FRONT, useValue: computed(() => outer() && entry.inFront()) },\n { provide: IN_TAB, useValue: tab },\n { provide: ActivatedRoute, useValue: route },\n {\n provide: ChildrenOutletContexts,\n useValue: this.parentContexts.getOrCreateContext(this.name).children,\n },\n ],\n });\n }\n}\n"]}
@@ -83,7 +83,7 @@ export class NativeToolbarItem {
83
83
  identifier = `native-toolbar-item-${created++}`;
84
84
  constructor() {
85
85
  const node = ownHost(inject(ElementRef).nativeElement, NativeToolbarItem);
86
- const engine = node.host ?? inject(HostEngine);
86
+ const engine = node.engine ?? inject(HostEngine);
87
87
  inject(DestroyRef).onDestroy(engine.setEventListener(node, 'topSelected', () => this.press.emit()));
88
88
  }
89
89
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: NativeToolbarItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -1 +1 @@
1
- {"version":3,"file":"native-toolbar.js","sourceRoot":"","sources":["../src/native-toolbar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACzF,OAAO,EAAmB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;;AAelE,MAAM,OAAO,aAAa;IACxB;QACE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,aAA2B,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5E,CAAC;uGAHU,aAAa;2FAAb,aAAa,oNAXd,gBAAgB;;2FAWf,aAAa;kBAbzB,SAAS;mBAAC;oBACT,QAAQ,EAAE,gBAAgB;oBAC1B,QAAQ,EAAE,gBAAgB;oBAC1B,+FAA+F;oBAC/F,+DAA+D;oBAC/D,IAAI,EAAE;wBACJ,kBAAkB,EAAE,YAAY;wBAChC,aAAa,EAAE,GAAG;wBAClB,cAAc,EAAE,GAAG;wBACnB,eAAe,EAAE,GAAG;wBACpB,gBAAgB,EAAE,GAAG;qBACtB;iBACF;;AAeD,mGAAmG;AACnG,IAAI,OAAO,GAAG,CAAC,CAAC;AAoBhB,MAAM,OAAO,iBAAiB;IACnB,IAAI,GAAG,KAAK;wFAAmB,CAAC;IAChC,KAAK,GAAG,KAAK;yFAAU,CAAC;IACjC,yBAAyB;IAChB,eAAe,GAAG,KAAK;mGAAU,CAAC;IAClC,SAAS,GAAG,KAAK;6FAAU,CAAC;IACrC,2EAA2E;IAClE,kBAAkB,GAAG,KAAK;sGAAyB,CAAC;IAC7D,sDAAsD;IAC7C,qBAAqB,GAAG,KAAK,CAAC,SAAS,6FAAI,SAAS,EAAE,eAAe,GAAG,CAAC;IAClF,gGAAgG;IACvF,gBAAgB,GAAG,KAAK,CAAC,SAAS,wFAAI,SAAS,EAAE,eAAe,GAAG,CAAC;IAC7E,+CAA+C;IACtC,KAAK,GAAG,KAAK,CAAC,SAAS,6EAAI,SAAS,EAAE,cAAc,GAAG,CAAC;IACjE,kFAAkF;IACzE,MAAM,GAAG,KAAK,CAAC,SAAS,8EAAI,SAAS,EAAE,eAAe,GAAG,CAAC;IAC1D,QAAQ,GAAG,KAAK,CAAC,SAAS,gFAAI,SAAS,EAAE,eAAe,GAAG,CAAC;IACrE,yEAAyE;IAChE,kBAAkB,GAAG,KAAK;sGAAU,CAAC;IAE9C,6BAA6B;IACpB,KAAK,GAAG,MAAM,EAAQ,CAAC;IAEb,UAAU,GAAG,uBAAuB,OAAO,EAAE,EAAE,CAAC;IAEnE;QACE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,aAA2B,EAAE,iBAAiB,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAC1B,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CACtE,CAAC;IACJ,CAAC;uGA/BU,iBAAiB;2FAAjB,iBAAiB,ghEAhBlB,EAAE;;2FAgBD,iBAAiB;kBAlB7B,SAAS;mBAAC;oBACT,QAAQ,EAAE,qBAAqB;oBAC/B,QAAQ,EAAE,EAAE;oBACZ,IAAI,EAAE;wBACJ,cAAc,EAAE,YAAY;wBAC5B,QAAQ,EAAE,QAAQ;wBAClB,SAAS,EAAE,SAAS;wBACpB,mBAAmB,EAAE,mBAAmB;wBACxC,aAAa,EAAE,aAAa;wBAC5B,sBAAsB,EAAE,sBAAsB;wBAC9C,yBAAyB,EAAE,yBAAyB;wBACpD,oBAAoB,EAAE,oBAAoB;wBAC1C,SAAS,EAAE,SAAS;wBACpB,UAAU,EAAE,UAAU;wBACtB,YAAY,EAAE,YAAY;wBAC1B,sBAAsB,EAAE,sBAAsB;qBAC/C;iBACF","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"]}
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.engine ?? inject(HostEngine);\n inject(DestroyRef).onDestroy(\n engine.setEventListener(node, 'topSelected', () => this.press.emit()),\n );\n }\n}\n"]}
@@ -15,7 +15,7 @@
15
15
  import { PlatformLocation } from '@angular/common';
16
16
  import { NavigationCancel, NavigationEnd, NavigationError, NavigationSkipped, RouteReuseStrategy, Router, provideRouter, } from '@angular/router';
17
17
  import { DestroyRef, ErrorHandler, computed, inject, makeEnvironmentProviders, provideEnvironmentInitializer, } from '@angular/core';
18
- import { ColorScheme, DeepLinks } from '@ng-native/device';
18
+ import { ColorScheme, DeepLinks, NATIVE_HISTORY } from '@ng-native/device';
19
19
  import { NATIVE_HEADER_DEFAULTS, NATIVE_TAB_DEFAULTS, } from "./native-bar-defaults.js";
20
20
  import { followLink, linkAncestry } from "./native-links.js";
21
21
  import { NATIVE_INTENT, NativeNavigation, carriesOn, carryIntentAcrossRedirects, intentOf, } from "./native-navigation.js";
@@ -107,8 +107,10 @@ function nativeProviders(parentOf) {
107
107
  ];
108
108
  if (!parentOf) {
109
109
  return [
110
+ // Kept under the token too, which web-compat's stand-in yields to: see `NATIVE_HISTORY`.
111
+ { provide: PlatformLocation, useExisting: NATIVE_HISTORY },
110
112
  {
111
- provide: PlatformLocation,
113
+ provide: NATIVE_HISTORY,
112
114
  useFactory: () => {
113
115
  const links = inject(DeepLinks);
114
116
  return new NativePlatformLocation({
@@ -128,8 +130,10 @@ function nativeProviders(parentOf) {
128
130
  ];
129
131
  }
130
132
  return [
133
+ // Kept under the token too, which web-compat's stand-in yields to: see `NATIVE_HISTORY`.
134
+ { provide: PlatformLocation, useExisting: NATIVE_HISTORY },
131
135
  {
132
- provide: PlatformLocation,
136
+ provide: NATIVE_HISTORY,
133
137
  // The app launches on the page the link belongs under; the link follows once it is shown.
134
138
  // Links while running go through the router below rather than straight into history.
135
139
  useFactory: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"provide-native-router.js","sourceRoot":"","sources":["../src/provide-native-router.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Angular's Router, on native navigation: `provideRouter` and the native pieces under it, in one\n * call.\n *\n * `provideNativeRouter(routes, withComponentInputBinding())` takes the same routes and the same\n * router features as `provideRouter` - it calls it - and adds what native needs on top: a\n * `PlatformLocation` over an in-memory history, a `RouteReuseStrategy` that detaches a pushed-away\n * screen instead of destroying it, and `NativeNavigation`. Those come after `provideRouter`'s own\n * providers, so they win over the web defaults without the app having to order anything.\n *\n * Deep links and Android's back button come from `@ng-native/device` and need no wiring: off a\n * device both report nothing, and navigation works either way. The native options - `withLinkParent`,\n * `withHeaderDefaults` and `withTabDefaults` - are passed like any other feature.\n */\nimport { PlatformLocation } from '@angular/common';\nimport {\n NavigationCancel,\n NavigationEnd,\n NavigationError,\n NavigationSkipped,\n RouteReuseStrategy,\n Router,\n provideRouter,\n type RouterFeatures,\n type Routes,\n} from '@angular/router';\nimport {\n DestroyRef,\n ErrorHandler,\n computed,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n type EnvironmentProviders,\n type InjectionToken,\n type Provider,\n type Signal,\n type Type,\n} from '@angular/core';\nimport { ColorScheme, DeepLinks, type Scheme } from '@ng-native/device';\nimport {\n NATIVE_HEADER_DEFAULTS,\n NATIVE_TAB_DEFAULTS,\n type HeaderDefaults,\n type SchemeDefaults,\n type TabDefaults,\n} from './native-bar-defaults.ts';\nimport { followLink, linkAncestry, type LinkParent } from './native-links.ts';\nimport {\n NATIVE_INTENT,\n NativeNavigation,\n carriesOn,\n carryIntentAcrossRedirects,\n intentOf,\n} from './native-navigation.ts';\nimport { NativePlatformLocation } from './native-platform-location.ts';\nimport { SVG_ICON_RENDERER, type SvgIconRenderer } from './svg-icons.ts';\nimport { NativeStackReuseStrategy } from './native-stack-reuse-strategy.ts';\nimport { ROUTE_PARKING, type ParkedPage } from './route-parking.ts';\nimport { registerScreenComponents } from './screens.ts';\n\n/** A native-only router option, passed to `provideNativeRouter` beside Angular's own features. */\nexport interface NativeRouterFeature {\n readonly ɵnativeRouter: { readonly linkParent?: LinkParent; readonly providers?: Provider[] };\n}\n\n/**\n * The page a deep link opens on top of, or null to open it alone. Without it a link to\n * `/settings/notifications` opens that page with no Back. See native-links.ts.\n */\nexport function withLinkParent(parentOf: LinkParent): NativeRouterFeature {\n return { ɵnativeRouter: { linkParent: parentOf } };\n}\n\n/**\n * How every `<native-header>` looks when it does not say: its colours, blur, shadow, fonts and\n * light or dark style. A header's own binding always wins.\n *\n * ```ts\n * provideNativeRouter(\n * routes,\n * withHeaderDefaults((scheme) => ({\n * backgroundColor: scheme === 'dark' ? '#101014' : '#f4f4f7',\n * titleColor: scheme === 'dark' ? '#ffffff' : '#101014',\n * color: '#3b6ef5',\n * })),\n * );\n * ```\n *\n * Colours it leaves out still come from `NATIVE_HEADER_PALETTE`.\n */\nexport function withHeaderDefaults(defaults: SchemeDefaults<HeaderDefaults>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [bySchemeProvider(NATIVE_HEADER_DEFAULTS, defaults)] } };\n}\n\n/**\n * How every `<native-tabs-outlet>` and `<native-tab>` looks when it does not say: the tint, the\n * background behind the tabs, the light or dark style, and each tab's bar appearance. An outlet's\n * or a tab's own binding always wins.\n */\nexport function withTabDefaults(defaults: SchemeDefaults<TabDefaults>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [bySchemeProvider(NATIVE_TAB_DEFAULTS, defaults)] } };\n}\n\n/**\n * What draws a `<native-tab>` icon written as SVG markup, `[icon]=\"{ svg }\"`, which neither\n * platform's tab bar can draw itself. `SvgImages` from `@ng-native/icons` is one:\n *\n * ```ts\n * provideNativeRouter(routes, withSvgIcons(SvgImages));\n * ```\n */\nexport function withSvgIcons(renderer: Type<SvgIconRenderer>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [{ provide: SVG_ICON_RENDERER, useClass: renderer }] } };\n}\n\n/** One signal for the whole app, rather than every bar calling the function again. */\nfunction bySchemeProvider<T>(\n token: InjectionToken<Signal<T>>,\n defaults: SchemeDefaults<T>,\n): Provider {\n return {\n provide: token,\n useFactory: () => {\n if (typeof defaults !== 'function') return computed(() => defaults);\n const scheme = inject(ColorScheme);\n return computed(() => (defaults as (scheme: Scheme) => T)(scheme.current()));\n },\n };\n}\n\nfunction isNative(feature: RouterFeatures | NativeRouterFeature): feature is NativeRouterFeature {\n return 'ɵnativeRouter' in feature;\n}\n\nexport function provideNativeRouter(\n routes: Routes,\n ...features: (RouterFeatures | NativeRouterFeature)[]\n): EnvironmentProviders {\n const angular = features.filter((feature): feature is RouterFeatures => !isNative(feature));\n const native = features.filter(isNative).map((feature) => feature.ɵnativeRouter);\n const parentOf = native.find((feature) => feature.linkParent)?.linkParent;\n return makeEnvironmentProviders([\n provideRouter(routes, ...angular),\n ...nativeProviders(parentOf),\n ...native.flatMap((feature) => feature.providers ?? []),\n ]);\n}\n\nfunction nativeProviders(parentOf: LinkParent | undefined): (Provider | EnvironmentProviders)[] {\n // The engine needs the element-to-view-name mapping before the first navigation renders.\n registerScreenComponents();\n\n const shared = [\n // Without this the router never detaches, so a pushed-away screen is destroyed and rebuilt.\n { provide: RouteReuseStrategy, useClass: NativeStackReuseStrategy },\n NativeNavigation,\n provideEnvironmentInitializer(carryIntentAcrossRedirects),\n provideEnvironmentInitializer(keepHistoryAcrossReloads),\n ];\n if (!parentOf) {\n return [\n {\n provide: PlatformLocation,\n useFactory: () => {\n const links = inject(DeepLinks);\n return new NativePlatformLocation({\n initialUrl: () => links.initialUrl(),\n subscribe: () => () => {},\n });\n },\n },\n provideEnvironmentInitializer(() => {\n const navigation = inject(NativeNavigation);\n const errors = inject(ErrorHandler);\n inject(DeepLinks).subscribe((url) => {\n navigation.push(url).catch((error: unknown) => errors.handleError(error));\n });\n }),\n ...shared,\n ];\n }\n\n return [\n {\n provide: PlatformLocation,\n // The app launches on the page the link belongs under; the link follows once it is shown.\n // Links while running go through the router below rather than straight into history.\n useFactory: () => {\n const initial = inject(DeepLinks).initialUrl();\n return new NativePlatformLocation({\n initialUrl: () => (initial && linkAncestry(initial, parentOf)[0]) || initial,\n subscribe: () => () => {},\n });\n },\n },\n provideEnvironmentInitializer(() => {\n const router = inject(Router);\n const links = inject(DeepLinks);\n const errors = inject(ErrorHandler);\n // A link nobody awaits: a page that fails to load is reported, as a tab tap's is, rather\n // than left as an unhandled rejection. The app's navigation error handler hears it too.\n const follow = (url: string) =>\n followLink(router, url, parentOf).catch((error: unknown) => errors.handleError(error));\n const initial = links.initialUrl();\n if (initial && parentOf(initial)) {\n // Followed over the first page to show, or not at all: one that failed to load leaves\n // the link nothing to go over, and the next page to show is not the one it waited for.\n const first = router.events.subscribe((event) => {\n if (!isEnd(event) || carriesOn(event)) return;\n first.unsubscribe();\n if (event instanceof NavigationEnd) void follow(initial);\n });\n }\n // A launch link arrives the way any other does, once `getInitialURL()` settles, which is\n // usually while the router's first navigation is still going: following it then cancels that\n // navigation, and the app opens with no root screen under the link. So links wait for it.\n const settled = new Promise<void>((resolve) => {\n if (router.navigated) return resolve();\n const first = router.events.subscribe((event) => {\n if (!isEnd(event) || carriesOn(event)) return;\n first.unsubscribe();\n resolve();\n });\n });\n links.subscribe((url) => void settled.then(() => follow(url)));\n }),\n ...shared,\n ];\n}\n\n/**\n * A history without its round trips: each page once, reached the way it last was. An app that went\n * from one tab to another and back has a history three entries long and is one page deep, and the\n * app that comes back has no use for the detour: gone through at the speed of a reload, the tab\n * bar is still on its way to the second tab when the third navigation asks for the first.\n */\nfunction direct(pages: ParkedPage[]): ParkedPage[] {\n const route: ParkedPage[] = [];\n for (const page of pages) {\n const before = route.findIndex((one) => one.url === page.url);\n if (before !== -1) route.length = before;\n route.push(page);\n }\n return route;\n}\n\ndeclare const __DEV__: boolean | undefined;\n\n/** A push's animation, with room to spare: 350ms on iOS, about the same on Android. */\nconst PUSH_SETTLES = 450;\n\n/**\n * In development, come back from a reload on the page it left: see `route-parking.ts`.\n *\n * The history a reload left is gone through again once the first navigation has ended, as a\n * launch link is and for the same reason. The hook is what `mount`'s reload waits on.\n */\nfunction keepHistoryAcrossReloads(): void {\n // The bare identifier, so a release build folds the rest away.\n if (typeof __DEV__ === 'undefined' || !__DEV__) return;\n const parking = inject(ROUTE_PARKING);\n if (!parking) return;\n const router = inject(Router);\n const history = inject(PlatformLocation);\n const errors = inject(ErrorHandler);\n const scope = globalThis as {\n __angularNativePark?: () => Promise<void>;\n __angularNativeRestoring?: Promise<void>;\n };\n // A page keeps how it was presented, a sheet or a modal, and nothing else of its navigation:\n // a replace has already happened to the history, and an app's own state may not survive JSON.\n const pages = (): ParkedPage[] =>\n history instanceof NativePlatformLocation\n ? history.ɵpages().map(({ url, state }) => {\n const presentation = intentOf(state)?.presentation;\n return presentation ? { url, presentation } : { url };\n })\n : [{ url: router.url }];\n const park = () => parking.park(direct(pages()));\n scope.__angularNativePark = park;\n\n // `mount` keeps the app out of sight until this settles, so the pages arrive unseen.\n const restoring = parking\n .collect()\n .then(async (parked) => {\n if (!parked) return;\n await new Promise<void>((resolve) => {\n if (router.navigated) return resolve();\n const first = router.events.subscribe((event) => {\n if (!isEnd(event) || carriesOn(event)) return;\n first.unsubscribe();\n resolve();\n });\n });\n let moved = false;\n for (const { url, presentation } of parked) {\n if (url === router.url) continue;\n const state = presentation && { [NATIVE_INTENT]: { stack: 'push', presentation } };\n moved = (await router.navigateByUrl(url, { state })) || moved;\n }\n // The last page is still sliding in when its navigation ends.\n if (moved) await new Promise((resolve) => setTimeout(resolve, PUSH_SETTLES));\n })\n .catch((error: unknown) => errors.handleError(error));\n scope.__angularNativeRestoring = restoring;\n inject(DestroyRef).onDestroy(() => {\n if (scope.__angularNativePark === park) delete scope.__angularNativePark;\n if (scope.__angularNativeRestoring === restoring) delete scope.__angularNativeRestoring;\n });\n}\n\n/** A navigation's last event, whichever way it went. */\nfunction isEnd(event: unknown): boolean {\n return (\n event instanceof NavigationEnd ||\n event instanceof NavigationCancel ||\n event instanceof NavigationError ||\n // A url the app's `UrlHandlingStrategy` leaves to something else: it ends with no page.\n event instanceof NavigationSkipped\n );\n}\n"]}
1
+ {"version":3,"file":"provide-native-router.js","sourceRoot":"","sources":["../src/provide-native-router.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Angular's Router, on native navigation: `provideRouter` and the native pieces under it, in one\n * call.\n *\n * `provideNativeRouter(routes, withComponentInputBinding())` takes the same routes and the same\n * router features as `provideRouter` - it calls it - and adds what native needs on top: a\n * `PlatformLocation` over an in-memory history, a `RouteReuseStrategy` that detaches a pushed-away\n * screen instead of destroying it, and `NativeNavigation`. Those come after `provideRouter`'s own\n * providers, so they win over the web defaults without the app having to order anything.\n *\n * Deep links and Android's back button come from `@ng-native/device` and need no wiring: off a\n * device both report nothing, and navigation works either way. The native options - `withLinkParent`,\n * `withHeaderDefaults` and `withTabDefaults` - are passed like any other feature.\n */\nimport { PlatformLocation } from '@angular/common';\nimport {\n NavigationCancel,\n NavigationEnd,\n NavigationError,\n NavigationSkipped,\n RouteReuseStrategy,\n Router,\n provideRouter,\n type RouterFeatures,\n type Routes,\n} from '@angular/router';\nimport {\n DestroyRef,\n ErrorHandler,\n computed,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n type EnvironmentProviders,\n type InjectionToken,\n type Provider,\n type Signal,\n type Type,\n} from '@angular/core';\nimport { ColorScheme, DeepLinks, NATIVE_HISTORY, type Scheme } from '@ng-native/device';\nimport {\n NATIVE_HEADER_DEFAULTS,\n NATIVE_TAB_DEFAULTS,\n type HeaderDefaults,\n type SchemeDefaults,\n type TabDefaults,\n} from './native-bar-defaults.ts';\nimport { followLink, linkAncestry, type LinkParent } from './native-links.ts';\nimport {\n NATIVE_INTENT,\n NativeNavigation,\n carriesOn,\n carryIntentAcrossRedirects,\n intentOf,\n} from './native-navigation.ts';\nimport { NativePlatformLocation } from './native-platform-location.ts';\nimport { SVG_ICON_RENDERER, type SvgIconRenderer } from './svg-icons.ts';\nimport { NativeStackReuseStrategy } from './native-stack-reuse-strategy.ts';\nimport { ROUTE_PARKING, type ParkedPage } from './route-parking.ts';\nimport { registerScreenComponents } from './screens.ts';\n\n/** A native-only router option, passed to `provideNativeRouter` beside Angular's own features. */\nexport interface NativeRouterFeature {\n readonly ɵnativeRouter: { readonly linkParent?: LinkParent; readonly providers?: Provider[] };\n}\n\n/**\n * The page a deep link opens on top of, or null to open it alone. Without it a link to\n * `/settings/notifications` opens that page with no Back. See native-links.ts.\n */\nexport function withLinkParent(parentOf: LinkParent): NativeRouterFeature {\n return { ɵnativeRouter: { linkParent: parentOf } };\n}\n\n/**\n * How every `<native-header>` looks when it does not say: its colours, blur, shadow, fonts and\n * light or dark style. A header's own binding always wins.\n *\n * ```ts\n * provideNativeRouter(\n * routes,\n * withHeaderDefaults((scheme) => ({\n * backgroundColor: scheme === 'dark' ? '#101014' : '#f4f4f7',\n * titleColor: scheme === 'dark' ? '#ffffff' : '#101014',\n * color: '#3b6ef5',\n * })),\n * );\n * ```\n *\n * Colours it leaves out still come from `NATIVE_HEADER_PALETTE`.\n */\nexport function withHeaderDefaults(defaults: SchemeDefaults<HeaderDefaults>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [bySchemeProvider(NATIVE_HEADER_DEFAULTS, defaults)] } };\n}\n\n/**\n * How every `<native-tabs-outlet>` and `<native-tab>` looks when it does not say: the tint, the\n * background behind the tabs, the light or dark style, and each tab's bar appearance. An outlet's\n * or a tab's own binding always wins.\n */\nexport function withTabDefaults(defaults: SchemeDefaults<TabDefaults>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [bySchemeProvider(NATIVE_TAB_DEFAULTS, defaults)] } };\n}\n\n/**\n * What draws a `<native-tab>` icon written as SVG markup, `[icon]=\"{ svg }\"`, which neither\n * platform's tab bar can draw itself. `SvgImages` from `@ng-native/icons` is one:\n *\n * ```ts\n * provideNativeRouter(routes, withSvgIcons(SvgImages));\n * ```\n */\nexport function withSvgIcons(renderer: Type<SvgIconRenderer>): NativeRouterFeature {\n return { ɵnativeRouter: { providers: [{ provide: SVG_ICON_RENDERER, useClass: renderer }] } };\n}\n\n/** One signal for the whole app, rather than every bar calling the function again. */\nfunction bySchemeProvider<T>(\n token: InjectionToken<Signal<T>>,\n defaults: SchemeDefaults<T>,\n): Provider {\n return {\n provide: token,\n useFactory: () => {\n if (typeof defaults !== 'function') return computed(() => defaults);\n const scheme = inject(ColorScheme);\n return computed(() => (defaults as (scheme: Scheme) => T)(scheme.current()));\n },\n };\n}\n\nfunction isNative(feature: RouterFeatures | NativeRouterFeature): feature is NativeRouterFeature {\n return 'ɵnativeRouter' in feature;\n}\n\nexport function provideNativeRouter(\n routes: Routes,\n ...features: (RouterFeatures | NativeRouterFeature)[]\n): EnvironmentProviders {\n const angular = features.filter((feature): feature is RouterFeatures => !isNative(feature));\n const native = features.filter(isNative).map((feature) => feature.ɵnativeRouter);\n const parentOf = native.find((feature) => feature.linkParent)?.linkParent;\n return makeEnvironmentProviders([\n provideRouter(routes, ...angular),\n ...nativeProviders(parentOf),\n ...native.flatMap((feature) => feature.providers ?? []),\n ]);\n}\n\nfunction nativeProviders(parentOf: LinkParent | undefined): (Provider | EnvironmentProviders)[] {\n // The engine needs the element-to-view-name mapping before the first navigation renders.\n registerScreenComponents();\n\n const shared = [\n // Without this the router never detaches, so a pushed-away screen is destroyed and rebuilt.\n { provide: RouteReuseStrategy, useClass: NativeStackReuseStrategy },\n NativeNavigation,\n provideEnvironmentInitializer(carryIntentAcrossRedirects),\n provideEnvironmentInitializer(keepHistoryAcrossReloads),\n ];\n if (!parentOf) {\n return [\n // Kept under the token too, which web-compat's stand-in yields to: see `NATIVE_HISTORY`.\n { provide: PlatformLocation, useExisting: NATIVE_HISTORY },\n {\n provide: NATIVE_HISTORY,\n useFactory: () => {\n const links = inject(DeepLinks);\n return new NativePlatformLocation({\n initialUrl: () => links.initialUrl(),\n subscribe: () => () => {},\n });\n },\n },\n provideEnvironmentInitializer(() => {\n const navigation = inject(NativeNavigation);\n const errors = inject(ErrorHandler);\n inject(DeepLinks).subscribe((url) => {\n navigation.push(url).catch((error: unknown) => errors.handleError(error));\n });\n }),\n ...shared,\n ];\n }\n\n return [\n // Kept under the token too, which web-compat's stand-in yields to: see `NATIVE_HISTORY`.\n { provide: PlatformLocation, useExisting: NATIVE_HISTORY },\n {\n provide: NATIVE_HISTORY,\n // The app launches on the page the link belongs under; the link follows once it is shown.\n // Links while running go through the router below rather than straight into history.\n useFactory: () => {\n const initial = inject(DeepLinks).initialUrl();\n return new NativePlatformLocation({\n initialUrl: () => (initial && linkAncestry(initial, parentOf)[0]) || initial,\n subscribe: () => () => {},\n });\n },\n },\n provideEnvironmentInitializer(() => {\n const router = inject(Router);\n const links = inject(DeepLinks);\n const errors = inject(ErrorHandler);\n // A link nobody awaits: a page that fails to load is reported, as a tab tap's is, rather\n // than left as an unhandled rejection. The app's navigation error handler hears it too.\n const follow = (url: string) =>\n followLink(router, url, parentOf).catch((error: unknown) => errors.handleError(error));\n const initial = links.initialUrl();\n if (initial && parentOf(initial)) {\n // Followed over the first page to show, or not at all: one that failed to load leaves\n // the link nothing to go over, and the next page to show is not the one it waited for.\n const first = router.events.subscribe((event) => {\n if (!isEnd(event) || carriesOn(event)) return;\n first.unsubscribe();\n if (event instanceof NavigationEnd) void follow(initial);\n });\n }\n // A launch link arrives the way any other does, once `getInitialURL()` settles, which is\n // usually while the router's first navigation is still going: following it then cancels that\n // navigation, and the app opens with no root screen under the link. So links wait for it.\n const settled = new Promise<void>((resolve) => {\n if (router.navigated) return resolve();\n const first = router.events.subscribe((event) => {\n if (!isEnd(event) || carriesOn(event)) return;\n first.unsubscribe();\n resolve();\n });\n });\n links.subscribe((url) => void settled.then(() => follow(url)));\n }),\n ...shared,\n ];\n}\n\n/**\n * A history without its round trips: each page once, reached the way it last was. An app that went\n * from one tab to another and back has a history three entries long and is one page deep, and the\n * app that comes back has no use for the detour: gone through at the speed of a reload, the tab\n * bar is still on its way to the second tab when the third navigation asks for the first.\n */\nfunction direct(pages: ParkedPage[]): ParkedPage[] {\n const route: ParkedPage[] = [];\n for (const page of pages) {\n const before = route.findIndex((one) => one.url === page.url);\n if (before !== -1) route.length = before;\n route.push(page);\n }\n return route;\n}\n\ndeclare const __DEV__: boolean | undefined;\n\n/** A push's animation, with room to spare: 350ms on iOS, about the same on Android. */\nconst PUSH_SETTLES = 450;\n\n/**\n * In development, come back from a reload on the page it left: see `route-parking.ts`.\n *\n * The history a reload left is gone through again once the first navigation has ended, as a\n * launch link is and for the same reason. The hook is what `mount`'s reload waits on.\n */\nfunction keepHistoryAcrossReloads(): void {\n // The bare identifier, so a release build folds the rest away.\n if (typeof __DEV__ === 'undefined' || !__DEV__) return;\n const parking = inject(ROUTE_PARKING);\n if (!parking) return;\n const router = inject(Router);\n const history = inject(PlatformLocation);\n const errors = inject(ErrorHandler);\n const scope = globalThis as {\n __angularNativePark?: () => Promise<void>;\n __angularNativeRestoring?: Promise<void>;\n };\n // A page keeps how it was presented, a sheet or a modal, and nothing else of its navigation:\n // a replace has already happened to the history, and an app's own state may not survive JSON.\n const pages = (): ParkedPage[] =>\n history instanceof NativePlatformLocation\n ? history.ɵpages().map(({ url, state }) => {\n const presentation = intentOf(state)?.presentation;\n return presentation ? { url, presentation } : { url };\n })\n : [{ url: router.url }];\n const park = () => parking.park(direct(pages()));\n scope.__angularNativePark = park;\n\n // `mount` keeps the app out of sight until this settles, so the pages arrive unseen.\n const restoring = parking\n .collect()\n .then(async (parked) => {\n if (!parked) return;\n await new Promise<void>((resolve) => {\n if (router.navigated) return resolve();\n const first = router.events.subscribe((event) => {\n if (!isEnd(event) || carriesOn(event)) return;\n first.unsubscribe();\n resolve();\n });\n });\n let moved = false;\n for (const { url, presentation } of parked) {\n if (url === router.url) continue;\n const state = presentation && { [NATIVE_INTENT]: { stack: 'push', presentation } };\n moved = (await router.navigateByUrl(url, { state })) || moved;\n }\n // The last page is still sliding in when its navigation ends.\n if (moved) await new Promise((resolve) => setTimeout(resolve, PUSH_SETTLES));\n })\n .catch((error: unknown) => errors.handleError(error));\n scope.__angularNativeRestoring = restoring;\n inject(DestroyRef).onDestroy(() => {\n if (scope.__angularNativePark === park) delete scope.__angularNativePark;\n if (scope.__angularNativeRestoring === restoring) delete scope.__angularNativeRestoring;\n });\n}\n\n/** A navigation's last event, whichever way it went. */\nfunction isEnd(event: unknown): boolean {\n return (\n event instanceof NavigationEnd ||\n event instanceof NavigationCancel ||\n event instanceof NavigationError ||\n // A url the app's `UrlHandlingStrategy` leaves to something else: it ends with no page.\n event instanceof NavigationSkipped\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-native/router",
3
- "version": "0.15.0",
3
+ "version": "0.17.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.15.0",
21
- "@ng-native/fabric": "0.15.0"
20
+ "@ng-native/device": "0.17.0",
21
+ "@ng-native/fabric": "0.17.0"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "@angular/common": "^22.0.0",