@symbiote-native/angular 0.7.0 → 1.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.
- package/README.md +3 -3
- package/babel-lower-host-primitives.cjs +636 -0
- package/babel-register-composed.cjs +21 -3
- package/build/angular/anchor-host-registry.js +3 -1
- package/build/angular/anchor-host-registry.js.map +1 -1
- package/build/angular/bootstrap.js +1 -1
- package/build/angular/bootstrap.js.map +1 -1
- package/build/angular/components/activity-indicator/index.android.js +7 -2
- package/build/angular/components/activity-indicator/index.android.js.map +1 -1
- package/build/angular/components/activity-indicator/index.ios.js +3 -1
- package/build/angular/components/activity-indicator/index.ios.js.map +1 -1
- package/build/angular/components/activity-indicator/shared.d.ts +1 -1
- package/build/angular/components/activity-indicator/shared.js +1 -1
- package/build/angular/components/activity-indicator/shared.js.map +1 -1
- package/build/angular/components/button.d.ts +3 -0
- package/build/angular/components/button.js +22 -5
- package/build/angular/components/button.js.map +1 -1
- package/build/angular/components/flat-list/index.d.ts +1 -1
- package/build/angular/components/flat-list/index.js +47 -14
- package/build/angular/components/flat-list/index.js.map +1 -1
- package/build/angular/components/image/index.android.js +4 -10
- package/build/angular/components/image/index.android.js.map +1 -1
- package/build/angular/components/image/index.ios.js +4 -10
- package/build/angular/components/image/index.ios.js.map +1 -1
- package/build/angular/components/image/shared.d.ts +4 -4
- package/build/angular/components/image/shared.js +51 -33
- package/build/angular/components/image/shared.js.map +1 -1
- package/build/angular/components/image-background.d.ts +3 -0
- package/build/angular/components/image-background.js +32 -9
- package/build/angular/components/image-background.js.map +1 -1
- package/build/angular/components/input-accessory-view/index.d.ts +2 -1
- package/build/angular/components/input-accessory-view/index.js +18 -16
- package/build/angular/components/input-accessory-view/index.js.map +1 -1
- package/build/angular/components/keyboard-avoiding-view/index.d.ts +3 -1
- package/build/angular/components/keyboard-avoiding-view/index.js +56 -19
- package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -1
- package/build/angular/components/modal/index.d.ts +1 -0
- package/build/angular/components/modal/index.js +21 -10
- package/build/angular/components/modal/index.js.map +1 -1
- package/build/angular/components/pressable/index.d.ts +10 -5
- package/build/angular/components/pressable/index.js +61 -16
- package/build/angular/components/pressable/index.js.map +1 -1
- package/build/angular/components/refresh-control/index.d.ts +2 -1
- package/build/angular/components/refresh-control/index.js +13 -9
- package/build/angular/components/refresh-control/index.js.map +1 -1
- package/build/angular/components/safe-area-view/index.d.ts +3 -1
- package/build/angular/components/safe-area-view/index.js +22 -20
- package/build/angular/components/safe-area-view/index.js.map +1 -1
- package/build/angular/components/scroll-view/index.android.js +44 -14
- package/build/angular/components/scroll-view/index.android.js.map +1 -1
- package/build/angular/components/scroll-view/index.ios.js +13 -5
- package/build/angular/components/scroll-view/index.ios.js.map +1 -1
- package/build/angular/components/scroll-view/projection.d.ts +32 -0
- package/build/angular/components/scroll-view/projection.js +212 -47
- package/build/angular/components/scroll-view/projection.js.map +1 -1
- package/build/angular/components/scroll-view/shared.d.ts +2 -0
- package/build/angular/components/scroll-view/shared.js +48 -11
- package/build/angular/components/scroll-view/shared.js.map +1 -1
- package/build/angular/components/scroll-view/sticky-header.js +7 -3
- package/build/angular/components/scroll-view/sticky-header.js.map +1 -1
- package/build/angular/components/section-list/index.d.ts +9 -1
- package/build/angular/components/section-list/index.js +72 -18
- package/build/angular/components/section-list/index.js.map +1 -1
- package/build/angular/components/switch/index.android.js +23 -9
- package/build/angular/components/switch/index.android.js.map +1 -1
- package/build/angular/components/switch/index.ios.js +23 -9
- package/build/angular/components/switch/index.ios.js.map +1 -1
- package/build/angular/components/switch/shared.d.ts +1 -1
- package/build/angular/components/switch/shared.js +5 -2
- package/build/angular/components/switch/shared.js.map +1 -1
- package/build/angular/components/text-input.d.ts +8 -2
- package/build/angular/components/text-input.js +79 -34
- package/build/angular/components/text-input.js.map +1 -1
- package/build/angular/components/touchable/index.d.ts +36 -7
- package/build/angular/components/touchable/index.js +280 -72
- package/build/angular/components/touchable/index.js.map +1 -1
- package/build/angular/components/touchable-native-feedback/index.d.ts +2 -1
- package/build/angular/components/touchable-native-feedback/index.js +19 -17
- package/build/angular/components/touchable-native-feedback/index.js.map +1 -1
- package/build/angular/components/virtualized-list/directives.js +4 -0
- package/build/angular/components/virtualized-list/directives.js.map +1 -1
- package/build/angular/components/virtualized-list/index.d.ts +8 -2
- package/build/angular/components/virtualized-list/index.js +207 -61
- package/build/angular/components/virtualized-list/index.js.map +1 -1
- package/build/angular/components/virtualized-section-list/directives.js.map +1 -1
- package/build/angular/components/virtualized-section-list/index.d.ts +21 -1
- package/build/angular/components/virtualized-section-list/index.js +100 -22
- package/build/angular/components/virtualized-section-list/index.js.map +1 -1
- package/build/angular/components.d.ts +2 -2
- package/build/angular/components.js +1 -1
- package/build/angular/components.js.map +1 -1
- package/build/angular/create-portal/index.d.ts +11 -2
- package/build/angular/create-portal/index.js +42 -12
- package/build/angular/create-portal/index.js.map +1 -1
- package/build/angular/create-tunnel/index.js.map +1 -1
- package/build/angular/descriptor-to-angular/index.js +3 -1
- package/build/angular/descriptor-to-angular/index.js.map +1 -1
- package/build/angular/diagnostics.d.ts +33 -0
- package/build/angular/diagnostics.js +82 -0
- package/build/angular/diagnostics.js.map +1 -0
- package/build/angular/gate-demand.d.ts +37 -0
- package/build/angular/gate-demand.js +84 -0
- package/build/angular/gate-demand.js.map +1 -0
- package/build/angular/host-instance/index.js +1 -1
- package/build/angular/host-instance/index.js.map +1 -1
- package/build/angular/index.d.ts +6 -2
- package/build/angular/index.js +16 -1
- package/build/angular/index.js.map +1 -1
- package/build/angular/modules/animated/create-animated-component.d.ts +1 -0
- package/build/angular/modules/animated/create-animated-component.js +41 -18
- package/build/angular/modules/animated/create-animated-component.js.map +1 -1
- package/build/angular/modules/app-registry/index.js.map +1 -1
- package/build/angular/modules/status-bar/index.js +1 -1
- package/build/angular/modules/status-bar/index.js.map +1 -1
- package/build/angular/primitives/index.d.ts +31 -2
- package/build/angular/primitives/index.js +81 -3
- package/build/angular/primitives/index.js.map +1 -1
- package/build/angular/primitives/shared.d.ts +9 -1
- package/build/angular/primitives/shared.js +49 -3
- package/build/angular/primitives/shared.js.map +1 -1
- package/build/angular/register.d.ts +1 -0
- package/build/angular/register.js +35 -0
- package/build/angular/register.js.map +1 -0
- package/build/angular/render/index.js +51 -6
- package/build/angular/render/index.js.map +1 -1
- package/build/angular/renderer/index.d.ts +1 -0
- package/build/angular/renderer/index.js +157 -21
- package/build/angular/renderer/index.js.map +1 -1
- package/build/angular/services/color-scheme.service.js.map +1 -1
- package/build/angular/services/window-dimensions.service.js +1 -1
- package/build/angular/services/window-dimensions.service.js.map +1 -1
- package/build/angular/state-style.d.ts +9 -0
- package/build/angular/state-style.js +39 -0
- package/build/angular/state-style.js.map +1 -0
- package/metro-transformer.cjs +69 -0
- package/package.json +27 -8
- package/src/anchor-host-registry.ts +3 -1
- package/src/bootstrap.ts +4 -1
- package/src/components/activity-indicator/index.android.ts +7 -2
- package/src/components/activity-indicator/index.ios.ts +3 -1
- package/src/components/activity-indicator/shared.ts +32 -13
- package/src/components/button.ts +36 -6
- package/src/components/flat-list/index.ts +91 -29
- package/src/components/image/index.android.ts +9 -6
- package/src/components/image/index.ios.ts +9 -6
- package/src/components/image/shared.ts +110 -45
- package/src/components/image-background.ts +47 -10
- package/src/components/input-accessory-view/index.ts +41 -18
- package/src/components/keyboard-avoiding-view/index.ts +76 -22
- package/src/components/modal/index.ts +39 -12
- package/src/components/pressable/index.ts +121 -31
- package/src/components/refresh-control/index.ts +36 -13
- package/src/components/safe-area-view/index.ts +44 -19
- package/src/components/scroll-view/index.android.ts +31 -9
- package/src/components/scroll-view/index.ios.ts +17 -4
- package/src/components/scroll-view/projection.ts +290 -63
- package/src/components/scroll-view/shared.ts +124 -30
- package/src/components/scroll-view/sticky-header.ts +25 -8
- package/src/components/section-list/index.ts +79 -19
- package/src/components/switch/index.android.ts +18 -7
- package/src/components/switch/index.ios.ts +18 -7
- package/src/components/switch/shared.ts +15 -4
- package/src/components/text-input.ts +119 -31
- package/src/components/touchable/index.ts +339 -72
- package/src/components/touchable-native-feedback/index.ts +50 -18
- package/src/components/virtualized-list/directives.ts +19 -5
- package/src/components/virtualized-list/index.ts +292 -72
- package/src/components/virtualized-section-list/directives.ts +6 -3
- package/src/components/virtualized-section-list/index.ts +164 -34
- package/src/components.ts +6 -1
- package/src/create-portal/index.ts +47 -11
- package/src/create-tunnel/index.ts +3 -1
- package/src/descriptor-to-angular/index.ts +29 -8
- package/src/diagnostics.ts +138 -0
- package/src/gate-demand.ts +109 -0
- package/src/host-instance/index.ts +9 -3
- package/src/index.ts +33 -2
- package/src/modules/animated/create-animated-component.ts +67 -19
- package/src/modules/app-registry/index.ts +3 -1
- package/src/modules/status-bar/index.ts +13 -4
- package/src/primitives/index.ts +73 -2
- package/src/primitives/shared.ts +70 -9
- package/src/register.ts +43 -0
- package/src/render/index.ts +59 -7
- package/src/renderer/index.ts +209 -37
- package/src/services/color-scheme.service.ts +3 -1
- package/src/services/window-dimensions.service.ts +11 -4
- package/src/state-style.ts +39 -0
|
@@ -7,12 +7,17 @@ export type { IActivityIndicatorProps } from './shared';
|
|
|
7
7
|
@Component({
|
|
8
8
|
selector: 'ActivityIndicator',
|
|
9
9
|
standalone: true,
|
|
10
|
-
hostDirectives: [
|
|
10
|
+
hostDirectives: [
|
|
11
|
+
{ directive: SymbioteStyleInputDirective, inputs: ['style'] },
|
|
12
|
+
],
|
|
11
13
|
imports: [DescriptorOutlet],
|
|
12
14
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13
15
|
template: `<symbiote-descriptor-outlet [node]="descriptor" />`,
|
|
14
16
|
})
|
|
15
17
|
export class ActivityIndicator extends ActivityIndicatorBase {
|
|
16
18
|
protected readonly defaultColor = null;
|
|
17
|
-
protected override readonly nativeExtras = {
|
|
19
|
+
protected override readonly nativeExtras = {
|
|
20
|
+
styleAttr: 'Normal',
|
|
21
|
+
indeterminate: true,
|
|
22
|
+
};
|
|
18
23
|
}
|
|
@@ -9,7 +9,9 @@ const IOS_DEFAULT_COLOR = '#999999';
|
|
|
9
9
|
@Component({
|
|
10
10
|
selector: 'ActivityIndicator',
|
|
11
11
|
standalone: true,
|
|
12
|
-
hostDirectives: [
|
|
12
|
+
hostDirectives: [
|
|
13
|
+
{ directive: SymbioteStyleInputDirective, inputs: ['style'] },
|
|
14
|
+
],
|
|
13
15
|
imports: [DescriptorOutlet],
|
|
14
16
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
15
17
|
template: `<symbiote-descriptor-outlet [node]="descriptor" />`,
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Directive,
|
|
3
|
+
ElementRef,
|
|
4
|
+
EventEmitter,
|
|
5
|
+
inject,
|
|
6
|
+
Input,
|
|
7
|
+
Output,
|
|
8
|
+
} from '@angular/core';
|
|
2
9
|
import {
|
|
3
10
|
renderActivityIndicator,
|
|
4
11
|
resolveAccessibilityProps,
|
|
@@ -13,7 +20,10 @@ import type { ISymbioteEvent } from '@symbiote-native/engine';
|
|
|
13
20
|
import type { IDescriptor } from '@symbiote-native/components';
|
|
14
21
|
import { anchorHostStyle } from '../../primitives';
|
|
15
22
|
|
|
16
|
-
export type {
|
|
23
|
+
export type {
|
|
24
|
+
IActivityIndicatorProps,
|
|
25
|
+
IActivityIndicatorSize,
|
|
26
|
+
} from '@symbiote-native/components';
|
|
17
27
|
|
|
18
28
|
// Narrows anchorHostStyle's `unknown` (it reads an opaque engine prop bag) to the shape
|
|
19
29
|
// IActivityIndicatorProps['style'] actually declares, the same runtime guard image/shared.ts's
|
|
@@ -61,8 +71,10 @@ export abstract class ActivityIndicatorBase implements IActivityIndicatorInputs
|
|
|
61
71
|
@Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
|
|
62
72
|
@Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
|
|
63
73
|
@Input() accessibilityLabelledBy?: string | string[];
|
|
64
|
-
@Input()
|
|
65
|
-
|
|
74
|
+
@Input()
|
|
75
|
+
importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
|
|
76
|
+
@Input()
|
|
77
|
+
accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
|
|
66
78
|
@Input() screenReaderFocusable?: boolean;
|
|
67
79
|
@Input() accessibilityViewIsModal?: boolean;
|
|
68
80
|
@Input() accessibilityElementsHidden?: boolean;
|
|
@@ -107,14 +119,18 @@ export abstract class ActivityIndicatorBase implements IActivityIndicatorInputs
|
|
|
107
119
|
// closure even when nothing changed — every CD pass would read as "props changed" and force a
|
|
108
120
|
// real Fabric re-clone cascading up every ancestor to the root (the same hazard
|
|
109
121
|
// AnimatedComponentBase.reconcile() and ScrollViewStickyHeader's onHostLayout guard against).
|
|
110
|
-
private readonly onLayoutHandler = (event: ISymbioteEvent): void =>
|
|
111
|
-
|
|
112
|
-
|
|
122
|
+
private readonly onLayoutHandler = (event: ISymbioteEvent): void =>
|
|
123
|
+
this.layout.emit(event);
|
|
124
|
+
private readonly onAccessibilityActionHandler = (
|
|
125
|
+
event: ISymbioteEvent,
|
|
126
|
+
): void => this.accessibilityAction.emit(event);
|
|
113
127
|
private readonly onAccessibilityTapHandler = (event: ISymbioteEvent): void =>
|
|
114
128
|
this.accessibilityTap.emit(event);
|
|
115
|
-
private readonly onMagicTapHandler = (event: ISymbioteEvent): void =>
|
|
116
|
-
|
|
117
|
-
|
|
129
|
+
private readonly onMagicTapHandler = (event: ISymbioteEvent): void =>
|
|
130
|
+
this.magicTap.emit(event);
|
|
131
|
+
private readonly onAccessibilityEscapeHandler = (
|
|
132
|
+
event: ISymbioteEvent,
|
|
133
|
+
): void => this.accessibilityEscape.emit(event);
|
|
118
134
|
|
|
119
135
|
get descriptor(): IDescriptor {
|
|
120
136
|
const props = resolveAccessibilityProps<IActivityIndicatorProps>({
|
|
@@ -141,8 +157,10 @@ export abstract class ActivityIndicatorBase implements IActivityIndicatorInputs
|
|
|
141
157
|
accessibilityElementsHidden: this.accessibilityElementsHidden,
|
|
142
158
|
accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
|
|
143
159
|
accessibilityLanguage: this.accessibilityLanguage,
|
|
144
|
-
accessibilityRespondsToUserInteraction:
|
|
145
|
-
|
|
160
|
+
accessibilityRespondsToUserInteraction:
|
|
161
|
+
this.accessibilityRespondsToUserInteraction,
|
|
162
|
+
accessibilityShowsLargeContentViewer:
|
|
163
|
+
this.accessibilityShowsLargeContentViewer,
|
|
146
164
|
accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
|
|
147
165
|
onAccessibilityAction: this.emitterHandler(
|
|
148
166
|
this.accessibilityAction,
|
|
@@ -174,7 +192,8 @@ export abstract class ActivityIndicatorBase implements IActivityIndicatorInputs
|
|
|
174
192
|
'aria-valuetext': this.ariaValueText,
|
|
175
193
|
});
|
|
176
194
|
|
|
177
|
-
const { animating, color, hidesWhenStopped, size, style, ...passthrough } =
|
|
195
|
+
const { animating, color, hidesWhenStopped, size, style, ...passthrough } =
|
|
196
|
+
props;
|
|
178
197
|
return renderActivityIndicator(
|
|
179
198
|
{
|
|
180
199
|
animating: animating !== false,
|
package/src/components/button.ts
CHANGED
|
@@ -33,9 +33,21 @@ import {
|
|
|
33
33
|
type IAriaProps,
|
|
34
34
|
type IButtonProps as ICoreButtonProps,
|
|
35
35
|
} from '@symbiote-native/components';
|
|
36
|
-
import type {
|
|
36
|
+
import type {
|
|
37
|
+
ISymbioteEvent,
|
|
38
|
+
ITextStyle,
|
|
39
|
+
IStyleProp,
|
|
40
|
+
IViewStyle,
|
|
41
|
+
} from '@symbiote-native/engine';
|
|
37
42
|
import { anchorStyleProp, TextHost } from '../primitives';
|
|
38
43
|
import { TouchableOpacity } from './touchable';
|
|
44
|
+
import {
|
|
45
|
+
gateWanted,
|
|
46
|
+
injectGateDemandAbove,
|
|
47
|
+
provideGateDemand,
|
|
48
|
+
type IGateDemand,
|
|
49
|
+
type IGatedAccessibilityEvent,
|
|
50
|
+
} from '../gate-demand';
|
|
39
51
|
|
|
40
52
|
export type IButtonProps = Omit<
|
|
41
53
|
ICoreButtonProps,
|
|
@@ -49,6 +61,7 @@ export type IButtonProps = Omit<
|
|
|
49
61
|
@Component({
|
|
50
62
|
selector: 'Button',
|
|
51
63
|
standalone: true,
|
|
64
|
+
viewProviders: [provideGateDemand(() => Button)],
|
|
52
65
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
53
66
|
imports: [TouchableOpacity, TextHost],
|
|
54
67
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
@@ -81,8 +94,12 @@ export type IButtonProps = Omit<
|
|
|
81
94
|
[accessibilityElementsHidden]="accessibilityElementsHidden"
|
|
82
95
|
[accessibilityIgnoresInvertColors]="accessibilityIgnoresInvertColors"
|
|
83
96
|
[accessibilityLanguage]="accessibilityLanguage"
|
|
84
|
-
[accessibilityRespondsToUserInteraction]="
|
|
85
|
-
|
|
97
|
+
[accessibilityRespondsToUserInteraction]="
|
|
98
|
+
accessibilityRespondsToUserInteraction
|
|
99
|
+
"
|
|
100
|
+
[accessibilityShowsLargeContentViewer]="
|
|
101
|
+
accessibilityShowsLargeContentViewer
|
|
102
|
+
"
|
|
86
103
|
[accessibilityLargeContentTitle]="accessibilityLargeContentTitle"
|
|
87
104
|
(accessibilityAction)="accessibilityAction.emit($event)"
|
|
88
105
|
(accessibilityTap)="accessibilityTap.emit($event)"
|
|
@@ -121,6 +138,15 @@ export class Button implements IButtonProps, DoCheck {
|
|
|
121
138
|
@Output() readonly magicTap = new EventEmitter<ISymbioteEvent>();
|
|
122
139
|
@Output() readonly accessibilityEscape = new EventEmitter<ISymbioteEvent>();
|
|
123
140
|
|
|
141
|
+
// This wrapper binds the four gated accessibility events on the component it renders, which
|
|
142
|
+
// Angular forces to be unconditional and which would light that component's gates on every
|
|
143
|
+
// instance. It answers for them instead — see `gate-demand.ts`.
|
|
144
|
+
private readonly gateDemandAbove = injectGateDemandAbove();
|
|
145
|
+
|
|
146
|
+
wantsGate(name: IGatedAccessibilityEvent): boolean {
|
|
147
|
+
return gateWanted(this.gateDemandAbove, name, this[name]);
|
|
148
|
+
}
|
|
149
|
+
|
|
124
150
|
// Button-owned props: title is the Text child, color/disabled fold into the label style, and
|
|
125
151
|
// touchSoundDisabled re-maps onto TouchableOpacity.
|
|
126
152
|
@Input() title = '';
|
|
@@ -149,8 +175,10 @@ export class Button implements IButtonProps, DoCheck {
|
|
|
149
175
|
@Input() accessibilityValue?: IAccessibilityProps['accessibilityValue'];
|
|
150
176
|
@Input() accessibilityActions?: IAccessibilityProps['accessibilityActions'];
|
|
151
177
|
@Input() accessibilityLabelledBy?: string | string[];
|
|
152
|
-
@Input()
|
|
153
|
-
|
|
178
|
+
@Input()
|
|
179
|
+
importantForAccessibility?: IAccessibilityProps['importantForAccessibility'];
|
|
180
|
+
@Input()
|
|
181
|
+
accessibilityLiveRegion?: IAccessibilityProps['accessibilityLiveRegion'];
|
|
154
182
|
@Input() screenReaderFocusable?: boolean;
|
|
155
183
|
@Input() accessibilityViewIsModal?: boolean;
|
|
156
184
|
@Input() accessibilityElementsHidden?: boolean;
|
|
@@ -195,7 +223,9 @@ export class Button implements IButtonProps, DoCheck {
|
|
|
195
223
|
// ngDoCheck runs during the PARENT's refresh even when this view is skipped; the signal write is
|
|
196
224
|
// what marks this view. The anchor returns the same props.style reference until a commit changes
|
|
197
225
|
// it, so Object.is makes an unchanged poll free.
|
|
198
|
-
private readonly anchorStyleValue = signal<
|
|
226
|
+
private readonly anchorStyleValue = signal<
|
|
227
|
+
IStyleProp<IViewStyle> | undefined
|
|
228
|
+
>(undefined);
|
|
199
229
|
|
|
200
230
|
ngDoCheck(): void {
|
|
201
231
|
this.anchorStyleValue.set(anchorStyleProp<IViewStyle>(this.elementRef));
|
|
@@ -80,14 +80,20 @@ import {
|
|
|
80
80
|
type IVListSeparatorContext,
|
|
81
81
|
} from '../virtualized-list';
|
|
82
82
|
import { VListOutletDirective } from '../virtualized-list/directives';
|
|
83
|
-
import {
|
|
83
|
+
import {
|
|
84
|
+
stableAnchorStyle,
|
|
85
|
+
SymbioteStyleInputDirective,
|
|
86
|
+
ViewHost,
|
|
87
|
+
} from '../../primitives';
|
|
84
88
|
|
|
85
89
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
86
90
|
return typeof value === 'object' && value !== null;
|
|
87
91
|
}
|
|
88
92
|
function isRow<ItemT>(value: unknown): value is IRow<ItemT> {
|
|
89
93
|
return (
|
|
90
|
-
isRecord(value) &&
|
|
94
|
+
isRecord(value) &&
|
|
95
|
+
Array.isArray(value['items']) &&
|
|
96
|
+
typeof value['startIndex'] === 'number'
|
|
91
97
|
);
|
|
92
98
|
}
|
|
93
99
|
function isSeparators(value: unknown): value is ISeparators {
|
|
@@ -129,7 +135,10 @@ export {
|
|
|
129
135
|
VListItemDirective,
|
|
130
136
|
VListSeparatorDirective,
|
|
131
137
|
} from '../virtualized-list';
|
|
132
|
-
export type {
|
|
138
|
+
export type {
|
|
139
|
+
IVListItemContext,
|
|
140
|
+
IVListSeparatorContext,
|
|
141
|
+
} from '../virtualized-list';
|
|
133
142
|
|
|
134
143
|
// FlatList's imperative handle is exactly VirtualizedList's.
|
|
135
144
|
export type IFlatListHandle = IVirtualizedListHandle;
|
|
@@ -164,7 +173,9 @@ export type IFlatListInputs<ItemT> = Omit<
|
|
|
164
173
|
@Component({
|
|
165
174
|
selector: 'FlatList',
|
|
166
175
|
standalone: true,
|
|
167
|
-
hostDirectives: [
|
|
176
|
+
hostDirectives: [
|
|
177
|
+
{ directive: SymbioteStyleInputDirective, inputs: ['style'] },
|
|
178
|
+
],
|
|
168
179
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
169
180
|
imports: [
|
|
170
181
|
VirtualizedList,
|
|
@@ -254,7 +265,9 @@ export type IFlatListInputs<ItemT> = Omit<
|
|
|
254
265
|
>
|
|
255
266
|
<ng-container
|
|
256
267
|
[vListOutlet]="separatorDir.templateRef"
|
|
257
|
-
[vListOutletContext]="
|
|
268
|
+
[vListOutletContext]="
|
|
269
|
+
rowSeparatorContext(highlighted, leadingItem, trailingItem)
|
|
270
|
+
"
|
|
258
271
|
></ng-container>
|
|
259
272
|
</ng-template>
|
|
260
273
|
}
|
|
@@ -299,7 +312,12 @@ export type IFlatListInputs<ItemT> = Omit<
|
|
|
299
312
|
[style]="resolvedStyle"
|
|
300
313
|
[contentContainerStyle]="contentContainerStyle"
|
|
301
314
|
>
|
|
302
|
-
<ng-template
|
|
315
|
+
<ng-template
|
|
316
|
+
vListItem
|
|
317
|
+
let-item
|
|
318
|
+
let-index="index"
|
|
319
|
+
let-separators="separators"
|
|
320
|
+
>
|
|
303
321
|
<ng-container
|
|
304
322
|
[vListOutlet]="itemDir?.templateRef"
|
|
305
323
|
[vListOutletContext]="{ $implicit: item, index, separators }"
|
|
@@ -329,7 +347,9 @@ export type IFlatListInputs<ItemT> = Omit<
|
|
|
329
347
|
>
|
|
330
348
|
<ng-container
|
|
331
349
|
[vListOutlet]="separatorDir.templateRef"
|
|
332
|
-
[vListOutletContext]="
|
|
350
|
+
[vListOutletContext]="
|
|
351
|
+
itemSeparatorContext(highlighted, leadingItem, trailingItem)
|
|
352
|
+
"
|
|
333
353
|
></ng-container>
|
|
334
354
|
</ng-template>
|
|
335
355
|
}
|
|
@@ -343,10 +363,16 @@ export class FlatList<ItemT = unknown>
|
|
|
343
363
|
// The list's edge/viewability/failure events as real Angular events: `(endReached)="…"`, not
|
|
344
364
|
// `[onEndReached]="…"` — re-emitted straight from the inner VirtualizedList's own @Output()s (see
|
|
345
365
|
// the template's `(endReached)="endReached.emit($event)"` style forwarding above).
|
|
346
|
-
@Output() readonly endReached = new EventEmitter<{
|
|
347
|
-
|
|
366
|
+
@Output() readonly endReached = new EventEmitter<{
|
|
367
|
+
distanceFromEnd: number;
|
|
368
|
+
}>();
|
|
369
|
+
@Output() readonly startReached = new EventEmitter<{
|
|
370
|
+
distanceFromStart: number;
|
|
371
|
+
}>();
|
|
348
372
|
@Output() readonly refresh = new EventEmitter<void>();
|
|
349
|
-
@Output() readonly viewableItemsChanged = new EventEmitter<
|
|
373
|
+
@Output() readonly viewableItemsChanged = new EventEmitter<
|
|
374
|
+
IViewableItemsChangedInfo<ItemT>
|
|
375
|
+
>();
|
|
350
376
|
@Output() readonly scrollToIndexFailed = new EventEmitter<{
|
|
351
377
|
index: number;
|
|
352
378
|
highestMeasuredFrameIndex: number;
|
|
@@ -367,8 +393,10 @@ export class FlatList<ItemT = unknown>
|
|
|
367
393
|
@Input() onStartReachedThreshold?: number;
|
|
368
394
|
@Input() refreshing?: boolean | null;
|
|
369
395
|
@Input() progressViewOffset?: number;
|
|
370
|
-
@Input()
|
|
371
|
-
|
|
396
|
+
@Input()
|
|
397
|
+
viewabilityConfig?: IVirtualizedListProps<ItemT>['viewabilityConfig'];
|
|
398
|
+
@Input()
|
|
399
|
+
viewabilityConfigCallbackPairs?: IViewabilityConfigCallbackPair<ItemT>[];
|
|
372
400
|
@Input() initialNumToRender?: number;
|
|
373
401
|
@Input() initialScrollIndex?: number;
|
|
374
402
|
@Input() maxToRenderPerBatch?: number;
|
|
@@ -380,10 +408,13 @@ export class FlatList<ItemT = unknown>
|
|
|
380
408
|
autoscrollToTopThreshold?: number;
|
|
381
409
|
};
|
|
382
410
|
@Input() onScroll?: IVirtualizedListProps<ItemT>['onScroll'];
|
|
383
|
-
@Input()
|
|
411
|
+
@Input()
|
|
412
|
+
onScrollBeginDrag?: IVirtualizedListProps<ItemT>['onScrollBeginDrag'];
|
|
384
413
|
@Input() onScrollEndDrag?: IVirtualizedListProps<ItemT>['onScrollEndDrag'];
|
|
385
|
-
@Input()
|
|
386
|
-
|
|
414
|
+
@Input()
|
|
415
|
+
onMomentumScrollBegin?: IVirtualizedListProps<ItemT>['onMomentumScrollBegin'];
|
|
416
|
+
@Input()
|
|
417
|
+
onMomentumScrollEnd?: IVirtualizedListProps<ItemT>['onMomentumScrollEnd'];
|
|
387
418
|
@Input() scrollEventThrottle?: number;
|
|
388
419
|
@Input() keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
389
420
|
@Input() keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
@@ -397,7 +428,8 @@ export class FlatList<ItemT = unknown>
|
|
|
397
428
|
@ContentChild(VListHeaderDirective) headerDir?: VListHeaderDirective;
|
|
398
429
|
@ContentChild(VListFooterDirective) footerDir?: VListFooterDirective;
|
|
399
430
|
@ContentChild(VListEmptyDirective) emptyDir?: VListEmptyDirective;
|
|
400
|
-
@ContentChild(VListSeparatorDirective)
|
|
431
|
+
@ContentChild(VListSeparatorDirective)
|
|
432
|
+
separatorDir?: VListSeparatorDirective<ItemT>;
|
|
401
433
|
|
|
402
434
|
// The composed inner list (whichever numColumns branch rendered). Its instance IS the
|
|
403
435
|
// IVirtualizedListHandle, so FlatList's handle delegates straight to it.
|
|
@@ -433,7 +465,11 @@ export class FlatList<ItemT = unknown>
|
|
|
433
465
|
// across ticks that changed nothing - a fresh object every tick defeats VirtualizedList's own
|
|
434
466
|
// dedup gate and free-runs CD (see stableAnchorStyle's doc comment).
|
|
435
467
|
ngDoCheck(): void {
|
|
436
|
-
this.resolvedStyle = stableAnchorStyle(
|
|
468
|
+
this.resolvedStyle = stableAnchorStyle(
|
|
469
|
+
this.elementRef,
|
|
470
|
+
this.style,
|
|
471
|
+
this.resolvedStyle,
|
|
472
|
+
);
|
|
437
473
|
}
|
|
438
474
|
|
|
439
475
|
ngOnChanges(changes: SimpleChanges): void {
|
|
@@ -444,11 +480,18 @@ export class FlatList<ItemT = unknown>
|
|
|
444
480
|
typeof this.columnWrapperStyle === 'string'
|
|
445
481
|
? resolveClassName(this.columnWrapperStyle)
|
|
446
482
|
: this.columnWrapperStyle;
|
|
447
|
-
this.rowStyle = flattenStyle([
|
|
483
|
+
this.rowStyle = flattenStyle([
|
|
484
|
+
{ flexDirection: 'row' },
|
|
485
|
+
resolvedColumnWrapperStyle,
|
|
486
|
+
]);
|
|
448
487
|
}
|
|
449
488
|
if (changes['data'] !== undefined || changes['numColumns'] !== undefined) {
|
|
450
|
-
this.rows = this.isMultiColumn
|
|
451
|
-
|
|
489
|
+
this.rows = this.isMultiColumn
|
|
490
|
+
? chunkIntoRows(this.data, this.columns)
|
|
491
|
+
: [];
|
|
492
|
+
dlog(
|
|
493
|
+
`Angular FlatList over ${this.data?.length ?? 0} items, ${this.columns} column(s)`,
|
|
494
|
+
);
|
|
452
495
|
}
|
|
453
496
|
if (
|
|
454
497
|
changes['viewabilityConfigCallbackPairs'] !== undefined ||
|
|
@@ -469,15 +512,24 @@ export class FlatList<ItemT = unknown>
|
|
|
469
512
|
|
|
470
513
|
// Viewability over rows expands back to per-item tokens, so the caller sees item-level
|
|
471
514
|
// visibility, not row-level (shared expandRowViewability), matching Vue.
|
|
472
|
-
rowViewableItemsChanged = (
|
|
473
|
-
|
|
515
|
+
rowViewableItemsChanged = (
|
|
516
|
+
info: IViewableItemsChangedInfo<IRow<ItemT>>,
|
|
517
|
+
): void => {
|
|
518
|
+
this.viewableItemsChanged.emit(
|
|
519
|
+
expandRowViewability(info, this.keyExtractor),
|
|
520
|
+
);
|
|
474
521
|
};
|
|
475
522
|
|
|
476
|
-
private buildRowViewabilityPairs():
|
|
523
|
+
private buildRowViewabilityPairs():
|
|
524
|
+
IViewabilityConfigCallbackPair<IRow<ItemT>>[] | undefined {
|
|
477
525
|
return this.viewabilityConfigCallbackPairs?.map(pair => ({
|
|
478
526
|
viewabilityConfig: pair.viewabilityConfig,
|
|
479
|
-
onViewableItemsChanged: (
|
|
480
|
-
|
|
527
|
+
onViewableItemsChanged: (
|
|
528
|
+
rowInfo: IViewableItemsChangedInfo<IRow<ItemT>>,
|
|
529
|
+
): void => {
|
|
530
|
+
pair.onViewableItemsChanged?.(
|
|
531
|
+
expandRowViewability(rowInfo, this.keyExtractor),
|
|
532
|
+
);
|
|
481
533
|
},
|
|
482
534
|
}));
|
|
483
535
|
}
|
|
@@ -494,7 +546,9 @@ export class FlatList<ItemT = unknown>
|
|
|
494
546
|
const handle = isSeparators(separators) ? separators : NOOP_SEPARATORS;
|
|
495
547
|
return row.items.map((item, column) => {
|
|
496
548
|
const index = row.startIndex + column;
|
|
497
|
-
const key = this.keyExtractor
|
|
549
|
+
const key = this.keyExtractor
|
|
550
|
+
? this.keyExtractor(item, index)
|
|
551
|
+
: String(index);
|
|
498
552
|
return { key, context: { $implicit: item, index, separators: handle } };
|
|
499
553
|
});
|
|
500
554
|
}
|
|
@@ -511,8 +565,12 @@ export class FlatList<ItemT = unknown>
|
|
|
511
565
|
return {
|
|
512
566
|
$implicit: isHighlighted,
|
|
513
567
|
highlighted: isHighlighted,
|
|
514
|
-
leadingItem: isRow<ItemT>(leadingRow)
|
|
515
|
-
|
|
568
|
+
leadingItem: isRow<ItemT>(leadingRow)
|
|
569
|
+
? lastItemOfRow(leadingRow)
|
|
570
|
+
: undefined,
|
|
571
|
+
trailingItem: isRow<ItemT>(trailingRow)
|
|
572
|
+
? firstItemOfRow(trailingRow)
|
|
573
|
+
: undefined,
|
|
516
574
|
};
|
|
517
575
|
}
|
|
518
576
|
|
|
@@ -545,7 +603,11 @@ export class FlatList<ItemT = unknown>
|
|
|
545
603
|
}): void {
|
|
546
604
|
this.listRef?.scrollToIndex(params);
|
|
547
605
|
}
|
|
548
|
-
scrollToItem(params: {
|
|
606
|
+
scrollToItem(params: {
|
|
607
|
+
item: unknown;
|
|
608
|
+
animated?: boolean;
|
|
609
|
+
viewPosition?: number;
|
|
610
|
+
}): void {
|
|
549
611
|
this.listRef?.scrollToItem(params);
|
|
550
612
|
}
|
|
551
613
|
scrollToEnd(params?: { animated?: boolean }): void {
|
|
@@ -13,7 +13,12 @@ import {
|
|
|
13
13
|
SymbioteHostPropsDirective,
|
|
14
14
|
SymbioteStyleInputDirective,
|
|
15
15
|
} from '../../primitives';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
IMAGE_INPUTS,
|
|
18
|
+
IMAGE_OUTPUTS,
|
|
19
|
+
ImageBase,
|
|
20
|
+
resolveImageProps,
|
|
21
|
+
} from './shared';
|
|
17
22
|
export { setImageSourceResolver } from './shared';
|
|
18
23
|
export type {
|
|
19
24
|
IImageProps,
|
|
@@ -27,7 +32,9 @@ export type {
|
|
|
27
32
|
@Component({
|
|
28
33
|
selector: 'Image',
|
|
29
34
|
standalone: true,
|
|
30
|
-
hostDirectives: [
|
|
35
|
+
hostDirectives: [
|
|
36
|
+
{ directive: SymbioteStyleInputDirective, inputs: ['style'] },
|
|
37
|
+
],
|
|
31
38
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
32
39
|
imports: [ImageHost, SymbioteHostPropsDirective],
|
|
33
40
|
inputs: IMAGE_INPUTS,
|
|
@@ -35,10 +42,6 @@ export type {
|
|
|
35
42
|
template: `
|
|
36
43
|
<symbiote-image
|
|
37
44
|
[symbioteHostProps]="imageProps()"
|
|
38
|
-
(accessibilityAction)="handleAccessibilityAction($event)"
|
|
39
|
-
(accessibilityTap)="handleAccessibilityTap($event)"
|
|
40
|
-
(magicTap)="handleMagicTap($event)"
|
|
41
|
-
(accessibilityEscape)="handleAccessibilityEscape($event)"
|
|
42
45
|
(loadStart)="handleLoadStart($event)"
|
|
43
46
|
(load)="handleLoad($event)"
|
|
44
47
|
(loadEnd)="handleLoadEnd($event)"
|
|
@@ -13,7 +13,12 @@ import {
|
|
|
13
13
|
SymbioteHostPropsDirective,
|
|
14
14
|
SymbioteStyleInputDirective,
|
|
15
15
|
} from '../../primitives';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
IMAGE_INPUTS,
|
|
18
|
+
IMAGE_OUTPUTS,
|
|
19
|
+
ImageBase,
|
|
20
|
+
resolveImageProps,
|
|
21
|
+
} from './shared';
|
|
17
22
|
export { setImageSourceResolver } from './shared';
|
|
18
23
|
export type {
|
|
19
24
|
IImageProps,
|
|
@@ -27,7 +32,9 @@ export type {
|
|
|
27
32
|
@Component({
|
|
28
33
|
selector: 'Image',
|
|
29
34
|
standalone: true,
|
|
30
|
-
hostDirectives: [
|
|
35
|
+
hostDirectives: [
|
|
36
|
+
{ directive: SymbioteStyleInputDirective, inputs: ['style'] },
|
|
37
|
+
],
|
|
31
38
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
32
39
|
imports: [ImageHost, SymbioteHostPropsDirective],
|
|
33
40
|
inputs: IMAGE_INPUTS,
|
|
@@ -35,10 +42,6 @@ export type {
|
|
|
35
42
|
template: `
|
|
36
43
|
<symbiote-image
|
|
37
44
|
[symbioteHostProps]="imageProps()"
|
|
38
|
-
(accessibilityAction)="handleAccessibilityAction($event)"
|
|
39
|
-
(accessibilityTap)="handleAccessibilityTap($event)"
|
|
40
|
-
(magicTap)="handleMagicTap($event)"
|
|
41
|
-
(accessibilityEscape)="handleAccessibilityEscape($event)"
|
|
42
45
|
(loadStart)="handleLoadStart($event)"
|
|
43
46
|
(load)="handleLoad($event)"
|
|
44
47
|
(loadEnd)="handleLoadEnd($event)"
|