@symbiote-native/angular 3.3.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/babel-register-composed.cjs +1 -0
  2. package/build/angular/accessibility-inputs.d.ts +2 -1
  3. package/build/angular/accessibility-inputs.js +4 -1
  4. package/build/angular/accessibility-inputs.js.map +1 -1
  5. package/build/angular/callback-host.d.ts +1 -1
  6. package/build/angular/callback-host.js +57 -9
  7. package/build/angular/callback-host.js.map +1 -1
  8. package/build/angular/components/flat-list/flat-list-handle.d.ts +35 -0
  9. package/build/angular/components/flat-list/flat-list-handle.js +48 -0
  10. package/build/angular/components/flat-list/flat-list-handle.js.map +1 -0
  11. package/build/angular/components/flat-list/flat-list-template.d.ts +1 -1
  12. package/build/angular/components/flat-list/flat-list-template.js +16 -0
  13. package/build/angular/components/flat-list/flat-list-template.js.map +1 -1
  14. package/build/angular/components/flat-list/index.d.ts +6 -30
  15. package/build/angular/components/flat-list/index.js +6 -36
  16. package/build/angular/components/flat-list/index.js.map +1 -1
  17. package/build/angular/components/image-inputs.d.ts +4 -0
  18. package/build/angular/components/image-inputs.js +81 -0
  19. package/build/angular/components/image-inputs.js.map +1 -0
  20. package/build/angular/components/image-props-resolve.d.ts +3 -0
  21. package/build/angular/components/image-props-resolve.js +133 -0
  22. package/build/angular/components/image-props-resolve.js.map +1 -0
  23. package/build/angular/components/image-shared.d.ts +8 -6
  24. package/build/angular/components/image-shared.js +23 -212
  25. package/build/angular/components/image-shared.js.map +1 -1
  26. package/build/angular/components/input-accessory-view-props.d.ts +4 -4
  27. package/build/angular/components/keyboard-avoiding-view/index.d.ts +3 -6
  28. package/build/angular/components/keyboard-avoiding-view/index.js +29 -56
  29. package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -1
  30. package/build/angular/components/layout-conformance-props.d.ts +4 -0
  31. package/build/angular/components/layout-conformance-props.js +2 -0
  32. package/build/angular/components/layout-conformance-props.js.map +1 -0
  33. package/build/angular/components/modal/index.d.ts +6 -5
  34. package/build/angular/components/modal/index.js +17 -2
  35. package/build/angular/components/modal/index.js.map +1 -1
  36. package/build/angular/components/refresh-control-props.d.ts +7 -7
  37. package/build/angular/components/scroll-view-props.d.ts +8 -5
  38. package/build/angular/components/section-list/index.d.ts +17 -8
  39. package/build/angular/components/section-list/index.js +37 -28
  40. package/build/angular/components/section-list/index.js.map +1 -1
  41. package/build/angular/components/touchable-props.d.ts +2 -2
  42. package/build/angular/components/virtualized-list/cell-renderer-context.d.ts +12 -0
  43. package/build/angular/components/virtualized-list/cell-renderer-context.js +16 -0
  44. package/build/angular/components/virtualized-list/cell-renderer-context.js.map +1 -0
  45. package/build/angular/components/virtualized-list/directives.d.ts +26 -6
  46. package/build/angular/components/virtualized-list/directives.js +59 -5
  47. package/build/angular/components/virtualized-list/directives.js.map +1 -1
  48. package/build/angular/components/virtualized-list/index.d.ts +19 -15
  49. package/build/angular/components/virtualized-list/index.js +91 -61
  50. package/build/angular/components/virtualized-list/index.js.map +1 -1
  51. package/build/angular/components/virtualized-list/list-bags.d.ts +5 -1
  52. package/build/angular/components/virtualized-list/list-bags.js +31 -19
  53. package/build/angular/components/virtualized-list/list-bags.js.map +1 -1
  54. package/build/angular/components/virtualized-list/list-effects.d.ts +2 -2
  55. package/build/angular/components/virtualized-list/list-effects.js +17 -27
  56. package/build/angular/components/virtualized-list/list-effects.js.map +1 -1
  57. package/build/angular/components/virtualized-list/list-handle.d.ts +4 -1
  58. package/build/angular/components/virtualized-list/list-handle.js +13 -3
  59. package/build/angular/components/virtualized-list/list-handle.js.map +1 -1
  60. package/build/angular/components/virtualized-list/list-inputs.d.ts +19 -5
  61. package/build/angular/components/virtualized-list/list-inputs.js +47 -4
  62. package/build/angular/components/virtualized-list/list-inputs.js.map +1 -1
  63. package/build/angular/components/virtualized-list/list-props.d.ts +9 -3
  64. package/build/angular/components/virtualized-list/list-rows.d.ts +25 -0
  65. package/build/angular/components/virtualized-list/list-rows.js +25 -0
  66. package/build/angular/components/virtualized-list/list-rows.js.map +1 -0
  67. package/build/angular/components/virtualized-list/list-styles.d.ts +4 -0
  68. package/build/angular/components/virtualized-list/list-styles.js +10 -2
  69. package/build/angular/components/virtualized-list/list-styles.js.map +1 -1
  70. package/build/angular/components/virtualized-list/list-template.d.ts +1 -1
  71. package/build/angular/components/virtualized-list/list-template.js +159 -73
  72. package/build/angular/components/virtualized-list/list-template.js.map +1 -1
  73. package/build/angular/components/virtualized-list/nested-scope.d.ts +6 -0
  74. package/build/angular/components/virtualized-list/nested-scope.js +17 -0
  75. package/build/angular/components/virtualized-list/nested-scope.js.map +1 -0
  76. package/build/angular/components/virtualized-section-list/directives.d.ts +21 -9
  77. package/build/angular/components/virtualized-section-list/directives.js +8 -28
  78. package/build/angular/components/virtualized-section-list/directives.js.map +1 -1
  79. package/build/angular/components/virtualized-section-list/index.d.ts +39 -60
  80. package/build/angular/components/virtualized-section-list/index.js +67 -33
  81. package/build/angular/components/virtualized-section-list/index.js.map +1 -1
  82. package/build/angular/components/virtualized-section-list/section-cell.d.ts +29 -0
  83. package/build/angular/components/virtualized-section-list/section-cell.js +82 -0
  84. package/build/angular/components/virtualized-section-list/section-cell.js.map +1 -0
  85. package/build/angular/components/virtualized-section-list/section-list-props.d.ts +56 -0
  86. package/build/angular/components/virtualized-section-list/section-list-props.js +3 -0
  87. package/build/angular/components/virtualized-section-list/section-list-props.js.map +1 -0
  88. package/build/angular/components/virtualized-section-list/section-list-template.d.ts +1 -1
  89. package/build/angular/components/virtualized-section-list/section-list-template.js +34 -26
  90. package/build/angular/components/virtualized-section-list/section-list-template.js.map +1 -1
  91. package/build/angular/components.d.ts +7 -3
  92. package/build/angular/components.js +2 -1
  93. package/build/angular/components.js.map +1 -1
  94. package/build/angular/element-base.d.ts +17 -1
  95. package/build/angular/element-base.js +33 -1
  96. package/build/angular/element-base.js.map +1 -1
  97. package/build/angular/element-props.d.ts +7 -7
  98. package/build/angular/element-text-input-native.d.ts +27 -0
  99. package/build/angular/element-text-input-native.js +52 -0
  100. package/build/angular/element-text-input-native.js.map +1 -0
  101. package/build/angular/elements-controls.d.ts +8 -2
  102. package/build/angular/elements-controls.js +13 -1
  103. package/build/angular/elements-controls.js.map +1 -1
  104. package/build/angular/elements-layout.d.ts +20 -3
  105. package/build/angular/elements-layout.js +37 -3
  106. package/build/angular/elements-layout.js.map +1 -1
  107. package/build/angular/elements-press.d.ts +10 -3
  108. package/build/angular/elements-press.js +13 -1
  109. package/build/angular/elements-press.js.map +1 -1
  110. package/build/angular/elements.d.ts +3 -3
  111. package/build/angular/elements.js +3 -2
  112. package/build/angular/elements.js.map +1 -1
  113. package/build/angular/index.d.ts +15 -7
  114. package/build/angular/index.js +22 -25
  115. package/build/angular/index.js.map +1 -1
  116. package/build/angular/modules/animated/create-animated-component.d.ts +1 -1
  117. package/build/angular/modules/animated/create-animated-component.js +1 -1
  118. package/build/angular/modules/animated/create-animated-component.js.map +1 -1
  119. package/build/angular/modules/animated/index.d.ts +54 -41
  120. package/build/angular/modules/animated/index.js +2 -26
  121. package/build/angular/modules/animated/index.js.map +1 -1
  122. package/build/angular/modules/app-registry/index.d.ts +3 -3
  123. package/build/angular/modules/app-registry/index.js +2 -2
  124. package/build/angular/modules/app-registry/index.js.map +1 -1
  125. package/build/angular/modules/status-bar/index.d.ts +9 -5
  126. package/build/angular/modules/status-bar/index.js +21 -10
  127. package/build/angular/modules/status-bar/index.js.map +1 -1
  128. package/build/angular/primitives/index.d.ts +4 -0
  129. package/build/angular/primitives/index.js +12 -0
  130. package/build/angular/primitives/index.js.map +1 -1
  131. package/build/angular/render/index.d.ts +2 -2
  132. package/build/angular/render/index.js +10 -29
  133. package/build/angular/render/index.js.map +1 -1
  134. package/build/angular/root-tag.d.ts +4 -0
  135. package/build/angular/root-tag.js +10 -0
  136. package/build/angular/root-tag.js.map +1 -0
  137. package/build/angular/services/color-scheme.service.d.ts +1 -1
  138. package/package.json +6 -6
  139. package/src/accessibility-inputs.ts +3 -0
  140. package/src/callback-host.ts +56 -8
  141. package/src/components/flat-list/flat-list-handle.ts +64 -0
  142. package/src/components/flat-list/flat-list-template.ts +16 -0
  143. package/src/components/flat-list/index.ts +6 -48
  144. package/src/components/image-inputs.ts +94 -0
  145. package/src/components/image-props-resolve.ts +172 -0
  146. package/src/components/image-shared.ts +26 -291
  147. package/src/components/input-accessory-view-props.ts +12 -8
  148. package/src/components/keyboard-avoiding-view/index.ts +39 -79
  149. package/src/components/layout-conformance-props.ts +8 -0
  150. package/src/components/modal/index.ts +42 -20
  151. package/src/components/refresh-control-props.ts +29 -25
  152. package/src/components/scroll-view-props.ts +84 -76
  153. package/src/components/section-list/index.ts +34 -37
  154. package/src/components/touchable-props.ts +6 -2
  155. package/src/components/virtualized-list/cell-renderer-context.ts +36 -0
  156. package/src/components/virtualized-list/directives.ts +84 -8
  157. package/src/components/virtualized-list/index.ts +118 -85
  158. package/src/components/virtualized-list/list-bags.ts +38 -19
  159. package/src/components/virtualized-list/list-effects.ts +20 -32
  160. package/src/components/virtualized-list/list-handle.ts +17 -4
  161. package/src/components/virtualized-list/list-inputs.ts +47 -0
  162. package/src/components/virtualized-list/list-props.ts +57 -50
  163. package/src/components/virtualized-list/list-rows.ts +66 -0
  164. package/src/components/virtualized-list/list-styles.ts +30 -1
  165. package/src/components/virtualized-list/list-template.ts +159 -73
  166. package/src/components/virtualized-list/nested-scope.ts +22 -0
  167. package/src/components/virtualized-section-list/directives.ts +41 -40
  168. package/src/components/virtualized-section-list/index.ts +114 -118
  169. package/src/components/virtualized-section-list/section-cell.ts +109 -0
  170. package/src/components/virtualized-section-list/section-list-props.ts +79 -0
  171. package/src/components/virtualized-section-list/section-list-template.ts +34 -26
  172. package/src/components.ts +8 -0
  173. package/src/element-base.ts +17 -0
  174. package/src/element-props.ts +35 -33
  175. package/src/element-text-input-native.ts +31 -0
  176. package/src/elements-controls.ts +9 -1
  177. package/src/elements-layout.ts +27 -0
  178. package/src/elements-press.ts +10 -2
  179. package/src/elements.ts +3 -0
  180. package/src/index.ts +79 -22
  181. package/src/modules/animated/index.ts +2 -47
  182. package/src/modules/app-registry/index.ts +3 -1
  183. package/src/modules/status-bar/index.ts +24 -11
  184. package/src/primitives/index.ts +7 -0
  185. package/src/render/index.ts +23 -50
  186. package/src/root-tag.ts +14 -0
  187. package/src/services/color-scheme.service.ts +1 -1
@@ -6,29 +6,9 @@
6
6
  // `Animated.timing(new Animated.Value(0), …).start()`, works against the Angular-driven engine.
7
7
 
8
8
  import {
9
- AnimatedValue,
10
- AnimatedValueXY,
11
- AnimatedColor,
9
+ AnimatedDrivers,
12
10
  AnimatedMock,
13
- Easing,
14
11
  Platform,
15
- timing,
16
- spring,
17
- decay,
18
- parallel,
19
- sequence,
20
- stagger,
21
- loop,
22
- delay,
23
- add,
24
- subtract,
25
- multiply,
26
- divide,
27
- modulo,
28
- diffClamp,
29
- event,
30
- forkEvent,
31
- unforkEvent,
32
12
  } from '@symbiote-native/engine';
33
13
  import {
34
14
  AnimatedFlatList,
@@ -61,37 +41,12 @@ export {
61
41
  // components exist. Angular still cannot synthesize arbitrary animated wrappers at runtime; custom
62
42
  // animated components remain explicit standalone components over AnimatedComponentBase.
63
43
 
64
- // The live, JS-driven driver namespace (real frames). RN's AnimatedImplementation.
65
- const liveDrivers = {
66
- Value: AnimatedValue,
67
- ValueXY: AnimatedValueXY,
68
- Color: AnimatedColor,
69
- Easing,
70
- timing,
71
- spring,
72
- decay,
73
- parallel,
74
- sequence,
75
- stagger,
76
- loop,
77
- delay,
78
- add,
79
- subtract,
80
- multiply,
81
- divide,
82
- modulo,
83
- diffClamp,
84
- event,
85
- forkEvent,
86
- unforkEvent,
87
- };
88
-
89
44
  // RN swaps the WHOLE driver namespace for the mock when the host reports isDisableAnimations
90
45
  // (reduced motion / test env): the mock keeps the same surface but jumps each animation to its
91
46
  // final value synchronously, no frames. The animated COMPONENTS are live in both branches; only
92
47
  // the drivers/value/operators/events half is swapped, exactly like RN spreading `...Animated`
93
48
  // (impl or mock) over the same components.
94
- const drivers = Platform.isDisableAnimations ? AnimatedMock : liveDrivers;
49
+ const drivers = Platform.isDisableAnimations ? AnimatedMock : AnimatedDrivers;
95
50
 
96
51
  export const Animated = {
97
52
  View: AnimatedView,
@@ -10,6 +10,7 @@ import type { Type } from '@angular/core';
10
10
  import {
11
11
  createAppRegistry,
12
12
  dlog,
13
+ HeadlessJsTaskError,
13
14
  type IAppParameters,
14
15
  type IRunnable,
15
16
  } from '@symbiote-native/engine';
@@ -47,8 +48,9 @@ const { AppRegistry, setHostRegistrar } = createAppRegistry<
47
48
  IWrapperComponentProvider
48
49
  >(runnableFor);
49
50
 
50
- export { AppRegistry, setHostRegistrar };
51
+ export { AppRegistry, HeadlessJsTaskError, setHostRegistrar };
51
52
  export type {
53
+ IAppConfig,
52
54
  IAppParameters,
53
55
  IRunnable,
54
56
  IHostRegistrar,
@@ -1,21 +1,20 @@
1
- // StatusBar, the Angular lifecycle half. The native StatusBarManager driving, the imperative
2
- // statics, and the Android bar-height constant all live in @symbiote-native/engine, shared verbatim with
3
- // React and Vue; Metro selects the engine's platform variant. Angular supplies only the
4
- // declarative shape: a component that renders nothing and re-applies the props through
5
- // ngOnChanges on mount + every prop change. Imperative statics are attached to the component
6
- // object the same way RN does.
1
+ // Angular half of StatusBar, the props stack, statics and Android bar-height constant live in
2
+ // @symbiote-native/engine. It renders nothing, keeps one stack entry through `ngOnChanges` and
3
+ // releases it in `ngOnDestroy`
7
4
 
8
5
  import {
9
6
  Component,
10
7
  Input,
11
8
  type OnChanges,
12
- type SimpleChanges,
9
+ type OnDestroy,
10
+ type OnInit,
13
11
  } from '@angular/core';
14
12
  import {
15
- applyStatusBarProps,
13
+ createStatusBarEntry,
16
14
  statusBarImperative,
17
15
  statusBarCurrentHeight,
18
16
  type IColorValue,
17
+ type IStatusBarAnimation,
19
18
  type IStatusBarProps,
20
19
  type IStatusBarStyle,
21
20
  } from '@symbiote-native/engine';
@@ -27,16 +26,29 @@ export type { IStatusBarProps, IStatusBarStyle } from '@symbiote-native/engine';
27
26
  standalone: true,
28
27
  template: '',
29
28
  })
30
- class StatusBarComponent implements OnChanges {
29
+ class StatusBarComponent implements OnInit, OnChanges, OnDestroy {
31
30
  @Input() barStyle?: IStatusBarStyle;
32
31
  @Input() hidden?: boolean;
33
32
  @Input() animated?: boolean;
33
+ @Input() showHideTransition?: IStatusBarAnimation;
34
34
  @Input() networkActivityIndicatorVisible?: boolean;
35
35
  @Input() backgroundColor?: IColorValue;
36
36
  @Input() translucent?: boolean;
37
37
 
38
- ngOnChanges(_changes: SimpleChanges): void {
39
- applyStatusBarProps(this.buildProps());
38
+ private readonly entry = createStatusBarEntry();
39
+
40
+ // `ngOnChanges` never runs without bound inputs, the bar still takes its place in the stack
41
+ ngOnInit(): void {
42
+ this.entry.apply(this.buildProps());
43
+ }
44
+
45
+ ngOnChanges(): void {
46
+ this.entry.apply(this.buildProps());
47
+ }
48
+
49
+ // Popping restores what the stack held below this entry
50
+ ngOnDestroy(): void {
51
+ this.entry.release();
40
52
  }
41
53
 
42
54
  private buildProps(): IStatusBarProps {
@@ -44,6 +56,7 @@ class StatusBarComponent implements OnChanges {
44
56
  barStyle: this.barStyle,
45
57
  hidden: this.hidden,
46
58
  animated: this.animated,
59
+ showHideTransition: this.showHideTransition,
47
60
  networkActivityIndicatorVisible: this.networkActivityIndicatorVisible,
48
61
  backgroundColor: this.backgroundColor,
49
62
  translucent: this.translucent,
@@ -103,6 +103,13 @@ export class ActivityIndicatorHost extends SymbiotePrimitiveHost {}
103
103
  })
104
104
  export class SafeAreaViewHost extends SymbiotePrimitiveHost {}
105
105
 
106
+ @Component({
107
+ selector: 'layout-conformance',
108
+ standalone: true,
109
+ template: '<ng-content></ng-content>',
110
+ })
111
+ export class LayoutConformanceHost extends SymbiotePrimitiveHost {}
112
+
106
113
  @Component({
107
114
  selector: 'modal',
108
115
  standalone: true,
@@ -34,6 +34,7 @@ import {
34
34
  type Type,
35
35
  } from '@angular/core';
36
36
  import { SymbioteRendererFactory } from '../renderer';
37
+ import { ROOT_TAG } from '../root-tag';
37
38
  import { ColorSchemeService, WindowDimensionsService } from '../services';
38
39
 
39
40
  // The two FFI-edge casts of this adapter, both confined here to bootstrap. Angular's core
@@ -57,13 +58,9 @@ function asAngularHost(hostNode: SymbioteSurface | ISymbioteNode): Element {
57
58
  return hostNode as unknown as Element;
58
59
  }
59
60
 
60
- // A bare `view` node, created directly through the engine (bypassing Angular's own
61
- // createElement, which only resolves KNOWN symbiote primitives, never an arbitrary component's
62
- // selector — see SymbioteRenderer.createElement). Used as the AppRegistry root's host when a
63
- // wrapperComponentProvider is set: Angular has no hostElement-less bootstrap for our renderer
64
- // (it would try `renderer.createElement(rootComponent.selector)`, which throws for anything
65
- // that isn't one of our primitives), so the root needs an explicit host too, one we then hand
66
- // to the wrapper as projectable content.
61
+ // A bare `view` node made through the engine, since Angular's `createElement` resolves only
62
+ // known primitives, never a component selector
63
+ // Host of the root when `wrapperComponentProvider` is set, projected into the wrapper
67
64
  function createDetachedViewHost(): ISymbioteNode {
68
65
  // 'view', not 'View': the public name is not a Fabric view name, and until
69
66
  // makeDescriptorFor learned to reject one it fell through to a view literally named `View`.
@@ -73,53 +70,32 @@ function createDetachedViewHost(): ISymbioteNode {
73
70
  );
74
71
  }
75
72
 
76
- // Angular's whole unhandled-error funnel: INTERNAL_APPLICATION_ERROR_HANDLER resolves this token
77
- // and hands it everything the framework caught on the app's behalf — a scheduled (async) tick that
78
- // threw, a template listener that threw, a rejected pending task. Routed to the engine so an
79
- // Angular app reaches the same native redbox as a React one instead of a console line nobody sees
80
- // off a dev machine.
81
- //
82
- // There is deliberately no caught-vs-uncaught split here, unlike the React adapter's
83
- // onUncaughtError/onCaughtError pair. Angular has no error boundary, and every path where the app
84
- // DID handle something keeps clear of this seam on its own: a `@defer` block with an `@error`
85
- // branch renders that branch (defer/rendering.ts calls handleUncaughtError only when there is
86
- // none), `resource()` parks the failure in its own error signal, and an app-level try/catch or
87
- // `catchError` never reaches Angular at all. So anything arriving here is by construction
88
- // unclaimed, and the redbox is the right answer for all of it.
89
- //
90
- // Two things this must not do. It must not also call `super.handleError` — reportUncaughtError
91
- // picks exactly one channel (host reporter or console) precisely because RN routes console.error
92
- // into LogBox too, so the pair would double-report every error. And it must not throw: the
93
- // scheduler invokes this from inside its own `catch` (zoneless_scheduling_impl.ts's tick), where a
94
- // second throw escapes to the host and kills the "report and keep running" behaviour the provider
95
- // exists for.
73
+ // Angular's whole unhandled-error funnel, routed to the engine for the native redbox
74
+ // No caught-vs-uncaught split, Angular has no error boundary and handled errors never arrive
75
+ // Never `super.handleError` (double report) and never throws (the scheduler calls it in a `catch`)
96
76
  class SymbioteErrorHandler extends ErrorHandler {
97
77
  override handleError(error: unknown): void {
98
78
  reportUncaughtError(error, { origin: 'angular render' });
99
79
  }
100
80
  }
101
81
 
102
- interface IMountedApp {
82
+ type IMountedApp = {
103
83
  cmpRef: ComponentRef<unknown>;
104
84
  rootRef: ComponentRef<unknown> | undefined;
105
85
  injector: EnvironmentInjector;
106
86
  /**
107
- * Kept so teardown can release it. Angular never will: it is provided as a `useValue`, so the
108
- * injector has nothing to destroy, and the renderer it owns listens to the engine's flush door
109
- * for as long as the surface lives. See `SymbioteRendererFactory.dispose`.
87
+ * Kept so teardown can release it, a `useValue` provider gives the injector nothing to destroy
88
+ * See `SymbioteRendererFactory.dispose`
110
89
  */
111
90
  rendererFactory: SymbioteRendererFactory;
112
- }
91
+ };
113
92
 
114
- // AppRegistry's `wrapperComponentProvider` support: the root renders detached (Angular gives
115
- // it its own host node via our renderer, not yet attached anywhere), and the wrapper — the
116
- // component actually attached to the surface — receives that host node as a projected child.
117
- // `<ng-content>` in the wrapper's template is the Angular idiom for "render my children", the
118
- // direct twin of React's `createElement(Wrapper, null, rootElement)`.
119
- export interface IMountOptions {
93
+ // `wrapperComponentProvider` support: the root renders detached and the wrapper, attached to the
94
+ // surface, receives its host as projected content through `<ng-content>`
95
+ export type IMountOptions = {
120
96
  initialProps?: object;
121
97
  wrapperComponent?: Type<unknown>;
122
- }
98
+ };
123
99
 
124
100
  // App-level providers (`provideHttpClient()` and the like), set once at bootstrap
125
101
  let rootProviders: (Provider | EnvironmentProviders)[] = [];
@@ -158,14 +134,9 @@ function teardown(rootTag: IRootTag): void {
158
134
  disposeRoot(rootTag);
159
135
  }
160
136
 
161
- // Metro's build switch, and esbuild's in this repo's headless runner. Declared HERE rather than in
162
- // an ambient `globals.d.ts`, because the AOT tests (`elements.test.ts`, `style-input-aot.test.ts`)
163
- // build their own ngtsc programs from an explicit file list that an ambient declaration never
164
- // reaches — seven of them went red with `Cannot find name '__DEV__'`, reported as an empty
165
- // diagnostic set, which reads as "the template checker found nothing" and is not that.
166
- //
167
- // `declare const` emits no JavaScript, so it shadows nothing at runtime and both bundlers still
168
- // substitute the identifier.
137
+ // Metro's build switch, and esbuild's in this repo's headless runner
138
+ // Declared here, not in an ambient `globals.d.ts`: the AOT tests build their own ngtsc programs
139
+ // from an explicit file list that never reaches an ambient declaration
169
140
  declare const __DEV__: boolean;
170
141
 
171
142
  /**
@@ -202,6 +173,7 @@ function settleAngularDevMode(): void {
202
173
 
203
174
  // Kept apart from `mount` so the provider list reads as one block
204
175
  function createRootInjector(
176
+ rootTag: IRootTag,
205
177
  surface: SymbioteSurface,
206
178
  rendererFactory: SymbioteRendererFactory,
207
179
  ): EnvironmentInjector {
@@ -209,6 +181,7 @@ function createRootInjector(
209
181
  [
210
182
  ...rootProviders,
211
183
  { provide: RendererFactory2, useValue: rendererFactory },
184
+ { provide: ROOT_TAG, useValue: rootTag },
212
185
  // `resource()` resolves TransferState, which calls `doc.getElementById`
213
186
  // a stub without it throws mid-construction and the whole screen renders nothing
214
187
  {
@@ -232,10 +205,10 @@ function createRootInjector(
232
205
  );
233
206
  }
234
207
 
235
- interface IRoots {
208
+ type IRoots = {
236
209
  cmpRef: ComponentRef<unknown>;
237
210
  rootRef: ComponentRef<unknown> | undefined;
238
- }
211
+ };
239
212
 
240
213
  function createRoots(
241
214
  injector: EnvironmentInjector,
@@ -279,7 +252,7 @@ export function mount(
279
252
 
280
253
  const surface = createSurface(rootTag);
281
254
  const rendererFactory = new SymbioteRendererFactory(surface);
282
- const injector = createRootInjector(surface, rendererFactory);
255
+ const injector = createRootInjector(rootTag, surface, rendererFactory);
283
256
  const { cmpRef, rootRef } = createRoots(
284
257
  injector,
285
258
  surface,
@@ -0,0 +1,14 @@
1
+ // RN's `RootTagContext` for Angular: `mount` provides the surface tag, 0 outside any surface
2
+
3
+ import { InjectionToken, inject } from '@angular/core';
4
+ import type { IRootTag } from '@symbiote-native/engine';
5
+
6
+ const NO_SURFACE = 0;
7
+
8
+ export const ROOT_TAG = new InjectionToken<IRootTag>('symbiote.rootTag', {
9
+ factory: () => NO_SURFACE,
10
+ });
11
+
12
+ export function injectRootTag(): IRootTag {
13
+ return inject(ROOT_TAG);
14
+ }
@@ -11,7 +11,7 @@ import { Appearance, type IColorSchemeName } from '@symbiote-native/engine';
11
11
  */
12
12
  @Injectable({ providedIn: 'root' })
13
13
  export class ColorSchemeService {
14
- readonly colorScheme = signal<IColorSchemeName | null>(
14
+ readonly colorScheme = signal<IColorSchemeName | null | undefined>(
15
15
  Appearance.getColorScheme(),
16
16
  );
17
17