@symbiote-native/angular 0.0.0-canary-20260724081123

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 (276) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/babel-linker.cjs +7 -0
  4. package/babel-register-composed.cjs +127 -0
  5. package/bin/symbiote-angular-dev.cjs +93 -0
  6. package/build/angular/anchor-host-registry.d.ts +2 -0
  7. package/build/angular/anchor-host-registry.js +84 -0
  8. package/build/angular/anchor-host-registry.js.map +1 -0
  9. package/build/angular/bootstrap.d.ts +7 -0
  10. package/build/angular/bootstrap.js +15 -0
  11. package/build/angular/bootstrap.js.map +1 -0
  12. package/build/angular/components/activity-indicator/index.android.d.ts +12 -0
  13. package/build/angular/components/activity-indicator/index.android.js +21 -0
  14. package/build/angular/components/activity-indicator/index.android.js.map +1 -0
  15. package/build/angular/components/activity-indicator/index.d.ts +1 -0
  16. package/build/angular/components/activity-indicator/index.ios.d.ts +8 -0
  17. package/build/angular/components/activity-indicator/index.ios.js +21 -0
  18. package/build/angular/components/activity-indicator/index.ios.js.map +1 -0
  19. package/build/angular/components/activity-indicator/index.js +4 -0
  20. package/build/angular/components/activity-indicator/index.js.map +1 -0
  21. package/build/angular/components/activity-indicator/shared.d.ts +67 -0
  22. package/build/angular/components/activity-indicator/shared.js +260 -0
  23. package/build/angular/components/activity-indicator/shared.js.map +1 -0
  24. package/build/angular/components/button.d.ts +63 -0
  25. package/build/angular/components/button.js +332 -0
  26. package/build/angular/components/button.js.map +1 -0
  27. package/build/angular/components/flat-list/index.d.ts +122 -0
  28. package/build/angular/components/flat-list/index.js +688 -0
  29. package/build/angular/components/flat-list/index.js.map +1 -0
  30. package/build/angular/components/image/index.android.d.ts +10 -0
  31. package/build/angular/components/image/index.android.js +59 -0
  32. package/build/angular/components/image/index.android.js.map +1 -0
  33. package/build/angular/components/image/index.d.ts +1 -0
  34. package/build/angular/components/image/index.ios.d.ts +10 -0
  35. package/build/angular/components/image/index.ios.js +59 -0
  36. package/build/angular/components/image/index.ios.js.map +1 -0
  37. package/build/angular/components/image/index.js +3 -0
  38. package/build/angular/components/image/index.js.map +1 -0
  39. package/build/angular/components/image/shared.d.ts +101 -0
  40. package/build/angular/components/image/shared.js +406 -0
  41. package/build/angular/components/image/shared.js.map +1 -0
  42. package/build/angular/components/image-background.d.ts +81 -0
  43. package/build/angular/components/image-background.js +418 -0
  44. package/build/angular/components/image-background.js.map +1 -0
  45. package/build/angular/components/input-accessory-view/index.d.ts +60 -0
  46. package/build/angular/components/input-accessory-view/index.js +251 -0
  47. package/build/angular/components/input-accessory-view/index.js.map +1 -0
  48. package/build/angular/components/keyboard-avoiding-view/index.d.ts +82 -0
  49. package/build/angular/components/keyboard-avoiding-view/index.js +358 -0
  50. package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -0
  51. package/build/angular/components/modal/index.d.ts +92 -0
  52. package/build/angular/components/modal/index.js +360 -0
  53. package/build/angular/components/modal/index.js.map +1 -0
  54. package/build/angular/components/pressable/index.d.ts +123 -0
  55. package/build/angular/components/pressable/index.js +420 -0
  56. package/build/angular/components/pressable/index.js.map +1 -0
  57. package/build/angular/components/refresh-control/index.d.ts +86 -0
  58. package/build/angular/components/refresh-control/index.js +342 -0
  59. package/build/angular/components/refresh-control/index.js.map +1 -0
  60. package/build/angular/components/safe-area-view/index.d.ts +57 -0
  61. package/build/angular/components/safe-area-view/index.js +248 -0
  62. package/build/angular/components/safe-area-view/index.js.map +1 -0
  63. package/build/angular/components/scroll-view/index.android.d.ts +21 -0
  64. package/build/angular/components/scroll-view/index.android.js +235 -0
  65. package/build/angular/components/scroll-view/index.android.js.map +1 -0
  66. package/build/angular/components/scroll-view/index.d.ts +3 -0
  67. package/build/angular/components/scroll-view/index.ios.d.ts +9 -0
  68. package/build/angular/components/scroll-view/index.ios.js +86 -0
  69. package/build/angular/components/scroll-view/index.ios.js.map +1 -0
  70. package/build/angular/components/scroll-view/index.js +6 -0
  71. package/build/angular/components/scroll-view/index.js.map +1 -0
  72. package/build/angular/components/scroll-view/projection.d.ts +32 -0
  73. package/build/angular/components/scroll-view/projection.js +334 -0
  74. package/build/angular/components/scroll-view/projection.js.map +1 -0
  75. package/build/angular/components/scroll-view/shared.d.ts +230 -0
  76. package/build/angular/components/scroll-view/shared.js +682 -0
  77. package/build/angular/components/scroll-view/shared.js.map +1 -0
  78. package/build/angular/components/scroll-view/sticky-header.d.ts +40 -0
  79. package/build/angular/components/scroll-view/sticky-header.js +225 -0
  80. package/build/angular/components/scroll-view/sticky-header.js.map +1 -0
  81. package/build/angular/components/section-list/index.d.ts +116 -0
  82. package/build/angular/components/section-list/index.js +641 -0
  83. package/build/angular/components/section-list/index.js.map +1 -0
  84. package/build/angular/components/switch/index.android.d.ts +20 -0
  85. package/build/angular/components/switch/index.android.js +70 -0
  86. package/build/angular/components/switch/index.android.js.map +1 -0
  87. package/build/angular/components/switch/index.d.ts +1 -0
  88. package/build/angular/components/switch/index.ios.d.ts +19 -0
  89. package/build/angular/components/switch/index.ios.js +69 -0
  90. package/build/angular/components/switch/index.ios.js.map +1 -0
  91. package/build/angular/components/switch/index.js +4 -0
  92. package/build/angular/components/switch/index.js.map +1 -0
  93. package/build/angular/components/switch/shared.d.ts +40 -0
  94. package/build/angular/components/switch/shared.js +127 -0
  95. package/build/angular/components/switch/shared.js.map +1 -0
  96. package/build/angular/components/text-input.d.ts +153 -0
  97. package/build/angular/components/text-input.js +599 -0
  98. package/build/angular/components/text-input.js.map +1 -0
  99. package/build/angular/components/touchable/index.d.ts +245 -0
  100. package/build/angular/components/touchable/index.js +1186 -0
  101. package/build/angular/components/touchable/index.js.map +1 -0
  102. package/build/angular/components/touchable-native-feedback/index.d.ts +83 -0
  103. package/build/angular/components/touchable-native-feedback/index.js +371 -0
  104. package/build/angular/components/touchable-native-feedback/index.js.map +1 -0
  105. package/build/angular/components/virtualized-list/directives.d.ts +54 -0
  106. package/build/angular/components/virtualized-list/directives.js +153 -0
  107. package/build/angular/components/virtualized-list/directives.js.map +1 -0
  108. package/build/angular/components/virtualized-list/index.d.ts +253 -0
  109. package/build/angular/components/virtualized-list/index.js +1031 -0
  110. package/build/angular/components/virtualized-list/index.js.map +1 -0
  111. package/build/angular/components/virtualized-section-list/directives.d.ts +37 -0
  112. package/build/angular/components/virtualized-section-list/directives.js +76 -0
  113. package/build/angular/components/virtualized-section-list/directives.js.map +1 -0
  114. package/build/angular/components/virtualized-section-list/index.d.ts +178 -0
  115. package/build/angular/components/virtualized-section-list/index.js +720 -0
  116. package/build/angular/components/virtualized-section-list/index.js.map +1 -0
  117. package/build/angular/components.d.ts +39 -0
  118. package/build/angular/components.js +38 -0
  119. package/build/angular/components.js.map +1 -0
  120. package/build/angular/create-portal/index.d.ts +22 -0
  121. package/build/angular/create-portal/index.js +74 -0
  122. package/build/angular/create-portal/index.js.map +1 -0
  123. package/build/angular/create-tunnel/index.d.ts +34 -0
  124. package/build/angular/create-tunnel/index.js +126 -0
  125. package/build/angular/create-tunnel/index.js.map +1 -0
  126. package/build/angular/descriptor-to-angular/index.d.ts +22 -0
  127. package/build/angular/descriptor-to-angular/index.js +142 -0
  128. package/build/angular/descriptor-to-angular/index.js.map +1 -0
  129. package/build/angular/host-instance/index.d.ts +2 -0
  130. package/build/angular/host-instance/index.js +37 -0
  131. package/build/angular/host-instance/index.js.map +1 -0
  132. package/build/angular/index.d.ts +22 -0
  133. package/build/angular/index.js +46 -0
  134. package/build/angular/index.js.map +1 -0
  135. package/build/angular/modules/animated/animated-leaf-binder/index.d.ts +14 -0
  136. package/build/angular/modules/animated/animated-leaf-binder/index.js +91 -0
  137. package/build/angular/modules/animated/animated-leaf-binder/index.js.map +1 -0
  138. package/build/angular/modules/animated/animated-leaf-binder.d.ts +14 -0
  139. package/build/angular/modules/animated/animated-leaf-binder.js +91 -0
  140. package/build/angular/modules/animated/animated-leaf-binder.js.map +1 -0
  141. package/build/angular/modules/animated/create-animated-component.d.ts +59 -0
  142. package/build/angular/modules/animated/create-animated-component.js +364 -0
  143. package/build/angular/modules/animated/create-animated-component.js.map +1 -0
  144. package/build/angular/modules/animated/index.d.ts +51 -0
  145. package/build/angular/modules/animated/index.js +59 -0
  146. package/build/angular/modules/animated/index.js.map +1 -0
  147. package/build/angular/modules/app-registry/index.d.ts +7 -0
  148. package/build/angular/modules/app-registry/index.js +23 -0
  149. package/build/angular/modules/app-registry/index.js.map +1 -0
  150. package/build/angular/modules/status-bar/index.d.ts +20 -0
  151. package/build/angular/modules/status-bar/index.js +59 -0
  152. package/build/angular/modules/status-bar/index.js.map +1 -0
  153. package/build/angular/primitives/index.d.ts +63 -0
  154. package/build/angular/primitives/index.js +189 -0
  155. package/build/angular/primitives/index.js.map +1 -0
  156. package/build/angular/primitives/shared.d.ts +88 -0
  157. package/build/angular/primitives/shared.js +171 -0
  158. package/build/angular/primitives/shared.js.map +1 -0
  159. package/build/angular/render/index.d.ts +11 -0
  160. package/build/angular/render/index.js +171 -0
  161. package/build/angular/render/index.js.map +1 -0
  162. package/build/angular/renderer/index.d.ts +37 -0
  163. package/build/angular/renderer/index.js +301 -0
  164. package/build/angular/renderer/index.js.map +1 -0
  165. package/build/angular/services/color-scheme.service.d.ts +16 -0
  166. package/build/angular/services/color-scheme.service.js +31 -0
  167. package/build/angular/services/color-scheme.service.js.map +1 -0
  168. package/build/angular/services/index.d.ts +2 -0
  169. package/build/angular/services/index.js +3 -0
  170. package/build/angular/services/index.js.map +1 -0
  171. package/build/angular/services/window-dimensions.service.d.ts +16 -0
  172. package/build/angular/services/window-dimensions.service.js +42 -0
  173. package/build/angular/services/window-dimensions.service.js.map +1 -0
  174. package/metro-config.cjs +48 -0
  175. package/metro-css-parser.cjs +13 -0
  176. package/package.json +80 -0
  177. package/src/__tests__/responder-change-detection.test.ts +102 -0
  178. package/src/__tests__/responder-nested-cd.test.ts +113 -0
  179. package/src/anchor-host-registry.ts +88 -0
  180. package/src/angular-gaps.test.ts +142 -0
  181. package/src/angular-imports.test.ts +100 -0
  182. package/src/bootstrap.ts +26 -0
  183. package/src/components/activity-indicator/activity-indicator-class-style.test.ts +44 -0
  184. package/src/components/activity-indicator/activity-indicator.test.ts +131 -0
  185. package/src/components/activity-indicator/index.android.ts +16 -0
  186. package/src/components/activity-indicator/index.ios.ts +17 -0
  187. package/src/components/activity-indicator/index.ts +4 -0
  188. package/src/components/activity-indicator/shared.ts +206 -0
  189. package/src/components/button.ts +193 -0
  190. package/src/components/flat-list/column-wrapper-style-class.test.ts +116 -0
  191. package/src/components/flat-list/flat-list-array-style.test.ts +131 -0
  192. package/src/components/flat-list/flat-list-class-style.test.ts +74 -0
  193. package/src/components/flat-list/flat-list-scroll-containment.test.ts +107 -0
  194. package/src/components/flat-list/flat-list.test.ts +99 -0
  195. package/src/components/flat-list/index.ts +574 -0
  196. package/src/components/image/image-class-style.test.ts +46 -0
  197. package/src/components/image/index.android.ts +48 -0
  198. package/src/components/image/index.ios.ts +48 -0
  199. package/src/components/image/index.ts +3 -0
  200. package/src/components/image/shared.ts +479 -0
  201. package/src/components/image-background-class-style.test.ts +48 -0
  202. package/src/components/image-background-style-class.test.ts +79 -0
  203. package/src/components/image-background.ts +270 -0
  204. package/src/components/input-accessory-view/index.ts +185 -0
  205. package/src/components/input-accessory-view/input-accessory-view.test.ts +43 -0
  206. package/src/components/keyboard-avoiding-view/index.ts +303 -0
  207. package/src/components/keyboard-avoiding-view/keyboard-avoiding-view.test.ts +54 -0
  208. package/src/components/modal/index.ts +299 -0
  209. package/src/components/modal/modal.test.ts +43 -0
  210. package/src/components/pressable/index.ts +373 -0
  211. package/src/components/pressable/pressable.test.ts +85 -0
  212. package/src/components/refresh-control/index.ts +284 -0
  213. package/src/components/refresh-control/refresh-control.test.ts +41 -0
  214. package/src/components/safe-area-view/index.ts +177 -0
  215. package/src/components/safe-area-view/safe-area-view.test.ts +43 -0
  216. package/src/components/scroll-view/android-scroll-view-axis-projection.test.ts +123 -0
  217. package/src/components/scroll-view/content-container-style-class.test.ts +75 -0
  218. package/src/components/scroll-view/index.android.ts +190 -0
  219. package/src/components/scroll-view/index.ios.ts +79 -0
  220. package/src/components/scroll-view/index.ts +7 -0
  221. package/src/components/scroll-view/projection.ts +414 -0
  222. package/src/components/scroll-view/scroll-view-class-style.test.ts +134 -0
  223. package/src/components/scroll-view/scroll-view-projection.test.ts +194 -0
  224. package/src/components/scroll-view/shared.ts +844 -0
  225. package/src/components/scroll-view/sticky-header.ts +255 -0
  226. package/src/components/section-list/index.ts +445 -0
  227. package/src/components/switch/android-switch-class.test.ts +42 -0
  228. package/src/components/switch/index.android.ts +61 -0
  229. package/src/components/switch/index.ios.ts +60 -0
  230. package/src/components/switch/index.ts +4 -0
  231. package/src/components/switch/shared.ts +197 -0
  232. package/src/components/switch/switch.test.ts +92 -0
  233. package/src/components/text-input-class-style.test.ts +54 -0
  234. package/src/components/text-input.ts +531 -0
  235. package/src/components/touchable/index.ts +629 -0
  236. package/src/components/touchable/touchable.test.ts +102 -0
  237. package/src/components/touchable-native-feedback/index.ts +254 -0
  238. package/src/components/touchable-native-feedback/touchable-native-feedback.test.ts +49 -0
  239. package/src/components/virtualized-list/directives.ts +168 -0
  240. package/src/components/virtualized-list/index.ts +992 -0
  241. package/src/components/virtualized-list/virtualized-list-class-style.test.ts +76 -0
  242. package/src/components/virtualized-section-list/directives.ts +90 -0
  243. package/src/components/virtualized-section-list/index.ts +601 -0
  244. package/src/components/virtualized-section-list/virtualized-section-list-class-style.test.ts +60 -0
  245. package/src/components.ts +149 -0
  246. package/src/create-portal/create-portal.test.ts +90 -0
  247. package/src/create-portal/index.ts +74 -0
  248. package/src/create-tunnel/create-tunnel.test.ts +120 -0
  249. package/src/create-tunnel/index.ts +136 -0
  250. package/src/descriptor-to-angular/descriptor-outlet.test.ts +94 -0
  251. package/src/descriptor-to-angular/index.ts +190 -0
  252. package/src/host-instance/host-instance.test.ts +49 -0
  253. package/src/host-instance/index.ts +36 -0
  254. package/src/index.ts +261 -0
  255. package/src/modules/animated/animated-leaf-binder/animated-leaf-binder.test.ts +116 -0
  256. package/src/modules/animated/animated-leaf-binder/index.ts +101 -0
  257. package/src/modules/animated/animated-leaf-binder.test.ts +116 -0
  258. package/src/modules/animated/animated-leaf-binder.ts +101 -0
  259. package/src/modules/animated/animated-scroll-view.test.ts +102 -0
  260. package/src/modules/animated/create-animated-component.ts +365 -0
  261. package/src/modules/animated/index.ts +105 -0
  262. package/src/modules/app-registry/app-registry.test.ts +106 -0
  263. package/src/modules/app-registry/index.ts +60 -0
  264. package/src/modules/status-bar/index.ts +57 -0
  265. package/src/modules/status-bar/status-bar.test.ts +50 -0
  266. package/src/primitives/index.ts +119 -0
  267. package/src/primitives/shared.ts +190 -0
  268. package/src/render/index.ts +235 -0
  269. package/src/render/render.test.ts +147 -0
  270. package/src/renderer/index.ts +347 -0
  271. package/src/renderer/renderer.test.ts +203 -0
  272. package/src/services/color-scheme.service.ts +27 -0
  273. package/src/services/index.ts +2 -0
  274. package/src/services/services.test.ts +163 -0
  275. package/src/services/window-dimensions.service.ts +41 -0
  276. package/tsconfig.angular.base.json +30 -0
@@ -0,0 +1,171 @@
1
+ // Mount an Angular app onto a Fabric surface. The native host hands us a rootTag; we
2
+ // create a surface and bootstrap a standalone Angular component WITHOUT platform-browser
3
+ // (no DOM) — createEnvironmentInjector + createComponent over @angular/core only, with our
4
+ // SymbioteRendererFactory provided so Angular drives the engine, which commits into
5
+ // nativeFabricUIManager; RN's own renderer never in the path. Angular twin of
6
+ // adapters/vue/src/render.ts.
7
+ import { createElement as createEngineElement, createSurface, disposeRoot, dlog, toPublicInstance, } from '@symbiote-native/engine';
8
+ import { descriptorFor } from '@symbiote-native/components';
9
+ import { ApplicationRef, createComponent, createEnvironmentInjector, DOCUMENT, ErrorHandler, RendererFactory2, ɵINJECTOR_SCOPE as INJECTOR_SCOPE, ɵprovideZonelessChangeDetectionInternal as provideZonelessChangeDetectionInternal, } from '@angular/core';
10
+ import { SymbioteRendererFactory } from '../renderer';
11
+ import { ColorSchemeService, WindowDimensionsService } from '../services';
12
+ // The two FFI-edge casts of this adapter, both confined here to bootstrap. Angular's core
13
+ // types model a browser: the injector parent is a non-null EnvironmentInjector, the host is
14
+ // a DOM Element. Our root has neither shape — a null parent IS a root injector, and the host
15
+ // is a SymbioteSurface (or, for a wrapped AppRegistry root, a plain engine node) the
16
+ // SymbioteRenderer (not the DOM) consumes. These are the sanctioned I/O-edge casts where our
17
+ // objects cross into Angular's web-typed API; revisit if Angular ever exposes a cast-free
18
+ // host. Nothing else in the adapter casts.
19
+ function rootInjectorParent() {
20
+ return null;
21
+ }
22
+ function asAngularHost(hostNode) {
23
+ // Angular's locateHostElement reads hostElement.tagName even when a concrete hostElement
24
+ // is supplied. The host container is given Angular the tiny DOM-shaped field it probes
25
+ // without changing the renderer target.
26
+ Object.defineProperty(hostNode, 'tagName', {
27
+ configurable: true,
28
+ value: 'symbiote-root',
29
+ });
30
+ return hostNode;
31
+ }
32
+ // A bare `symbiote-view` node, created directly through the engine (bypassing Angular's own
33
+ // createElement, which only resolves KNOWN symbiote primitives, never an arbitrary component's
34
+ // selector — see SymbioteRenderer.createElement). Used as the AppRegistry root's host when a
35
+ // wrapperComponentProvider is set: Angular has no hostElement-less bootstrap for our renderer
36
+ // (it would try `renderer.createElement(rootComponent.selector)`, which throws for anything
37
+ // that isn't one of our primitives), so the root needs an explicit host too, one we then hand
38
+ // to the wrapper as projectable content.
39
+ function createDetachedViewHost() {
40
+ const descriptor = descriptorFor('View');
41
+ return toPublicInstance(createEngineElement(descriptor.component, descriptor.isText));
42
+ }
43
+ function applyInputs(cmpRef, initialProps) {
44
+ if (initialProps === undefined)
45
+ return;
46
+ for (const [key, value] of Object.entries(initialProps)) {
47
+ cmpRef.setInput(key, value);
48
+ }
49
+ }
50
+ // One Angular app per surface, so a surface can be torn down (unmount) or cleanly
51
+ // re-mounted on the same rootTag: the bridgeless host stops and restarts a surface on Fast
52
+ // Refresh and on lifecycle/focus changes, reusing the rootTag.
53
+ const apps = new Map();
54
+ function teardown(rootTag) {
55
+ const app = apps.get(rootTag);
56
+ if (app === undefined)
57
+ return;
58
+ app.rootRef?.destroy();
59
+ app.cmpRef.destroy();
60
+ app.injector.destroy();
61
+ apps.delete(rootTag);
62
+ disposeRoot(rootTag);
63
+ }
64
+ export function mount(rootTag, rootComponent, options) {
65
+ // A re-mount on a live rootTag starts clean; otherwise the stale app double-drives the surface.
66
+ teardown(rootTag);
67
+ const surface = createSurface(rootTag);
68
+ const injector = createEnvironmentInjector([
69
+ {
70
+ provide: RendererFactory2,
71
+ useValue: new SymbioteRendererFactory(surface),
72
+ },
73
+ { provide: DOCUMENT, useValue: { head: surface, body: surface } },
74
+ // createEnvironmentInjector with a null parent gives this injector scope
75
+ // {'environment'} only (see EnvironmentNgModuleRefAdapter), so providedIn:'root'
76
+ // tokens — ApplicationRef included — never resolve on their own (R3Injector.get
77
+ // walks up looking for an injector whose `scopes` contains 'root', and a null
78
+ // parent means that search always dead-ends in NullInjector). platform-browser's
79
+ // BROWSER_MODULE_PROVIDERS solves this the same way for real DOM apps: it hands
80
+ // { provide: INJECTOR_SCOPE, useValue: 'root' } to its OWN app-level providers, and
81
+ // R3Injector's constructor reads that provider and self-tags this.scopes with
82
+ // 'root'. We do the same here — no PlatformRef, no DOM, just this one provider.
83
+ { provide: INJECTOR_SCOPE, useValue: 'root' },
84
+ // Supplies the real ChangeDetectionSchedulerImpl (microtask-batched, self-scheduling
85
+ // via ApplicationRef.afterTick) + NoopNgZone + ZONELESS_ENABLED: true — the exact
86
+ // bundle internalCreateApplication() uses. With ApplicationRef reachable (see above),
87
+ // there is no more reason for a hand-rolled scheduler: it replaces our old
88
+ // unconditional `rootView.detectChanges(); cmpView.detectChanges()` (which force-ran
89
+ // BOTH root views on every tick regardless of cause) with Angular's own tick(), which
90
+ // only enters an attached view when something actually marked it (RefreshView / Dirty
91
+ // consumer / HasChildViewsToRefresh). NOTE: this does NOT stop the root's own template
92
+ // from re-running on a plain press or `ChangeDetectorRef.markForCheck()` anywhere in
93
+ // the tree — `markViewDirty` (which both native (event) bindings and `markForCheck()`
94
+ // go through, see SymbioteHostPropsDirective) unconditionally sets RefreshView on
95
+ // EVERY ancestor up to the root; that is fundamental, unavoidable Angular zoneless
96
+ // behavior, true in every Angular app, not something this swap changes. What DOES
97
+ // still protect a sibling branch from an unrelated press is a genuine child
98
+ // `@Component` boundary — SignalView-compiled children are skip-eligible regardless of
99
+ // this scheduler.
100
+ ...provideZonelessChangeDetectionInternal(),
101
+ // Angular's own INTERNAL_APPLICATION_ERROR_HANDLER (core.mjs) reports a tick()
102
+ // exception by calling `injector.get(ErrorHandler)` — a normal `bootstrapApplication`
103
+ // registers this token by default (platform-browser's BROWSER_MODULE_PROVIDERS), but
104
+ // our from-scratch environment injector never did, so that lookup itself threw
105
+ // NG0201 and REPLACED whatever the real error was with an unrelated "No provider
106
+ // found for ErrorHandler" — the real exception never got logged, and the NG0201 itself
107
+ // propagated out of a bare Timeout callback uncaught (nothing above it in the stack to
108
+ // catch it), i.e. any async tick() exception, anywhere in the app, crashed hard instead
109
+ // of being reported. Providing the default `ErrorHandler` (same one bootstrapApplication
110
+ // ships) restores the intended behavior: `console.error('ERROR', e)` and keep running.
111
+ { provide: ErrorHandler, useClass: ErrorHandler },
112
+ ColorSchemeService,
113
+ WindowDimensionsService,
114
+ ], rootInjectorParent());
115
+ // hostElement = the surface: the component's template content commits straight into the
116
+ // surface with no wrapper view, the engine wrapping surface.children in its synthetic flex
117
+ // root — the Angular equivalent of Vue's `app.mount(surface)`.
118
+ let cmpRef;
119
+ let rootRef;
120
+ if (options?.wrapperComponent === undefined) {
121
+ cmpRef = createComponent(rootComponent, {
122
+ environmentInjector: injector,
123
+ hostElement: asAngularHost(surface),
124
+ });
125
+ applyInputs(cmpRef, options?.initialProps);
126
+ }
127
+ else {
128
+ // The root gets its own host node from the renderer (createComponent without a
129
+ // hostElement) but is not attached to the surface directly; it is handed to the
130
+ // wrapper as projectable content instead, so only the wrapper needs a real host.
131
+ const rootHost = asAngularHost(createDetachedViewHost());
132
+ rootRef = createComponent(rootComponent, {
133
+ environmentInjector: injector,
134
+ hostElement: rootHost,
135
+ });
136
+ applyInputs(rootRef, options.initialProps);
137
+ cmpRef = createComponent(options.wrapperComponent, {
138
+ environmentInjector: injector,
139
+ hostElement: asAngularHost(surface),
140
+ projectableNodes: [[rootHost]],
141
+ });
142
+ }
143
+ // Attach both root views to ApplicationRef so its own tick() (via the real
144
+ // ChangeDetectionSchedulerImpl provided above) drives them from here on — no manual
145
+ // ChangeDetectorRef juggling needed. markForCheck anywhere in the tree now notifies
146
+ // the real scheduler, which batches a microtask and calls appRef.tick() itself.
147
+ const appRef = injector.get(ApplicationRef);
148
+ appRef.attachView(cmpRef.hostView);
149
+ if (rootRef !== undefined) {
150
+ appRef.attachView(rootRef.hostView);
151
+ }
152
+ dlog(`angular mount root=${rootTag}`);
153
+ appRef.tick(); // first paint
154
+ surface.requestCommit();
155
+ apps.set(rootTag, { cmpRef, rootRef, injector });
156
+ return surface;
157
+ }
158
+ // Tear down a surface by rootTag: the public pair of `mount`, and the JS half of the
159
+ // bridgeless `RN$stopSurface` contract (see installStopSurfaceGlobal).
160
+ export function unmount(rootTag) {
161
+ dlog(`angular unmount root=${rootTag}`);
162
+ teardown(rootTag);
163
+ }
164
+ function installStopSurfaceGlobal() {
165
+ globalThis.RN$stopSurface = (surfaceId) => {
166
+ unmount(surfaceId);
167
+ };
168
+ dlog('installed global.RN$stopSurface');
169
+ }
170
+ installStopSurfaceGlobal();
171
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/render/index.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,yFAAyF;AACzF,2FAA2F;AAC3F,oFAAoF;AACpF,8EAA8E;AAC9E,8BAA8B;AAE9B,OAAO,EACL,aAAa,IAAI,mBAAmB,EACpC,aAAa,EACb,WAAW,EACX,IAAI,EACJ,gBAAgB,GAIjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EACL,cAAc,EACd,eAAe,EACf,yBAAyB,EACzB,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,eAAe,IAAI,cAAc,EACjC,uCAAuC,IAAI,sCAAsC,GAIlF,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE1E,0FAA0F;AAC1F,4FAA4F;AAC5F,6FAA6F;AAC7F,qFAAqF;AACrF,6FAA6F;AAC7F,0FAA0F;AAC1F,2CAA2C;AAC3C,SAAS,kBAAkB;IACzB,OAAO,IAAsC,CAAC;AAChD,CAAC;AACD,SAAS,aAAa,CAAC,QAAyC;IAC9D,yFAAyF;IACzF,uFAAuF;IACvF,wCAAwC;IACxC,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE;QACzC,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,eAAe;KACvB,CAAC,CAAC;IACH,OAAO,QAA8B,CAAC;AACxC,CAAC;AAED,4FAA4F;AAC5F,+FAA+F;AAC/F,6FAA6F;AAC7F,8FAA8F;AAC9F,4FAA4F;AAC5F,8FAA8F;AAC9F,yCAAyC;AACzC,SAAS,sBAAsB;IAC7B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,gBAAgB,CAAC,mBAAmB,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACxF,CAAC;AAkBD,SAAS,WAAW,CAAC,MAA6B,EAAE,YAAgC;IAClF,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACxD,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,2FAA2F;AAC3F,+DAA+D;AAC/D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;AAE9C,SAAS,QAAQ,CAAC,OAAiB;IACjC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO;IAC9B,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;IACvB,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IACrB,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrB,WAAW,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,KAAK,CACnB,OAAiB,EACjB,aAA4B,EAC5B,OAAuB;IAEvB,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAElB,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,yBAAyB,CACxC;QACE;YACE,OAAO,EAAE,gBAAgB;YACzB,QAAQ,EAAE,IAAI,uBAAuB,CAAC,OAAO,CAAC;SAC/C;QACD,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACjE,yEAAyE;QACzE,iFAAiF;QACjF,gFAAgF;QAChF,8EAA8E;QAC9E,iFAAiF;QACjF,gFAAgF;QAChF,oFAAoF;QACpF,8EAA8E;QAC9E,gFAAgF;QAChF,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE;QAC7C,qFAAqF;QACrF,kFAAkF;QAClF,sFAAsF;QACtF,2EAA2E;QAC3E,qFAAqF;QACrF,sFAAsF;QACtF,sFAAsF;QACtF,uFAAuF;QACvF,qFAAqF;QACrF,sFAAsF;QACtF,kFAAkF;QAClF,mFAAmF;QACnF,kFAAkF;QAClF,4EAA4E;QAC5E,uFAAuF;QACvF,kBAAkB;QAClB,GAAG,sCAAsC,EAAE;QAC3C,+EAA+E;QAC/E,sFAAsF;QACtF,qFAAqF;QACrF,+EAA+E;QAC/E,iFAAiF;QACjF,uFAAuF;QACvF,uFAAuF;QACvF,wFAAwF;QACxF,yFAAyF;QACzF,uFAAuF;QACvF,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE;QACjD,kBAAkB;QAClB,uBAAuB;KACxB,EACD,kBAAkB,EAAE,CACrB,CAAC;IAEF,wFAAwF;IACxF,2FAA2F;IAC3F,+DAA+D;IAC/D,IAAI,MAA6B,CAAC;IAClC,IAAI,OAA0C,CAAC;IAC/C,IAAI,OAAO,EAAE,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC5C,MAAM,GAAG,eAAe,CAAU,aAAa,EAAE;YAC/C,mBAAmB,EAAE,QAAQ;YAC7B,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC;SACpC,CAAC,CAAC;QACH,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,+EAA+E;QAC/E,gFAAgF;QAChF,iFAAiF;QACjF,MAAM,QAAQ,GAAG,aAAa,CAAC,sBAAsB,EAAE,CAAC,CAAC;QACzD,OAAO,GAAG,eAAe,CAAU,aAAa,EAAE;YAChD,mBAAmB,EAAE,QAAQ;YAC7B,WAAW,EAAE,QAAQ;SACtB,CAAC,CAAC;QACH,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,GAAG,eAAe,CAAU,OAAO,CAAC,gBAAgB,EAAE;YAC1D,mBAAmB,EAAE,QAAQ;YAC7B,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC;YACnC,gBAAgB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,oFAAoF;IACpF,oFAAoF;IACpF,gFAAgF;IAChF,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5C,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAC;IACtC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,cAAc;IAC7B,OAAO,CAAC,aAAa,EAAE,CAAC;IAExB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,qFAAqF;AACrF,uEAAuE;AACvE,MAAM,UAAU,OAAO,CAAC,OAAiB;IACvC,IAAI,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACpB,CAAC;AAWD,SAAS,wBAAwB;IAC/B,UAAU,CAAC,cAAc,GAAG,CAAC,SAAiB,EAAQ,EAAE;QACtD,OAAO,CAAC,SAAS,CAAC,CAAC;IACrB,CAAC,CAAC;IACF,IAAI,CAAC,iCAAiC,CAAC,CAAC;AAC1C,CAAC;AAED,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { SymbioteSurface, type ISymbioteNode } from '@symbiote-native/engine';
2
+ import type { Renderer2, RendererFactory2, RendererType2 } from '@angular/core';
3
+ type IHostNode = ISymbioteNode;
4
+ type IHostElement = ISymbioteNode | SymbioteSurface;
5
+ export declare class SymbioteRenderer implements Renderer2 {
6
+ private readonly surface;
7
+ readonly data: Record<string, unknown>;
8
+ destroyNode: ((node: ISymbioteNode) => void) | null;
9
+ constructor(surface: SymbioteSurface);
10
+ destroy(): void;
11
+ createElement(name: string): IHostNode;
12
+ createComment(): IHostNode;
13
+ createText(value: string): IHostNode;
14
+ appendChild(parent: IHostElement | null, newChild: IHostNode): void;
15
+ insertBefore(parent: IHostElement | null, newChild: IHostNode, refChild: IHostNode | null): void;
16
+ removeChild(_parent: IHostElement | null, oldChild: IHostNode): void;
17
+ parentNode(node: IHostNode): IHostElement | null;
18
+ nextSibling(node: IHostNode): IHostNode | null;
19
+ selectRootElement(selectorOrNode: string | IHostElement): IHostElement;
20
+ setAttribute(el: IHostElement, name: string, value: string): void;
21
+ removeAttribute(el: IHostElement, name: string): void;
22
+ private readonly classTokens;
23
+ addClass(el: IHostElement, name: string): void;
24
+ removeClass(el: IHostElement, name: string): void;
25
+ setStyle(el: IHostElement, style: string, value: unknown): void;
26
+ removeStyle(el: IHostElement, style: string): void;
27
+ setProperty(el: IHostElement, name: string, value: unknown): void;
28
+ setValue(node: IHostNode, value: string): void;
29
+ listen(target: unknown, eventName: string, callback: (event: unknown) => boolean | void): () => void;
30
+ }
31
+ export declare class SymbioteRendererFactory implements RendererFactory2 {
32
+ private readonly surface;
33
+ private renderer;
34
+ constructor(surface: SymbioteSurface);
35
+ createRenderer(_hostElement: unknown, _type: RendererType2 | null): Renderer2;
36
+ }
37
+ export {};
@@ -0,0 +1,301 @@
1
+ // An Angular custom renderer over @symbiote-native/engine. Angular components never touch the
2
+ // DOM directly — every paint goes through Renderer2 (created per-component by
3
+ // RendererFactory2). We provide OUR factory, so each Renderer2 method maps onto the
4
+ // engine's tiny mutation API; the engine owns all Fabric clone-on-write, shared with
5
+ // every other adapter. This is the Angular twin of adapters/vue/src/renderer.ts — proof
6
+ // that the same engine mutation API drives both frameworks.
7
+ import { appendChild, createAnchor, createElement, createRawText, dlog, getExplicitStyle, insertBefore, isDebug, isSymbioteNode, removeChild, routeProp, setEventListener, setText, toPublicInstance, RAW_TEXT_COMPONENT, SymbioteSurface, } from '@symbiote-native/engine';
8
+ import { descriptorFor } from '@symbiote-native/components';
9
+ import { isAnchorHostComponent } from '../anchor-host-registry';
10
+ import { getScrollViewProjection, removeScrollViewProjectedChild, } from '../components/scroll-view/projection';
11
+ function isSurface(parent) {
12
+ return parent instanceof SymbioteSurface;
13
+ }
14
+ function isRawText(node) {
15
+ return node.component === RAW_TEXT_COMPONENT;
16
+ }
17
+ function isRecord(value) {
18
+ return typeof value === 'object' && value !== null;
19
+ }
20
+ // Diagnostic-only: tags each anchor with a sequential id so log lines can tell distinct
21
+ // anchors apart (they all otherwise print the same generic '#anchor' component name).
22
+ // Gated behind isDebug() so a production build pays zero cost (no WeakMap writes).
23
+ let anchorDebugCounter = 0;
24
+ const anchorDebugIds = new WeakMap();
25
+ function tagAnchorForDebug(node) {
26
+ if (isDebug()) {
27
+ anchorDebugCounter += 1;
28
+ anchorDebugIds.set(node, anchorDebugCounter);
29
+ }
30
+ return node;
31
+ }
32
+ // Diagnostic identity string for a renderer node/surface — component name, or 'surface'.
33
+ // Null-tolerant: a diagnostic must never throw (Angular hands insertBefore a null refChild).
34
+ function describeHost(node) {
35
+ if (node === null || node === undefined)
36
+ return 'null';
37
+ if (isSurface(node))
38
+ return 'surface';
39
+ const anchorId = anchorDebugIds.get(node);
40
+ return anchorId !== undefined ? `${node.component}#${anchorId}` : node.component;
41
+ }
42
+ const PRIMITIVE_SELECTOR_ALIAS = {
43
+ // Public ergonomic selectors map directly to the engine primitive descriptors.
44
+ View: 'symbiote-view',
45
+ Text: 'symbiote-text',
46
+ };
47
+ // The ANCHOR_HOST_COMPONENTS Set and registerComposedComponent now live in the dependency-free
48
+ // leaf module ../anchor-host-registry (imported above as isAnchorHostComponent) — see its header
49
+ // for why the registry must NOT sit in this require-cyclic renderer module.
50
+ // Inserting a bare raw-text node anywhere but inside a <Text> is invalid in Fabric (a
51
+ // stray RCTRawText would paint). Angular's ɵɵtext only ever lands text inside a <Text>,
52
+ // but guard anyway for parity with the Vue adapter and to fail loudly on a bad template.
53
+ function assertTextPlacement(child, parent) {
54
+ if (isRawText(child) && (isSurface(parent) || !parent.isText)) {
55
+ throw new Error(`Text string "${String(child.props.text)}" must be rendered inside a <Text>`);
56
+ }
57
+ }
58
+ // One renderer per mounted surface. Every mutation asks the surface to (microtask-
59
+ // coalesced) recommit — the same seam Vue uses; a burst of Angular change-detection
60
+ // mutations collapses into one completeRoot.
61
+ export class SymbioteRenderer {
62
+ surface;
63
+ data = {};
64
+ // Angular calls destroyNode per-node only when this is non-null; teardown happens in
65
+ // render.ts (unmount), so per-node cleanup is a no-op.
66
+ destroyNode = null;
67
+ constructor(surface) {
68
+ this.surface = surface;
69
+ }
70
+ destroy() { }
71
+ createElement(name) {
72
+ // `name` is the component's host tag — a symbiote intrinsic (`symbiote-view`,
73
+ // `symbiote-text`, …), a public ergonomic alias (`View`, `Text`), or a raw Fabric view
74
+ // name for a native leaf. Public aliases are normalized to their engine primitive name
75
+ // before descriptor lookup. descriptorFor resolves it; an unknown `symbiote-*` is a typo,
76
+ // any other string flows through as a raw Fabric name (events/processors derived from its
77
+ // ViewConfig). toPublicInstance grafts the imperative API (measure / setNativeProps /
78
+ // focus) onto the raw node in place, returning the SAME identity the commit mirror keys on.
79
+ const engineName = PRIMITIVE_SELECTOR_ALIAS[name] ?? name;
80
+ if (isAnchorHostComponent(engineName)) {
81
+ const anchor = tagAnchorForDebug(createAnchor());
82
+ dlog(`angular createElement ${name} -> anchor host ${describeHost(anchor)}`);
83
+ return anchor;
84
+ }
85
+ const descriptor = descriptorFor(engineName);
86
+ const node = createElement(descriptor.component, descriptor.isText);
87
+ dlog(`angular createElement ${name} -> ${descriptor.component}`);
88
+ return toPublicInstance(node);
89
+ }
90
+ createComment() {
91
+ // Angular structural directives (*ngIf / @if / @for) need anchor nodes to track
92
+ // position. A real retained node the commit walk SKIPS — no native view. Twin of the
93
+ // Vue createComment path.
94
+ const anchor = tagAnchorForDebug(createAnchor());
95
+ dlog(`Angular renderer createComment -> ${describeHost(anchor)}`);
96
+ return anchor;
97
+ }
98
+ createText(value) {
99
+ return createRawText(value);
100
+ }
101
+ appendChild(parent, newChild) {
102
+ // Angular defers insertion for content awaiting its host component's own projection
103
+ // (see parentNode below) — mirrors Angular's own `if (parentRNode !== null)` guard in
104
+ // addLViewToLContainer: skip silently now, the later projection pass places it correctly.
105
+ if (parent === null)
106
+ return;
107
+ assertTextPlacement(newChild, parent);
108
+ if (isSurface(parent)) {
109
+ dlog(`Angular renderer appendChild parent=surface child=${describeHost(newChild)}`);
110
+ parent.appendChild(newChild);
111
+ }
112
+ else {
113
+ const projection = getScrollViewProjection(parent);
114
+ dlog(`Angular renderer appendChild parent=${describeHost(parent)} child=${describeHost(newChild)} projection=${projection !== undefined}`);
115
+ if (projection !== undefined) {
116
+ projection.appendProjectedChild(parent, newChild, (target, child) => appendChild(target, child));
117
+ }
118
+ else {
119
+ appendChild(parent, newChild);
120
+ }
121
+ }
122
+ this.surface.requestCommit();
123
+ }
124
+ insertBefore(parent, newChild, refChild) {
125
+ if (parent === null)
126
+ return; // see the appendChild guard above
127
+ assertTextPlacement(newChild, parent);
128
+ if (isSurface(parent)) {
129
+ dlog(`Angular renderer insertBefore parent=surface child=${describeHost(newChild)} ref=${refChild ? describeHost(refChild) : 'null'}`);
130
+ if (refChild)
131
+ parent.insertBefore(newChild, refChild);
132
+ else
133
+ parent.appendChild(newChild);
134
+ }
135
+ else {
136
+ const projection = getScrollViewProjection(parent);
137
+ dlog(`Angular renderer insertBefore parent=${describeHost(parent)} child=${describeHost(newChild)} ref=${refChild ? describeHost(refChild) : 'null'} projection=${projection !== undefined}`);
138
+ if (projection !== undefined) {
139
+ projection.insertProjectedChild(parent, newChild, refChild, (target, child, before) => {
140
+ if (before === undefined)
141
+ appendChild(target, child);
142
+ else
143
+ insertBefore(target, child, before);
144
+ });
145
+ }
146
+ else if (refChild) {
147
+ insertBefore(parent, newChild, refChild);
148
+ }
149
+ else {
150
+ appendChild(parent, newChild);
151
+ }
152
+ }
153
+ this.surface.requestCommit();
154
+ }
155
+ removeChild(_parent, oldChild) {
156
+ // Detach from the child's own retained parent (a top-level node lives in
157
+ // surface.children with no parent). Angular's `parent` arg is ignored in favor of the
158
+ // authoritative link, mirroring the Vue adapter's remove.
159
+ const angularParent = _parent !== null ? describeHost(_parent) : 'null';
160
+ const retainedParent = oldChild.parent !== undefined ? describeHost(oldChild.parent) : 'none';
161
+ const wasProjected = removeScrollViewProjectedChild(oldChild, (parent, child) => removeChild(parent, child));
162
+ dlog(`Angular renderer removeChild angularParent=${angularParent} retainedParent=${retainedParent} child=${describeHost(oldChild)} viaProjection=${wasProjected}`);
163
+ if (!wasProjected) {
164
+ const parent = oldChild.parent;
165
+ if (parent !== undefined)
166
+ removeChild(parent, oldChild);
167
+ else
168
+ this.surface.removeChild(oldChild);
169
+ }
170
+ this.surface.requestCommit();
171
+ }
172
+ // FlatList/VirtualizedList cells are content projected into a component host (our
173
+ // ANCHOR_HOST_COMPONENTS, e.g. ScrollView) — Angular's own addLViewToLContainer
174
+ // (.vendors/angular node_manipulation.ts/container.ts) treats a null parent here as "defer —
175
+ // the child component's own <ng-content>/ɵɵprojection will place this once its structure
176
+ // resolves" (e.g. ScrollView's `@if(isHorizontal)` branch). Renderer2's contract types this
177
+ // return as nullable for exactly that reason; returning `this.surface` as a non-null fallback
178
+ // defeated that defer check and caused premature top-level insertion (2026-07: FlatList cells
179
+ // rendered outside their ScrollView).
180
+ //
181
+ // Safe only because appendChild/insertBefore above now also treat a null parent as "skip, wait
182
+ // for projection" — a second Angular call site (`insertAnchorNode`, hit whenever a directive
183
+ // does `inject(ViewContainerRef)`, e.g. VListOutletDirective) forwards this null straight into
184
+ // insertBefore without checking it; without that guard it crashed on-device.
185
+ parentNode(node) {
186
+ return node.parent ?? null;
187
+ }
188
+ nextSibling(node) {
189
+ const siblings = node.parent !== undefined ? node.parent.children : this.surface.children;
190
+ const index = siblings.indexOf(node);
191
+ return index >= 0 ? (siblings[index + 1] ?? null) : null;
192
+ }
193
+ // locateHostElement always routes createComponent's `hostElement` THROUGH here as
194
+ // `selectorOrNode` (Angular's own core.mjs) — it is never bypassed just because a real
195
+ // object (vs. a selector string) was given. A string only reaches us on the (unused here)
196
+ // selector-string bootstrap path, so the surface is the fallback for that case only.
197
+ selectRootElement(selectorOrNode) {
198
+ return typeof selectorOrNode === 'string' ? this.surface : selectorOrNode;
199
+ }
200
+ setAttribute(el, name, value) {
201
+ if (isSurface(el))
202
+ return;
203
+ routeProp(el, name, value);
204
+ this.surface.requestCommit();
205
+ }
206
+ removeAttribute(el, name) {
207
+ if (isSurface(el))
208
+ return;
209
+ routeProp(el, name, undefined);
210
+ this.surface.requestCommit();
211
+ }
212
+ // Ivy compiles every class= / [class.foo] / [ngClass] form down to per-token addClass/
213
+ // removeClass calls (never a single setAttribute('class', ...) call), so a per-node token set
214
+ // is accumulated here and re-joined into one string on every change, then handed to
215
+ // routeProp('class', ...) exactly like Vue's template `class="..."` and React's JSX
216
+ // `className="..."` — all three resolve through the SAME centralized class+style merge in
217
+ // core/engine/src/node.ts, so a class registered via the SFC/CSS-Modules style compiler
218
+ // resolves identically regardless of adapter.
219
+ classTokens = new WeakMap();
220
+ addClass(el, name) {
221
+ if (isSurface(el))
222
+ return;
223
+ const tokens = this.classTokens.get(el) ?? new Set();
224
+ tokens.add(name);
225
+ this.classTokens.set(el, tokens);
226
+ routeProp(el, 'class', [...tokens].join(' '));
227
+ this.surface.requestCommit();
228
+ }
229
+ removeClass(el, name) {
230
+ if (isSurface(el))
231
+ return;
232
+ const tokens = this.classTokens.get(el);
233
+ if (tokens === undefined)
234
+ return;
235
+ tokens.delete(name);
236
+ routeProp(el, 'class', tokens.size > 0 ? [...tokens].join(' ') : undefined);
237
+ this.surface.requestCommit();
238
+ }
239
+ // Angular decomposes a [style] binding into per-key setStyle calls (ɵɵstyleMap). RN wants
240
+ // the whole style object as one `style` prop, so merge each key into it — onto the explicit
241
+ // style half tracked by routeProp's centralized class+style merge (core/engine/src/node.ts),
242
+ // NOT el.props.style directly: that may now be the [classStyle, explicitStyle] array the
243
+ // merge writes, and spreading an array as a record would silently produce numeric-index keys.
244
+ setStyle(el, style, value) {
245
+ if (isSurface(el))
246
+ return;
247
+ const current = getExplicitStyle(el);
248
+ const base = isRecord(current) ? current : {};
249
+ routeProp(el, 'style', { ...base, [style]: value });
250
+ this.surface.requestCommit();
251
+ }
252
+ removeStyle(el, style) {
253
+ if (isSurface(el))
254
+ return;
255
+ const current = getExplicitStyle(el);
256
+ if (!isRecord(current))
257
+ return;
258
+ const { [style]: _removed, ...rest } = current;
259
+ routeProp(el, 'style', rest);
260
+ this.surface.requestCommit();
261
+ }
262
+ // [prop]="x" bindings. routeProp makes the prop-vs-event decision from the node's
263
+ // ViewConfig (identical to React/Vue), so the whole flat-bag prop layer is shared.
264
+ setProperty(el, name, value) {
265
+ if (isSurface(el))
266
+ return;
267
+ routeProp(el, name, value);
268
+ this.surface.requestCommit();
269
+ }
270
+ setValue(node, value) {
271
+ // A useful permanent seam: text mutations are low-frequency and the one place a stale
272
+ // `{{binding}}` (a change-detection gap) shows up as "the setValue never fired".
273
+ dlog(`Angular renderer setValue "${value}" on ${describeHost(node)}`);
274
+ setText(node, value);
275
+ this.surface.requestCommit();
276
+ }
277
+ // (event)="x" bindings. Angular hands the event name EXPLICITLY (no onX->x inference),
278
+ // so we drive the engine's structural event channel directly — the path setEventListener
279
+ // in core/engine/src/node.ts already names "Angular Renderer2.listen" for. Global targets
280
+ // (window/document/body) have no Fabric node, so they no-op.
281
+ listen(target, eventName, callback) {
282
+ if (!isSymbioteNode(target))
283
+ return () => { };
284
+ setEventListener(target, eventName, callback);
285
+ return () => setEventListener(target, eventName, undefined);
286
+ }
287
+ }
288
+ // Provided to Angular as RendererFactory2; createRenderer returns the single
289
+ // surface-bound renderer for every component (begin/end commit-coalescing is unnecessary —
290
+ // requestCommit already microtask-coalesces).
291
+ export class SymbioteRendererFactory {
292
+ surface;
293
+ renderer;
294
+ constructor(surface) {
295
+ this.surface = surface;
296
+ }
297
+ createRenderer(_hostElement, _type) {
298
+ return (this.renderer ??= new SymbioteRenderer(this.surface));
299
+ }
300
+ }
301
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/renderer/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type IColorSchemeName } from '@symbiote-native/engine';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Angular twin of React's `useColorScheme` and Vue's `useColorScheme` composable. The service
5
+ * holds a Signal that tracks the device color scheme; consumers read it via `inject`:
6
+ *
7
+ * readonly colorScheme = inject(ColorSchemeService).colorScheme;
8
+ *
9
+ * State and lifecycle live in DI, not in a function closure.
10
+ */
11
+ export declare class ColorSchemeService {
12
+ readonly colorScheme: import("@angular/core").WritableSignal<IColorSchemeName | null>;
13
+ constructor();
14
+ static ɵfac: i0.ɵɵFactoryDeclaration<ColorSchemeService, never>;
15
+ static ɵprov: i0.ɵɵInjectableDeclaration<ColorSchemeService>;
16
+ }
@@ -0,0 +1,31 @@
1
+ import { DestroyRef, inject, Injectable, signal } from '@angular/core';
2
+ import { Appearance } from '@symbiote-native/engine';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * Angular twin of React's `useColorScheme` and Vue's `useColorScheme` composable. The service
6
+ * holds a Signal that tracks the device color scheme; consumers read it via `inject`:
7
+ *
8
+ * readonly colorScheme = inject(ColorSchemeService).colorScheme;
9
+ *
10
+ * State and lifecycle live in DI, not in a function closure.
11
+ */
12
+ export class ColorSchemeService {
13
+ colorScheme = signal(Appearance.getColorScheme(), /* @ts-ignore */
14
+ ...(ngDevMode ? [{ debugName: "colorScheme" }] : /* istanbul ignore next */ []));
15
+ constructor() {
16
+ const destroyRef = inject(DestroyRef);
17
+ const subscription = Appearance.addChangeListener(preferences => {
18
+ this.colorScheme.set(preferences.colorScheme);
19
+ });
20
+ destroyRef.onDestroy(() => {
21
+ subscription.remove();
22
+ });
23
+ }
24
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ColorSchemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
25
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ColorSchemeService, providedIn: 'root' });
26
+ }
27
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ColorSchemeService, decorators: [{
28
+ type: Injectable,
29
+ args: [{ providedIn: 'root' }]
30
+ }], ctorParameters: () => [] });
31
+ //# sourceMappingURL=color-scheme.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-scheme.service.js","sourceRoot":"","sources":["../../../src/services/color-scheme.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,UAAU,EAAyB,MAAM,yBAAyB,CAAC;;AAE5E;;;;;;;GAOG;AAEH,MAAM,OAAO,kBAAkB;IACpB,WAAW,GAAG,MAAM,CAA0B,UAAU,CAAC,cAAc,EAAE;oFAAC,CAAC;IAEpF;QACE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QAEtC,MAAM,YAAY,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,EAAE;YAC9D,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE;YACxB,YAAY,CAAC,MAAM,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;uGAbU,kBAAkB;2GAAlB,kBAAkB,cADL,MAAM;;2FACnB,kBAAkB;kBAD9B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE"}
@@ -0,0 +1,2 @@
1
+ export { ColorSchemeService } from './color-scheme.service';
2
+ export { WindowDimensionsService } from './window-dimensions.service';
@@ -0,0 +1,3 @@
1
+ export { ColorSchemeService } from './color-scheme.service';
2
+ export { WindowDimensionsService } from './window-dimensions.service';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type IDisplayMetrics } from '@symbiote-native/engine';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Angular twin of React's `useWindowDimensions` and Vue's `useWindowDimensions` composable. The
5
+ * service holds a Signal that tracks window metrics; consumers read it via `inject`:
6
+ *
7
+ * readonly dimensions = inject(WindowDimensionsService).dimensions;
8
+ *
9
+ * State and lifecycle live in DI, not in a function closure.
10
+ */
11
+ export declare class WindowDimensionsService {
12
+ readonly dimensions: import("@angular/core").WritableSignal<IDisplayMetrics>;
13
+ constructor();
14
+ static ɵfac: i0.ɵɵFactoryDeclaration<WindowDimensionsService, never>;
15
+ static ɵprov: i0.ɵɵInjectableDeclaration<WindowDimensionsService>;
16
+ }