@symbiote-native/angular 0.6.0 → 0.6.2

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 (193) hide show
  1. package/README.md +1 -1
  2. package/babel-register-composed.cjs +11 -3
  3. package/build/angular/anchor-host-registry.d.ts +2 -0
  4. package/build/angular/anchor-host-registry.js +84 -0
  5. package/build/angular/anchor-host-registry.js.map +1 -0
  6. package/build/angular/components/input-accessory-view/index.d.ts +2 -1
  7. package/build/angular/components/input-accessory-view/index.js +28 -39
  8. package/build/angular/components/input-accessory-view/index.js.map +1 -1
  9. package/build/angular/components/scroll-view/projection.js +70 -48
  10. package/build/angular/components/scroll-view/projection.js.map +1 -1
  11. package/build/angular/components/scroll-view/shared.js +28 -25
  12. package/build/angular/components/scroll-view/shared.js.map +1 -1
  13. package/build/angular/components/scroll-view/sticky-header.d.ts +6 -7
  14. package/build/angular/components/scroll-view/sticky-header.js +82 -65
  15. package/build/angular/components/scroll-view/sticky-header.js.map +1 -1
  16. package/build/angular/components/touchable/index.d.ts +2 -5
  17. package/build/angular/components/touchable/index.js +36 -56
  18. package/build/angular/components/touchable/index.js.map +1 -1
  19. package/build/angular/components/virtualized-list/index.d.ts +5 -20
  20. package/build/angular/components/virtualized-list/index.js +145 -275
  21. package/build/angular/components/virtualized-list/index.js.map +1 -1
  22. package/build/angular/components/virtualized-section-list/index.js +2 -4
  23. package/build/angular/components/virtualized-section-list/index.js.map +1 -1
  24. package/build/angular/index.d.ts +2 -1
  25. package/build/angular/index.js +6 -1
  26. package/build/angular/index.js.map +1 -1
  27. package/build/angular/renderer/index.d.ts +0 -1
  28. package/build/angular/renderer/index.js +5 -60
  29. package/build/angular/renderer/index.js.map +1 -1
  30. package/package.json +8 -4
  31. package/src/anchor-host-registry.ts +88 -0
  32. package/src/components/input-accessory-view/index.ts +30 -39
  33. package/src/components/scroll-view/projection.ts +76 -46
  34. package/src/components/scroll-view/shared.ts +27 -19
  35. package/src/components/scroll-view/sticky-header.ts +89 -64
  36. package/src/components/touchable/index.ts +52 -66
  37. package/src/components/virtualized-list/index.ts +157 -368
  38. package/src/components/virtualized-section-list/index.ts +6 -3
  39. package/src/index.ts +6 -1
  40. package/src/renderer/index.ts +5 -63
  41. package/build/bootstrap.d.ts +0 -7
  42. package/build/bootstrap.js +0 -14
  43. package/build/components/activity-indicator/index.android.d.ts +0 -9
  44. package/build/components/activity-indicator/index.android.js +0 -64
  45. package/build/components/activity-indicator/index.d.ts +0 -1
  46. package/build/components/activity-indicator/index.ios.d.ts +0 -5
  47. package/build/components/activity-indicator/index.ios.js +0 -64
  48. package/build/components/activity-indicator/index.js +0 -3
  49. package/build/components/activity-indicator/shared.d.ts +0 -64
  50. package/build/components/activity-indicator/shared.js +0 -424
  51. package/build/components/button.d.ts +0 -60
  52. package/build/components/button.js +0 -456
  53. package/build/components/flat-list/index.d.ts +0 -119
  54. package/build/components/flat-list/index.js +0 -691
  55. package/build/components/image/index.android.d.ts +0 -7
  56. package/build/components/image/index.android.js +0 -88
  57. package/build/components/image/index.d.ts +0 -1
  58. package/build/components/image/index.ios.d.ts +0 -7
  59. package/build/components/image/index.ios.js +0 -88
  60. package/build/components/image/index.js +0 -2
  61. package/build/components/image/shared.d.ts +0 -101
  62. package/build/components/image/shared.js +0 -405
  63. package/build/components/image-background.d.ts +0 -78
  64. package/build/components/image-background.js +0 -583
  65. package/build/components/input-accessory-view/index.d.ts +0 -56
  66. package/build/components/input-accessory-view/index.js +0 -403
  67. package/build/components/keyboard-avoiding-view/index.d.ts +0 -79
  68. package/build/components/keyboard-avoiding-view/index.js +0 -504
  69. package/build/components/modal/index.d.ts +0 -89
  70. package/build/components/modal/index.js +0 -529
  71. package/build/components/pressable/index.d.ts +0 -120
  72. package/build/components/pressable/index.js +0 -639
  73. package/build/components/refresh-control/index.d.ts +0 -83
  74. package/build/components/refresh-control/index.js +0 -509
  75. package/build/components/safe-area-view/index.d.ts +0 -54
  76. package/build/components/safe-area-view/index.js +0 -388
  77. package/build/components/scroll-view/index.android.d.ts +0 -16
  78. package/build/components/scroll-view/index.android.js +0 -228
  79. package/build/components/scroll-view/index.d.ts +0 -3
  80. package/build/components/scroll-view/index.ios.d.ts +0 -6
  81. package/build/components/scroll-view/index.ios.js +0 -113
  82. package/build/components/scroll-view/index.js +0 -5
  83. package/build/components/scroll-view/projection.d.ts +0 -32
  84. package/build/components/scroll-view/projection.js +0 -311
  85. package/build/components/scroll-view/shared.d.ts +0 -225
  86. package/build/components/scroll-view/shared.js +0 -757
  87. package/build/components/scroll-view/sticky-header.d.ts +0 -38
  88. package/build/components/scroll-view/sticky-header.js +0 -257
  89. package/build/components/section-list/index.d.ts +0 -113
  90. package/build/components/section-list/index.js +0 -768
  91. package/build/components/switch/index.android.d.ts +0 -17
  92. package/build/components/switch/index.android.js +0 -107
  93. package/build/components/switch/index.d.ts +0 -1
  94. package/build/components/switch/index.ios.d.ts +0 -16
  95. package/build/components/switch/index.ios.js +0 -106
  96. package/build/components/switch/index.js +0 -3
  97. package/build/components/switch/shared.d.ts +0 -37
  98. package/build/components/switch/shared.js +0 -176
  99. package/build/components/text-input.d.ts +0 -150
  100. package/build/components/text-input.js +0 -821
  101. package/build/components/touchable/index.d.ts +0 -241
  102. package/build/components/touchable/index.js +0 -1672
  103. package/build/components/touchable-native-feedback/index.d.ts +0 -80
  104. package/build/components/touchable-native-feedback/index.js +0 -545
  105. package/build/components/virtualized-list/directives.d.ts +0 -41
  106. package/build/components/virtualized-list/directives.js +0 -249
  107. package/build/components/virtualized-list/index.d.ts +0 -265
  108. package/build/components/virtualized-list/index.js +0 -1343
  109. package/build/components/virtualized-section-list/directives.d.ts +0 -28
  110. package/build/components/virtualized-section-list/directives.js +0 -148
  111. package/build/components/virtualized-section-list/index.d.ts +0 -175
  112. package/build/components/virtualized-section-list/index.js +0 -854
  113. package/build/components.d.ts +0 -39
  114. package/build/components.js +0 -37
  115. package/build/create-portal/index.d.ts +0 -17
  116. package/build/create-portal/index.js +0 -128
  117. package/build/create-tunnel/index.d.ts +0 -29
  118. package/build/create-tunnel/index.js +0 -181
  119. package/build/descriptor-to-angular/index.d.ts +0 -19
  120. package/build/descriptor-to-angular/index.js +0 -186
  121. package/build/host-instance/index.d.ts +0 -2
  122. package/build/host-instance/index.js +0 -36
  123. package/build/index.d.ts +0 -21
  124. package/build/index.js +0 -40
  125. package/build/modules/animated/animated-leaf-binder/index.d.ts +0 -14
  126. package/build/modules/animated/animated-leaf-binder/index.js +0 -90
  127. package/build/modules/animated/animated-leaf-binder.d.ts +0 -14
  128. package/build/modules/animated/animated-leaf-binder.js +0 -90
  129. package/build/modules/animated/create-animated-component.d.ts +0 -48
  130. package/build/modules/animated/create-animated-component.js +0 -425
  131. package/build/modules/animated/index.d.ts +0 -51
  132. package/build/modules/animated/index.js +0 -58
  133. package/build/modules/app-registry/index.d.ts +0 -7
  134. package/build/modules/app-registry/index.js +0 -22
  135. package/build/modules/status-bar/index.d.ts +0 -17
  136. package/build/modules/status-bar/index.js +0 -121
  137. package/build/primitives/index.d.ts +0 -32
  138. package/build/primitives/index.js +0 -386
  139. package/build/primitives/shared.d.ts +0 -83
  140. package/build/primitives/shared.js +0 -230
  141. package/build/render/index.d.ts +0 -11
  142. package/build/render/index.js +0 -170
  143. package/build/renderer/index.d.ts +0 -38
  144. package/build/renderer/index.js +0 -355
  145. package/build/services/color-scheme.service.d.ts +0 -13
  146. package/build/services/color-scheme.service.js +0 -72
  147. package/build/services/index.d.ts +0 -2
  148. package/build/services/index.js +0 -2
  149. package/build/services/window-dimensions.service.d.ts +0 -13
  150. package/build/services/window-dimensions.service.js +0 -83
  151. package/src/__tests__/responder-change-detection.test.ts +0 -102
  152. package/src/__tests__/responder-nested-cd.test.ts +0 -113
  153. package/src/angular-gaps.test.ts +0 -142
  154. package/src/angular-imports.test.ts +0 -100
  155. package/src/components/activity-indicator/activity-indicator-class-style.test.ts +0 -44
  156. package/src/components/activity-indicator/activity-indicator.test.ts +0 -131
  157. package/src/components/flat-list/column-wrapper-style-class.test.ts +0 -116
  158. package/src/components/flat-list/flat-list-array-style.test.ts +0 -131
  159. package/src/components/flat-list/flat-list-class-style.test.ts +0 -74
  160. package/src/components/flat-list/flat-list-scroll-containment.test.ts +0 -107
  161. package/src/components/flat-list/flat-list.test.ts +0 -99
  162. package/src/components/image/image-class-style.test.ts +0 -46
  163. package/src/components/image-background-class-style.test.ts +0 -48
  164. package/src/components/image-background-style-class.test.ts +0 -79
  165. package/src/components/input-accessory-view/input-accessory-view.test.ts +0 -43
  166. package/src/components/keyboard-avoiding-view/keyboard-avoiding-view.test.ts +0 -54
  167. package/src/components/modal/modal.test.ts +0 -43
  168. package/src/components/pressable/pressable.test.ts +0 -85
  169. package/src/components/refresh-control/refresh-control.test.ts +0 -41
  170. package/src/components/safe-area-view/safe-area-view.test.ts +0 -43
  171. package/src/components/scroll-view/android-scroll-view-axis-projection.test.ts +0 -123
  172. package/src/components/scroll-view/content-container-style-class.test.ts +0 -75
  173. package/src/components/scroll-view/scroll-view-class-style.test.ts +0 -134
  174. package/src/components/scroll-view/scroll-view-projection.test.ts +0 -194
  175. package/src/components/switch/android-switch-class.test.ts +0 -42
  176. package/src/components/switch/switch.test.ts +0 -92
  177. package/src/components/text-input-class-style.test.ts +0 -54
  178. package/src/components/touchable/touchable.test.ts +0 -102
  179. package/src/components/touchable-native-feedback/touchable-native-feedback.test.ts +0 -49
  180. package/src/components/virtualized-list/virtualized-list-class-style.test.ts +0 -76
  181. package/src/components/virtualized-section-list/virtualized-section-list-class-style.test.ts +0 -60
  182. package/src/create-portal/create-portal.test.ts +0 -90
  183. package/src/create-tunnel/create-tunnel.test.ts +0 -120
  184. package/src/descriptor-to-angular/descriptor-outlet.test.ts +0 -94
  185. package/src/host-instance/host-instance.test.ts +0 -49
  186. package/src/modules/animated/animated-leaf-binder/animated-leaf-binder.test.ts +0 -116
  187. package/src/modules/animated/animated-leaf-binder.test.ts +0 -116
  188. package/src/modules/animated/animated-scroll-view.test.ts +0 -102
  189. package/src/modules/app-registry/app-registry.test.ts +0 -106
  190. package/src/modules/status-bar/status-bar.test.ts +0 -50
  191. package/src/render/render.test.ts +0 -147
  192. package/src/renderer/renderer.test.ts +0 -202
  193. package/src/services/services.test.ts +0 -163
@@ -1,43 +0,0 @@
1
- import '@angular/compiler';
2
- import { Component } from '@angular/core';
3
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
- import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
5
- import { installFabric } from '@symbiote-native/test-utils';
6
-
7
- import { mount, unmount } from '../../render';
8
- import { Modal } from './index';
9
-
10
- const ROOT_TAG = 912;
11
- const fabric = installFabric();
12
-
13
- @Component({
14
- selector: 'symbiote-modal-host',
15
- standalone: true,
16
- imports: [Modal],
17
- template: `
18
- <Modal [visible]="true" [testID]="'modal'" class="sheet">
19
- <symbiote-text>Hello</symbiote-text>
20
- </Modal>
21
- `,
22
- })
23
- class ModalHostFixture {}
24
-
25
- beforeEach(() => {
26
- fabric.reset();
27
- });
28
- afterEach(() => {
29
- unmount(ROOT_TAG);
30
- clearGlobalStyles();
31
- });
32
-
33
- describe('Modal', () => {
34
- it('resolves a class= on the Modal use site onto the real committed view, not the anchor', async () => {
35
- registerStyles({ sheet: { backgroundColor: 'purple' } });
36
-
37
- mount(ROOT_TAG, ModalHostFixture);
38
- await new Promise<void>(resolve => setTimeout(resolve, 0));
39
-
40
- const node = fabric.find(n => n.props.testID === 'modal');
41
- expect(node?.props.backgroundColor).toBe('purple');
42
- });
43
- });
@@ -1,85 +0,0 @@
1
- import '@angular/compiler';
2
- import { Component } from '@angular/core';
3
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
- import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
5
- import { installFabric } from '@symbiote-native/test-utils';
6
-
7
- import { mount, unmount } from '../../render';
8
- import { Pressable } from './index';
9
-
10
- const ROOT_TAG = 903;
11
- const fabric = installFabric();
12
-
13
- let capturedHost: PressableHost | undefined;
14
-
15
- @Component({
16
- selector: 'symbiote-pressable-host',
17
- standalone: true,
18
- imports: [Pressable],
19
- template: `
20
- <Pressable
21
- [testID]="'pressable'"
22
- class="card"
23
- (press)="onPress($event)"
24
- (pressIn)="onPressIn($event)"
25
- (pressOut)="onPressOut($event)"
26
- >
27
- <symbiote-text>Press me</symbiote-text>
28
- </Pressable>
29
- `,
30
- })
31
- class PressableHost {
32
- onPress = vi.fn();
33
- onPressIn = vi.fn();
34
- onPressOut = vi.fn();
35
-
36
- constructor() {
37
- // Captures the live component instance so the test can drive its signals after mount.
38
- // eslint-disable-next-line @typescript-eslint/no-this-alias
39
- capturedHost = this;
40
- }
41
- }
42
-
43
- beforeEach(() => {
44
- capturedHost = undefined;
45
- fabric.reset();
46
- });
47
- afterEach(() => {
48
- unmount(ROOT_TAG);
49
- clearGlobalStyles();
50
- });
51
-
52
- describe('Pressable', () => {
53
- it('synthesizes a press from a touch sequence and fires the lifecycle handlers', async () => {
54
- mount(ROOT_TAG, PressableHost);
55
- await new Promise<void>(resolve => setTimeout(resolve, 0));
56
-
57
- const node = fabric.find(n => n.props.testID === 'pressable');
58
- expect(node, 'Pressable view committed').toBeDefined();
59
-
60
- const now = Date.now();
61
- const touch = { identifier: 1, pageX: 10, pageY: 10, timestamp: now };
62
- const nativeEvent = { touches: [touch], changedTouches: [touch] };
63
-
64
- fabric.fireEvent(node?.instanceHandle, 'topTouchStart', nativeEvent);
65
- await new Promise<void>(resolve => setTimeout(resolve, 0));
66
-
67
- expect(capturedHost?.onPressIn).toHaveBeenCalledOnce();
68
-
69
- fabric.fireEvent(node?.instanceHandle, 'topTouchEnd', nativeEvent);
70
- await new Promise<void>(resolve => setTimeout(resolve, 0));
71
-
72
- expect(capturedHost?.onPress).toHaveBeenCalledOnce();
73
- expect(capturedHost?.onPressOut).toHaveBeenCalledOnce();
74
- });
75
-
76
- it('resolves a class= on the Pressable use site onto the real committed view, not the anchor', async () => {
77
- registerStyles({ card: { backgroundColor: 'red' } });
78
-
79
- mount(ROOT_TAG, PressableHost);
80
- await new Promise<void>(resolve => setTimeout(resolve, 0));
81
-
82
- const node = fabric.find(n => n.props.testID === 'pressable');
83
- expect(node?.props.backgroundColor).toBe('red');
84
- });
85
- });
@@ -1,41 +0,0 @@
1
- import '@angular/compiler';
2
- import { Component } from '@angular/core';
3
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
- import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
5
- import { installFabric } from '@symbiote-native/test-utils';
6
-
7
- import { mount, unmount } from '../../render';
8
- import { RefreshControl } from './index';
9
-
10
- const ROOT_TAG = 914;
11
- const fabric = installFabric();
12
-
13
- @Component({
14
- selector: 'symbiote-refresh-control-host',
15
- standalone: true,
16
- imports: [RefreshControl],
17
- template: `
18
- <RefreshControl [refreshing]="false" [testID]="'refresh'" class="spinner"></RefreshControl>
19
- `,
20
- })
21
- class RefreshControlHostFixture {}
22
-
23
- beforeEach(() => {
24
- fabric.reset();
25
- });
26
- afterEach(() => {
27
- unmount(ROOT_TAG);
28
- clearGlobalStyles();
29
- });
30
-
31
- describe('RefreshControl', () => {
32
- it('resolves a class= on the RefreshControl use site onto the real committed view, not the anchor', async () => {
33
- registerStyles({ spinner: { backgroundColor: 'green' } });
34
-
35
- mount(ROOT_TAG, RefreshControlHostFixture);
36
- await new Promise<void>(resolve => setTimeout(resolve, 0));
37
-
38
- const node = fabric.find(n => n.props.testID === 'refresh');
39
- expect(node?.props.backgroundColor).toBe('green');
40
- });
41
- });
@@ -1,43 +0,0 @@
1
- import '@angular/compiler';
2
- import { Component } from '@angular/core';
3
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4
- import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
5
- import { installFabric } from '@symbiote-native/test-utils';
6
-
7
- import { mount, unmount } from '../../render';
8
- import { SafeAreaView } from './index';
9
-
10
- const ROOT_TAG = 910;
11
- const fabric = installFabric();
12
-
13
- @Component({
14
- selector: 'symbiote-safe-area-view-host',
15
- standalone: true,
16
- imports: [SafeAreaView],
17
- template: `
18
- <SafeAreaView [testID]="'safe-area'" class="screen">
19
- <symbiote-text>Hello</symbiote-text>
20
- </SafeAreaView>
21
- `,
22
- })
23
- class SafeAreaViewHostFixture {}
24
-
25
- beforeEach(() => {
26
- fabric.reset();
27
- });
28
- afterEach(() => {
29
- unmount(ROOT_TAG);
30
- clearGlobalStyles();
31
- });
32
-
33
- describe('SafeAreaView', () => {
34
- it('resolves a class= on the SafeAreaView use site onto the real committed view, not the anchor', async () => {
35
- registerStyles({ screen: { backgroundColor: 'navy' } });
36
-
37
- mount(ROOT_TAG, SafeAreaViewHostFixture);
38
- await new Promise<void>(resolve => setTimeout(resolve, 0));
39
-
40
- const node = fabric.find(n => n.props.testID === 'safe-area');
41
- expect(node?.props.backgroundColor).toBe('navy');
42
- });
43
- });
@@ -1,123 +0,0 @@
1
- // Regression test for an Android content-projection bug:
2
- // ScrollView on Android picks a different native content view per axis (RCTView vs
3
- // AndroidHorizontalScrollContentView), which used to require a separate <ng-content> per
4
- // axis x refresh-control combination — and Angular only reliably projects into a component's
5
- // LAST-declared <ng-content> when 2+ distinct declarations exist. Fixed by routing all four
6
- // branches through a single shared <ng-template>/<ng-content> via a local template-outlet
7
- // directive (see index.android.ts). Covers all four static combinations plus a runtime axis
8
- // flip, which the projection.ts records/reconcile path must survive without dropping children.
9
- import '@angular/compiler';
10
- import { Component, CUSTOM_ELEMENTS_SCHEMA, signal } from '@angular/core';
11
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
12
- import { installFabric } from '@symbiote-native/test-utils';
13
- import { mount, unmount } from '../../render';
14
- import { RefreshControl } from '../refresh-control';
15
- import { ScrollView } from './index.android';
16
-
17
- const ROOT_TAG = 919;
18
- const fabric = installFabric();
19
- const tick = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 0));
20
-
21
- function expectCellsProjected(): void {
22
- expect(fabric.find(node => node.props.testID === 'a')).toBeDefined();
23
- expect(fabric.find(node => node.props.testID === 'b')).toBeDefined();
24
- }
25
-
26
- class HorizontalNoRefreshApp {}
27
- Component({
28
- selector: 'axis-projection-horizontal-no-refresh',
29
- standalone: true,
30
- imports: [ScrollView],
31
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
32
- template: `
33
- <ScrollView [horizontal]="true">
34
- <symbiote-view testID="a"></symbiote-view>
35
- <symbiote-view testID="b"></symbiote-view>
36
- </ScrollView>
37
- `,
38
- })(HorizontalNoRefreshApp);
39
-
40
- class HorizontalRefreshApp {
41
- refresh = (): void => {};
42
- }
43
- Component({
44
- selector: 'axis-projection-horizontal-refresh',
45
- standalone: true,
46
- imports: [ScrollView, RefreshControl],
47
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
48
- template: `
49
- <ScrollView [horizontal]="true">
50
- <RefreshControl [refreshing]="true" (refresh)="refresh()" />
51
- <symbiote-view testID="a"></symbiote-view>
52
- <symbiote-view testID="b"></symbiote-view>
53
- </ScrollView>
54
- `,
55
- })(HorizontalRefreshApp);
56
-
57
- class VerticalNoRefreshApp {}
58
- Component({
59
- selector: 'axis-projection-vertical-no-refresh',
60
- standalone: true,
61
- imports: [ScrollView],
62
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
63
- template: `
64
- <ScrollView>
65
- <symbiote-view testID="a"></symbiote-view>
66
- <symbiote-view testID="b"></symbiote-view>
67
- </ScrollView>
68
- `,
69
- })(VerticalNoRefreshApp);
70
-
71
- class AxisSwitchApp {
72
- static readonly horizontal = signal(false);
73
- get isHorizontal(): boolean {
74
- return AxisSwitchApp.horizontal();
75
- }
76
- }
77
- Component({
78
- selector: 'axis-projection-axis-switch',
79
- standalone: true,
80
- imports: [ScrollView],
81
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
82
- template: `
83
- <ScrollView [horizontal]="isHorizontal">
84
- <symbiote-view testID="a"></symbiote-view>
85
- <symbiote-view testID="b"></symbiote-view>
86
- </ScrollView>
87
- `,
88
- })(AxisSwitchApp);
89
-
90
- beforeEach(() => fabric.reset());
91
- afterEach(() => unmount(ROOT_TAG));
92
-
93
- describe('Android ScrollView projects content across every axis x refresh combination', () => {
94
- it('horizontal, no refresh control', async () => {
95
- mount(ROOT_TAG, HorizontalNoRefreshApp);
96
- await tick();
97
- expectCellsProjected();
98
- });
99
-
100
- it('horizontal, with a projected refresh control', async () => {
101
- mount(ROOT_TAG, HorizontalRefreshApp);
102
- await tick();
103
- expectCellsProjected();
104
- });
105
-
106
- it('vertical, no refresh control', async () => {
107
- mount(ROOT_TAG, VerticalNoRefreshApp);
108
- await tick();
109
- expectCellsProjected();
110
- });
111
-
112
- it('survives a runtime vertical -> horizontal axis switch', async () => {
113
- AxisSwitchApp.horizontal.set(false);
114
- mount(ROOT_TAG, AxisSwitchApp);
115
- await tick();
116
- expectCellsProjected();
117
-
118
- AxisSwitchApp.horizontal.set(true);
119
- await tick();
120
- await tick();
121
- expectCellsProjected();
122
- });
123
- });
@@ -1,75 +0,0 @@
1
- // Regression guard: contentContainerStyle previously accepted ONLY a JS style object/array. It
2
- // now also resolves a class-name string through the shared style registry, same as `class`/
3
- // `style` (see shared.ts's resolvedContentContainerStyle getter). Mirrors the Vue twin
4
- // (content-container-style-class.test.ts) and scroll-view-class-style.test.ts's style-for-this-
5
- // exact-scenario shape.
6
- import '@angular/compiler';
7
- import { Component } from '@angular/core';
8
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
9
- import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
10
- import { installFabric, type IFakeNode } from '@symbiote-native/test-utils';
11
-
12
- import { mount, unmount } from '../../render';
13
- import { ScrollView } from './index.ios';
14
-
15
- const ROOT_TAG = 952;
16
- const fabric = installFabric();
17
- const tick = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 0));
18
-
19
- function committedContentView(): IFakeNode {
20
- const node = fabric.find(n => n.viewName === 'RCTScrollContentView');
21
- expect(node, 'the scroll content view was committed').toBeDefined();
22
- if (node === undefined) throw new Error('unreachable: content view missing');
23
- return node;
24
- }
25
-
26
- @Component({
27
- selector: 'symbiote-scroll-content-style-class-host',
28
- standalone: true,
29
- imports: [ScrollView],
30
- template: `
31
- <ScrollView [contentContainerStyle]="'padded'">
32
- <symbiote-text>content</symbiote-text>
33
- </ScrollView>
34
- `,
35
- })
36
- class ScrollViewContentStyleClassHost {}
37
-
38
- @Component({
39
- selector: 'symbiote-scroll-content-style-object-host',
40
- standalone: true,
41
- imports: [ScrollView],
42
- template: `
43
- <ScrollView [contentContainerStyle]="{ padding: 12 }">
44
- <symbiote-text>content</symbiote-text>
45
- </ScrollView>
46
- `,
47
- })
48
- class ScrollViewContentStyleObjectHost {}
49
-
50
- beforeEach(() => {
51
- fabric.reset();
52
- registerStyles({ padded: { padding: 20 } });
53
- });
54
- afterEach(() => {
55
- unmount(ROOT_TAG);
56
- clearGlobalStyles();
57
- });
58
-
59
- describe('ScrollView contentContainerStyle class-name support', () => {
60
- it('resolves a class-name string onto the content view, not the outer scroll view', async () => {
61
- mount(ROOT_TAG, ScrollViewContentStyleClassHost);
62
- await tick();
63
-
64
- expect(committedContentView().props.padding).toBe(20);
65
- const scrollHost = fabric.find(n => n.viewName === 'RCTScrollView');
66
- expect(scrollHost?.props.padding).toBeUndefined();
67
- });
68
-
69
- it('still accepts an ordinary style object unchanged', async () => {
70
- mount(ROOT_TAG, ScrollViewContentStyleObjectHost);
71
- await tick();
72
-
73
- expect(committedContentView().props.padding).toBe(12);
74
- });
75
- });
@@ -1,134 +0,0 @@
1
- // Regression test for the anchor/class bug: a composed component's own
2
- // use-site `class="..."` resolves through Angular's addClass/removeClass onto the component's
3
- // non-painting ANCHOR host (ANCHOR_HOST_COMPONENTS in renderer.ts), never onto the real Fabric
4
- // node its own template renders — so the resolved style was silently lost. Fixed via
5
- // anchorHostStyle(this.elementRef) merged into ScrollView's own scrollProps/androidWrappedScrollProps
6
- // getters (see index.ios.ts / index.android.ts). Mirrors pressable.test.ts's "resolves a class=" case,
7
- // covering BOTH platforms and the Android refresh-control-wrapped branch (androidWrappedScrollProps
8
- // is a SEPARATE override from scrollProps, since it recomputes `style` from scratch rather than
9
- // inheriting the base getter's result).
10
- import '@angular/compiler';
11
- import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
12
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
13
- import { clearGlobalStyles, registerStyles } from '@symbiote-native/engine';
14
- import { installFabric } from '@symbiote-native/test-utils';
15
-
16
- import { mount, unmount } from '../../render';
17
- import { RefreshControl } from '../refresh-control';
18
- import { ScrollView as AndroidScrollView } from './index.android';
19
- import { ScrollView as IOSScrollView } from './index.ios';
20
-
21
- const ROOT_TAG = 950;
22
- const fabric = installFabric();
23
- const tick = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 0));
24
-
25
- @Component({
26
- selector: 'symbiote-scroll-ios-class-host',
27
- standalone: true,
28
- imports: [IOSScrollView],
29
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
30
- template: `
31
- <ScrollView class="card">
32
- <symbiote-view testID="cell"></symbiote-view>
33
- </ScrollView>
34
- `,
35
- })
36
- class IOSScrollViewClassHost {}
37
-
38
- @Component({
39
- selector: 'symbiote-scroll-android-class-host',
40
- standalone: true,
41
- imports: [AndroidScrollView],
42
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
43
- template: `
44
- <ScrollView class="card">
45
- <symbiote-view testID="cell"></symbiote-view>
46
- </ScrollView>
47
- `,
48
- })
49
- class AndroidScrollViewClassHost {}
50
-
51
- @Component({
52
- selector: 'symbiote-scroll-android-wrapped-class-host',
53
- standalone: true,
54
- imports: [AndroidScrollView, RefreshControl],
55
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
56
- template: `
57
- <ScrollView class="card">
58
- <RefreshControl [refreshing]="true" (refresh)="refresh()" />
59
- <symbiote-view testID="cell"></symbiote-view>
60
- </ScrollView>
61
- `,
62
- })
63
- class AndroidWrappedScrollViewClassHost {
64
- refresh = (): void => undefined;
65
- }
66
-
67
- @Component({
68
- selector: 'symbiote-scroll-android-wrapped-layout-class-host',
69
- standalone: true,
70
- imports: [AndroidScrollView, RefreshControl],
71
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
72
- template: `
73
- <ScrollView class="box">
74
- <RefreshControl [refreshing]="true" (refresh)="refresh()" />
75
- <symbiote-view testID="cell"></symbiote-view>
76
- </ScrollView>
77
- `,
78
- })
79
- class AndroidWrappedScrollViewLayoutClassHost {
80
- refresh = (): void => undefined;
81
- }
82
-
83
- beforeEach(() => {
84
- fabric.reset();
85
- registerStyles({ card: { backgroundColor: 'red' }, box: { flex: 1, height: 84 } });
86
- });
87
- afterEach(() => {
88
- unmount(ROOT_TAG);
89
- clearGlobalStyles();
90
- });
91
-
92
- describe('ScrollView anchor class= resolution', () => {
93
- it('resolves a class= on the iOS ScrollView use site onto the real committed scroll host', async () => {
94
- mount(ROOT_TAG, IOSScrollViewClassHost);
95
- await tick();
96
-
97
- const node = fabric.find(n => n.props.backgroundColor === 'red');
98
- expect(node, 'a real Fabric node carries the class-derived style').toBeDefined();
99
- });
100
-
101
- it('resolves a class= on the Android ScrollView use site (no refresh control)', async () => {
102
- mount(ROOT_TAG, AndroidScrollViewClassHost);
103
- await tick();
104
-
105
- const node = fabric.find(n => n.props.backgroundColor === 'red');
106
- expect(node, 'a real Fabric node carries the class-derived style').toBeDefined();
107
- });
108
-
109
- it('resolves a class= on the Android ScrollView use site wrapped by a projected RefreshControl', async () => {
110
- mount(ROOT_TAG, AndroidWrappedScrollViewClassHost);
111
- await tick();
112
-
113
- const node = fabric.find(n => n.props.backgroundColor === 'red');
114
- expect(node, 'a real Fabric node carries the class-derived style').toBeDefined();
115
- });
116
-
117
- // Regression for a real device bug distinct from the one above: a class-derived LAYOUT
118
- // property (flex/height/…) must reach the OUTER refresh-control wrapper via splitLayoutProps,
119
- // not just the inner scroll view — a class carrying only a color property (the test above)
120
- // never exercises this split at all, since color is never a layout key. Without
121
- // `layoutSplitStyle` feeding the anchor's style INTO the split (not tacked on after), the
122
- // wrapper never receives its flex/height share and collapses to zero size — the whole
123
- // ScrollView renders nothing on a real Android device. Mirrors the Vue adapter's identical
124
- // `layoutSplitStyle` fix (same root cause, same symptom).
125
- it('resolves a class-derived LAYOUT style onto the Android outer refresh-control wrapper', async () => {
126
- mount(ROOT_TAG, AndroidWrappedScrollViewLayoutClassHost);
127
- await tick();
128
-
129
- const wrapper = fabric.find(n => n.props.refreshing === true);
130
- expect(wrapper, 'the outer refresh-control wrapper committed').toBeDefined();
131
- expect(wrapper?.props.flex).toBe(1);
132
- expect(wrapper?.props.height).toBe(84);
133
- });
134
- });