@ng-native/router 0.2.0 → 0.4.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.
@@ -9,12 +9,36 @@ export interface PoppableStack {
9
9
  /** Pop to the screen showing `url`, or null when no screen below the top shows it. */
10
10
  popTo(url: string): Promise<boolean> | null;
11
11
  }
12
+ /**
13
+ * What a tab bar offers `NativeNavigation` for a push into one of its tabs from outside it. A tab
14
+ * nobody has opened has no stack yet, and a page pushed into it would be the stack's first
15
+ * screen, with nothing under it to go back to.
16
+ */
17
+ export interface TabBar {
18
+ /** The url of the tab `url` is a page inside, when that tab has not been opened. */
19
+ unopenedTabOf(url: string): string | null;
20
+ /** Whether `url` is a tab other than the one in front, or a page inside one. */
21
+ behind(url: string): boolean;
22
+ }
12
23
  export declare class NativeBack {
13
24
  private readonly hardwareBack;
14
25
  /** Oldest first, as `HardwareBack` holds them. */
15
26
  private readonly answers;
16
27
  /** Oldest first, and so outermost first, as the answers are. */
17
28
  private readonly stacks;
29
+ /** Oldest first. */
30
+ private readonly tabBars;
31
+ /** Offer a tab bar's unopened tabs to a push into one. Returns an unsubscribe. */
32
+ addTabBar(bar: TabBar): () => void;
33
+ /** The url of the unopened tab `url` is a page inside, or null: see `TabBar`. */
34
+ unopenedTabOf(url: string): string | null;
35
+ /** Whether `url` belongs to a tab that is not the one in front. */
36
+ inTabBehind(url: string): boolean;
37
+ /**
38
+ * Whether the app's own stack takes a page presented over whatever is showing. Set by the root
39
+ * stack outlet for as long as there is one: see `presented-route.ts`.
40
+ */
41
+ presents: boolean;
18
42
  /** Offer a stack for popping several screens at once. Returns an unsubscribe. */
19
43
  addStack(stack: PoppableStack): () => void;
20
44
  /** Pop the innermost stack in front that is deeper than one screen, to its first. */
@@ -22,15 +46,20 @@ export declare class NativeBack {
22
46
  /** Pop the innermost stack in front that has a screen at `url` below its top, down to it. */
23
47
  popTo(url: string): Promise<boolean>;
24
48
  /**
25
- * Offer an outlet's answer to a back. It returns whether it went back, and false lets the next
26
- * one out try. Returns an unsubscribe.
49
+ * Offer an outlet's answer to a back. It returns whether it took the back, and false lets the
50
+ * next one out try. Returns an unsubscribe.
27
51
  */
28
- handle(answer: () => boolean): () => void;
52
+ handle(answer: BackAnswer): () => void;
29
53
  /** Go back as the button would, innermost outlet first. False when none had anywhere to go. */
30
54
  back(): boolean;
31
55
  static ɵfac: i0.ɵɵFactoryDeclaration<NativeBack, never>;
32
56
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
33
57
  }
58
+ /**
59
+ * An outlet's answer to a back, told where it came from: Android's button, which is the platform's
60
+ * own dismissal and a screen may refuse, or the app's `NativeNavigation.back()`, which it may not.
61
+ */
62
+ export type BackAnswer = (from: 'button' | 'app') => boolean;
34
63
  /**
35
64
  * Whether a route is part of what the router shows now, rather than a subtree the reuse strategy
36
65
  * detached and is keeping for later: a tab behind, or a screen covered by one pushed over it.
@@ -20,6 +20,35 @@ export class NativeBack {
20
20
  answers = [];
21
21
  /** Oldest first, and so outermost first, as the answers are. */
22
22
  stacks = [];
23
+ /** Oldest first. */
24
+ tabBars = [];
25
+ /** Offer a tab bar's unopened tabs to a push into one. Returns an unsubscribe. */
26
+ addTabBar(bar) {
27
+ this.tabBars.push(bar);
28
+ return () => {
29
+ const index = this.tabBars.indexOf(bar);
30
+ if (index !== -1)
31
+ this.tabBars.splice(index, 1);
32
+ };
33
+ }
34
+ /** The url of the unopened tab `url` is a page inside, or null: see `TabBar`. */
35
+ unopenedTabOf(url) {
36
+ for (const bar of this.tabBars) {
37
+ const root = bar.unopenedTabOf(url);
38
+ if (root)
39
+ return root;
40
+ }
41
+ return null;
42
+ }
43
+ /** Whether `url` belongs to a tab that is not the one in front. */
44
+ inTabBehind(url) {
45
+ return this.tabBars.some((bar) => bar.behind(url));
46
+ }
47
+ /**
48
+ * Whether the app's own stack takes a page presented over whatever is showing. Set by the root
49
+ * stack outlet for as long as there is one: see `presented-route.ts`.
50
+ */
51
+ presents = false;
23
52
  /** Offer a stack for popping several screens at once. Returns an unsubscribe. */
24
53
  addStack(stack) {
25
54
  this.stacks.push(stack);
@@ -52,12 +81,12 @@ export class NativeBack {
52
81
  return Promise.resolve(false);
53
82
  }
54
83
  /**
55
- * Offer an outlet's answer to a back. It returns whether it went back, and false lets the next
56
- * one out try. Returns an unsubscribe.
84
+ * Offer an outlet's answer to a back. It returns whether it took the back, and false lets the
85
+ * next one out try. Returns an unsubscribe.
57
86
  */
58
87
  handle(answer) {
59
88
  this.answers.push(answer);
60
- const stop = this.hardwareBack.handle(answer);
89
+ const stop = this.hardwareBack.handle(() => answer('button'));
61
90
  return () => {
62
91
  stop();
63
92
  const index = this.answers.indexOf(answer);
@@ -67,7 +96,7 @@ export class NativeBack {
67
96
  }
68
97
  /** Go back as the button would, innermost outlet first. False when none had anywhere to go. */
69
98
  back() {
70
- return [...this.answers].reverse().some((answer) => answer());
99
+ return [...this.answers].reverse().some((answer) => answer('app'));
71
100
  }
72
101
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: NativeBack, deps: [], target: i0.ɵɵFactoryTarget.Service });
73
102
  static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.2.0", ngImport: i0, type: NativeBack });
@@ -1 +1 @@
1
- {"version":3,"file":"native-back.js","sourceRoot":"","sources":["../src/native-back.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Who answers a back: Android's hardware button, and `NativeNavigation.back()`.\n *\n * Every outlet offers an answer, and the one in front takes it. Each answer is also handed to\n * `HardwareBack` directly, where React Native asks the newest first. An outlet always subscribes\n * after the outlet it sits inside, so that order runs from the innermost outlet out, and a\n * screen's own handler, subscribed after its outlet, still outranks it. `back()` asks the outlets\n * in that same order, without the screens' own handlers: those are for the button.\n *\n * Newest first is not enough on its own. A stack in a tab behind the one in front, or under a\n * screen pushed over the whole tab bar, is still subscribed, so each answer first checks that\n * its outlet is showing what the router is showing.\n */\nimport { Service, inject } from '@angular/core';\nimport type { ActivatedRoute, Router } from '@angular/router';\nimport { HardwareBack } from '@ng-native/device';\n\n/** What a stack offers `NativeNavigation` beyond a back: going down it several screens at once. */\nexport interface PoppableStack {\n /** Whether this stack is part of what the router shows now. */\n showing(): boolean;\n /** Pop to its first screen, or null when it is showing only that one. */\n popToRoot(): Promise<boolean> | null;\n /** Pop to the screen showing `url`, or null when no screen below the top shows it. */\n popTo(url: string): Promise<boolean> | null;\n}\n\n@Service()\nexport class NativeBack {\n private readonly hardwareBack = inject(HardwareBack);\n /** Oldest first, as `HardwareBack` holds them. */\n private readonly answers: (() => boolean)[] = [];\n /** Oldest first, and so outermost first, as the answers are. */\n private readonly stacks: PoppableStack[] = [];\n\n /** Offer a stack for popping several screens at once. Returns an unsubscribe. */\n addStack(stack: PoppableStack): () => void {\n this.stacks.push(stack);\n return () => {\n const index = this.stacks.indexOf(stack);\n if (index !== -1) this.stacks.splice(index, 1);\n };\n }\n\n /** Pop the innermost stack in front that is deeper than one screen, to its first. */\n popToRoot(): Promise<boolean> {\n for (const stack of [...this.stacks].reverse()) {\n if (!stack.showing()) continue;\n const popped = stack.popToRoot();\n if (popped) return popped;\n }\n return Promise.resolve(false);\n }\n\n /** Pop the innermost stack in front that has a screen at `url` below its top, down to it. */\n popTo(url: string): Promise<boolean> {\n for (const stack of [...this.stacks].reverse()) {\n if (!stack.showing()) continue;\n const popped = stack.popTo(url);\n if (popped) return popped;\n }\n return Promise.resolve(false);\n }\n\n /**\n * Offer an outlet's answer to a back. It returns whether it went back, and false lets the next\n * one out try. Returns an unsubscribe.\n */\n handle(answer: () => boolean): () => void {\n this.answers.push(answer);\n const stop = this.hardwareBack.handle(answer);\n return () => {\n stop();\n const index = this.answers.indexOf(answer);\n if (index !== -1) this.answers.splice(index, 1);\n };\n }\n\n /** Go back as the button would, innermost outlet first. False when none had anywhere to go. */\n back(): boolean {\n return [...this.answers].reverse().some((answer) => answer());\n }\n}\n\n/**\n * Whether a route is part of what the router shows now, rather than a subtree the reuse strategy\n * detached and is keeping for later: a tab behind, or a screen covered by one pushed over it.\n */\nexport function isShowing(router: Router, route: ActivatedRoute | null): boolean {\n if (!route) return false;\n const visit = (node: ActivatedRoute): boolean => node === route || node.children.some(visit);\n return visit(router.routerState.root);\n}\n"]}
1
+ {"version":3,"file":"native-back.js","sourceRoot":"","sources":["../src/native-back.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Who answers a back: Android's hardware button, and `NativeNavigation.back()`.\n *\n * Every outlet offers an answer, and the one in front takes it. Each answer is also handed to\n * `HardwareBack` directly, where React Native asks the newest first. An outlet always subscribes\n * after the outlet it sits inside, so that order runs from the innermost outlet out, and a\n * screen's own handler, subscribed after its outlet, still outranks it. `back()` asks the outlets\n * in that same order, without the screens' own handlers: those are for the button.\n *\n * Newest first is not enough on its own. A stack in a tab behind the one in front, or under a\n * screen pushed over the whole tab bar, is still subscribed, so each answer first checks that\n * its outlet is showing what the router is showing.\n */\nimport { Service, inject } from '@angular/core';\nimport type { ActivatedRoute, Router } from '@angular/router';\nimport { HardwareBack } from '@ng-native/device';\n\n/** What a stack offers `NativeNavigation` beyond a back: going down it several screens at once. */\nexport interface PoppableStack {\n /** Whether this stack is part of what the router shows now. */\n showing(): boolean;\n /** Pop to its first screen, or null when it is showing only that one. */\n popToRoot(): Promise<boolean> | null;\n /** Pop to the screen showing `url`, or null when no screen below the top shows it. */\n popTo(url: string): Promise<boolean> | null;\n}\n\n/**\n * What a tab bar offers `NativeNavigation` for a push into one of its tabs from outside it. A tab\n * nobody has opened has no stack yet, and a page pushed into it would be the stack's first\n * screen, with nothing under it to go back to.\n */\nexport interface TabBar {\n /** The url of the tab `url` is a page inside, when that tab has not been opened. */\n unopenedTabOf(url: string): string | null;\n /** Whether `url` is a tab other than the one in front, or a page inside one. */\n behind(url: string): boolean;\n}\n\n@Service()\nexport class NativeBack {\n private readonly hardwareBack = inject(HardwareBack);\n /** Oldest first, as `HardwareBack` holds them. */\n private readonly answers: BackAnswer[] = [];\n /** Oldest first, and so outermost first, as the answers are. */\n private readonly stacks: PoppableStack[] = [];\n\n /** Oldest first. */\n private readonly tabBars: TabBar[] = [];\n\n /** Offer a tab bar's unopened tabs to a push into one. Returns an unsubscribe. */\n addTabBar(bar: TabBar): () => void {\n this.tabBars.push(bar);\n return () => {\n const index = this.tabBars.indexOf(bar);\n if (index !== -1) this.tabBars.splice(index, 1);\n };\n }\n\n /** The url of the unopened tab `url` is a page inside, or null: see `TabBar`. */\n unopenedTabOf(url: string): string | null {\n for (const bar of this.tabBars) {\n const root = bar.unopenedTabOf(url);\n if (root) return root;\n }\n return null;\n }\n\n /** Whether `url` belongs to a tab that is not the one in front. */\n inTabBehind(url: string): boolean {\n return this.tabBars.some((bar) => bar.behind(url));\n }\n\n /**\n * Whether the app's own stack takes a page presented over whatever is showing. Set by the root\n * stack outlet for as long as there is one: see `presented-route.ts`.\n */\n presents = false;\n\n /** Offer a stack for popping several screens at once. Returns an unsubscribe. */\n addStack(stack: PoppableStack): () => void {\n this.stacks.push(stack);\n return () => {\n const index = this.stacks.indexOf(stack);\n if (index !== -1) this.stacks.splice(index, 1);\n };\n }\n\n /** Pop the innermost stack in front that is deeper than one screen, to its first. */\n popToRoot(): Promise<boolean> {\n for (const stack of [...this.stacks].reverse()) {\n if (!stack.showing()) continue;\n const popped = stack.popToRoot();\n if (popped) return popped;\n }\n return Promise.resolve(false);\n }\n\n /** Pop the innermost stack in front that has a screen at `url` below its top, down to it. */\n popTo(url: string): Promise<boolean> {\n for (const stack of [...this.stacks].reverse()) {\n if (!stack.showing()) continue;\n const popped = stack.popTo(url);\n if (popped) return popped;\n }\n return Promise.resolve(false);\n }\n\n /**\n * Offer an outlet's answer to a back. It returns whether it took the back, and false lets the\n * next one out try. Returns an unsubscribe.\n */\n handle(answer: BackAnswer): () => void {\n this.answers.push(answer);\n const stop = this.hardwareBack.handle(() => answer('button'));\n return () => {\n stop();\n const index = this.answers.indexOf(answer);\n if (index !== -1) this.answers.splice(index, 1);\n };\n }\n\n /** Go back as the button would, innermost outlet first. False when none had anywhere to go. */\n back(): boolean {\n return [...this.answers].reverse().some((answer) => answer('app'));\n }\n}\n\n/**\n * An outlet's answer to a back, told where it came from: Android's button, which is the platform's\n * own dismissal and a screen may refuse, or the app's `NativeNavigation.back()`, which it may not.\n */\nexport type BackAnswer = (from: 'button' | 'app') => boolean;\n\n/**\n * Whether a route is part of what the router shows now, rather than a subtree the reuse strategy\n * detached and is keeping for later: a tab behind, or a screen covered by one pushed over it.\n */\nexport function isShowing(router: Router, route: ActivatedRoute | null): boolean {\n if (!route) return false;\n const visit = (node: ActivatedRoute): boolean => node === route || node.children.some(visit);\n return visit(router.routerState.root);\n}\n"]}
@@ -18,6 +18,13 @@ import type { TabAppearance } from './native-tab.ts';
18
18
  export type SchemeDefaults<T> = T | ((scheme: Scheme) => T);
19
19
  /** The appearance inputs of `<native-header>` that make sense for a whole app. */
20
20
  export interface HeaderDefaults {
21
+ /**
22
+ * On iOS 26 and later, the Liquid Glass navigation bar for every header that has no background
23
+ * of its own: clear and unlined, with the content scrolling under it and blurring out. The bar
24
+ * is then over the page, so the page's scroll view takes
25
+ * `contentInsetAdjustmentBehavior="automatic"` to start below it. Elsewhere it does nothing.
26
+ */
27
+ readonly liquidGlass?: boolean;
21
28
  readonly userInterfaceStyle?: HeaderInterfaceStyle;
22
29
  readonly backgroundColor?: string | number;
23
30
  readonly color?: string | number;
@@ -1 +1 @@
1
- {"version":3,"file":"native-bar-defaults.js","sourceRoot":"","sources":["../src/native-bar-defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,EAAe,MAAM,eAAe,CAAC;AAwCpE,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;AAErC,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,cAAc,CACtD,qCAAqC,EACrC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,cAAc,CACnD,kCAAkC,EAClC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CACxB,CAAC","sourcesContent":["/**\n * How every bar in the app looks when a call site does not say, set once with\n * `withHeaderDefaults` and `withTabDefaults` beside the routes.\n *\n * A bar is configured with props, and a prop cannot read the cascade, so an app whose bars should\n * match its pages would otherwise repeat the same bindings on every `<native-header>`. These fill\n * only what a call site left unset: a header that binds `backgroundColor` keeps it.\n *\n * Either kind can be a function of the colour scheme, which is how a bar follows the system\n * appearance the way a page's `@media (prefers-color-scheme: dark)` rules do. It runs inside a\n * `computed`, so any signal it reads is followed too.\n */\nimport { InjectionToken, signal, type Signal } from '@angular/core';\nimport type { Scheme } from '@ng-native/device';\nimport type { BackButtonDisplayMode, BlurEffect, HeaderInterfaceStyle } from './native-header.ts';\nimport type { TabAppearance } from './native-tab.ts';\n\n/** A set of defaults, fixed or chosen per colour scheme. */\nexport type SchemeDefaults<T> = T | ((scheme: Scheme) => T);\n\n/** The appearance inputs of `<native-header>` that make sense for a whole app. */\nexport interface HeaderDefaults {\n readonly userInterfaceStyle?: HeaderInterfaceStyle;\n readonly backgroundColor?: string | number;\n readonly color?: string | number;\n readonly blurEffect?: BlurEffect;\n readonly hideShadow?: boolean;\n readonly translucent?: boolean;\n readonly titleColor?: string | number;\n readonly titleFontFamily?: string;\n readonly titleFontSize?: number;\n readonly titleFontWeight?: string;\n readonly largeTitleColor?: string | number;\n readonly largeTitleBackgroundColor?: string | number;\n readonly largeTitleFontFamily?: string;\n readonly largeTitleFontSize?: number;\n readonly largeTitleFontWeight?: string;\n readonly largeTitleHideShadow?: boolean;\n readonly backTitleFontFamily?: string;\n readonly backTitleFontSize?: number;\n readonly backButtonDisplayMode?: BackButtonDisplayMode;\n}\n\n/** The appearance inputs of `<native-tabs-outlet>` and `<native-tab>` that suit a whole app. */\nexport interface TabDefaults {\n readonly tintColor?: string | number;\n readonly backgroundColor?: string | number;\n readonly colorScheme?: 'inherit' | 'light' | 'dark';\n readonly standardAppearance?: TabAppearance;\n readonly scrollEdgeAppearance?: TabAppearance;\n}\n\nconst none = signal({}).asReadonly();\n\nexport const NATIVE_HEADER_DEFAULTS = new InjectionToken<Signal<HeaderDefaults>>(\n 'angular-native.nativeHeaderDefaults',\n { factory: () => none },\n);\n\nexport const NATIVE_TAB_DEFAULTS = new InjectionToken<Signal<TabDefaults>>(\n 'angular-native.nativeTabDefaults',\n { factory: () => none },\n);\n"]}
1
+ {"version":3,"file":"native-bar-defaults.js","sourceRoot":"","sources":["../src/native-bar-defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,EAAe,MAAM,eAAe,CAAC;AA+CpE,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;AAErC,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,cAAc,CACtD,qCAAqC,EACrC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,cAAc,CACnD,kCAAkC,EAClC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CACxB,CAAC","sourcesContent":["/**\n * How every bar in the app looks when a call site does not say, set once with\n * `withHeaderDefaults` and `withTabDefaults` beside the routes.\n *\n * A bar is configured with props, and a prop cannot read the cascade, so an app whose bars should\n * match its pages would otherwise repeat the same bindings on every `<native-header>`. These fill\n * only what a call site left unset: a header that binds `backgroundColor` keeps it.\n *\n * Either kind can be a function of the colour scheme, which is how a bar follows the system\n * appearance the way a page's `@media (prefers-color-scheme: dark)` rules do. It runs inside a\n * `computed`, so any signal it reads is followed too.\n */\nimport { InjectionToken, signal, type Signal } from '@angular/core';\nimport type { Scheme } from '@ng-native/device';\nimport type { BackButtonDisplayMode, BlurEffect, HeaderInterfaceStyle } from './native-header.ts';\nimport type { TabAppearance } from './native-tab.ts';\n\n/** A set of defaults, fixed or chosen per colour scheme. */\nexport type SchemeDefaults<T> = T | ((scheme: Scheme) => T);\n\n/** The appearance inputs of `<native-header>` that make sense for a whole app. */\nexport interface HeaderDefaults {\n /**\n * On iOS 26 and later, the Liquid Glass navigation bar for every header that has no background\n * of its own: clear and unlined, with the content scrolling under it and blurring out. The bar\n * is then over the page, so the page's scroll view takes\n * `contentInsetAdjustmentBehavior=\"automatic\"` to start below it. Elsewhere it does nothing.\n */\n readonly liquidGlass?: boolean;\n readonly userInterfaceStyle?: HeaderInterfaceStyle;\n readonly backgroundColor?: string | number;\n readonly color?: string | number;\n readonly blurEffect?: BlurEffect;\n readonly hideShadow?: boolean;\n readonly translucent?: boolean;\n readonly titleColor?: string | number;\n readonly titleFontFamily?: string;\n readonly titleFontSize?: number;\n readonly titleFontWeight?: string;\n readonly largeTitleColor?: string | number;\n readonly largeTitleBackgroundColor?: string | number;\n readonly largeTitleFontFamily?: string;\n readonly largeTitleFontSize?: number;\n readonly largeTitleFontWeight?: string;\n readonly largeTitleHideShadow?: boolean;\n readonly backTitleFontFamily?: string;\n readonly backTitleFontSize?: number;\n readonly backButtonDisplayMode?: BackButtonDisplayMode;\n}\n\n/** The appearance inputs of `<native-tabs-outlet>` and `<native-tab>` that suit a whole app. */\nexport interface TabDefaults {\n readonly tintColor?: string | number;\n readonly backgroundColor?: string | number;\n readonly colorScheme?: 'inherit' | 'light' | 'dark';\n readonly standardAppearance?: TabAppearance;\n readonly scrollEdgeAppearance?: TabAppearance;\n}\n\nconst none = signal({}).asReadonly();\n\nexport const NATIVE_HEADER_DEFAULTS = new InjectionToken<Signal<HeaderDefaults>>(\n 'angular-native.nativeHeaderDefaults',\n { factory: () => none },\n);\n\nexport const NATIVE_TAB_DEFAULTS = new InjectionToken<Signal<TabDefaults>>(\n 'angular-native.nativeTabDefaults',\n { factory: () => none },\n);\n"]}
@@ -22,6 +22,15 @@ export declare class NativeHeader {
22
22
  * or `withHeaderDefaults` did say. See `native-header-palette.ts` for retuning them.
23
23
  */
24
24
  private readonly colours;
25
+ /** iOS 26 and later, where the system's own bar is clear and floats over the content. */
26
+ private readonly glass;
27
+ /**
28
+ * Whether the bar is iOS 26's Liquid Glass one, which `liquidGlass` asks for here or through
29
+ * `withHeaderDefaults`: clear, over the content, with no line under it, where the system blurs
30
+ * what scrolls beneath and floats the buttons. Only on iOS 26 and later, and only while nothing
31
+ * gave the bar a background of its own.
32
+ */
33
+ protected readonly isLiquidGlass: import("@angular/core").Signal<true | undefined>;
25
34
  protected readonly resolvedBackgroundColor: import("@angular/core").Signal<string | number>;
26
35
  protected readonly resolvedColor: import("@angular/core").Signal<string | number>;
27
36
  protected readonly resolvedTitleColor: import("@angular/core").Signal<string | number>;
@@ -42,6 +51,13 @@ export declare class NativeHeader {
42
51
  readonly titleFontSize: import("@angular/core").InputSignalWithTransform<number | undefined, unknown>;
43
52
  /** A CSS font weight, `'600'` or `'bold'`. */
44
53
  readonly titleFontWeight: import("@angular/core").InputSignal<string | undefined>;
54
+ /**
55
+ * On iOS 26 and later, the Liquid Glass navigation bar for this header, where it has no
56
+ * background of its own: clear and unlined, with the content scrolling under it. `false` keeps
57
+ * the neutral bar on a page of an app whose `withHeaderDefaults` asks for the glass one. The
58
+ * bar is over the page, so its scroll view takes `contentInsetAdjustmentBehavior="automatic"`.
59
+ */
60
+ readonly liquidGlass: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
45
61
  /** The bar's background. Ignored unless `blurEffect` is `none`. */
46
62
  readonly backgroundColor: import("@angular/core").InputSignal<string | number | undefined>;
47
63
  /** Tint colour: the back chevron, and any header item that does not set its own. */
@@ -99,5 +115,5 @@ export declare class NativeHeader {
99
115
  readonly consumeRightInset: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
100
116
  readonly consumeBottomInset: import("@angular/core").InputSignalWithTransform<boolean | undefined, unknown>;
101
117
  static ɵfac: i0.ɵɵFactoryDeclaration<NativeHeader, never>;
102
- static ɵcmp: i0.ɵɵComponentDeclaration<NativeHeader, "native-header", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "titleColor": { "alias": "titleColor"; "required": false; "isSignal": true; }; "titleFontFamily": { "alias": "titleFontFamily"; "required": false; "isSignal": true; }; "titleFontSize": { "alias": "titleFontSize"; "required": false; "isSignal": true; }; "titleFontWeight": { "alias": "titleFontWeight"; "required": false; "isSignal": true; }; "backgroundColor": { "alias": "backgroundColor"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "blurEffect": { "alias": "blurEffect"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; "hideShadow": { "alias": "hideShadow"; "required": false; "isSignal": true; }; "translucent": { "alias": "translucent"; "required": false; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "topInsetEnabled": { "alias": "topInsetEnabled"; "required": false; "isSignal": true; }; "userInterfaceStyle": { "alias": "userInterfaceStyle"; "required": false; "isSignal": true; }; "largeTitle": { "alias": "largeTitle"; "required": false; "isSignal": true; }; "largeTitleColor": { "alias": "largeTitleColor"; "required": false; "isSignal": true; }; "largeTitleBackgroundColor": { "alias": "largeTitleBackgroundColor"; "required": false; "isSignal": true; }; "largeTitleFontFamily": { "alias": "largeTitleFontFamily"; "required": false; "isSignal": true; }; "largeTitleFontSize": { "alias": "largeTitleFontSize"; "required": false; "isSignal": true; }; "largeTitleFontWeight": { "alias": "largeTitleFontWeight"; "required": false; "isSignal": true; }; "largeTitleHideShadow": { "alias": "largeTitleHideShadow"; "required": false; "isSignal": true; }; "backTitle": { "alias": "backTitle"; "required": false; "isSignal": true; }; "backTitleFontFamily": { "alias": "backTitleFontFamily"; "required": false; "isSignal": true; }; "backTitleFontSize": { "alias": "backTitleFontSize"; "required": false; "isSignal": true; }; "backTitleVisible": { "alias": "backTitleVisible"; "required": false; "isSignal": true; }; "backButtonDisplayMode": { "alias": "backButtonDisplayMode"; "required": false; "isSignal": true; }; "backButtonInCustomView": { "alias": "backButtonInCustomView"; "required": false; "isSignal": true; }; "disableBackButtonMenu": { "alias": "disableBackButtonMenu"; "required": false; "isSignal": true; }; "hideBackButton": { "alias": "hideBackButton"; "required": false; "isSignal": true; }; "consumeTopInset": { "alias": "consumeTopInset"; "required": false; "isSignal": true; }; "consumeLeftInset": { "alias": "consumeLeftInset"; "required": false; "isSignal": true; }; "consumeRightInset": { "alias": "consumeRightInset"; "required": false; "isSignal": true; }; "consumeBottomInset": { "alias": "consumeBottomInset"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
118
+ static ɵcmp: i0.ɵɵComponentDeclaration<NativeHeader, "native-header", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "titleColor": { "alias": "titleColor"; "required": false; "isSignal": true; }; "titleFontFamily": { "alias": "titleFontFamily"; "required": false; "isSignal": true; }; "titleFontSize": { "alias": "titleFontSize"; "required": false; "isSignal": true; }; "titleFontWeight": { "alias": "titleFontWeight"; "required": false; "isSignal": true; }; "liquidGlass": { "alias": "liquidGlass"; "required": false; "isSignal": true; }; "backgroundColor": { "alias": "backgroundColor"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "blurEffect": { "alias": "blurEffect"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; "hideShadow": { "alias": "hideShadow"; "required": false; "isSignal": true; }; "translucent": { "alias": "translucent"; "required": false; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "topInsetEnabled": { "alias": "topInsetEnabled"; "required": false; "isSignal": true; }; "userInterfaceStyle": { "alias": "userInterfaceStyle"; "required": false; "isSignal": true; }; "largeTitle": { "alias": "largeTitle"; "required": false; "isSignal": true; }; "largeTitleColor": { "alias": "largeTitleColor"; "required": false; "isSignal": true; }; "largeTitleBackgroundColor": { "alias": "largeTitleBackgroundColor"; "required": false; "isSignal": true; }; "largeTitleFontFamily": { "alias": "largeTitleFontFamily"; "required": false; "isSignal": true; }; "largeTitleFontSize": { "alias": "largeTitleFontSize"; "required": false; "isSignal": true; }; "largeTitleFontWeight": { "alias": "largeTitleFontWeight"; "required": false; "isSignal": true; }; "largeTitleHideShadow": { "alias": "largeTitleHideShadow"; "required": false; "isSignal": true; }; "backTitle": { "alias": "backTitle"; "required": false; "isSignal": true; }; "backTitleFontFamily": { "alias": "backTitleFontFamily"; "required": false; "isSignal": true; }; "backTitleFontSize": { "alias": "backTitleFontSize"; "required": false; "isSignal": true; }; "backTitleVisible": { "alias": "backTitleVisible"; "required": false; "isSignal": true; }; "backButtonDisplayMode": { "alias": "backButtonDisplayMode"; "required": false; "isSignal": true; }; "backButtonInCustomView": { "alias": "backButtonInCustomView"; "required": false; "isSignal": true; }; "disableBackButtonMenu": { "alias": "disableBackButtonMenu"; "required": false; "isSignal": true; }; "hideBackButton": { "alias": "hideBackButton"; "required": false; "isSignal": true; }; "consumeTopInset": { "alias": "consumeTopInset"; "required": false; "isSignal": true; }; "consumeLeftInset": { "alias": "consumeLeftInset"; "required": false; "isSignal": true; }; "consumeRightInset": { "alias": "consumeRightInset"; "required": false; "isSignal": true; }; "consumeBottomInset": { "alias": "consumeBottomInset"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
103
119
  }
@@ -27,7 +27,7 @@
27
27
  */
28
28
  import { Component, computed, input } from '@angular/core';
29
29
  import { ElementRef, inject } from '@angular/core';
30
- import { ColorScheme } from '@ng-native/device';
30
+ import { ColorScheme, OS_VERSION } from '@ng-native/device';
31
31
  import { NATIVE_HEADER_DEFAULTS } from "./native-bar-defaults.js";
32
32
  import { NATIVE_HEADER_PALETTE } from "./native-header-palette.js";
33
33
  import { ownHost } from "./own-host.js";
@@ -52,7 +52,24 @@ export class NativeHeader {
52
52
  */
53
53
  colours = computed(() => this.palette[this.scheme.current()], /* @ts-ignore */
54
54
  ...(ngDevMode ? [{ debugName: "colours" }] : /* istanbul ignore next */ []));
55
- resolvedBackgroundColor = computed(() => this.backgroundColor() ?? this.defaults().backgroundColor ?? this.colours().background, /* @ts-ignore */
55
+ /** iOS 26 and later, where the system's own bar is clear and floats over the content. */
56
+ glass = nativePlatform() === 'ios' && (inject(OS_VERSION) ?? 0) >= 26;
57
+ /**
58
+ * Whether the bar is iOS 26's Liquid Glass one, which `liquidGlass` asks for here or through
59
+ * `withHeaderDefaults`: clear, over the content, with no line under it, where the system blurs
60
+ * what scrolls beneath and floats the buttons. Only on iOS 26 and later, and only while nothing
61
+ * gave the bar a background of its own.
62
+ */
63
+ isLiquidGlass = computed(() => this.glass &&
64
+ (this.liquidGlass() ?? this.defaults().liquidGlass) &&
65
+ this.backgroundColor() === undefined &&
66
+ this.defaults().backgroundColor === undefined
67
+ ? true
68
+ : undefined, /* @ts-ignore */
69
+ ...(ngDevMode ? [{ debugName: "isLiquidGlass" }] : /* istanbul ignore next */ []));
70
+ resolvedBackgroundColor = computed(() => this.backgroundColor() ??
71
+ this.defaults().backgroundColor ??
72
+ (this.isLiquidGlass() ? 'transparent' : this.colours().background), /* @ts-ignore */
56
73
  ...(ngDevMode ? [{ debugName: "resolvedBackgroundColor" }] : /* istanbul ignore next */ []));
57
74
  resolvedColor = computed(() => this.color() ?? this.defaults().color ?? this.colours().foreground, /* @ts-ignore */
58
75
  ...(ngDevMode ? [{ debugName: "resolvedColor" }] : /* istanbul ignore next */ []));
@@ -85,6 +102,13 @@ export class NativeHeader {
85
102
  titleFontWeight = input(/* @ts-ignore */
86
103
  ...(ngDevMode ? [undefined, { debugName: "titleFontWeight" }] : /* istanbul ignore next */ []));
87
104
  // --- the bar itself ------------------------------------------------------------------
105
+ /**
106
+ * On iOS 26 and later, the Liquid Glass navigation bar for this header, where it has no
107
+ * background of its own: clear and unlined, with the content scrolling under it. `false` keeps
108
+ * the neutral bar on a page of an app whose `withHeaderDefaults` asks for the glass one. The
109
+ * bar is over the page, so its scroll view takes `contentInsetAdjustmentBehavior="automatic"`.
110
+ */
111
+ liquidGlass = input(undefined, { ...(ngDevMode ? { debugName: "liquidGlass" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
88
112
  /** The bar's background. Ignored unless `blurEffect` is `none`. */
89
113
  backgroundColor = input(/* @ts-ignore */
90
114
  ...(ngDevMode ? [undefined, { debugName: "backgroundColor" }] : /* istanbul ignore next */ []));
@@ -157,7 +181,7 @@ export class NativeHeader {
157
181
  consumeRightInset = input(undefined, { ...(ngDevMode ? { debugName: "consumeRightInset" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
158
182
  consumeBottomInset = input(undefined, { ...(ngDevMode ? { debugName: "consumeBottomInset" } : /* istanbul ignore next */ {}), transform: optionalBoolean });
159
183
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: NativeHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
160
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: NativeHeader, isStandalone: true, selector: "native-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, titleColor: { classPropertyName: "titleColor", publicName: "titleColor", isSignal: true, isRequired: false, transformFunction: null }, titleFontFamily: { classPropertyName: "titleFontFamily", publicName: "titleFontFamily", isSignal: true, isRequired: false, transformFunction: null }, titleFontSize: { classPropertyName: "titleFontSize", publicName: "titleFontSize", isSignal: true, isRequired: false, transformFunction: null }, titleFontWeight: { classPropertyName: "titleFontWeight", publicName: "titleFontWeight", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, blurEffect: { classPropertyName: "blurEffect", publicName: "blurEffect", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, hideShadow: { classPropertyName: "hideShadow", publicName: "hideShadow", isSignal: true, isRequired: false, transformFunction: null }, translucent: { classPropertyName: "translucent", publicName: "translucent", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, topInsetEnabled: { classPropertyName: "topInsetEnabled", publicName: "topInsetEnabled", isSignal: true, isRequired: false, transformFunction: null }, userInterfaceStyle: { classPropertyName: "userInterfaceStyle", publicName: "userInterfaceStyle", isSignal: true, isRequired: false, transformFunction: null }, largeTitle: { classPropertyName: "largeTitle", publicName: "largeTitle", isSignal: true, isRequired: false, transformFunction: null }, largeTitleColor: { classPropertyName: "largeTitleColor", publicName: "largeTitleColor", isSignal: true, isRequired: false, transformFunction: null }, largeTitleBackgroundColor: { classPropertyName: "largeTitleBackgroundColor", publicName: "largeTitleBackgroundColor", isSignal: true, isRequired: false, transformFunction: null }, largeTitleFontFamily: { classPropertyName: "largeTitleFontFamily", publicName: "largeTitleFontFamily", isSignal: true, isRequired: false, transformFunction: null }, largeTitleFontSize: { classPropertyName: "largeTitleFontSize", publicName: "largeTitleFontSize", isSignal: true, isRequired: false, transformFunction: null }, largeTitleFontWeight: { classPropertyName: "largeTitleFontWeight", publicName: "largeTitleFontWeight", isSignal: true, isRequired: false, transformFunction: null }, largeTitleHideShadow: { classPropertyName: "largeTitleHideShadow", publicName: "largeTitleHideShadow", isSignal: true, isRequired: false, transformFunction: null }, backTitle: { classPropertyName: "backTitle", publicName: "backTitle", isSignal: true, isRequired: false, transformFunction: null }, backTitleFontFamily: { classPropertyName: "backTitleFontFamily", publicName: "backTitleFontFamily", isSignal: true, isRequired: false, transformFunction: null }, backTitleFontSize: { classPropertyName: "backTitleFontSize", publicName: "backTitleFontSize", isSignal: true, isRequired: false, transformFunction: null }, backTitleVisible: { classPropertyName: "backTitleVisible", publicName: "backTitleVisible", isSignal: true, isRequired: false, transformFunction: null }, backButtonDisplayMode: { classPropertyName: "backButtonDisplayMode", publicName: "backButtonDisplayMode", isSignal: true, isRequired: false, transformFunction: null }, backButtonInCustomView: { classPropertyName: "backButtonInCustomView", publicName: "backButtonInCustomView", isSignal: true, isRequired: false, transformFunction: null }, disableBackButtonMenu: { classPropertyName: "disableBackButtonMenu", publicName: "disableBackButtonMenu", isSignal: true, isRequired: false, transformFunction: null }, hideBackButton: { classPropertyName: "hideBackButton", publicName: "hideBackButton", isSignal: true, isRequired: false, transformFunction: null }, consumeTopInset: { classPropertyName: "consumeTopInset", publicName: "consumeTopInset", isSignal: true, isRequired: false, transformFunction: null }, consumeLeftInset: { classPropertyName: "consumeLeftInset", publicName: "consumeLeftInset", isSignal: true, isRequired: false, transformFunction: null }, consumeRightInset: { classPropertyName: "consumeRightInset", publicName: "consumeRightInset", isSignal: true, isRequired: false, transformFunction: null }, consumeBottomInset: { classPropertyName: "consumeBottomInset", publicName: "consumeBottomInset", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "title": "title()", "titleColor": "resolvedTitleColor()", "titleFontFamily": "titleFontFamily() ?? defaults().titleFontFamily", "titleFontSize": "titleFontSize() ?? defaults().titleFontSize", "titleFontWeight": "titleFontWeight() ?? defaults().titleFontWeight", "backgroundColor": "resolvedBackgroundColor()", "color": "resolvedColor()", "blurEffect": "blurEffect() ?? defaults().blurEffect", "hidden": "hidden()", "hideShadow": "hideShadow() ?? defaults().hideShadow", "translucent": "translucent() ?? defaults().translucent ?? iosLargeTitle()", "direction": "direction()", "topInsetEnabled": "topInsetEnabled()", "userInterfaceStyle": "userInterfaceStyle() ?? defaults().userInterfaceStyle", "largeTitle": "largeTitle()", "largeTitleColor": "largeTitleColor() ?? defaults().largeTitleColor", "largeTitleBackgroundColor": "resolvedLargeTitleBackgroundColor()", "largeTitleFontFamily": "largeTitleFontFamily() ?? defaults().largeTitleFontFamily", "largeTitleFontSize": "largeTitleFontSize() ?? defaults().largeTitleFontSize", "largeTitleFontWeight": "largeTitleFontWeight() ?? defaults().largeTitleFontWeight", "largeTitleHideShadow": "largeTitleHideShadow() ?? defaults().largeTitleHideShadow ?? iosLargeTitle()", "backTitle": "backTitle()", "backTitleFontFamily": "backTitleFontFamily() ?? defaults().backTitleFontFamily", "backTitleFontSize": "backTitleFontSize() ?? defaults().backTitleFontSize", "backTitleVisible": "backTitleVisible()", "backButtonDisplayMode": "backButtonDisplayMode() ?? defaults().backButtonDisplayMode", "backButtonInCustomView": "backButtonInCustomView()", "disableBackButtonMenu": "disableBackButtonMenu()", "hideBackButton": "hideBackButton()", "consumeTopInset": "consumeTopInset()", "consumeLeftInset": "consumeLeftInset()", "consumeRightInset": "consumeRightInset()", "consumeBottomInset": "consumeBottomInset()" } }, ngImport: i0, template: '<ng-content />', isInline: true });
184
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.0", type: NativeHeader, isStandalone: true, selector: "native-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, titleColor: { classPropertyName: "titleColor", publicName: "titleColor", isSignal: true, isRequired: false, transformFunction: null }, titleFontFamily: { classPropertyName: "titleFontFamily", publicName: "titleFontFamily", isSignal: true, isRequired: false, transformFunction: null }, titleFontSize: { classPropertyName: "titleFontSize", publicName: "titleFontSize", isSignal: true, isRequired: false, transformFunction: null }, titleFontWeight: { classPropertyName: "titleFontWeight", publicName: "titleFontWeight", isSignal: true, isRequired: false, transformFunction: null }, liquidGlass: { classPropertyName: "liquidGlass", publicName: "liquidGlass", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, blurEffect: { classPropertyName: "blurEffect", publicName: "blurEffect", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, hideShadow: { classPropertyName: "hideShadow", publicName: "hideShadow", isSignal: true, isRequired: false, transformFunction: null }, translucent: { classPropertyName: "translucent", publicName: "translucent", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, topInsetEnabled: { classPropertyName: "topInsetEnabled", publicName: "topInsetEnabled", isSignal: true, isRequired: false, transformFunction: null }, userInterfaceStyle: { classPropertyName: "userInterfaceStyle", publicName: "userInterfaceStyle", isSignal: true, isRequired: false, transformFunction: null }, largeTitle: { classPropertyName: "largeTitle", publicName: "largeTitle", isSignal: true, isRequired: false, transformFunction: null }, largeTitleColor: { classPropertyName: "largeTitleColor", publicName: "largeTitleColor", isSignal: true, isRequired: false, transformFunction: null }, largeTitleBackgroundColor: { classPropertyName: "largeTitleBackgroundColor", publicName: "largeTitleBackgroundColor", isSignal: true, isRequired: false, transformFunction: null }, largeTitleFontFamily: { classPropertyName: "largeTitleFontFamily", publicName: "largeTitleFontFamily", isSignal: true, isRequired: false, transformFunction: null }, largeTitleFontSize: { classPropertyName: "largeTitleFontSize", publicName: "largeTitleFontSize", isSignal: true, isRequired: false, transformFunction: null }, largeTitleFontWeight: { classPropertyName: "largeTitleFontWeight", publicName: "largeTitleFontWeight", isSignal: true, isRequired: false, transformFunction: null }, largeTitleHideShadow: { classPropertyName: "largeTitleHideShadow", publicName: "largeTitleHideShadow", isSignal: true, isRequired: false, transformFunction: null }, backTitle: { classPropertyName: "backTitle", publicName: "backTitle", isSignal: true, isRequired: false, transformFunction: null }, backTitleFontFamily: { classPropertyName: "backTitleFontFamily", publicName: "backTitleFontFamily", isSignal: true, isRequired: false, transformFunction: null }, backTitleFontSize: { classPropertyName: "backTitleFontSize", publicName: "backTitleFontSize", isSignal: true, isRequired: false, transformFunction: null }, backTitleVisible: { classPropertyName: "backTitleVisible", publicName: "backTitleVisible", isSignal: true, isRequired: false, transformFunction: null }, backButtonDisplayMode: { classPropertyName: "backButtonDisplayMode", publicName: "backButtonDisplayMode", isSignal: true, isRequired: false, transformFunction: null }, backButtonInCustomView: { classPropertyName: "backButtonInCustomView", publicName: "backButtonInCustomView", isSignal: true, isRequired: false, transformFunction: null }, disableBackButtonMenu: { classPropertyName: "disableBackButtonMenu", publicName: "disableBackButtonMenu", isSignal: true, isRequired: false, transformFunction: null }, hideBackButton: { classPropertyName: "hideBackButton", publicName: "hideBackButton", isSignal: true, isRequired: false, transformFunction: null }, consumeTopInset: { classPropertyName: "consumeTopInset", publicName: "consumeTopInset", isSignal: true, isRequired: false, transformFunction: null }, consumeLeftInset: { classPropertyName: "consumeLeftInset", publicName: "consumeLeftInset", isSignal: true, isRequired: false, transformFunction: null }, consumeRightInset: { classPropertyName: "consumeRightInset", publicName: "consumeRightInset", isSignal: true, isRequired: false, transformFunction: null }, consumeBottomInset: { classPropertyName: "consumeBottomInset", publicName: "consumeBottomInset", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "title": "title()", "titleColor": "resolvedTitleColor()", "titleFontFamily": "titleFontFamily() ?? defaults().titleFontFamily", "titleFontSize": "titleFontSize() ?? defaults().titleFontSize", "titleFontWeight": "titleFontWeight() ?? defaults().titleFontWeight", "backgroundColor": "resolvedBackgroundColor()", "color": "resolvedColor()", "blurEffect": "blurEffect() ?? defaults().blurEffect", "hidden": "hidden()", "hideShadow": "hideShadow() ?? defaults().hideShadow ?? isLiquidGlass()", "translucent": "translucent() ?? defaults().translucent ?? iosLargeTitle() ?? isLiquidGlass()", "direction": "direction()", "topInsetEnabled": "topInsetEnabled()", "userInterfaceStyle": "userInterfaceStyle() ?? defaults().userInterfaceStyle", "largeTitle": "largeTitle()", "largeTitleColor": "largeTitleColor() ?? defaults().largeTitleColor", "largeTitleBackgroundColor": "resolvedLargeTitleBackgroundColor()", "largeTitleFontFamily": "largeTitleFontFamily() ?? defaults().largeTitleFontFamily", "largeTitleFontSize": "largeTitleFontSize() ?? defaults().largeTitleFontSize", "largeTitleFontWeight": "largeTitleFontWeight() ?? defaults().largeTitleFontWeight", "largeTitleHideShadow": "largeTitleHideShadow() ?? defaults().largeTitleHideShadow ?? iosLargeTitle()", "backTitle": "backTitle()", "backTitleFontFamily": "backTitleFontFamily() ?? defaults().backTitleFontFamily", "backTitleFontSize": "backTitleFontSize() ?? defaults().backTitleFontSize", "backTitleVisible": "backTitleVisible()", "backButtonDisplayMode": "backButtonDisplayMode() ?? defaults().backButtonDisplayMode", "backButtonInCustomView": "backButtonInCustomView()", "disableBackButtonMenu": "disableBackButtonMenu()", "hideBackButton": "hideBackButton()", "consumeTopInset": "consumeTopInset()", "consumeLeftInset": "consumeLeftInset()", "consumeRightInset": "consumeRightInset()", "consumeBottomInset": "consumeBottomInset()" } }, ngImport: i0, template: '<ng-content />', isInline: true });
161
185
  }
162
186
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: NativeHeader, decorators: [{
163
187
  type: Component,
@@ -174,8 +198,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
174
198
  '[color]': 'resolvedColor()',
175
199
  '[blurEffect]': 'blurEffect() ?? defaults().blurEffect',
176
200
  '[hidden]': 'hidden()',
177
- '[hideShadow]': 'hideShadow() ?? defaults().hideShadow',
178
- '[translucent]': 'translucent() ?? defaults().translucent ?? iosLargeTitle()',
201
+ '[hideShadow]': 'hideShadow() ?? defaults().hideShadow ?? isLiquidGlass()',
202
+ '[translucent]': 'translucent() ?? defaults().translucent ?? iosLargeTitle() ?? isLiquidGlass()',
179
203
  '[direction]': 'direction()',
180
204
  '[topInsetEnabled]': 'topInsetEnabled()',
181
205
  '[userInterfaceStyle]': 'userInterfaceStyle() ?? defaults().userInterfaceStyle',
@@ -200,5 +224,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImpor
200
224
  '[consumeBottomInset]': 'consumeBottomInset()',
201
225
  },
202
226
  }]
203
- }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], titleColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleColor", required: false }] }], titleFontFamily: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleFontFamily", required: false }] }], titleFontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleFontSize", required: false }] }], titleFontWeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleFontWeight", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], blurEffect: [{ type: i0.Input, args: [{ isSignal: true, alias: "blurEffect", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], hideShadow: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideShadow", required: false }] }], translucent: [{ type: i0.Input, args: [{ isSignal: true, alias: "translucent", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], topInsetEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "topInsetEnabled", required: false }] }], userInterfaceStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "userInterfaceStyle", required: false }] }], largeTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitle", required: false }] }], largeTitleColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleColor", required: false }] }], largeTitleBackgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleBackgroundColor", required: false }] }], largeTitleFontFamily: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleFontFamily", required: false }] }], largeTitleFontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleFontSize", required: false }] }], largeTitleFontWeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleFontWeight", required: false }] }], largeTitleHideShadow: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleHideShadow", required: false }] }], backTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "backTitle", required: false }] }], backTitleFontFamily: [{ type: i0.Input, args: [{ isSignal: true, alias: "backTitleFontFamily", required: false }] }], backTitleFontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "backTitleFontSize", required: false }] }], backTitleVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "backTitleVisible", required: false }] }], backButtonDisplayMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "backButtonDisplayMode", required: false }] }], backButtonInCustomView: [{ type: i0.Input, args: [{ isSignal: true, alias: "backButtonInCustomView", required: false }] }], disableBackButtonMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableBackButtonMenu", required: false }] }], hideBackButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideBackButton", required: false }] }], consumeTopInset: [{ type: i0.Input, args: [{ isSignal: true, alias: "consumeTopInset", required: false }] }], consumeLeftInset: [{ type: i0.Input, args: [{ isSignal: true, alias: "consumeLeftInset", required: false }] }], consumeRightInset: [{ type: i0.Input, args: [{ isSignal: true, alias: "consumeRightInset", required: false }] }], consumeBottomInset: [{ type: i0.Input, args: [{ isSignal: true, alias: "consumeBottomInset", required: false }] }] } });
227
+ }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], titleColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleColor", required: false }] }], titleFontFamily: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleFontFamily", required: false }] }], titleFontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleFontSize", required: false }] }], titleFontWeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleFontWeight", required: false }] }], liquidGlass: [{ type: i0.Input, args: [{ isSignal: true, alias: "liquidGlass", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], blurEffect: [{ type: i0.Input, args: [{ isSignal: true, alias: "blurEffect", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], hideShadow: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideShadow", required: false }] }], translucent: [{ type: i0.Input, args: [{ isSignal: true, alias: "translucent", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], topInsetEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "topInsetEnabled", required: false }] }], userInterfaceStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "userInterfaceStyle", required: false }] }], largeTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitle", required: false }] }], largeTitleColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleColor", required: false }] }], largeTitleBackgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleBackgroundColor", required: false }] }], largeTitleFontFamily: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleFontFamily", required: false }] }], largeTitleFontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleFontSize", required: false }] }], largeTitleFontWeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleFontWeight", required: false }] }], largeTitleHideShadow: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeTitleHideShadow", required: false }] }], backTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "backTitle", required: false }] }], backTitleFontFamily: [{ type: i0.Input, args: [{ isSignal: true, alias: "backTitleFontFamily", required: false }] }], backTitleFontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "backTitleFontSize", required: false }] }], backTitleVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "backTitleVisible", required: false }] }], backButtonDisplayMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "backButtonDisplayMode", required: false }] }], backButtonInCustomView: [{ type: i0.Input, args: [{ isSignal: true, alias: "backButtonInCustomView", required: false }] }], disableBackButtonMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableBackButtonMenu", required: false }] }], hideBackButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideBackButton", required: false }] }], consumeTopInset: [{ type: i0.Input, args: [{ isSignal: true, alias: "consumeTopInset", required: false }] }], consumeLeftInset: [{ type: i0.Input, args: [{ isSignal: true, alias: "consumeLeftInset", required: false }] }], consumeRightInset: [{ type: i0.Input, args: [{ isSignal: true, alias: "consumeRightInset", required: false }] }], consumeBottomInset: [{ type: i0.Input, args: [{ isSignal: true, alias: "consumeBottomInset", required: false }] }] } });
204
228
  //# sourceMappingURL=native-header.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"native-header.js","sourceRoot":"","sources":["../src/native-header.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The screen's navigation bar, as a component you write inside a page's template.\n *\n * Commits as `RNSScreenStackHeaderConfig`. It is a configuration node rather than a view: the\n * native side reads its props and builds a `UINavigationItem` from them, and the only children\n * that mean anything are `native-header-item`s. `findHeaderConfig` in `RNSScreen.mm` scans the\n * screen's direct `reactSubviews` without recursing, which is why a page's host element is the\n * screen itself (ADR 0004). It can still be written anywhere in the page, inside a `safe-area-view`\n * or a layout component: `registerScreenComponents` has the engine commit it as a direct child of\n * the screen, just after the part of the page it was written in (`registerHoist`). Keep the page's\n * scroll view ahead of it. UIKit then finds that scroll view and collapses a large title into the\n * inline title as the content scrolls.\n *\n * A header owns the top inset. A page that has one should not also wrap itself in a\n * `safe-area-view`, or the content clears the notch twice.\n *\n * **A presented screen has no header.** `RNSScreenStack.mm` presents a modal or a sheet with\n * `presentViewController:`, outside the stack's `UINavigationController`, so there is no\n * navigation bar for this to configure and nothing adjusting the screen's insets either. A page\n * opened with `present()` owns its own chrome: its title, its way out, and its `safe-area-view`.\n * react-navigation has the same shape, which is why a modal there needs a stack nested inside it\n * before it has a header.\n *\n * Props are the `RNSScreenStackHeaderConfig` codegen spec. `headerLeftBarButtonItems` and\n * `headerRightBarButtonItems` are deliberately absent: native bar button items are data rather\n * than views, and they are a later opt-in rather than the primary API.\n */\nimport { Component, computed, input } from '@angular/core';\nimport { ElementRef, inject } from '@angular/core';\nimport { ColorScheme } from '@ng-native/device';\nimport { NATIVE_HEADER_DEFAULTS } from './native-bar-defaults.ts';\nimport { NATIVE_HEADER_PALETTE } from './native-header-palette.ts';\nimport type { EngineNode } from '@ng-native/fabric';\nimport { ownHost } from './own-host.ts';\nimport { nativePlatform } from '@ng-native/fabric';\nimport { optionalBoolean, optionalNumber } from './transforms.ts';\n\n/** Where the back button's title comes from, on iOS 14+. */\nexport type BackButtonDisplayMode = 'minimal' | 'default' | 'generic';\n\n/** Direction the bar lays out in, for right-to-left languages. */\nexport type HeaderDirection = 'ltr' | 'rtl';\n\n/** How the bar blurs what scrolls under it. `none` paints `backgroundColor` instead. */\nexport type BlurEffect =\n | 'none'\n | 'extraLight'\n | 'light'\n | 'dark'\n | 'regular'\n | 'prominent'\n | 'systemUltraThinMaterial'\n | 'systemThinMaterial'\n | 'systemMaterial'\n | 'systemThickMaterial'\n | 'systemChromeMaterial'\n | 'systemUltraThinMaterialLight'\n | 'systemThinMaterialLight'\n | 'systemMaterialLight'\n | 'systemThickMaterialLight'\n | 'systemChromeMaterialLight'\n | 'systemUltraThinMaterialDark'\n | 'systemThinMaterialDark'\n | 'systemMaterialDark'\n | 'systemThickMaterialDark'\n | 'systemChromeMaterialDark';\n\n/** Overrides the bar's light/dark appearance independently of the app's. */\nexport type HeaderInterfaceStyle = 'unspecified' | 'light' | 'dark';\n\n@Component({\n selector: 'native-header',\n template: '<ng-content />',\n host: {\n '[title]': 'title()',\n '[titleColor]': 'resolvedTitleColor()',\n '[titleFontFamily]': 'titleFontFamily() ?? defaults().titleFontFamily',\n '[titleFontSize]': 'titleFontSize() ?? defaults().titleFontSize',\n '[titleFontWeight]': 'titleFontWeight() ?? defaults().titleFontWeight',\n '[backgroundColor]': 'resolvedBackgroundColor()',\n '[color]': 'resolvedColor()',\n '[blurEffect]': 'blurEffect() ?? defaults().blurEffect',\n '[hidden]': 'hidden()',\n '[hideShadow]': 'hideShadow() ?? defaults().hideShadow',\n '[translucent]': 'translucent() ?? defaults().translucent ?? iosLargeTitle()',\n '[direction]': 'direction()',\n '[topInsetEnabled]': 'topInsetEnabled()',\n '[userInterfaceStyle]': 'userInterfaceStyle() ?? defaults().userInterfaceStyle',\n '[largeTitle]': 'largeTitle()',\n '[largeTitleColor]': 'largeTitleColor() ?? defaults().largeTitleColor',\n '[largeTitleBackgroundColor]': 'resolvedLargeTitleBackgroundColor()',\n '[largeTitleFontFamily]': 'largeTitleFontFamily() ?? defaults().largeTitleFontFamily',\n '[largeTitleFontSize]': 'largeTitleFontSize() ?? defaults().largeTitleFontSize',\n '[largeTitleFontWeight]': 'largeTitleFontWeight() ?? defaults().largeTitleFontWeight',\n '[largeTitleHideShadow]':\n 'largeTitleHideShadow() ?? defaults().largeTitleHideShadow ?? iosLargeTitle()',\n '[backTitle]': 'backTitle()',\n '[backTitleFontFamily]': 'backTitleFontFamily() ?? defaults().backTitleFontFamily',\n '[backTitleFontSize]': 'backTitleFontSize() ?? defaults().backTitleFontSize',\n '[backTitleVisible]': 'backTitleVisible()',\n '[backButtonDisplayMode]': 'backButtonDisplayMode() ?? defaults().backButtonDisplayMode',\n '[backButtonInCustomView]': 'backButtonInCustomView()',\n '[disableBackButtonMenu]': 'disableBackButtonMenu()',\n '[hideBackButton]': 'hideBackButton()',\n '[consumeTopInset]': 'consumeTopInset()',\n '[consumeLeftInset]': 'consumeLeftInset()',\n '[consumeRightInset]': 'consumeRightInset()',\n '[consumeBottomInset]': 'consumeBottomInset()',\n },\n})\nexport class NativeHeader {\n private readonly scheme = inject(ColorScheme);\n private readonly palette = inject(NATIVE_HEADER_PALETTE);\n /** The app's `withHeaderDefaults`, for whatever this header does not bind itself. */\n protected readonly defaults = inject(NATIVE_HEADER_DEFAULTS);\n\n constructor() {\n ownHost(inject(ElementRef).nativeElement as EngineNode, this.constructor);\n }\n\n /**\n * The palette for the scheme the app is wearing, for whichever colours were not bound.\n *\n * A header prop cannot read the cascade, so left alone each platform chooses: iOS follows the\n * system appearance and looks about right, Android takes the app theme's `colorPrimary` and is\n * the framework blue on every screen. These fill the gap without overriding anything a call site\n * or `withHeaderDefaults` did say. See `native-header-palette.ts` for retuning them.\n */\n private readonly colours = computed(() => this.palette[this.scheme.current()]);\n\n protected readonly resolvedBackgroundColor = computed(\n () => this.backgroundColor() ?? this.defaults().backgroundColor ?? this.colours().background,\n );\n protected readonly resolvedColor = computed(\n () => this.color() ?? this.defaults().color ?? this.colours().foreground,\n );\n protected readonly resolvedTitleColor = computed(\n () => this.titleColor() ?? this.defaults().titleColor ?? this.colours().foreground,\n );\n\n /**\n * A large title on iOS, drawn as UIKit draws one unless the call site says otherwise: over the\n * content with the bar clear and unlined at the top, so the page's scroll view (with\n * `contentInsetAdjustmentBehavior=\"automatic\"`) collapses it into the bar as it scrolls. Since\n * iOS 26 the large title sits in the scroll view, above its content, where a bar with a\n * background paints over it; and over an opaque bar the inline title never fades in.\n */\n protected readonly iosLargeTitle = computed(() =>\n this.largeTitle() && nativePlatform() === 'ios' ? true : undefined,\n );\n protected readonly resolvedLargeTitleBackgroundColor = computed(\n () =>\n this.largeTitleBackgroundColor() ??\n this.defaults().largeTitleBackgroundColor ??\n (this.iosLargeTitle() ? 'transparent' : undefined),\n );\n\n // --- title ---------------------------------------------------------------------------\n\n /** The bar's title. Absent leaves whatever the platform would show, which is nothing. */\n readonly title = input<string>();\n /** Title colour. */\n readonly titleColor = input<string | number>();\n readonly titleFontFamily = input<string>();\n readonly titleFontSize = input(undefined, { transform: optionalNumber });\n /** A CSS font weight, `'600'` or `'bold'`. */\n readonly titleFontWeight = input<string>();\n\n // --- the bar itself ------------------------------------------------------------------\n\n /** The bar's background. Ignored unless `blurEffect` is `none`. */\n readonly backgroundColor = input<string | number>();\n /** Tint colour: the back chevron, and any header item that does not set its own. */\n readonly color = input<string | number>();\n /** iOS blur material behind the bar. */\n readonly blurEffect = input<BlurEffect>();\n /** Hide the bar entirely, keeping the screen's gestures and safe areas. */\n readonly hidden = input(undefined, { transform: optionalBoolean });\n /** Drop the hairline under the bar. */\n readonly hideShadow = input(undefined, { transform: optionalBoolean });\n /** Let content scroll under the bar rather than starting below it. */\n readonly translucent = input(undefined, { transform: optionalBoolean });\n /** Lay the bar out right to left. */\n readonly direction = input<HeaderDirection>();\n /** Android: add the status bar inset to the bar's height. */\n readonly topInsetEnabled = input(undefined, { transform: optionalBoolean });\n /** Force the bar light or dark regardless of the app's appearance. */\n readonly userInterfaceStyle = input<HeaderInterfaceStyle>();\n\n // --- large title (iOS) ---------------------------------------------------------------\n\n /** iOS large title, which collapses into the bar as content scrolls. */\n readonly largeTitle = input(undefined, { transform: optionalBoolean });\n readonly largeTitleColor = input<string | number>();\n readonly largeTitleBackgroundColor = input<string | number>();\n readonly largeTitleFontFamily = input<string>();\n readonly largeTitleFontSize = input(undefined, { transform: optionalNumber });\n readonly largeTitleFontWeight = input<string>();\n readonly largeTitleHideShadow = input(undefined, { transform: optionalBoolean });\n\n // --- the back button -----------------------------------------------------------------\n\n /**\n * What *this* screen's back button says. `RNSScreenStackHeaderConfig.mm` writes it onto the\n * previous screen's navigation item, falling back to that screen's title, which is why an\n * unset back title reads as the title of the screen you came from.\n */\n readonly backTitle = input<string>();\n readonly backTitleFontFamily = input<string>();\n readonly backTitleFontSize = input(undefined, { transform: optionalNumber });\n /** Show the back button's title at all. Native defaults this to true. */\n readonly backTitleVisible = input(undefined, { transform: optionalBoolean });\n /** iOS 14+: how aggressively the back title is shortened when space is tight. */\n readonly backButtonDisplayMode = input<BackButtonDisplayMode>();\n /** Put the back button in the custom view slot, so a `back` header item can replace it. */\n readonly backButtonInCustomView = input(undefined, { transform: optionalBoolean });\n /** Drop the long-press menu of the screens below. */\n readonly disableBackButtonMenu = input(undefined, { transform: optionalBoolean });\n /** Hide the back button without disabling the swipe-back gesture. */\n readonly hideBackButton = input(undefined, { transform: optionalBoolean });\n\n // --- insets (experimental in react-native-screens) -------------------------------------\n\n /**\n * Android: whether the bar takes the status bar's height as padding, so its title sits below\n * it rather than under it.\n *\n * Defaulted per platform because getting it wrong is invisible in a screenshot until you look\n * for it: react-native-screens leaves it false, Android 15 draws every app edge to edge, and\n * the result is a title behind the clock. iOS has a navigation controller doing this itself.\n */\n readonly consumeTopInset = input(nativePlatform() === 'android', {\n transform: optionalBoolean,\n });\n readonly consumeLeftInset = input(undefined, { transform: optionalBoolean });\n readonly consumeRightInset = input(undefined, { transform: optionalBoolean });\n readonly consumeBottomInset = input(undefined, { transform: optionalBoolean });\n}\n"]}
1
+ {"version":3,"file":"native-header.js","sourceRoot":"","sources":["../src/native-header.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The screen's navigation bar, as a component you write inside a page's template.\n *\n * Commits as `RNSScreenStackHeaderConfig`. It is a configuration node rather than a view: the\n * native side reads its props and builds a `UINavigationItem` from them, and the only children\n * that mean anything are `native-header-item`s. `findHeaderConfig` in `RNSScreen.mm` scans the\n * screen's direct `reactSubviews` without recursing, which is why a page's host element is the\n * screen itself (ADR 0004). It can still be written anywhere in the page, inside a `safe-area-view`\n * or a layout component: `registerScreenComponents` has the engine commit it as a direct child of\n * the screen, just after the part of the page it was written in (`registerHoist`). Keep the page's\n * scroll view ahead of it. UIKit then finds that scroll view and collapses a large title into the\n * inline title as the content scrolls.\n *\n * A header owns the top inset. A page that has one should not also wrap itself in a\n * `safe-area-view`, or the content clears the notch twice.\n *\n * **A presented screen has no header.** `RNSScreenStack.mm` presents a modal or a sheet with\n * `presentViewController:`, outside the stack's `UINavigationController`, so there is no\n * navigation bar for this to configure and nothing adjusting the screen's insets either. A page\n * opened with `present()` owns its own chrome: its title, its way out, and its `safe-area-view`.\n * react-navigation has the same shape, which is why a modal there needs a stack nested inside it\n * before it has a header.\n *\n * Props are the `RNSScreenStackHeaderConfig` codegen spec. `headerLeftBarButtonItems` and\n * `headerRightBarButtonItems` are deliberately absent: native bar button items are data rather\n * than views, and they are a later opt-in rather than the primary API.\n */\nimport { Component, computed, input } from '@angular/core';\nimport { ElementRef, inject } from '@angular/core';\nimport { ColorScheme, OS_VERSION } from '@ng-native/device';\nimport { NATIVE_HEADER_DEFAULTS } from './native-bar-defaults.ts';\nimport { NATIVE_HEADER_PALETTE } from './native-header-palette.ts';\nimport type { EngineNode } from '@ng-native/fabric';\nimport { ownHost } from './own-host.ts';\nimport { nativePlatform } from '@ng-native/fabric';\nimport { optionalBoolean, optionalNumber } from './transforms.ts';\n\n/** Where the back button's title comes from, on iOS 14+. */\nexport type BackButtonDisplayMode = 'minimal' | 'default' | 'generic';\n\n/** Direction the bar lays out in, for right-to-left languages. */\nexport type HeaderDirection = 'ltr' | 'rtl';\n\n/** How the bar blurs what scrolls under it. `none` paints `backgroundColor` instead. */\nexport type BlurEffect =\n | 'none'\n | 'extraLight'\n | 'light'\n | 'dark'\n | 'regular'\n | 'prominent'\n | 'systemUltraThinMaterial'\n | 'systemThinMaterial'\n | 'systemMaterial'\n | 'systemThickMaterial'\n | 'systemChromeMaterial'\n | 'systemUltraThinMaterialLight'\n | 'systemThinMaterialLight'\n | 'systemMaterialLight'\n | 'systemThickMaterialLight'\n | 'systemChromeMaterialLight'\n | 'systemUltraThinMaterialDark'\n | 'systemThinMaterialDark'\n | 'systemMaterialDark'\n | 'systemThickMaterialDark'\n | 'systemChromeMaterialDark';\n\n/** Overrides the bar's light/dark appearance independently of the app's. */\nexport type HeaderInterfaceStyle = 'unspecified' | 'light' | 'dark';\n\n@Component({\n selector: 'native-header',\n template: '<ng-content />',\n host: {\n '[title]': 'title()',\n '[titleColor]': 'resolvedTitleColor()',\n '[titleFontFamily]': 'titleFontFamily() ?? defaults().titleFontFamily',\n '[titleFontSize]': 'titleFontSize() ?? defaults().titleFontSize',\n '[titleFontWeight]': 'titleFontWeight() ?? defaults().titleFontWeight',\n '[backgroundColor]': 'resolvedBackgroundColor()',\n '[color]': 'resolvedColor()',\n '[blurEffect]': 'blurEffect() ?? defaults().blurEffect',\n '[hidden]': 'hidden()',\n '[hideShadow]': 'hideShadow() ?? defaults().hideShadow ?? isLiquidGlass()',\n '[translucent]':\n 'translucent() ?? defaults().translucent ?? iosLargeTitle() ?? isLiquidGlass()',\n '[direction]': 'direction()',\n '[topInsetEnabled]': 'topInsetEnabled()',\n '[userInterfaceStyle]': 'userInterfaceStyle() ?? defaults().userInterfaceStyle',\n '[largeTitle]': 'largeTitle()',\n '[largeTitleColor]': 'largeTitleColor() ?? defaults().largeTitleColor',\n '[largeTitleBackgroundColor]': 'resolvedLargeTitleBackgroundColor()',\n '[largeTitleFontFamily]': 'largeTitleFontFamily() ?? defaults().largeTitleFontFamily',\n '[largeTitleFontSize]': 'largeTitleFontSize() ?? defaults().largeTitleFontSize',\n '[largeTitleFontWeight]': 'largeTitleFontWeight() ?? defaults().largeTitleFontWeight',\n '[largeTitleHideShadow]':\n 'largeTitleHideShadow() ?? defaults().largeTitleHideShadow ?? iosLargeTitle()',\n '[backTitle]': 'backTitle()',\n '[backTitleFontFamily]': 'backTitleFontFamily() ?? defaults().backTitleFontFamily',\n '[backTitleFontSize]': 'backTitleFontSize() ?? defaults().backTitleFontSize',\n '[backTitleVisible]': 'backTitleVisible()',\n '[backButtonDisplayMode]': 'backButtonDisplayMode() ?? defaults().backButtonDisplayMode',\n '[backButtonInCustomView]': 'backButtonInCustomView()',\n '[disableBackButtonMenu]': 'disableBackButtonMenu()',\n '[hideBackButton]': 'hideBackButton()',\n '[consumeTopInset]': 'consumeTopInset()',\n '[consumeLeftInset]': 'consumeLeftInset()',\n '[consumeRightInset]': 'consumeRightInset()',\n '[consumeBottomInset]': 'consumeBottomInset()',\n },\n})\nexport class NativeHeader {\n private readonly scheme = inject(ColorScheme);\n private readonly palette = inject(NATIVE_HEADER_PALETTE);\n /** The app's `withHeaderDefaults`, for whatever this header does not bind itself. */\n protected readonly defaults = inject(NATIVE_HEADER_DEFAULTS);\n\n constructor() {\n ownHost(inject(ElementRef).nativeElement as EngineNode, this.constructor);\n }\n\n /**\n * The palette for the scheme the app is wearing, for whichever colours were not bound.\n *\n * A header prop cannot read the cascade, so left alone each platform chooses: iOS follows the\n * system appearance and looks about right, Android takes the app theme's `colorPrimary` and is\n * the framework blue on every screen. These fill the gap without overriding anything a call site\n * or `withHeaderDefaults` did say. See `native-header-palette.ts` for retuning them.\n */\n private readonly colours = computed(() => this.palette[this.scheme.current()]);\n\n /** iOS 26 and later, where the system's own bar is clear and floats over the content. */\n private readonly glass = nativePlatform() === 'ios' && (inject(OS_VERSION) ?? 0) >= 26;\n\n /**\n * Whether the bar is iOS 26's Liquid Glass one, which `liquidGlass` asks for here or through\n * `withHeaderDefaults`: clear, over the content, with no line under it, where the system blurs\n * what scrolls beneath and floats the buttons. Only on iOS 26 and later, and only while nothing\n * gave the bar a background of its own.\n */\n protected readonly isLiquidGlass = computed(() =>\n this.glass &&\n (this.liquidGlass() ?? this.defaults().liquidGlass) &&\n this.backgroundColor() === undefined &&\n this.defaults().backgroundColor === undefined\n ? true\n : undefined,\n );\n\n protected readonly resolvedBackgroundColor = computed(\n () =>\n this.backgroundColor() ??\n this.defaults().backgroundColor ??\n (this.isLiquidGlass() ? 'transparent' : this.colours().background),\n );\n protected readonly resolvedColor = computed(\n () => this.color() ?? this.defaults().color ?? this.colours().foreground,\n );\n protected readonly resolvedTitleColor = computed(\n () => this.titleColor() ?? this.defaults().titleColor ?? this.colours().foreground,\n );\n\n /**\n * A large title on iOS, drawn as UIKit draws one unless the call site says otherwise: over the\n * content with the bar clear and unlined at the top, so the page's scroll view (with\n * `contentInsetAdjustmentBehavior=\"automatic\"`) collapses it into the bar as it scrolls. Since\n * iOS 26 the large title sits in the scroll view, above its content, where a bar with a\n * background paints over it; and over an opaque bar the inline title never fades in.\n */\n protected readonly iosLargeTitle = computed(() =>\n this.largeTitle() && nativePlatform() === 'ios' ? true : undefined,\n );\n protected readonly resolvedLargeTitleBackgroundColor = computed(\n () =>\n this.largeTitleBackgroundColor() ??\n this.defaults().largeTitleBackgroundColor ??\n (this.iosLargeTitle() ? 'transparent' : undefined),\n );\n\n // --- title ---------------------------------------------------------------------------\n\n /** The bar's title. Absent leaves whatever the platform would show, which is nothing. */\n readonly title = input<string>();\n /** Title colour. */\n readonly titleColor = input<string | number>();\n readonly titleFontFamily = input<string>();\n readonly titleFontSize = input(undefined, { transform: optionalNumber });\n /** A CSS font weight, `'600'` or `'bold'`. */\n readonly titleFontWeight = input<string>();\n\n // --- the bar itself ------------------------------------------------------------------\n\n /**\n * On iOS 26 and later, the Liquid Glass navigation bar for this header, where it has no\n * background of its own: clear and unlined, with the content scrolling under it. `false` keeps\n * the neutral bar on a page of an app whose `withHeaderDefaults` asks for the glass one. The\n * bar is over the page, so its scroll view takes `contentInsetAdjustmentBehavior=\"automatic\"`.\n */\n readonly liquidGlass = input(undefined, { transform: optionalBoolean });\n /** The bar's background. Ignored unless `blurEffect` is `none`. */\n readonly backgroundColor = input<string | number>();\n /** Tint colour: the back chevron, and any header item that does not set its own. */\n readonly color = input<string | number>();\n /** iOS blur material behind the bar. */\n readonly blurEffect = input<BlurEffect>();\n /** Hide the bar entirely, keeping the screen's gestures and safe areas. */\n readonly hidden = input(undefined, { transform: optionalBoolean });\n /** Drop the hairline under the bar. */\n readonly hideShadow = input(undefined, { transform: optionalBoolean });\n /** Let content scroll under the bar rather than starting below it. */\n readonly translucent = input(undefined, { transform: optionalBoolean });\n /** Lay the bar out right to left. */\n readonly direction = input<HeaderDirection>();\n /** Android: add the status bar inset to the bar's height. */\n readonly topInsetEnabled = input(undefined, { transform: optionalBoolean });\n /** Force the bar light or dark regardless of the app's appearance. */\n readonly userInterfaceStyle = input<HeaderInterfaceStyle>();\n\n // --- large title (iOS) ---------------------------------------------------------------\n\n /** iOS large title, which collapses into the bar as content scrolls. */\n readonly largeTitle = input(undefined, { transform: optionalBoolean });\n readonly largeTitleColor = input<string | number>();\n readonly largeTitleBackgroundColor = input<string | number>();\n readonly largeTitleFontFamily = input<string>();\n readonly largeTitleFontSize = input(undefined, { transform: optionalNumber });\n readonly largeTitleFontWeight = input<string>();\n readonly largeTitleHideShadow = input(undefined, { transform: optionalBoolean });\n\n // --- the back button -----------------------------------------------------------------\n\n /**\n * What *this* screen's back button says. `RNSScreenStackHeaderConfig.mm` writes it onto the\n * previous screen's navigation item, falling back to that screen's title, which is why an\n * unset back title reads as the title of the screen you came from.\n */\n readonly backTitle = input<string>();\n readonly backTitleFontFamily = input<string>();\n readonly backTitleFontSize = input(undefined, { transform: optionalNumber });\n /** Show the back button's title at all. Native defaults this to true. */\n readonly backTitleVisible = input(undefined, { transform: optionalBoolean });\n /** iOS 14+: how aggressively the back title is shortened when space is tight. */\n readonly backButtonDisplayMode = input<BackButtonDisplayMode>();\n /** Put the back button in the custom view slot, so a `back` header item can replace it. */\n readonly backButtonInCustomView = input(undefined, { transform: optionalBoolean });\n /** Drop the long-press menu of the screens below. */\n readonly disableBackButtonMenu = input(undefined, { transform: optionalBoolean });\n /** Hide the back button without disabling the swipe-back gesture. */\n readonly hideBackButton = input(undefined, { transform: optionalBoolean });\n\n // --- insets (experimental in react-native-screens) -------------------------------------\n\n /**\n * Android: whether the bar takes the status bar's height as padding, so its title sits below\n * it rather than under it.\n *\n * Defaulted per platform because getting it wrong is invisible in a screenshot until you look\n * for it: react-native-screens leaves it false, Android 15 draws every app edge to edge, and\n * the result is a title behind the clock. iOS has a navigation controller doing this itself.\n */\n readonly consumeTopInset = input(nativePlatform() === 'android', {\n transform: optionalBoolean,\n });\n readonly consumeLeftInset = input(undefined, { transform: optionalBoolean });\n readonly consumeRightInset = input(undefined, { transform: optionalBoolean });\n readonly consumeBottomInset = input(undefined, { transform: optionalBoolean });\n}\n"]}
@@ -60,6 +60,8 @@ export declare class NativeNavigation {
60
60
  * another tab is that tab. At the root of the app there is nowhere to go, and this does nothing.
61
61
  */
62
62
  back(): void;
63
+ /** The wait of a back asked for mid-navigation, so two asked for in one are one. */
64
+ private backWaiting;
63
65
  /**
64
66
  * Pop straight back to the screen at `commands`, taking every screen above it off the stack at
65
67
  * once - `popToViewController`. The screen is the one already there, with its state, not a new
@@ -73,6 +75,23 @@ export declare class NativeNavigation {
73
75
  */
74
76
  popToRoot(): Promise<boolean>;
75
77
  private go;
78
+ /**
79
+ * A push into a tab nobody has opened goes to the tab first, so its stack has the tab's own
80
+ * first screen under the page, and a back from the page lands there: what a tab bar with a
81
+ * navigation controller per tab does. Without it the page is the stack's only screen, and the
82
+ * same push leaves a different stack behind depending on whether the tab was ever tapped. A
83
+ * presented screen goes where it is asked, and a replace or a reset has nothing to keep.
84
+ */
85
+ private underTabRoot;
86
+ /** The path the commands lead to, without its query and fragment. */
87
+ private pathFor;
88
+ /**
89
+ * A page of a tab that is not in front, presented over the one that is: its url would select
90
+ * its own tab and show it there, so it goes to the root's presented outlet instead, where the
91
+ * app's own stack shows it over everything. See `presented-route.ts`. Null for a page of the
92
+ * tab in front, or of no tab, which is presented where its url puts it.
93
+ */
94
+ private overTheTabInFront;
76
95
  /**
77
96
  * The query and fragment written into a url string, as the extras `navigate` takes them: it
78
97
  * reads a string command as one path segment, and would encode a `?` into it. Extras given