@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
@@ -1,95 +0,0 @@
1
- import {
2
- CUSTOM_ELEMENTS_SCHEMA,
3
- Component,
4
- ElementRef,
5
- inject,
6
- signal,
7
- type DoCheck,
8
- type OnChanges,
9
- } from '@angular/core';
10
- import {
11
- anchorHostStyle,
12
- ImageHost,
13
- SymbioteHostPropsDirective,
14
- SymbioteStyleInputDirective,
15
- } from '../../primitives';
16
- import {
17
- IMAGE_INPUTS,
18
- IMAGE_OUTPUTS,
19
- ImageBase,
20
- resolveImageProps,
21
- } from './shared';
22
- export { setImageSourceResolver } from './shared';
23
- export type {
24
- IImageProps,
25
- IImageSource,
26
- IImageSourceProp,
27
- IResizeMode,
28
- IImageSize,
29
- IImageCacheStatus,
30
- } from './shared';
31
-
32
- @Component({
33
- selector: 'Image',
34
- standalone: true,
35
- hostDirectives: [
36
- { directive: SymbioteStyleInputDirective, inputs: ['style'] },
37
- ],
38
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
39
- imports: [ImageHost, SymbioteHostPropsDirective],
40
- inputs: IMAGE_INPUTS,
41
- outputs: IMAGE_OUTPUTS,
42
- template: `
43
- <symbiote-image
44
- [symbioteHostProps]="imageProps()"
45
- (loadStart)="handleLoadStart($event)"
46
- (load)="handleLoad($event)"
47
- (loadEnd)="handleLoadEnd($event)"
48
- (error)="handleError($event)"
49
- (progress)="handleProgress($event)"
50
- (partialLoad)="handlePartialLoad($event)"
51
- />
52
- `,
53
- })
54
- export class Image extends ImageBase implements OnChanges, DoCheck {
55
- // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
56
- // onto (see anchorHostStyle's doc comment) — NOT the inner `symbiote-image` one level down.
57
- private readonly elementRef = inject(ElementRef);
58
-
59
- // The anchor's class-derived style is written by the renderer's addClass/removeClass and never
60
- // reaches Angular's input pipeline (a bare `class="x"` never appears in SimpleChanges — see
61
- // anchorHostStyle's doc comment), so ImageBase's inputsRevision cannot see it. Hence its own
62
- // signal: a plain field read inside a computed() would be untracked and the bag would go stale
63
- // the moment a `[class.x]`/`[ngClass]` toggled.
64
- //
65
- // ngDoCheck is the right cadence: render3's callHooks flushes a node's pre-order hooks at the
66
- // next `ɵɵadvance` past it (or in refreshView's post-template flush), i.e. AFTER the declaring
67
- // template's ɵɵclassProp wrote the class onto this element and BEFORE this component's own view
68
- // refreshes — the exact window a class poll needs. callHooks also runs under
69
- // setActiveConsumer(null), so the write registers no dependency on the caller's view (no NG0600).
70
- // commitClassStyle allocates a fresh style array only when a token actually moved, so signal.set's
71
- // own Object.is check makes an unchanged poll a no-op that dirties nothing.
72
- //
73
- // Known gap, shared with every other component polling this way (Pressable, SafeAreaView,
74
- // TouchableNativeFeedback): `[ngClass]` applies its tokens from NgClass's OWN ngDoCheck, and a
75
- // node's hooks flush in registration order with the component's first, so an [ngClass] flip lands
76
- // one pass after this poll reads it. `class=` and `[class.x]` are written by the declaring
77
- // template's styling instructions and so are always current here.
78
- private readonly anchorStyle = signal<unknown>(undefined);
79
-
80
- // ImageBase is undecorated, so the input bump is declared here rather than inherited.
81
- ngOnChanges(): void {
82
- this.bumpInputsRevision();
83
- }
84
-
85
- ngDoCheck(): void {
86
- this.anchorStyle.set(anchorHostStyle(this.elementRef));
87
- }
88
-
89
- protected override buildImageProps(): Record<string, unknown> {
90
- return resolveImageProps({
91
- ...this.imageInputProps,
92
- style: [this.anchorStyle(), this.style],
93
- });
94
- }
95
- }
@@ -1,3 +0,0 @@
1
- // Base/default Image. Re-exports the iOS build; Metro picks index.ios.ts / index.android.ts in platform bundles.
2
-
3
- export * from './index.ios';
@@ -1,308 +0,0 @@
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 {
41
- anchorHostStyle,
42
- SymbioteStyleInputDirective,
43
- ViewHost,
44
- } from '../primitives';
45
- import {
46
- gateWanted,
47
- injectGateDemandAbove,
48
- provideGateDemand,
49
- type IGateDemand,
50
- type IGatedAccessibilityEvent,
51
- } from '../gate-demand';
52
-
53
- // Mirrors React's IImageBackgroundProps minus children (Angular takes children via <ng-content>):
54
- // every forwarding Image prop flows onto the inner image; `style` is the WRAPPER View style and
55
- // `imageStyle` the inner image's.
56
- export interface IAngularImageBackgroundProps extends Omit<
57
- IImageProps,
58
- 'style'
59
- > {
60
- style?: IStyleProp<IViewStyle>;
61
- // A bare string resolves through the shared style registry, like `class` on the wrapper.
62
- imageStyle?: IStyleProp<IViewStyle> | string;
63
- }
64
-
65
- // What the ImageBackground component itself takes as plain @Input()s: the full surface minus the
66
- // inner Image's callback-shaped events, which it exposes as real @Output() EventEmitters instead
67
- // (re-emitting the inner <Image>'s own already-converted outputs — see the template below).
68
- export type IAngularImageBackgroundInputs = Omit<
69
- IAngularImageBackgroundProps,
70
- | 'onAccessibilityAction'
71
- | 'onAccessibilityTap'
72
- | 'onMagicTap'
73
- | 'onAccessibilityEscape'
74
- | 'onLoadStart'
75
- | 'onLoad'
76
- | 'onLoadEnd'
77
- | 'onError'
78
- | 'onProgress'
79
- | 'onPartialLoad'
80
- >;
81
-
82
- @Component({
83
- selector: 'ImageBackground',
84
- standalone: true,
85
- viewProviders: [provideGateDemand(() => ImageBackground)],
86
- hostDirectives: [
87
- { directive: SymbioteStyleInputDirective, inputs: ['style'] },
88
- ],
89
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
90
- imports: [Image, ViewHost],
91
- changeDetection: ChangeDetectionStrategy.OnPush,
92
- template: `
93
- <symbiote-view [style]="wrapperStyle">
94
- <Image
95
- [source]="source"
96
- [defaultSource]="defaultSource"
97
- [loadingIndicatorSource]="loadingIndicatorSource"
98
- [style]="imageStyle"
99
- [resizeMode]="resizeMode"
100
- [resizeMethod]="resizeMethod"
101
- [tintColor]="tintColor"
102
- [blurRadius]="blurRadius"
103
- [capInsets]="capInsets"
104
- [fadeDuration]="fadeDuration"
105
- [progressiveRenderingEnabled]="progressiveRenderingEnabled"
106
- [src]="src"
107
- [srcSet]="srcSet"
108
- [alt]="alt"
109
- [width]="width"
110
- [height]="height"
111
- [crossOrigin]="crossOrigin"
112
- [referrerPolicy]="referrerPolicy"
113
- [testID]="testID"
114
- [nativeID]="nativeID"
115
- [accessible]="accessible"
116
- [accessibilityLabel]="folded.accessibilityLabel"
117
- [accessibilityHint]="folded.accessibilityHint"
118
- [accessibilityRole]="folded.accessibilityRole"
119
- [accessibilityState]="folded.accessibilityState"
120
- [accessibilityValue]="folded.accessibilityValue"
121
- [accessibilityActions]="folded.accessibilityActions"
122
- [accessibilityLabelledBy]="folded.accessibilityLabelledBy"
123
- [importantForAccessibility]="folded.importantForAccessibility"
124
- [accessibilityLiveRegion]="folded.accessibilityLiveRegion"
125
- [screenReaderFocusable]="folded.screenReaderFocusable"
126
- [accessibilityViewIsModal]="folded.accessibilityViewIsModal"
127
- [accessibilityElementsHidden]="folded.accessibilityElementsHidden"
128
- [accessibilityIgnoresInvertColors]="
129
- folded.accessibilityIgnoresInvertColors
130
- "
131
- [accessibilityLanguage]="folded.accessibilityLanguage"
132
- [accessibilityRespondsToUserInteraction]="
133
- folded.accessibilityRespondsToUserInteraction
134
- "
135
- [accessibilityShowsLargeContentViewer]="
136
- folded.accessibilityShowsLargeContentViewer
137
- "
138
- [accessibilityLargeContentTitle]="folded.accessibilityLargeContentTitle"
139
- (loadStart)="loadStart.emit($event)"
140
- (load)="load.emit($event)"
141
- (loadEnd)="loadEnd.emit($event)"
142
- (error)="error.emit($event)"
143
- (progress)="progress.emit($event)"
144
- (partialLoad)="partialLoad.emit($event)"
145
- (accessibilityAction)="accessibilityAction.emit($event)"
146
- (accessibilityTap)="accessibilityTap.emit($event)"
147
- (magicTap)="magicTap.emit($event)"
148
- (accessibilityEscape)="accessibilityEscape.emit($event)"
149
- />
150
- <ng-content></ng-content>
151
- </symbiote-view>
152
- `,
153
- })
154
- export class ImageBackground implements IAngularImageBackgroundInputs {
155
- // The inner <Image>'s events as real Angular events, re-emitted verbatim through
156
- // ImageBackground's own outputs: `(load)="load.emit($event)"`, not `[onLoad]="onLoad"`.
157
- @Output() readonly accessibilityAction = new EventEmitter<ISymbioteEvent>();
158
- @Output() readonly accessibilityTap = new EventEmitter<ISymbioteEvent>();
159
- @Output() readonly magicTap = new EventEmitter<ISymbioteEvent>();
160
- @Output() readonly accessibilityEscape = new EventEmitter<ISymbioteEvent>();
161
-
162
- // This wrapper binds the four gated accessibility events on the component it renders, which
163
- // Angular forces to be unconditional and which would light that component's gates on every
164
- // instance. It answers for them instead — see `gate-demand.ts`.
165
- private readonly gateDemandAbove = injectGateDemandAbove();
166
-
167
- wantsGate(name: IGatedAccessibilityEvent): boolean {
168
- return gateWanted(this.gateDemandAbove, name, this[name]);
169
- }
170
-
171
- @Output() readonly loadStart = new EventEmitter<ISymbioteEvent>();
172
- @Output() readonly load = new EventEmitter<ISymbioteEvent>();
173
- @Output() readonly loadEnd = new EventEmitter<ISymbioteEvent>();
174
- @Output() readonly error = new EventEmitter<ISymbioteEvent>();
175
- @Output() readonly progress = new EventEmitter<ISymbioteEvent>();
176
- @Output() readonly partialLoad = new EventEmitter<ISymbioteEvent>();
177
- @Input() source?: IImageSourceProp;
178
- @Input() defaultSource?: IImageSourceProp;
179
- @Input() loadingIndicatorSource?: IImageSourceProp;
180
- @Input() style?: IStyleProp<IViewStyle>;
181
- @Input('imageStyle') imageStyleValue?: IStyleProp<IViewStyle> | string;
182
- @Input() resizeMode?: IResizeMode;
183
- @Input() resizeMethod?: IImageProps['resizeMethod'];
184
- @Input() tintColor?: string;
185
- @Input() blurRadius?: number;
186
- @Input() capInsets?: IImageProps['capInsets'];
187
- @Input() fadeDuration?: number;
188
- @Input() progressiveRenderingEnabled?: boolean;
189
- @Input() src?: string;
190
- @Input() srcSet?: string;
191
- @Input() alt?: string;
192
- @Input() width?: number;
193
- @Input() height?: number;
194
- @Input() crossOrigin?: 'anonymous' | 'use-credentials';
195
- @Input() referrerPolicy?: string;
196
- @Input() testID?: string;
197
- @Input() nativeID?: string;
198
- @Input() accessible?: boolean;
199
- @Input() accessibilityLabel?: string;
200
- @Input() accessibilityHint?: string;
201
- @Input() accessibilityRole?: IAccessibilityProps['accessibilityRole'];
202
- @Input() accessibilityState?: IAccessibilityStateValue;
203
- @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
204
- @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
205
- @Input() accessibilityLabelledBy?: string | string[];
206
- @Input()
207
- importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
208
- @Input()
209
- accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
210
- @Input() screenReaderFocusable?: boolean;
211
- @Input() accessibilityViewIsModal?: boolean;
212
- @Input() accessibilityElementsHidden?: boolean;
213
- @Input() accessibilityIgnoresInvertColors?: boolean;
214
- @Input() accessibilityLanguage?: string;
215
- @Input() accessibilityRespondsToUserInteraction?: boolean;
216
- @Input() accessibilityShowsLargeContentViewer?: boolean;
217
- @Input() accessibilityLargeContentTitle?: string;
218
- @Input() role?: IAriaProps['role'];
219
- @Input('aria-label') ariaLabel?: string;
220
- @Input('aria-labelledby') ariaLabelledBy?: string;
221
- @Input('aria-live') ariaLive?: IAriaProps['aria-live'];
222
- @Input('aria-hidden') ariaHidden?: boolean;
223
- @Input('aria-busy') ariaBusy?: boolean;
224
- @Input('aria-checked') ariaChecked?: boolean | 'mixed';
225
- @Input('aria-disabled') ariaDisabled?: boolean;
226
- @Input('aria-expanded') ariaExpanded?: boolean;
227
- @Input('aria-selected') ariaSelected?: boolean;
228
- @Input('aria-modal') ariaModal?: boolean;
229
- @Input('aria-valuemax') ariaValueMax?: number;
230
- @Input('aria-valuemin') ariaValueMin?: number;
231
- @Input('aria-valuenow') ariaValueNow?: number;
232
- @Input('aria-valuetext') ariaValueText?: string;
233
-
234
- // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
235
- // onto (see anchorHostStyle's doc comment) — NOT the inner `symbiote-view [style]="wrapperStyle"`
236
- // one level down. Merged FIRST so the explicit `style` @Input still wins (flattenStyle's
237
- // later-wins collapse), mirroring every other composed component's anchor merge. `imageStyle`
238
- // below stays untouched per the ImageBackground-specific nuance: it targets the inner image, not
239
- // this component's own root.
240
- private readonly elementRef = inject(ElementRef);
241
-
242
- get wrapperStyle(): unknown {
243
- return [anchorHostStyle(this.elementRef), this.style];
244
- }
245
-
246
- // renderImageBackground owns the absolute-fill + wrapper-dimension-proxy + imageStyle merge
247
- // (shared verbatim with React/Vue); read the inner image Descriptor's style off the tree it
248
- // returns rather than reimplementing it. Only style/imageStyle drive that merge, so the image
249
- // bag is empty here — the inner <Image> below resolves source / a11y / events on its own.
250
- get imageStyle(): IStyleProp<IViewStyle> | undefined {
251
- // imageStyle targets the INNER image (renderImageBackground's own field); resolve a
252
- // class-name string here, before it flows into the merge.
253
- const resolvedImageStyleValue =
254
- typeof this.imageStyleValue === 'string'
255
- ? resolveClassName(this.imageStyleValue)
256
- : this.imageStyleValue;
257
- const inner = renderImageBackground({
258
- style: this.style,
259
- imageStyle: resolvedImageStyleValue,
260
- image: { passthrough: {} },
261
- }).children[0];
262
- return typeof inner === 'string'
263
- ? undefined
264
- : (inner.props.style as IStyleProp<IViewStyle> | undefined);
265
- }
266
-
267
- // Fold the web aria-*/role aliases into the canonical accessibility* props once per render, so the
268
- // inner image never sees an aria-* key (native ignores them) — the shared transform every adapter
269
- // runs. The inner <Image> re-runs the same fold idempotently over the already-folded props.
270
- get folded(): Partial<IAngularImageBackgroundProps> {
271
- return resolveAccessibilityProps({
272
- accessibilityLabel: this.accessibilityLabel,
273
- accessibilityHint: this.accessibilityHint,
274
- accessibilityRole: this.accessibilityRole,
275
- accessibilityState: this.accessibilityState,
276
- accessibilityValue: this.accessibilityValue,
277
- accessibilityActions: this.accessibilityActions,
278
- accessibilityLabelledBy: this.accessibilityLabelledBy,
279
- importantForAccessibility: this.importantForAccessibility,
280
- accessibilityLiveRegion: this.accessibilityLiveRegion,
281
- screenReaderFocusable: this.screenReaderFocusable,
282
- accessibilityViewIsModal: this.accessibilityViewIsModal,
283
- accessibilityElementsHidden: this.accessibilityElementsHidden,
284
- accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
285
- accessibilityLanguage: this.accessibilityLanguage,
286
- accessibilityRespondsToUserInteraction:
287
- this.accessibilityRespondsToUserInteraction,
288
- accessibilityShowsLargeContentViewer:
289
- this.accessibilityShowsLargeContentViewer,
290
- accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
291
- role: this.role,
292
- 'aria-label': this.ariaLabel,
293
- 'aria-labelledby': this.ariaLabelledBy,
294
- 'aria-live': this.ariaLive,
295
- 'aria-hidden': this.ariaHidden,
296
- 'aria-busy': this.ariaBusy,
297
- 'aria-checked': this.ariaChecked,
298
- 'aria-disabled': this.ariaDisabled,
299
- 'aria-expanded': this.ariaExpanded,
300
- 'aria-selected': this.ariaSelected,
301
- 'aria-modal': this.ariaModal,
302
- 'aria-valuemax': this.ariaValueMax,
303
- 'aria-valuemin': this.ariaValueMin,
304
- 'aria-valuenow': this.ariaValueNow,
305
- 'aria-valuetext': this.ariaValueText,
306
- });
307
- }
308
- }
@@ -1,246 +0,0 @@
1
- // InputAccessoryView, the Angular lifecycle half (iOS). RCTInputAccessoryView is a real Fabric
2
- // host node that docks its content above the keyboard; a TextInput points at it by nativeID through
3
- // its inputAccessoryViewID. The host-node assembly (nativeID / backgroundColor / style /
4
- // accessibility forwarding) lives framework-agnostic in
5
- // @symbiote-native/components/renderInputAccessoryView and is shared verbatim with React/Vue; here
6
- // Angular supplies only the lifecycle — it folds aria/role, reads the resolved props off the
7
- // Descriptor, and nests the user children under the host via <ng-content>. The Angular twin of the
8
- // React/Vue InputAccessoryView. No platform branch, so this stays flat.
9
-
10
- import {
11
- CUSTOM_ELEMENTS_SCHEMA,
12
- ChangeDetectionStrategy,
13
- Component,
14
- computed,
15
- ElementRef,
16
- EventEmitter,
17
- inject,
18
- Input,
19
- Output,
20
- signal,
21
- type DoCheck,
22
- type OnChanges,
23
- } from '@angular/core';
24
- import {
25
- renderInputAccessoryView,
26
- resolveAccessibilityProps,
27
- type IAccessibilityProps,
28
- type IAccessibilityStateValue,
29
- type IAriaProps,
30
- } from '@symbiote-native/components';
31
- import {
32
- isSymbioteEvent,
33
- type IStyleProp,
34
- type ISymbioteEvent,
35
- type IViewStyle,
36
- } from '@symbiote-native/engine';
37
- import {
38
- anchorHostStyle,
39
- InputAccessoryViewHost,
40
- SymbioteHostPropsDirective,
41
- SymbioteStyleInputDirective,
42
- } from '../../primitives';
43
-
44
- // Mirrors React's IInputAccessoryViewProps minus children (Angular takes children via
45
- // <ng-content>), declared per-adapter over the shared a11y base.
46
- export interface IAngularInputAccessoryViewProps
47
- extends IAccessibilityProps, IAriaProps {
48
- // The id a TextInput's inputAccessoryViewID points at to dock above its keyboard.
49
- nativeID?: string;
50
- backgroundColor?: string;
51
- style?: IStyleProp<IViewStyle>;
52
- }
53
-
54
- // What the component itself takes as plain @Input()s: the full surface minus the accessibility
55
- // callbacks, which it exposes as real @Output() EventEmitters instead (see the class below),
56
- // mirroring Pressable's IAngularPressableInputs split.
57
- export type IAngularInputAccessoryViewInputs = Omit<
58
- IAngularInputAccessoryViewProps,
59
- | 'onAccessibilityAction'
60
- | 'onAccessibilityTap'
61
- | 'onMagicTap'
62
- | 'onAccessibilityEscape'
63
- >;
64
-
65
- @Component({
66
- selector: 'InputAccessoryView',
67
- standalone: true,
68
- hostDirectives: [
69
- { directive: SymbioteStyleInputDirective, inputs: ['style'] },
70
- ],
71
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
72
- imports: [InputAccessoryViewHost, SymbioteHostPropsDirective],
73
- changeDetection: ChangeDetectionStrategy.OnPush,
74
- template: `
75
- <symbiote-input-accessory-view [symbioteHostProps]="hostProps()">
76
- <ng-content></ng-content>
77
- </symbiote-input-accessory-view>
78
- `,
79
- })
80
- export class InputAccessoryView
81
- implements IAngularInputAccessoryViewInputs, OnChanges, DoCheck
82
- {
83
- @Input() nativeID?: string;
84
- @Input() backgroundColor?: string;
85
- @Input() style?: IStyleProp<IViewStyle>;
86
- @Output() readonly accessibilityAction = new EventEmitter<ISymbioteEvent>();
87
- @Output() readonly accessibilityTap = new EventEmitter<ISymbioteEvent>();
88
- @Output() readonly magicTap = new EventEmitter<ISymbioteEvent>();
89
- @Output() readonly accessibilityEscape = new EventEmitter<ISymbioteEvent>();
90
- @Input() testID?: string;
91
- @Input() accessible?: boolean;
92
- @Input() accessibilityLabel?: string;
93
- @Input() accessibilityHint?: string;
94
- @Input() accessibilityRole?: IAccessibilityProps['accessibilityRole'];
95
- @Input() accessibilityState?: IAccessibilityStateValue;
96
- @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
97
- @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
98
- @Input() accessibilityLabelledBy?: string | string[];
99
- @Input()
100
- importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
101
- @Input()
102
- accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
103
- @Input() screenReaderFocusable?: boolean;
104
- @Input() accessibilityViewIsModal?: boolean;
105
- @Input() accessibilityElementsHidden?: boolean;
106
- @Input() accessibilityIgnoresInvertColors?: boolean;
107
- @Input() accessibilityLanguage?: string;
108
- @Input() accessibilityRespondsToUserInteraction?: boolean;
109
- @Input() accessibilityShowsLargeContentViewer?: boolean;
110
- @Input() accessibilityLargeContentTitle?: string;
111
- @Input() role?: IAriaProps['role'];
112
- @Input('aria-label') ariaLabel?: string;
113
- @Input('aria-labelledby') ariaLabelledBy?: string;
114
- @Input('aria-live') ariaLive?: IAriaProps['aria-live'];
115
- @Input('aria-hidden') ariaHidden?: boolean;
116
- @Input('aria-busy') ariaBusy?: boolean;
117
- @Input('aria-checked') ariaChecked?: boolean | 'mixed';
118
- @Input('aria-disabled') ariaDisabled?: boolean;
119
- @Input('aria-expanded') ariaExpanded?: boolean;
120
- @Input('aria-selected') ariaSelected?: boolean;
121
- @Input('aria-modal') ariaModal?: boolean;
122
- @Input('aria-valuemax') ariaValueMax?: number;
123
- @Input('aria-valuemin') ariaValueMin?: number;
124
- @Input('aria-valuenow') ariaValueNow?: number;
125
- @Input('aria-valuetext') ariaValueText?: string;
126
-
127
- // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
128
- // onto (see anchorHostStyle's doc comment). InputAccessoryView has no inner ViewChild, so this
129
- // is the only ElementRef in the class.
130
- private readonly elementRef = inject(ElementRef);
131
-
132
- // Forward an engine event to the matching @Output(), narrowing the template's untyped $event.
133
- private emit(emitter: EventEmitter<ISymbioteEvent>, event: unknown): void {
134
- if (isSymbioteEvent(event)) emitter.emit(event);
135
- }
136
-
137
- // The four accessibility events are boolean-GATED Fabric events
138
- // (`.claude/rules/fabric-boolean-event-gates.md`). `.observed`-gated, mirroring Pressable's.
139
- private eventEmitterHandler(
140
- emitter: EventEmitter<ISymbioteEvent>,
141
- ): ((event: unknown) => void) | undefined {
142
- return emitter.observed ? event => this.emit(emitter, event) : undefined;
143
- }
144
-
145
- // renderInputAccessoryView owns the host-node assembly (shared with React/Vue); the adapter reads
146
- // the resolved host props off the Descriptor it returns.
147
- private get descriptor() {
148
- return renderInputAccessoryView({
149
- nativeID: this.nativeID,
150
- backgroundColor: this.backgroundColor,
151
- style: this.style,
152
- passthrough: resolveAccessibilityProps(this.accessibilityInputs()),
153
- });
154
- }
155
-
156
- // Bridges the non-reactive fields `hostProps` reads into the reactive graph, so it can memoize.
157
- // Plain fields read inside a computed() are UNTRACKED - something must signal "a dependency
158
- // changed" or the bag goes stale. Signal inputs would do this natively, but `input()` is visible
159
- // only to the AOT compiler and this package's unit suite runs on JIT (see the
160
- // `angular-adapter-change-detection` skill, §6); `signal()`/`computed()` are plain runtime APIs.
161
- private readonly hostPropsRevision = signal(0);
162
- // What the anchor's class-derived style was when the bag was last built (identity, not value).
163
- private lastAnchorStyle: unknown;
164
-
165
- ngOnChanges(): void {
166
- // The single moment Angular has finished writing every changed @Input for this pass.
167
- this.hostPropsRevision.update(revision => revision + 1);
168
- }
169
-
170
- // The anchor's class-derived style is NOT an @Input: `class="..."`/`[ngClass]` at the use site
171
- // resolves through the renderer's addClass onto this component's anchor host (see
172
- // anchorHostStyle's doc comment), so it never shows up in SimpleChanges and ngOnChanges alone
173
- // would leave a later class toggle stranded. ngDoCheck runs at exactly the cadence the old
174
- // getter was re-read, and bumps only on a real identity change.
175
- ngDoCheck(): void {
176
- const anchorStyle = anchorHostStyle(this.elementRef);
177
- if (anchorStyle === this.lastAnchorStyle) return;
178
- this.lastAnchorStyle = anchorStyle;
179
- this.hostPropsRevision.update(revision => revision + 1);
180
- }
181
-
182
- // The anchor's class-derived style goes FIRST, the Descriptor's resolved style SECOND —
183
- // flattenStyle's later-wins collapse keeps an explicit [style] winning over its ambient class.
184
- //
185
- // A computed(), not a getter: Angular re-reads a template getter on every refresh of this view
186
- // and `[symbioteHostProps]` compares by REFERENCE, so a freshly rebuilt (but identical) bag
187
- // re-pushes every key through renderer.setProperty -> the engine's prop routing - and this one
188
- // re-runs renderInputAccessoryView to build it.
189
- readonly hostProps = computed<Record<string, unknown>>(() => {
190
- this.hostPropsRevision();
191
- const descriptorProps = this.descriptor.props;
192
- return {
193
- ...descriptorProps,
194
- style: [anchorHostStyle(this.elementRef), descriptorProps.style],
195
- onAccessibilityAction: this.eventEmitterHandler(this.accessibilityAction),
196
- onAccessibilityTap: this.eventEmitterHandler(this.accessibilityTap),
197
- onMagicTap: this.eventEmitterHandler(this.magicTap),
198
- onAccessibilityEscape: this.eventEmitterHandler(this.accessibilityEscape),
199
- };
200
- });
201
-
202
- // Typed as the a11y intersection WITH the string index (the bag renderInputAccessoryView spreads
203
- // into the host props), so resolveAccessibilityProps's result stays assignable to passthrough.
204
- private accessibilityInputs(): IAccessibilityProps &
205
- IAriaProps &
206
- Record<string, unknown> {
207
- return {
208
- testID: this.testID,
209
- accessible: this.accessible,
210
- accessibilityLabel: this.accessibilityLabel,
211
- accessibilityHint: this.accessibilityHint,
212
- accessibilityRole: this.accessibilityRole,
213
- accessibilityState: this.accessibilityState,
214
- accessibilityValue: this.accessibilityValue,
215
- accessibilityActions: this.accessibilityActions,
216
- accessibilityLabelledBy: this.accessibilityLabelledBy,
217
- importantForAccessibility: this.importantForAccessibility,
218
- accessibilityLiveRegion: this.accessibilityLiveRegion,
219
- screenReaderFocusable: this.screenReaderFocusable,
220
- accessibilityViewIsModal: this.accessibilityViewIsModal,
221
- accessibilityElementsHidden: this.accessibilityElementsHidden,
222
- accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
223
- accessibilityLanguage: this.accessibilityLanguage,
224
- accessibilityRespondsToUserInteraction:
225
- this.accessibilityRespondsToUserInteraction,
226
- accessibilityShowsLargeContentViewer:
227
- this.accessibilityShowsLargeContentViewer,
228
- accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
229
- role: this.role,
230
- 'aria-label': this.ariaLabel,
231
- 'aria-labelledby': this.ariaLabelledBy,
232
- 'aria-live': this.ariaLive,
233
- 'aria-hidden': this.ariaHidden,
234
- 'aria-busy': this.ariaBusy,
235
- 'aria-checked': this.ariaChecked,
236
- 'aria-disabled': this.ariaDisabled,
237
- 'aria-expanded': this.ariaExpanded,
238
- 'aria-selected': this.ariaSelected,
239
- 'aria-modal': this.ariaModal,
240
- 'aria-valuemax': this.ariaValueMax,
241
- 'aria-valuemin': this.ariaValueMin,
242
- 'aria-valuenow': this.ariaValueNow,
243
- 'aria-valuetext': this.ariaValueText,
244
- };
245
- }
246
- }