@symbiote-native/angular 1.0.0 → 2.0.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 (248) hide show
  1. package/README.md +13 -10
  2. package/babel-register-composed.cjs +41 -19
  3. package/bin/symbiote-angular-dev.cjs +16 -4
  4. package/build/angular/anchor-host-registry.js +1 -17
  5. package/build/angular/anchor-host-registry.js.map +1 -1
  6. package/build/angular/change-detection-flush.d.ts +31 -0
  7. package/build/angular/change-detection-flush.js +110 -0
  8. package/build/angular/change-detection-flush.js.map +1 -0
  9. package/build/angular/components/activity-indicator-props.d.ts +2 -0
  10. package/build/angular/components/activity-indicator-props.js +2 -0
  11. package/build/angular/components/activity-indicator-props.js.map +1 -0
  12. package/build/angular/components/button-props.d.ts +2 -0
  13. package/build/angular/components/button-props.js +2 -0
  14. package/build/angular/components/button-props.js.map +1 -0
  15. package/build/angular/components/flat-list/index.d.ts +2 -1
  16. package/build/angular/components/flat-list/index.js +22 -10
  17. package/build/angular/components/flat-list/index.js.map +1 -1
  18. package/build/angular/components/image-background-props.d.ts +6 -0
  19. package/build/angular/components/image-background-props.js +2 -0
  20. package/build/angular/components/image-background-props.js.map +1 -0
  21. package/build/angular/components/{image/shared.d.ts → image-shared.d.ts} +1 -1
  22. package/build/angular/components/{image/shared.js → image-shared.js} +7 -2
  23. package/build/angular/components/image-shared.js.map +1 -0
  24. package/build/angular/components/input-accessory-view-props.d.ts +7 -0
  25. package/build/angular/components/input-accessory-view-props.js +9 -0
  26. package/build/angular/components/input-accessory-view-props.js.map +1 -0
  27. package/build/angular/components/keyboard-avoiding-view/index.js +11 -17
  28. package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -1
  29. package/build/angular/components/modal/index.d.ts +1 -0
  30. package/build/angular/components/modal/index.js +19 -12
  31. package/build/angular/components/modal/index.js.map +1 -1
  32. package/build/angular/components/pressable-props.d.ts +32 -0
  33. package/build/angular/components/pressable-props.js +11 -0
  34. package/build/angular/components/pressable-props.js.map +1 -0
  35. package/build/angular/components/refresh-control-props.d.ts +16 -0
  36. package/build/angular/components/refresh-control-props.js +14 -0
  37. package/build/angular/components/refresh-control-props.js.map +1 -0
  38. package/build/angular/components/safe-area-view-props.d.ts +7 -0
  39. package/build/angular/components/safe-area-view-props.js +11 -0
  40. package/build/angular/components/safe-area-view-props.js.map +1 -0
  41. package/build/angular/components/scroll-view-props.d.ts +76 -0
  42. package/build/angular/components/scroll-view-props.js +18 -0
  43. package/build/angular/components/scroll-view-props.js.map +1 -0
  44. package/build/angular/components/text-input-props.d.ts +45 -0
  45. package/build/angular/components/text-input-props.js +18 -0
  46. package/build/angular/components/text-input-props.js.map +1 -0
  47. package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.d.ts +6 -0
  48. package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.js +2 -0
  49. package/build/angular/components/touchable-native-feedback/touchable-native-feedback-props.js.map +1 -0
  50. package/build/angular/components/touchable-props.d.ts +14 -0
  51. package/build/angular/components/touchable-props.js +13 -0
  52. package/build/angular/components/touchable-props.js.map +1 -0
  53. package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.d.ts +3 -0
  54. package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.js +2 -0
  55. package/build/angular/components/touchable-without-feedback/touchable-without-feedback-props.js.map +1 -0
  56. package/build/angular/components/virtualized-list/index.d.ts +5 -1
  57. package/build/angular/components/virtualized-list/index.js +366 -280
  58. package/build/angular/components/virtualized-list/index.js.map +1 -1
  59. package/build/angular/components.d.ts +20 -26
  60. package/build/angular/components.js +12 -14
  61. package/build/angular/components.js.map +1 -1
  62. package/build/angular/create-portal/index.d.ts +2 -2
  63. package/build/angular/create-portal/index.js +5 -5
  64. package/build/angular/create-tunnel/index.js +1 -1
  65. package/build/angular/element-props.d.ts +53 -0
  66. package/build/angular/element-props.js +2 -0
  67. package/build/angular/element-props.js.map +1 -0
  68. package/build/angular/elements.d.ts +528 -0
  69. package/build/angular/elements.js +1444 -0
  70. package/build/angular/elements.js.map +1 -0
  71. package/build/angular/host-instance/index.js +1 -1
  72. package/build/angular/index.d.ts +4 -2
  73. package/build/angular/index.js +15 -1
  74. package/build/angular/index.js.map +1 -1
  75. package/build/angular/modules/animated/create-animated-component.d.ts +5 -6
  76. package/build/angular/modules/animated/create-animated-component.js +60 -73
  77. package/build/angular/modules/animated/create-animated-component.js.map +1 -1
  78. package/build/angular/modules/animated/index.js +1 -1
  79. package/build/angular/modules/animated/index.js.map +1 -1
  80. package/build/angular/modules/image/index.d.ts +3 -0
  81. package/build/angular/modules/image/index.js +16 -0
  82. package/build/angular/modules/image/index.js.map +1 -0
  83. package/build/angular/primitives/index.d.ts +18 -18
  84. package/build/angular/primitives/index.js +40 -36
  85. package/build/angular/primitives/index.js.map +1 -1
  86. package/build/angular/primitives/shared.d.ts +2 -3
  87. package/build/angular/primitives/shared.js +8 -53
  88. package/build/angular/primitives/shared.js.map +1 -1
  89. package/build/angular/register.d.ts +1 -1
  90. package/build/angular/register.js +12 -31
  91. package/build/angular/register.js.map +1 -1
  92. package/build/angular/render/index.js +3 -3
  93. package/build/angular/render/index.js.map +1 -1
  94. package/build/angular/renderer/index.js +113 -67
  95. package/build/angular/renderer/index.js.map +1 -1
  96. package/build/angular/renderer/value-change.d.ts +2 -0
  97. package/build/angular/renderer/value-change.js +9 -0
  98. package/build/angular/renderer/value-change.js.map +1 -0
  99. package/metro-config.cjs +23 -5
  100. package/metro-css-parser.cjs +2 -1
  101. package/package.json +5 -14
  102. package/src/anchor-host-registry.ts +1 -17
  103. package/src/change-detection-flush.ts +120 -0
  104. package/src/components/activity-indicator-props.ts +21 -0
  105. package/src/components/button-props.ts +26 -0
  106. package/src/components/flat-list/index.ts +12 -4
  107. package/src/components/image-background-props.ts +24 -0
  108. package/src/components/{image/shared.ts → image-shared.ts} +6 -1
  109. package/src/components/input-accessory-view-props.ts +21 -0
  110. package/src/components/keyboard-avoiding-view/index.ts +6 -9
  111. package/src/components/modal/index.ts +15 -7
  112. package/src/components/pressable-props.ts +73 -0
  113. package/src/components/refresh-control-props.ts +43 -0
  114. package/src/components/safe-area-view-props.ts +28 -0
  115. package/src/components/scroll-view-props.ts +109 -0
  116. package/src/components/text-input-props.ts +72 -0
  117. package/src/components/touchable-native-feedback/touchable-native-feedback-props.ts +23 -0
  118. package/src/components/touchable-props.ts +30 -0
  119. package/src/components/touchable-without-feedback/touchable-without-feedback-props.ts +21 -0
  120. package/src/components/virtualized-list/index.ts +239 -156
  121. package/src/components.ts +84 -35
  122. package/src/create-portal/index.ts +5 -5
  123. package/src/create-tunnel/index.ts +1 -1
  124. package/src/diagnostics.ts +1 -1
  125. package/src/element-props.ts +90 -0
  126. package/src/elements.ts +919 -0
  127. package/src/host-instance/index.ts +1 -1
  128. package/src/index.ts +52 -15
  129. package/src/modules/animated/create-animated-component.ts +50 -55
  130. package/src/modules/animated/index.ts +1 -1
  131. package/src/modules/image/index.ts +18 -0
  132. package/src/primitives/index.ts +22 -18
  133. package/src/primitives/shared.ts +11 -44
  134. package/src/register.ts +12 -40
  135. package/src/render/index.ts +3 -3
  136. package/src/renderer/index.ts +122 -73
  137. package/src/renderer/value-change.ts +8 -0
  138. package/babel-lower-host-primitives.cjs +0 -636
  139. package/build/angular/components/activity-indicator/index.android.d.ts +0 -13
  140. package/build/angular/components/activity-indicator/index.android.js +0 -29
  141. package/build/angular/components/activity-indicator/index.android.js.map +0 -1
  142. package/build/angular/components/activity-indicator/index.d.ts +0 -1
  143. package/build/angular/components/activity-indicator/index.ios.d.ts +0 -9
  144. package/build/angular/components/activity-indicator/index.ios.js +0 -26
  145. package/build/angular/components/activity-indicator/index.ios.js.map +0 -1
  146. package/build/angular/components/activity-indicator/index.js +0 -4
  147. package/build/angular/components/activity-indicator/index.js.map +0 -1
  148. package/build/angular/components/activity-indicator/shared.d.ts +0 -67
  149. package/build/angular/components/activity-indicator/shared.js +0 -260
  150. package/build/angular/components/activity-indicator/shared.js.map +0 -1
  151. package/build/angular/components/button.d.ts +0 -68
  152. package/build/angular/components/button.js +0 -360
  153. package/build/angular/components/button.js.map +0 -1
  154. package/build/angular/components/image/index.android.d.ts +0 -15
  155. package/build/angular/components/image/index.android.js +0 -83
  156. package/build/angular/components/image/index.android.js.map +0 -1
  157. package/build/angular/components/image/index.d.ts +0 -1
  158. package/build/angular/components/image/index.ios.d.ts +0 -15
  159. package/build/angular/components/image/index.ios.js +0 -83
  160. package/build/angular/components/image/index.ios.js.map +0 -1
  161. package/build/angular/components/image/index.js +0 -3
  162. package/build/angular/components/image/index.js.map +0 -1
  163. package/build/angular/components/image/shared.js.map +0 -1
  164. package/build/angular/components/image-background.d.ts +0 -85
  165. package/build/angular/components/image-background.js +0 -443
  166. package/build/angular/components/image-background.js.map +0 -1
  167. package/build/angular/components/input-accessory-view/index.d.ts +0 -66
  168. package/build/angular/components/input-accessory-view/index.js +0 -287
  169. package/build/angular/components/input-accessory-view/index.js.map +0 -1
  170. package/build/angular/components/pressable/index.d.ts +0 -134
  171. package/build/angular/components/pressable/index.js +0 -514
  172. package/build/angular/components/pressable/index.js.map +0 -1
  173. package/build/angular/components/refresh-control/index.d.ts +0 -91
  174. package/build/angular/components/refresh-control/index.js +0 -382
  175. package/build/angular/components/refresh-control/index.js.map +0 -1
  176. package/build/angular/components/safe-area-view/index.d.ts +0 -64
  177. package/build/angular/components/safe-area-view/index.js +0 -287
  178. package/build/angular/components/safe-area-view/index.js.map +0 -1
  179. package/build/angular/components/scroll-view/index.android.d.ts +0 -20
  180. package/build/angular/components/scroll-view/index.android.js +0 -262
  181. package/build/angular/components/scroll-view/index.android.js.map +0 -1
  182. package/build/angular/components/scroll-view/index.d.ts +0 -3
  183. package/build/angular/components/scroll-view/index.ios.d.ts +0 -8
  184. package/build/angular/components/scroll-view/index.ios.js +0 -92
  185. package/build/angular/components/scroll-view/index.ios.js.map +0 -1
  186. package/build/angular/components/scroll-view/index.js +0 -6
  187. package/build/angular/components/scroll-view/index.js.map +0 -1
  188. package/build/angular/components/scroll-view/projection.d.ts +0 -67
  189. package/build/angular/components/scroll-view/projection.js +0 -560
  190. package/build/angular/components/scroll-view/projection.js.map +0 -1
  191. package/build/angular/components/scroll-view/shared.d.ts +0 -241
  192. package/build/angular/components/scroll-view/shared.js +0 -848
  193. package/build/angular/components/scroll-view/shared.js.map +0 -1
  194. package/build/angular/components/scroll-view/sticky-header.d.ts +0 -40
  195. package/build/angular/components/scroll-view/sticky-header.js +0 -224
  196. package/build/angular/components/scroll-view/sticky-header.js.map +0 -1
  197. package/build/angular/components/switch/index.android.d.ts +0 -24
  198. package/build/angular/components/switch/index.android.js +0 -112
  199. package/build/angular/components/switch/index.android.js.map +0 -1
  200. package/build/angular/components/switch/index.d.ts +0 -1
  201. package/build/angular/components/switch/index.ios.d.ts +0 -23
  202. package/build/angular/components/switch/index.ios.js +0 -111
  203. package/build/angular/components/switch/index.ios.js.map +0 -1
  204. package/build/angular/components/switch/index.js +0 -4
  205. package/build/angular/components/switch/index.js.map +0 -1
  206. package/build/angular/components/switch/shared.d.ts +0 -49
  207. package/build/angular/components/switch/shared.js +0 -191
  208. package/build/angular/components/switch/shared.js.map +0 -1
  209. package/build/angular/components/text-input.d.ts +0 -167
  210. package/build/angular/components/text-input.js +0 -684
  211. package/build/angular/components/text-input.js.map +0 -1
  212. package/build/angular/components/touchable/index.d.ts +0 -283
  213. package/build/angular/components/touchable/index.js +0 -1453
  214. package/build/angular/components/touchable/index.js.map +0 -1
  215. package/build/angular/components/touchable-native-feedback/index.d.ts +0 -87
  216. package/build/angular/components/touchable-native-feedback/index.js +0 -409
  217. package/build/angular/components/touchable-native-feedback/index.js.map +0 -1
  218. package/build/angular/state-style.d.ts +0 -9
  219. package/build/angular/state-style.js +0 -39
  220. package/build/angular/state-style.js.map +0 -1
  221. package/metro-transformer.cjs +0 -69
  222. package/src/components/activity-indicator/index.android.ts +0 -23
  223. package/src/components/activity-indicator/index.ios.ts +0 -21
  224. package/src/components/activity-indicator/index.ts +0 -4
  225. package/src/components/activity-indicator/shared.ts +0 -225
  226. package/src/components/button.ts +0 -237
  227. package/src/components/image/index.android.ts +0 -95
  228. package/src/components/image/index.ios.ts +0 -95
  229. package/src/components/image/index.ts +0 -3
  230. package/src/components/image-background.ts +0 -308
  231. package/src/components/input-accessory-view/index.ts +0 -246
  232. package/src/components/pressable/index.ts +0 -522
  233. package/src/components/refresh-control/index.ts +0 -349
  234. package/src/components/safe-area-view/index.ts +0 -247
  235. package/src/components/scroll-view/index.android.ts +0 -205
  236. package/src/components/scroll-view/index.ios.ts +0 -81
  237. package/src/components/scroll-view/index.ts +0 -7
  238. package/src/components/scroll-view/projection.ts +0 -713
  239. package/src/components/scroll-view/shared.ts +0 -1093
  240. package/src/components/scroll-view/sticky-header.ts +0 -267
  241. package/src/components/switch/index.android.ts +0 -113
  242. package/src/components/switch/index.ios.ts +0 -112
  243. package/src/components/switch/index.ts +0 -4
  244. package/src/components/switch/shared.ts +0 -284
  245. package/src/components/text-input.ts +0 -669
  246. package/src/components/touchable/index.ts +0 -956
  247. package/src/components/touchable-native-feedback/index.ts +0 -327
  248. package/src/state-style.ts +0 -39
@@ -0,0 +1,120 @@
1
+ // A dependency-free LEAF so `renderer/index.ts` can ask a view to re-check itself without importing
2
+ // the element directives, which import the renderer (same reasoning as `renderer/value-change.ts`
3
+ // and `anchor-host-registry.ts`).
4
+ //
5
+ // WHY ANYTHING IS NEEDED. Zoneless change detection is scheduled on a
6
+ // requestAnimationFrame/setTimeout RACE (`ChangeDetectionSchedulerImpl`, upstream
7
+ // `zoneless_scheduling_impl.ts`), so an app's state update from a native event lands a whole
8
+ // MACROTASK later. A bound template listener DOES notify Angular — that is one of the documented
9
+ // notification sources — so nothing is missing; what is wrong is the TIMING. Three engine behaviors
10
+ // read the app's answer back within the same MICROTASK turn:
11
+ //
12
+ // behaviors/text-input.ts `afterCommit` re-commands the native text from `props.value`
13
+ // behaviors/switch.ts `queueMicrotask` snap-back reads `props.value`
14
+ // behaviors/refresh-control.ts `queueMicrotask` snap-back reads `props.refreshing`
15
+ //
16
+ // Every other adapter's state update lands inside that turn; zoneless Angular cannot, so all three
17
+ // read the PRE-event value and UNDO the user. Device-reported 2026-09-11: `[(value)]` on a
18
+ // `<text-input>` commanded the stale text back after one keystroke, a `[(value)]` `<switch>` snapped
19
+ // straight off again, and pull-to-refresh stopped itself.
20
+ //
21
+ // WHY `ChangeDetectorRef.detectChanges()` AND NOT `ApplicationRef.tick()`. Both re-evaluate the
22
+ // binding; only one of them is safe to call from a native event. `tick()` emits `afterTick`
23
+ // UNCONDITIONALLY — `dirtyFlags === 0` included — and the scheduler's `afterTick` subscriber runs
24
+ // `switchToMicrotaskScheduler`, which sets `useMicrotaskScheduler` for the rest of the turn. Every
25
+ // notification raised while that flag is set is counted by `trackMicrotaskNotificationForDebugging`
26
+ // against `CONSECUTIVE_MICROTASK_NOTIFICATION_LIMIT` (100), and the ONLY reset is a notification
27
+ // raised while it is clear. A commit can dispatch further events (`onLayout`), each of which
28
+ // notifies, so forcing a tick per native event turns that into NG0103, "Angular could not stabilize
29
+ // because there were endless change notifications" — device-reported the same day, on the first fix
30
+ // for the paragraph above. `ViewRef.detectChanges()` sets `RefreshView` and calls
31
+ // `detectChangesInternal` (upstream `render3/view_ref.ts`): no `afterTick`, no scheduler
32
+ // notification, so it cannot open that window at all. It is also the narrower answer — the only
33
+ // view that has to be re-checked is the one holding the binding.
34
+ //
35
+ // The flush is registered by the element DIRECTIVE, which is the only thing here that owns a
36
+ // `ChangeDetectorRef` for that view. A tag written under `CUSTOM_ELEMENTS_SCHEMA` with no directive
37
+ // matched therefore gets no flush and keeps the stale-read behaviour — the directive is the
38
+ // supported route (`[(value)]` is NG8007 without it), and this leaf has no way to reach a view it
39
+ // was never handed.
40
+ //
41
+ // When a fourth behavior starts reading an app value back, it needs a name in the renderer's
42
+ // `READ_BACK_*` sets — the census is `queueMicrotask` / `afterCommit` in
43
+ // `core/components/src/behaviors`.
44
+ const viewFlushes = new WeakMap<object, () => void>();
45
+
46
+ const ON_PREFIX = /^on[A-Z]/;
47
+
48
+ // The one `onX` that fires per FRAME rather than per gesture — with sticky headers RN pins
49
+ // `scrollEventThrottle` to 1, i.e. 60 times a second. `markForCheck` walks to the ROOT, so wrapping
50
+ // it costs a full ancestor-screen template execution per frame: measured as the canary's ~37fps
51
+ // scroll (`components/virtualized-list/scroll-cost.test.ts`). Nothing loses its refresh — the list
52
+ // marks itself when its window moves, sticky rides the native driver, and a caller's own handler is
53
+ // typically an Animated.event touching no Angular state. Drag and momentum begin/end stay wrapped;
54
+ // once per gesture is not a hot path.
55
+ const PER_FRAME_CALLBACK = 'onScroll';
56
+
57
+ interface IViewMarker {
58
+ markForCheck(): void;
59
+ }
60
+
61
+ type ICallbackWrapper = (key: string, value: unknown) => unknown;
62
+
63
+ /**
64
+ * Makes an app callback handed to the engine as a PROP re-enter Angular's update loop.
65
+ *
66
+ * An `(event)` binding is wrapped by Angular's own `wrapListenerIn_markDirtyAndPreventDefault` and
67
+ * notifies on its own. A `[onPressMove]="fn"` prop is an `@Input` forwarded to the node, and the
68
+ * ENGINE calls it on event dispatch — Angular is told NOTHING, so a plain field mutation inside it
69
+ * dirties no view and the template reading it stays stale until something unrelated ticks.
70
+ * Device-reported 2026-09-11: a pan readout stuck at `dx 0 · dy 0` for a whole gesture, its real
71
+ * numbers arriving on the next button press.
72
+ *
73
+ * `markForCheck()` is one of the two notification sources Angular sanctions for an event source
74
+ * outside the framework (the other is writing a signal the template reads, which an ADAPTER cannot
75
+ * choose on the app's behalf). It flags the INJECTING view and every ancestor with RefreshView —
76
+ * the reach `detectChanges()` does not have — and notifies the scheduler.
77
+ *
78
+ * `flushViewFor` is the second, narrower half: three behaviors read the app's answer back inside
79
+ * the SAME microtask turn, and `markForCheck` only SCHEDULES. It is a no-op on a node that
80
+ * registered no flush.
81
+ *
82
+ * ONE wrapper per original handler, for the caller's lifetime. A fresh closure per push would make
83
+ * the engine store a new listener every time and would defeat every downstream identity check.
84
+ */
85
+ export function createCallbackWrapper(
86
+ view: IViewMarker,
87
+ node: unknown,
88
+ ): ICallbackWrapper {
89
+ const wrappers = new WeakMap<object, (...args: unknown[]) => unknown>();
90
+ return (key: string, value: unknown): unknown => {
91
+ if (!ON_PREFIX.test(key) || typeof value !== 'function') return value;
92
+ if (key === PER_FRAME_CALLBACK) return value;
93
+ const cached = wrappers.get(value);
94
+ if (cached !== undefined) return cached;
95
+ // Reflect.apply rather than a cast-to-signature local: `typeof value === 'function'` narrows to
96
+ // `Function`, which carries no call signature, and this repo does not use `as` to paper over it.
97
+ // `undefined` as the receiver preserves the previous unbound call.
98
+ const wrapper = (...args: unknown[]): unknown => {
99
+ const result: unknown = Reflect.apply(value, undefined, args);
100
+ view.markForCheck();
101
+ flushViewFor(node);
102
+ return result;
103
+ };
104
+ wrappers.set(value, wrapper);
105
+ return wrapper;
106
+ };
107
+ }
108
+
109
+ export function registerViewFlush(node: object, flush: () => void): void {
110
+ viewFlushes.set(node, flush);
111
+ }
112
+
113
+ export function unregisterViewFlush(node: object): void {
114
+ viewFlushes.delete(node);
115
+ }
116
+
117
+ export function flushViewFor(node: unknown): void {
118
+ if (typeof node !== 'object' || node === null) return;
119
+ viewFlushes.get(node)?.();
120
+ }
@@ -0,0 +1,21 @@
1
+ // The prop surface of `<activity-indicator>`, for Angular.
2
+ //
3
+ // No component left to type — the element IS the tag, matched by `ActivityIndicatorElement`
4
+ // (`../elements.ts`). RN's ActivityIndicator is a centering `<view>` around a native spinner
5
+ // (ActivityIndicator.js:112) and takes no children, and the engine behavior now builds both nodes
6
+ // (`core/components/src/behaviors/activity-indicator/`). This stays exported because an app that
7
+ // wraps the tag in its own component types the bag it forwards against something.
8
+ //
9
+ // The five callbacks are omitted for the reason every Angular element type omits them: they are
10
+ // `(layout)` / `(accessibilityAction)` / … OUTPUT bindings here, not inputs. Everything else is the
11
+ // shared agnostic surface, re-exported rather than redeclared.
12
+ import type { IActivityIndicatorProps as ICoreActivityIndicatorProps } from '@symbiote-native/components';
13
+
14
+ export type IActivityIndicatorProps = Omit<
15
+ ICoreActivityIndicatorProps,
16
+ | 'onLayout'
17
+ | 'onAccessibilityAction'
18
+ | 'onAccessibilityTap'
19
+ | 'onMagicTap'
20
+ | 'onAccessibilityEscape'
21
+ >;
@@ -0,0 +1,26 @@
1
+ // The prop surface of `<button>`, for Angular.
2
+ //
3
+ // No component left to type — the element IS the tag, matched by `ButtonElement`
4
+ // (`../elements.ts`). RN's Button takes no children (`title` is a string prop, Button.js:363) and
5
+ // builds its own touchable > view > text subtree, which the engine behavior now builds instead
6
+ // (`core/components/src/behaviors/button.ts`). This stays exported because an app that wraps the
7
+ // tag in its own component types the bag it forwards against something.
8
+ //
9
+ // The five callbacks are omitted for the reason every Angular element type omits them: they are
10
+ // `(press)` / `(accessibilityAction)` / … OUTPUT bindings here, not inputs. Everything else is the
11
+ // shared agnostic surface, re-exported rather than redeclared.
12
+ //
13
+ // `ButtonElement` inherits the touchable's own inputs (`android_ripple`, `delayLongPress`,
14
+ // `activeOpacity`, …) because it extends `TouchableOpacityElement`. That is the element class, not
15
+ // this contract: RN's Button declares none of them, so they stay out of the type an app writes
16
+ // against.
17
+ import type { IButtonProps as ICoreButtonProps } from '@symbiote-native/components';
18
+
19
+ export type IButtonProps = Omit<
20
+ ICoreButtonProps,
21
+ | 'onPress'
22
+ | 'onAccessibilityAction'
23
+ | 'onAccessibilityTap'
24
+ | 'onMagicTap'
25
+ | 'onAccessibilityEscape'
26
+ >;
@@ -226,20 +226,21 @@ export type IFlatListInputs<ItemT> = Omit<
226
226
  [scrollEventThrottle]="scrollEventThrottle"
227
227
  [keyboardShouldPersistTaps]="keyboardShouldPersistTaps"
228
228
  [keyboardDismissMode]="keyboardDismissMode"
229
+ [testID]="testID"
229
230
  [style]="resolvedStyle"
230
231
  [contentContainerStyle]="contentContainerStyle"
231
232
  >
232
233
  <ng-template vListItem let-row let-separators="separators">
233
- <symbiote-view [style]="rowStyle">
234
+ <view [style]="rowStyle">
234
235
  @for (cell of rowCells(row, separators); track cell.key) {
235
- <symbiote-view [style]="columnCellStyle">
236
+ <view [style]="columnCellStyle">
236
237
  <ng-container
237
238
  [vListOutlet]="itemDir?.templateRef"
238
239
  [vListOutletContext]="cell.context"
239
240
  ></ng-container>
240
- </symbiote-view>
241
+ </view>
241
242
  }
242
- </symbiote-view>
243
+ </view>
243
244
  </ng-template>
244
245
  @if (headerDir !== undefined) {
245
246
  <ng-template vListHeader>
@@ -309,6 +310,7 @@ export type IFlatListInputs<ItemT> = Omit<
309
310
  [scrollEventThrottle]="scrollEventThrottle"
310
311
  [keyboardShouldPersistTaps]="keyboardShouldPersistTaps"
311
312
  [keyboardDismissMode]="keyboardDismissMode"
313
+ [testID]="testID"
312
314
  [style]="resolvedStyle"
313
315
  [contentContainerStyle]="contentContainerStyle"
314
316
  >
@@ -379,6 +381,12 @@ export class FlatList<ItemT = unknown>
379
381
  averageItemLength: number;
380
382
  }>();
381
383
  @Input({ required: true }) data!: readonly ItemT[];
384
+ // RN's FlatList spreads its props onto the VirtualizedList it renders, so `testID` lands on the
385
+ // scroll view. Angular has no spread, and this one was simply missing: `<FlatList testID="x">`
386
+ // compiled (a static attribute on a component tag is never checked), reached the non-painting
387
+ // anchor host, and committed nowhere — so the list was untargetable by a test or an e2e selector
388
+ // while looking perfectly healthy on screen. VirtualizedList has always declared it.
389
+ @Input() testID?: string;
382
390
  @Input() numColumns?: number;
383
391
  @Input() columnWrapperStyle?: IStyleProp<IViewStyle> | string;
384
392
  @Input() keyExtractor?: (item: ItemT, index: number) => string;
@@ -0,0 +1,24 @@
1
+ // The prop surface of `<image-background>`, for Angular.
2
+ //
3
+ // No component left to type — the element IS the tag; the composition lives in the engine behavior
4
+ // (`core/components/src/behaviors/image-background.ts`). This stays exported because an app that
5
+ // wraps the tag in its own component types the bag it forwards against something, and because
6
+ // `elements.ts` indexes the element directive's input types off it.
7
+ //
8
+ // PER-ADAPTER, not shared: Angular takes children via `<ng-content>` and its class binding is the
9
+ // framework's own (<prop_types_split_agnostic_vs_per_adapter>).
10
+ import type { IImageProps } from '@symbiote-native/components';
11
+ import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
12
+
13
+ export interface IAngularImageBackgroundProps extends Omit<
14
+ IImageProps,
15
+ 'style'
16
+ > {
17
+ // The wrapper View's style; its width/height are reapplied to the inner Image so the image fills
18
+ // the box rather than collapsing to its source's intrinsic size. Bound through Angular's own
19
+ // styling engine, so `elements.ts` excludes it from the directive's inputs like every other tag.
20
+ style?: IStyleProp<IViewStyle>;
21
+ // Style merged onto the inner absolute-fill Image, after the proxied dimensions. A bare string
22
+ // is a class name and resolves through the shared style registry.
23
+ imageStyle?: IStyleProp<IViewStyle> | string;
24
+ }
@@ -1,9 +1,14 @@
1
+ // The input surface and prop fold `AnimatedImage` builds on. The `Image` COMPONENT that used to
2
+ // share it is gone (2026-09-10) — the primitive is the `<image>` tag, matched by `ImageElement`,
3
+ // and `registerImageBehavior` folds its source on that path. `Animated.Image` is not a primitive
4
+ // and stays a component, so what it needs from here survived the deletion; the folder collapsed to
5
+ // this one flat file with it (`symbiote-file-layout`).
1
6
  import { EventEmitter, computed, signal } from '@angular/core';
2
7
  import {
3
8
  gateWanted,
4
9
  injectGateDemand,
5
10
  type IGatedAccessibilityEvent,
6
- } from '../../gate-demand';
11
+ } from '../gate-demand';
7
12
  import {
8
13
  imageStatics,
9
14
  renderImage,
@@ -0,0 +1,21 @@
1
+ // The `<input-accessory-view>` tag's prop surface. The tag is matched by
2
+ // `InputAccessoryViewElement` (`../elements`) and commits one `RCTInputAccessoryView`; its whole
3
+ // wrapper was a prop FOLD with no aliasing at all (`registerInputAccessoryViewBehavior`), so it was
4
+ // deleted 2026-09-10 and the behavior applies the same mapping on the tag's own path.
5
+ //
6
+ // The type stays for a component forwarding a bag, and because `IAngularInputAccessoryViewProps` is
7
+ // public API.
8
+
9
+ import type {
10
+ IAccessibilityProps,
11
+ IAriaProps,
12
+ } from '@symbiote-native/components';
13
+ import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
14
+
15
+ export interface IAngularInputAccessoryViewProps
16
+ extends IAccessibilityProps, IAriaProps {
17
+ // The id a TextInput's inputAccessoryViewID points at to dock above its keyboard.
18
+ nativeID?: string;
19
+ backgroundColor?: string;
20
+ style?: IStyleProp<IViewStyle>;
21
+ }
@@ -6,7 +6,7 @@
6
6
  // Angular twin of React's setState / Vue's reactive ref), ngOnDestroy tears the subscriptions down,
7
7
  // and the wrapper's onLayout measures the frame that feeds the next event's inset. The user
8
8
  // children nest under the wrapper (or, for 'position', an inner View) via <ng-content>. No native
9
- // host of its own — it wraps symbiote-view — so this stays a flat single file.
9
+ // host of its own — it wraps view — so this stays a flat single file.
10
10
  //
11
11
  // Full parity: behavior 'height'|'position'|'padding', enabled, keyboardVerticalOffset,
12
12
  // contentContainerStyle, onLayout, plus the full a11y/aria surface every View carries.
@@ -103,18 +103,15 @@ export type IAngularKeyboardAvoidingViewInputs = Omit<
103
103
  // on `.observed` would silently break the inset fixpoint correction the moment an app didn't
104
104
  // listen to `layout`.
105
105
  template: `
106
- <symbiote-view
107
- [symbioteHostProps]="hostProps"
108
- (layout)="handleLayout($event)"
109
- >
106
+ <view [symbioteHostProps]="hostProps" (layout)="handleLayout($event)">
110
107
  @if (isNested) {
111
- <symbiote-view [style]="innerStyle">
108
+ <view [style]="innerStyle">
112
109
  <ng-content></ng-content>
113
- </symbiote-view>
110
+ </view>
114
111
  } @else {
115
112
  <ng-content></ng-content>
116
113
  }
117
- </symbiote-view>
114
+ </view>
118
115
  `,
119
116
  })
120
117
  export class KeyboardAvoidingView
@@ -189,7 +186,7 @@ export class KeyboardAvoidingView
189
186
 
190
187
  private readonly changeDetector = inject(ChangeDetectorRef);
191
188
  // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
192
- // onto (see anchorHostStyle's doc comment) — NOT a ViewChild into the inner symbiote-view (this
189
+ // onto (see anchorHostStyle's doc comment) — NOT a ViewChild into the inner view (this
193
190
  // component has none; the wrapper IS the outer template node hostProps binds onto).
194
191
  private readonly elementRef = inject(ElementRef);
195
192
 
@@ -109,17 +109,17 @@ export type IAngularModalInputs = Omit<
109
109
  changeDetection: ChangeDetectionStrategy.OnPush,
110
110
  template: `
111
111
  @if (shouldRender) {
112
- <symbiote-modal
112
+ <modal
113
113
  [symbioteHostProps]="hostProps()"
114
114
  (show)="show.emit()"
115
115
  (dismiss)="dismiss.emit()"
116
116
  (requestClose)="requestClose.emit()"
117
117
  (orientationChange)="emit(orientationChange, $event)"
118
118
  >
119
- <symbiote-view [style]="containerStyle" [collapsable]="false">
119
+ <view [style]="containerStyle" [symbioteHostProps]="containerProps">
120
120
  <ng-content></ng-content>
121
- </symbiote-view>
122
- </symbiote-modal>
121
+ </view>
122
+ </modal>
123
123
  }
124
124
  `,
125
125
  })
@@ -186,8 +186,8 @@ export class Modal implements IAngularModalInputs, OnInit, OnChanges, DoCheck {
186
186
 
187
187
  private readonly changeDetector = inject(ChangeDetectorRef);
188
188
  // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
189
- // onto (see anchorHostStyle's doc comment) — NOT the inner `symbiote-view [style]="containerStyle"`
190
- // that hosts the user children; the outer `symbiote-modal` node (bound via `hostProps` below) is
189
+ // onto (see anchorHostStyle's doc comment) — NOT the inner `view [style]="containerStyle"`
190
+ // that hosts the user children; the outer `modal` node (bound via `hostProps` below) is
191
191
  // the real primitive the anchor sits in front of.
192
192
  private readonly elementRef = inject(ElementRef);
193
193
 
@@ -261,7 +261,7 @@ export class Modal implements IAngularModalInputs, OnInit, OnChanges, DoCheck {
261
261
  this.hostPropsRevision.update(revision => revision + 1);
262
262
  }
263
263
 
264
- // renderModal's own MODAL_HOST_STYLE (position:'absolute') is the outer symbiote-modal node's
264
+ // renderModal's own MODAL_HOST_STYLE (position:'absolute') is the outer modal node's
265
265
  // style; the anchor's class-derived style goes FIRST, that resolved style SECOND —
266
266
  // flattenStyle's later-wins collapse keeps the modal's own style winning over its ambient class.
267
267
  //
@@ -282,6 +282,14 @@ export class Modal implements IAngularModalInputs, OnInit, OnChanges, DoCheck {
282
282
  };
283
283
  });
284
284
 
285
+ // Through the props bag rather than `[collapsable]="false"`: `view` matches `ViewHost`, a real
286
+ // component, so a binding it does not declare is NG8002 under `ngc` — and `CUSTOM_ELEMENTS_SCHEMA`
287
+ // does not rescue a binding on a MATCHED component. Invisible to `tsc` and to vitest; only a real
288
+ // AOT build says so. Frozen and shared, so the directive's own diff sees one unchanged object.
289
+ readonly containerProps: Readonly<Record<string, unknown>> = Object.freeze({
290
+ collapsable: false,
291
+ });
292
+
285
293
  get containerStyle(): unknown {
286
294
  const container = this.descriptor.children[0];
287
295
  return typeof container === 'string' ? undefined : container.props.style;
@@ -0,0 +1,73 @@
1
+ // The `<pressable>` tag's prop surface. The tag is matched by `PressableElement`
2
+ // (`../elements`) and carries the press machine as an engine behavior
3
+ // (`registerPressableBehavior`), so the wrapper that used to run it in Angular was deleted
4
+ // 2026-09-10.
5
+ //
6
+ // The type stays for a component forwarding a bag, for the four `Touchable*` prop types that share
7
+ // this base, and because `IAngularPressableProps` is public API. Mirrors React's IPressableProps
8
+ // minus children, which Angular takes via `<ng-content>`, and minus the render-prop `children`
9
+ // React allows.
10
+
11
+ import type {
12
+ IAccessibilityProps,
13
+ IAriaProps,
14
+ IPressableAndroidRippleConfig,
15
+ IPressHandler,
16
+ IPressState,
17
+ IRectOffset,
18
+ } from '@symbiote-native/components';
19
+ import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
20
+
21
+ export type {
22
+ IPressState,
23
+ IPressableAndroidRippleConfig,
24
+ } from '@symbiote-native/components';
25
+
26
+ export interface IAngularPressableProps
27
+ extends IAccessibilityProps, IAriaProps {
28
+ onPress?: IPressHandler;
29
+ onPressIn?: IPressHandler;
30
+ onPressOut?: IPressHandler;
31
+ onPressMove?: IPressHandler;
32
+ onLongPress?: IPressHandler;
33
+ delayLongPress?: number;
34
+ disabled?: boolean;
35
+ cancelable?: boolean;
36
+ hitSlop?: IRectOffset;
37
+ pressRetentionOffset?: IRectOffset;
38
+ unstable_pressDelay?: number;
39
+ android_ripple?: IPressableAndroidRippleConfig;
40
+ android_disableSound?: boolean;
41
+ onHoverIn?: IPressHandler;
42
+ onHoverOut?: IPressHandler;
43
+ delayHoverIn?: number;
44
+ delayHoverOut?: number;
45
+ testID?: string;
46
+ nativeID?: string;
47
+ hasTVPreferredFocus?: boolean;
48
+ nextFocusDown?: number;
49
+ nextFocusForward?: number;
50
+ nextFocusLeft?: number;
51
+ nextFocusRight?: number;
52
+ nextFocusUp?: number;
53
+ style?:
54
+ IStyleProp<IViewStyle> | ((state: IPressState) => IStyleProp<IViewStyle>);
55
+ }
56
+
57
+ // The half an Angular template writes as plain `[prop]` bindings: everything minus the callbacks a
58
+ // tag takes as `(event)` instead. The four `Touchable*` prop types are built over THIS rather than
59
+ // over the whole surface, for that reason.
60
+ export type IAngularPressableInputs = Omit<
61
+ IAngularPressableProps,
62
+ | 'onPress'
63
+ | 'onPressIn'
64
+ | 'onPressOut'
65
+ | 'onPressMove'
66
+ | 'onLongPress'
67
+ | 'onHoverIn'
68
+ | 'onHoverOut'
69
+ | 'onAccessibilityAction'
70
+ | 'onAccessibilityTap'
71
+ | 'onMagicTap'
72
+ | 'onAccessibilityEscape'
73
+ >;
@@ -0,0 +1,43 @@
1
+ // The `<refresh-control>` tag's prop surface. The tag is matched by `RefreshControlElement`
2
+ // (`../elements`) and carries the controlled-spinner handshake as an engine behavior
3
+ // (`registerRefreshControlBehavior` — mirror what native last reported, command it back when the
4
+ // app's `refreshing` disagrees, RefreshControl.js:145-166), so the wrapper that ran that in Angular
5
+ // was deleted 2026-09-11.
6
+ //
7
+ // WHERE it goes is the ScrollView's decision, not this tag's: write it as an ordinary FIRST CHILD
8
+ // on both platforms and the scroll-view behavior re-parents it — iOS a sibling before the content
9
+ // container, Android the `AndroidSwipeRefreshLayout` WRAPPING the scroll view.
10
+ //
11
+ // The type stays for a component forwarding a bag, and because `IAngularRefreshControlProps` is
12
+ // public API.
13
+
14
+ import type {
15
+ IAccessibilityProps,
16
+ IAriaProps,
17
+ } from '@symbiote-native/components';
18
+ import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
19
+
20
+ export interface IAngularRefreshControlProps
21
+ extends IAccessibilityProps, IAriaProps {
22
+ refreshing: boolean;
23
+ // `id` — RN's W3C alias for `nativeID`, folded by the spec entry's ID_ALIAS.
24
+ id?: string;
25
+ // RN's onRefresh is `() => void | Promise<void>`, the handler may be async; the promise is
26
+ // fire-and-forget (native already starts refreshing on the gesture).
27
+ onRefresh?: () => void | Promise<void>;
28
+ tintColor?: string;
29
+ title?: string;
30
+ titleColor?: string;
31
+ progressViewOffset?: number;
32
+ // Android-only spinner styling (RN RefreshControlPropsAndroid): `colors` are the indicator's
33
+ // animated stroke colors, `progressBackgroundColor` the disc behind it, `size` the diameter
34
+ // preset. AndroidSwipeRefreshLayout reads them; PullToRefreshView on iOS ignores unknown props.
35
+ colors?: readonly string[];
36
+ progressBackgroundColor?: string;
37
+ size?: 'default' | 'large';
38
+ // Android-only native prop forwarded to AndroidSwipeRefreshLayout; iOS native never reads it.
39
+ enabled?: boolean;
40
+ // The Android scroll-view wrap injects the layout half of the style onto this host; iOS leaves it
41
+ // unset (the RefreshControl is a childless sibling). Harmless to forward on both.
42
+ style?: IStyleProp<IViewStyle>;
43
+ }
@@ -0,0 +1,28 @@
1
+ // The `<safe-area-view>` tag's prop surface. The tag is matched by `SafeAreaViewElement`
2
+ // (`../elements`) and commits a single `SafeAreaView` native view whose host insets its children to
3
+ // the safe area; there is no JS-side translation to do, so the wrapper that used to fold
4
+ // aria/role and forward a host bag was deleted 2026-09-10 — the engine's own aria fold and the
5
+ // renderer's `id` -> `nativeID` alias cover both, on every path.
6
+ //
7
+ // The type stays for a component forwarding a bag, and because `IAngularSafeAreaViewProps` is
8
+ // public API. Mirrors React's ISafeAreaViewProps minus children, which Angular takes via
9
+ // `<ng-content>`.
10
+
11
+ import type {
12
+ IAccessibilityProps,
13
+ IAriaProps,
14
+ } from '@symbiote-native/components';
15
+ import type {
16
+ IStyleProp,
17
+ ISymbioteEvent,
18
+ IViewStyle,
19
+ } from '@symbiote-native/engine';
20
+
21
+ export interface IAngularSafeAreaViewProps
22
+ extends IAccessibilityProps, IAriaProps {
23
+ style?: IStyleProp<IViewStyle>;
24
+ // `id` — accepted here and folded to `nativeID` by the renderer, matching upstream, whose
25
+ // SafeAreaView takes the full ViewProps surface.
26
+ id?: string;
27
+ onLayout?: (event: ISymbioteEvent) => void;
28
+ }
@@ -0,0 +1,109 @@
1
+ // The `<scroll-view>` / `<horizontal-scroll-view>` tag's prop surface — the axis is the TAG you
2
+ // write, not a `horizontal` binding, because Android resolves a different native class per axis.
3
+ //
4
+ // The wrapper was deleted 2026-09-11 and nothing replaced it in the adapter: the ENGINE owns the
5
+ // whole shape now (`core/components/src/behaviors/scroll-view/`). `buildStructure` builds the
6
+ // content node the children go under, `slotProps` routes `contentContainerStyle` onto it as its
7
+ // `style`, `payloadFold` composes the two base styles, and the sticky machinery pins by DOCUMENT
8
+ // ORDER through the `<sticky-header>` tag — so the Angular projection bridge that used to wrap
9
+ // projected children by index is gone with it, along with its renderer hooks.
10
+ //
11
+ // A `<refresh-control>` is an ordinary FIRST CHILD on both platforms; the behavior re-parents it
12
+ // per platform (iOS a sibling before the content, Android the swipe layout WRAPPING the scroll
13
+ // view), which is why the adapter no longer has an `.ios`/`.android` split here.
14
+ //
15
+ // The imperative surface comes from `buildScrollViewHandle` (`@symbiote-native/components`) over
16
+ // the node a template ref hands back.
17
+
18
+ import type {
19
+ IAccessibilityProps,
20
+ IAriaProps,
21
+ } from '@symbiote-native/components';
22
+ import type {
23
+ IStyleProp,
24
+ ISymbioteEvent,
25
+ IViewStyle,
26
+ } from '@symbiote-native/engine';
27
+
28
+ export type { IScrollViewHandle } from '@symbiote-native/components';
29
+
30
+ type IScrollHandler = (event: ISymbioteEvent) => void;
31
+ type IContentSizeHandler = (width: number, height: number) => void;
32
+
33
+ export interface IAngularScrollViewProps
34
+ extends IAccessibilityProps, IAriaProps {
35
+ style?: IStyleProp<IViewStyle>;
36
+ // A bare string resolves through the shared style registry, like `class` on the host node.
37
+ contentContainerStyle?: IStyleProp<IViewStyle> | string;
38
+ scrollEnabled?: boolean;
39
+ showsVerticalScrollIndicator?: boolean;
40
+ showsHorizontalScrollIndicator?: boolean;
41
+ pagingEnabled?: boolean;
42
+ bounces?: boolean;
43
+ decelerationRate?: 'normal' | 'fast' | number;
44
+ scrollEventThrottle?: number;
45
+ contentInset?: {
46
+ top?: number;
47
+ left?: number;
48
+ bottom?: number;
49
+ right?: number;
50
+ };
51
+ contentOffset?: { x: number; y: number };
52
+ removeClippedSubviews?: boolean;
53
+ snapToInterval?: number;
54
+ snapToOffsets?: number[];
55
+ snapToAlignment?: 'start' | 'center' | 'end';
56
+ snapToStart?: boolean;
57
+ snapToEnd?: boolean;
58
+ disableIntervalMomentum?: boolean;
59
+ // Sticky headers: RN implements stickiness PURELY IN JS — the native scroll view does not honor
60
+ // an index array. The engine's behavior resolves the indices against its own content children.
61
+ stickyHeaderIndices?: number[];
62
+ invertStickyHeaders?: boolean;
63
+ keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
64
+ keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
65
+ maintainVisibleContentPosition?: {
66
+ minIndexForVisible: number;
67
+ autoscrollToTopThreshold?: number;
68
+ };
69
+ // iOS-only forwarding props (harmless on Android: its manager ignores unknown props).
70
+ alwaysBounceHorizontal?: boolean;
71
+ alwaysBounceVertical?: boolean;
72
+ centerContent?: boolean;
73
+ scrollIndicatorInsets?: {
74
+ top?: number;
75
+ left?: number;
76
+ bottom?: number;
77
+ right?: number;
78
+ };
79
+ indicatorStyle?: 'default' | 'black' | 'white';
80
+ directionalLockEnabled?: boolean;
81
+ automaticallyAdjustKeyboardInsets?: boolean;
82
+ contentInsetAdjustmentBehavior?:
83
+ 'automatic' | 'scrollableAxes' | 'never' | 'always';
84
+ minimumZoomScale?: number;
85
+ maximumZoomScale?: number;
86
+ zoomScale?: number;
87
+ bouncesZoom?: boolean;
88
+ pinchGestureEnabled?: boolean;
89
+ // Android-only forwarding props (harmless on iOS).
90
+ nestedScrollEnabled?: boolean;
91
+ overScrollMode?: 'auto' | 'always' | 'never';
92
+ fadingEdgeLength?: number;
93
+ persistentScrollbar?: boolean;
94
+ endFillColor?: string;
95
+ onLayout?: IScrollHandler;
96
+ onScroll?: IScrollHandler;
97
+ onScrollBeginDrag?: IScrollHandler;
98
+ onScrollEndDrag?: IScrollHandler;
99
+ onMomentumScrollBegin?: IScrollHandler;
100
+ onMomentumScrollEnd?: IScrollHandler;
101
+ // iOS-only: user tapped the status bar to scroll to top. Inert on Android.
102
+ onScrollToTop?: IScrollHandler;
103
+ // Synthesized in JS from the content view's onLayout (RN _handleContentOnLayout); deduped.
104
+ onContentSizeChange?: IContentSizeHandler;
105
+ onAccessibilityAction?: (event: ISymbioteEvent) => void;
106
+ onAccessibilityTap?: (event: ISymbioteEvent) => void;
107
+ onMagicTap?: (event: ISymbioteEvent) => void;
108
+ onAccessibilityEscape?: (event: ISymbioteEvent) => void;
109
+ }