@symbiote-native/angular 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (372) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/build/angular/components/activity-indicator/index.android.d.ts +12 -0
  4. package/build/angular/components/activity-indicator/index.android.js +21 -0
  5. package/build/angular/components/activity-indicator/index.android.js.map +1 -0
  6. package/build/angular/components/activity-indicator/index.d.ts +1 -0
  7. package/build/angular/components/activity-indicator/index.ios.d.ts +8 -0
  8. package/build/angular/components/activity-indicator/index.ios.js +21 -0
  9. package/build/angular/components/activity-indicator/index.ios.js.map +1 -0
  10. package/build/angular/components/activity-indicator/index.js +4 -0
  11. package/build/angular/components/activity-indicator/index.js.map +1 -0
  12. package/build/angular/components/activity-indicator/shared.d.ts +67 -0
  13. package/build/angular/components/activity-indicator/shared.js +260 -0
  14. package/build/angular/components/activity-indicator/shared.js.map +1 -0
  15. package/build/angular/components/button.d.ts +63 -0
  16. package/build/angular/components/button.js +332 -0
  17. package/build/angular/components/button.js.map +1 -0
  18. package/build/angular/components/drawer-layout-android/index.android.d.ts +34 -0
  19. package/build/angular/components/drawer-layout-android/index.android.js +291 -0
  20. package/build/angular/components/drawer-layout-android/index.android.js.map +1 -0
  21. package/build/angular/components/drawer-layout-android/index.d.ts +11 -0
  22. package/build/angular/components/drawer-layout-android/index.js +109 -0
  23. package/build/angular/components/drawer-layout-android/index.js.map +1 -0
  24. package/build/angular/components/drawer-layout-android/shared.d.ts +74 -0
  25. package/build/angular/components/drawer-layout-android/shared.js +138 -0
  26. package/build/angular/components/drawer-layout-android/shared.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 +689 -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 +408 -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.d.ts +59 -0
  46. package/build/angular/components/input-accessory-view.js +266 -0
  47. package/build/angular/components/input-accessory-view.js.map +1 -0
  48. package/build/angular/components/keyboard-avoiding-view.d.ts +82 -0
  49. package/build/angular/components/keyboard-avoiding-view.js +363 -0
  50. package/build/angular/components/keyboard-avoiding-view.js.map +1 -0
  51. package/build/angular/components/modal.d.ts +92 -0
  52. package/build/angular/components/modal.js +365 -0
  53. package/build/angular/components/modal.js.map +1 -0
  54. package/build/angular/components/pressable/index.d.ts +123 -0
  55. package/build/angular/components/pressable/index.js +421 -0
  56. package/build/angular/components/pressable/index.js.map +1 -0
  57. package/build/angular/components/refresh-control.d.ts +86 -0
  58. package/build/angular/components/refresh-control.js +347 -0
  59. package/build/angular/components/refresh-control.js.map +1 -0
  60. package/build/angular/components/safe-area-view.d.ts +57 -0
  61. package/build/angular/components/safe-area-view.js +253 -0
  62. package/build/angular/components/safe-area-view.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 +312 -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 +679 -0
  77. package/build/angular/components/scroll-view/shared.js.map +1 -0
  78. package/build/angular/components/scroll-view/sticky-header.d.ts +41 -0
  79. package/build/angular/components/scroll-view/sticky-header.js +208 -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 +604 -0
  98. package/build/angular/components/text-input.js.map +1 -0
  99. package/build/angular/components/touchable-native-feedback.d.ts +83 -0
  100. package/build/angular/components/touchable-native-feedback.js +376 -0
  101. package/build/angular/components/touchable-native-feedback.js.map +1 -0
  102. package/build/angular/components/touchable.d.ts +248 -0
  103. package/build/angular/components/touchable.js +1206 -0
  104. package/build/angular/components/touchable.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 +154 -0
  107. package/build/angular/components/virtualized-list/directives.js.map +1 -0
  108. package/build/angular/components/virtualized-list/index.d.ts +268 -0
  109. package/build/angular/components/virtualized-list/index.js +1162 -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 +77 -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 +722 -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.d.ts +22 -0
  121. package/build/angular/create-portal.js +74 -0
  122. package/build/angular/create-portal.js.map +1 -0
  123. package/build/angular/create-tunnel.d.ts +34 -0
  124. package/build/angular/create-tunnel.js +126 -0
  125. package/build/angular/create-tunnel.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 +21 -0
  133. package/build/angular/index.js +42 -0
  134. package/build/angular/index.js.map +1 -0
  135. package/build/angular/modules/animated/create-animated-component.d.ts +68 -0
  136. package/build/angular/modules/animated/create-animated-component.js +429 -0
  137. package/build/angular/modules/animated/create-animated-component.js.map +1 -0
  138. package/build/angular/modules/animated/index.d.ts +51 -0
  139. package/build/angular/modules/animated/index.js +59 -0
  140. package/build/angular/modules/animated/index.js.map +1 -0
  141. package/build/angular/modules/app-registry/index.d.ts +7 -0
  142. package/build/angular/modules/app-registry/index.js +23 -0
  143. package/build/angular/modules/app-registry/index.js.map +1 -0
  144. package/build/angular/modules/status-bar.d.ts +20 -0
  145. package/build/angular/modules/status-bar.js +59 -0
  146. package/build/angular/modules/status-bar.js.map +1 -0
  147. package/build/angular/primitives/index.d.ts +63 -0
  148. package/build/angular/primitives/index.js +189 -0
  149. package/build/angular/primitives/index.js.map +1 -0
  150. package/build/angular/primitives/shared.d.ts +89 -0
  151. package/build/angular/primitives/shared.js +172 -0
  152. package/build/angular/primitives/shared.js.map +1 -0
  153. package/build/angular/render.d.ts +11 -0
  154. package/build/angular/render.js +161 -0
  155. package/build/angular/render.js.map +1 -0
  156. package/build/angular/renderer.d.ts +38 -0
  157. package/build/angular/renderer.js +360 -0
  158. package/build/angular/renderer.js.map +1 -0
  159. package/build/angular/services/color-scheme.service.d.ts +16 -0
  160. package/build/angular/services/color-scheme.service.js +31 -0
  161. package/build/angular/services/color-scheme.service.js.map +1 -0
  162. package/build/angular/services/index.d.ts +2 -0
  163. package/build/angular/services/index.js +3 -0
  164. package/build/angular/services/index.js.map +1 -0
  165. package/build/angular/services/window-dimensions.service.d.ts +16 -0
  166. package/build/angular/services/window-dimensions.service.js +42 -0
  167. package/build/angular/services/window-dimensions.service.js.map +1 -0
  168. package/build/components/activity-indicator/index.android.d.ts +9 -0
  169. package/build/components/activity-indicator/index.android.js +64 -0
  170. package/build/components/activity-indicator/index.d.ts +1 -0
  171. package/build/components/activity-indicator/index.ios.d.ts +5 -0
  172. package/build/components/activity-indicator/index.ios.js +64 -0
  173. package/build/components/activity-indicator/index.js +3 -0
  174. package/build/components/activity-indicator/shared.d.ts +64 -0
  175. package/build/components/activity-indicator/shared.js +424 -0
  176. package/build/components/button.d.ts +60 -0
  177. package/build/components/button.js +456 -0
  178. package/build/components/drawer-layout-android/index.android.d.ts +29 -0
  179. package/build/components/drawer-layout-android/index.android.js +326 -0
  180. package/build/components/drawer-layout-android/index.d.ts +8 -0
  181. package/build/components/drawer-layout-android/index.js +145 -0
  182. package/build/components/drawer-layout-android/shared.d.ts +71 -0
  183. package/build/components/drawer-layout-android/shared.js +205 -0
  184. package/build/components/flat-list/index.d.ts +119 -0
  185. package/build/components/flat-list/index.js +692 -0
  186. package/build/components/image/index.android.d.ts +7 -0
  187. package/build/components/image/index.android.js +88 -0
  188. package/build/components/image/index.d.ts +1 -0
  189. package/build/components/image/index.ios.d.ts +7 -0
  190. package/build/components/image/index.ios.js +88 -0
  191. package/build/components/image/index.js +2 -0
  192. package/build/components/image/shared.d.ts +101 -0
  193. package/build/components/image/shared.js +407 -0
  194. package/build/components/image-background.d.ts +78 -0
  195. package/build/components/image-background.js +583 -0
  196. package/build/components/input-accessory-view.d.ts +56 -0
  197. package/build/components/input-accessory-view.js +407 -0
  198. package/build/components/keyboard-avoiding-view.d.ts +79 -0
  199. package/build/components/keyboard-avoiding-view.js +509 -0
  200. package/build/components/modal.d.ts +89 -0
  201. package/build/components/modal.js +534 -0
  202. package/build/components/pressable/index.d.ts +120 -0
  203. package/build/components/pressable/index.js +640 -0
  204. package/build/components/refresh-control.d.ts +83 -0
  205. package/build/components/refresh-control.js +514 -0
  206. package/build/components/safe-area-view.d.ts +54 -0
  207. package/build/components/safe-area-view.js +393 -0
  208. package/build/components/scroll-view/index.android.d.ts +16 -0
  209. package/build/components/scroll-view/index.android.js +228 -0
  210. package/build/components/scroll-view/index.d.ts +3 -0
  211. package/build/components/scroll-view/index.ios.d.ts +6 -0
  212. package/build/components/scroll-view/index.ios.js +113 -0
  213. package/build/components/scroll-view/index.js +5 -0
  214. package/build/components/scroll-view/projection.d.ts +32 -0
  215. package/build/components/scroll-view/projection.js +311 -0
  216. package/build/components/scroll-view/shared.d.ts +225 -0
  217. package/build/components/scroll-view/shared.js +757 -0
  218. package/build/components/scroll-view/sticky-header.d.ts +38 -0
  219. package/build/components/scroll-view/sticky-header.js +257 -0
  220. package/build/components/section-list/index.d.ts +113 -0
  221. package/build/components/section-list/index.js +768 -0
  222. package/build/components/switch/index.android.d.ts +17 -0
  223. package/build/components/switch/index.android.js +107 -0
  224. package/build/components/switch/index.d.ts +1 -0
  225. package/build/components/switch/index.ios.d.ts +16 -0
  226. package/build/components/switch/index.ios.js +106 -0
  227. package/build/components/switch/index.js +3 -0
  228. package/build/components/switch/shared.d.ts +37 -0
  229. package/build/components/switch/shared.js +176 -0
  230. package/build/components/text-input.d.ts +150 -0
  231. package/build/components/text-input.js +826 -0
  232. package/build/components/touchable-native-feedback.d.ts +80 -0
  233. package/build/components/touchable-native-feedback.js +550 -0
  234. package/build/components/touchable.d.ts +241 -0
  235. package/build/components/touchable.js +1672 -0
  236. package/build/components/virtualized-list/directives.d.ts +41 -0
  237. package/build/components/virtualized-list/directives.js +250 -0
  238. package/build/components/virtualized-list/index.d.ts +265 -0
  239. package/build/components/virtualized-list/index.js +1344 -0
  240. package/build/components/virtualized-section-list/directives.d.ts +28 -0
  241. package/build/components/virtualized-section-list/directives.js +149 -0
  242. package/build/components/virtualized-section-list/index.d.ts +175 -0
  243. package/build/components/virtualized-section-list/index.js +854 -0
  244. package/build/components.d.ts +39 -0
  245. package/build/components.js +37 -0
  246. package/build/create-portal.d.ts +17 -0
  247. package/build/create-portal.js +128 -0
  248. package/build/create-tunnel.d.ts +29 -0
  249. package/build/create-tunnel.js +181 -0
  250. package/build/descriptor-to-angular/index.d.ts +19 -0
  251. package/build/descriptor-to-angular/index.js +186 -0
  252. package/build/host-instance/index.d.ts +2 -0
  253. package/build/host-instance/index.js +36 -0
  254. package/build/index.d.ts +21 -0
  255. package/build/index.js +41 -0
  256. package/build/modules/animated/create-animated-component.d.ts +57 -0
  257. package/build/modules/animated/create-animated-component.js +490 -0
  258. package/build/modules/animated/index.d.ts +51 -0
  259. package/build/modules/animated/index.js +58 -0
  260. package/build/modules/app-registry/index.d.ts +7 -0
  261. package/build/modules/app-registry/index.js +22 -0
  262. package/build/modules/status-bar.d.ts +17 -0
  263. package/build/modules/status-bar.js +121 -0
  264. package/build/primitives/index.d.ts +32 -0
  265. package/build/primitives/index.js +386 -0
  266. package/build/primitives/shared.d.ts +84 -0
  267. package/build/primitives/shared.js +231 -0
  268. package/build/render.d.ts +11 -0
  269. package/build/render.js +160 -0
  270. package/build/renderer.d.ts +38 -0
  271. package/build/renderer.js +359 -0
  272. package/build/services/color-scheme.service.d.ts +13 -0
  273. package/build/services/color-scheme.service.js +72 -0
  274. package/build/services/index.d.ts +2 -0
  275. package/build/services/index.js +2 -0
  276. package/build/services/window-dimensions.service.d.ts +13 -0
  277. package/build/services/window-dimensions.service.js +83 -0
  278. package/metro-css-parser.cjs +11 -0
  279. package/package.json +57 -0
  280. package/src/__tests__/responder-change-detection.test.ts +102 -0
  281. package/src/__tests__/responder-nested-cd.test.ts +113 -0
  282. package/src/angular-gaps.test.ts +142 -0
  283. package/src/angular-imports.test.ts +100 -0
  284. package/src/components/activity-indicator/activity-indicator-class-style.test.ts +44 -0
  285. package/src/components/activity-indicator/activity-indicator.test.ts +131 -0
  286. package/src/components/activity-indicator/index.android.ts +16 -0
  287. package/src/components/activity-indicator/index.ios.ts +17 -0
  288. package/src/components/activity-indicator/index.ts +4 -0
  289. package/src/components/activity-indicator/shared.ts +206 -0
  290. package/src/components/button.ts +193 -0
  291. package/src/components/flat-list/column-wrapper-style-class.test.ts +116 -0
  292. package/src/components/flat-list/flat-list-array-style.test.ts +131 -0
  293. package/src/components/flat-list/flat-list-class-style.test.ts +74 -0
  294. package/src/components/flat-list/flat-list-scroll-containment.test.ts +107 -0
  295. package/src/components/flat-list/flat-list.test.ts +99 -0
  296. package/src/components/flat-list/index.ts +575 -0
  297. package/src/components/image/image-class-style.test.ts +46 -0
  298. package/src/components/image/index.android.ts +48 -0
  299. package/src/components/image/index.ios.ts +48 -0
  300. package/src/components/image/index.ts +3 -0
  301. package/src/components/image/shared.ts +478 -0
  302. package/src/components/image-background-class-style.test.ts +48 -0
  303. package/src/components/image-background-style-class.test.ts +79 -0
  304. package/src/components/image-background.ts +270 -0
  305. package/src/components/input-accessory-view.test.ts +43 -0
  306. package/src/components/input-accessory-view.ts +191 -0
  307. package/src/components/keyboard-avoiding-view.test.ts +54 -0
  308. package/src/components/keyboard-avoiding-view.ts +308 -0
  309. package/src/components/modal.test.ts +43 -0
  310. package/src/components/modal.ts +304 -0
  311. package/src/components/pressable/index.ts +371 -0
  312. package/src/components/pressable/pressable.test.ts +85 -0
  313. package/src/components/refresh-control.test.ts +41 -0
  314. package/src/components/refresh-control.ts +288 -0
  315. package/src/components/safe-area-view.test.ts +43 -0
  316. package/src/components/safe-area-view.ts +178 -0
  317. package/src/components/scroll-view/android-scroll-view-axis-projection.test.ts +123 -0
  318. package/src/components/scroll-view/content-container-style-class.test.ts +75 -0
  319. package/src/components/scroll-view/index.android.ts +190 -0
  320. package/src/components/scroll-view/index.ios.ts +79 -0
  321. package/src/components/scroll-view/index.ts +7 -0
  322. package/src/components/scroll-view/projection.ts +384 -0
  323. package/src/components/scroll-view/scroll-view-class-style.test.ts +134 -0
  324. package/src/components/scroll-view/scroll-view-projection.test.ts +194 -0
  325. package/src/components/scroll-view/shared.ts +836 -0
  326. package/src/components/scroll-view/sticky-header.ts +230 -0
  327. package/src/components/section-list/index.ts +445 -0
  328. package/src/components/switch/android-switch-class.test.ts +42 -0
  329. package/src/components/switch/index.android.ts +61 -0
  330. package/src/components/switch/index.ios.ts +60 -0
  331. package/src/components/switch/index.ts +4 -0
  332. package/src/components/switch/shared.ts +197 -0
  333. package/src/components/switch/switch.test.ts +92 -0
  334. package/src/components/text-input-class-style.test.ts +54 -0
  335. package/src/components/text-input.ts +536 -0
  336. package/src/components/touchable-native-feedback.test.ts +49 -0
  337. package/src/components/touchable-native-feedback.ts +260 -0
  338. package/src/components/touchable.test.ts +102 -0
  339. package/src/components/touchable.ts +643 -0
  340. package/src/components/virtualized-list/directives.ts +169 -0
  341. package/src/components/virtualized-list/index.ts +1204 -0
  342. package/src/components/virtualized-list/virtualized-list-class-style.test.ts +76 -0
  343. package/src/components/virtualized-section-list/directives.ts +91 -0
  344. package/src/components/virtualized-section-list/index.ts +598 -0
  345. package/src/components/virtualized-section-list/virtualized-section-list-class-style.test.ts +60 -0
  346. package/src/components.ts +149 -0
  347. package/src/create-portal.test.ts +90 -0
  348. package/src/create-portal.ts +74 -0
  349. package/src/create-tunnel.test.ts +120 -0
  350. package/src/create-tunnel.ts +136 -0
  351. package/src/descriptor-to-angular/descriptor-outlet.test.ts +94 -0
  352. package/src/descriptor-to-angular/index.ts +190 -0
  353. package/src/host-instance/host-instance.test.ts +49 -0
  354. package/src/host-instance/index.ts +36 -0
  355. package/src/index.ts +257 -0
  356. package/src/modules/animated/animated-scroll-view.test.ts +85 -0
  357. package/src/modules/animated/create-animated-component.ts +435 -0
  358. package/src/modules/animated/index.ts +105 -0
  359. package/src/modules/app-registry/app-registry.test.ts +106 -0
  360. package/src/modules/app-registry/index.ts +60 -0
  361. package/src/modules/status-bar.test.ts +50 -0
  362. package/src/modules/status-bar.ts +57 -0
  363. package/src/primitives/index.ts +119 -0
  364. package/src/primitives/shared.ts +191 -0
  365. package/src/render.test.ts +147 -0
  366. package/src/render.ts +224 -0
  367. package/src/renderer.test.ts +179 -0
  368. package/src/renderer.ts +407 -0
  369. package/src/services/color-scheme.service.ts +27 -0
  370. package/src/services/index.ts +2 -0
  371. package/src/services/services.test.ts +163 -0
  372. package/src/services/window-dimensions.service.ts +41 -0
@@ -0,0 +1,270 @@
1
+ // ImageBackground: the Angular lifecycle half. ImageBackground has NO native host of its own —
2
+ // it composes an outer View, an absolute-fill Image behind the user children, and the children
3
+ // on top. The composition math (the absolute-fill, the wrapper-dimension proxy onto the inner
4
+ // image, the imageStyle merge) lives framework-agnostic in @symbiote-native/components/renderImageBackground
5
+ // and is shared verbatim with React/Vue. React/Vue bridge the Descriptor it returns; Angular has
6
+ // no hyperscript bridge, so it composes with a TEMPLATE instead and reuses renderImageBackground
7
+ // ONLY to compute the inner image's merged style (read off the tree it returns) — the math stays
8
+ // shared, never reimplemented. The inner <Image> is the adapter's own Image component, which owns
9
+ // source resolution / a11y folding / event emission; ImageBackground forwards every Image prop onto
10
+ // it. `style` is the WRAPPER View style; `imageStyle` targets the inner image. Children paint AFTER
11
+ // the image (on top) via <ng-content>. The Angular twin of the React/Vue ImageBackground.
12
+
13
+ import {
14
+ CUSTOM_ELEMENTS_SCHEMA,
15
+ ChangeDetectionStrategy,
16
+ Component,
17
+ ElementRef,
18
+ EventEmitter,
19
+ inject,
20
+ Input,
21
+ Output,
22
+ } from '@angular/core';
23
+ import {
24
+ renderImageBackground,
25
+ resolveAccessibilityProps,
26
+ type IAccessibilityProps,
27
+ type IAccessibilityStateValue,
28
+ type IAriaProps,
29
+ type IImageProps,
30
+ type IImageSourceProp,
31
+ type IResizeMode,
32
+ } from '@symbiote-native/components';
33
+ import {
34
+ resolveClassName,
35
+ type IStyleProp,
36
+ type ISymbioteEvent,
37
+ type IViewStyle,
38
+ } from '@symbiote-native/engine';
39
+ import { Image } from './image';
40
+ import { anchorHostStyle, ViewHost } from '../primitives';
41
+
42
+ // Mirrors React's IImageBackgroundProps minus children (Angular takes children via <ng-content>):
43
+ // every forwarding Image prop flows onto the inner image; `style` is the WRAPPER View style and
44
+ // `imageStyle` the inner image's, per <prop_types_split_agnostic_vs_per_adapter>.
45
+ export interface IAngularImageBackgroundProps extends Omit<IImageProps, 'style'> {
46
+ style?: IStyleProp<IViewStyle>;
47
+ // A bare string resolves through the shared style registry, like `class` on the wrapper.
48
+ imageStyle?: IStyleProp<IViewStyle> | string;
49
+ }
50
+
51
+ // What the ImageBackground component itself takes as plain @Input()s: the full surface minus the
52
+ // inner Image's callback-shaped events, which it exposes as real @Output() EventEmitters instead
53
+ // (re-emitting the inner <Image>'s own already-converted outputs — see the template below).
54
+ export type IAngularImageBackgroundInputs = Omit<
55
+ IAngularImageBackgroundProps,
56
+ | 'onAccessibilityAction'
57
+ | 'onAccessibilityTap'
58
+ | 'onMagicTap'
59
+ | 'onAccessibilityEscape'
60
+ | 'onLoadStart'
61
+ | 'onLoad'
62
+ | 'onLoadEnd'
63
+ | 'onError'
64
+ | 'onProgress'
65
+ | 'onPartialLoad'
66
+ >;
67
+
68
+ @Component({
69
+ selector: 'ImageBackground',
70
+ standalone: true,
71
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
72
+ imports: [Image, ViewHost],
73
+ changeDetection: ChangeDetectionStrategy.OnPush,
74
+ template: `
75
+ <symbiote-view [style]="wrapperStyle">
76
+ <Image
77
+ [source]="source"
78
+ [defaultSource]="defaultSource"
79
+ [loadingIndicatorSource]="loadingIndicatorSource"
80
+ [style]="imageStyle"
81
+ [resizeMode]="resizeMode"
82
+ [resizeMethod]="resizeMethod"
83
+ [tintColor]="tintColor"
84
+ [blurRadius]="blurRadius"
85
+ [capInsets]="capInsets"
86
+ [fadeDuration]="fadeDuration"
87
+ [progressiveRenderingEnabled]="progressiveRenderingEnabled"
88
+ [src]="src"
89
+ [srcSet]="srcSet"
90
+ [alt]="alt"
91
+ [width]="width"
92
+ [height]="height"
93
+ [crossOrigin]="crossOrigin"
94
+ [referrerPolicy]="referrerPolicy"
95
+ [testID]="testID"
96
+ [nativeID]="nativeID"
97
+ [accessible]="accessible"
98
+ [accessibilityLabel]="folded.accessibilityLabel"
99
+ [accessibilityHint]="folded.accessibilityHint"
100
+ [accessibilityRole]="folded.accessibilityRole"
101
+ [accessibilityState]="folded.accessibilityState"
102
+ [accessibilityValue]="folded.accessibilityValue"
103
+ [accessibilityActions]="folded.accessibilityActions"
104
+ [accessibilityLabelledBy]="folded.accessibilityLabelledBy"
105
+ [importantForAccessibility]="folded.importantForAccessibility"
106
+ [accessibilityLiveRegion]="folded.accessibilityLiveRegion"
107
+ [screenReaderFocusable]="folded.screenReaderFocusable"
108
+ [accessibilityViewIsModal]="folded.accessibilityViewIsModal"
109
+ [accessibilityElementsHidden]="folded.accessibilityElementsHidden"
110
+ [accessibilityIgnoresInvertColors]="folded.accessibilityIgnoresInvertColors"
111
+ [accessibilityLanguage]="folded.accessibilityLanguage"
112
+ [accessibilityRespondsToUserInteraction]="folded.accessibilityRespondsToUserInteraction"
113
+ [accessibilityShowsLargeContentViewer]="folded.accessibilityShowsLargeContentViewer"
114
+ [accessibilityLargeContentTitle]="folded.accessibilityLargeContentTitle"
115
+ (loadStart)="loadStart.emit($event)"
116
+ (load)="load.emit($event)"
117
+ (loadEnd)="loadEnd.emit($event)"
118
+ (error)="error.emit($event)"
119
+ (progress)="progress.emit($event)"
120
+ (partialLoad)="partialLoad.emit($event)"
121
+ (accessibilityAction)="accessibilityAction.emit($event)"
122
+ (accessibilityTap)="accessibilityTap.emit($event)"
123
+ (magicTap)="magicTap.emit($event)"
124
+ (accessibilityEscape)="accessibilityEscape.emit($event)"
125
+ />
126
+ <ng-content></ng-content>
127
+ </symbiote-view>
128
+ `,
129
+ })
130
+ export class ImageBackground implements IAngularImageBackgroundInputs {
131
+ // The inner <Image>'s events as real Angular events, re-emitted verbatim through
132
+ // ImageBackground's own outputs: `(load)="load.emit($event)"`, not `[onLoad]="onLoad"`.
133
+ @Output() readonly accessibilityAction = new EventEmitter<ISymbioteEvent>();
134
+ @Output() readonly accessibilityTap = new EventEmitter<ISymbioteEvent>();
135
+ @Output() readonly magicTap = new EventEmitter<ISymbioteEvent>();
136
+ @Output() readonly accessibilityEscape = new EventEmitter<ISymbioteEvent>();
137
+ @Output() readonly loadStart = new EventEmitter<ISymbioteEvent>();
138
+ @Output() readonly load = new EventEmitter<ISymbioteEvent>();
139
+ @Output() readonly loadEnd = new EventEmitter<ISymbioteEvent>();
140
+ @Output() readonly error = new EventEmitter<ISymbioteEvent>();
141
+ @Output() readonly progress = new EventEmitter<ISymbioteEvent>();
142
+ @Output() readonly partialLoad = new EventEmitter<ISymbioteEvent>();
143
+ @Input() source?: IImageSourceProp;
144
+ @Input() defaultSource?: IImageSourceProp;
145
+ @Input() loadingIndicatorSource?: IImageSourceProp;
146
+ @Input() style?: IStyleProp<IViewStyle>;
147
+ @Input('imageStyle') imageStyleValue?: IStyleProp<IViewStyle> | string;
148
+ @Input() resizeMode?: IResizeMode;
149
+ @Input() resizeMethod?: IImageProps['resizeMethod'];
150
+ @Input() tintColor?: string;
151
+ @Input() blurRadius?: number;
152
+ @Input() capInsets?: IImageProps['capInsets'];
153
+ @Input() fadeDuration?: number;
154
+ @Input() progressiveRenderingEnabled?: boolean;
155
+ @Input() src?: string;
156
+ @Input() srcSet?: string;
157
+ @Input() alt?: string;
158
+ @Input() width?: number;
159
+ @Input() height?: number;
160
+ @Input() crossOrigin?: 'anonymous' | 'use-credentials';
161
+ @Input() referrerPolicy?: string;
162
+ @Input() testID?: string;
163
+ @Input() nativeID?: string;
164
+ @Input() accessible?: boolean;
165
+ @Input() accessibilityLabel?: string;
166
+ @Input() accessibilityHint?: string;
167
+ @Input() accessibilityRole?: IAccessibilityProps['accessibilityRole'];
168
+ @Input() accessibilityState?: IAccessibilityStateValue;
169
+ @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
170
+ @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
171
+ @Input() accessibilityLabelledBy?: string | string[];
172
+ @Input() importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
173
+ @Input() accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
174
+ @Input() screenReaderFocusable?: boolean;
175
+ @Input() accessibilityViewIsModal?: boolean;
176
+ @Input() accessibilityElementsHidden?: boolean;
177
+ @Input() accessibilityIgnoresInvertColors?: boolean;
178
+ @Input() accessibilityLanguage?: string;
179
+ @Input() accessibilityRespondsToUserInteraction?: boolean;
180
+ @Input() accessibilityShowsLargeContentViewer?: boolean;
181
+ @Input() accessibilityLargeContentTitle?: string;
182
+ @Input() role?: IAriaProps['role'];
183
+ @Input('aria-label') ariaLabel?: string;
184
+ @Input('aria-labelledby') ariaLabelledBy?: string;
185
+ @Input('aria-live') ariaLive?: IAriaProps['aria-live'];
186
+ @Input('aria-hidden') ariaHidden?: boolean;
187
+ @Input('aria-busy') ariaBusy?: boolean;
188
+ @Input('aria-checked') ariaChecked?: boolean | 'mixed';
189
+ @Input('aria-disabled') ariaDisabled?: boolean;
190
+ @Input('aria-expanded') ariaExpanded?: boolean;
191
+ @Input('aria-selected') ariaSelected?: boolean;
192
+ @Input('aria-modal') ariaModal?: boolean;
193
+ @Input('aria-valuemax') ariaValueMax?: number;
194
+ @Input('aria-valuemin') ariaValueMin?: number;
195
+ @Input('aria-valuenow') ariaValueNow?: number;
196
+ @Input('aria-valuetext') ariaValueText?: string;
197
+
198
+ // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
199
+ // onto (see anchorHostStyle's doc comment) — NOT the inner `symbiote-view [style]="wrapperStyle"`
200
+ // one level down. Merged FIRST so the explicit `style` @Input still wins (flattenStyle's
201
+ // later-wins collapse), mirroring every other composed component's anchor merge. `imageStyle`
202
+ // below stays untouched per the ImageBackground-specific nuance: it targets the inner image, not
203
+ // this component's own root.
204
+ private readonly elementRef = inject(ElementRef);
205
+
206
+ get wrapperStyle(): unknown {
207
+ return [anchorHostStyle(this.elementRef), this.style];
208
+ }
209
+
210
+ // renderImageBackground owns the absolute-fill + wrapper-dimension-proxy + imageStyle merge
211
+ // (shared verbatim with React/Vue); read the inner image Descriptor's style off the tree it
212
+ // returns rather than reimplementing it. Only style/imageStyle drive that merge, so the image
213
+ // bag is empty here — the inner <Image> below resolves source / a11y / events on its own.
214
+ get imageStyle(): IStyleProp<IViewStyle> | undefined {
215
+ // imageStyle targets the INNER image (renderImageBackground's own field); resolve a
216
+ // class-name string here, before it flows into the merge.
217
+ const resolvedImageStyleValue =
218
+ typeof this.imageStyleValue === 'string'
219
+ ? resolveClassName(this.imageStyleValue)
220
+ : this.imageStyleValue;
221
+ const inner = renderImageBackground({
222
+ style: this.style,
223
+ imageStyle: resolvedImageStyleValue,
224
+ image: { passthrough: {} },
225
+ }).children[0];
226
+ return typeof inner === 'string'
227
+ ? undefined
228
+ : (inner.props.style as IStyleProp<IViewStyle> | undefined);
229
+ }
230
+
231
+ // Fold the web aria-*/role aliases into the canonical accessibility* props once per render, so the
232
+ // inner image never sees an aria-* key (native ignores them) — the shared transform every adapter
233
+ // runs. The inner <Image> re-runs the same fold idempotently over the already-folded props.
234
+ get folded(): Partial<IAngularImageBackgroundProps> {
235
+ return resolveAccessibilityProps({
236
+ accessibilityLabel: this.accessibilityLabel,
237
+ accessibilityHint: this.accessibilityHint,
238
+ accessibilityRole: this.accessibilityRole,
239
+ accessibilityState: this.accessibilityState,
240
+ accessibilityValue: this.accessibilityValue,
241
+ accessibilityActions: this.accessibilityActions,
242
+ accessibilityLabelledBy: this.accessibilityLabelledBy,
243
+ importantForAccessibility: this.importantForAccessibility,
244
+ accessibilityLiveRegion: this.accessibilityLiveRegion,
245
+ screenReaderFocusable: this.screenReaderFocusable,
246
+ accessibilityViewIsModal: this.accessibilityViewIsModal,
247
+ accessibilityElementsHidden: this.accessibilityElementsHidden,
248
+ accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
249
+ accessibilityLanguage: this.accessibilityLanguage,
250
+ accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
251
+ accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
252
+ accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
253
+ role: this.role,
254
+ 'aria-label': this.ariaLabel,
255
+ 'aria-labelledby': this.ariaLabelledBy,
256
+ 'aria-live': this.ariaLive,
257
+ 'aria-hidden': this.ariaHidden,
258
+ 'aria-busy': this.ariaBusy,
259
+ 'aria-checked': this.ariaChecked,
260
+ 'aria-disabled': this.ariaDisabled,
261
+ 'aria-expanded': this.ariaExpanded,
262
+ 'aria-selected': this.ariaSelected,
263
+ 'aria-modal': this.ariaModal,
264
+ 'aria-valuemax': this.ariaValueMax,
265
+ 'aria-valuemin': this.ariaValueMin,
266
+ 'aria-valuenow': this.ariaValueNow,
267
+ 'aria-valuetext': this.ariaValueText,
268
+ });
269
+ }
270
+ }
@@ -0,0 +1,43 @@
1
+ import '@angular/compiler';
2
+ import { Component } from '@angular/core';
3
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
+ import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
5
+ import { installFabric } from '@symbiote-native/test-utils';
6
+
7
+ import { mount, unmount } from '../render';
8
+ import { InputAccessoryView } from './input-accessory-view';
9
+
10
+ const ROOT_TAG = 913;
11
+ const fabric = installFabric();
12
+
13
+ @Component({
14
+ selector: 'symbiote-iav-host',
15
+ standalone: true,
16
+ imports: [InputAccessoryView],
17
+ template: `
18
+ <InputAccessoryView [testID]="'iav'" class="toolbar">
19
+ <symbiote-text>Hello</symbiote-text>
20
+ </InputAccessoryView>
21
+ `,
22
+ })
23
+ class InputAccessoryViewHostFixture {}
24
+
25
+ beforeEach(() => {
26
+ fabric.reset();
27
+ });
28
+ afterEach(() => {
29
+ unmount(ROOT_TAG);
30
+ clearGlobalStyles();
31
+ });
32
+
33
+ describe('InputAccessoryView', () => {
34
+ it('resolves a class= on the InputAccessoryView use site onto the real committed view, not the anchor', async () => {
35
+ registerStyles({ toolbar: { backgroundColor: 'orange' } });
36
+
37
+ mount(ROOT_TAG, InputAccessoryViewHostFixture);
38
+ await new Promise<void>(resolve => setTimeout(resolve, 0));
39
+
40
+ const node = fabric.find(n => n.props.testID === 'iav');
41
+ expect(node?.props.backgroundColor).toBe('orange');
42
+ });
43
+ });
@@ -0,0 +1,191 @@
1
+ // InputAccessoryView, the Angular lifecycle half (iOS). A real Fabric host node
2
+ // (RCTInputAccessoryView) that docks its content above the keyboard; a TextInput points at it by
3
+ // nativeID through its inputAccessoryViewID. There is no JS-side translation — style / nativeID /
4
+ // backgroundColor map straight onto the intrinsic, children via <ng-content> — so this folds
5
+ // aria/role through the shared resolveAccessibilityProps and binds the rest onto the host. The
6
+ // Angular twin of the React/Vue InputAccessoryView. No platform branch, so this stays flat.
7
+
8
+ import {
9
+ CUSTOM_ELEMENTS_SCHEMA,
10
+ ChangeDetectionStrategy,
11
+ Component,
12
+ ElementRef,
13
+ EventEmitter,
14
+ inject,
15
+ Input,
16
+ Output,
17
+ } from '@angular/core';
18
+ import {
19
+ resolveAccessibilityProps,
20
+ type IAccessibilityProps,
21
+ type IAccessibilityStateValue,
22
+ type IAriaProps,
23
+ } from '@symbiote-native/components';
24
+ import type { IStyleProp, ISymbioteEvent, IViewStyle } from '@symbiote-native/engine';
25
+ import { anchorHostStyle, InputAccessoryViewHost, SymbioteHostPropsDirective } from '../primitives';
26
+
27
+ // Angular infers an `(event)` binding's $event as the DOM Event for a custom-schema element,
28
+ // so each handler enters as `unknown` and is narrowed here before reaching a typed callback.
29
+ function isSymbioteEvent(value: unknown): value is ISymbioteEvent {
30
+ return typeof value === 'object' && value !== null && 'nativeEvent' in value;
31
+ }
32
+
33
+ // Mirrors React's IInputAccessoryViewProps minus children (Angular takes children via
34
+ // <ng-content>), declared per-adapter over the shared a11y base.
35
+ export interface IAngularInputAccessoryViewProps extends IAccessibilityProps, IAriaProps {
36
+ // The id a TextInput's inputAccessoryViewID points at to dock above its keyboard.
37
+ nativeID?: string;
38
+ backgroundColor?: string;
39
+ style?: IStyleProp<IViewStyle>;
40
+ }
41
+
42
+ // What the component itself takes as plain @Input()s: the full surface minus the accessibility
43
+ // callbacks, which it exposes as real @Output() EventEmitters instead (see the class below),
44
+ // mirroring Pressable's IAngularPressableInputs split.
45
+ export type IAngularInputAccessoryViewInputs = Omit<
46
+ IAngularInputAccessoryViewProps,
47
+ 'onAccessibilityAction' | 'onAccessibilityTap' | 'onMagicTap' | 'onAccessibilityEscape'
48
+ >;
49
+
50
+ @Component({
51
+ selector: 'InputAccessoryView',
52
+ standalone: true,
53
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
54
+ imports: [InputAccessoryViewHost, SymbioteHostPropsDirective],
55
+ changeDetection: ChangeDetectionStrategy.OnPush,
56
+ template: `
57
+ <symbiote-input-accessory-view
58
+ [symbioteHostProps]="hostProps"
59
+ (accessibilityAction)="emit(accessibilityAction, $event)"
60
+ (accessibilityTap)="emit(accessibilityTap, $event)"
61
+ (magicTap)="emit(magicTap, $event)"
62
+ (accessibilityEscape)="emit(accessibilityEscape, $event)"
63
+ >
64
+ <ng-content></ng-content>
65
+ </symbiote-input-accessory-view>
66
+ `,
67
+ })
68
+ export class InputAccessoryView implements IAngularInputAccessoryViewInputs {
69
+ @Input() nativeID?: string;
70
+ @Input() backgroundColor?: string;
71
+ @Input() style?: IStyleProp<IViewStyle>;
72
+ @Output() readonly accessibilityAction = new EventEmitter<ISymbioteEvent>();
73
+ @Output() readonly accessibilityTap = new EventEmitter<ISymbioteEvent>();
74
+ @Output() readonly magicTap = new EventEmitter<ISymbioteEvent>();
75
+ @Output() readonly accessibilityEscape = new EventEmitter<ISymbioteEvent>();
76
+ @Input() testID?: string;
77
+ @Input() accessible?: boolean;
78
+ @Input() accessibilityLabel?: string;
79
+ @Input() accessibilityHint?: string;
80
+ @Input() accessibilityRole?: IAccessibilityProps['accessibilityRole'];
81
+ @Input() accessibilityState?: IAccessibilityStateValue;
82
+ @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
83
+ @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
84
+ @Input() accessibilityLabelledBy?: string | string[];
85
+ @Input() importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
86
+ @Input() accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
87
+ @Input() screenReaderFocusable?: boolean;
88
+ @Input() accessibilityViewIsModal?: boolean;
89
+ @Input() accessibilityElementsHidden?: boolean;
90
+ @Input() accessibilityIgnoresInvertColors?: boolean;
91
+ @Input() accessibilityLanguage?: string;
92
+ @Input() accessibilityRespondsToUserInteraction?: boolean;
93
+ @Input() accessibilityShowsLargeContentViewer?: boolean;
94
+ @Input() accessibilityLargeContentTitle?: string;
95
+ @Input() role?: IAriaProps['role'];
96
+ @Input('aria-label') ariaLabel?: string;
97
+ @Input('aria-labelledby') ariaLabelledBy?: string;
98
+ @Input('aria-live') ariaLive?: IAriaProps['aria-live'];
99
+ @Input('aria-hidden') ariaHidden?: boolean;
100
+ @Input('aria-busy') ariaBusy?: boolean;
101
+ @Input('aria-checked') ariaChecked?: boolean | 'mixed';
102
+ @Input('aria-disabled') ariaDisabled?: boolean;
103
+ @Input('aria-expanded') ariaExpanded?: boolean;
104
+ @Input('aria-selected') ariaSelected?: boolean;
105
+ @Input('aria-modal') ariaModal?: boolean;
106
+ @Input('aria-valuemax') ariaValueMax?: number;
107
+ @Input('aria-valuemin') ariaValueMin?: number;
108
+ @Input('aria-valuenow') ariaValueNow?: number;
109
+ @Input('aria-valuetext') ariaValueText?: string;
110
+
111
+ // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
112
+ // onto (see anchorHostStyle's doc comment). InputAccessoryView has no inner ViewChild, so this
113
+ // is the only ElementRef in the class.
114
+ private readonly elementRef = inject(ElementRef);
115
+
116
+ // Forward an engine event to the matching @Output(), narrowing the template's untyped $event.
117
+ emit(emitter: EventEmitter<ISymbioteEvent>, event: unknown): void {
118
+ if (isSymbioteEvent(event)) emitter.emit(event);
119
+ }
120
+
121
+ // Folds every host-bound prop into one record for `symbioteHostProps` — the same fields the
122
+ // template used to bind one-by-one, assembled locally (no shared renderX for this component yet).
123
+ // The anchor's class-derived style goes FIRST, this component's own explicit `style` @Input
124
+ // SECOND — flattenStyle's later-wins collapse keeps an explicit [style] winning over its class.
125
+ get hostProps(): Record<string, unknown> {
126
+ const folded = this.folded;
127
+ return {
128
+ style: [anchorHostStyle(this.elementRef), this.style],
129
+ nativeID: this.nativeID,
130
+ backgroundColor: this.backgroundColor,
131
+ testID: this.testID,
132
+ accessible: this.accessible,
133
+ accessibilityLabel: folded.accessibilityLabel,
134
+ accessibilityHint: folded.accessibilityHint,
135
+ accessibilityRole: folded.accessibilityRole,
136
+ accessibilityState: folded.accessibilityState,
137
+ accessibilityValue: folded.accessibilityValue,
138
+ accessibilityActions: folded.accessibilityActions,
139
+ accessibilityLabelledBy: folded.accessibilityLabelledBy,
140
+ importantForAccessibility: folded.importantForAccessibility,
141
+ accessibilityLiveRegion: folded.accessibilityLiveRegion,
142
+ screenReaderFocusable: folded.screenReaderFocusable,
143
+ accessibilityViewIsModal: folded.accessibilityViewIsModal,
144
+ accessibilityElementsHidden: folded.accessibilityElementsHidden,
145
+ accessibilityIgnoresInvertColors: folded.accessibilityIgnoresInvertColors,
146
+ accessibilityLanguage: folded.accessibilityLanguage,
147
+ accessibilityRespondsToUserInteraction: folded.accessibilityRespondsToUserInteraction,
148
+ accessibilityShowsLargeContentViewer: folded.accessibilityShowsLargeContentViewer,
149
+ accessibilityLargeContentTitle: folded.accessibilityLargeContentTitle,
150
+ };
151
+ }
152
+
153
+ // Fold the web aria-*/role aliases into the canonical accessibility* props once per render, so
154
+ // the host node never sees an aria-* key (native ignores them) — the shared transform.
155
+ get folded(): Partial<IAngularInputAccessoryViewProps> {
156
+ return resolveAccessibilityProps({
157
+ accessibilityLabel: this.accessibilityLabel,
158
+ accessibilityHint: this.accessibilityHint,
159
+ accessibilityRole: this.accessibilityRole,
160
+ accessibilityState: this.accessibilityState,
161
+ accessibilityValue: this.accessibilityValue,
162
+ accessibilityActions: this.accessibilityActions,
163
+ accessibilityLabelledBy: this.accessibilityLabelledBy,
164
+ importantForAccessibility: this.importantForAccessibility,
165
+ accessibilityLiveRegion: this.accessibilityLiveRegion,
166
+ screenReaderFocusable: this.screenReaderFocusable,
167
+ accessibilityViewIsModal: this.accessibilityViewIsModal,
168
+ accessibilityElementsHidden: this.accessibilityElementsHidden,
169
+ accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
170
+ accessibilityLanguage: this.accessibilityLanguage,
171
+ accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
172
+ accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
173
+ accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
174
+ role: this.role,
175
+ 'aria-label': this.ariaLabel,
176
+ 'aria-labelledby': this.ariaLabelledBy,
177
+ 'aria-live': this.ariaLive,
178
+ 'aria-hidden': this.ariaHidden,
179
+ 'aria-busy': this.ariaBusy,
180
+ 'aria-checked': this.ariaChecked,
181
+ 'aria-disabled': this.ariaDisabled,
182
+ 'aria-expanded': this.ariaExpanded,
183
+ 'aria-selected': this.ariaSelected,
184
+ 'aria-modal': this.ariaModal,
185
+ 'aria-valuemax': this.ariaValueMax,
186
+ 'aria-valuemin': this.ariaValueMin,
187
+ 'aria-valuenow': this.ariaValueNow,
188
+ 'aria-valuetext': this.ariaValueText,
189
+ });
190
+ }
191
+ }
@@ -0,0 +1,54 @@
1
+ import '@angular/compiler';
2
+ import { Component } from '@angular/core';
3
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
+ import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
5
+ import { installFabric } from '@symbiote-native/test-utils';
6
+
7
+ import { mount, unmount } from '../render';
8
+ import { KeyboardAvoidingView } from './keyboard-avoiding-view';
9
+
10
+ const ROOT_TAG = 911;
11
+ const fabric = installFabric();
12
+
13
+ // KeyboardAvoidingView's ngOnInit subscribes to the Keyboard module, which installs the
14
+ // bridgeless device-event hub on first use — needs a fake RN$registerCallableModule so
15
+ // installDeviceEventHub() doesn't throw (core/engine/src/native-events.ts). No native event is
16
+ // actually emitted in this test, only the subscribe/unsubscribe lifecycle runs.
17
+ Object.assign(globalThis, {
18
+ RN$registerCallableModule: (
19
+ _name: string,
20
+ _factory: () => { emit: (eventType: string, ...args: unknown[]) => void },
21
+ ): void => {},
22
+ });
23
+
24
+ @Component({
25
+ selector: 'symbiote-kav-host',
26
+ standalone: true,
27
+ imports: [KeyboardAvoidingView],
28
+ template: `
29
+ <KeyboardAvoidingView [testID]="'kav'" class="panel">
30
+ <symbiote-text>Hello</symbiote-text>
31
+ </KeyboardAvoidingView>
32
+ `,
33
+ })
34
+ class KeyboardAvoidingViewHostFixture {}
35
+
36
+ beforeEach(() => {
37
+ fabric.reset();
38
+ });
39
+ afterEach(() => {
40
+ unmount(ROOT_TAG);
41
+ clearGlobalStyles();
42
+ });
43
+
44
+ describe('KeyboardAvoidingView', () => {
45
+ it('resolves a class= on the KeyboardAvoidingView use site onto the real committed view, not the anchor', async () => {
46
+ registerStyles({ panel: { backgroundColor: 'teal' } });
47
+
48
+ mount(ROOT_TAG, KeyboardAvoidingViewHostFixture);
49
+ await new Promise<void>(resolve => setTimeout(resolve, 0));
50
+
51
+ const node = fabric.find(n => n.props.testID === 'kav');
52
+ expect(node?.props.backgroundColor).toBe('teal');
53
+ });
54
+ });