@symbiote-native/angular 0.7.0 → 0.8.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 (158) hide show
  1. package/README.md +3 -3
  2. package/build/angular/bootstrap.js +1 -1
  3. package/build/angular/bootstrap.js.map +1 -1
  4. package/build/angular/components/activity-indicator/index.android.js +7 -2
  5. package/build/angular/components/activity-indicator/index.android.js.map +1 -1
  6. package/build/angular/components/activity-indicator/index.ios.js +3 -1
  7. package/build/angular/components/activity-indicator/index.ios.js.map +1 -1
  8. package/build/angular/components/activity-indicator/shared.d.ts +1 -1
  9. package/build/angular/components/activity-indicator/shared.js +1 -1
  10. package/build/angular/components/activity-indicator/shared.js.map +1 -1
  11. package/build/angular/components/button.js +13 -5
  12. package/build/angular/components/button.js.map +1 -1
  13. package/build/angular/components/flat-list/index.d.ts +1 -1
  14. package/build/angular/components/flat-list/index.js +47 -14
  15. package/build/angular/components/flat-list/index.js.map +1 -1
  16. package/build/angular/components/image/index.android.js +4 -2
  17. package/build/angular/components/image/index.android.js.map +1 -1
  18. package/build/angular/components/image/index.ios.js +4 -2
  19. package/build/angular/components/image/index.ios.js.map +1 -1
  20. package/build/angular/components/image/shared.js +18 -6
  21. package/build/angular/components/image/shared.js.map +1 -1
  22. package/build/angular/components/image-background.js +22 -8
  23. package/build/angular/components/image-background.js.map +1 -1
  24. package/build/angular/components/input-accessory-view/index.js +7 -2
  25. package/build/angular/components/input-accessory-view/index.js.map +1 -1
  26. package/build/angular/components/keyboard-avoiding-view/index.d.ts +1 -0
  27. package/build/angular/components/keyboard-avoiding-view/index.js +39 -9
  28. package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -1
  29. package/build/angular/components/modal/index.js +7 -2
  30. package/build/angular/components/modal/index.js.map +1 -1
  31. package/build/angular/components/pressable/index.d.ts +1 -1
  32. package/build/angular/components/pressable/index.js +6 -2
  33. package/build/angular/components/pressable/index.js.map +1 -1
  34. package/build/angular/components/refresh-control/index.js +3 -1
  35. package/build/angular/components/refresh-control/index.js.map +1 -1
  36. package/build/angular/components/safe-area-view/index.js +3 -1
  37. package/build/angular/components/safe-area-view/index.js.map +1 -1
  38. package/build/angular/components/scroll-view/index.android.js +44 -14
  39. package/build/angular/components/scroll-view/index.android.js.map +1 -1
  40. package/build/angular/components/scroll-view/index.ios.js +13 -5
  41. package/build/angular/components/scroll-view/index.ios.js.map +1 -1
  42. package/build/angular/components/scroll-view/projection.d.ts +32 -0
  43. package/build/angular/components/scroll-view/projection.js +212 -47
  44. package/build/angular/components/scroll-view/projection.js.map +1 -1
  45. package/build/angular/components/scroll-view/shared.js +28 -7
  46. package/build/angular/components/scroll-view/shared.js.map +1 -1
  47. package/build/angular/components/scroll-view/sticky-header.js +7 -3
  48. package/build/angular/components/scroll-view/sticky-header.js.map +1 -1
  49. package/build/angular/components/section-list/index.d.ts +6 -1
  50. package/build/angular/components/section-list/index.js +63 -18
  51. package/build/angular/components/section-list/index.js.map +1 -1
  52. package/build/angular/components/switch/index.android.js +17 -3
  53. package/build/angular/components/switch/index.android.js.map +1 -1
  54. package/build/angular/components/switch/index.ios.js +17 -3
  55. package/build/angular/components/switch/index.ios.js.map +1 -1
  56. package/build/angular/components/switch/shared.d.ts +1 -1
  57. package/build/angular/components/switch/shared.js +5 -2
  58. package/build/angular/components/switch/shared.js.map +1 -1
  59. package/build/angular/components/text-input.d.ts +1 -1
  60. package/build/angular/components/text-input.js +25 -5
  61. package/build/angular/components/text-input.js.map +1 -1
  62. package/build/angular/components/touchable/index.d.ts +29 -7
  63. package/build/angular/components/touchable/index.js +246 -69
  64. package/build/angular/components/touchable/index.js.map +1 -1
  65. package/build/angular/components/touchable-native-feedback/index.js +2 -2
  66. package/build/angular/components/touchable-native-feedback/index.js.map +1 -1
  67. package/build/angular/components/virtualized-list/directives.js +4 -0
  68. package/build/angular/components/virtualized-list/directives.js.map +1 -1
  69. package/build/angular/components/virtualized-list/index.d.ts +5 -2
  70. package/build/angular/components/virtualized-list/index.js +197 -60
  71. package/build/angular/components/virtualized-list/index.js.map +1 -1
  72. package/build/angular/components/virtualized-section-list/directives.js.map +1 -1
  73. package/build/angular/components/virtualized-section-list/index.d.ts +18 -1
  74. package/build/angular/components/virtualized-section-list/index.js +90 -21
  75. package/build/angular/components/virtualized-section-list/index.js.map +1 -1
  76. package/build/angular/components.d.ts +1 -1
  77. package/build/angular/components.js.map +1 -1
  78. package/build/angular/create-portal/index.js +5 -1
  79. package/build/angular/create-portal/index.js.map +1 -1
  80. package/build/angular/create-tunnel/index.js.map +1 -1
  81. package/build/angular/descriptor-to-angular/index.js +3 -1
  82. package/build/angular/descriptor-to-angular/index.js.map +1 -1
  83. package/build/angular/diagnostics.d.ts +33 -0
  84. package/build/angular/diagnostics.js +82 -0
  85. package/build/angular/diagnostics.js.map +1 -0
  86. package/build/angular/host-instance/index.js +1 -1
  87. package/build/angular/host-instance/index.js.map +1 -1
  88. package/build/angular/index.d.ts +5 -2
  89. package/build/angular/index.js +15 -1
  90. package/build/angular/index.js.map +1 -1
  91. package/build/angular/modules/animated/create-animated-component.js +27 -9
  92. package/build/angular/modules/animated/create-animated-component.js.map +1 -1
  93. package/build/angular/modules/app-registry/index.js.map +1 -1
  94. package/build/angular/modules/status-bar/index.js +1 -1
  95. package/build/angular/modules/status-bar/index.js.map +1 -1
  96. package/build/angular/primitives/index.d.ts +19 -2
  97. package/build/angular/primitives/index.js +39 -3
  98. package/build/angular/primitives/index.js.map +1 -1
  99. package/build/angular/primitives/shared.d.ts +9 -1
  100. package/build/angular/primitives/shared.js +49 -3
  101. package/build/angular/primitives/shared.js.map +1 -1
  102. package/build/angular/render/index.js +48 -5
  103. package/build/angular/render/index.js.map +1 -1
  104. package/build/angular/renderer/index.d.ts +1 -0
  105. package/build/angular/renderer/index.js +37 -2
  106. package/build/angular/renderer/index.js.map +1 -1
  107. package/build/angular/services/color-scheme.service.js.map +1 -1
  108. package/build/angular/services/window-dimensions.service.js +1 -1
  109. package/build/angular/services/window-dimensions.service.js.map +1 -1
  110. package/package.json +5 -5
  111. package/src/bootstrap.ts +4 -1
  112. package/src/components/activity-indicator/index.android.ts +7 -2
  113. package/src/components/activity-indicator/index.ios.ts +3 -1
  114. package/src/components/activity-indicator/shared.ts +32 -13
  115. package/src/components/button.ts +19 -6
  116. package/src/components/flat-list/index.ts +91 -29
  117. package/src/components/image/index.android.ts +9 -2
  118. package/src/components/image/index.ios.ts +9 -2
  119. package/src/components/image/shared.ts +58 -19
  120. package/src/components/image-background.ts +29 -10
  121. package/src/components/input-accessory-view/index.ts +27 -10
  122. package/src/components/keyboard-avoiding-view/index.ts +55 -15
  123. package/src/components/modal/index.ts +22 -8
  124. package/src/components/pressable/index.ts +51 -21
  125. package/src/components/refresh-control/index.ts +22 -8
  126. package/src/components/safe-area-view/index.ts +16 -7
  127. package/src/components/scroll-view/index.android.ts +31 -9
  128. package/src/components/scroll-view/index.ios.ts +17 -4
  129. package/src/components/scroll-view/projection.ts +290 -63
  130. package/src/components/scroll-view/shared.ts +93 -26
  131. package/src/components/scroll-view/sticky-header.ts +25 -8
  132. package/src/components/section-list/index.ts +61 -19
  133. package/src/components/switch/index.android.ts +14 -3
  134. package/src/components/switch/index.ios.ts +14 -3
  135. package/src/components/switch/shared.ts +15 -4
  136. package/src/components/text-input.ts +45 -13
  137. package/src/components/touchable/index.ts +296 -72
  138. package/src/components/touchable-native-feedback/index.ts +32 -10
  139. package/src/components/virtualized-list/directives.ts +19 -5
  140. package/src/components/virtualized-list/index.ts +274 -72
  141. package/src/components/virtualized-section-list/directives.ts +6 -3
  142. package/src/components/virtualized-section-list/index.ts +146 -34
  143. package/src/components.ts +4 -1
  144. package/src/create-portal/index.ts +8 -2
  145. package/src/create-tunnel/index.ts +3 -1
  146. package/src/descriptor-to-angular/index.ts +29 -8
  147. package/src/diagnostics.ts +138 -0
  148. package/src/host-instance/index.ts +9 -3
  149. package/src/index.ts +31 -2
  150. package/src/modules/animated/create-animated-component.ts +44 -15
  151. package/src/modules/app-registry/index.ts +3 -1
  152. package/src/modules/status-bar/index.ts +13 -4
  153. package/src/primitives/index.ts +46 -2
  154. package/src/primitives/shared.ts +70 -9
  155. package/src/render/index.ts +56 -6
  156. package/src/renderer/index.ts +76 -14
  157. package/src/services/color-scheme.service.ts +3 -1
  158. package/src/services/window-dimensions.service.ts +11 -4
@@ -2,7 +2,7 @@
2
2
  // keyboard's way as it shows/hides. The inset math + the behavior → style/structure decision
3
3
  // live framework-agnostic in @symbiote-native/components (render-keyboard-avoiding-view), shared verbatim
4
4
  // with React/Vue; Angular supplies only the lifecycle: a plain inset field, ngOnInit subscribes to
5
- // the core Keyboard module (show / changeFrame / hide) and markForCheck pulls the OnPush view (the
5
+ // the core Keyboard module (the host's show / hide pair) and markForCheck pulls the OnPush view (the
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
@@ -26,8 +26,10 @@ import {
26
26
  } from '@angular/core';
27
27
  import {
28
28
  computeInset,
29
+ keyboardAvoidingEventNamesFor,
29
30
  readKeyboardFrame,
30
31
  readLayoutFrame,
32
+ readPrefersCrossFadeTransitions,
31
33
  resolveAccessibilityProps,
32
34
  resolveKeyboardAvoidingLayout,
33
35
  DEFAULT_VERTICAL_OFFSET,
@@ -40,7 +42,7 @@ import {
40
42
  } from '@symbiote-native/components';
41
43
  import {
42
44
  Keyboard,
43
- KEYBOARD_EVENT,
45
+ Platform,
44
46
  dlog,
45
47
  isSymbioteEvent,
46
48
  type IEventSubscription,
@@ -60,7 +62,8 @@ export type { IKeyboardAvoidingBehavior } from '@symbiote-native/components';
60
62
  // Mirrors React's IKeyboardAvoidingViewProps minus children (Angular takes children via
61
63
  // <ng-content>), declared per-adapter over the shared accessibility base since a framework-specific
62
64
  // children field keeps it from being fully shared across adapters.
63
- export interface IAngularKeyboardAvoidingViewProps extends IAccessibilityProps, IAriaProps {
65
+ export interface IAngularKeyboardAvoidingViewProps
66
+ extends IAccessibilityProps, IAriaProps {
64
67
  behavior?: IKeyboardAvoidingBehavior;
65
68
  enabled?: boolean;
66
69
  keyboardVerticalOffset?: number;
@@ -84,7 +87,9 @@ export type IAngularKeyboardAvoidingViewInputs = Omit<
84
87
  @Component({
85
88
  selector: 'KeyboardAvoidingView',
86
89
  standalone: true,
87
- hostDirectives: [{ directive: SymbioteStyleInputDirective, inputs: ['style'] }],
90
+ hostDirectives: [
91
+ { directive: SymbioteStyleInputDirective, inputs: ['style'] },
92
+ ],
88
93
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
89
94
  imports: [ViewHost, SymbioteHostPropsDirective],
90
95
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -110,7 +115,9 @@ export type IAngularKeyboardAvoidingViewInputs = Omit<
110
115
  </symbiote-view>
111
116
  `,
112
117
  })
113
- export class KeyboardAvoidingView implements IAngularKeyboardAvoidingViewInputs, OnInit, OnDestroy {
118
+ export class KeyboardAvoidingView
119
+ implements IAngularKeyboardAvoidingViewInputs, OnInit, OnDestroy
120
+ {
114
121
  @Input() behavior?: IKeyboardAvoidingBehavior;
115
122
  @Input() enabled?: boolean;
116
123
  @Input() keyboardVerticalOffset?: number;
@@ -135,8 +142,10 @@ export class KeyboardAvoidingView implements IAngularKeyboardAvoidingViewInputs,
135
142
  @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
136
143
  @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
137
144
  @Input() accessibilityLabelledBy?: string | string[];
138
- @Input() importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
139
- @Input() accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
145
+ @Input()
146
+ importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
147
+ @Input()
148
+ accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
140
149
  @Input() screenReaderFocusable?: boolean;
141
150
  @Input() accessibilityViewIsModal?: boolean;
142
151
  @Input() accessibilityElementsHidden?: boolean;
@@ -168,6 +177,12 @@ export class KeyboardAvoidingView implements IAngularKeyboardAvoidingViewInputs,
168
177
  // keyboard event's inset math (React's frameRef / initialHeightRef, Vue's frame / initialHeight).
169
178
  private frame?: IMeasuredFrame;
170
179
  private initialHeight?: number;
180
+ // The iOS "Prefer Cross-Fade Transitions" setting, read once per mount. Deliberately a plain
181
+ // field and NOT markForCheck'd when the promise lands: it is a device setting that cannot change
182
+ // mid-session, and it feeds only the NEXT keyboard event's math — never the current render — so
183
+ // under zoneless CD there is nothing to repaint at resolve time. The keyboard event that does use
184
+ // it already calls markForCheck itself.
185
+ private prefersCrossFadeTransitions = false;
171
186
  private subscriptions: IEventSubscription[] = [];
172
187
 
173
188
  private readonly changeDetector = inject(ChangeDetectorRef);
@@ -177,11 +192,21 @@ export class KeyboardAvoidingView implements IAngularKeyboardAvoidingViewInputs,
177
192
  private readonly elementRef = inject(ElementRef);
178
193
 
179
194
  ngOnInit(): void {
195
+ // TWO events, picked per host, never three: iOS takes the will* pair so the view rides up with
196
+ // the keyboard animation, Android the did* pair. The change-frame notification is deliberately
197
+ // absent — with an undocked/split/floating iOS keyboard it fires BEFORE the hide, so listening
198
+ // to it applies a frame captured mid-dismissal (RN KeyboardAvoidingView.js's own comment).
199
+ const events = keyboardAvoidingEventNamesFor(Platform.OS);
180
200
  this.subscriptions = [
181
- Keyboard.addListener(KEYBOARD_EVENT.didShow, payload => this.onShow(payload)),
182
- Keyboard.addListener(KEYBOARD_EVENT.didChangeFrame, payload => this.onShow(payload)),
183
- Keyboard.addListener(KEYBOARD_EVENT.didHide, () => this.onHide()),
201
+ Keyboard.addListener(events.show, payload => this.onShow(payload)),
202
+ Keyboard.addListener(events.hide, () => this.onHide()),
184
203
  ];
204
+ // The core wrapper, not AccessibilityInfo directly: the engine's iOS getter REJECTS on a
205
+ // native error (RN parity), and nobody awaits this read, so an unwrapped call would surface
206
+ // as an unhandled rejection. The wrapper answers false on a failed read.
207
+ void readPrefersCrossFadeTransitions().then(enabled => {
208
+ this.prefersCrossFadeTransitions = enabled;
209
+ });
185
210
  }
186
211
 
187
212
  ngOnDestroy(): void {
@@ -192,7 +217,17 @@ export class KeyboardAvoidingView implements IAngularKeyboardAvoidingViewInputs,
192
217
  private onShow(payload: unknown): void {
193
218
  const keyboard = readKeyboardFrame(payload);
194
219
  const offset = this.keyboardVerticalOffset ?? DEFAULT_VERTICAL_OFFSET;
195
- const next = computeInset(this.frame, keyboard, offset);
220
+ const next = computeInset(this.frame, keyboard, offset, {
221
+ // Read off the field at event time, not captured when the subscription was built: `behavior`
222
+ // is an @Input that can change under a long-lived subscription, and a stale one keeps
223
+ // applying the old mode's math (it gates the previous-inset correction below).
224
+ behavior: this.behavior,
225
+ // The inset CURRENTLY applied (RN's this.state.bottom), read off the field at event time so
226
+ // 'height' mode's fixpoint correction sees the live value: that mode SHRINKS the wrapper by
227
+ // the inset, so the next onLayout reports a frame shorter by exactly that much.
228
+ previousInset: this.inset,
229
+ prefersCrossFadeTransitions: this.prefersCrossFadeTransitions,
230
+ });
196
231
  dlog(`KeyboardAvoidingView show -> inset ${next}`);
197
232
  this.inset = next;
198
233
  this.changeDetector.markForCheck();
@@ -211,7 +246,8 @@ export class KeyboardAvoidingView implements IAngularKeyboardAvoidingViewInputs,
211
246
  const measured = readLayoutFrame(event.nativeEvent.layout);
212
247
  if (measured !== undefined) {
213
248
  this.frame = measured;
214
- if (this.initialHeight === undefined) this.initialHeight = measured.height;
249
+ if (this.initialHeight === undefined)
250
+ this.initialHeight = measured.height;
215
251
  }
216
252
  this.layout.emit(event);
217
253
  }
@@ -244,7 +280,9 @@ export class KeyboardAvoidingView implements IAngularKeyboardAvoidingViewInputs,
244
280
  }
245
281
 
246
282
  get innerStyle(): IStyleProp<IViewStyle> | undefined {
247
- return this.resolvedLayout.kind === 'nested' ? this.resolvedLayout.innerStyle : undefined;
283
+ return this.resolvedLayout.kind === 'nested'
284
+ ? this.resolvedLayout.innerStyle
285
+ : undefined;
248
286
  }
249
287
 
250
288
  // The wrapper's full prop bag (style + identity + a11y) folded for `[symbioteHostProps]`,
@@ -286,8 +324,10 @@ export class KeyboardAvoidingView implements IAngularKeyboardAvoidingViewInputs,
286
324
  accessibilityElementsHidden: this.accessibilityElementsHidden,
287
325
  accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
288
326
  accessibilityLanguage: this.accessibilityLanguage,
289
- accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
290
- accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
327
+ accessibilityRespondsToUserInteraction:
328
+ this.accessibilityRespondsToUserInteraction,
329
+ accessibilityShowsLargeContentViewer:
330
+ this.accessibilityShowsLargeContentViewer,
291
331
  accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
292
332
  role: this.role,
293
333
  'aria-label': this.ariaLabel,
@@ -101,7 +101,9 @@ export type IAngularModalInputs = Omit<
101
101
  @Component({
102
102
  selector: 'Modal',
103
103
  standalone: true,
104
- hostDirectives: [{ directive: SymbioteStyleInputDirective, inputs: ['style'] }],
104
+ hostDirectives: [
105
+ { directive: SymbioteStyleInputDirective, inputs: ['style'] },
106
+ ],
105
107
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
106
108
  imports: [ModalHost, ViewHost, SymbioteHostPropsDirective],
107
109
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -154,8 +156,10 @@ export class Modal implements IAngularModalInputs, OnInit, OnChanges, DoCheck {
154
156
  @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
155
157
  @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
156
158
  @Input() accessibilityLabelledBy?: string | string[];
157
- @Input() importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
158
- @Input() accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
159
+ @Input()
160
+ importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
161
+ @Input()
162
+ accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
159
163
  @Input() screenReaderFocusable?: boolean;
160
164
  @Input() accessibilityViewIsModal?: boolean;
161
165
  @Input() accessibilityElementsHidden?: boolean;
@@ -216,7 +220,10 @@ export class Modal implements IAngularModalInputs, OnInit, OnChanges, DoCheck {
216
220
  // Queue on a microtask so the reducer runs AFTER this CD pass renders with the OLD state —
217
221
  // the keep-alive frame. A synchronous dispatch here would unmount in the same pass.
218
222
  queueMicrotask(() => {
219
- this.state = modalReducer(this.state, isVisible ? { type: 'show' } : { type: 'hide' });
223
+ this.state = modalReducer(
224
+ this.state,
225
+ isVisible ? { type: 'show' } : { type: 'hide' },
226
+ );
220
227
  this.changeDetector.markForCheck();
221
228
  });
222
229
  }
@@ -269,7 +276,10 @@ export class Modal implements IAngularModalInputs, OnInit, OnChanges, DoCheck {
269
276
  readonly hostProps = computed<Record<string, unknown>>(() => {
270
277
  this.hostPropsRevision();
271
278
  const descriptorProps = this.descriptor.props;
272
- return { ...descriptorProps, style: [anchorHostStyle(this.elementRef), descriptorProps.style] };
279
+ return {
280
+ ...descriptorProps,
281
+ style: [anchorHostStyle(this.elementRef), descriptorProps.style],
282
+ };
273
283
  });
274
284
 
275
285
  get containerStyle(): unknown {
@@ -283,7 +293,9 @@ export class Modal implements IAngularModalInputs, OnInit, OnChanges, DoCheck {
283
293
 
284
294
  // Typed as the a11y intersection WITH the string index (the bag renderModal spreads into the
285
295
  // host props), so resolveAccessibilityProps's result stays assignable to passthrough.
286
- private accessibilityInputs(): IAccessibilityProps & IAriaProps & Record<string, unknown> {
296
+ private accessibilityInputs(): IAccessibilityProps &
297
+ IAriaProps &
298
+ Record<string, unknown> {
287
299
  return {
288
300
  testID: this.testID,
289
301
  accessible: this.accessible,
@@ -301,8 +313,10 @@ export class Modal implements IAngularModalInputs, OnInit, OnChanges, DoCheck {
301
313
  accessibilityElementsHidden: this.accessibilityElementsHidden,
302
314
  accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
303
315
  accessibilityLanguage: this.accessibilityLanguage,
304
- accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
305
- accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
316
+ accessibilityRespondsToUserInteraction:
317
+ this.accessibilityRespondsToUserInteraction,
318
+ accessibilityShowsLargeContentViewer:
319
+ this.accessibilityShowsLargeContentViewer,
306
320
  accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
307
321
  role: this.role,
308
322
  'aria-label': this.ariaLabel,
@@ -51,13 +51,17 @@ import {
51
51
  ViewHost,
52
52
  } from '../../primitives';
53
53
 
54
- export type { IPressState, IPressableAndroidRippleConfig } from '@symbiote-native/components';
54
+ export type {
55
+ IPressState,
56
+ IPressableAndroidRippleConfig,
57
+ } from '@symbiote-native/components';
55
58
 
56
59
  // The full logical Pressable surface, callback-shaped press/hover events included. Touchable* and
57
60
  // TouchableNativeFeedback still take their OWN onPress/onPressIn/... as @Input() callbacks (that is
58
61
  // a separate, not-yet-converted decision) and derive their public prop types from this - so it keeps
59
62
  // the callback fields even though the Pressable component below no longer implements them directly.
60
- export interface IAngularPressableProps extends IAccessibilityProps, IAriaProps {
63
+ export interface IAngularPressableProps
64
+ extends IAccessibilityProps, IAriaProps {
61
65
  onPress?: IPressHandler;
62
66
  onPressIn?: IPressHandler;
63
67
  onPressOut?: IPressHandler;
@@ -83,7 +87,8 @@ export interface IAngularPressableProps extends IAccessibilityProps, IAriaProps
83
87
  nextFocusLeft?: number;
84
88
  nextFocusRight?: number;
85
89
  nextFocusUp?: number;
86
- style?: IStyleProp<IViewStyle> | ((state: IPressState) => IStyleProp<IViewStyle>);
90
+ style?:
91
+ IStyleProp<IViewStyle> | ((state: IPressState) => IStyleProp<IViewStyle>);
87
92
  }
88
93
 
89
94
  // What the Pressable component itself takes as plain @Input()s: the full surface minus the press/
@@ -105,7 +110,9 @@ export type IAngularPressableInputs = Omit<
105
110
  | 'onAccessibilityEscape'
106
111
  >;
107
112
 
108
- function isStyleFn(value: unknown): value is (state: IPressState) => IStyleProp<IViewStyle> {
113
+ function isStyleFn(
114
+ value: unknown,
115
+ ): value is (state: IPressState) => IStyleProp<IViewStyle> {
109
116
  return typeof value === 'function';
110
117
  }
111
118
 
@@ -118,7 +125,9 @@ function asSymbioteEvent(event: unknown): ISymbioteEvent | undefined {
118
125
  @Component({
119
126
  selector: 'Pressable, symbiote-pressable',
120
127
  standalone: true,
121
- hostDirectives: [{ directive: SymbioteStyleInputDirective, inputs: ['style'] }],
128
+ hostDirectives: [
129
+ { directive: SymbioteStyleInputDirective, inputs: ['style'] },
130
+ ],
122
131
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
123
132
  imports: [ViewHost, SymbioteHostPropsDirective],
124
133
  template: `
@@ -186,10 +195,13 @@ export class Pressable implements IAngularPressableInputs, OnChanges, DoCheck {
186
195
  @Input() accessibilityRole?: IAngularPressableProps['accessibilityRole'];
187
196
  @Input() accessibilityState?: IAccessibilityStateValue;
188
197
  @Input() accessibilityValue?: IAngularPressableProps['accessibilityValue'];
189
- @Input() accessibilityActions?: IAngularPressableProps['accessibilityActions'];
198
+ @Input()
199
+ accessibilityActions?: IAngularPressableProps['accessibilityActions'];
190
200
  @Input() accessibilityLabelledBy?: string | string[];
191
- @Input() importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
192
- @Input() accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
201
+ @Input()
202
+ importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
203
+ @Input()
204
+ accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
193
205
  @Input() screenReaderFocusable?: boolean;
194
206
  @Input() accessibilityViewIsModal?: boolean;
195
207
  @Input() accessibilityElementsHidden?: boolean;
@@ -215,7 +227,8 @@ export class Pressable implements IAngularPressableInputs, OnChanges, DoCheck {
215
227
  @Input() id?: string;
216
228
  @Input() role?: IAngularPressableProps['role'];
217
229
 
218
- @ViewChild('host', { read: ElementRef }) private hostElement?: ElementRef<unknown>;
230
+ @ViewChild('host', { read: ElementRef })
231
+ private hostElement?: ElementRef<unknown>;
219
232
 
220
233
  // INTERNAL mutable state, driven by the press machine rather than by an @Input, so ngOnChanges
221
234
  // can never cover it - it carries its OWN signal, which is what lets the memoized bag below stay
@@ -293,7 +306,10 @@ export class Pressable implements IAngularPressableInputs, OnChanges, DoCheck {
293
306
  accessibilityLabel: this.accessibilityLabel,
294
307
  accessibilityHint: this.accessibilityHint,
295
308
  accessibilityRole: this.accessibilityRole,
296
- accessibilityState: resolveDisabledAccessibilityState(this.accessibilityState, this.disabled),
309
+ accessibilityState: resolveDisabledAccessibilityState(
310
+ this.accessibilityState,
311
+ this.disabled,
312
+ ),
297
313
  accessibilityValue: this.accessibilityValue,
298
314
  accessibilityActions: this.accessibilityActions,
299
315
  accessibilityLabelledBy: this.accessibilityLabelledBy,
@@ -304,8 +320,10 @@ export class Pressable implements IAngularPressableInputs, OnChanges, DoCheck {
304
320
  accessibilityElementsHidden: this.accessibilityElementsHidden,
305
321
  accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
306
322
  accessibilityLanguage: this.accessibilityLanguage,
307
- accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
308
- accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
323
+ accessibilityRespondsToUserInteraction:
324
+ this.accessibilityRespondsToUserInteraction,
325
+ accessibilityShowsLargeContentViewer:
326
+ this.accessibilityShowsLargeContentViewer,
309
327
  accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
310
328
  'aria-label': this.ariaLabel,
311
329
  'aria-busy': this.ariaBusy,
@@ -327,7 +345,9 @@ export class Pressable implements IAngularPressableInputs, OnChanges, DoCheck {
327
345
  }
328
346
 
329
347
  get resolvedRippleProps(): Record<string, unknown> | undefined {
330
- return this.android_ripple === undefined ? undefined : rippleProps(this.android_ripple);
348
+ return this.android_ripple === undefined
349
+ ? undefined
350
+ : rippleProps(this.android_ripple);
331
351
  }
332
352
 
333
353
  // Flat bag for `[symbioteHostProps]` (Renderer2.setProperty per key) - see primitives/shared.ts.
@@ -352,32 +372,38 @@ export class Pressable implements IAngularPressableInputs, OnChanges, DoCheck {
352
372
  accessible: this.accessible,
353
373
  ...this.foldedAccessibility,
354
374
  android_disableSound: this.android_disableSound,
355
- nativeBackgroundAndroid: this.resolvedRippleProps?.nativeBackgroundAndroid,
356
- nativeForegroundAndroid: this.resolvedRippleProps?.nativeForegroundAndroid,
375
+ nativeBackgroundAndroid:
376
+ this.resolvedRippleProps?.nativeBackgroundAndroid,
377
+ nativeForegroundAndroid:
378
+ this.resolvedRippleProps?.nativeForegroundAndroid,
357
379
  };
358
380
  });
359
381
 
360
382
  handlePressIn(event: unknown): void {
361
383
  const symbioteEvent = asSymbioteEvent(event);
362
- if (shouldSuppressPress(this.disabled) || symbioteEvent === undefined) return;
384
+ if (shouldSuppressPress(this.disabled) || symbioteEvent === undefined)
385
+ return;
363
386
  this.handlers.handlePressIn(symbioteEvent);
364
387
  }
365
388
 
366
389
  handlePressOut(event: unknown): void {
367
390
  const symbioteEvent = asSymbioteEvent(event);
368
- if (shouldSuppressPress(this.disabled) || symbioteEvent === undefined) return;
391
+ if (shouldSuppressPress(this.disabled) || symbioteEvent === undefined)
392
+ return;
369
393
  this.handlers.handlePressOut(symbioteEvent);
370
394
  }
371
395
 
372
396
  handlePress(event: unknown): void {
373
397
  const symbioteEvent = asSymbioteEvent(event);
374
- if (shouldSuppressPress(this.disabled) || symbioteEvent === undefined) return;
398
+ if (shouldSuppressPress(this.disabled) || symbioteEvent === undefined)
399
+ return;
375
400
  this.handlers.handlePress(symbioteEvent);
376
401
  }
377
402
 
378
403
  handleResponderMove(event: unknown): void {
379
404
  const symbioteEvent = asSymbioteEvent(event);
380
- if (shouldSuppressPress(this.disabled) || symbioteEvent === undefined) return;
405
+ if (shouldSuppressPress(this.disabled) || symbioteEvent === undefined)
406
+ return;
381
407
  this.handlers.handleResponderMove(symbioteEvent);
382
408
  }
383
409
 
@@ -398,14 +424,18 @@ export class Pressable implements IAngularPressableInputs, OnChanges, DoCheck {
398
424
  // is listening anyway, mirroring core's noteHoverNoop but off `.observed` instead of an @Input.
399
425
  private noteHoverNoop(): void {
400
426
  if (this.hoverIn.observed || this.hoverOut.observed) {
401
- dlog('Pressable hover is a no-op on this host (no pointer-enter/leave event)');
427
+ dlog(
428
+ 'Pressable hover is a no-op on this host (no pointer-enter/leave event)',
429
+ );
402
430
  }
403
431
  }
404
432
 
405
433
  // Wraps an @Output() as an IPressHandler only while it has a subscriber, so an unbound
406
434
  // (longPress) still skips arming the timer, matching createPressHandlers' "undefined means
407
435
  // nobody cares" contract.
408
- private emitterHandler(emitter: EventEmitter<ISymbioteEvent>): IPressHandler | undefined {
436
+ private emitterHandler(
437
+ emitter: EventEmitter<ISymbioteEvent>,
438
+ ): IPressHandler | undefined {
409
439
  return emitter.observed ? event => emitter.emit(event) : undefined;
410
440
  }
411
441
 
@@ -60,7 +60,8 @@ type IHostProps = Record<string, unknown>;
60
60
  // via <ng-content>), declared per-adapter over the shared accessibility base since the framework-specific
61
61
  // children slot keeps it from being fully shared across adapters. Read the React reference for the
62
62
  // native prop names.
63
- export interface IAngularRefreshControlProps extends IAccessibilityProps, IAriaProps {
63
+ export interface IAngularRefreshControlProps
64
+ extends IAccessibilityProps, IAriaProps {
64
65
  refreshing: boolean;
65
66
  // RN's onRefresh is `() => void | Promise<void>`, the handler may be async; the promise is
66
67
  // fire-and-forget (native already starts refreshing on the gesture).
@@ -97,7 +98,9 @@ export type IAngularRefreshControlInputs = Omit<
97
98
  @Component({
98
99
  selector: 'RefreshControl',
99
100
  standalone: true,
100
- hostDirectives: [{ directive: SymbioteStyleInputDirective, inputs: ['style'] }],
101
+ hostDirectives: [
102
+ { directive: SymbioteStyleInputDirective, inputs: ['style'] },
103
+ ],
101
104
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
102
105
  imports: [RefreshControlHost, SymbioteHostPropsDirective],
103
106
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -116,7 +119,12 @@ export type IAngularRefreshControlInputs = Omit<
116
119
  `,
117
120
  })
118
121
  export class RefreshControl
119
- implements IAngularRefreshControlInputs, OnInit, OnChanges, DoCheck, AfterViewInit
122
+ implements
123
+ IAngularRefreshControlInputs,
124
+ OnInit,
125
+ OnChanges,
126
+ DoCheck,
127
+ AfterViewInit
120
128
  {
121
129
  // Controlled prop the parent owns; required to match the React reference surface.
122
130
  @Input({ required: true }) refreshing!: boolean;
@@ -142,8 +150,10 @@ export class RefreshControl
142
150
  @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
143
151
  @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
144
152
  @Input() accessibilityLabelledBy?: string | string[];
145
- @Input() importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
146
- @Input() accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
153
+ @Input()
154
+ importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
155
+ @Input()
156
+ accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
147
157
  @Input() screenReaderFocusable?: boolean;
148
158
  @Input() accessibilityViewIsModal?: boolean;
149
159
  @Input() accessibilityElementsHidden?: boolean;
@@ -218,7 +228,9 @@ export class RefreshControl
218
228
  this.lastNativeRefreshing = this.refreshing;
219
229
  return;
220
230
  }
221
- this.syncNativeRefreshing(this.refreshNativeNode ?? this.host?.nativeElement);
231
+ this.syncNativeRefreshing(
232
+ this.refreshNativeNode ?? this.host?.nativeElement,
233
+ );
222
234
  }
223
235
 
224
236
  // Native starts the spinner before JS runs. Mirror RN's RefreshControl controlled-component
@@ -303,8 +315,10 @@ export class RefreshControl
303
315
  accessibilityElementsHidden: this.accessibilityElementsHidden,
304
316
  accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
305
317
  accessibilityLanguage: this.accessibilityLanguage,
306
- accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
307
- accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
318
+ accessibilityRespondsToUserInteraction:
319
+ this.accessibilityRespondsToUserInteraction,
320
+ accessibilityShowsLargeContentViewer:
321
+ this.accessibilityShowsLargeContentViewer,
308
322
  accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
309
323
  role: this.role,
310
324
  'aria-label': this.ariaLabel,
@@ -42,7 +42,8 @@ import {
42
42
  // Mirrors React's ISafeAreaViewProps minus children (Angular takes children via <ng-content>),
43
43
  // declared per-adapter over the shared accessibility base since the framework-specific children
44
44
  // slot keeps it from being fully shared across adapters.
45
- export interface IAngularSafeAreaViewProps extends IAccessibilityProps, IAriaProps {
45
+ export interface IAngularSafeAreaViewProps
46
+ extends IAccessibilityProps, IAriaProps {
46
47
  style?: IStyleProp<IViewStyle>;
47
48
  onLayout?: (event: ISymbioteEvent) => void;
48
49
  }
@@ -62,7 +63,9 @@ export type IAngularSafeAreaViewInputs = Omit<
62
63
  @Component({
63
64
  selector: 'SafeAreaView',
64
65
  standalone: true,
65
- hostDirectives: [{ directive: SymbioteStyleInputDirective, inputs: ['style'] }],
66
+ hostDirectives: [
67
+ { directive: SymbioteStyleInputDirective, inputs: ['style'] },
68
+ ],
66
69
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
67
70
  imports: [SafeAreaViewHost, SymbioteHostPropsDirective],
68
71
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -79,7 +82,9 @@ export type IAngularSafeAreaViewInputs = Omit<
79
82
  </symbiote-safe-area-view>
80
83
  `,
81
84
  })
82
- export class SafeAreaView implements IAngularSafeAreaViewInputs, OnChanges, DoCheck {
85
+ export class SafeAreaView
86
+ implements IAngularSafeAreaViewInputs, OnChanges, DoCheck
87
+ {
83
88
  @Input() style?: IStyleProp<IViewStyle>;
84
89
  // Real @Output()s, not `[onX]="…"` callbacks. Safe to name `layout` the same as the native
85
90
  // `layout` event fired inside this component's own template — the engine's bubble() treats
@@ -99,8 +104,10 @@ export class SafeAreaView implements IAngularSafeAreaViewInputs, OnChanges, DoCh
99
104
  @Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
100
105
  @Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
101
106
  @Input() accessibilityLabelledBy?: string | string[];
102
- @Input() importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
103
- @Input() accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
107
+ @Input()
108
+ importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
109
+ @Input()
110
+ accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
104
111
  @Input() screenReaderFocusable?: boolean;
105
112
  @Input() accessibilityViewIsModal?: boolean;
106
113
  @Input() accessibilityElementsHidden?: boolean;
@@ -199,8 +206,10 @@ export class SafeAreaView implements IAngularSafeAreaViewInputs, OnChanges, DoCh
199
206
  accessibilityElementsHidden: this.accessibilityElementsHidden,
200
207
  accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
201
208
  accessibilityLanguage: this.accessibilityLanguage,
202
- accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
203
- accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
209
+ accessibilityRespondsToUserInteraction:
210
+ this.accessibilityRespondsToUserInteraction,
211
+ accessibilityShowsLargeContentViewer:
212
+ this.accessibilityShowsLargeContentViewer,
204
213
  accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
205
214
  role: this.role,
206
215
  'aria-label': this.ariaLabel,
@@ -43,7 +43,11 @@ import {
43
43
  SymbioteHostPropsDirective,
44
44
  SymbioteStyleInputDirective,
45
45
  } from '../../primitives';
46
- import { ScrollViewBase, ScrollViewProjectionDirective, SCROLL_VIEW_INPUTS } from './shared';
46
+ import {
47
+ ScrollViewBase,
48
+ ScrollViewProjectionDirective,
49
+ SCROLL_VIEW_INPUTS,
50
+ } from './shared';
47
51
  export type { IAngularScrollViewProps, IScrollViewHandle } from './shared';
48
52
 
49
53
  // Minimal local twin of `@angular/common`'s NgTemplateOutlet (this adapter deliberately has no
@@ -66,7 +70,9 @@ export class SymbioteTemplateOutletDirective implements OnChanges, OnDestroy {
66
70
  this.viewRef = undefined;
67
71
  }
68
72
  if (this.symbioteTemplateOutlet !== null) {
69
- this.viewRef = this.viewContainerRef.createEmbeddedView(this.symbioteTemplateOutlet);
73
+ this.viewRef = this.viewContainerRef.createEmbeddedView(
74
+ this.symbioteTemplateOutlet,
75
+ );
70
76
  }
71
77
  }
72
78
 
@@ -87,7 +93,9 @@ function asStyle(value: unknown): IStyleProp<IViewStyle> | undefined {
87
93
  @Component({
88
94
  selector: 'ScrollView',
89
95
  standalone: true,
90
- hostDirectives: [{ directive: SymbioteStyleInputDirective, inputs: ['style'] }],
96
+ hostDirectives: [
97
+ { directive: SymbioteStyleInputDirective, inputs: ['style'] },
98
+ ],
91
99
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
92
100
  imports: [
93
101
  ScrollViewHost,
@@ -120,17 +128,24 @@ function asStyle(value: unknown): IStyleProp<IViewStyle> | undefined {
120
128
  [symbioteHostProps]="contentProps()"
121
129
  [symbioteScrollViewProjection]="projectionController"
122
130
  >
123
- <ng-container [symbioteTemplateOutlet]="sharedContent"></ng-container>
131
+ <ng-container
132
+ [symbioteTemplateOutlet]="sharedContent"
133
+ ></ng-container>
124
134
  </symbiote-horizontal-scroll-content>
125
135
  </symbiote-horizontal-scroll-view>
126
136
  </symbiote-refresh-control>
127
137
  } @else {
128
- <symbiote-horizontal-scroll-view #host="symbioteHost" [symbioteHostProps]="scrollProps()">
138
+ <symbiote-horizontal-scroll-view
139
+ #host="symbioteHost"
140
+ [symbioteHostProps]="scrollProps()"
141
+ >
129
142
  <symbiote-horizontal-scroll-content
130
143
  [symbioteHostProps]="contentProps()"
131
144
  [symbioteScrollViewProjection]="projectionController"
132
145
  >
133
- <ng-container [symbioteTemplateOutlet]="sharedContent"></ng-container>
146
+ <ng-container
147
+ [symbioteTemplateOutlet]="sharedContent"
148
+ ></ng-container>
134
149
  </symbiote-horizontal-scroll-content>
135
150
  </symbiote-horizontal-scroll-view>
136
151
  }
@@ -149,17 +164,24 @@ function asStyle(value: unknown): IStyleProp<IViewStyle> | undefined {
149
164
  [symbioteHostProps]="contentProps()"
150
165
  [symbioteScrollViewProjection]="projectionController"
151
166
  >
152
- <ng-container [symbioteTemplateOutlet]="sharedContent"></ng-container>
167
+ <ng-container
168
+ [symbioteTemplateOutlet]="sharedContent"
169
+ ></ng-container>
153
170
  </symbiote-scroll-content>
154
171
  </symbiote-scroll-view>
155
172
  </symbiote-refresh-control>
156
173
  } @else {
157
- <symbiote-scroll-view #host="symbioteHost" [symbioteHostProps]="scrollProps()">
174
+ <symbiote-scroll-view
175
+ #host="symbioteHost"
176
+ [symbioteHostProps]="scrollProps()"
177
+ >
158
178
  <symbiote-scroll-content
159
179
  [symbioteHostProps]="contentProps()"
160
180
  [symbioteScrollViewProjection]="projectionController"
161
181
  >
162
- <ng-container [symbioteTemplateOutlet]="sharedContent"></ng-container>
182
+ <ng-container
183
+ [symbioteTemplateOutlet]="sharedContent"
184
+ ></ng-container>
163
185
  </symbiote-scroll-content>
164
186
  </symbiote-scroll-view>
165
187
  }