@symbiote-native/angular 3.3.0 → 3.5.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 +1 -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/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 +7 -3
- package/build/angular/components.js +2 -1
- package/build/angular/components.js.map +1 -1
- package/build/angular/element-base.d.ts +17 -1
- package/build/angular/element-base.js +33 -1
- package/build/angular/element-base.js.map +1 -1
- 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 +8 -2
- package/build/angular/elements-controls.js +13 -1
- package/build/angular/elements-controls.js.map +1 -1
- package/build/angular/elements-layout.d.ts +20 -3
- package/build/angular/elements-layout.js +37 -3
- package/build/angular/elements-layout.js.map +1 -1
- package/build/angular/elements-press.d.ts +10 -3
- package/build/angular/elements-press.js +13 -1
- package/build/angular/elements-press.js.map +1 -1
- package/build/angular/elements.d.ts +3 -3
- package/build/angular/elements.js +3 -2
- package/build/angular/elements.js.map +1 -1
- package/build/angular/index.d.ts +15 -7
- package/build/angular/index.js +22 -25
- 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/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/render/index.d.ts +2 -2
- package/build/angular/render/index.js +10 -29
- package/build/angular/render/index.js.map +1 -1
- package/build/angular/root-tag.d.ts +4 -0
- package/build/angular/root-tag.js +10 -0
- package/build/angular/root-tag.js.map +1 -0
- package/build/angular/services/color-scheme.service.d.ts +1 -1
- package/package.json +6 -6
- package/src/accessibility-inputs.ts +3 -0
- package/src/callback-host.ts +56 -8
- 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 +8 -0
- package/src/element-base.ts +17 -0
- package/src/element-props.ts +35 -33
- package/src/element-text-input-native.ts +31 -0
- package/src/elements-controls.ts +9 -1
- package/src/elements-layout.ts +27 -0
- package/src/elements-press.ts +10 -2
- package/src/elements.ts +3 -0
- package/src/index.ts +79 -22
- 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/primitives/index.ts +7 -0
- package/src/render/index.ts +23 -50
- package/src/root-tag.ts +14 -0
- package/src/services/color-scheme.service.ts +1 -1
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
inject,
|
|
13
13
|
} from '@angular/core';
|
|
14
14
|
import type {
|
|
15
|
+
IInnerViewRef,
|
|
15
16
|
IScrollViewHandle,
|
|
16
|
-
ISection,
|
|
17
17
|
IVirtualizedSectionListHandle,
|
|
18
18
|
} from '@symbiote-native/components';
|
|
19
19
|
import {
|
|
@@ -23,11 +23,11 @@ import {
|
|
|
23
23
|
type IViewStyle,
|
|
24
24
|
} from '@symbiote-native/engine';
|
|
25
25
|
import {
|
|
26
|
+
VListCellDirective,
|
|
26
27
|
VListEmptyDirective,
|
|
27
28
|
VListFooterDirective,
|
|
28
29
|
VListHeaderDirective,
|
|
29
30
|
VListSeparatorDirective,
|
|
30
|
-
type IVListSeparatorContext,
|
|
31
31
|
} from '../virtualized-list';
|
|
32
32
|
import { VListOutletDirective } from '../virtualized-list/directives';
|
|
33
33
|
import { LIST_ACCESSIBILITY_FORWARD } from '../virtualized-list/list-a11y-forward';
|
|
@@ -43,16 +43,11 @@ import {
|
|
|
43
43
|
VSectionItemDirective,
|
|
44
44
|
VSectionSeparatorDirective,
|
|
45
45
|
VirtualizedSectionList,
|
|
46
|
+
type ISection,
|
|
46
47
|
type IVirtualizedSectionListProps,
|
|
47
48
|
} from '../virtualized-section-list';
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
// template with no type argument to pin the item type. The narrowest cast for that gap
|
|
51
|
-
function asItem<ItemT>(value: unknown): ItemT | undefined {
|
|
52
|
-
return value as ItemT | undefined;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export type { ISection } from '@symbiote-native/components';
|
|
50
|
+
export type { ISection } from '../virtualized-section-list';
|
|
56
51
|
export type ISectionListHandle = IVirtualizedSectionListHandle;
|
|
57
52
|
|
|
58
53
|
// Re-exported so app code gets the whole `vSection*` and `vList*` authoring surface from here
|
|
@@ -124,20 +119,28 @@ export type ISectionListInputs<ItemT> = Omit<
|
|
|
124
119
|
[maxToRenderPerBatch]="maxToRenderPerBatch"
|
|
125
120
|
[updateCellsBatchingPeriod]="updateCellsBatchingPeriod"
|
|
126
121
|
[windowSize]="windowSize"
|
|
122
|
+
[disableVirtualization]="disableVirtualization"
|
|
127
123
|
[inverted]="inverted"
|
|
124
|
+
[horizontal]="horizontal"
|
|
128
125
|
[maintainVisibleContentPosition]="maintainVisibleContentPosition"
|
|
129
126
|
[onScroll]="onScroll"
|
|
130
127
|
[onScrollBeginDrag]="onScrollBeginDrag"
|
|
131
128
|
[onScrollEndDrag]="onScrollEndDrag"
|
|
132
129
|
[onMomentumScrollBegin]="onMomentumScrollBegin"
|
|
133
130
|
[onMomentumScrollEnd]="onMomentumScrollEnd"
|
|
131
|
+
[onContentSizeChange]="onContentSizeChange"
|
|
134
132
|
[scrollEventThrottle]="scrollEventThrottle"
|
|
135
133
|
[keyboardShouldPersistTaps]="keyboardShouldPersistTaps"
|
|
136
134
|
[keyboardDismissMode]="keyboardDismissMode"
|
|
137
135
|
[removeClippedSubviews]="removeClippedSubviews"
|
|
138
136
|
[nestedScrollEnabled]="nestedScrollEnabled"
|
|
137
|
+
[stickyHeaderHiddenOnScroll]="stickyHeaderHiddenOnScroll"
|
|
138
|
+
[innerViewRef]="innerViewRef"
|
|
139
139
|
[style]="resolvedStyle"
|
|
140
140
|
[contentContainerStyle]="contentContainerStyle"
|
|
141
|
+
[listHeaderComponentStyle]="listHeaderComponentStyle"
|
|
142
|
+
[listFooterComponentStyle]="listFooterComponentStyle"
|
|
143
|
+
[cellRendererTemplate]="cellDir?.templateRef"
|
|
141
144
|
[testID]="testID"
|
|
142
145
|
[nativeID]="nativeID"
|
|
143
146
|
${LIST_ACCESSIBILITY_FORWARD}
|
|
@@ -177,9 +180,10 @@ export type ISectionListInputs<ItemT> = Omit<
|
|
|
177
180
|
</ng-template>
|
|
178
181
|
}
|
|
179
182
|
@if (sectionSeparatorDir !== undefined) {
|
|
180
|
-
<ng-template vSectionSeparator>
|
|
183
|
+
<ng-template vSectionSeparator let-props="props">
|
|
181
184
|
<ng-container
|
|
182
185
|
[vListOutlet]="sectionSeparatorDir.templateRef"
|
|
186
|
+
[vListOutletContext]="props"
|
|
183
187
|
></ng-container>
|
|
184
188
|
</ng-template>
|
|
185
189
|
}
|
|
@@ -203,17 +207,10 @@ export type ISectionListInputs<ItemT> = Omit<
|
|
|
203
207
|
</ng-template>
|
|
204
208
|
}
|
|
205
209
|
@if (itemSeparatorDir !== undefined) {
|
|
206
|
-
<ng-template
|
|
207
|
-
vListSeparator
|
|
208
|
-
let-highlighted="highlighted"
|
|
209
|
-
let-leadingItem="leadingItem"
|
|
210
|
-
let-trailingItem="trailingItem"
|
|
211
|
-
>
|
|
210
|
+
<ng-template vListSeparator let-props="props">
|
|
212
211
|
<ng-container
|
|
213
212
|
[vListOutlet]="itemSeparatorDir.templateRef"
|
|
214
|
-
[vListOutletContext]="
|
|
215
|
-
itemSeparatorContext(highlighted, leadingItem, trailingItem)
|
|
216
|
-
"
|
|
213
|
+
[vListOutletContext]="props"
|
|
217
214
|
></ng-container>
|
|
218
215
|
</ng-template>
|
|
219
216
|
}
|
|
@@ -242,7 +239,9 @@ export class SectionList<ItemT = unknown>
|
|
|
242
239
|
@Input() maxToRenderPerBatch?: number;
|
|
243
240
|
@Input() updateCellsBatchingPeriod?: number;
|
|
244
241
|
@Input() windowSize?: number;
|
|
242
|
+
@Input() disableVirtualization?: boolean;
|
|
245
243
|
@Input() inverted?: boolean;
|
|
244
|
+
@Input() horizontal?: boolean;
|
|
246
245
|
@Input() maintainVisibleContentPosition?: {
|
|
247
246
|
minIndexForVisible: number;
|
|
248
247
|
autoscrollToTopThreshold?: number;
|
|
@@ -252,13 +251,18 @@ export class SectionList<ItemT = unknown>
|
|
|
252
251
|
@Input() onScrollEndDrag?: (event: ISymbioteEvent) => void;
|
|
253
252
|
@Input() onMomentumScrollBegin?: (event: ISymbioteEvent) => void;
|
|
254
253
|
@Input() onMomentumScrollEnd?: (event: ISymbioteEvent) => void;
|
|
254
|
+
@Input() onContentSizeChange?: (width: number, height: number) => void;
|
|
255
255
|
@Input() scrollEventThrottle?: number;
|
|
256
256
|
@Input() keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
257
257
|
@Input() keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
258
258
|
@Input() removeClippedSubviews?: boolean;
|
|
259
259
|
@Input() nestedScrollEnabled?: boolean;
|
|
260
|
+
@Input() stickyHeaderHiddenOnScroll?: boolean;
|
|
261
|
+
@Input() innerViewRef?: IInnerViewRef;
|
|
260
262
|
@Input() style?: IStyleProp<IViewStyle>;
|
|
261
263
|
@Input() contentContainerStyle?: IStyleProp<IViewStyle>;
|
|
264
|
+
@Input() listHeaderComponentStyle?: IStyleProp<IViewStyle>;
|
|
265
|
+
@Input() listFooterComponentStyle?: IStyleProp<IViewStyle>;
|
|
262
266
|
@Input() testID?: string;
|
|
263
267
|
@Input() nativeID?: string;
|
|
264
268
|
|
|
@@ -282,12 +286,13 @@ export class SectionList<ItemT = unknown>
|
|
|
282
286
|
@ContentChild(VSectionFooterDirective)
|
|
283
287
|
sectionFooterDir?: VSectionFooterDirective<ItemT>;
|
|
284
288
|
@ContentChild(VSectionSeparatorDirective)
|
|
285
|
-
sectionSeparatorDir?: VSectionSeparatorDirective
|
|
289
|
+
sectionSeparatorDir?: VSectionSeparatorDirective<ItemT>;
|
|
286
290
|
@ContentChild(VListHeaderDirective) listHeaderDir?: VListHeaderDirective;
|
|
287
291
|
@ContentChild(VListFooterDirective) listFooterDir?: VListFooterDirective;
|
|
288
292
|
@ContentChild(VListEmptyDirective) listEmptyDir?: VListEmptyDirective;
|
|
289
293
|
@ContentChild(VListSeparatorDirective)
|
|
290
294
|
itemSeparatorDir?: VListSeparatorDirective<ItemT>;
|
|
295
|
+
@ContentChild(VListCellDirective) cellDir?: VListCellDirective;
|
|
291
296
|
|
|
292
297
|
// The inner list, whose instance is the scroll handle, reads lazily
|
|
293
298
|
@ViewChild(VirtualizedSectionList)
|
|
@@ -296,22 +301,6 @@ export class SectionList<ItemT = unknown>
|
|
|
296
301
|
// This component's own host, the anchor `class="..."` resolves onto, not the inner list's
|
|
297
302
|
private readonly elementRef = inject(ElementRef);
|
|
298
303
|
|
|
299
|
-
// The leading and trailing items arrive `unknown` from the template's `let` bindings, already
|
|
300
|
-
// unwrapped to real items
|
|
301
|
-
itemSeparatorContext(
|
|
302
|
-
highlighted: unknown,
|
|
303
|
-
leadingItem: unknown,
|
|
304
|
-
trailingItem: unknown,
|
|
305
|
-
): IVListSeparatorContext<ItemT> {
|
|
306
|
-
const isHighlighted = highlighted === true;
|
|
307
|
-
return {
|
|
308
|
-
$implicit: isHighlighted,
|
|
309
|
-
highlighted: isHighlighted,
|
|
310
|
-
leadingItem: asItem<ItemT>(leadingItem),
|
|
311
|
-
trailingItem: asItem<ItemT>(trailingItem),
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
|
|
315
304
|
scrollToLocation(params: {
|
|
316
305
|
sectionIndex: number;
|
|
317
306
|
itemIndex: number;
|
|
@@ -326,7 +315,7 @@ export class SectionList<ItemT = unknown>
|
|
|
326
315
|
this.list?.flashScrollIndicators();
|
|
327
316
|
}
|
|
328
317
|
|
|
329
|
-
getNativeScrollRef():
|
|
318
|
+
getNativeScrollRef(): ISymbioteNode | null {
|
|
330
319
|
return this.list?.getNativeScrollRef() ?? null;
|
|
331
320
|
}
|
|
332
321
|
|
|
@@ -342,7 +331,15 @@ export class SectionList<ItemT = unknown>
|
|
|
342
331
|
return this.list?.getScrollNode() ?? null;
|
|
343
332
|
}
|
|
344
333
|
|
|
334
|
+
getScrollRef(): ISymbioteNode | null {
|
|
335
|
+
return this.list?.getScrollRef() ?? null;
|
|
336
|
+
}
|
|
337
|
+
|
|
345
338
|
recordInteraction(): void {
|
|
346
339
|
this.list?.recordInteraction();
|
|
347
340
|
}
|
|
341
|
+
|
|
342
|
+
setNativeProps(props: Record<string, unknown>): void {
|
|
343
|
+
this.list?.setNativeProps(props);
|
|
344
|
+
}
|
|
348
345
|
}
|
|
@@ -9,7 +9,11 @@
|
|
|
9
9
|
// <prop_types_split_agnostic_vs_per_adapter> describes. Mirrors React/Vue's ITouchableBaseProps.
|
|
10
10
|
|
|
11
11
|
import type { IPressTimingProps } from '@symbiote-native/components';
|
|
12
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
IColorValue,
|
|
14
|
+
IStyleProp,
|
|
15
|
+
IViewStyle,
|
|
16
|
+
} from '@symbiote-native/engine';
|
|
13
17
|
|
|
14
18
|
import type { IAngularPressableInputs } from './pressable-props';
|
|
15
19
|
|
|
@@ -24,7 +28,7 @@ export type IAngularTouchableOpacityProps = IAngularTouchableBaseProps & {
|
|
|
24
28
|
|
|
25
29
|
export type IAngularTouchableHighlightProps = IAngularTouchableBaseProps & {
|
|
26
30
|
activeOpacity?: number;
|
|
27
|
-
underlayColor?:
|
|
31
|
+
underlayColor?: IColorValue;
|
|
28
32
|
// RN's snapshot affordance (`Pressable.js:151`, `TouchableHighlight.js:61`): render the control in
|
|
29
33
|
// its pressed state with no gesture, so a test can capture it. Consumed by the engine and stripped
|
|
30
34
|
// before the payload — no ViewConfig declares it.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// The context a `vListCell` template reads for one cell: RN's `CellRendererComponent` props plus
|
|
2
|
+
// the template that stamps the item and its separator inside the wrapper the app draws
|
|
3
|
+
|
|
4
|
+
import type { TemplateRef } from '@angular/core';
|
|
5
|
+
import type { IViewStyle } from '@symbiote-native/engine';
|
|
6
|
+
import type { IWindowCell } from './cell-registry';
|
|
7
|
+
import type { IVListCellContext } from './directives';
|
|
8
|
+
|
|
9
|
+
export type ICellRendererArgs<ItemT> = {
|
|
10
|
+
cell: IWindowCell<ItemT>;
|
|
11
|
+
style: IViewStyle | undefined;
|
|
12
|
+
// The list's own template holding the cell's item and separator outlets
|
|
13
|
+
body: TemplateRef<unknown> | undefined;
|
|
14
|
+
layout: (
|
|
15
|
+
measure: IWindowCell<ItemT>['measure'],
|
|
16
|
+
event: unknown,
|
|
17
|
+
index: number,
|
|
18
|
+
) => void;
|
|
19
|
+
focus: (index: number) => void;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function buildCellRendererContext<ItemT>(
|
|
23
|
+
args: ICellRendererArgs<ItemT>,
|
|
24
|
+
): IVListCellContext {
|
|
25
|
+
const { cell, style, body, layout, focus } = args;
|
|
26
|
+
return {
|
|
27
|
+
$implicit: cell.context.$implicit,
|
|
28
|
+
cellKey: cell.key,
|
|
29
|
+
index: cell.index,
|
|
30
|
+
style,
|
|
31
|
+
layout: event => layout(cell.measure, event, cell.index),
|
|
32
|
+
focus: () => focus(cell.index),
|
|
33
|
+
content: body,
|
|
34
|
+
contentContext: { $implicit: cell },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -30,36 +30,60 @@ import {
|
|
|
30
30
|
TemplateRef,
|
|
31
31
|
ViewContainerRef,
|
|
32
32
|
inject,
|
|
33
|
+
reflectComponentType,
|
|
34
|
+
type ComponentRef,
|
|
33
35
|
type EmbeddedViewRef,
|
|
34
36
|
type OnChanges,
|
|
35
37
|
type OnDestroy,
|
|
36
38
|
type SimpleChanges,
|
|
39
|
+
type Type,
|
|
37
40
|
} from '@angular/core';
|
|
38
|
-
import { dlog, isDebug } from '@symbiote-native/engine';
|
|
41
|
+
import { dlog, isDebug, type IViewStyle } from '@symbiote-native/engine';
|
|
39
42
|
import { countAngular } from '../../diagnostics';
|
|
40
43
|
import type { ISeparators } from '@symbiote-native/components';
|
|
41
44
|
|
|
42
45
|
let vListOutletInstanceCounter = 0;
|
|
43
46
|
|
|
47
|
+
function nextOutletInstanceId(): number {
|
|
48
|
+
vListOutletInstanceCounter += 1;
|
|
49
|
+
return vListOutletInstanceCounter;
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
// The context a `vListItem` template receives, mirroring RN's renderItem info arg
|
|
45
53
|
// ({ item, index, separators }). `$implicit` is the item, so `let-item` (no key) binds it.
|
|
46
|
-
export
|
|
54
|
+
export type IVListItemContext<ItemT> = {
|
|
47
55
|
$implicit: ItemT;
|
|
48
56
|
index: number;
|
|
49
57
|
separators: ISeparators;
|
|
50
|
-
}
|
|
58
|
+
};
|
|
51
59
|
|
|
52
60
|
// The context a `vListSeparator` template receives, mirroring RN's ItemSeparatorComponent props
|
|
53
61
|
// (the highlight flag the cell toggles + the items flanking the gap). `$implicit` is the highlight
|
|
54
62
|
// flag, so `let-highlighted` binds it.
|
|
55
|
-
export
|
|
63
|
+
export type IVListSeparatorContext<ItemT> = {
|
|
56
64
|
$implicit: boolean;
|
|
57
65
|
highlighted: boolean;
|
|
58
66
|
leadingItem?: ItemT;
|
|
59
67
|
trailingItem?: ItemT;
|
|
60
68
|
// RN lets a row drive arbitrary separator props via separators.updateProps; they ride here.
|
|
61
69
|
[key: string]: unknown;
|
|
62
|
-
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// The context a `vListCell` template receives, RN's `CellRendererComponent` props
|
|
73
|
+
// The template draws the wrapper and stamps the item and its separator through `content`
|
|
74
|
+
// The item is `unknown`, a wrapping list hands it an entry or a row, not its own item type
|
|
75
|
+
export type IVListCellContext = {
|
|
76
|
+
$implicit: unknown;
|
|
77
|
+
cellKey: string;
|
|
78
|
+
index: number;
|
|
79
|
+
style: IViewStyle | undefined;
|
|
80
|
+
// Wire both onto the wrapper: `(layout)="cell.layout($event)"`, `(focus)="cell.focus()"`
|
|
81
|
+
layout: (event: unknown) => void;
|
|
82
|
+
focus: () => void;
|
|
83
|
+
// Stamp it with `[vListOutlet]="cell.content" [vListOutletContext]="cell.contentContext"`
|
|
84
|
+
content: TemplateRef<unknown> | undefined;
|
|
85
|
+
contentContext: unknown;
|
|
86
|
+
};
|
|
63
87
|
|
|
64
88
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
65
89
|
return typeof value === 'object' && value !== null;
|
|
@@ -114,6 +138,20 @@ export class VListSeparatorDirective<ItemT = unknown> {
|
|
|
114
138
|
}
|
|
115
139
|
}
|
|
116
140
|
|
|
141
|
+
// `<ng-template vListCell>` replaces the view around each cell (RN CellRendererComponent)
|
|
142
|
+
// It must wire `layout` and `focus` itself, as RN's custom cell must wire `onLayout`
|
|
143
|
+
@Directive({ selector: '[vListCell]', standalone: true })
|
|
144
|
+
export class VListCellDirective {
|
|
145
|
+
readonly templateRef = inject<TemplateRef<IVListCellContext>>(TemplateRef);
|
|
146
|
+
|
|
147
|
+
static ngTemplateContextGuard(
|
|
148
|
+
_dir: VListCellDirective,
|
|
149
|
+
_ctx: unknown,
|
|
150
|
+
): _ctx is IVListCellContext {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
117
155
|
// Core-only NgTemplateOutlet twin. The adapter cannot import @angular/common's NgTemplateOutlet
|
|
118
156
|
// (not a dependency), so the list stamps templates through this: it creates the embedded view when
|
|
119
157
|
// the template changes and updates the live view's context IN PLACE on a context change, so a
|
|
@@ -122,19 +160,32 @@ export class VListSeparatorDirective<ItemT = unknown> {
|
|
|
122
160
|
export class VListOutletDirective<C = unknown> implements OnChanges, OnDestroy {
|
|
123
161
|
@Input({ alias: 'vListOutlet' }) templateRef?: TemplateRef<C>;
|
|
124
162
|
@Input({ alias: 'vListOutletContext' }) context?: C;
|
|
163
|
+
// RN's `ListItemComponent`: stamped instead of the template, its inputs are the item context
|
|
164
|
+
@Input({ alias: 'vListOutletComponent' }) component?: Type<unknown>;
|
|
125
165
|
|
|
126
166
|
private viewRef: EmbeddedViewRef<C> | null = null;
|
|
167
|
+
private componentRef: ComponentRef<unknown> | null = null;
|
|
127
168
|
private readonly viewContainer = inject(ViewContainerRef);
|
|
128
|
-
private readonly instanceId = (
|
|
169
|
+
private readonly instanceId = nextOutletInstanceId();
|
|
129
170
|
|
|
130
171
|
ngOnChanges(changes: SimpleChanges): void {
|
|
131
|
-
if (
|
|
172
|
+
if (
|
|
173
|
+
changes['templateRef'] !== undefined ||
|
|
174
|
+
changes['component'] !== undefined
|
|
175
|
+
) {
|
|
132
176
|
if (isDebug())
|
|
133
177
|
dlog(
|
|
134
|
-
`Angular VListOutlet#${this.instanceId} templateRef CHANGED (was=${changes['templateRef']
|
|
178
|
+
`Angular VListOutlet#${this.instanceId} templateRef CHANGED (was=${changes['templateRef']?.previousValue !== undefined} now=${this.templateRef !== undefined}) -> clear + recreate`,
|
|
135
179
|
);
|
|
136
180
|
this.viewContainer.clear();
|
|
137
181
|
countAngular('outletCreates');
|
|
182
|
+
this.componentRef = null;
|
|
183
|
+
this.viewRef = null;
|
|
184
|
+
if (this.component !== undefined) {
|
|
185
|
+
this.componentRef = this.viewContainer.createComponent(this.component);
|
|
186
|
+
this.writeComponentInputs(this.componentRef);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
138
189
|
this.viewRef =
|
|
139
190
|
this.templateRef === undefined
|
|
140
191
|
? null
|
|
@@ -144,6 +195,11 @@ export class VListOutletDirective<C = unknown> implements OnChanges, OnDestroy {
|
|
|
144
195
|
);
|
|
145
196
|
return;
|
|
146
197
|
}
|
|
198
|
+
if (this.componentRef !== null) {
|
|
199
|
+
countAngular('outletUpdates');
|
|
200
|
+
this.writeComponentInputs(this.componentRef);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
147
203
|
if (this.viewRef !== null && this.context !== undefined) {
|
|
148
204
|
countAngular('outletUpdates');
|
|
149
205
|
if (isDebug())
|
|
@@ -161,6 +217,26 @@ export class VListOutletDirective<C = unknown> implements OnChanges, OnDestroy {
|
|
|
161
217
|
this.viewContainer.clear();
|
|
162
218
|
}
|
|
163
219
|
|
|
220
|
+
// The item context becomes the component's inputs, only those it declares: RN hands a
|
|
221
|
+
// `ListItemComponent` item, index and separators, and one may not read all three
|
|
222
|
+
private writeComponentInputs(ref: ComponentRef<unknown>): void {
|
|
223
|
+
const { context } = this;
|
|
224
|
+
if (!isRecord(context)) return;
|
|
225
|
+
const declared = new Set(
|
|
226
|
+
reflectComponentType(ref.componentType)?.inputs.map(
|
|
227
|
+
input => input.propName,
|
|
228
|
+
),
|
|
229
|
+
);
|
|
230
|
+
const inputs = {
|
|
231
|
+
item: context['$implicit'],
|
|
232
|
+
index: context['index'],
|
|
233
|
+
separators: context['separators'],
|
|
234
|
+
};
|
|
235
|
+
for (const [name, value] of Object.entries(inputs)) {
|
|
236
|
+
if (declared.has(name)) ref.setInput(name, value);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
164
240
|
// Copy the new context's fields onto the live embedded view's context object (whose identity the
|
|
165
241
|
// consumer's `let-` bindings already read), dropping keys that disappeared. The generic `C` can't
|
|
166
242
|
// be index-WRITTEN even once narrowed (TS2862), so the copy runs in a non-generic helper the
|