@nstudio/ui-collectionview 5.1.9-alpha.4 → 5.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/angular/collectionview.component.d.ts +8 -33
  2. package/angular/{fesm2020 → fesm2022}/nstudio-ui-collectionview-angular.mjs +58 -151
  3. package/angular/fesm2022/nstudio-ui-collectionview-angular.mjs.map +1 -0
  4. package/angular/index.d.ts +2 -2
  5. package/angular/package.json +2 -10
  6. package/common.d.ts +28 -66
  7. package/common.js +96 -138
  8. package/common.js.map +1 -1
  9. package/index.android.d.ts +38 -19
  10. package/index.android.js +448 -158
  11. package/index.android.js.map +1 -1
  12. package/index.d.ts +49 -16
  13. package/index.ios.d.ts +83 -28
  14. package/index.ios.js +589 -375
  15. package/index.ios.js.map +1 -1
  16. package/package.json +5 -2
  17. package/react/index.d.ts +1 -1
  18. package/react/index.js.map +1 -1
  19. package/svelte/index.d.ts +0 -1
  20. package/svelte/index.js +11 -7
  21. package/svelte/index.js.map +1 -1
  22. package/vue3/component.d.ts +36 -0
  23. package/vue3/component.js +98 -0
  24. package/vue3/component.js.map +1 -0
  25. package/vue3/index.d.ts +11 -0
  26. package/vue3/index.js +14 -0
  27. package/vue3/index.js.map +1 -0
  28. package/angular/esm2020/collectionview.component.mjs +0 -497
  29. package/angular/esm2020/index.mjs +0 -19
  30. package/angular/esm2020/nstudio-ui-collectionview-angular.mjs +0 -5
  31. package/angular/fesm2015/nstudio-ui-collectionview-angular.mjs +0 -528
  32. package/angular/fesm2015/nstudio-ui-collectionview-angular.mjs.map +0 -1
  33. package/angular/fesm2020/nstudio-ui-collectionview-angular.mjs.map +0 -1
  34. package/vue/component.d.ts +0 -38
  35. package/vue/component.js +0 -104
  36. package/vue/component.js.map +0 -1
  37. package/vue/index.d.ts +0 -4
  38. package/vue/index.js +0 -12
  39. package/vue/index.js.map +0 -1
package/index.ios.js CHANGED
@@ -1,5 +1,6 @@
1
- import { ChangeType, ContentView, Observable, Property, ProxyViewContainer, Trace, Utils, View, paddingBottomProperty, paddingLeftProperty, paddingRightProperty, paddingTopProperty, profile } from '@nativescript/core';
2
- import { CLog, CLogTypes, CollectionViewBase, ViewTemplateType, isBounceEnabledProperty, isScrollEnabledProperty, itemTemplatesProperty, orientationProperty, reorderLongPressEnabledProperty, reorderingEnabledProperty, reverseLayoutProperty, scrollBarIndicatorVisibleProperty, getUUID } from './common';
1
+ import { ChangeType, ContentView, Length, Observable, Property, ProxyViewContainer, Trace, Utils, View, booleanConverter, paddingBottomProperty, paddingLeftProperty, paddingRightProperty, paddingTopProperty, profile } from '@nativescript/core';
2
+ import { reorderLongPressEnabledProperty, reorderingEnabledProperty, reverseLayoutProperty, scrollBarIndicatorVisibleProperty } from '.';
3
+ import { CLog, CLogTypes, CollectionViewBase, ListViewViewTypes, isBounceEnabledProperty, isScrollEnabledProperty, itemTemplatesProperty, orientationProperty } from './common';
3
4
  export * from './common';
4
5
  const infinity = Utils.layout.makeMeasureSpec(0, Utils.layout.UNSPECIFIED);
5
6
  export var ContentInsetAdjustmentBehavior;
@@ -32,18 +33,37 @@ export const contentInsetAdjustmentBehaviorProperty = new Property({
32
33
  valueConverter: parseContentInsetAdjustmentBehavior,
33
34
  defaultValue: ContentInsetAdjustmentBehavior.Automatic
34
35
  });
36
+ export const estimatedItemSizeProperty = new Property({
37
+ name: 'estimatedItemSize',
38
+ defaultValue: true,
39
+ valueConverter: booleanConverter
40
+ });
41
+ export const autoSizeProperty = new Property({
42
+ name: 'autoSize',
43
+ defaultValue: false,
44
+ valueConverter: booleanConverter
45
+ });
46
+ export var SnapPosition;
47
+ (function (SnapPosition) {
48
+ SnapPosition[SnapPosition["START"] = -1] = "START";
49
+ SnapPosition[SnapPosition["END"] = 1] = "END"; // = androidx.recyclerview.widget.LinearSmoothScroller.SNAP_TO_END
50
+ })(SnapPosition || (SnapPosition = {}));
35
51
  export class CollectionView extends CollectionViewBase {
52
+ // dragDelegate: UICollectionViewDragDelegateImpl;
53
+ // dropDelegate: UICollectionViewDropDelegateImpl;
36
54
  constructor() {
37
55
  super();
38
56
  this._preparingCell = false;
57
+ this.autoSize = false;
39
58
  this.reorderStartingRow = -1;
40
59
  this.reorderEndingRow = -1;
41
60
  this.manualDragging = false;
42
61
  this.scrollEnabledBeforeDragging = true;
43
- this.cellRegistrations = {};
62
+ this.estimatedItemSize = true;
44
63
  this.needsScrollStartEvent = false;
45
64
  this.isScrolling = false;
46
65
  this._map = new Map();
66
+ // this._sizes = new Array<number[]>();
47
67
  }
48
68
  createNativeView() {
49
69
  let layout;
@@ -51,28 +71,37 @@ export class CollectionView extends CollectionViewBase {
51
71
  layout = this._layout = CollectionViewBase.layoutStyles[this.layoutStyle].createLayout(this);
52
72
  }
53
73
  else {
54
- layout = this._layout = UICollectionViewFlowLayout.alloc().init();
74
+ layout = this._layout = UICollectionViewFlowLayoutImpl.initWithOwner(this);
75
+ // layout = this._layout = UICollectionViewFlowLayout.new();
55
76
  }
56
77
  if (layout instanceof UICollectionViewFlowLayout) {
57
78
  layout.minimumLineSpacing = 0;
58
79
  layout.minimumInteritemSpacing = 0;
59
80
  }
60
- const view = UICollectionView.alloc().initWithFrameCollectionViewLayout(CGRectMake(0, 0, 0, 0), layout);
81
+ // const view = UICollectionViewImpl.initWithFrameCollectionViewLayout(CGRectMake(0, 0, 0, 0), layout) as UICollectionViewImpl;
82
+ const view = UICollectionViewImpl.initWithOwner(this, layout);
61
83
  view.backgroundColor = UIColor.clearColor;
84
+ this._itemTemplatesInternal.forEach((t) => {
85
+ view.registerClassForCellWithReuseIdentifier(CollectionViewCell.class(), t.key.toLowerCase());
86
+ });
62
87
  view.autoresizesSubviews = false;
63
88
  view.autoresizingMask = 0 /* UIViewAutoresizing.None */;
64
89
  this.lastContentOffset = view.contentOffset;
65
90
  return view;
66
91
  }
67
- // onTemplateAdded(t) {
68
- // super.onTemplateAdded(t);
69
- // if (this.nativeViewProtected) {
70
- // // this.nativeViewProtected.registerClassForCellWithReuseIdentifier(CollectionViewCell.class(), t.key.toLowerCase());
71
- // }
72
- // }
92
+ onTemplateAdded(t) {
93
+ super.onTemplateAdded(t);
94
+ if (this.nativeViewProtected) {
95
+ this.nativeViewProtected.registerClassForCellWithReuseIdentifier(CollectionViewCell.class(), t.key.toLowerCase());
96
+ }
97
+ }
73
98
  initNativeView() {
74
99
  super.initNativeView();
75
- this.setupDataSource();
100
+ const nativeView = this.nativeViewProtected;
101
+ this._dataSource = CollectionViewDataSource.initWithOwner(this);
102
+ nativeView.dataSource = this._dataSource;
103
+ // this.dragDelegate = nativeView.dragDelegate = UICollectionViewDragDelegateImpl.initWithOwner(this);
104
+ // this.dropDelegate = nativeView.dropDelegate = UICollectionViewDropDelegateImpl.initWithOwner(this);
76
105
  // delegate will be set in first onLayout because we need computed _effectiveColWidth and _effectiveRowHeight
77
106
  this._measureCellMap = new Map();
78
107
  // waterfall requires the delegate to be set as soon as possible
@@ -83,139 +112,20 @@ export class CollectionView extends CollectionViewBase {
83
112
  this._delegate = layoutStyle.createDelegate(this);
84
113
  this.nativeViewProtected.delegate = this._delegate;
85
114
  }
86
- this._setNativeClipToBounds();
87
- }
88
- setupDataSource() {
89
- // Important: cell's must be registered before creating the datasource
90
- // eg: they can *not* be created within the initWithCollectionViewCellProvider
91
- const templateKeys = this._itemTemplatesInternal.keys();
92
- for (const key of templateKeys) {
93
- // register cell for each template type
94
- this.cellRegistrations[key] = UICollectionViewCellRegistration.registrationWithCellClassConfigurationHandler(CollectionViewCell.class(), (view, indexPath, identifier) => {
95
- const templateType = this._getItemTemplateType(indexPath);
96
- // console.log('registrationWithCellClassConfigurationHandler templateType:', templateType)
97
- const cell = view;
98
- const firstRender = !cell.view;
99
- if (Trace.isEnabled()) {
100
- CLog(CLogTypes.log, 'cellProvider for row:', indexPath.row, ' templateType:', templateType);
101
- }
102
- this._prepareCell(cell, indexPath, templateType);
103
- // the cell layout will be called from NSCellView layoutSubviews
104
- const cellView = cell.view;
105
- if (!firstRender && cellView['isLayoutRequired']) {
106
- this.layoutCell(indexPath.row, cell, cellView);
107
- }
108
- return cell;
109
- });
110
- }
111
- this._dataSource = UICollectionViewDiffableDataSource.alloc().initWithCollectionViewCellProvider(this.nativeView, (view, indexPath, identifier) => {
112
- return this.nativeViewProtected.dequeueConfiguredReusableCellWithRegistrationForIndexPathItem(this.cellRegistrations[this._getItemTemplateType(indexPath)], indexPath, identifier);
113
- });
114
- this.setupHeaderFooter();
115
- if (!this.sections) {
116
- // every collectionview must have at least 1 section
117
- this.sections = [{
118
- identifier: getUUID(),
119
- key: 'default'
120
- }];
121
- }
122
- if (this.items?.length) {
123
- this.refreshDataSourceSnapshot(this.getDefaultSectionIdentifier());
124
- }
125
- this.nativeView.dataSource = this._dataSource;
126
- }
127
- refreshDataSourceSnapshot(sectionIdentifier) {
128
- if (this.items) {
129
- this.modifyDataSourceSnapshot(ChangeType.Add, [], sectionIdentifier, false, true);
130
- }
131
- }
132
- modifyDataSourceSnapshot(type, identifiers, sectionIdentifier, animate = true, reload = false) {
133
- if (this.items) {
134
- if (!this._dataSourceSnapshot || reload) {
135
- this._dataSourceSnapshot = NSDiffableDataSourceSnapshot.alloc().init();
136
- this._dataSourceSnapshot.appendSectionsWithIdentifiers(this.sections.map(s => s.identifier));
137
- }
138
- else {
139
- this._dataSourceSnapshot = this._dataSource.snapshot();
140
- }
141
- if (Trace.isEnabled()) {
142
- CLog(CLogTypes.info, 'modifyDataSourceSnapshot identifiers: ', type, identifiers);
143
- }
144
- // console.log('modifyDataSourceSnapshot identifiers: ', type, identifiers);
145
- switch (type) {
146
- case ChangeType.Add:
147
- const itemIdentifiers = [];
148
- if (reload) {
149
- this.items.forEach(() => {
150
- // forEach works well with ObservableArray and Array
151
- itemIdentifiers.push(getUUID());
152
- });
153
- }
154
- if (identifiers.length) {
155
- itemIdentifiers.push(...identifiers);
156
- }
157
- if (sectionIdentifier) {
158
- this._dataSourceSnapshot.appendItemsWithIdentifiersIntoSectionWithIdentifier(itemIdentifiers, sectionIdentifier);
159
- }
160
- else {
161
- this._dataSourceSnapshot.appendItemsWithIdentifiers(itemIdentifiers);
162
- }
163
- break;
164
- case ChangeType.Update:
165
- this._dataSourceSnapshot.reloadItemsWithIdentifiers(identifiers);
166
- break;
167
- case ChangeType.Delete:
168
- this._dataSourceSnapshot.deleteItemsWithIdentifiers(identifiers);
169
- break;
170
- }
171
- if (this.isAnimationEnabled) {
172
- this._dataSource.applySnapshotAnimatingDifferences(this._dataSourceSnapshot, this.loadingMore ? false : animate);
173
- }
174
- else {
175
- this._dataSource.applySnapshotUsingReloadData(this._dataSourceSnapshot);
176
- }
177
- }
178
- }
179
- getDefaultSectionIdentifier() {
180
- // each collectionview must have at least 1 section
181
- return this.sections[0].identifier;
182
- }
183
- setupHeaderFooter() {
184
- if (!this.headerKey) {
185
- // TODO: work on keyed header for multiple sections
186
- this.headerKey = ViewTemplateType.Header;
187
- }
188
- if (this.headerItemTemplate) {
189
- this.headerRegistration = UICollectionViewSupplementaryRegistration.registrationWithSupplementaryClassElementKindConfigurationHandler(CollectionViewCell.class(), this.headerKey, (cell, elementKind, indexPath) => {
190
- this._prepareHeaderFooter(cell, indexPath, this.headerKey, ViewTemplateType.Header);
191
- });
192
- }
193
- if (!this.footerKey) {
194
- // TODO: work on keyed footer for multiple sections
195
- this.footerKey = ViewTemplateType.Footer;
196
- }
197
- if (this.footerItemTemplate) {
198
- this.footerRegistration = UICollectionViewSupplementaryRegistration.registrationWithSupplementaryClassElementKindConfigurationHandler(CollectionViewCell.class(), this.footerKey, (cell, elementKind, indexPath) => {
199
- this._prepareHeaderFooter(cell, indexPath, this.footerKey, ViewTemplateType.Footer);
200
- });
201
- }
202
- if (this.headerItemTemplate || this.footerItemTemplate) {
203
- this._dataSource.supplementaryViewProvider = (view, elementKind, indexPath) => {
204
- if (this.headerRegistration && elementKind == this.headerKey) {
205
- return this.nativeViewProtected.dequeueConfiguredReusableSupplementaryViewWithRegistrationForIndexPath(this.headerRegistration, indexPath);
206
- }
207
- else if (this.footerRegistration) {
208
- return this.nativeViewProtected.dequeueConfiguredReusableSupplementaryViewWithRegistrationForIndexPath(this.footerRegistration, indexPath);
209
- }
210
- };
115
+ else if (this.autoSize) {
116
+ this._delegate = UICollectionViewDelegateImpl.initWithOwner(this);
117
+ this.nativeViewProtected.delegate = this._delegate;
211
118
  }
119
+ this._setNativeClipToBounds();
212
120
  }
213
121
  disposeNativeView() {
214
122
  if (Trace.isEnabled()) {
215
123
  CLog(CLogTypes.log, 'disposeNativeView');
216
124
  }
217
- const nativeView = this.nativeView;
125
+ const nativeView = this.nativeViewProtected;
218
126
  nativeView.delegate = null;
127
+ // nativeView.dragDelegate = null;
128
+ // nativeView.dropDelegate = null;
219
129
  this._delegate = null;
220
130
  nativeView.dataSource = null;
221
131
  this._dataSource = null;
@@ -232,6 +142,13 @@ export class CollectionView extends CollectionViewBase {
232
142
  get _childrenCount() {
233
143
  return this._map.size;
234
144
  }
145
+ onLoaded() {
146
+ super.onLoaded();
147
+ // we need refreshVisibleItems
148
+ // if some items were updated while unloaded they wont re layout
149
+ // after this (because we are not a Layout view)
150
+ this.refreshVisibleItems();
151
+ }
235
152
  eachChild(callback) {
236
153
  // used for css updates (like theme change)
237
154
  this._map.forEach((view) => {
@@ -245,12 +162,45 @@ export class CollectionView extends CollectionViewBase {
245
162
  }
246
163
  }
247
164
  });
165
+ // we need to call on measure cells too
166
+ // otherwise they would not get notified of some css changes
167
+ // like fontScale change
168
+ this._measureCellMap?.forEach((view) => {
169
+ callback(view.view);
170
+ });
171
+ }
172
+ async eachChildAsync(callback) {
173
+ // used for css updates (like theme change)
174
+ const children = [...this._map.values()];
175
+ for (let index = 0; index < children.length; index++) {
176
+ const view = children[index];
177
+ if (view.parent instanceof CollectionView) {
178
+ await callback(view);
179
+ }
180
+ else {
181
+ // in some cases (like item is unloaded from another place (like angular) view.parent becomes undefined)
182
+ if (view.parent) {
183
+ await callback(view.parent);
184
+ }
185
+ }
186
+ }
248
187
  }
249
188
  getViewForItemAtIndex(index) {
250
189
  let result;
251
190
  if (this.nativeViewProtected) {
191
+ // when the collectionview is not loaded anymore, cellForItemAtIndexPath wont return
192
+ // then we use our cached map to get the view
252
193
  const cell = this.nativeViewProtected.cellForItemAtIndexPath(NSIndexPath.indexPathForRowInSection(index, 0));
253
- return cell?.view;
194
+ if (cell) {
195
+ return cell?.view;
196
+ }
197
+ else {
198
+ for (const [cell, view] of this._map) {
199
+ if (cell.currentIndex === index) {
200
+ return view;
201
+ }
202
+ }
203
+ }
254
204
  }
255
205
  return result;
256
206
  }
@@ -319,13 +269,29 @@ export class CollectionView extends CollectionViewBase {
319
269
  return;
320
270
  }
321
271
  switch (gesture.state) {
322
- case 1 /* UIGestureRecognizerState.Began */:
323
- const selectedIndexPath = collectionView.indexPathForItemAtPoint(gesture.locationInView(collectionView));
272
+ case 1 /* UIGestureRecognizerState.Began */: {
273
+ let point = gesture.locationInView(collectionView);
274
+ const selectedIndexPath = collectionView.indexPathForItemAtPoint(point);
275
+ const view = this.getViewForItemAtIndex(selectedIndexPath.row);
276
+ if (view) {
277
+ const size = view.nativeViewProtected.bounds.size;
278
+ point = gesture.locationInView(view.nativeViewProtected);
279
+ this.draggingStartDelta = [point.x - size.width / 2, point.y - size.height / 2];
280
+ }
324
281
  collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath);
325
282
  break;
326
- case 2 /* UIGestureRecognizerState.Changed */:
327
- collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(collectionView));
283
+ }
284
+ case 2 /* UIGestureRecognizerState.Changed */: {
285
+ const point = gesture.locationInView(collectionView);
286
+ let x = point.x;
287
+ let y = point.y;
288
+ if (this.draggingStartDelta) {
289
+ x -= this.draggingStartDelta[0];
290
+ y -= this.draggingStartDelta[1];
291
+ }
292
+ collectionView.updateInteractiveMovementTargetPosition(CGPointMake(x, y));
328
293
  break;
294
+ }
329
295
  case 3 /* UIGestureRecognizerState.Ended */:
330
296
  collectionView.endInteractiveMovement();
331
297
  this.handleReorderEnd();
@@ -336,21 +302,27 @@ export class CollectionView extends CollectionViewBase {
336
302
  break;
337
303
  }
338
304
  }
305
+ // @ts-ignore
339
306
  [contentInsetAdjustmentBehaviorProperty.setNative](value) {
340
307
  this.nativeViewProtected.contentInsetAdjustmentBehavior = value;
341
308
  }
309
+ // @ts-ignore
342
310
  [paddingTopProperty.setNative](value) {
343
311
  this._setPadding({ top: Utils.layout.toDeviceIndependentPixels(this.effectivePaddingTop) });
344
312
  }
313
+ // @ts-ignore
345
314
  [paddingRightProperty.setNative](value) {
346
315
  this._setPadding({ right: Utils.layout.toDeviceIndependentPixels(this.effectivePaddingRight) });
347
316
  }
317
+ // @ts-ignore
348
318
  [paddingBottomProperty.setNative](value) {
349
319
  this._setPadding({ bottom: Utils.layout.toDeviceIndependentPixels(this.effectivePaddingBottom) });
350
320
  }
321
+ // @ts-ignore
351
322
  [paddingLeftProperty.setNative](value) {
352
323
  this._setPadding({ left: Utils.layout.toDeviceIndependentPixels(this.effectivePaddingLeft) });
353
324
  }
325
+ // @ts-ignore
354
326
  [orientationProperty.setNative](value) {
355
327
  const layout = this._layout;
356
328
  if (layout instanceof UICollectionViewFlowLayout) {
@@ -363,20 +335,25 @@ export class CollectionView extends CollectionViewBase {
363
335
  }
364
336
  this.updateScrollBarVisibility(this.scrollBarIndicatorVisible);
365
337
  }
338
+ // @ts-ignore
366
339
  [isScrollEnabledProperty.setNative](value) {
367
340
  this.nativeViewProtected.scrollEnabled = value;
368
341
  this.scrollEnabledBeforeDragging = value;
369
342
  }
343
+ // @ts-ignore
370
344
  [isBounceEnabledProperty.setNative](value) {
371
345
  this.nativeViewProtected.bounces = value;
372
346
  // this.nativeViewProtected.alwaysBounceHorizontal = value;
373
347
  }
348
+ // @ts-ignore
374
349
  [itemTemplatesProperty.getDefault]() {
375
350
  return null;
376
351
  }
352
+ // @ts-ignore
377
353
  [reverseLayoutProperty.setNative](value) {
378
354
  this.nativeViewProtected.transform = value ? CGAffineTransformMakeRotation(-Math.PI) : null;
379
355
  }
356
+ // @ts-ignore
380
357
  [reorderLongPressEnabledProperty.setNative](value) {
381
358
  if (value) {
382
359
  if (!this.reorderLongPressGesture) {
@@ -394,6 +371,7 @@ export class CollectionView extends CollectionViewBase {
394
371
  }
395
372
  }
396
373
  }
374
+ // @ts-ignore
397
375
  [reorderingEnabledProperty.setNative](value) {
398
376
  if (value) {
399
377
  this.on('touch', this.onReorderingTouch, this);
@@ -402,9 +380,11 @@ export class CollectionView extends CollectionViewBase {
402
380
  this.off('touch', this.onReorderingTouch, this);
403
381
  }
404
382
  }
383
+ // @ts-ignore
405
384
  [scrollBarIndicatorVisibleProperty.getDefault]() {
406
385
  return true;
407
386
  }
387
+ // @ts-ignore
408
388
  [scrollBarIndicatorVisibleProperty.setNative](value) {
409
389
  this.updateScrollBarVisibility(value);
410
390
  }
@@ -426,6 +406,10 @@ export class CollectionView extends CollectionViewBase {
426
406
  }
427
407
  onLayout(left, top, right, bottom) {
428
408
  super.onLayout(left, top, right, bottom);
409
+ const layoutView = this.nativeViewProtected?.collectionViewLayout;
410
+ if (!layoutView) {
411
+ return;
412
+ }
429
413
  const p = CollectionViewBase.plugins[this.layoutStyle];
430
414
  if (p && p.onLayout) {
431
415
  p.onLayout(this, left, top, right, bottom);
@@ -434,10 +418,6 @@ export class CollectionView extends CollectionViewBase {
434
418
  const p = CollectionViewBase.plugins[k];
435
419
  p.onLayout && p.onLayout(this, left, top, right, bottom);
436
420
  });
437
- const layoutView = this.nativeViewProtected.collectionViewLayout;
438
- if (!layoutView) {
439
- return;
440
- }
441
421
  if (!this._delegate) {
442
422
  const layoutStyle = CollectionViewBase.layoutStyles[this.layoutStyle];
443
423
  if (layoutStyle && layoutStyle.createDelegate) {
@@ -457,25 +437,66 @@ export class CollectionView extends CollectionViewBase {
457
437
  // this._delegate._owner = new WeakRef(this);
458
438
  this.nativeViewProtected.delegate = this._delegate;
459
439
  }
440
+ this.updateRowColSize();
441
+ // there is no need to call refresh if it was triggered before with same size.
442
+ // this refresh is just to handle size change
443
+ const layoutKey = this._innerWidth + '_' + this._innerHeight;
444
+ if (this._lastLayoutKey !== layoutKey) {
445
+ this.refresh();
446
+ }
447
+ }
448
+ updateRowColSize() {
449
+ const layoutView = this.nativeViewProtected?.collectionViewLayout;
460
450
  if (layoutView instanceof UICollectionViewFlowLayout) {
461
451
  if (this._effectiveRowHeight && this._effectiveColWidth) {
462
452
  layoutView.itemSize = CGSizeMake(Utils.layout.toDeviceIndependentPixels(this._effectiveColWidth), Utils.layout.toDeviceIndependentPixels(this._effectiveRowHeight));
463
453
  }
464
- else {
454
+ else if (this.estimatedItemSize && !this.autoSize) {
465
455
  layoutView.estimatedItemSize = CGSizeMake(Utils.layout.toDeviceIndependentPixels(this._effectiveColWidth), Utils.layout.toDeviceIndependentPixels(this._effectiveRowHeight));
466
456
  }
457
+ layoutView.invalidateLayout();
467
458
  }
468
- layoutView.invalidateLayout();
469
- // there is no need to call refresh if it was triggered before with same size.
470
- // this refresh is just to handle size change
471
- const layoutKey = this._innerWidth + '_' + this._innerHeight;
472
- if (this._lastLayoutKey !== layoutKey) {
473
- this.refresh();
474
- }
459
+ }
460
+ _onRowHeightPropertyChanged(oldValue, newValue) {
461
+ this.updateRowColSize();
462
+ this.refresh();
463
+ }
464
+ _onColWidthPropertyChanged(oldValue, newValue) {
465
+ this.updateRowColSize();
466
+ this.refresh();
475
467
  }
476
468
  isHorizontal() {
477
469
  return this.orientation === 'horizontal';
478
470
  }
471
+ clearCachedSize(...indexes) {
472
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
473
+ if (sizes) {
474
+ indexes.forEach((index) => {
475
+ if (index < sizes.count) {
476
+ sizes.replaceObjectAtIndexWithObject(index, NSValue.valueWithCGSize(CGSizeZero));
477
+ }
478
+ });
479
+ }
480
+ }
481
+ layoutAttributesForElementsInRect(attributesArray, rect) {
482
+ if (this.itemOverlap) {
483
+ let currentDeltaX = 0;
484
+ let currentDeltaY = 0;
485
+ for (let index = 0; index < attributesArray.count; index++) {
486
+ const attributes = attributesArray.objectAtIndex(index);
487
+ if (attributes.representedElementCategory === 0 /* UICollectionElementCategory.Cell */) {
488
+ const row = attributes.indexPath.row;
489
+ if (this.itemOverlap) {
490
+ attributes.zIndex = row;
491
+ }
492
+ const itemOverlap = this.itemOverlap(this.getItemAtIndex(row), row);
493
+ currentDeltaX += Utils.layout.toDeviceIndependentPixels(Length.toDevicePixels(itemOverlap[1], 0) + Length.toDevicePixels(itemOverlap[3], 0));
494
+ currentDeltaY += Utils.layout.toDeviceIndependentPixels(Length.toDevicePixels(itemOverlap[0], 0) + Length.toDevicePixels(itemOverlap[2], 0));
495
+ attributes.center = CGPointMake(attributes.center.x + currentDeltaX, attributes.center.y + currentDeltaY);
496
+ }
497
+ }
498
+ }
499
+ }
479
500
  onSourceCollectionChanged(event) {
480
501
  const view = this.nativeViewProtected;
481
502
  if (!view || this._dataUpdatesSuspended || !this._lastLayoutKey) {
@@ -484,97 +505,132 @@ export class CollectionView extends CollectionViewBase {
484
505
  if (Trace.isEnabled()) {
485
506
  CLog(CLogTypes.log, 'onItemsChanged', ChangeType.Update, event.action, event.index, event.addedCount, event.removed && event.removed.length);
486
507
  }
487
- // console.log('----')
488
- // console.log('event.action:', event.action)
489
- // console.log('event.addedCount:', event.addedCount);
490
- // console.log('event.removed:', event.removed);
491
- // console.log('event.index:', event.index)
492
- // console.log(' >')
493
- const sectionIdentifier = this._dataSource.sectionIdentifierForIndex(0);
494
- // console.log(' sectionIdentifier:', sectionIdentifier)
495
- const contentOffset = view.contentOffset;
508
+ // we need to clear stored cell sizes and it wont be correct anymore
509
+ // this.clearCellSize();
510
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
511
+ const performBatchUpdatesCompletion = (c) => {
512
+ // if we are not "presented" (viewController hidden) then performBatchUpdatesCompletion would crash
513
+ const viewIsLoaded = !!this.page?.viewController ? !!this.page.viewController.view.window : true;
514
+ if (viewIsLoaded) {
515
+ view.performBatchUpdatesCompletion(c, null);
516
+ }
517
+ else {
518
+ this.refresh();
519
+ }
520
+ };
496
521
  switch (event.action) {
497
522
  case ChangeType.Delete: {
498
- const deleteIdentifiers = [];
523
+ const indexes = NSMutableArray.new();
499
524
  for (let index = 0; index < event.addedCount; index++) {
500
- const indexPath = NSIndexPath.indexPathForRowInSection(event.index + index, sectionIdentifier);
501
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath);
502
- // console.log(' delete identifier:', identifier)
503
- deleteIdentifiers.push(identifier);
525
+ indexes.addObject(NSIndexPath.indexPathForRowInSection(event.index + index, 0));
526
+ if (sizes) {
527
+ sizes.removeObjectAtIndex(event.index);
528
+ }
504
529
  }
530
+ // this._sizes.splice(event.index, event.addedCount);
505
531
  this.unbindUnusedCells(event.removed);
506
- this.modifyDataSourceSnapshot(ChangeType.Delete, deleteIdentifiers, sectionIdentifier);
532
+ if (Trace.isEnabled()) {
533
+ CLog(CLogTypes.info, 'deleteItemsAtIndexPaths', indexes.count);
534
+ }
535
+ performBatchUpdatesCompletion(() => {
536
+ view.deleteItemsAtIndexPaths(indexes);
537
+ });
507
538
  return;
508
539
  }
509
540
  case ChangeType.Update: {
510
- const updateIdentifiers = [];
511
- const indexPath = NSIndexPath.indexPathForRowInSection(event.index, sectionIdentifier);
512
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath);
513
- // console.log(' update identifier:', identifier)
514
- updateIdentifiers.push(identifier);
515
- this.modifyDataSourceSnapshot(ChangeType.Update, updateIdentifiers, sectionIdentifier);
541
+ const indexes = NSMutableArray.new();
542
+ indexes.addObject(NSIndexPath.indexPathForRowInSection(event.index, 0));
543
+ if (sizes && event.index < sizes.count) {
544
+ sizes.replaceObjectAtIndexWithObject(event.index, NSValue.valueWithCGSize(CGSizeZero));
545
+ }
546
+ // this._sizes[event.index] = null;
547
+ if (Trace.isEnabled()) {
548
+ CLog(CLogTypes.info, 'reloadItemsAtIndexPaths', event.index, indexes.count);
549
+ }
550
+ performBatchUpdatesCompletion(() => {
551
+ view.reloadItemsAtIndexPaths(indexes);
552
+ });
516
553
  return;
517
554
  }
518
555
  case ChangeType.Add: {
519
- const addIdentifiers = [];
556
+ const indexes = NSMutableArray.new();
520
557
  for (let index = 0; index < event.addedCount; index++) {
521
- const indexPath = NSIndexPath.indexPathForRowInSection(event.index + index, sectionIdentifier);
522
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath) || getUUID();
523
- // console.log(' add identifier:', identifier)
524
- addIdentifiers.push(identifier);
558
+ indexes.addObject(NSIndexPath.indexPathForRowInSection(event.index + index, 0));
559
+ if (sizes) {
560
+ sizes.insertObjectAtIndex(NSValue.valueWithCGSize(CGSizeZero), event.index);
561
+ }
562
+ // this._sizes.splice(index, 0, null);
525
563
  }
526
- this.modifyDataSourceSnapshot(ChangeType.Add, addIdentifiers, sectionIdentifier);
564
+ if (Trace.isEnabled()) {
565
+ CLog(CLogTypes.info, 'insertItemsAtIndexPaths', indexes.count);
566
+ }
567
+ performBatchUpdatesCompletion(() => {
568
+ view.insertItemsAtIndexPaths(indexes);
569
+ });
527
570
  return;
528
571
  }
529
572
  case ChangeType.Splice: {
530
- const added = event.addedCount;
531
- const removed = (event.removed && event.removed.length) || 0;
532
- if (added > 0 && added === removed) {
533
- const spliceIdentifiers = [];
534
- for (let index = 0; index < added; index++) {
535
- const indexPath = NSIndexPath.indexPathForRowInSection(event.index + index, sectionIdentifier);
536
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath) || getUUID();
537
- // console.log(' splice, update identifier:', identifier)
538
- spliceIdentifiers.push(identifier);
539
- }
540
- this.modifyDataSourceSnapshot(ChangeType.Update, spliceIdentifiers, sectionIdentifier);
541
- }
542
- else {
543
- if (event.removed && event.removed.length > 0) {
544
- const removeIdentifiers = [];
545
- for (let index = 0; index < event.removed.length; index++) {
546
- const indexPath = NSIndexPath.indexPathForItemInSection(event.index + index, sectionIdentifier);
547
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath);
548
- // console.log(' splice, remove identifier:', identifier)
549
- removeIdentifiers.push(identifier);
573
+ performBatchUpdatesCompletion(() => {
574
+ const added = event.addedCount;
575
+ const removed = (event.removed && event.removed.length) || 0;
576
+ if (added > 0 && added === removed) {
577
+ const indexes = NSMutableArray.new();
578
+ for (let index = 0; index < added; index++) {
579
+ indexes.addObject(NSIndexPath.indexPathForRowInSection(event.index + index, 0));
580
+ if (sizes && event.index + index < sizes.count) {
581
+ sizes.replaceObjectAtIndexWithObject(event.index + index, NSValue.valueWithCGSize(CGSizeZero));
582
+ }
583
+ // this._sizes[event.index + index] = null;
550
584
  }
551
- this.unbindUnusedCells(event.removed);
552
- this.modifyDataSourceSnapshot(ChangeType.Delete, removeIdentifiers, sectionIdentifier);
585
+ view.reloadItemsAtIndexPaths(indexes);
553
586
  }
554
- if (event.addedCount > 0) {
555
- const identifiers = [];
556
- for (let index = 0; index < event.addedCount; index++) {
557
- const indexPath = NSIndexPath.indexPathForItemInSection(event.index + index, sectionIdentifier);
558
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath) || getUUID();
559
- // console.log(' splice, add identifier:', identifier)
560
- identifiers.push(identifier);
587
+ else {
588
+ if (event.removed && event.removed.length > 0) {
589
+ const indexes = NSMutableArray.new();
590
+ for (let index = 0; index < event.removed.length; index++) {
591
+ indexes.addObject(NSIndexPath.indexPathForItemInSection(event.index + index, 0));
592
+ if (sizes) {
593
+ sizes.removeObjectAtIndex(event.index);
594
+ }
595
+ }
596
+ // this._sizes.splice(event.index, event.removed.length);
597
+ this.unbindUnusedCells(event.removed);
598
+ if (Trace.isEnabled()) {
599
+ CLog(CLogTypes.info, 'deleteItemsAtIndexPaths', indexes.count);
600
+ }
601
+ view.deleteItemsAtIndexPaths(indexes);
602
+ }
603
+ if (event.addedCount > 0) {
604
+ const indexes = NSMutableArray.alloc().init();
605
+ for (let index = 0; index < event.addedCount; index++) {
606
+ indexes.addObject(NSIndexPath.indexPathForItemInSection(event.index + index, 0));
607
+ if (sizes) {
608
+ sizes.insertObjectAtIndex(NSValue.valueWithCGSize(CGSizeZero), event.index);
609
+ }
610
+ // this._sizes.splice(event.index, 0, null);
611
+ }
612
+ if (Trace.isEnabled()) {
613
+ CLog(CLogTypes.info, 'insertItemsAtIndexPaths', indexes.count);
614
+ }
615
+ view.insertItemsAtIndexPaths(indexes);
561
616
  }
562
- this.modifyDataSourceSnapshot(ChangeType.Add, identifiers, sectionIdentifier);
563
617
  }
564
- }
565
- // view.collectionViewLayout.invalidateLayout();
566
- break;
618
+ // view.collectionViewLayout.invalidateLayout();
619
+ });
620
+ return;
567
621
  }
568
622
  }
569
- // this.refresh();
570
- view.contentOffset = contentOffset;
571
- this.loadingMore = false;
623
+ this.refresh();
572
624
  }
573
- clearEmbeddedViews() {
574
- this.clearRealizedCells();
575
- // if (this.itemViewDisposer !== undefined) {
576
- // this.itemViewDisposer();
577
- // }
625
+ onItemTemplatesChanged(oldValue, newValue) {
626
+ super.onItemTemplatesChanged(oldValue, newValue);
627
+ if (!this.nativeViewProtected) {
628
+ return;
629
+ }
630
+ const view = this.nativeViewProtected;
631
+ this._itemTemplatesInternal.forEach((t) => {
632
+ view.registerClassForCellWithReuseIdentifier(CollectionViewCell.class(), t.key.toLowerCase());
633
+ });
578
634
  }
579
635
  unbindUnusedCells(removedDataItems) {
580
636
  this._map.forEach((view, nativeView, map) => {
@@ -591,7 +647,16 @@ export class CollectionView extends CollectionViewBase {
591
647
  if (!view) {
592
648
  return;
593
649
  }
650
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
594
651
  const visibles = view.indexPathsForVisibleItems;
652
+ if (sizes) {
653
+ const indexes = Array.from(visibles);
654
+ indexes.forEach((value) => {
655
+ if (value.row < sizes.count) {
656
+ sizes.replaceObjectAtIndexWithObject(value.row, NSValue.valueWithCGSize(CGSizeZero));
657
+ }
658
+ });
659
+ }
595
660
  UIView.performWithoutAnimation(() => {
596
661
  view.performBatchUpdatesCompletion(() => {
597
662
  view.reloadItemsAtIndexPaths(visibles);
@@ -606,6 +671,25 @@ export class CollectionView extends CollectionViewBase {
606
671
  const indexes = Array.from(view.indexPathsForVisibleItems);
607
672
  return indexes.some((visIndex) => visIndex.row === itemIndex);
608
673
  }
674
+ findFirstVisibleItemIndex() {
675
+ const view = this.nativeViewProtected;
676
+ if (!view) {
677
+ return -1;
678
+ }
679
+ return this.getRowIndexPath(view)[0] ?? -1;
680
+ }
681
+ findLastVisibleItemIndex() {
682
+ const view = this.nativeViewProtected;
683
+ if (!view) {
684
+ return -1;
685
+ }
686
+ return this.getRowIndexPath(view).at(-1) ?? -1;
687
+ }
688
+ getRowIndexPath(view) {
689
+ return Array.from(view.indexPathsForVisibleItems)
690
+ .map((e) => e.row)
691
+ .sort((a, b) => a - b);
692
+ }
609
693
  refresh() {
610
694
  if (!this.isLoaded || !this.nativeView) {
611
695
  this._isDataDirty = true;
@@ -616,13 +700,18 @@ export class CollectionView extends CollectionViewBase {
616
700
  if (Trace.isEnabled()) {
617
701
  CLog(CLogTypes.info, 'refresh');
618
702
  }
703
+ // we need to clear stored cell sizes and it wont be correct anymore
704
+ // this.clearCellSize();
705
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
706
+ if (sizes) {
707
+ sizes.removeAllObjects();
708
+ }
619
709
  // clear bindingContext when it is not observable because otherwise bindings to items won't reevaluate
620
710
  this._map.forEach((view, nativeView, map) => {
621
711
  if (!(view.bindingContext instanceof Observable)) {
622
712
  view.bindingContext = null;
623
713
  }
624
714
  });
625
- this.refreshDataSourceSnapshot(this.getDefaultSectionIdentifier());
626
715
  // TODO: this is ugly look here: https://github.com/nativescript-vue/nativescript-vue/issues/525
627
716
  // this.clearRealizedCells();
628
717
  // dispatch_async(main_queue, () => {
@@ -641,8 +730,38 @@ export class CollectionView extends CollectionViewBase {
641
730
  get verticalOffsetY() {
642
731
  return this.nativeViewProtected?.contentOffset.y || 0;
643
732
  }
644
- scrollToIndex(index, animated = true) {
645
- this.nativeViewProtected.scrollToItemAtIndexPathAtScrollPositionAnimated(NSIndexPath.indexPathForItemInSection(index, 0), this.orientation === 'vertical' ? 1 /* UICollectionViewScrollPosition.Top */ : 8 /* UICollectionViewScrollPosition.Left */, animated);
733
+ scrollToIndex(index, animated = true, snap = SnapPosition.START) {
734
+ const nativeView = this.nativeViewProtected;
735
+ if (!nativeView) {
736
+ return;
737
+ }
738
+ const nbItems = nativeView.numberOfItemsInSection(0);
739
+ if (nbItems > 0 && index < nbItems) {
740
+ let scrollPosition = 1 /* UICollectionViewScrollPosition.Top */;
741
+ if (this.orientation === 'vertical') {
742
+ scrollPosition = snap === SnapPosition.START ? 1 /* UICollectionViewScrollPosition.Top */ : 4 /* UICollectionViewScrollPosition.Bottom */;
743
+ }
744
+ else {
745
+ scrollPosition = snap === SnapPosition.START ? 8 /* UICollectionViewScrollPosition.Left */ : 32 /* UICollectionViewScrollPosition.Right */;
746
+ }
747
+ nativeView.scrollToItemAtIndexPathAtScrollPositionAnimated(NSIndexPath.indexPathForItemInSection(index, 0), scrollPosition, animated);
748
+ }
749
+ }
750
+ scrollToOffset(value, animated) {
751
+ const view = this.nativeViewProtected;
752
+ if (view && this.isScrollEnabled) {
753
+ const { width, height } = view.bounds.size;
754
+ let rect;
755
+ if (this.orientation === 'vertical') {
756
+ rect = CGRectMake(0, value, width, height);
757
+ }
758
+ else {
759
+ rect = CGRectMake(value, 0, width, height);
760
+ }
761
+ if (rect) {
762
+ view.scrollRectToVisibleAnimated(rect, animated);
763
+ }
764
+ }
646
765
  }
647
766
  requestLayout() {
648
767
  // When preparing cell don't call super - no need to invalidate our measure when cell desiredSize is changed.
@@ -659,64 +778,17 @@ export class CollectionView extends CollectionViewBase {
659
778
  return args;
660
779
  }
661
780
  _getItemTemplateType(indexPath) {
662
- return (this._itemTemplateSelector ? this._itemTemplateSelector.call(this, this.getItemAtIndex(indexPath.row), indexPath.row, this.items) : this._defaultTemplate.key).toLowerCase();
663
- }
664
- disableIosOverflowSafeArea(parentView) {
665
- if (parentView) {
666
- parentView.iosOverflowSafeAreaEnabled = false;
781
+ const selector = this._itemTemplateSelector;
782
+ let type = this._defaultTemplate.key;
783
+ if (selector) {
784
+ type = selector.call(this, this.getItemAtIndex(indexPath.item), indexPath.item, this.items);
667
785
  }
786
+ return type.toLowerCase();
668
787
  }
669
- _prepareHeaderFooter(cell, indexPath, templateKey, templateType, notForCellSizeComp = true) {
670
- let cellSize;
671
- try {
672
- this._preparingCell = true;
673
- const firstRender = !cell.view;
674
- let view = cell.view;
675
- const index = indexPath.row;
676
- if (!view) {
677
- view = this.getViewForTemplateType(templateKey, templateType);
678
- }
679
- if (Trace.isEnabled()) {
680
- CLog(CLogTypes.log, '_prepareHeaderFooter', index, templateType, !!cell.view, !!view, cell.view !== view, notForCellSizeComp);
681
- }
682
- if (view) {
683
- if (firstRender) {
684
- view['iosIgnoreSafeArea'] = true;
685
- }
686
- view.bindingContext = this.bindingContext;
687
- if (view instanceof ProxyViewContainer) {
688
- const sp = new ContentView();
689
- sp.content = view;
690
- view = sp;
691
- }
692
- if (!cell.view) {
693
- cell.owner = new WeakRef(view);
694
- }
695
- else if (cell.view !== view) {
696
- this._removeContainer(cell);
697
- if (cell.view?.nativeViewProtected) {
698
- cell.view.nativeViewProtected.removeFromSuperview();
699
- }
700
- cell.owner = new WeakRef(view);
701
- }
702
- cell.currentIndex = indexPath.row;
703
- if (view && !view.parent) {
704
- this._addView(view);
705
- const innerView = NSCellView.new();
706
- innerView.autoresizingMask = 2 /* UIViewAutoresizing.FlexibleWidth */ | 16 /* UIViewAutoresizing.FlexibleHeight */;
707
- innerView.view = new WeakRef(view);
708
- innerView.addSubview(view.nativeViewProtected);
709
- cell.addSubview(innerView);
710
- }
711
- cellSize = this.measureCell(cell, view, indexPath.row);
712
- }
713
- }
714
- finally {
715
- this._preparingCell = false;
716
- }
717
- return cellSize;
788
+ getItemTemplateContent(index, templateType) {
789
+ return this.getViewForViewType(ListViewViewTypes.ItemView, templateType);
718
790
  }
719
- _prepareCell(cell, indexPath, templateKey, notForCellSizeComp = true) {
791
+ _prepareCell(cell, indexPath, templateType, notForCellSizeComp = true) {
720
792
  let cellSize;
721
793
  try {
722
794
  this._preparingCell = true;
@@ -724,11 +796,11 @@ export class CollectionView extends CollectionViewBase {
724
796
  let view = cell.view;
725
797
  const index = indexPath.row;
726
798
  if (!view) {
727
- view = this.getViewForTemplateType(templateKey);
799
+ view = this.getItemTemplateContent(index, templateType);
728
800
  }
729
801
  const bindingContext = this._prepareItem(view, index);
730
802
  if (Trace.isEnabled()) {
731
- CLog(CLogTypes.log, '_prepareCell', index, templateKey, !!cell.view, !!view, cell.view !== view, notForCellSizeComp);
803
+ CLog(CLogTypes.log, '_prepareCell', index, templateType, !!cell.view, !!view, cell.view !== view, notForCellSizeComp);
732
804
  }
733
805
  const args = this.notifyForItemAtIndex(CollectionViewBase.itemLoadingEvent, view, indexPath.row, bindingContext, cell);
734
806
  view = args.view;
@@ -746,7 +818,7 @@ export class CollectionView extends CollectionViewBase {
746
818
  }
747
819
  else if (cell.view !== view) {
748
820
  this._removeContainer(cell);
749
- if (cell.view?.nativeViewProtected) {
821
+ if (cell.view.nativeViewProtected) {
750
822
  cell.view.nativeViewProtected.removeFromSuperview();
751
823
  }
752
824
  cell.owner = new WeakRef(view);
@@ -760,21 +832,29 @@ export class CollectionView extends CollectionViewBase {
760
832
  const innerView = NSCellView.new();
761
833
  innerView.autoresizingMask = 2 /* UIViewAutoresizing.FlexibleWidth */ | 16 /* UIViewAutoresizing.FlexibleHeight */;
762
834
  innerView.view = new WeakRef(view);
763
- // if (notForCellSizeComp && this.autoReloadItemOnLayout) {
764
- // // for a cell to update correctly on cell layout change we need
765
- // // to do it ourself instead of "propagating it"
766
- // view['performLayout'] = () => {
767
- // if (!this._preparingCell) {
768
- // const index = cell.currentIndex;
769
- // const nativeView = this.nativeViewProtected;
770
- // nativeView.performBatchUpdatesCompletion(() => {
771
- // this.measureCell(cell, view, index);
772
- // this.notifyForItemAtIndex(CollectionViewBase.itemLoadingEvent, view, indexPath.row, view.bindingContext, cell);
773
- // }, null);
774
- // nativeView.collectionViewLayout.invalidateLayout();
775
- // }
776
- // };
777
- // }
835
+ if (notForCellSizeComp && this.autoReloadItemOnLayout) {
836
+ // for a cell to update correctly on cell layout change we need
837
+ // to do it ourself instead of "propagating it"
838
+ view['performLayout'] = () => {
839
+ if (!this._preparingCell && !view['inPerformLayout']) {
840
+ view['inPerformLayout'] = true;
841
+ const index = cell.currentIndex;
842
+ const nativeView = this.nativeViewProtected;
843
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
844
+ if (sizes && index < sizes.count) {
845
+ sizes.replaceObjectAtIndexWithObject(index, NSValue.valueWithCGSize(CGSizeZero));
846
+ }
847
+ nativeView.performBatchUpdatesCompletion(() => {
848
+ this.notifyForItemAtIndex(CollectionViewBase.itemLoadingEvent, view, indexPath.row, view.bindingContext, cell);
849
+ // the order is important because measureCell will set layout as requested and notifyForItemAtIndex would call requestLayout => endless loop
850
+ this.measureCell(cell, view, index);
851
+ cell.contentView.subviews.objectAtIndex(0)?.layoutSubviews();
852
+ // nativeView.collectionViewLayout.invalidateLayout();
853
+ }, null);
854
+ view['inPerformLayout'] = false;
855
+ }
856
+ };
857
+ }
778
858
  innerView.addSubview(view.nativeViewProtected);
779
859
  cell.contentView.addSubview(innerView);
780
860
  }
@@ -792,6 +872,7 @@ export class CollectionView extends CollectionViewBase {
792
872
  return cellSize;
793
873
  }
794
874
  getCellSize(index) {
875
+ // let result = this._sizes[index];
795
876
  let result;
796
877
  // CLog(CLogTypes.log, 'getCellSize', index, result, this._effectiveColWidth, this._effectiveRowHeight, this.getMeasuredWidth(), this.getMeasuredHeight());
797
878
  if (!result) {
@@ -821,6 +902,12 @@ export class CollectionView extends CollectionViewBase {
821
902
  // return undefined;
822
903
  return result;
823
904
  }
905
+ // public storeCellSize(index: number, value) {
906
+ // this._sizes[index] = value;
907
+ // }
908
+ // public clearCellSize() {
909
+ // this._sizes = new Array<number[]>();
910
+ // }
824
911
  measureCell(cell, cellView, position) {
825
912
  if (cellView) {
826
913
  let width = this._effectiveColWidth;
@@ -836,18 +923,14 @@ export class CollectionView extends CollectionViewBase {
836
923
  width *= spanSize;
837
924
  }
838
925
  }
839
- const widthMeasureSpec = width
840
- ? Utils.layout.makeMeasureSpec(width, Utils.layout.EXACTLY)
841
- : horizontal
842
- ? infinity
843
- : Utils.layout.makeMeasureSpec(this._innerWidth, Utils.layout.UNSPECIFIED);
926
+ const widthMeasureSpec = width ? Utils.layout.makeMeasureSpec(width, Utils.layout.EXACTLY) : horizontal ? infinity : Utils.layout.makeMeasureSpec(this._innerWidth, Utils.layout.EXACTLY);
844
927
  const heightMeasureSpec = height
845
928
  ? Utils.layout.makeMeasureSpec(height, Utils.layout.EXACTLY)
846
929
  : horizontal
847
- ? Utils.layout.makeMeasureSpec(this._innerHeight, Utils.layout.UNSPECIFIED)
930
+ ? Utils.layout.makeMeasureSpec(this._innerHeight, Utils.layout.EXACTLY)
848
931
  : infinity;
849
932
  if (Trace.isEnabled()) {
850
- CLog(CLogTypes.log, 'measureCell', position, width, height, widthMeasureSpec, heightMeasureSpec);
933
+ CLog(CLogTypes.log, 'measureCell', position, width, height, this._innerWidth, this._innerHeight, widthMeasureSpec, heightMeasureSpec);
851
934
  }
852
935
  const measuredSize = View.measureChild(this, cellView, widthMeasureSpec, heightMeasureSpec);
853
936
  const result = [measuredSize.measuredWidth, measuredSize.measuredHeight];
@@ -881,6 +964,7 @@ export class CollectionView extends CollectionViewBase {
881
964
  }
882
965
  _removeContainer(cell) {
883
966
  const view = cell.view;
967
+ this.notifyForItemAtIndex(CollectionViewBase.itemDisposingEvent, view, cell.currentIndex, view.bindingContext, cell);
884
968
  // This is to clear the StackLayout that is used to wrap ProxyViewContainer instances.
885
969
  if (!(view.parent instanceof CollectionView)) {
886
970
  this._removeView(view.parent);
@@ -894,15 +978,18 @@ export class CollectionView extends CollectionViewBase {
894
978
  }
895
979
  _setPadding(newPadding) {
896
980
  const layout = this._layout;
897
- const padding = {
898
- top: layout['sectionInset'].top,
899
- right: layout['sectionInset'].right,
900
- bottom: layout['sectionInset'].bottom,
901
- left: layout['sectionInset'].left
902
- };
903
- // tslint:disable-next-line:prefer-object-spread
904
- const newValue = Object.assign(padding, newPadding);
905
- layout['sectionInset'] = newValue;
981
+ // Need to guard sectionInset when using custom layouts
982
+ if (layout && layout['sectionInset']) {
983
+ const padding = {
984
+ top: layout['sectionInset'].top,
985
+ right: layout['sectionInset'].right,
986
+ bottom: layout['sectionInset'].bottom,
987
+ left: layout['sectionInset'].left
988
+ };
989
+ // tslint:disable-next-line:prefer-object-spread
990
+ const newValue = Object.assign(padding, newPadding);
991
+ layout['sectionInset'] = newValue;
992
+ }
906
993
  }
907
994
  numberOfSectionsInCollectionView(collectionView) {
908
995
  if (!this._lastLayoutKey) {
@@ -919,6 +1006,12 @@ export class CollectionView extends CollectionViewBase {
919
1006
  if (!cell) {
920
1007
  cell = CollectionViewCell.new();
921
1008
  }
1009
+ if (this.itemOverlap) {
1010
+ // should we force clipsToBounds? not doing so allows more complex layouts like overlapping
1011
+ // we set zPosition to allow overlap. Should we make it an option?
1012
+ cell.layer.zPosition = indexPath.row;
1013
+ }
1014
+ cell.clipsToBounds = true;
922
1015
  const firstRender = !cell.view;
923
1016
  if (Trace.isEnabled()) {
924
1017
  CLog(CLogTypes.log, 'collectionViewCellForItemAtIndexPath', indexPath.row, templateType, !!cell.view, cell);
@@ -929,30 +1022,10 @@ export class CollectionView extends CollectionViewBase {
929
1022
  if (!firstRender && cellView['isLayoutRequired']) {
930
1023
  this.layoutCell(indexPath.row, cell, cellView);
931
1024
  }
1025
+ // if the cell view is a canvas we need to ensure redraw is called
1026
+ (cellView.content || cellView).nativeViewProtected.setNeedsDisplay();
932
1027
  return cell;
933
1028
  }
934
- // collectionViewViewForSupplementaryElementOfKindAtIndexPath(view: UICollectionView, kind: string, indexPath: NSIndexPath): UICollectionReusableView {
935
- // // const templateType = kind === UICollectionElementKindSectionHeader ? this._headerTemplate.key : this._footerTemplate.key;
936
- // const templateType = kind;
937
- // console.log('templateType:', templateType)
938
- // // let cell = collectionView.dequeueConfiguredReusableSupplementaryViewWithRegistrationForIndexPath(kind, templateType, indexPath) as CollectionViewReusableView;
939
- // let cell = this._dataSource.supplementaryViewProvider(view, kind, indexPath);
940
- // console.log('cell:', cell)
941
- // // if (!cell) {
942
- // // cell = CollectionViewReusableView.new() as CollectionViewReusableView;
943
- // // }
944
- // // const firstRender = !cell.view;
945
- // // if (Trace.isEnabled()) {
946
- // // CLog(CLogTypes.log, 'collectionViewViewForSupplementaryElementOfKindAtIndexPath', indexPath.row, templateType, !!cell.view, cell);
947
- // // }
948
- // // this._prepareHeaderFooter(cell, indexPath, templateType);
949
- // // the cell layout will be called from NSCellView layoutSubviews
950
- // // const cellView: View = cell.view;
951
- // // if (!firstRender && cellView['isLayoutRequired']) {
952
- // // this.layoutCell(indexPath.row, cell, cellView);
953
- // // }
954
- // return cell;
955
- // }
956
1029
  collectionViewWillDisplayCellForItemAtIndexPath(collectionView, cell, indexPath) {
957
1030
  if (this.reverseLayout) {
958
1031
  cell.transform = CGAffineTransformMakeRotation(-Math.PI);
@@ -960,20 +1033,19 @@ export class CollectionView extends CollectionViewBase {
960
1033
  if (this.items) {
961
1034
  const loadMoreItemIndex = this.items.length - this.loadMoreThreshold;
962
1035
  if (indexPath.row === loadMoreItemIndex && this.hasListeners(CollectionViewBase.loadMoreItemsEvent)) {
963
- this.loadingMore = true;
964
1036
  this.notify({
965
1037
  eventName: CollectionViewBase.loadMoreItemsEvent,
966
1038
  object: this
967
1039
  });
968
1040
  }
969
1041
  }
970
- // if (this.hasListeners(CollectionViewBase.displayItemEvent) ) {
971
- // this.notify<CollectionViewItemDisplayEventData>({
972
- // eventName: CollectionViewBase.displayItemEvent,
973
- // index:indexPath.row,
974
- // object: this,
975
- // });
976
- // }
1042
+ if (this.hasListeners(CollectionViewBase.displayItemEvent)) {
1043
+ this.notify({
1044
+ eventName: CollectionViewBase.displayItemEvent,
1045
+ index: indexPath.row,
1046
+ object: this
1047
+ });
1048
+ }
977
1049
  if (cell.preservesSuperviewLayoutMargins) {
978
1050
  cell.preservesSuperviewLayoutMargins = false;
979
1051
  }
@@ -1059,26 +1131,12 @@ export class CollectionView extends CollectionViewBase {
1059
1131
  object: this,
1060
1132
  eventName,
1061
1133
  scrollOffset: offset,
1134
+ scrollSize: size,
1062
1135
  scrollOffsetPercentage: offset / size,
1063
1136
  dx,
1064
1137
  dy: dy + safeAreaInsetsTop
1065
1138
  };
1066
1139
  }
1067
- scrollToOffset(value, animated) {
1068
- if (this.nativeViewProtected && this.isScrollEnabled) {
1069
- const { width, height } = this.nativeViewProtected.bounds.size;
1070
- let rect;
1071
- if (this.orientation === 'vertical') {
1072
- rect = CGRectMake(0, value, width, height);
1073
- }
1074
- else if (this.orientation === 'horizontal') {
1075
- rect = CGRectMake(value, 0, width, height);
1076
- }
1077
- if (rect) {
1078
- this.nativeViewProtected.scrollRectToVisibleAnimated(rect, animated);
1079
- }
1080
- }
1081
- }
1082
1140
  scrollViewWillBeginDragging(scrollView) {
1083
1141
  this.lastContentOffset = scrollView.contentOffset;
1084
1142
  this.needsScrollStartEvent = true;
@@ -1100,11 +1158,11 @@ export class CollectionView extends CollectionViewBase {
1100
1158
  stopScrolling(scrollView) {
1101
1159
  if (this.isScrolling) {
1102
1160
  this.isScrolling = false;
1161
+ this.notify(this.computeScrollEventData(scrollView, CollectionViewBase.scrollEndEvent));
1103
1162
  }
1104
1163
  }
1105
1164
  scrollViewDidEndDecelerating(scrollView) {
1106
1165
  this.stopScrolling(scrollView);
1107
- this.notify(this.computeScrollEventData(scrollView, CollectionViewBase.scrollEndEvent));
1108
1166
  }
1109
1167
  scrollViewWillEndDraggingWithVelocityTargetContentOffset(scrollView, velocity, targetContentOffset) {
1110
1168
  this.stopScrolling(scrollView);
@@ -1123,6 +1181,8 @@ __decorate([
1123
1181
  __metadata("design:returntype", void 0)
1124
1182
  ], CollectionView.prototype, "refresh", null);
1125
1183
  contentInsetAdjustmentBehaviorProperty.register(CollectionView);
1184
+ estimatedItemSizeProperty.register(CollectionView);
1185
+ autoSizeProperty.register(CollectionView);
1126
1186
  var NSCellView = /** @class */ (function (_super) {
1127
1187
  __extends(NSCellView, _super);
1128
1188
  function NSCellView() {
@@ -1130,7 +1190,7 @@ var NSCellView = /** @class */ (function (_super) {
1130
1190
  }
1131
1191
  NSCellView.prototype.layoutSubviews = function () {
1132
1192
  _super.prototype.layoutSubviews.call(this);
1133
- var view = this.view && this.view.deref();
1193
+ var view = this.view && this.view.get();
1134
1194
  if (!view) {
1135
1195
  return;
1136
1196
  }
@@ -1156,27 +1216,155 @@ var CollectionViewCell = /** @class */ (function (_super) {
1156
1216
  var _a;
1157
1217
  var owner = (_a = this.owner) === null || _a === void 0 ? void 0 : _a.deref();
1158
1218
  if (owner) {
1159
- var dimensions = { measuredWidth: owner.getMeasuredWidth(), measuredHeight: owner.getMeasuredHeight() };
1219
+ var dimensions = {
1220
+ measuredWidth: owner.getMeasuredWidth(),
1221
+ measuredHeight: owner.getMeasuredHeight(),
1222
+ };
1160
1223
  return CGSizeMake(Utils.layout.toDeviceIndependentPixels(dimensions.measuredWidth), Utils.layout.toDeviceIndependentPixels(dimensions.measuredHeight));
1161
1224
  }
1162
1225
  return targetSize;
1163
1226
  };
1164
1227
  return CollectionViewCell;
1165
1228
  }(UICollectionViewCell));
1166
- var CollectionViewReusableView = /** @class */ (function (_super) {
1167
- __extends(CollectionViewReusableView, _super);
1168
- function CollectionViewReusableView() {
1229
+ var UICollectionViewImpl = /** @class */ (function (_super) {
1230
+ __extends(UICollectionViewImpl, _super);
1231
+ function UICollectionViewImpl() {
1169
1232
  return _super !== null && _super.apply(this, arguments) || this;
1170
1233
  }
1171
- Object.defineProperty(CollectionViewReusableView.prototype, "view", {
1172
- get: function () {
1173
- return this.owner ? this.owner.deref() : null;
1174
- },
1175
- enumerable: true,
1176
- configurable: true
1177
- });
1178
- return CollectionViewReusableView;
1179
- }(UICollectionReusableView));
1234
+ UICollectionViewImpl.prototype.sizeThatFits = function (size) {
1235
+ var _a, _b, _c;
1236
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1237
+ if (owner === null || owner === void 0 ? void 0 : owner.autoSize) {
1238
+ if (this.superview) {
1239
+ (_b = this.superview) === null || _b === void 0 ? void 0 : _b.layoutIfNeeded();
1240
+ }
1241
+ var horizontal = owner.orientation === 'horizontal';
1242
+ // Calculate the total size based on the cells' sizes
1243
+ var width = 0;
1244
+ var height = 0;
1245
+ var dataSource = owner._dataSource;
1246
+ var delegate = owner._delegate;
1247
+ if (dataSource && delegate) {
1248
+ var numberOfItems = dataSource.collectionViewNumberOfItemsInSection(this, 0);
1249
+ for (var index = 0; index < numberOfItems; index++) {
1250
+ var indexPath = NSIndexPath.indexPathForItemInSection(index, 0);
1251
+ var estimatedSize = (_c = delegate.collectionViewLayoutSizeForItemAtIndexPath(this, owner._layout, indexPath)) !== null && _c !== void 0 ? _c : CGSizeZero;
1252
+ if (horizontal) {
1253
+ width = Math.max(width, estimatedSize.width);
1254
+ height += estimatedSize.height;
1255
+ }
1256
+ else {
1257
+ height = Math.max(height, estimatedSize.height);
1258
+ width += estimatedSize.width;
1259
+ }
1260
+ }
1261
+ return CGSizeMake(width, height);
1262
+ }
1263
+ }
1264
+ return _super.prototype.sizeThatFits.call(this, size);
1265
+ };
1266
+ UICollectionViewImpl.initWithOwner = function (owner, layout) {
1267
+ var view = UICollectionViewImpl.alloc().initWithFrameCollectionViewLayout(CGRectMake(0, 0, 0, 0), layout);
1268
+ view._owner = new WeakRef(owner);
1269
+ return view;
1270
+ };
1271
+ return UICollectionViewImpl;
1272
+ }(UICollectionView));
1273
+ var UICollectionViewFlowLayoutImpl = /** @class */ (function (_super) {
1274
+ __extends(UICollectionViewFlowLayoutImpl, _super);
1275
+ function UICollectionViewFlowLayoutImpl() {
1276
+ return _super !== null && _super.apply(this, arguments) || this;
1277
+ }
1278
+ UICollectionViewFlowLayoutImpl.initWithOwner = function (owner) {
1279
+ var layout = UICollectionViewFlowLayoutImpl.new();
1280
+ layout._owner = new WeakRef(owner);
1281
+ return layout;
1282
+ };
1283
+ UICollectionViewFlowLayoutImpl.prototype.invalidationContextForInteractivelyMovingItemsWithTargetPositionPreviousIndexPathsPreviousPosition = function (targetIndexPaths, targetPosition, previousIndexPaths, previousPosition) {
1284
+ var _a;
1285
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1286
+ if (owner && targetIndexPaths.count) {
1287
+ owner.clearCachedSize(targetIndexPaths.objectAtIndex(0).row, previousIndexPaths.objectAtIndex(0).row);
1288
+ }
1289
+ return _super.prototype.invalidationContextForInteractivelyMovingItemsWithTargetPositionPreviousIndexPathsPreviousPosition.call(this, targetIndexPaths, targetPosition, previousIndexPaths, previousPosition);
1290
+ };
1291
+ UICollectionViewFlowLayoutImpl.prototype.layoutAttributesForElementsInRect = function (rect) {
1292
+ var _a;
1293
+ var attributesArray = _super.prototype.layoutAttributesForElementsInRect.call(this, rect);
1294
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1295
+ owner === null || owner === void 0 ? void 0 : owner.layoutAttributesForElementsInRect(attributesArray, rect);
1296
+ return attributesArray;
1297
+ };
1298
+ UICollectionViewFlowLayoutImpl.prototype.shouldInvalidateLayoutForBoundsChange = function (newBounds) {
1299
+ var _a;
1300
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1301
+ if (owner === null || owner === void 0 ? void 0 : owner.itemOverlap) {
1302
+ return true;
1303
+ }
1304
+ return _super.prototype.shouldInvalidateLayoutForBoundsChange.call(this, newBounds);
1305
+ };
1306
+ return UICollectionViewFlowLayoutImpl;
1307
+ }(UICollectionViewFlowLayout));
1308
+ var CollectionViewDataSource = /** @class */ (function (_super) {
1309
+ __extends(CollectionViewDataSource, _super);
1310
+ function CollectionViewDataSource() {
1311
+ return _super !== null && _super.apply(this, arguments) || this;
1312
+ }
1313
+ CollectionViewDataSource.initWithOwner = function (owner) {
1314
+ var delegate = CollectionViewDataSource.new();
1315
+ delegate._owner = new WeakRef(owner);
1316
+ return delegate;
1317
+ };
1318
+ CollectionViewDataSource.prototype.numberOfSectionsInCollectionView = function (collectionView) {
1319
+ var owner = this._owner.deref();
1320
+ if (owner) {
1321
+ return owner.numberOfSectionsInCollectionView(collectionView);
1322
+ }
1323
+ return 0;
1324
+ };
1325
+ CollectionViewDataSource.prototype.collectionViewNumberOfItemsInSection = function (collectionView, section) {
1326
+ var owner = this._owner.deref();
1327
+ if (owner) {
1328
+ return owner.collectionViewNumberOfItemsInSection(collectionView, section);
1329
+ }
1330
+ return 0;
1331
+ };
1332
+ CollectionViewDataSource.prototype.collectionViewCellForItemAtIndexPath = function (collectionView, indexPath) {
1333
+ var owner = this._owner.deref();
1334
+ if (owner) {
1335
+ return owner.collectionViewCellForItemAtIndexPath(collectionView, indexPath);
1336
+ }
1337
+ return null;
1338
+ };
1339
+ CollectionViewDataSource.prototype.collectionViewMoveItemAtIndexPathToIndexPath = function (collectionView, sourceIndexPath, destinationIndexPath) {
1340
+ var owner = this._owner.deref();
1341
+ if (owner) {
1342
+ owner.reorderStartingRow = sourceIndexPath.row;
1343
+ owner.reorderEndingRow = destinationIndexPath.row;
1344
+ // owner._reorderItemInSource(sourceIndexPath.row, destinationIndexPath.row, false);
1345
+ }
1346
+ };
1347
+ CollectionViewDataSource.prototype.collectionViewTargetIndexPathForMoveFromItemAtIndexPathToProposedIndexPath = function (collectionView, originalIndexPath, proposedIndexPath) {
1348
+ var owner = this._owner.deref();
1349
+ if (owner) {
1350
+ owner.reorderEndingRow = proposedIndexPath.row;
1351
+ }
1352
+ return proposedIndexPath;
1353
+ };
1354
+ CollectionViewDataSource.prototype.collectionViewCanMoveItemAtIndexPath = function (collectionView, indexPath) {
1355
+ var owner = this._owner.deref();
1356
+ if (owner) {
1357
+ var result = owner.shouldMoveItemAtIndex(indexPath.row);
1358
+ if (result) {
1359
+ owner.reorderStartingRow = indexPath.row;
1360
+ }
1361
+ return result;
1362
+ }
1363
+ return false;
1364
+ };
1365
+ CollectionViewDataSource.ObjCProtocols = [UICollectionViewDataSource];
1366
+ return CollectionViewDataSource;
1367
+ }(NSObject));
1180
1368
  var UICollectionViewDelegateImpl = /** @class */ (function (_super) {
1181
1369
  __extends(UICollectionViewDelegateImpl, _super);
1182
1370
  function UICollectionViewDelegateImpl() {
@@ -1243,6 +1431,19 @@ var UICollectionViewDelegateImpl = /** @class */ (function (_super) {
1243
1431
  owner.scrollViewDidEndScrollingAnimation(scrollView);
1244
1432
  }
1245
1433
  };
1434
+ UICollectionViewDelegateImpl.prototype.collectionViewTargetIndexPathForMoveFromItemAtIndexPathToProposedIndexPath = function (collectionView, currentIndexPath, proposedIndexPath) {
1435
+ var _a;
1436
+ if (currentIndexPath === proposedIndexPath) {
1437
+ return proposedIndexPath;
1438
+ }
1439
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1440
+ if (owner && !owner._canReorderToPosition(currentIndexPath.row, proposedIndexPath.row, owner.getItemAtIndex(proposedIndexPath.row))) {
1441
+ return currentIndexPath;
1442
+ }
1443
+ owner._reorderItemInSource(currentIndexPath.row, proposedIndexPath.row, false);
1444
+ owner.clearCachedSize(currentIndexPath.row, proposedIndexPath.row);
1445
+ return proposedIndexPath;
1446
+ };
1246
1447
  UICollectionViewDelegateImpl.ObjCProtocols = [UICollectionViewDelegate, UICollectionViewDelegateFlowLayout];
1247
1448
  return UICollectionViewDelegateImpl;
1248
1449
  }(UICollectionViewCacheDelegateFlowLayout));
@@ -1305,6 +1506,19 @@ var UICollectionViewDelegateFixedSizeImpl = /** @class */ (function (_super) {
1305
1506
  owner.scrollViewDidEndScrollingAnimation(scrollView);
1306
1507
  }
1307
1508
  };
1509
+ UICollectionViewDelegateFixedSizeImpl.prototype.collectionViewTargetIndexPathForMoveFromItemAtIndexPathToProposedIndexPath = function (collectionView, currentIndexPath, proposedIndexPath) {
1510
+ var _a;
1511
+ if (currentIndexPath === proposedIndexPath) {
1512
+ return proposedIndexPath;
1513
+ }
1514
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1515
+ if (owner && !owner._canReorderToPosition(currentIndexPath.row, proposedIndexPath.row, owner.getItemAtIndex(proposedIndexPath.row))) {
1516
+ return currentIndexPath;
1517
+ }
1518
+ owner._reorderItemInSource(currentIndexPath.row, proposedIndexPath.row, false);
1519
+ owner.clearCachedSize(currentIndexPath.row, proposedIndexPath.row);
1520
+ return proposedIndexPath;
1521
+ };
1308
1522
  UICollectionViewDelegateFixedSizeImpl.ObjCProtocols = [UICollectionViewDelegate, UICollectionViewDelegateFlowLayout];
1309
1523
  return UICollectionViewDelegateFixedSizeImpl;
1310
1524
  }(NSObject));