bm-core-ui 2.7.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.
Files changed (99) hide show
  1. package/CHANGELOG.md +1624 -0
  2. package/LICENSE +21 -0
  3. package/README.md +145 -0
  4. package/build/@types/index.d.ts +14078 -0
  5. package/build/BMCodeEditor/BMCodeEditor.js +707 -0
  6. package/build/BMCollectionView/BMCollectionView.js +5861 -0
  7. package/build/BMCollectionView/BMCollectionViewCell.js +688 -0
  8. package/build/BMCollectionView/BMCollectionViewFlowLayout.js +4467 -0
  9. package/build/BMCollectionView/BMCollectionViewLayout.js +830 -0
  10. package/build/BMCollectionView/BMCollectionViewLayoutAttributes.js +673 -0
  11. package/build/BMCollectionView/BMCollectionViewMasonryLayout.js +491 -0
  12. package/build/BMCollectionView/BMCollectionViewStackLayout.js +634 -0
  13. package/build/BMCollectionView/BMCollectionViewTileLayout.js +1121 -0
  14. package/build/BMCoreUI.css +2833 -0
  15. package/build/BMView/BMAttributedLabelView.js +310 -0
  16. package/build/BMView/BMLayoutConstraint_v2.5.js +1813 -0
  17. package/build/BMView/BMLayoutGuide.js +192 -0
  18. package/build/BMView/BMLayoutSizeClass.js +466 -0
  19. package/build/BMView/BMMenu.js +574 -0
  20. package/build/BMView/BMScrollView.js +247 -0
  21. package/build/BMView/BMTextField.js +512 -0
  22. package/build/BMView/BMTextFieldDelegate.js +71 -0
  23. package/build/BMView/BMView_v2.5.js +3572 -0
  24. package/build/BMView/BMViewport.js +221 -0
  25. package/build/BMViewLayoutEditor/BMLayoutEditor.js +6117 -0
  26. package/build/BMViewLayoutEditor/BMLayoutEditorConstraintSettings.js +417 -0
  27. package/build/BMViewLayoutEditor/BMLayoutEditorDelegate.js +59 -0
  28. package/build/BMViewLayoutEditor/BMLayoutEditorSettingCells.js +1653 -0
  29. package/build/BMViewLayoutEditor/BMLayoutEditorSettings.js +1480 -0
  30. package/build/BMViewLayoutEditor/BMLayoutEditorSettingsComplexCells.js +431 -0
  31. package/build/BMViewLayoutEditor/BMLayoutEditorSettingsDelegate.js +46 -0
  32. package/build/BMViewLayoutEditor/BMLayoutEditorVariablesController.js +460 -0
  33. package/build/BMViewLayoutEditor/BMLayoutEditorViewGroupSettings.js +293 -0
  34. package/build/BMViewLayoutEditor/BMLayoutEditorViewSettings.js +382 -0
  35. package/build/BMViewLayoutEditor/BMLayoutVariableProvider.js +202 -0
  36. package/build/BMWindow/BMConfirmationPopup.js +477 -0
  37. package/build/BMWindow/BMKeyboardShortcut.js +151 -0
  38. package/build/BMWindow/BMPopover/BMPopover.js +492 -0
  39. package/build/BMWindow/BMToolWindow.js +71 -0
  40. package/build/BMWindow/BMWindow.js +2000 -0
  41. package/build/Core/BMAnimationContext.js +1181 -0
  42. package/build/Core/BMColor.js +991 -0
  43. package/build/Core/BMCoreUI.js +470 -0
  44. package/build/Core/BMFunctionCollection.js +110 -0
  45. package/build/Core/BMIndexPath.js +165 -0
  46. package/build/Core/BMInset.js +138 -0
  47. package/build/Core/BMKeyPath.js +100 -0
  48. package/build/Core/BMPoint.js +291 -0
  49. package/build/Core/BMRect.js +556 -0
  50. package/build/Core/BMSize.js +137 -0
  51. package/build/iScroll/LICENSE +22 -0
  52. package/build/iScroll/iscroll-probe.js +2154 -0
  53. package/build/images/AlignBottom.png +0 -0
  54. package/build/images/AlignCenterX.png +0 -0
  55. package/build/images/AlignCenterY.png +0 -0
  56. package/build/images/AlignLeading.png +0 -0
  57. package/build/images/AlignTop.png +0 -0
  58. package/build/images/AlignTrailing.png +0 -0
  59. package/build/images/AllConstraints.png +0 -0
  60. package/build/images/BottomConstraint.png +0 -0
  61. package/build/images/CenterXConstraint.png +0 -0
  62. package/build/images/CenterYConstraint.png +0 -0
  63. package/build/images/CoreUI2.png +0 -0
  64. package/build/images/CoreUI2@2x.png +0 -0
  65. package/build/images/Desktop.png +0 -0
  66. package/build/images/DesktopMini.png +0 -0
  67. package/build/images/EqualHeight.png +0 -0
  68. package/build/images/EqualHorizontalSpacing.png +0 -0
  69. package/build/images/EqualHorizontalSpacingInSuperview.png +0 -0
  70. package/build/images/EqualVerticalSpacing.png +0 -0
  71. package/build/images/EqualVerticalSpacingInSuperview.png +0 -0
  72. package/build/images/EqualWidth.png +0 -0
  73. package/build/images/HeightConstraint.png +0 -0
  74. package/build/images/InactiveConstraints.png +0 -0
  75. package/build/images/Layout.png +0 -0
  76. package/build/images/LayoutVariables.png +0 -0
  77. package/build/images/LeftConstraint.png +0 -0
  78. package/build/images/OwnConstraints.png +0 -0
  79. package/build/images/Phone.png +0 -0
  80. package/build/images/PhoneLandscape.png +0 -0
  81. package/build/images/PhoneLandscapeMini.png +0 -0
  82. package/build/images/PhoneMini.png +0 -0
  83. package/build/images/PhonePortrait.png +0 -0
  84. package/build/images/PhonePortraitMini.png +0 -0
  85. package/build/images/Properties.png +0 -0
  86. package/build/images/RightConstraint.png +0 -0
  87. package/build/images/SubviewConstraints.png +0 -0
  88. package/build/images/Tablet.png +0 -0
  89. package/build/images/TabletLandscape.png +0 -0
  90. package/build/images/TabletLandscapeMini.png +0 -0
  91. package/build/images/TabletMini.png +0 -0
  92. package/build/images/TabletPortrait.png +0 -0
  93. package/build/images/TabletPortraitMini.png +0 -0
  94. package/build/images/TopConstraint.png +0 -0
  95. package/build/images/WidthConstraint.png +0 -0
  96. package/build/index.js +40 -0
  97. package/lib/@types/BMCoreUI.min.d.ts +14078 -0
  98. package/lib/BMCoreUI.min.js +1 -0
  99. package/package.json +58 -0
@@ -0,0 +1,1181 @@
1
+ // @ts-check
2
+
3
+ import {YES, NO, BMNumberByInterpolatingNumbersWithFraction, BMCopyProperties} from './BMCoreUI'
4
+ import {BMFunctionCollectionMake} from './BMFunctionCollection'
5
+ import 'velocity-animate'
6
+
7
+
8
+ // When set to YES, this will cause animation contexts to use Velocity.js 2 as their animation engine
9
+ export const BM_USE_VELOCITY2 = NO;
10
+ // When set to YES, this will cause animation contexts to use the web animations api as their animation engine whenever possible
11
+ export var BM_USE_WEB_ANIMATIONS = NO;
12
+
13
+ /*
14
+ ****************************************************************************************************************************************************************
15
+ Animations
16
+ ****************************************************************************************************************************************************************
17
+ */
18
+
19
+
20
+
21
+ // @type BMAnimationSubscriber
22
+
23
+ /**
24
+ * An animation subscriber is used with animation contexts when multiple animation properties should be batched for the same animation target.<br/><br/>
25
+ * There is no constructor or prototype for animation subscribers. Instead, they may be any object that conforms to the subscriber specification.
26
+ */
27
+ //function BMAnimationSubscriber() {} // <constructor>
28
+
29
+ // BMAnimationSubscriber.prototype = {
30
+
31
+ /**
32
+ * This method is invoked by animation context
33
+ */
34
+ // applyForContext: function(context) {
35
+
36
+ // }
37
+
38
+ // @endtype
39
+
40
+ // @type BMAnimationController
41
+
42
+ /**
43
+ * A decorator that may be applied to properties to make them animatable using CoreUI.
44
+ * This decorator should be applied to properties whose type is a class that implements <code>BMAnimating</code>.
45
+ * When a property marked animatable is changed while an animation context is active, an animation will
46
+ * be registered to run for that property. Classes using this decorator must have a <code>node</code> property that
47
+ * returns the DOM node on which animations run.
48
+ *
49
+ * The property extended by this decorator must have a setter defined for it.
50
+ *
51
+ * Using this decorator will cause your class to gain a private underscore-prefixed version
52
+ * of the target property that will be used by CoreUI for storage, unless you also define
53
+ * a getter for the property.
54
+ * @param target <Object> The target object.
55
+ * @param key <String> The property to which this decorator will apply.
56
+ * @param descriptor <Object> The property descriptor of the target property.
57
+ */
58
+ export function BMAnimatable(target, key, descriptor) {
59
+
60
+ if (!descriptor.set) throw new Error('[BMCoreUI] Incorrectly applied BMAnimatable to property ' + key + ' that doesn\'t have a setter');
61
+
62
+ if (!descriptor.get) {
63
+ descriptor.get = function () { return this['_' + key]; };
64
+
65
+ var oldSet = descriptor.set;
66
+ descriptor.set = function (value) {
67
+ if (BMAnimationContextGetCurrent()) {
68
+ let controller = BMAnimationContextGetCurrent().controllerForObject(this, {node: this.node || document.body});
69
+ controller.registerAnimatableProperty(key, {targetValue: value.copy(), startingValue: this[key].copy()});
70
+ }
71
+ else {
72
+ oldSet.call(this, value);
73
+ this['_' + key] = value.copy();
74
+ }
75
+ }
76
+ }
77
+ else {
78
+ var oldSet = descriptor.set;
79
+ descriptor.set = function (value) {
80
+ if (BMAnimationContextGetCurrent()) {
81
+ let controller = BMAnimationContextGetCurrent().controllerForObject(this, {node: this.node || document.body});
82
+ controller.registerAnimatableProperty(key, {targetValue: value.copy(), startingValue: this[key].copy()});
83
+ }
84
+ else {
85
+ oldSet.call(this, value);
86
+ }
87
+ }
88
+ }
89
+
90
+ }
91
+
92
+ /**
93
+ * A decorator that may be applied to properties to make them animatable using CoreUI.
94
+ * This decorator should be applied to properties whose type is a number.
95
+ * When a property marked animatable is changed while an animation context is active, an animation will
96
+ * be registered to run for that property. Classes using this decorator must have a <code>node</code> property that
97
+ * returns the DOM node on which animations run.
98
+ *
99
+ * The property extended by this decorator must have a setter defined for it.
100
+ *
101
+ * Using this decorator will cause your class to gain a private underscore-prefixed version
102
+ * of the target property that will be used by CoreUI for storage, unless you also define
103
+ * a getter for the property.
104
+ * @param target <Object> The target object.
105
+ * @param key <String> The property to which this decorator will apply.
106
+ * @param descriptor <Object> The property descriptor of the target property.
107
+ */
108
+ export function BMAnimatableNumber(target, key, descriptor) {
109
+
110
+ if (!descriptor.set) throw new Error('[BMCoreUI] Incorrectly applied BMAnimatable to property ' + key + ' that doesn\'t have a setter');
111
+
112
+ if (!descriptor.get) {
113
+ descriptor.get = function () { return this['_' + key]; };
114
+
115
+ var oldSet = descriptor.set;
116
+ descriptor.set = function (value) {
117
+ if (BMAnimationContextGetCurrent()) {
118
+ let controller = BMAnimationContextGetCurrent().controllerForObject(this, {node: this.node || document.body});
119
+ controller.registerOwnProperty(key, {targetValue: value, startingValue: this[key] || 0});
120
+ }
121
+ else {
122
+ oldSet.call(this, value);
123
+ this['_' + key] = value;
124
+ }
125
+ }
126
+ }
127
+ else {
128
+ var oldSet = descriptor.set;
129
+ descriptor.set = function (value) {
130
+ if (BMAnimationContextGetCurrent()) {
131
+ let controller = BMAnimationContextGetCurrent().controllerForObject(this, {node: this.node || document.body});
132
+ controller.registerOwnProperty(key, {targetValue: value, startingValue: this[key] || 0});
133
+ }
134
+ else {
135
+ oldSet.call(this, value);
136
+ }
137
+ }
138
+ }
139
+
140
+ }
141
+
142
+ /**
143
+ * An animation controller is an object that makes it easier to integrate custom properties with the animation engine.
144
+ *
145
+ * Animation controllers are never created explicitly, instead all animation contexts provide a method that creates
146
+ * an animation controller for an object. After retrieving an animation controller, you may use it to register either regular
147
+ * CSS/transform properties or custom properties with an update handler.
148
+ * To retrieve an animation controller for an object, invoke the `controllerForObject(_)` method on the active animation context,
149
+ * passing in the caller object as the parameter. If a previous animation controller was already retrieved for that object, the
150
+ * method will return that existing instance already.
151
+ *
152
+ * Besides the animation controller, in supported environments you may annotate your properties with the
153
+ * <code>@BMAnimatable</code> or <code>@BMAnimatableNumber</code> decorators. For properties annotated in this way,
154
+ * CoreUI automatically handles checking for animation conexts, retrieving animation controllers and setting up
155
+ * progress handlers.
156
+ */
157
+ export function BMAnimationController() {} // <constructor>
158
+
159
+ BMAnimationController.prototype = {
160
+
161
+ /**
162
+ * The animation context to which this animation controller applies.
163
+ */
164
+ _animation: undefined, // <BMAnimationContext>
165
+
166
+ /**
167
+ * The object for which this animation controller was created.
168
+ */
169
+ _owner: undefined, // <AnyObject>
170
+
171
+ /**
172
+ * The DOM node on which the animation will run.
173
+ */
174
+ _node: undefined, // <DOMNode>
175
+
176
+ /**
177
+ * A promise that resolves when the animation initiated by this controller finishes.
178
+ */
179
+ _promise: undefined, // <Promise<Void>>
180
+
181
+ get promise() {
182
+ return this._promise;
183
+ },
184
+
185
+ /**
186
+ * Used internally to resolve the promise used by this controller.
187
+ */
188
+ _resolve: undefined, // <Function>
189
+
190
+ /**
191
+ * An object containing the properties that are registered to this animation controller.
192
+ * For standard properties, the key name is the property name and its value is the usual
193
+ * `Velocity.js` value.
194
+ * For custom properties, a single `tween` property is created whose value is another object where
195
+ * its keys are the names of the custom properties and their values are functions that control what
196
+ * happens when the property value is updated.
197
+ */
198
+ _properties: undefined, // <Object<String, AnyObject>>
199
+
200
+ /**
201
+ * Initializes this animation controller with the given owner and animation context.
202
+ * @param animation <BMAnimationContext> The animation context to which this controller will apply.
203
+ * {
204
+ * @param owner <AnyObject> The object to which this animation controller is associated.
205
+ * @param node <DOMNode> The DOM node upon which the animation will run.
206
+ * }
207
+ * @return <BMAnimationController> This animation controller.
208
+ */
209
+ initWithAnimation(animation, args) {
210
+ this._animation = animation;
211
+ this._owner = args.owner;
212
+ this._node = args.node;
213
+ this._properties = {};
214
+ this._promise = new Promise(resolve => this._resolve = resolve);
215
+ return this;
216
+ },
217
+
218
+ /**
219
+ * Registers an animation that will run on the given standard CSS or transform property.
220
+ * @param property <String> The name of the property.
221
+ * {
222
+ * @param withValue <AnyObject> The value to which the property's value will animate or any of Velocity's animation syntaxes.
223
+ * }
224
+ */
225
+ registerBuiltInProperty(property, args) {
226
+ this._properties[property] = args.withValue;
227
+ },
228
+
229
+ /**
230
+ * Registers an animation that will run on the given standard CSS or transform properties.
231
+ * @param properties <Dictionary<AnyObject>> A dictionary whose keys are property names and their values
232
+ * are the values to which each property will animate.
233
+ */
234
+ registerBuiltInPropertiesWithDictionary(properties) {
235
+ for (let key in properties) this.registerBuiltInProperty(key, {withValue: properties[key]});
236
+ },
237
+
238
+ /**
239
+ * Registers an animation that will run on the given custom property.
240
+ * @param property <String> The name of the custom property.
241
+ * {
242
+ * @param withHandler <void ^(number, number)>
243
+ * A handler that is invoked on each animation frame, where the developer should perform their changes.
244
+ * This handler is passed the following parameters:
245
+ * * __fraction__: <Number> - The animation completion percentage. This will typically be a number between 0 and 1,
246
+ * however for animations that overshoot or undershoot their values, this completion
247
+ * fraction may surpass those values as well.
248
+ * * __value__: <Number, nullable> - Supplied if the property was registered with a starting and ending value.
249
+ * Represents the current interpolated value.
250
+ * @param startingValue <Number, nullable> An optional starting value from which the property will animate.
251
+ * If this argument is specified, `targetValue` should also be specified.
252
+ * @param targetValue <Number, nullable> An optional ending value to which the property will animate.
253
+ * If this argument is specified, `startingValue` should also be specified.
254
+ * }
255
+ */
256
+ registerCustomProperty(property, args) {
257
+ if (!this._properties.tween) this._properties.tween = {};
258
+
259
+ if (BM_USE_WEB_ANIMATIONS) console.warn(`[BMAnimationController] Registering custom property ${property} with handler ${args.withHandler} which will run in legacy mode.`);
260
+
261
+ this._properties.tween[property] = {
262
+ handler: args.withHandler,
263
+ startingValue: args.startingValue,
264
+ targetValue: args.targetValue,
265
+ BMAnimatable: NO
266
+ }
267
+ },
268
+
269
+ /**
270
+ * Registers an animation that will run on one of the target object's own properties.
271
+ * @param property <String> The name of the custom property.
272
+ * {
273
+ * @param targetValue <Number> The value to which this property will animate.
274
+ * @param startingValue <Number, nullable> Defaults to the property's value at the time when the animation begins.
275
+ * An optional starting value from which the property will animate.
276
+ * }
277
+ */
278
+ registerOwnProperty(property, args) {
279
+ if (!this._properties.tween) this._properties.tween = {};
280
+
281
+ if (BM_USE_WEB_ANIMATIONS) console.warn(`[BMAnimationController] Registering own property ${property} which will run in legacy mode.`);
282
+
283
+ var self = this;
284
+
285
+ this._properties.tween[property] = {
286
+ handler: (fraction, value) => {
287
+ self._owner[property] = value;
288
+ },
289
+ startingValue: args.startingValue,
290
+ targetValue: args.targetValue,
291
+ name: property,
292
+ BMAnimatable: NO
293
+ }
294
+ },
295
+
296
+ /**
297
+ * Registers an animation that will run on one of the target object's own properties.
298
+ * @param property <String> The name of the custom property.
299
+ * {
300
+ * @param targetValue <BMAnimating> The value to which this property will animate.
301
+ * @param startingValue <BMAnimating, nullable> Defaults to the property's value at the time when the animation begins.
302
+ * An optional starting value from which the property will animate.
303
+ * }
304
+ */
305
+ registerAnimatableProperty(property, args) {
306
+ if (!this._properties.tween) this._properties.tween = {};
307
+
308
+ if (BM_USE_WEB_ANIMATIONS) console.warn(`[BMAnimationController] Registering animatable property ${property} which will run in legacy mode.`);
309
+
310
+ var self = this;
311
+
312
+ this._properties.tween[property] = {
313
+ // For types that implement BMAnimating, CoreUI will handle the interpolation
314
+ handler: (fraction, value) => {
315
+ self._owner[property] = value;
316
+ },
317
+ startingValue: args.startingValue,
318
+ targetValue: args.targetValue,
319
+ name: property,
320
+ BMAnimatable: YES
321
+ }
322
+ },
323
+
324
+ // @override - BMAnimationSubscriber
325
+ apply(animation) {
326
+ // All properties other than tween use the default Velocity.js value types
327
+ this._options = {
328
+ complete: () => {
329
+ this._resolve();
330
+ }
331
+ };
332
+
333
+ if ('tween' in this._properties) {
334
+
335
+ // Tween is converted into a single property, with the progress handler taking care of
336
+ // actually applying the properties
337
+ var value = this._properties.tween;
338
+ this._properties.tween = [1, 0];
339
+
340
+ var self = this;
341
+ var progressHandler = BMFunctionCollectionMake();
342
+ Object.getOwnPropertyNames(value).forEach((key) => {
343
+ var property = value[key];
344
+ if (!property.name) {
345
+ if (typeof property.startingValue == 'number' && typeof property.targetValue == 'number') {
346
+ progressHandler.push((elements, complete, remaining, start, fraction) => {
347
+ property.handler(fraction, BMNumberByInterpolatingNumbersWithFraction(property.startingValue, property.targetValue, fraction));
348
+ });
349
+ }
350
+ else {
351
+ progressHandler.push((elements, complete, remaining, start, fraction) => {
352
+ property.handler(fraction);
353
+ });
354
+ }
355
+ }
356
+ else if (property.BMAnimatable) {
357
+ var startingValue = property.startingValue;
358
+ if (!startingValue) {
359
+ startingValue = self._owner[property.name].copy();
360
+ }
361
+ progressHandler.push((elements, complete, remaining, start, fraction) => {
362
+ property.handler(fraction, startingValue.interpolatedValueWithFraction(fraction, {toValue: property.targetValue}));
363
+ });
364
+ }
365
+ else {
366
+ var startingValue = property.startingValue;
367
+ if (startingValue === undefined) {
368
+ startingValue = self._owner[property.name];
369
+ }
370
+ progressHandler.push((elements, complete, remaining, start, fraction) => {
371
+ property.handler(fraction, BMNumberByInterpolatingNumbersWithFraction(startingValue, property.targetValue, fraction));
372
+ });
373
+ }
374
+ });
375
+
376
+ this._options.progress = progressHandler;
377
+ }
378
+
379
+ animation.targets.push({element: this._node, properties: this._properties, options: this._options});
380
+ }
381
+
382
+ };
383
+
384
+ // @endtype
385
+
386
+ // @type interface BMAnimationTarget
387
+
388
+ /**
389
+ * This interface represents an object that specifies a portion of an animation.
390
+ */
391
+ // function BMAnimationTarget() {} // <constructor>
392
+
393
+ // {
394
+
395
+ /**
396
+ * The jQuery element that will be affected by this animation.
397
+ */
398
+ // element: undefined, // <$>
399
+
400
+ /**
401
+ * A dictionary of properties that will be changed by the animation.
402
+ */
403
+ // properties: undefined, // <Dictionary<any>>
404
+
405
+ /**
406
+ * An optional map of options that will override the animation context's options.
407
+ */
408
+ // options: undefined, // <Dictionary<any>, nullable>
409
+
410
+ // }
411
+
412
+ // @endtype
413
+
414
+
415
+ // @type BMAnimationEasing extends String
416
+
417
+ /**
418
+ * An enum containing predefined easings. These all resolve to bezier curves that are compatible
419
+ * with the Web Animations API.
420
+ */
421
+ const BMAnimationEasing = Object.freeze({ // <enum>
422
+ ease: "cubic-bezier(0.25, 0.1, 0.25, 1)",
423
+ easeIn: "cubic-bezier(0.42, 0, 1, 1)",
424
+ easeOut: "cubic-bezier(0, 0, 0.58, 1)",
425
+ easeInOut: "cubic-bezier(0.42, 0, 0.58, 1)",
426
+ easeInSine: "cubic-bezier(0.47, 0, 0.745, 0.715)",
427
+ easeOutSine: "cubic-bezier(0.39, 0.575, 0.565, 1)",
428
+ easeInOutSine: "cubic-bezier(0.445, 0.05, 0.55, 0.95)",
429
+ easeInQuad: "cubic-bezier(0.55, 0.085, 0.68, 0.53)",
430
+ easeOutQuad: "cubic-bezier(0.25, 0.46, 0.45, 0.94)",
431
+ easeInOutQuad: "cubic-bezier(0.455, 0.03, 0.515, 0.955)",
432
+ easeInCubic: "cubic-bezier(0.55, 0.055, 0.675, 0.19)",
433
+ easeOutCubic: "cubic-bezier(0.215, 0.61, 0.355, 1)",
434
+ easeInOutCubic: "cubic-bezier(0.645, 0.045, 0.355, 1)",
435
+ easeInQuart: "cubic-bezier(0.895, 0.03, 0.685, 0.22)",
436
+ easeOutQuart: "cubic-bezier(0.165, 0.84, 0.44, 1)",
437
+ easeInOutQuart: "cubic-bezier(0.77, 0, 0.175, 1)",
438
+ easeInQuint: "cubic-bezier(0.755, 0.05, 0.855, 0.06)",
439
+ easeOutQuint: "cubic-bezier(0.23, 1, 0.32, 1)",
440
+ easeInOutQuint: "cubic-bezier(0.86, 0, 0.07, 1)",
441
+ easeInExpo: "cubic-bezier(0.95, 0.05, 0.795, 0.035)",
442
+ easeOutExpo: "cubic-bezier(0.19, 1, 0.22, 1)",
443
+ easeInOutExpo: "cubic-bezier(1, 0, 0, 1)",
444
+ easeInCirc: "cubic-bezier(0.6, 0.04, 0.98, 0.335)",
445
+ easeOutCirc: "cubic-bezier(0.075, 0.82, 0.165, 1)",
446
+ easeInOutCirc: "cubic-bezier(0.785, 0.135, 0.15, 0.86)"
447
+ });
448
+
449
+ // @endtype
450
+
451
+ // These values are used to combine transform properties into a single transform string
452
+ /* @private */ const BMAnimationTransformPropertyDefaults = Object.freeze({
453
+ scaleX: 1,
454
+ scaleY: 1,
455
+ scaleZ: 1,
456
+ rotate: 0,
457
+ rotateX: 0,
458
+ rotateY: 0,
459
+ rotateZ: 0,
460
+ skewX: 0,
461
+ skewY: 0,
462
+ skewZ: 0,
463
+ translateZ: 0,
464
+ translateX: 0,
465
+ translateY: 0
466
+ });
467
+
468
+ // These values are used to combine filter properties into a single filter string
469
+ /* @private */ const BMAnimationFilterPropertyDefaults = Object.freeze({
470
+ blur: 1,
471
+ brightness: 1,
472
+ contrast: 1,
473
+ 'drop-shadow': 0,
474
+ grayscale: 0,
475
+ 'hue-rotate': 0,
476
+ invert: 0,
477
+ saturate: 0,
478
+ sepia: 0
479
+ });
480
+
481
+ // Convenience method used in converting from velocity calls to BMAnimationContext - only used internally.
482
+ // This uses almost the same syntax as velocity js but supports some of the features of BMAnimationContext, such as using web animations.
483
+ export function __BMVelocityAnimate(node, properties, options, useWebAnimations) {
484
+ return BMAnimateWithBlock(() => {
485
+ let controller = BMAnimationContextGetCurrent().controllerForObject(node, {node: node});
486
+ controller.registerBuiltInPropertiesWithDictionary(properties);
487
+
488
+ if (useWebAnimations) BMAnimationContextEnableWebAnimations();
489
+ }, options);
490
+ }
491
+
492
+ // @type BMAnimationContext
493
+
494
+ /**
495
+ * Allows using <code>$.Velocity.hook</code> by passing in a key-value object similar to `$.fn.css`.
496
+ * @param element <$ or DOMNode> The jQuery element or DOM node on which to apply the properties.
497
+ * @param properties <Object> The properties map.
498
+ */
499
+ export function BMHook(element, properties) {
500
+ if (BM_USE_VELOCITY2) {
501
+ let node = element;
502
+ if (element instanceof window.$) {
503
+ node = element[0];
504
+ }
505
+
506
+ // In Velocity 2.0 mode, transforms are no longer supported as individual properties and old .hook() function is gone
507
+ // In this case, use the same principle as web animations, combining transform and filter properties and applying them
508
+ // as standard CSS properties
509
+ let webAnimationProperties = {};
510
+
511
+ let transformProperty = '';
512
+ for (let key in properties) {
513
+ if (key in BMAnimationTransformPropertyDefaults) {
514
+ transformProperty += `${key}(${properties[key]}) `;
515
+ }
516
+ else {
517
+ webAnimationProperties[key] = properties[key];
518
+ }
519
+ }
520
+ if (transformProperty) webAnimationProperties.transform = transformProperty;
521
+
522
+ let filterProperty = '';
523
+ for (let key in properties) {
524
+ if (key in BMAnimationFilterPropertyDefaults) {
525
+ filterProperty += `${key}(${properties[key]}) `;
526
+ }
527
+ }
528
+ if (filterProperty) webAnimationProperties.filter = filterProperty;
529
+
530
+ BMCopyProperties(node.style, webAnimationProperties);
531
+ }
532
+ else {
533
+ for (var key in properties) {
534
+ (window.Velocity || $.Velocity).hook(element, key, properties[key]);
535
+ }
536
+ }
537
+ }
538
+
539
+ /**
540
+ * An animation context manages the options and animated elements for an animation.
541
+ * Animation contexts are never created explicitly, instead they are created and activated in the background by
542
+ * <code>BMAnimationBeginWithDuration()</code> or <code>BMAnimateWithBlock()</code>.
543
+ *
544
+ * While there is an active animation context, changing compatible properties will be done through an animation, using
545
+ * that context's animation options.
546
+ *
547
+ * To support animating with animation contexts, the current animation context may be retrieved by invoking the global <code>BMAnimationContextGetCurrent()</code>
548
+ * function. This will return the current animation context if one is active. That context may be used to register animations in response to property changes.
549
+ */
550
+ export function BMAnimationContext() { // <constructor>
551
+ throw new Error("Animation contexts may not be created manually. To create an animation context, invoke the BMAnimationBeginWithDuration() function.");
552
+ }
553
+
554
+ BMAnimationContext.prototype = {
555
+
556
+ /**
557
+ * @private
558
+ * The animation options for this context.
559
+ */
560
+ options: {}, // <Object>
561
+
562
+ /**
563
+ * @private
564
+ * A map containing the callbacks for animations that are registered and should be applied when this animation begins.
565
+ * The keys in this map may be any type of object and their values must be objects that contain the <code>apply</code> method which will
566
+ * be invoked when this animation is about to begin.
567
+ */
568
+ subscribers: undefined, // <Map<AnyObject, BMAnimationSubscriber>>
569
+
570
+ /**
571
+ * Returns an animation controller for the given object. If an animation controller was previously requested
572
+ * for this object for this animation, this method will return that previously created controller.
573
+ * @param object <AnyObject> The object which will make use of the animation controller.
574
+ * {
575
+ * @param node <DOMNode> The node upon which the animation will run.
576
+ * }
577
+ * @return <BMAnimationController> An animation controller.
578
+ */
579
+ controllerForObject(object, args) {
580
+ // Get the current subscriber for this object
581
+ let subscriber = this.subscribers.get(object);
582
+
583
+ if (!subscriber) {
584
+ // If one isn't available, create it and associate it to this object
585
+ subscriber = Object.create(BMAnimationController.prototype).initWithAnimation(this, {owner: object, node: args.node});
586
+ this.subscribers.set(object, subscriber);
587
+ }
588
+
589
+ return subscriber;
590
+ },
591
+
592
+ /**
593
+ * @private
594
+ * An array containing the animation targets for the current context.
595
+ * An animation target is an object with the following three properties:
596
+ * <ul>
597
+ * <li>element &lt;$&gt;: The jQuery node to which the animation should be applied.</li>
598
+ * <li>properties &lt;Object&gt;: An object containing the node properties which will be animated.</li>
599
+ * <li>options &lt;Object&gt;: An optional object containing animation property overrides.</li>
600
+ * </ul>
601
+ */
602
+ targets: undefined, // <[BMAnimationTarget]>
603
+
604
+ /**
605
+ * Should be invoked to register an animation that will run when this animation context is started.
606
+ * @param target <$ or DOMNode> The DOM node or jQuery wrapper on which this animation will run.
607
+ * {
608
+ * @param properties <Object<String, AnyObject>> An object describing the properties that will be changed by this animation.
609
+ * This object has the same format as the Velocity.js property object.
610
+ * @param options <nullable Object<String, AnyObject>> An optional object describing the animation options that this particular animation should use.
611
+ * Specifying this parameter will cause the animation context's animation options to be overriden for this animation.
612
+ * }
613
+ */
614
+ registerAnimationForTarget: function(target, args) {
615
+ this.targets.push({
616
+ element: target,
617
+ properties: args.properties,
618
+ options: args.options
619
+ });
620
+ },
621
+
622
+ registerSubscriber: function(subscriber, args) {
623
+
624
+ }
625
+
626
+ }
627
+
628
+ /**
629
+ * The animation stack holds all animations with their attributes.
630
+ * Whenever an attribute property is changed while there is an active animation, that property
631
+ * will smoothly interpolate to the new value using the top-most animation's attributes.
632
+ */
633
+ var _BMAnimationStack = []; // <[BMAnimationContext]>
634
+
635
+ /**
636
+ * Retrieves the currently active animation context, if there is one.
637
+ * @return <BMAnimationContext, nullable> The current animation context if there is one, `undefined` otherwise or if the current animation context
638
+ * is static.
639
+ */
640
+ export function BMAnimationContextGetCurrent() {
641
+ let context = _BMAnimationStack[_BMAnimationStack.length - 1];
642
+
643
+ if (context && context._isDisabled) {
644
+ return;
645
+ }
646
+ else {
647
+ return context;
648
+ }
649
+ }
650
+
651
+ /**
652
+ * Causes the current animation context to run in web animations mode, if available.
653
+ * If no animation context is currently active, this method does nothing.
654
+ */
655
+ export function BMAnimationContextEnableWebAnimations() {
656
+ let context = BMAnimationContextGetCurrent();
657
+ if (context) context._useWebAnimations = YES;
658
+ }
659
+
660
+ /**
661
+ * Should be invoked to start a new static attribute animation.
662
+ * A static animation context supresses any existing animation context, causing property updates while it is active to not be animated.
663
+ * While a static animation context is active, `BMAnimationContextGetCurrent()` returns `undefined`.
664
+ *
665
+ * Like with regular animation contexts, static contexts must be applied via `BMAnimationApply()` or `BMAnimationApplyBlocking(_)`.
666
+ */
667
+ export function BMAnimationContextBeginStatic() {
668
+
669
+ var animationContext = Object.create(BMAnimationContext.prototype);
670
+
671
+ animationContext.options = {duration: 0, easing: 'linear'};
672
+ animationContext.targets = [];
673
+ animationContext._isDisabled = YES;
674
+ // The subscribers property is used internally by cells and views that need to interact with the animation before it is applied
675
+ // It is a map of objects where cells and views add themselves as keys with arbitrary values.
676
+ // The subscriber value objects however must contain an 'apply()' method; this method will be invoked by the animation when it is about to be applied.
677
+ animationContext.subscribers = new Map();
678
+
679
+ _BMAnimationStack.push(animationContext);
680
+
681
+ return animationContext;
682
+
683
+ }
684
+
685
+
686
+ // @param easing <Multiple Types> The animation's easing, using any of Velocity.js supported easing formats.
687
+ // @param ... <> Additional Velocity.js parameters
688
+
689
+ /**
690
+ * Should be invoked to start a new attribute animation.
691
+ * After this call, you should assign the new values to the attributes you want to animate
692
+ * and finally call <code>BMAnimationApply()</code> to start the animations.
693
+ * You may call <code>BMAnimationBeginWithDuration()</code> multiple times in a row to set up multiple animations, but each call must be balanced
694
+ * by calling <code>BMAnimationApply()</code>.
695
+ * @param duration <Int> The animation's duration, in milliseconds.
696
+ * @param options <Object, nullable> An object of animation attributes. This object is optional and contains the same keys and values as Velocity.js's animation options object.
697
+ * This object should not be modified afterwards until this animation is applied.
698
+ * @return <BMAnimationContext> The animation context associated with the new animation.
699
+ */
700
+ export function BMAnimationBeginWithDuration(duration, options) {
701
+ options = options || {};
702
+ options.duration = duration;
703
+
704
+ var animationContext = Object.create(BMAnimationContext.prototype);
705
+
706
+ animationContext.options = options;
707
+ animationContext.targets = [];
708
+ // The subscribers property is used internally by cells and views that need to interact with the animation before it is applied
709
+ // It is a map of objects where cells and views add themselves as keys with arbitrary values.
710
+ // The subscriber value objects however must contain an 'apply()' method; this method will be invoked by the animation when it is about to be applied.
711
+ animationContext.subscribers = new Map();
712
+
713
+ _BMAnimationStack.push(animationContext);
714
+
715
+ return animationContext;
716
+ }
717
+
718
+ /**
719
+ * Registers a completion handler that will fire when the current animation context has finished running its animation.
720
+ * If there is no current animation context or if the current animation context is static, the provided completion handler will
721
+ * execute synchronously before this method returns.
722
+ * @param handler <void ^()> The handler to invoke.
723
+ */
724
+ export function BMAnimationContextAddCompletionHandler(handler) {
725
+ let context;
726
+ if (context = BMAnimationContextGetCurrent()) {
727
+ if (context.options.complete) {
728
+ if (context.options.complete._isFunctionCollection) {
729
+ context.options.complete.push(handler);
730
+ }
731
+ else {
732
+ let functionCollection = BMFunctionCollectionMake();
733
+ functionCollection.push(context.options.complete);
734
+ functionCollection.push(handler);
735
+ context.options.complete = functionCollection;
736
+ }
737
+ }
738
+ else {
739
+ context.options.complete = BMFunctionCollectionMake();
740
+ context.options.complete.push(handler);
741
+ }
742
+ }
743
+ else {
744
+ handler();
745
+ }
746
+ }
747
+
748
+ /**
749
+ * Must be invoked after a <code>BMAnimationBeginWithDuration()</code> call to apply the pending animation.
750
+ * @return <Promise<void>> A promise that resolves when the animation completes.
751
+ */
752
+ export function BMAnimationApply() {
753
+ return BMAnimationApplyBlocking(NO);
754
+ }
755
+
756
+ // Set to `YES` if the environment does not fully support web animations
757
+ var BM_WEB_ANIMATIONS_DISABLED = NO;
758
+
759
+ /**
760
+ * Must be invoked after a <code>BMAnimationBeginWithDuration()</code> call to apply the pending animation.
761
+ * Applying the animation in this way will stop all other running animations on the animation targets.
762
+ * @param blocking <Boolean, nullable> Defaults to `YES`. If set to `YES`, the animation will be blocking, otherwise it will be scheduled.
763
+ * A blocking animation will cancel all other animations currently running on any of the target elements.
764
+ * @return <Promise<void>> A promise that resolves when the animation completes.
765
+ */
766
+ export function BMAnimationApplyBlocking(blocking) {
767
+ // If the current context is static, pop it allowing other animation contexts to run
768
+ let context = _BMAnimationStack[_BMAnimationStack.length - 1];
769
+ if (!context) {
770
+ console.error('Attempted to apply an animation while there was no animation context active. This method call will be ignored.');
771
+ return Promise.resolve(void 0);
772
+ }
773
+ if (context._isDisabled) {
774
+ _BMAnimationStack.pop();
775
+ return Promise.resolve(void 0);
776
+ }
777
+
778
+ if (blocking === undefined) blocking = YES;
779
+
780
+ // Give the subscribers a chance to modify the animation prior to it actually being applied
781
+ new Map(BMAnimationContextGetCurrent().subscribers).forEach(function (value, key, map) {
782
+ value.prepare && value.prepare(animation);
783
+ });
784
+
785
+ var animation = _BMAnimationStack.pop();
786
+ var animationTargets = animation.targets;
787
+
788
+ // Notify the subscribers that the animation is about to be applied
789
+ var animationSubscribers = animation.subscribers;
790
+ animationSubscribers.forEach(function (value, key, map) {
791
+ value.apply(animation);
792
+ });
793
+
794
+ // The complete callback should only be invoked once
795
+ // when the last element finishes animating
796
+ var completeCallback;
797
+ var completeAnimations = NO;
798
+ if (animation.options.complete) {
799
+ var optionsCompleteCallback = animation.options.complete;
800
+ completeCallback = async function (elements) {
801
+ if (completeAnimations) return;
802
+ completeAnimations = YES;
803
+
804
+ // Set timeout is used to schedule the callback to after all animations in the set have finished
805
+ await 0;
806
+ optionsCompleteCallback(elements);
807
+
808
+ for (var i = 0; i < animationTargetsLength; i++) {
809
+ if (animationTargets[i].options && animationTargets[i].options.complete) {
810
+ animationTargets[i].options.complete(elements);
811
+ }
812
+ else if (animationTargets[i].complete) {
813
+ animationTargets[i].complete(elements);
814
+ }
815
+ }
816
+ }
817
+ }
818
+ else {
819
+ completeCallback = async function (elements) {
820
+ if (completeAnimations) return;
821
+ completeAnimations = YES;
822
+
823
+ // Set timeout is used to schedule the callback to after all animations in the set have finished
824
+ await 0;
825
+ for (var i = 0; i < animationTargetsLength; i++) {
826
+ if (animationTargets[i].options && animationTargets[i].options.complete) {
827
+ animationTargets[i].options.complete(elements);
828
+ }
829
+ else if (animationTargets[i].complete) {
830
+ animationTargets[i].complete(elements);
831
+ }
832
+ }
833
+ }
834
+ }
835
+ animation.options.complete = completeCallback;
836
+
837
+ if (window.event && window.event.shiftKey) {
838
+ animation.options.duration = animation.options.duration * 5;
839
+ window.event.preventDefault();
840
+ }
841
+
842
+ var stride = animation.options.stride;
843
+ var delay = animation.options.delay || 0;
844
+
845
+ var velocity = window.Velocity || $.Velocity;
846
+ var promises = [];
847
+
848
+ // An array to which web animations are added to set their start time to the same value
849
+ let webAnimations = [];
850
+
851
+ // Fire all the animations
852
+ var animationTargetsLength = animation.targets.length;
853
+ for (var i = 0; i < animationTargetsLength; i++) {
854
+ var element = animationTargets[i].element;
855
+
856
+ if (blocking) velocity(element, 'stop', true);
857
+
858
+ // Allow each target to set its own options
859
+ var options = animationTargets[i].options ? BMCopyProperties({}, animation.options, animationTargets[i].options) : BMCopyProperties({}, animation.options);
860
+
861
+ if (stride) {
862
+ options = BMCopyProperties({}, options);
863
+
864
+ if (i < animationTargetsLength - 1) {
865
+ delete options.complete;
866
+ }
867
+
868
+ options.delay = delay;
869
+ delay += stride;
870
+ }
871
+
872
+ delete options.complete;
873
+
874
+ if ((context._useWebAnimations || BM_USE_WEB_ANIMATIONS) && document.body.animate && !BM_WEB_ANIMATIONS_DISABLED) {
875
+ if (options.queue) {
876
+ console.warn('[BMCoreUI] Using the queue animation option with web animations which is not supported. This argument will be ignored.');
877
+ }
878
+
879
+ // For web animations, extract all non-tween properties and use web animations api on them
880
+ // also unify all transform and filter properties into a single transform property
881
+ let webAnimationProperties = {};
882
+
883
+ // Extract and unify the transform properties
884
+ let sourceTransformProperty = '';
885
+ let transformProperty = '';
886
+ for (let key in animationTargets[i].properties) {
887
+ if (key in BMAnimationTransformPropertyDefaults) {
888
+ // Specify an initial value if the property value is forcefed
889
+ if (Array.isArray(animationTargets[i].properties[key])) {
890
+ transformProperty += `${key}(${animationTargets[i].properties[key][0]}) `;
891
+ sourceTransformProperty += `${key}(${animationTargets[i].properties[key][1]}) `;
892
+ }
893
+ else {
894
+ transformProperty += `${key}(${animationTargets[i].properties[key]}) `;
895
+ }
896
+ }
897
+ }
898
+
899
+ // If a transform property was created, prepare it for web animations
900
+ if (transformProperty) {
901
+ // Specify the initial forcefed value if it existed
902
+ if (sourceTransformProperty) {
903
+ webAnimationProperties.transform = [transformProperty, sourceTransformProperty];
904
+ }
905
+ else {
906
+ webAnimationProperties.transform = transformProperty;
907
+ }
908
+ }
909
+
910
+ // Perform the same for filter properties
911
+ let filterProperty = '';
912
+ for (let key in animationTargets[i].properties) {
913
+ if (key in BMAnimationFilterPropertyDefaults) {
914
+ filterProperty += `${key}(${animationTargets[i].properties[key]}) `;
915
+ }
916
+ }
917
+ if (filterProperty) webAnimationProperties.filter = filterProperty;
918
+
919
+ // Add all the other properties
920
+ for (let key in animationTargets[i].properties) {
921
+ if ((key in BMAnimationTransformPropertyDefaults) || (key in BMAnimationFilterPropertyDefaults)) continue;
922
+ if (key == 'tween') continue;
923
+ webAnimationProperties[key] = animationTargets[i].properties[key];
924
+ }
925
+
926
+ // Set up the animation
927
+ let node = element;
928
+ if (element instanceof window.$) {
929
+ node = element[0];
930
+ }
931
+
932
+ if (options.display == 'block') {
933
+ node.style.display = 'block';
934
+ }
935
+
936
+ let sourceAnimationProperties = {};
937
+
938
+ for (let key in webAnimationProperties) {
939
+ if (Array.isArray(webAnimationProperties[key])) {
940
+ // When the parameter is an array, this is interpreted as forcefeeding an initial value in velocity js
941
+ sourceAnimationProperties[key] = webAnimationProperties[key][1];
942
+ webAnimationProperties[key] = webAnimationProperties[key][0];
943
+ // Apply the forcefed value to the node initially, if there is any delay
944
+ if (options.delay) {
945
+ node.style[key] = webAnimationProperties[key][1];
946
+ }
947
+ }
948
+ else {
949
+ sourceAnimationProperties[key] = node.style[key];
950
+ }
951
+ }
952
+
953
+ const easing = Array.isArray(options.easing) ? `cubic-bezier(${options.easing.join(',')})` : BMAnimationEasing[options.easing];
954
+
955
+ let nodeAnimation;
956
+ try {
957
+ nodeAnimation = node.animate([sourceAnimationProperties, webAnimationProperties], {
958
+ //nodeAnimation = node.animate([{perspective: 1000}, {perspective: 1000}], {
959
+ duration: options.duration * (window.BMAnimationMultiplier || 1),
960
+ easing: easing || 'linear',
961
+ //fill: 'none',
962
+ delay: options.delay && (options.delay * (window.BMAnimationMultiplier || 1)),
963
+ composite: 'replace',
964
+ iterationComposite: 'replace'
965
+ });
966
+ }
967
+ catch (e) {
968
+ console.error('[BMCoreUI] This environment does not fully support web animations and use of this API will be disabled.');
969
+ // If the current browser doesn't properly support animations, web animations will be
970
+ // permanently disabled for this page and the sequence rerun with Velocity.js
971
+ BM_WEB_ANIMATIONS_DISABLED = YES;
972
+ i--;
973
+ continue;
974
+ }
975
+
976
+ // Some implementations do not have promise support for web animations
977
+ let hasPromiseSupport = NO;
978
+ if (nodeAnimation.finished) {
979
+ hasPromiseSupport = YES;
980
+ nodeAnimation.finished.then(async () => {
981
+ // Set up the final values when the animation finishes
982
+ // Animation fill mode is not used because it breaks all other CSS
983
+ for (let key in webAnimationProperties) {
984
+ node.style[key] = webAnimationProperties[key];
985
+ }
986
+ });
987
+ }
988
+
989
+ // Store a reference to this animation; the start times of all of the animations will be synchronized at the end of the loop
990
+ webAnimations.push(nodeAnimation);
991
+
992
+ // Set up a promise and add it to the animation to maintain compatibility with the Velocity.js promise
993
+ let promise = new Promise((resolve, reject) => {
994
+ let finished = NO;
995
+ nodeAnimation.onfinish = function () {
996
+ if (finished) return;
997
+ finished = YES;
998
+
999
+ // If the engine does not have promise support, then the final values will be applied in onFinish
1000
+ if (!hasPromiseSupport) {
1001
+ for (let key in webAnimationProperties) {
1002
+ node.style[key] = webAnimationProperties[key];
1003
+ }
1004
+ }
1005
+
1006
+ if (options.display == 'none') {
1007
+ node.style.display = 'none';
1008
+ }
1009
+
1010
+ //nodeAnimation.cancel();
1011
+
1012
+ resolve();
1013
+ };
1014
+ nodeAnimation.oncancel = function () {
1015
+ resolve();
1016
+ };
1017
+
1018
+ // On Safari, onfinish and oncancel are bugged currently do not fire at times, so they are manually resolved as a workaround
1019
+ //setTimeout(nodeAnimation.onfinish, ((options.delay || 0) + options.duration) * (window.BMAnimationMultiplier || 1));
1020
+ });
1021
+ promises.push(promise);
1022
+
1023
+ // If a progress handler is specified for the options, set up an accompanying Velocity.js animation to handle it
1024
+ if (options.progress) {
1025
+ promises.push(velocity.animate(element, {tween: 1}, options));
1026
+ }
1027
+
1028
+ }
1029
+ else if (BM_USE_VELOCITY2) {
1030
+ if (element instanceof window.$) {
1031
+ promises.push(element[0].velocity(animationTargets[i].properties, options));
1032
+ }
1033
+ else {
1034
+ promises.push(element.velocity(animationTargets[i].properties, options));
1035
+ }
1036
+ }
1037
+ else {
1038
+ promises.push(velocity.animate(element, animationTargets[i].properties, options));
1039
+
1040
+ if (options.queue) {
1041
+ velocity.Utilities.dequeue(element, options.queue);
1042
+ }
1043
+ }
1044
+ }
1045
+
1046
+ if (window.Promise) {
1047
+ let promise = Promise.all(promises);
1048
+ promise.then(function () {
1049
+ if (animation.options.complete) {
1050
+ animation.options.complete();
1051
+ }
1052
+ });
1053
+ return promise;
1054
+ }
1055
+ }
1056
+
1057
+
1058
+ //@param blocking <Boolean, nullable> Defaults to NO. If set to YES, this animation will be blocking and stop all other animations, otherwise it will be scheduled.
1059
+ //@param stride <Number, nullable> Defaults to 0. If set to a number, this will add stride millisecond delay between each animation. The animation delays will
1060
+ // be added to the elements in the order that their animations were scheduled.
1061
+ //@param duration <Int> The animation's duration in milliseconds.
1062
+ //@param ... <> Additional Velocity.js parameters
1063
+
1064
+ /**
1065
+ * Animates the properties modified in the given callback using the supplied options.
1066
+ * @param block <void (^)()> The callback in which you can modify the properties which will smoothly animate to their new values.
1067
+ * @param options <Object> An object of animation attributes. This object contains the same keys and values as Velocity.js's animation options object.
1068
+ * This object should not be modified afterwards until this animation is applied.
1069
+ * This object must contain a valid duration property.
1070
+ * @return <Promise<void>> A promise that resolves when this animation completes or is cancelled.
1071
+ */
1072
+ export function BMAnimateWithBlock(block, options) {
1073
+ var context = BMAnimationBeginWithDuration(options.duration, options);
1074
+
1075
+ block();
1076
+
1077
+ if (options.blocking) {
1078
+ return BMAnimationApplyBlocking(YES);
1079
+ }
1080
+ else {
1081
+ return BMAnimationApply();
1082
+ }
1083
+ }
1084
+
1085
+
1086
+
1087
+ /**
1088
+ * Converts the given element to a material design-like ripple that activates on mouse/touch down and up events on the given target element.
1089
+ * Though this is not required, it is recommended that the ripple element be an absolutely positioned direct descendant of the target element.
1090
+ * For best results, the ripple should also have its border radius set to 50% and its pointer-events set to none.
1091
+ * @param ripple <$> The jQuery element that will act as the ripple.
1092
+ * {
1093
+ * @param forTarget <$> The jQuery element.
1094
+ * }
1095
+ */
1096
+ export function BMRippleMakeWithElement(ripple, options) {
1097
+ // TODO: get rid of jQuery
1098
+ var target = options.forTarget;
1099
+
1100
+ ripple[0].classList.add('BMRipple');
1101
+
1102
+ var startEvent = BMIsTouchDevice ? 'touchstart.ripple' : 'mousedown.ripple';
1103
+ var endEvent = BMIsTouchDevice ? 'touchend.ripple' : 'mouseup.ripple';
1104
+
1105
+ target.on(startEvent, function (event) {
1106
+ var width = target.outerWidth();
1107
+ var height = target.outerHeight();
1108
+
1109
+ var highestDimension = Math.max(width, height);
1110
+ var diagonal = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
1111
+ var box = target[0].getBoundingClientRect();
1112
+ var targetOffset = {
1113
+ left: box.left,
1114
+ top: box.top
1115
+ };
1116
+
1117
+ event.pageX = BMIsTouchDevice ? event.originalEvent.touches[0].screenX : event.originalEvent.clientX;
1118
+ event.pageY = BMIsTouchDevice ? event.originalEvent.touches[0].screenY : event.originalEvent.clientY;
1119
+
1120
+ ripple.velocity("stop", true).css({
1121
+ width: '0px',
1122
+ height: '0px',
1123
+ opacity: 0
1124
+ });
1125
+ BMHook(ripple, {
1126
+ translateX: (event.pageX - targetOffset.left) + 'px',
1127
+ translateY: (event.pageY - targetOffset.top) + 'px'
1128
+ });
1129
+ ripple.velocity({
1130
+ translateX: ((width - diagonal) / 2) + 'px',
1131
+ translateY: ((height - diagonal) / 2) + 'px',
1132
+ width: diagonal + 'px',
1133
+ height: diagonal + 'px',
1134
+ opacity: 1
1135
+ }, {
1136
+ duration: 400,
1137
+ easing: 'ease-out',
1138
+ display: 'block',
1139
+ queue: NO
1140
+ });
1141
+
1142
+ let UUID = BMUUIDMake();
1143
+
1144
+ $(window).on(endEvent + UUID, function (event) {
1145
+ $(window).off(endEvent + UUID);
1146
+ ripple.velocity({
1147
+ opacity: 0
1148
+ }, {
1149
+ duration: 300,
1150
+ easing: 'ease-in-out',
1151
+ display: 'none',
1152
+ queue: NO
1153
+ });
1154
+ });
1155
+ });
1156
+ }
1157
+
1158
+ /**
1159
+ * Creates a material design-like ripple that activates on mouse/touch down and up events on the given target element.
1160
+ * @param target <$> The jQuery element.
1161
+ * {
1162
+ * @param withColor <BMColor or String, nullable> Defaults to rgba(0, 0, 0, .1). The color to use for the ripple.
1163
+ * }
1164
+ * @return <$> The newly created ripple element.
1165
+ */
1166
+ export function BMRippleMakeForTarget(target, args) {
1167
+ // TODO: get rid of jQuery
1168
+ var color = (args && args.withColor) || 'rgba(0, 0, 0, .1)';
1169
+
1170
+ color = color.RGBAString || color;
1171
+
1172
+ var ripple = $('<div style="position: absolute; display: block; top: 0px; left: 0px; border-radius: 50%;"></div>');
1173
+ ripple.css({backgroundColor: color});
1174
+
1175
+ BMRippleMakeWithElement(ripple, {forTarget: target});
1176
+
1177
+ return ripple;
1178
+ }
1179
+
1180
+
1181
+ // @endtype