bm-core-ui 2.10.5 → 2.11.1
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/build/@types/index.d.ts +312 -12
- package/build/BMCodeEditor/BMCodeEditor.js +2 -2
- package/build/BMCollectionView/BMCollectionView.js +302 -56
- package/build/BMCollectionView/BMCollectionViewCell.js +54 -27
- package/build/BMCollectionView/BMCollectionViewFlowLayout.js +2 -1
- package/build/BMCollectionView/BMCollectionViewMasonryLayout.js +1 -1
- package/build/BMCollectionView/BMCollectionViewStackLayout.js +1 -1
- package/build/BMCollectionView/BMCollectionViewTileLayout.js +1 -1
- package/build/BMWindow/BMWindow.js +141 -0
- package/build/Core/BMAnimationContext.js +93 -5
- package/lib/@types/BMCoreUI.min.d.ts +312 -12
- package/lib/BMCoreUI.min.js +1 -1
- package/package.json +1 -1
|
@@ -114,6 +114,39 @@ BMJQueryShim.shimWithDOMNode = function (node) {
|
|
|
114
114
|
// When set to YES, this will cause collection view cells to extend view
|
|
115
115
|
const BM_USE_BMVIEW_SUBCLASS = YES;
|
|
116
116
|
|
|
117
|
+
// @type BMCollectionViewCellReuseState
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Constants describing the various reuse states that a collection view cell may be in.
|
|
121
|
+
*/
|
|
122
|
+
export const BMCollectionViewCellReuseState = Object.freeze({ // <enum>
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Indicates that this cell is currently bound to a data source object and retained
|
|
126
|
+
* or managed by the collection view.
|
|
127
|
+
*/
|
|
128
|
+
InUse: "InUse", // <enum>
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Indicates that this cell is not currently in use, but may be reused in the future.
|
|
132
|
+
*/
|
|
133
|
+
InQueue: "InQueue", // <enum>
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Indicates that this cell is in the process of being deleted and is bound to a data
|
|
137
|
+
* source object that no longer has a valid index path.
|
|
138
|
+
*/
|
|
139
|
+
Deleting: "Deleting", // <enum>
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Indicates that this cell is not currently in use and cannot be reused in the future.
|
|
143
|
+
* References to cells in this state should be cleared as they are no longer valid.
|
|
144
|
+
*/
|
|
145
|
+
Discarded: "Discarded" // <enum>
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// @endtype
|
|
149
|
+
|
|
117
150
|
// @type BMCollectionViewCell extends BMView
|
|
118
151
|
|
|
119
152
|
/**
|
|
@@ -156,16 +189,13 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
156
189
|
return this.retainCount > 0;
|
|
157
190
|
},
|
|
158
191
|
|
|
159
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
160
192
|
get _frame() {
|
|
161
193
|
return this._attributes && this._attributes.frame;
|
|
162
194
|
},
|
|
163
195
|
|
|
164
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
165
196
|
get frame() {
|
|
166
197
|
return this._attributes && this._attributes.frame;
|
|
167
198
|
},
|
|
168
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
169
199
|
set frame(frame) {
|
|
170
200
|
// NOTE: A cell's frame is controlled by its layout attributes, therefore this operation is a no-op
|
|
171
201
|
},
|
|
@@ -192,12 +222,6 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
192
222
|
*/
|
|
193
223
|
_element: undefined, // <BMJQueryShim>
|
|
194
224
|
get element() { return this._element || (this._element = BMJQueryShim.shimWithDOMNode(this.node)); },
|
|
195
|
-
|
|
196
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
197
|
-
/**
|
|
198
|
-
* The DOM node managed by this cell.
|
|
199
|
-
*/
|
|
200
|
-
//node: undefined, // <DOMNode>
|
|
201
225
|
|
|
202
226
|
/**
|
|
203
227
|
* The type of item this cell represents.
|
|
@@ -206,7 +230,8 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
206
230
|
itemType: BMCollectionViewLayoutAttributesType.Cell, // <BMCollectionViewLayoutAttributesType>
|
|
207
231
|
|
|
208
232
|
/**
|
|
209
|
-
* The cell's reuse identifier which
|
|
233
|
+
* The cell's reuse identifier which controls when this cell is reused when data source objects
|
|
234
|
+
* request cell instances from the associated collection view.
|
|
210
235
|
*/
|
|
211
236
|
_reuseIdentifier: undefined, // <String>
|
|
212
237
|
|
|
@@ -396,10 +421,8 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
396
421
|
recycle: function () {
|
|
397
422
|
this._unmanage();
|
|
398
423
|
|
|
399
|
-
this.invalidate();
|
|
400
|
-
|
|
401
|
-
//this.collectionView.cellWasUnmanaged(this);
|
|
402
424
|
if (this.retainCount > 0) {
|
|
425
|
+
this.invalidate();
|
|
403
426
|
this.collectionView.cellWasInvalidated(this);
|
|
404
427
|
this.destroy();
|
|
405
428
|
|
|
@@ -422,9 +445,8 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
422
445
|
releaseRecycledCell: function () {
|
|
423
446
|
this.release();
|
|
424
447
|
|
|
425
|
-
this.invalidate();
|
|
426
|
-
|
|
427
448
|
if (this.retainCount > 0) {
|
|
449
|
+
this.invalidate();
|
|
428
450
|
this.collectionView.cellWasInvalidated(this);
|
|
429
451
|
this.destroy();
|
|
430
452
|
|
|
@@ -438,6 +460,15 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
438
460
|
}
|
|
439
461
|
},
|
|
440
462
|
|
|
463
|
+
/**
|
|
464
|
+
* The cell's current reuse state.
|
|
465
|
+
*/
|
|
466
|
+
_reuseState: BMCollectionViewCellReuseState.InQueue, // <BMCollectionViewCellReuseState>
|
|
467
|
+
|
|
468
|
+
get reuseState() {
|
|
469
|
+
return this._reuseState;
|
|
470
|
+
},
|
|
471
|
+
|
|
441
472
|
/**
|
|
442
473
|
* Should be set to YES to hide the cell, or NO to reveal it.
|
|
443
474
|
*/
|
|
@@ -475,7 +506,6 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
475
506
|
this.node.classList.remove('BMCollectionViewCellHidden');
|
|
476
507
|
},
|
|
477
508
|
|
|
478
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
479
509
|
_prepareForAutomaticIntrinsicSize() {
|
|
480
510
|
for (let subview of this._subviews) {
|
|
481
511
|
subview._prepareForAutomaticIntrinsicSize();
|
|
@@ -489,27 +519,25 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
489
519
|
}
|
|
490
520
|
else {
|
|
491
521
|
if (this._requiredWidth) {
|
|
492
|
-
// Otherwise derive the measured size using the
|
|
522
|
+
// Otherwise derive the measured size using the intrinsic CSS size
|
|
493
523
|
BMCopyProperties(this._node.style, {width: this._requiredWidth + 'px', height: 'auto'});
|
|
494
524
|
}
|
|
495
525
|
else {
|
|
496
|
-
// Otherwise derive the measured size using the
|
|
526
|
+
// Otherwise derive the measured size using the intrinsic CSS size
|
|
497
527
|
BMCopyProperties(this._node.style, {width: 'auto', height: 'auto'});
|
|
498
528
|
}
|
|
499
529
|
}
|
|
500
530
|
}
|
|
501
531
|
},
|
|
502
532
|
|
|
503
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
504
533
|
_supportsAutomaticIntrinsicSize: NO,
|
|
505
534
|
|
|
506
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
507
535
|
/**
|
|
536
|
+
* @protected
|
|
508
537
|
* Temporarily set to `YES` while this cell is being measured.
|
|
509
538
|
*/
|
|
510
539
|
_isMeasuring: NO,
|
|
511
540
|
|
|
512
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
513
541
|
internalConstraints() {
|
|
514
542
|
var constraints = [];
|
|
515
543
|
|
|
@@ -550,19 +578,19 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
550
578
|
/**
|
|
551
579
|
* Invoked prior to this cell being collected for reuse by the collection view.
|
|
552
580
|
* Subclasses can override this method to perform any changes necessary for reusing this cell.
|
|
553
|
-
* Subclasses
|
|
581
|
+
* Subclasses must invoke the superclass method at some point in their implementation.
|
|
554
582
|
*/
|
|
555
583
|
prepareForReuse() {
|
|
556
|
-
|
|
584
|
+
this._reuseState = BMCollectionViewCellReuseState.InQueue;
|
|
557
585
|
},
|
|
558
586
|
|
|
559
587
|
/**
|
|
560
588
|
* Invoked prior to this cell being shown on the screen either after being initialized or after having been previously collected.
|
|
561
|
-
* Subclasses can override this method to perform any changes
|
|
562
|
-
* Subclasses
|
|
589
|
+
* Subclasses can override this method to perform any changes necessary for displaying this cell.
|
|
590
|
+
* Subclasses must invoke the superclass method at some point in their implementation.
|
|
563
591
|
*/
|
|
564
592
|
prepareForDisplay() {
|
|
565
|
-
|
|
593
|
+
this._reuseState = BMCollectionViewCellReuseState.InUse;
|
|
566
594
|
},
|
|
567
595
|
|
|
568
596
|
/**
|
|
@@ -625,7 +653,6 @@ BMCollectionViewCell.prototype = BMExtend(BM_USE_BMVIEW_SUBCLASS ? Object.create
|
|
|
625
653
|
|
|
626
654
|
this.collectionView = collectionView;
|
|
627
655
|
|
|
628
|
-
// #FLAG BM_USE_BMVIEW_SUBCLASS
|
|
629
656
|
if (BM_USE_BMVIEW_SUBCLASS) {
|
|
630
657
|
BMView.prototype.initWithDOMNode.call(this, args.node);
|
|
631
658
|
}
|
|
@@ -41,6 +41,7 @@ export var BMCollectionViewTableLayoutSupplementaryView = Object.freeze({ // <en
|
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* @deprecated Use `BMCollectionViewFlowLayout` with the `maximumCellsPerRow` property set to `1`.
|
|
44
|
+
*
|
|
44
45
|
* --------------------------------------
|
|
45
46
|
* A basic layout implementation, the BMCollectionViewTableLayout will lay out its elements as a list where each row can have
|
|
46
47
|
* either a fixed height or a variable height.
|
|
@@ -4964,7 +4965,7 @@ BMCollectionViewFlowLayout.prototype = BMExtend(Object.create(BMCollectionViewLa
|
|
|
4964
4965
|
* @return <BMCollectionViewFlowLayout> A flow layout.
|
|
4965
4966
|
*/
|
|
4966
4967
|
BMCollectionViewFlowLayout.flowLayout = function () {
|
|
4967
|
-
return new
|
|
4968
|
+
return new this();
|
|
4968
4969
|
}
|
|
4969
4970
|
|
|
4970
4971
|
// @endtype
|
|
@@ -625,7 +625,7 @@ BMCollectionViewMasonryLayout.prototype = BMExtend({}, BMCollectionViewLayout.pr
|
|
|
625
625
|
* @returns <BMCollectionViewMasonryLayout> A masonry layout.
|
|
626
626
|
*/
|
|
627
627
|
BMCollectionViewMasonryLayout.masonryLayout = function () {
|
|
628
|
-
return new
|
|
628
|
+
return new this();
|
|
629
629
|
};
|
|
630
630
|
|
|
631
631
|
// @endtype
|
|
@@ -628,7 +628,7 @@ BMCollectionViewStackLayout.prototype = BMExtend({}, BMCollectionViewLayout.prot
|
|
|
628
628
|
* @returns <BMCollectionViewStackLayout> A stack layout.
|
|
629
629
|
*/
|
|
630
630
|
BMCollectionViewStackLayout.stackLayout = function () {
|
|
631
|
-
return new
|
|
631
|
+
return new this();
|
|
632
632
|
}
|
|
633
633
|
|
|
634
634
|
// @endtype
|
|
@@ -1260,7 +1260,7 @@ BMCollectionViewTileLayout.prototype = BMExtend({}, BMCollectionViewLayout.proto
|
|
|
1260
1260
|
* @return <BMCollectionViewTileLayout> A tile layout.
|
|
1261
1261
|
*/
|
|
1262
1262
|
BMCollectionViewTileLayout.tileLayout = function () {
|
|
1263
|
-
return new
|
|
1263
|
+
return new this();
|
|
1264
1264
|
};
|
|
1265
1265
|
|
|
1266
1266
|
// @endtype
|
|
@@ -1075,6 +1075,147 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1075
1075
|
return this;
|
|
1076
1076
|
},
|
|
1077
1077
|
|
|
1078
|
+
/**
|
|
1079
|
+
* Starts a drag event from the specified `mousedown` or `touchstart` event that moves this window.
|
|
1080
|
+
* When this method is invoked, further mouse and touch events will be blocked until the drag finishes.
|
|
1081
|
+
*
|
|
1082
|
+
* If there is already a drag operation in progress or if this window is full screen or a modal window,
|
|
1083
|
+
* this method has no effect.
|
|
1084
|
+
* @param event <MouseEvent | TouchEvent> The `mousedown` or `touchstart` event from which to begin
|
|
1085
|
+
* the window movement.
|
|
1086
|
+
*/
|
|
1087
|
+
performDragWithEvent(event) {
|
|
1088
|
+
if (event.type == 'mousedown') {
|
|
1089
|
+
this.performDragWithMouseEvent(event);
|
|
1090
|
+
}
|
|
1091
|
+
else if (event.type == 'touchstart') {
|
|
1092
|
+
this.performDragWithTouchEvent(event);
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* Starts a drag event from the specified `mousedown` event that will move this window.
|
|
1098
|
+
* When this method is invoked, further mouse events will be blocked until the drag finishes.
|
|
1099
|
+
*
|
|
1100
|
+
* If there is already a drag operation in progress or if this window is full screen or a modal window,
|
|
1101
|
+
* this method has no effect.
|
|
1102
|
+
* @param event <MouseEvent | TouchEvent> The `mousedown` event from which to begin the window movement.
|
|
1103
|
+
*/
|
|
1104
|
+
performDragWithMouseEvent(event) {
|
|
1105
|
+
// Full screen and modal windows cannot be moved
|
|
1106
|
+
if (this._fullScreen) return;
|
|
1107
|
+
|
|
1108
|
+
this._dragged = YES;
|
|
1109
|
+
|
|
1110
|
+
this._position = BMPointMake(this.node.offsetLeft, this.node.offsetTop);
|
|
1111
|
+
let lastPosition = BMPointMake(event.clientX, event.clientY);
|
|
1112
|
+
|
|
1113
|
+
let mouseMoveEventListener = event => {
|
|
1114
|
+
let position = BMPointMake(event.clientX, event.clientY);
|
|
1115
|
+
const newPosition = BMPointMake(this._position.x + position.x - lastPosition.x, this._position.y + position.y - lastPosition.y);
|
|
1116
|
+
|
|
1117
|
+
// Check if the window can move
|
|
1118
|
+
let canMove = YES;
|
|
1119
|
+
if (this.delegate && this.delegate.windowShouldMove) {
|
|
1120
|
+
canMove = this.delegate.windowShouldMove(this, newPosition);
|
|
1121
|
+
}
|
|
1122
|
+
if (!canMove) return;
|
|
1123
|
+
|
|
1124
|
+
this.leftConstraint.constant = this._position.x + position.x - lastPosition.x;
|
|
1125
|
+
this.topConstraint.constant = this._position.y + position.y - lastPosition.y;
|
|
1126
|
+
this._position = newPosition;
|
|
1127
|
+
lastPosition = position;
|
|
1128
|
+
this.layout();
|
|
1129
|
+
event.preventDefault();
|
|
1130
|
+
};
|
|
1131
|
+
|
|
1132
|
+
let mouseUpEventListener = event => {
|
|
1133
|
+
window.removeEventListener('mousemove', mouseMoveEventListener, YES);
|
|
1134
|
+
window.removeEventListener('mouseup', mouseUpEventListener, YES);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
window.addEventListener('mousemove', mouseMoveEventListener, YES);
|
|
1138
|
+
window.addEventListener('mouseup', mouseUpEventListener, YES);
|
|
1139
|
+
|
|
1140
|
+
event.preventDefault();
|
|
1141
|
+
},
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* The identifier of the touch point that is tracked during a drag operation. `undefined`
|
|
1145
|
+
* when not tracking a drag.
|
|
1146
|
+
*/
|
|
1147
|
+
_touchDragPoint: undefined, // <String>
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* Starts a drag event from the specified `touchstart` event that will move this window.
|
|
1151
|
+
* When this method is invoked, further touch events will be blocked until the drag finishes.
|
|
1152
|
+
*
|
|
1153
|
+
*
|
|
1154
|
+
* If there is already a drag operation in progress or if this window is full screen or a modal window,
|
|
1155
|
+
* this method has no effect.
|
|
1156
|
+
* @param event <MouseEvent | TouchEvent> The `touchstart` event from which to begin the window movement.
|
|
1157
|
+
*/
|
|
1158
|
+
performDragWithTouchEvent(event) {
|
|
1159
|
+
// If there is already a drag in progress, don't process this new event
|
|
1160
|
+
if (typeof this._touchDragPoint !== 'undefined') {
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// Full screen windows cannot be moved
|
|
1165
|
+
if (this._fullScreen) return;
|
|
1166
|
+
|
|
1167
|
+
// Only use the first touch point
|
|
1168
|
+
this._touchDragPoint = event.changedTouches[0].identifier;
|
|
1169
|
+
this._dragged = YES;
|
|
1170
|
+
|
|
1171
|
+
this._position = BMPointMake(this.node.offsetLeft, this.node.offsetTop);
|
|
1172
|
+
let lastPosition = BMPointMake(event.changedTouches[0].clientX, event.changedTouches[0].clientY);
|
|
1173
|
+
|
|
1174
|
+
let mouseMoveEventListener = event => {
|
|
1175
|
+
// Look for the actively tracked touch point
|
|
1176
|
+
let touch;
|
|
1177
|
+
for (let changedTouch of event.changedTouches) {
|
|
1178
|
+
if (changedTouch.identifier == this._touchDragPoint) {
|
|
1179
|
+
touch = changedTouch;
|
|
1180
|
+
break;
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
// If the actively tracked touch point did not move, do not process this event
|
|
1185
|
+
if (!touch) return;
|
|
1186
|
+
|
|
1187
|
+
let position = BMPointMake(touch.clientX, touch.clientY);
|
|
1188
|
+
const newPosition = BMPointMake(this._position.x + position.x - lastPosition.x, this._position.y + position.y - lastPosition.y);
|
|
1189
|
+
|
|
1190
|
+
// Check if the window can move
|
|
1191
|
+
let canMove = YES;
|
|
1192
|
+
if (this.delegate && this.delegate.windowShouldMove) {
|
|
1193
|
+
canMove = this.delegate.windowShouldMove(this, newPosition);
|
|
1194
|
+
}
|
|
1195
|
+
if (!canMove) return;
|
|
1196
|
+
|
|
1197
|
+
this.leftConstraint.constant = this._position.x + position.x - lastPosition.x;
|
|
1198
|
+
this.topConstraint.constant = this._position.y + position.y - lastPosition.y;
|
|
1199
|
+
this._position = newPosition;
|
|
1200
|
+
lastPosition = position;
|
|
1201
|
+
this.layout();
|
|
1202
|
+
event.preventDefault();
|
|
1203
|
+
};
|
|
1204
|
+
|
|
1205
|
+
let mouseUpEventListener = event => {
|
|
1206
|
+
this._touchDragPoint = undefined;
|
|
1207
|
+
window.removeEventListener('touchmove', mouseMoveEventListener);
|
|
1208
|
+
window.removeEventListener('touchend', mouseUpEventListener);
|
|
1209
|
+
window.removeEventListener('touchcancel', mouseUpEventListener);
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
window.addEventListener('touchmove', mouseMoveEventListener);
|
|
1213
|
+
window.addEventListener('touchend', mouseUpEventListener);
|
|
1214
|
+
window.removeEventListener('touchcancel', mouseUpEventListener);
|
|
1215
|
+
|
|
1216
|
+
event.preventDefault();
|
|
1217
|
+
},
|
|
1218
|
+
|
|
1078
1219
|
// @override - BMView
|
|
1079
1220
|
colorSchemeDidChange(scheme) {
|
|
1080
1221
|
BMView.prototype.colorSchemeDidChange.apply(this, arguments);
|
|
@@ -625,6 +625,11 @@ BMAnimationContext.prototype = {
|
|
|
625
625
|
|
|
626
626
|
}
|
|
627
627
|
|
|
628
|
+
/**
|
|
629
|
+
* A map having DOM nodes as keys which contains delayed animations that have yet to start.
|
|
630
|
+
*/
|
|
631
|
+
BMAnimationContext._pendingAnimations = new Map; // Map<DOMNode, unknown[]>
|
|
632
|
+
|
|
628
633
|
/**
|
|
629
634
|
* The animation stack holds all animations with their attributes.
|
|
630
635
|
* Whenever an attribute property is changed while there is an active animation, that property
|
|
@@ -756,6 +761,37 @@ export function BMAnimationApply() {
|
|
|
756
761
|
// Set to `YES` if the environment does not fully support web animations
|
|
757
762
|
var BM_WEB_ANIMATIONS_DISABLED = NO;
|
|
758
763
|
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* Stops all current animations for the specified node on the properties that
|
|
767
|
+
* are specified in an animation that is about to start.
|
|
768
|
+
* @param node <DOMNode> The DOM node on which the animation is about to start.
|
|
769
|
+
* {
|
|
770
|
+
* @param withProperties <Dictionary<unknown>> The properties that are about to be animated.
|
|
771
|
+
* @param options <Dictionary<unknown>> The options of the animation that is about to start.
|
|
772
|
+
* }
|
|
773
|
+
*/
|
|
774
|
+
BMAnimationContext._prepareAnimationForNode = function (node, {withProperties: properties, options}) {
|
|
775
|
+
const velocity = window.Velocity || window.$?.Velocity;
|
|
776
|
+
if (!velocity) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// Find all animations targeting the specified node
|
|
781
|
+
const nodeAnimations = velocity.State.calls.filter(c => c[1]?.[0] == node);
|
|
782
|
+
|
|
783
|
+
// For each animation clear out the properties that are about to be animated, except for the tween property
|
|
784
|
+
for (const call of nodeAnimations) {
|
|
785
|
+
for (const property in properties) {
|
|
786
|
+
if (property == 'element' || property == 'tween') {
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
delete call[0]?.[0]?.[property];
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
759
795
|
/**
|
|
760
796
|
* Must be invoked after a <code>BMAnimationBeginWithDuration()</code> call to apply the pending animation.
|
|
761
797
|
* Applying the animation in this way will stop all other running animations on the animation targets.
|
|
@@ -849,7 +885,13 @@ export function BMAnimationApplyBlocking(blocking) {
|
|
|
849
885
|
for (var i = 0; i < animationTargetsLength; i++) {
|
|
850
886
|
var element = animationTargets[i].element;
|
|
851
887
|
|
|
852
|
-
if (blocking
|
|
888
|
+
if (blocking && velocity) {
|
|
889
|
+
// velocity(element, 'stop', true);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// Web animations are used if enabled specifically for this animation context, enabled
|
|
893
|
+
// globally via the build flag and fully supported by the browser
|
|
894
|
+
const useWebAnimations = (context._useWebAnimations || BM_USE_WEB_ANIMATIONS) && document.body.animate && !BM_WEB_ANIMATIONS_DISABLED;
|
|
853
895
|
|
|
854
896
|
// Allow each target to set its own options
|
|
855
897
|
var options = animationTargets[i].options ? BMCopyProperties({}, animation.options, animationTargets[i].options) : BMCopyProperties({}, animation.options);
|
|
@@ -865,9 +907,15 @@ export function BMAnimationApplyBlocking(blocking) {
|
|
|
865
907
|
delay += stride;
|
|
866
908
|
}
|
|
867
909
|
|
|
910
|
+
if (velocity && !useWebAnimations && !delay) {
|
|
911
|
+
// When velocity is used, if an element is already part of the velocity calls, clear out any properties
|
|
912
|
+
// that are part of this new animation
|
|
913
|
+
BMAnimationContext._prepareAnimationForNode(element, {withProperties: animationTargets[i].properties, options});
|
|
914
|
+
}
|
|
915
|
+
|
|
868
916
|
delete options.complete;
|
|
869
917
|
|
|
870
|
-
if (
|
|
918
|
+
if (useWebAnimations) {
|
|
871
919
|
if (options.queue) {
|
|
872
920
|
console.warn('[BMCoreUI] Using the queue animation option with web animations which is not supported. This argument will be ignored.');
|
|
873
921
|
}
|
|
@@ -1031,10 +1079,50 @@ export function BMAnimationApplyBlocking(blocking) {
|
|
|
1031
1079
|
}
|
|
1032
1080
|
}
|
|
1033
1081
|
else {
|
|
1034
|
-
promises.push(velocity.animate(element, animationTargets[i].properties, options));
|
|
1035
|
-
|
|
1036
1082
|
if (options.queue) {
|
|
1037
|
-
|
|
1083
|
+
console.warn(`Ignoring deprecated property "queue" for animation context.`);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
options.queue = false;
|
|
1087
|
+
|
|
1088
|
+
// If a delay is specified, use setTimeout as velocity leaks delayed animations
|
|
1089
|
+
if (options.delay) {
|
|
1090
|
+
const node = element;
|
|
1091
|
+
const properties = animationTargets[i].properties;
|
|
1092
|
+
const animationOptions = options;
|
|
1093
|
+
|
|
1094
|
+
promises.push(new Promise(async resolve => {
|
|
1095
|
+
const delay = options.delay;
|
|
1096
|
+
options.delay = undefined;
|
|
1097
|
+
const pendingAnimation = {node, properties, options: animationOptions, animationContext: context};
|
|
1098
|
+
|
|
1099
|
+
const timeout = setTimeout(async () => {
|
|
1100
|
+
// When the timeout expires, start the animation and remove it from the pending list for the element
|
|
1101
|
+
const pendingAnimations = BMAnimationContext._pendingAnimations.get(element) || [];
|
|
1102
|
+
const index = pendingAnimations?.indexOf(pendingAnimation) ?? -1;
|
|
1103
|
+
if (index != -1) {
|
|
1104
|
+
pendingAnimations.splice(index, 1);
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
// If there are no further pending animations remove the element from the map
|
|
1108
|
+
if (!pendingAnimation?.length) {
|
|
1109
|
+
BMAnimationContext._pendingAnimations.delete(element);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// Before starting the animation, ensure that no other animations affect this node's properties
|
|
1113
|
+
BMAnimationContext._prepareAnimationForNode(node, {withProperties: properties, options: animationOptions});
|
|
1114
|
+
const animationResult = await velocity.animate(node, properties, animationOptions);
|
|
1115
|
+
resolve(animationResult);
|
|
1116
|
+
}, delay);
|
|
1117
|
+
|
|
1118
|
+
// Store this animation as pending
|
|
1119
|
+
const pendingAnimations = BMAnimationContext._pendingAnimations.get(element) || [];
|
|
1120
|
+
pendingAnimations.push(pendingAnimation);
|
|
1121
|
+
BMAnimationContext._pendingAnimations.set(element, pendingAnimations);
|
|
1122
|
+
}));
|
|
1123
|
+
}
|
|
1124
|
+
else {
|
|
1125
|
+
promises.push(velocity.animate(element, animationTargets[i].properties, options));
|
|
1038
1126
|
}
|
|
1039
1127
|
}
|
|
1040
1128
|
}
|