@symbiote-native/angular 3.2.0 → 3.4.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/babel-register-composed.cjs +2 -0
- package/build/angular/accessibility-inputs.d.ts +2 -1
- package/build/angular/accessibility-inputs.js +4 -1
- package/build/angular/accessibility-inputs.js.map +1 -1
- package/build/angular/callback-host.d.ts +1 -1
- package/build/angular/callback-host.js +57 -9
- package/build/angular/callback-host.js.map +1 -1
- package/build/angular/components/checkbox-props.d.ts +2 -0
- package/build/angular/components/checkbox-props.js +2 -0
- package/build/angular/components/checkbox-props.js.map +1 -0
- package/build/angular/components/flat-list/flat-list-handle.d.ts +35 -0
- package/build/angular/components/flat-list/flat-list-handle.js +48 -0
- package/build/angular/components/flat-list/flat-list-handle.js.map +1 -0
- package/build/angular/components/flat-list/flat-list-template.d.ts +1 -1
- package/build/angular/components/flat-list/flat-list-template.js +16 -0
- package/build/angular/components/flat-list/flat-list-template.js.map +1 -1
- package/build/angular/components/flat-list/index.d.ts +6 -30
- package/build/angular/components/flat-list/index.js +6 -36
- package/build/angular/components/flat-list/index.js.map +1 -1
- package/build/angular/components/image-inputs.d.ts +4 -0
- package/build/angular/components/image-inputs.js +81 -0
- package/build/angular/components/image-inputs.js.map +1 -0
- package/build/angular/components/image-props-resolve.d.ts +3 -0
- package/build/angular/components/image-props-resolve.js +133 -0
- package/build/angular/components/image-props-resolve.js.map +1 -0
- package/build/angular/components/image-shared.d.ts +8 -6
- package/build/angular/components/image-shared.js +23 -212
- package/build/angular/components/image-shared.js.map +1 -1
- package/build/angular/components/input-accessory-view-props.d.ts +4 -4
- package/build/angular/components/keyboard-avoiding-view/index.d.ts +3 -6
- package/build/angular/components/keyboard-avoiding-view/index.js +29 -56
- package/build/angular/components/keyboard-avoiding-view/index.js.map +1 -1
- package/build/angular/components/layout-conformance-props.d.ts +4 -0
- package/build/angular/components/layout-conformance-props.js +2 -0
- package/build/angular/components/layout-conformance-props.js.map +1 -0
- package/build/angular/components/modal/index.d.ts +6 -5
- package/build/angular/components/modal/index.js +17 -2
- package/build/angular/components/modal/index.js.map +1 -1
- package/build/angular/components/refresh-control-props.d.ts +7 -7
- package/build/angular/components/scroll-view-props.d.ts +8 -5
- package/build/angular/components/section-list/index.d.ts +17 -8
- package/build/angular/components/section-list/index.js +37 -28
- package/build/angular/components/section-list/index.js.map +1 -1
- package/build/angular/components/touchable-props.d.ts +2 -2
- package/build/angular/components/virtualized-list/cell-renderer-context.d.ts +12 -0
- package/build/angular/components/virtualized-list/cell-renderer-context.js +16 -0
- package/build/angular/components/virtualized-list/cell-renderer-context.js.map +1 -0
- package/build/angular/components/virtualized-list/directives.d.ts +26 -6
- package/build/angular/components/virtualized-list/directives.js +59 -5
- package/build/angular/components/virtualized-list/directives.js.map +1 -1
- package/build/angular/components/virtualized-list/index.d.ts +19 -15
- package/build/angular/components/virtualized-list/index.js +91 -61
- package/build/angular/components/virtualized-list/index.js.map +1 -1
- package/build/angular/components/virtualized-list/list-bags.d.ts +5 -1
- package/build/angular/components/virtualized-list/list-bags.js +31 -19
- package/build/angular/components/virtualized-list/list-bags.js.map +1 -1
- package/build/angular/components/virtualized-list/list-effects.d.ts +2 -2
- package/build/angular/components/virtualized-list/list-effects.js +17 -27
- package/build/angular/components/virtualized-list/list-effects.js.map +1 -1
- package/build/angular/components/virtualized-list/list-handle.d.ts +4 -1
- package/build/angular/components/virtualized-list/list-handle.js +13 -3
- package/build/angular/components/virtualized-list/list-handle.js.map +1 -1
- package/build/angular/components/virtualized-list/list-inputs.d.ts +19 -5
- package/build/angular/components/virtualized-list/list-inputs.js +47 -4
- package/build/angular/components/virtualized-list/list-inputs.js.map +1 -1
- package/build/angular/components/virtualized-list/list-props.d.ts +9 -3
- package/build/angular/components/virtualized-list/list-rows.d.ts +25 -0
- package/build/angular/components/virtualized-list/list-rows.js +25 -0
- package/build/angular/components/virtualized-list/list-rows.js.map +1 -0
- package/build/angular/components/virtualized-list/list-styles.d.ts +4 -0
- package/build/angular/components/virtualized-list/list-styles.js +10 -2
- package/build/angular/components/virtualized-list/list-styles.js.map +1 -1
- package/build/angular/components/virtualized-list/list-template.d.ts +1 -1
- package/build/angular/components/virtualized-list/list-template.js +159 -73
- package/build/angular/components/virtualized-list/list-template.js.map +1 -1
- package/build/angular/components/virtualized-list/nested-scope.d.ts +6 -0
- package/build/angular/components/virtualized-list/nested-scope.js +17 -0
- package/build/angular/components/virtualized-list/nested-scope.js.map +1 -0
- package/build/angular/components/virtualized-section-list/directives.d.ts +21 -9
- package/build/angular/components/virtualized-section-list/directives.js +8 -28
- package/build/angular/components/virtualized-section-list/directives.js.map +1 -1
- package/build/angular/components/virtualized-section-list/index.d.ts +39 -60
- package/build/angular/components/virtualized-section-list/index.js +67 -33
- package/build/angular/components/virtualized-section-list/index.js.map +1 -1
- package/build/angular/components/virtualized-section-list/section-cell.d.ts +29 -0
- package/build/angular/components/virtualized-section-list/section-cell.js +82 -0
- package/build/angular/components/virtualized-section-list/section-cell.js.map +1 -0
- package/build/angular/components/virtualized-section-list/section-list-props.d.ts +56 -0
- package/build/angular/components/virtualized-section-list/section-list-props.js +3 -0
- package/build/angular/components/virtualized-section-list/section-list-props.js.map +1 -0
- package/build/angular/components/virtualized-section-list/section-list-template.d.ts +1 -1
- package/build/angular/components/virtualized-section-list/section-list-template.js +34 -26
- package/build/angular/components/virtualized-section-list/section-list-template.js.map +1 -1
- package/build/angular/components.d.ts +8 -3
- package/build/angular/components.js +2 -1
- package/build/angular/components.js.map +1 -1
- package/build/angular/descriptor-to-angular/descriptor-host.d.ts +8 -0
- package/build/angular/descriptor-to-angular/descriptor-host.js +38 -0
- package/build/angular/descriptor-to-angular/descriptor-host.js.map +1 -0
- package/build/angular/descriptor-to-angular/index.d.ts +1 -0
- package/build/angular/descriptor-to-angular/index.js +4 -0
- package/build/angular/descriptor-to-angular/index.js.map +1 -1
- package/build/angular/element-base.d.ts +169 -0
- package/build/angular/element-base.js +304 -0
- package/build/angular/element-base.js.map +1 -0
- package/build/angular/element-props.d.ts +7 -7
- package/build/angular/element-text-input-native.d.ts +27 -0
- package/build/angular/element-text-input-native.js +52 -0
- package/build/angular/element-text-input-native.js.map +1 -0
- package/build/angular/elements-controls.d.ts +171 -0
- package/build/angular/elements-controls.js +394 -0
- package/build/angular/elements-controls.js.map +1 -0
- package/build/angular/elements-layout.d.ts +139 -0
- package/build/angular/elements-layout.js +276 -0
- package/build/angular/elements-layout.js.map +1 -0
- package/build/angular/elements-press.d.ts +103 -0
- package/build/angular/elements-press.js +239 -0
- package/build/angular/elements-press.js.map +1 -0
- package/build/angular/elements.d.ts +6 -516
- package/build/angular/elements.js +9 -1091
- package/build/angular/elements.js.map +1 -1
- package/build/angular/host-instance/index.d.ts +2 -0
- package/build/angular/host-instance/index.js +4 -4
- package/build/angular/host-instance/index.js.map +1 -1
- package/build/angular/index.d.ts +17 -9
- package/build/angular/index.js +24 -27
- package/build/angular/index.js.map +1 -1
- package/build/angular/modules/animated/create-animated-component.d.ts +1 -1
- package/build/angular/modules/animated/create-animated-component.js +1 -1
- package/build/angular/modules/animated/create-animated-component.js.map +1 -1
- package/build/angular/modules/animated/index.d.ts +54 -41
- package/build/angular/modules/animated/index.js +2 -26
- package/build/angular/modules/animated/index.js.map +1 -1
- package/build/angular/modules/app-registry/index.d.ts +3 -3
- package/build/angular/modules/app-registry/index.js +2 -2
- package/build/angular/modules/app-registry/index.js.map +1 -1
- package/build/angular/modules/status-bar/index.d.ts +9 -5
- package/build/angular/modules/status-bar/index.js +21 -10
- package/build/angular/modules/status-bar/index.js.map +1 -1
- package/build/angular/native-view-base.d.ts +10 -2
- package/build/angular/native-view-base.js +23 -2
- package/build/angular/native-view-base.js.map +1 -1
- package/build/angular/primitives/index.d.ts +4 -0
- package/build/angular/primitives/index.js +12 -0
- package/build/angular/primitives/index.js.map +1 -1
- package/build/angular/services/color-scheme.service.d.ts +1 -1
- package/build/angular/services/index.d.ts +1 -0
- package/build/angular/services/index.js +1 -0
- package/build/angular/services/index.js.map +1 -1
- package/build/angular/services/inject-event.d.ts +6 -0
- package/build/angular/services/inject-event.js +24 -0
- package/build/angular/services/inject-event.js.map +1 -0
- package/package.json +6 -6
- package/src/accessibility-inputs.ts +3 -0
- package/src/callback-host.ts +56 -8
- package/src/components/checkbox-props.ts +12 -0
- package/src/components/flat-list/flat-list-handle.ts +64 -0
- package/src/components/flat-list/flat-list-template.ts +16 -0
- package/src/components/flat-list/index.ts +6 -48
- package/src/components/image-inputs.ts +94 -0
- package/src/components/image-props-resolve.ts +172 -0
- package/src/components/image-shared.ts +26 -291
- package/src/components/input-accessory-view-props.ts +12 -8
- package/src/components/keyboard-avoiding-view/index.ts +39 -79
- package/src/components/layout-conformance-props.ts +8 -0
- package/src/components/modal/index.ts +42 -20
- package/src/components/refresh-control-props.ts +29 -25
- package/src/components/scroll-view-props.ts +84 -76
- package/src/components/section-list/index.ts +34 -37
- package/src/components/touchable-props.ts +6 -2
- package/src/components/virtualized-list/cell-renderer-context.ts +36 -0
- package/src/components/virtualized-list/directives.ts +84 -8
- package/src/components/virtualized-list/index.ts +118 -85
- package/src/components/virtualized-list/list-bags.ts +38 -19
- package/src/components/virtualized-list/list-effects.ts +20 -32
- package/src/components/virtualized-list/list-handle.ts +17 -4
- package/src/components/virtualized-list/list-inputs.ts +47 -0
- package/src/components/virtualized-list/list-props.ts +57 -50
- package/src/components/virtualized-list/list-rows.ts +66 -0
- package/src/components/virtualized-list/list-styles.ts +30 -1
- package/src/components/virtualized-list/list-template.ts +159 -73
- package/src/components/virtualized-list/nested-scope.ts +22 -0
- package/src/components/virtualized-section-list/directives.ts +41 -40
- package/src/components/virtualized-section-list/index.ts +114 -118
- package/src/components/virtualized-section-list/section-cell.ts +109 -0
- package/src/components/virtualized-section-list/section-list-props.ts +79 -0
- package/src/components/virtualized-section-list/section-list-template.ts +34 -26
- package/src/components.ts +9 -0
- package/src/descriptor-to-angular/descriptor-host.ts +27 -0
- package/src/descriptor-to-angular/index.ts +5 -0
- package/src/element-base.ts +289 -0
- package/src/element-props.ts +35 -33
- package/src/element-text-input-native.ts +31 -0
- package/src/elements-controls.ts +290 -0
- package/src/elements-layout.ts +168 -0
- package/src/elements-press.ts +153 -0
- package/src/elements.ts +76 -788
- package/src/host-instance/index.ts +4 -4
- package/src/index.ts +78 -23
- package/src/modules/animated/index.ts +2 -47
- package/src/modules/app-registry/index.ts +3 -1
- package/src/modules/status-bar/index.ts +24 -11
- package/src/native-view-base.ts +37 -2
- package/src/primitives/index.ts +7 -0
- package/src/services/color-scheme.service.ts +1 -1
- package/src/services/index.ts +1 -0
- package/src/services/inject-event.ts +52 -0
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// reducer only knows a delay for (the incremental fill and the viewability debounce)
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
EMPTY_OFFSET,
|
|
6
5
|
LIST_ACTION_KIND,
|
|
7
6
|
LIST_EFFECT_KIND,
|
|
8
7
|
type IListAction,
|
|
@@ -24,13 +23,14 @@ export type IEffectHost<ItemT> = {
|
|
|
24
23
|
}>;
|
|
25
24
|
};
|
|
26
25
|
|
|
27
|
-
type
|
|
28
|
-
IListEffect<
|
|
29
|
-
{ kind: typeof LIST_EFFECT_KIND.
|
|
26
|
+
type IScheduledViewable = Extract<
|
|
27
|
+
IListEffect<unknown>,
|
|
28
|
+
{ kind: typeof LIST_EFFECT_KIND.scheduleViewable }
|
|
30
29
|
>;
|
|
31
30
|
|
|
32
31
|
export class ListEffectRunner<ItemT> {
|
|
33
|
-
|
|
32
|
+
// RN never cancels a `minimumViewTime` timer, each one comes due and the reducer filters it
|
|
33
|
+
private readonly viewableTimers = new Set<ReturnType<typeof setTimeout>>();
|
|
34
34
|
private batchTimer: ReturnType<typeof setTimeout> | null = null;
|
|
35
35
|
|
|
36
36
|
constructor(private readonly host: IEffectHost<ItemT>) {}
|
|
@@ -40,7 +40,8 @@ export class ListEffectRunner<ItemT> {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
dispose(): void {
|
|
43
|
-
|
|
43
|
+
for (const timer of this.viewableTimers) clearTimeout(timer);
|
|
44
|
+
this.viewableTimers.clear();
|
|
44
45
|
if (this.batchTimer !== null) clearTimeout(this.batchTimer);
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -71,7 +72,12 @@ export class ListEffectRunner<ItemT> {
|
|
|
71
72
|
this.scheduleRefill(effect.delay);
|
|
72
73
|
break;
|
|
73
74
|
case LIST_EFFECT_KIND.fireViewable:
|
|
74
|
-
|
|
75
|
+
inputs.viewabilityPairs[effect.pairIndex]?.onViewableItemsChanged(
|
|
76
|
+
effect.info,
|
|
77
|
+
);
|
|
78
|
+
break;
|
|
79
|
+
case LIST_EFFECT_KIND.scheduleViewable:
|
|
80
|
+
this.scheduleViewable(effect);
|
|
75
81
|
break;
|
|
76
82
|
}
|
|
77
83
|
}
|
|
@@ -84,33 +90,15 @@ export class ListEffectRunner<ItemT> {
|
|
|
84
90
|
}, delay);
|
|
85
91
|
}
|
|
86
92
|
|
|
87
|
-
private
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
): void {
|
|
91
|
-
const fire = (): void => {
|
|
92
|
-
for (const pair of inputs.viewabilityPairs) {
|
|
93
|
-
pair.onViewableItemsChanged({
|
|
94
|
-
...effect.info,
|
|
95
|
-
viewabilityConfig: pair.viewabilityConfig,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
93
|
+
private scheduleViewable(effect: IScheduledViewable): void {
|
|
94
|
+
const timer = setTimeout(() => {
|
|
95
|
+
this.viewableTimers.delete(timer);
|
|
98
96
|
this.host.dispatch({
|
|
99
|
-
kind: LIST_ACTION_KIND.
|
|
100
|
-
|
|
97
|
+
kind: LIST_ACTION_KIND.viewableDue,
|
|
98
|
+
pairIndex: effect.pairIndex,
|
|
99
|
+
indices: effect.indices,
|
|
101
100
|
});
|
|
102
|
-
};
|
|
103
|
-
if (this.viewableTimer !== null) {
|
|
104
|
-
clearTimeout(this.viewableTimer);
|
|
105
|
-
this.viewableTimer = null;
|
|
106
|
-
}
|
|
107
|
-
if (effect.delay <= EMPTY_OFFSET) {
|
|
108
|
-
fire();
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
this.viewableTimer = setTimeout(() => {
|
|
112
|
-
this.viewableTimer = null;
|
|
113
|
-
fire();
|
|
114
101
|
}, effect.delay);
|
|
102
|
+
this.viewableTimers.add(timer);
|
|
115
103
|
}
|
|
116
104
|
}
|
|
@@ -70,23 +70,36 @@ export abstract class VirtualizedListHandleBase<ItemT>
|
|
|
70
70
|
this.scrollHandle.flashScrollIndicators();
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
// Null until the scroll tag commits, RN's "no scroll view yet" answer
|
|
74
|
+
private handleOrNull(): IScrollViewHandle | null {
|
|
75
|
+
return this.scrollNode === null ? null : this.scrollHandle;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getNativeScrollRef(): ISymbioteNode | null {
|
|
79
|
+
return this.scrollHandle.getScrollNode();
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
getScrollableNode(): IScrollViewHandle | null {
|
|
78
|
-
return this.
|
|
83
|
+
return this.handleOrNull();
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
getScrollResponder(): IScrollViewHandle | null {
|
|
82
|
-
return this.
|
|
87
|
+
return this.handleOrNull();
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
getScrollNode(): ISymbioteNode | null {
|
|
86
91
|
return this.scrollHandle.getScrollNode();
|
|
87
92
|
}
|
|
88
93
|
|
|
94
|
+
getScrollRef(): ISymbioteNode | null {
|
|
95
|
+
return this.scrollHandle.getScrollNode();
|
|
96
|
+
}
|
|
97
|
+
|
|
89
98
|
recordInteraction(): void {
|
|
90
99
|
this.dispatch({ kind: LIST_ACTION_KIND.recordInteraction });
|
|
91
100
|
}
|
|
101
|
+
|
|
102
|
+
setNativeProps(props: Record<string, unknown>): void {
|
|
103
|
+
this.scrollNode?.setNativeProps(props);
|
|
104
|
+
}
|
|
92
105
|
}
|
|
@@ -8,12 +8,16 @@ import {
|
|
|
8
8
|
Input,
|
|
9
9
|
Output,
|
|
10
10
|
TemplateRef,
|
|
11
|
+
type Type,
|
|
11
12
|
} from '@angular/core';
|
|
12
13
|
import {
|
|
13
14
|
DEFAULT_INITIAL_NUM_TO_RENDER,
|
|
14
15
|
DEFAULT_MAX_TO_RENDER_PER_BATCH,
|
|
15
16
|
DEFAULT_UPDATE_CELLS_BATCHING_PERIOD,
|
|
16
17
|
DEFAULT_WINDOW_SIZE,
|
|
18
|
+
ITEM_RENDERER,
|
|
19
|
+
pickItemRenderer,
|
|
20
|
+
type IInnerViewRef,
|
|
17
21
|
type IViewabilityConfig,
|
|
18
22
|
type IViewabilityConfigCallbackPair,
|
|
19
23
|
type IViewableItemsChangedInfo,
|
|
@@ -24,11 +28,13 @@ import type {
|
|
|
24
28
|
IViewStyle,
|
|
25
29
|
} from '@symbiote-native/engine';
|
|
26
30
|
import {
|
|
31
|
+
VListCellDirective,
|
|
27
32
|
VListEmptyDirective,
|
|
28
33
|
VListFooterDirective,
|
|
29
34
|
VListHeaderDirective,
|
|
30
35
|
VListItemDirective,
|
|
31
36
|
VListSeparatorDirective,
|
|
37
|
+
type IVListCellContext,
|
|
32
38
|
type IVListItemContext,
|
|
33
39
|
type IVListSeparatorContext,
|
|
34
40
|
} from './directives';
|
|
@@ -66,6 +72,8 @@ export abstract class ListInputsBase<ItemT> extends ListEventsBase {
|
|
|
66
72
|
@Input() maxToRenderPerBatch?: number;
|
|
67
73
|
@Input() updateCellsBatchingPeriod?: number;
|
|
68
74
|
@Input() windowSize?: number;
|
|
75
|
+
// Mounts every cell from the top and paints no spacer, the window only grows toward the end
|
|
76
|
+
@Input() disableVirtualization?: boolean;
|
|
69
77
|
@Input() stickyHeaderIndices?: number[];
|
|
70
78
|
@Input() maintainVisibleContentPosition?: {
|
|
71
79
|
minIndexForVisible: number;
|
|
@@ -76,15 +84,23 @@ export abstract class ListInputsBase<ItemT> extends ListEventsBase {
|
|
|
76
84
|
@Input() onScrollEndDrag?: (event: ISymbioteEvent) => void;
|
|
77
85
|
@Input() onMomentumScrollBegin?: (event: ISymbioteEvent) => void;
|
|
78
86
|
@Input() onMomentumScrollEnd?: (event: ISymbioteEvent) => void;
|
|
87
|
+
@Input() onContentSizeChange?: (width: number, height: number) => void;
|
|
79
88
|
@Input() scrollEventThrottle?: number;
|
|
80
89
|
@Input() keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
81
90
|
@Input() keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
82
91
|
@Input() removeClippedSubviews?: boolean;
|
|
83
92
|
@Input() nestedScrollEnabled?: boolean;
|
|
93
|
+
@Input() stickyHeaderHiddenOnScroll?: boolean;
|
|
94
|
+
@Input() innerViewRef?: IInnerViewRef;
|
|
84
95
|
@Input() style?: IStyleProp<IViewStyle>;
|
|
85
96
|
@Input() contentContainerStyle?: IStyleProp<IViewStyle>;
|
|
97
|
+
@Input() listHeaderComponentStyle?: IStyleProp<IViewStyle>;
|
|
98
|
+
@Input() listFooterComponentStyle?: IStyleProp<IViewStyle>;
|
|
86
99
|
@Input() testID?: string;
|
|
87
100
|
@Input() nativeID?: string;
|
|
101
|
+
// RN's `ListItemComponent`: a component taking `item`, `index` and `separators` inputs, in place
|
|
102
|
+
// of the `vListItem` template, and it wins when both are given
|
|
103
|
+
@Input() listItemComponent?: Type<unknown>;
|
|
88
104
|
|
|
89
105
|
// The cell and slot templates the app authors, captured from projected <ng-template> content
|
|
90
106
|
@ContentChild(VListItemDirective) itemDir?: VListItemDirective<ItemT>;
|
|
@@ -93,11 +109,33 @@ export abstract class ListInputsBase<ItemT> extends ListEventsBase {
|
|
|
93
109
|
@ContentChild(VListEmptyDirective) emptyDir?: VListEmptyDirective;
|
|
94
110
|
@ContentChild(VListSeparatorDirective)
|
|
95
111
|
separatorDir?: VListSeparatorDirective<ItemT>;
|
|
112
|
+
@ContentChild(VListCellDirective) cellDir?: VListCellDirective;
|
|
96
113
|
|
|
97
114
|
get isHorizontal(): boolean {
|
|
98
115
|
return this.horizontal === true;
|
|
99
116
|
}
|
|
100
117
|
|
|
118
|
+
// The app's `vListCell`, which a list built on this one may replace with its own
|
|
119
|
+
get cellRendererTpl(): TemplateRef<IVListCellContext> | undefined {
|
|
120
|
+
return this.cellDir?.templateRef;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// The component to stamp per cell, RN's `_renderElement`: it wins over the item template, and a
|
|
124
|
+
// cell with neither throws
|
|
125
|
+
get itemComponent(): Type<unknown> | undefined {
|
|
126
|
+
const kind = pickItemRenderer({
|
|
127
|
+
hasRenderItem: this.hasItemTemplate,
|
|
128
|
+
hasComponent: this.listItemComponent !== undefined,
|
|
129
|
+
});
|
|
130
|
+
return kind === ITEM_RENDERER.component
|
|
131
|
+
? this.listItemComponent
|
|
132
|
+
: undefined;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
protected get hasItemTemplate(): boolean {
|
|
136
|
+
return this.itemDir !== undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
101
139
|
protected get isInverted(): boolean {
|
|
102
140
|
return this.inverted === true;
|
|
103
141
|
}
|
|
@@ -137,11 +175,20 @@ export abstract class VirtualizedListInputs<
|
|
|
137
175
|
// outlet deep instead of a wrapper outlet around the app's own. Each wins over projection
|
|
138
176
|
@Input() itemTemplate?: TemplateRef<IVListItemContext<ItemT>>;
|
|
139
177
|
@Input() itemSeparatorTemplate?: TemplateRef<IVListSeparatorContext<ItemT>>;
|
|
178
|
+
@Input() cellRendererTemplate?: TemplateRef<IVListCellContext>;
|
|
179
|
+
|
|
180
|
+
override get cellRendererTpl(): TemplateRef<IVListCellContext> | undefined {
|
|
181
|
+
return this.cellRendererTemplate ?? this.cellDir?.templateRef;
|
|
182
|
+
}
|
|
140
183
|
|
|
141
184
|
get cellTemplate(): TemplateRef<IVListItemContext<ItemT>> | undefined {
|
|
142
185
|
return this.itemTemplate ?? this.itemDir?.templateRef;
|
|
143
186
|
}
|
|
144
187
|
|
|
188
|
+
protected override get hasItemTemplate(): boolean {
|
|
189
|
+
return this.cellTemplate !== undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
145
192
|
get separatorTemplate():
|
|
146
193
|
TemplateRef<IVListSeparatorContext<ItemT>> | undefined {
|
|
147
194
|
return this.itemSeparatorTemplate ?? this.separatorDir?.templateRef;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import type {
|
|
4
4
|
IAccessibilityProps,
|
|
5
5
|
IAriaProps,
|
|
6
|
+
IInnerViewRef,
|
|
6
7
|
IViewabilityConfig,
|
|
7
8
|
IViewabilityConfigCallbackPair,
|
|
8
9
|
IViewableItemsChangedInfo,
|
|
@@ -14,57 +15,63 @@ import type {
|
|
|
14
15
|
} from '@symbiote-native/engine';
|
|
15
16
|
|
|
16
17
|
// The React and Vue surface minus element-returning props, which are `<ng-template>` here
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
18
|
+
export type IVirtualizedListProps<ItemT> = IAccessibilityProps &
|
|
19
|
+
IAriaProps & {
|
|
20
|
+
data: unknown;
|
|
21
|
+
getItem: (data: unknown, index: number) => ItemT;
|
|
22
|
+
getItemCount: (data: unknown) => number;
|
|
23
|
+
keyExtractor?: (item: ItemT, index: number) => string;
|
|
24
|
+
getItemLayout?: (
|
|
25
|
+
data: unknown,
|
|
26
|
+
index: number,
|
|
27
|
+
) => { length: number; offset: number; index: number };
|
|
28
|
+
horizontal?: boolean;
|
|
29
|
+
inverted?: boolean;
|
|
30
|
+
extraData?: unknown;
|
|
31
|
+
onEndReached?: (info: { distanceFromEnd: number }) => void;
|
|
32
|
+
onEndReachedThreshold?: number;
|
|
33
|
+
onStartReached?: (info: { distanceFromStart: number }) => void;
|
|
34
|
+
onStartReachedThreshold?: number;
|
|
35
|
+
onRefresh?: () => void;
|
|
36
|
+
refreshing?: boolean | null;
|
|
37
|
+
progressViewOffset?: number;
|
|
38
|
+
onViewableItemsChanged?: (info: IViewableItemsChangedInfo<ItemT>) => void;
|
|
39
|
+
viewabilityConfig?: IViewabilityConfig;
|
|
40
|
+
viewabilityConfigCallbackPairs?: IViewabilityConfigCallbackPair<ItemT>[];
|
|
41
|
+
onScrollToIndexFailed?: (info: {
|
|
42
|
+
index: number;
|
|
43
|
+
highestMeasuredFrameIndex: number;
|
|
44
|
+
averageItemLength: number;
|
|
45
|
+
}) => void;
|
|
46
|
+
initialNumToRender?: number;
|
|
47
|
+
initialScrollIndex?: number;
|
|
48
|
+
maxToRenderPerBatch?: number;
|
|
49
|
+
updateCellsBatchingPeriod?: number;
|
|
50
|
+
windowSize?: number;
|
|
51
|
+
disableVirtualization?: boolean;
|
|
52
|
+
stickyHeaderIndices?: number[];
|
|
53
|
+
maintainVisibleContentPosition?: {
|
|
54
|
+
minIndexForVisible: number;
|
|
55
|
+
autoscrollToTopThreshold?: number;
|
|
56
|
+
};
|
|
57
|
+
onScroll?: (event: ISymbioteEvent) => void;
|
|
58
|
+
onScrollBeginDrag?: (event: ISymbioteEvent) => void;
|
|
59
|
+
onScrollEndDrag?: (event: ISymbioteEvent) => void;
|
|
60
|
+
onMomentumScrollBegin?: (event: ISymbioteEvent) => void;
|
|
61
|
+
onMomentumScrollEnd?: (event: ISymbioteEvent) => void;
|
|
62
|
+
onContentSizeChange?: (width: number, height: number) => void;
|
|
63
|
+
scrollEventThrottle?: number;
|
|
64
|
+
keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
65
|
+
keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
66
|
+
removeClippedSubviews?: boolean;
|
|
67
|
+
nestedScrollEnabled?: boolean;
|
|
68
|
+
stickyHeaderHiddenOnScroll?: boolean;
|
|
69
|
+
innerViewRef?: IInnerViewRef;
|
|
70
|
+
style?: IStyleProp<IViewStyle>;
|
|
71
|
+
contentContainerStyle?: IStyleProp<IViewStyle>;
|
|
72
|
+
listHeaderComponentStyle?: IStyleProp<IViewStyle>;
|
|
73
|
+
listFooterComponentStyle?: IStyleProp<IViewStyle>;
|
|
54
74
|
};
|
|
55
|
-
onScroll?: (event: ISymbioteEvent) => void;
|
|
56
|
-
onScrollBeginDrag?: (event: ISymbioteEvent) => void;
|
|
57
|
-
onScrollEndDrag?: (event: ISymbioteEvent) => void;
|
|
58
|
-
onMomentumScrollBegin?: (event: ISymbioteEvent) => void;
|
|
59
|
-
onMomentumScrollEnd?: (event: ISymbioteEvent) => void;
|
|
60
|
-
scrollEventThrottle?: number;
|
|
61
|
-
keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
62
|
-
keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
63
|
-
removeClippedSubviews?: boolean;
|
|
64
|
-
nestedScrollEnabled?: boolean;
|
|
65
|
-
style?: IStyleProp<IViewStyle>;
|
|
66
|
-
contentContainerStyle?: IStyleProp<IViewStyle>;
|
|
67
|
-
}
|
|
68
75
|
|
|
69
76
|
// The plain inputs: the full surface minus the events exposed as real outputs
|
|
70
77
|
export type IVirtualizedListInputs<ItemT> = Omit<
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// The rows the template stamps: the plan's spacers and cells, keyed so a window slide moves them
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
LIST_SEGMENT_KIND,
|
|
5
|
+
spacerStyleOf,
|
|
6
|
+
type IWindowPlan,
|
|
7
|
+
} from '@symbiote-native/components';
|
|
8
|
+
import type { IViewStyle } from '@symbiote-native/engine';
|
|
9
|
+
import type { CellRegistry, IWindowCell } from './cell-registry';
|
|
10
|
+
import type { IVListCellContext } from './directives';
|
|
11
|
+
|
|
12
|
+
export type ISpacerRow = {
|
|
13
|
+
kind: typeof LIST_SEGMENT_KIND.spacer;
|
|
14
|
+
key: string;
|
|
15
|
+
style: IViewStyle;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type ICellRow<ItemT> = {
|
|
19
|
+
kind: typeof LIST_SEGMENT_KIND.cell;
|
|
20
|
+
key: string;
|
|
21
|
+
cell: IWindowCell<ItemT>;
|
|
22
|
+
// Only when the app drew its own cell wrapper with `vListCell`
|
|
23
|
+
renderer: IVListCellContext | undefined;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type IListRow<ItemT> = ISpacerRow | ICellRow<ItemT>;
|
|
27
|
+
|
|
28
|
+
export type IRowsParams<ItemT> = {
|
|
29
|
+
windowPlan: IWindowPlan;
|
|
30
|
+
cells: CellRegistry<ItemT>;
|
|
31
|
+
count: number;
|
|
32
|
+
isHorizontal: boolean;
|
|
33
|
+
hasSeparators: boolean;
|
|
34
|
+
rendererFor: ((cell: IWindowCell<ItemT>) => IVListCellContext) | undefined;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// A cell and a spacer never share a row key, an item key cannot start with `spacer-`
|
|
38
|
+
export function stampPlanRows<ItemT>(
|
|
39
|
+
params: IRowsParams<ItemT>,
|
|
40
|
+
): IListRow<ItemT>[] {
|
|
41
|
+
const { windowPlan, cells, count, isHorizontal, hasSeparators, rendererFor } =
|
|
42
|
+
params;
|
|
43
|
+
return windowPlan.plan.segments.map((segment): IListRow<ItemT> => {
|
|
44
|
+
if (segment.kind === LIST_SEGMENT_KIND.spacer) {
|
|
45
|
+
return {
|
|
46
|
+
kind: segment.kind,
|
|
47
|
+
key: segment.key,
|
|
48
|
+
style: spacerStyleOf(segment.extent, isHorizontal),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// The separator gates on the last index of the data, not of the window, or a cell's height
|
|
52
|
+
// would shift as it slides past
|
|
53
|
+
const cell = cells.windowCell(
|
|
54
|
+
segment.index,
|
|
55
|
+
segment.key,
|
|
56
|
+
hasSeparators && segment.index < count - 1,
|
|
57
|
+
windowPlan.stickySet?.has(segment.index) === true,
|
|
58
|
+
);
|
|
59
|
+
return {
|
|
60
|
+
kind: segment.kind,
|
|
61
|
+
key: `cell-${segment.key}`,
|
|
62
|
+
cell,
|
|
63
|
+
renderer: rendererFor?.(cell),
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import {
|
|
5
5
|
INVERTED_X_STYLE,
|
|
6
6
|
INVERTED_Y_STYLE,
|
|
7
|
+
cellStyleOf,
|
|
7
8
|
} from '@symbiote-native/components';
|
|
8
9
|
import {
|
|
9
10
|
flattenStyle,
|
|
@@ -23,6 +24,8 @@ export type IListStyleInput = {
|
|
|
23
24
|
hasHeader: boolean;
|
|
24
25
|
style: IStyleProp<IViewStyle> | undefined;
|
|
25
26
|
contentContainerStyle: IStyleProp<IViewStyle> | undefined;
|
|
27
|
+
listHeaderComponentStyle: IStyleProp<IViewStyle> | undefined;
|
|
28
|
+
listFooterComponentStyle: IStyleProp<IViewStyle> | undefined;
|
|
26
29
|
// The class-derived style of the list's own anchor host
|
|
27
30
|
anchorStyle: unknown;
|
|
28
31
|
maintainVisibleContentPosition: IMaintainVisibleContentPosition | undefined;
|
|
@@ -34,9 +37,20 @@ export type IListStyles = {
|
|
|
34
37
|
style: IViewStyle | undefined;
|
|
35
38
|
contentContainerStyle: IStyleProp<IViewStyle> | undefined;
|
|
36
39
|
cellStyle: IViewStyle | undefined;
|
|
40
|
+
// The slot wrappers counter-flip with an inverted list, then take the slot's own style
|
|
41
|
+
headerStyle: IViewStyle | undefined;
|
|
42
|
+
footerStyle: IViewStyle | undefined;
|
|
37
43
|
maintainVisibleContentPosition: IMaintainVisibleContentPosition | undefined;
|
|
38
44
|
};
|
|
39
45
|
|
|
46
|
+
function slotStyle(
|
|
47
|
+
isInverted: boolean,
|
|
48
|
+
inversion: IViewStyle,
|
|
49
|
+
style: IStyleProp<IViewStyle> | undefined,
|
|
50
|
+
): IViewStyle | undefined {
|
|
51
|
+
return flattenStyle(isInverted ? [inversion, style] : style);
|
|
52
|
+
}
|
|
53
|
+
|
|
40
54
|
export function resolveListStyles(input: IListStyleInput): IListStyles {
|
|
41
55
|
const inversion = input.isHorizontal ? INVERTED_X_STYLE : INVERTED_Y_STYLE;
|
|
42
56
|
const mvcp = input.maintainVisibleContentPosition;
|
|
@@ -49,7 +63,22 @@ export function resolveListStyles(input: IListStyleInput): IListStyles {
|
|
|
49
63
|
input.anchorStyle,
|
|
50
64
|
input.isInverted ? [inversion, input.style] : input.style,
|
|
51
65
|
]),
|
|
52
|
-
cellStyle:
|
|
66
|
+
cellStyle: flattenStyle(
|
|
67
|
+
cellStyleOf({
|
|
68
|
+
horizontal: input.isHorizontal,
|
|
69
|
+
inverted: input.isInverted,
|
|
70
|
+
}),
|
|
71
|
+
),
|
|
72
|
+
headerStyle: slotStyle(
|
|
73
|
+
input.isInverted,
|
|
74
|
+
inversion,
|
|
75
|
+
input.listHeaderComponentStyle,
|
|
76
|
+
),
|
|
77
|
+
footerStyle: slotStyle(
|
|
78
|
+
input.isInverted,
|
|
79
|
+
inversion,
|
|
80
|
+
input.listFooterComponentStyle,
|
|
81
|
+
),
|
|
53
82
|
maintainVisibleContentPosition:
|
|
54
83
|
mvcp === undefined
|
|
55
84
|
? undefined
|