bm-core-ui 2.11.8 → 2.11.9-beta.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 +391 -6
- package/build/BMCoreUI.css +88 -12
- package/build/BMWindow/BMPopover/BMPopover.js +590 -86
- package/build/BMWindow/BMWindow.js +468 -132
- package/lib/@types/BMCoreUI.min.d.ts +391 -6
- package/lib/BMCoreUI.min.js +2 -2
- package/package.json +1 -1
|
@@ -1,21 +1,172 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
import { BMExtend, NO, YES, BMCopyProperties, BMNumberByConstrainingNumberToBounds, BMUUIDMake } from "../../Core/BMCoreUI";
|
|
3
|
+
import { BMExtend, NO, YES, BMCopyProperties, BMNumberByConstrainingNumberToBounds, BMUUIDMake, BMNumberByInterpolatingNumbersWithFraction } from "../../Core/BMCoreUI";
|
|
4
4
|
import { BMWindow } from "../BMWindow";
|
|
5
5
|
import { BMRectMakeWithOrigin, BMRectMakeWithNodeFrame, BMRectMake } from "../../Core/BMRect";
|
|
6
6
|
import { BMPointMake } from "../../Core/BMPoint";
|
|
7
|
-
import { BMHook, __BMVelocityAnimate } from "../../Core/BMAnimationContext";
|
|
7
|
+
import { BMAnimateWithBlock, BMAnimationApplyBlocking, BMAnimationBeginWithDuration, BMAnimationContext, BMAnimationContextAddCompletionHandler, BMAnimationContextBeginStatic, BMAnimationContextGetCurrent, BMHook, __BMVelocityAnimate } from "../../Core/BMAnimationContext";
|
|
8
8
|
import { BMView, BMViewColorScheme } from "../../BMView/BMView_v2.5";
|
|
9
9
|
import { BMInsetMakeWithEqualInsets } from "../../Core/BMInset";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The number of pixels a touch or clicked pointer can wander off before causing a popover to detach.
|
|
14
|
+
*/
|
|
15
|
+
const BMPopoverDragThreshold = 128; // <Number>
|
|
16
|
+
|
|
17
|
+
// @type _BMPopoverDisplayConfiguration implements BMAnimating
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A class that describes the display attributes of a popover and supports interpolation.
|
|
21
|
+
*/
|
|
22
|
+
function _BMPopoverDisplayConfiguration() {} // <constructor>
|
|
23
|
+
|
|
24
|
+
_BMPopoverDisplayConfiguration.prototype = {
|
|
25
|
+
/**
|
|
26
|
+
* The popover's frame, excluding the indicator's size.
|
|
27
|
+
*/
|
|
28
|
+
_frame: undefined, // <BMRect>
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The indicator's direction relative to the popover's anchor.
|
|
32
|
+
*/
|
|
33
|
+
_direction: undefined, // <BMPopoverIndicatorDirection>
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The indicator's position along the popover's edge.
|
|
37
|
+
*/
|
|
38
|
+
_indicatorPosition: undefined, // <Number>
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The size of the indicator.
|
|
42
|
+
*/
|
|
43
|
+
_indicatorSize: undefined, // <Number>
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The round radius of the popover's corners.
|
|
47
|
+
*/
|
|
48
|
+
_borderRadius: undefined, // <Number>
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The height of the visible portion of the indicator.
|
|
52
|
+
*/
|
|
53
|
+
get _indicatorHeight() { // <Number>
|
|
54
|
+
// The indicator height represents the edge size of the indicator square;
|
|
55
|
+
// Therefore its total width/height represents the diagonal of that square
|
|
56
|
+
// and its visible height is half of the square's diagonal
|
|
57
|
+
const indicatorWidth = this._indicatorSize * Math.SQRT2;
|
|
58
|
+
return indicatorWidth / 2 | 0;
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Initializes this popover popover display configuration object with the specified values.
|
|
63
|
+
* @param frame <BMRect> The popover's frame.
|
|
64
|
+
* {
|
|
65
|
+
* @param direction <BMPopoverIndicatorDirection> The indicator's direction relative to the popover's anchor.
|
|
66
|
+
* @param indicatorPosition <Number> The indicator's position relative to the popover's edge.
|
|
67
|
+
* @param indicatorSize <Number> The size of the indicator.
|
|
68
|
+
* @param borderRadius <Number> The size of the popover's corners.
|
|
69
|
+
* }
|
|
70
|
+
* @returns <_BMPopoverDisplayConfiguration> This popover display configuration.
|
|
71
|
+
*/
|
|
72
|
+
initWithFrame(frame, {direction, indicatorPosition, indicatorSize, borderRadius}) {
|
|
73
|
+
this._frame = frame.copy();
|
|
74
|
+
this._direction = direction;
|
|
75
|
+
this._indicatorPosition = indicatorPosition;
|
|
76
|
+
this._indicatorSize = indicatorSize;
|
|
77
|
+
this._borderRadius = borderRadius;
|
|
78
|
+
|
|
79
|
+
return this;
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Initializes this popover popover display configuration object by copying the values of
|
|
84
|
+
* the specified popover display configuration.
|
|
85
|
+
* @param config <_BMPopoverDisplayConfiguration> The configuration whose values to copy.
|
|
86
|
+
* @returns <_BMPopoverDisplayConfiguration> This popover display configuration.
|
|
87
|
+
*/
|
|
88
|
+
initWithPopoverDisplayConfiguration(config) {
|
|
89
|
+
this._frame = config._frame.copy();
|
|
90
|
+
this._direction = config._direction;
|
|
91
|
+
this._indicatorPosition = config._indicatorPosition;
|
|
92
|
+
this._indicatorSize = config._indicatorSize;
|
|
93
|
+
this._borderRadius = config._borderRadius;
|
|
94
|
+
|
|
95
|
+
return this;
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Creates and returns a copy of this popover display configuration.
|
|
100
|
+
* @returns <_BMPopoverDisplayConfiguration> A copy of this object.
|
|
101
|
+
*/
|
|
102
|
+
copy() {
|
|
103
|
+
return (new _BMPopoverDisplayConfiguration).initWithPopoverDisplayConfiguration(this);
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Invoked by the CoreUI animation engine to obtain an interpolated
|
|
108
|
+
* value between this object and the target object.
|
|
109
|
+
* @param fraction <Number> The animation fraction.
|
|
110
|
+
* {
|
|
111
|
+
* @param toValue <_BMPopoverDisplayConfiguration> The object to which to interpolate.
|
|
112
|
+
* }
|
|
113
|
+
* @return <_BMPopoverDisplayConfiguration> A popover display configuration.
|
|
114
|
+
*/
|
|
115
|
+
interpolatedValueWithFraction(fraction, {toValue: target}) {
|
|
116
|
+
const copy = this.copy();
|
|
117
|
+
|
|
118
|
+
copy._frame = this._frame.interpolatedValueWithFraction(fraction, {toValue: target._frame});
|
|
119
|
+
|
|
120
|
+
if (this._direction == target._direction) {
|
|
121
|
+
// When the direction remains the same animate all other indicator properties smoothly
|
|
122
|
+
copy._indicatorPosition = BMNumberByInterpolatingNumbersWithFraction(this._indicatorPosition, target._indicatorPosition, fraction);
|
|
123
|
+
copy._indicatorSize = BMNumberByInterpolatingNumbersWithFraction(this._indicatorSize, target._indicatorSize, fraction);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Otherwise hide then indicator from its source direction then reveal it at the target direction over the course of the animation
|
|
127
|
+
if (fraction < 0.5) {
|
|
128
|
+
// In the first half, hide the indicator, keeping it in the source direction
|
|
129
|
+
copy._direction = this._direction;
|
|
130
|
+
copy._indicatorPosition = this._indicatorPosition;
|
|
131
|
+
copy._indicatorSize = BMNumberByInterpolatingNumbersWithFraction(this._indicatorSize, 0, fraction * 2);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// In the second half, show the indicator, keeping it in the target direction
|
|
135
|
+
copy._direction = target._direction;
|
|
136
|
+
copy._indicatorPosition = target._indicatorPosition;
|
|
137
|
+
copy._indicatorSize = BMNumberByInterpolatingNumbersWithFraction(0, target._indicatorSize, (fraction - 0.5) * 2);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
copy._borderRadius = BMNumberByInterpolatingNumbersWithFraction(this._borderRadius, target._borderRadius, fraction);
|
|
142
|
+
|
|
143
|
+
return copy;
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Creates and returns a popover display configuration object initialized with the specified values.
|
|
149
|
+
* @param frame <BMRect> The popover's frame.
|
|
150
|
+
* {
|
|
151
|
+
* @param direction <BMPopoverIndicatorDirection> The indicator's direction relative to the popover's anchor.
|
|
152
|
+
* @param indicatorPosition <Number> The indicator's position relative to the popover's edge.
|
|
153
|
+
* @param indicatorSize <Number> The size of the indicator.
|
|
154
|
+
* @param borderRadius <Number> The size of the popover's corners.
|
|
155
|
+
* }
|
|
156
|
+
* @returns <_BMPopoverDisplayConfiguration> A popover display configuration.
|
|
157
|
+
*/
|
|
158
|
+
_BMPopoverDisplayConfiguration.configurationWithFrame = function (frame, args) {
|
|
159
|
+
return (new this).initWithFrame(frame, args);
|
|
160
|
+
};
|
|
12
161
|
|
|
13
162
|
// @endtype
|
|
14
163
|
|
|
164
|
+
// @type BMPopoverIndicatorDirection
|
|
165
|
+
|
|
15
166
|
/**
|
|
16
167
|
* Constants describing the position where the indicator appears on its popover.
|
|
17
168
|
*/
|
|
18
|
-
|
|
169
|
+
export var BMPopoverIndicatorDirection = Object.freeze({ // <enum>
|
|
19
170
|
/**
|
|
20
171
|
* Causes the popover indicator to appear on the top edge of the popover.
|
|
21
172
|
*/
|
|
@@ -37,6 +188,8 @@ import { BMInsetMakeWithEqualInsets } from "../../Core/BMInset";
|
|
|
37
188
|
Right: "Right" // <enum>
|
|
38
189
|
});
|
|
39
190
|
|
|
191
|
+
// @endtype
|
|
192
|
+
|
|
40
193
|
// @type BMPopover extends BMWindow
|
|
41
194
|
|
|
42
195
|
/**
|
|
@@ -49,9 +202,14 @@ import { BMInsetMakeWithEqualInsets } from "../../Core/BMInset";
|
|
|
49
202
|
export function BMPopover() {} // <constructor>
|
|
50
203
|
|
|
51
204
|
BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* An optional delegate which this popover may notify of key events.
|
|
208
|
+
*/
|
|
209
|
+
delegate: undefined, // <BMPopoverDelegate, nullable>
|
|
52
210
|
|
|
53
211
|
/**
|
|
54
|
-
* The point from which this popover should originate, relative to the document. Either this property
|
|
212
|
+
* Animatable. The point from which this popover should originate, relative to the document. Either this property
|
|
55
213
|
* or `anchorNode` or `anchorRect` must be set before this popover is displayed.
|
|
56
214
|
*/
|
|
57
215
|
_anchorPoint: undefined, // <BMPoint, nullable>
|
|
@@ -60,12 +218,16 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
60
218
|
return this._anchorPoint;
|
|
61
219
|
},
|
|
62
220
|
set anchorPoint(point) {
|
|
221
|
+
this._anchorRect = undefined;
|
|
222
|
+
this._anchorNode = undefined;
|
|
63
223
|
this._anchorPoint = point;
|
|
224
|
+
|
|
225
|
+
this._updatePosition();
|
|
64
226
|
},
|
|
65
227
|
|
|
66
228
|
|
|
67
229
|
/**
|
|
68
|
-
* The rect from which this popover should originate, relative to the document. Either this property
|
|
230
|
+
* Animatable. The rect from which this popover should originate, relative to the document. Either this property
|
|
69
231
|
* or `anchorPoint` or `anchorNode` must be set before this popover is displayed.
|
|
70
232
|
*/
|
|
71
233
|
_anchorRect: undefined, // <BMRect, nullable>
|
|
@@ -74,12 +236,16 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
74
236
|
return this._anchorRect;
|
|
75
237
|
},
|
|
76
238
|
set anchorRect(rect) {
|
|
239
|
+
this._anchorPoint = undefined;
|
|
240
|
+
this._anchorNode = undefined;
|
|
77
241
|
this._anchorRect = rect;
|
|
242
|
+
|
|
243
|
+
this._updatePosition();
|
|
78
244
|
},
|
|
79
245
|
|
|
80
246
|
|
|
81
247
|
/**
|
|
82
|
-
* The element from which this popover should originate. Either this property
|
|
248
|
+
* Animatable. The element from which this popover should originate. Either this property
|
|
83
249
|
* or `anchorPoint` or `anchorRect` must be set before this popover is displayed.
|
|
84
250
|
*/
|
|
85
251
|
_anchorNode: undefined, // <DOMNode, nullable>
|
|
@@ -88,7 +254,11 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
88
254
|
return this._anchorNode;
|
|
89
255
|
},
|
|
90
256
|
set anchorNode(node) {
|
|
257
|
+
this._anchorRect = undefined;
|
|
258
|
+
this._anchorPoint = undefined;
|
|
91
259
|
this._anchorNode = node;
|
|
260
|
+
|
|
261
|
+
this._updatePosition();
|
|
92
262
|
},
|
|
93
263
|
|
|
94
264
|
/**
|
|
@@ -101,6 +271,8 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
101
271
|
},
|
|
102
272
|
set size(size) {
|
|
103
273
|
this._size = size.copy();
|
|
274
|
+
|
|
275
|
+
this._updatePosition();
|
|
104
276
|
},
|
|
105
277
|
|
|
106
278
|
/**
|
|
@@ -113,6 +285,8 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
113
285
|
},
|
|
114
286
|
set indicatorSize(size) {
|
|
115
287
|
this._indicatorSize = size;
|
|
288
|
+
|
|
289
|
+
this._updatePosition();
|
|
116
290
|
},
|
|
117
291
|
|
|
118
292
|
/**
|
|
@@ -125,6 +299,8 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
125
299
|
},
|
|
126
300
|
set borderRadius(radius) {
|
|
127
301
|
this._borderRadius = radius;
|
|
302
|
+
|
|
303
|
+
this._updatePosition();
|
|
128
304
|
},
|
|
129
305
|
|
|
130
306
|
/**
|
|
@@ -139,11 +315,7 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
139
315
|
set edgeInsets(margin) {
|
|
140
316
|
this._edgeInsets = margin || BMInsetMakeWithEqualInsets(8);
|
|
141
317
|
|
|
142
|
-
|
|
143
|
-
// If this is updated while the popover is visible, update its position accordingly
|
|
144
|
-
// TODO: Only update when this would actually change the position
|
|
145
|
-
this._updatePosition();
|
|
146
|
-
}
|
|
318
|
+
this._updatePosition();
|
|
147
319
|
},
|
|
148
320
|
|
|
149
321
|
/**
|
|
@@ -244,6 +416,8 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
244
416
|
},
|
|
245
417
|
set permittedDirections(directions) {
|
|
246
418
|
this._permittedDirections = directions.slice();
|
|
419
|
+
|
|
420
|
+
this._updatePosition();
|
|
247
421
|
},
|
|
248
422
|
|
|
249
423
|
/**
|
|
@@ -340,119 +514,237 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
340
514
|
},
|
|
341
515
|
|
|
342
516
|
/**
|
|
343
|
-
*
|
|
517
|
+
* Set to `YES` while this popover is detached. When set to `YES` the popover is detached from
|
|
518
|
+
* its anchor and can be freely moved. When set to `NO`, the popover remains attached to its
|
|
519
|
+
* anchor in a fixed position.
|
|
344
520
|
*/
|
|
345
|
-
|
|
521
|
+
_isDetached: NO, // <Boolean>
|
|
522
|
+
|
|
523
|
+
get isDetached() {
|
|
524
|
+
return this._isDetached;
|
|
525
|
+
},
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* The current detached position of this popover.
|
|
529
|
+
*/
|
|
530
|
+
_position: undefined, // <BMPoint>
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* The popover's current direction. Set to `undefined` until this popover is first displayed.
|
|
534
|
+
*/
|
|
535
|
+
_direction: undefined, // <BMPopoverIndicatorDirection, nullable>
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Controls whether this popover retains the direction that was set to it when it was first
|
|
539
|
+
* displayed. When set to `NO`, whenever the popover's size or attributes change it will try
|
|
540
|
+
* to find a new direction around the anchor. When set to `YES`, the current direction or the
|
|
541
|
+
* initial display direction will be kept regardless of how the popover changes.
|
|
542
|
+
*
|
|
543
|
+
* When set to `undefined`, this popover will use the behaviour set on the `BMPopover` class.
|
|
544
|
+
*/
|
|
545
|
+
_retainsDirection: undefined, // <Boolean, nullable>
|
|
546
|
+
|
|
547
|
+
get retainsDirection() {
|
|
548
|
+
return this._retainsDirection ?? BMPopover._retainsDirection;
|
|
549
|
+
},
|
|
550
|
+
|
|
551
|
+
set retainsDirection(retains) {
|
|
552
|
+
this._retainsDirection = retains;
|
|
553
|
+
},
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* The current display configuration. Set to `undefined` until this popover is first displayed.
|
|
557
|
+
*/
|
|
558
|
+
_config: undefined, // <_BMPopoverDisplayConfiguration, nullable>
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* The current display configuration. Set to `undefined` until this popover is first displayed.
|
|
562
|
+
*/
|
|
563
|
+
get _displayConfiguration() { // <_BMPopoverDisplayConfiguration, nullable>
|
|
564
|
+
return this._config;
|
|
565
|
+
},
|
|
566
|
+
|
|
567
|
+
set _displayConfiguration(config) {
|
|
568
|
+
this._config = config;
|
|
569
|
+
this._applyDisplayConfiguration(config);
|
|
570
|
+
},
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Invoked by CoreUI to create a new display configuration for this popover based on the
|
|
574
|
+
* current values of its properties.
|
|
575
|
+
* @return <_BMPopoverDisplayConfiguration> The configuration.
|
|
576
|
+
*/
|
|
577
|
+
_createDisplayConfiguration() {
|
|
346
578
|
const frame = BMRectMake();
|
|
347
|
-
frame.size.height = this._size.height
|
|
579
|
+
frame.size.height = this._size.height;
|
|
348
580
|
frame.size.width = this._size.width;
|
|
581
|
+
frame.origin.x = (this._position?.x ?? this._frame.origin.x) | 0;
|
|
582
|
+
frame.origin.y = (this._position?.y ?? this._frame.origin.y) | 0;
|
|
349
583
|
|
|
350
584
|
const nodeFrame = this.anchorRect || (this.anchorNode && BMRectMakeWithNodeFrame(this.anchorNode));
|
|
351
585
|
const location = this.anchorPoint ? this.anchorPoint.copy() : nodeFrame.center;
|
|
352
586
|
|
|
353
587
|
// Determine the appropriate direction to display this popover
|
|
354
588
|
let direction;
|
|
355
|
-
if (this.
|
|
589
|
+
if (this._direction && this.retainsDirection) {
|
|
590
|
+
direction = this._direction;
|
|
591
|
+
}
|
|
592
|
+
else if (this.anchorPoint) {
|
|
356
593
|
direction = this._directionAroundPoint(location);
|
|
357
594
|
}
|
|
358
595
|
else {
|
|
359
596
|
direction = this._directionAroundRect(nodeFrame);
|
|
360
597
|
}
|
|
361
598
|
|
|
362
|
-
|
|
599
|
+
if (!this._isDetached) {
|
|
600
|
+
// If this popover is attached, update the frame's position based on the anchor
|
|
601
|
+
// Move the frame to the appropriate position based on the selected direction
|
|
602
|
+
switch (direction) {
|
|
603
|
+
case BMPopoverIndicatorDirection.Top:
|
|
604
|
+
frame.size.height += this._indicatorHeight;
|
|
605
|
+
frame.origin.y = this.anchorPoint ? location.y : nodeFrame.bottom - 2;
|
|
606
|
+
|
|
607
|
+
frame.origin.x = location.x - frame.size.width / 2 | 0;
|
|
608
|
+
|
|
609
|
+
if (frame.origin.x < this._edgeInsets.left) {
|
|
610
|
+
frame.origin.x = this._edgeInsets.left;
|
|
611
|
+
}
|
|
612
|
+
if (frame.right > window.innerWidth - this._edgeInsets.right) {
|
|
613
|
+
frame.origin.x = window.innerWidth - frame.size.width - this._edgeInsets.right;
|
|
614
|
+
}
|
|
615
|
+
break;
|
|
616
|
+
case BMPopoverIndicatorDirection.Bottom:
|
|
617
|
+
frame.size.height += this._indicatorHeight;
|
|
618
|
+
frame.origin.y = this.anchorPoint ? location.y - frame.size.height : nodeFrame.origin.y + 2 - frame.size.height;
|
|
619
|
+
|
|
620
|
+
frame.origin.x = location.x - frame.size.width / 2 | 0;
|
|
621
|
+
|
|
622
|
+
if (frame.origin.x < this._edgeInsets.left) {
|
|
623
|
+
frame.origin.x = this._edgeInsets.left;
|
|
624
|
+
}
|
|
625
|
+
if (frame.right > window.innerWidth - this._edgeInsets.right) {
|
|
626
|
+
frame.origin.x = window.innerWidth - frame.size.width - this._edgeInsets.right;
|
|
627
|
+
}
|
|
628
|
+
break;
|
|
629
|
+
case BMPopoverIndicatorDirection.Right:
|
|
630
|
+
frame.size.width += this._indicatorHeight;
|
|
631
|
+
frame.origin.x = this.anchorPoint ? location.x - frame.size.width : nodeFrame.origin.x + 2 - frame.size.width;
|
|
632
|
+
|
|
633
|
+
frame.origin.y = location.y - frame.size.height / 2 | 0;
|
|
634
|
+
|
|
635
|
+
if (frame.origin.y < this._edgeInsets.top) {
|
|
636
|
+
frame.origin.y = this._edgeInsets.top;
|
|
637
|
+
}
|
|
638
|
+
if (frame.bottom > window.innerHeight - this._edgeInsets.bottom) {
|
|
639
|
+
frame.origin.y = window.innerHeight - frame.size.height - this._edgeInsets.bottom;
|
|
640
|
+
}
|
|
641
|
+
break;
|
|
642
|
+
case BMPopoverIndicatorDirection.Left:
|
|
643
|
+
frame.size.width += this._indicatorHeight;
|
|
644
|
+
frame.origin.x = this.anchorPoint ? location.x : nodeFrame.right - 2;
|
|
645
|
+
|
|
646
|
+
frame.origin.y = location.y - frame.size.height / 2 | 0;
|
|
647
|
+
|
|
648
|
+
if (frame.origin.y < this._edgeInsets.top) {
|
|
649
|
+
frame.origin.y = this._edgeInsets.top;
|
|
650
|
+
}
|
|
651
|
+
if (frame.bottom > window.innerHeight - this._edgeInsets.bottom) {
|
|
652
|
+
frame.origin.y = window.innerHeight - frame.size.height - this._edgeInsets.bottom;
|
|
653
|
+
}
|
|
654
|
+
break;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
// If the popover is detached, prevent it from exceeding the screen's size
|
|
659
|
+
frame.size.width = BMNumberByConstrainingNumberToBounds(frame.size.width, 0, window.innerWidth);
|
|
660
|
+
frame.size.height = BMNumberByConstrainingNumberToBounds(frame.size.height, 0, window.innerHeight);
|
|
661
|
+
frame.origin.x = BMNumberByConstrainingNumberToBounds(frame.origin.x, 0, window.innerWidth - frame.size.width);
|
|
662
|
+
frame.origin.y = BMNumberByConstrainingNumberToBounds(frame.origin.y, 0, window.innerHeight - frame.size.height);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// Determine the indicator's position along its edge
|
|
666
|
+
let indicatorPosition;
|
|
363
667
|
switch (direction) {
|
|
668
|
+
case BMPopoverIndicatorDirection.Bottom:
|
|
364
669
|
case BMPopoverIndicatorDirection.Top:
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
frame.origin.x = location.x - frame.size.width / 2 | 0;
|
|
368
|
-
|
|
369
|
-
if (frame.origin.x < this._edgeInsets.left) {
|
|
370
|
-
frame.origin.x = this._edgeInsets.left;
|
|
670
|
+
if (!this._isDetached) {
|
|
671
|
+
frame.size.height -= this._indicatorHeight;
|
|
371
672
|
}
|
|
372
|
-
|
|
373
|
-
|
|
673
|
+
indicatorPosition = BMNumberByConstrainingNumberToBounds(location.x - frame.origin.x, this._borderRadius * 1.5 + this._indicatorSize * Math.SQRT2 / 2, frame.size.width - this._borderRadius * 1.5 - this._indicatorSize * Math.SQRT2 / 2);
|
|
674
|
+
break;
|
|
675
|
+
case BMPopoverIndicatorDirection.Left:
|
|
676
|
+
case BMPopoverIndicatorDirection.Right:
|
|
677
|
+
if (!this._isDetached) {
|
|
678
|
+
frame.size.width -= this._indicatorHeight;
|
|
374
679
|
}
|
|
375
|
-
|
|
376
|
-
|
|
680
|
+
indicatorPosition = BMNumberByConstrainingNumberToBounds(location.y - frame.origin.y, this._borderRadius * 1.5 + this._indicatorSize * Math.SQRT2 / 2, frame.size.height - this._borderRadius * 1.5 - this._indicatorSize * Math.SQRT2 / 2);
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const indicatorSize = this._isDetached ? 0 : this._indicatorSize;
|
|
685
|
+
|
|
686
|
+
const configuration = _BMPopoverDisplayConfiguration.configurationWithFrame(frame, {direction, indicatorSize, indicatorPosition, borderRadius: this._borderRadius});
|
|
687
|
+
return configuration;
|
|
688
|
+
},
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Invoked by CoreUI to apply the specified display configuration to this popover and its various SVG elements.
|
|
692
|
+
* @param config <_BMPopoverDisplayConfiguration> The configuration to apply.
|
|
693
|
+
*/
|
|
694
|
+
_applyDisplayConfiguration(config) {
|
|
695
|
+
if (this.__released) {
|
|
696
|
+
// Prevent configuration applications from throwing an error if a popover was released while an
|
|
697
|
+
// animation was playing
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const frame = config._frame.copy();
|
|
702
|
+
const indicatorHeight = config._indicatorHeight;
|
|
703
|
+
const direction = config._direction;
|
|
704
|
+
|
|
705
|
+
// Adjust the constraints based on the direction
|
|
706
|
+
switch (direction) {
|
|
707
|
+
case BMPopoverIndicatorDirection.Top:
|
|
708
|
+
frame.size.height += indicatorHeight;
|
|
709
|
+
this._contentViewTopConstraint.constant = indicatorHeight;
|
|
377
710
|
this._contentViewBottomConstraint.constant = 0;
|
|
378
711
|
this._contentViewLeftConstraint.constant = 0;
|
|
379
712
|
this._contentViewRightConstraint.constant = 0;
|
|
380
713
|
break;
|
|
381
714
|
case BMPopoverIndicatorDirection.Bottom:
|
|
382
|
-
frame.
|
|
383
|
-
|
|
384
|
-
frame.origin.x = location.x - frame.size.width / 2 | 0;
|
|
385
|
-
|
|
386
|
-
if (frame.origin.x < this._edgeInsets.left) {
|
|
387
|
-
frame.origin.x = this._edgeInsets.left;
|
|
388
|
-
}
|
|
389
|
-
if (frame.right > window.innerWidth - this._edgeInsets.right) {
|
|
390
|
-
frame.origin.x = window.innerWidth - frame.size.width - this._edgeInsets.right;
|
|
391
|
-
}
|
|
392
|
-
|
|
715
|
+
frame.size.height += indicatorHeight;
|
|
393
716
|
this._contentViewTopConstraint.constant = 0;
|
|
394
|
-
this._contentViewBottomConstraint.constant = -
|
|
717
|
+
this._contentViewBottomConstraint.constant = -indicatorHeight;
|
|
395
718
|
this._contentViewLeftConstraint.constant = 0;
|
|
396
719
|
this._contentViewRightConstraint.constant = 0;
|
|
397
720
|
break;
|
|
398
721
|
case BMPopoverIndicatorDirection.Right:
|
|
399
|
-
frame.
|
|
400
|
-
|
|
401
|
-
frame.origin.y = location.y - frame.size.height / 2 | 0;
|
|
402
|
-
|
|
403
|
-
if (frame.origin.y < this._edgeInsets.top) {
|
|
404
|
-
frame.origin.y = this._edgeInsets.top;
|
|
405
|
-
}
|
|
406
|
-
if (frame.bottom > window.innerHeight - this._edgeInsets.bottom) {
|
|
407
|
-
frame.origin.y = window.innerHeight - frame.size.height - this._edgeInsets.bottom;
|
|
408
|
-
}
|
|
409
|
-
|
|
722
|
+
frame.size.width += indicatorHeight;
|
|
410
723
|
this._contentViewTopConstraint.constant = 0;
|
|
411
724
|
this._contentViewBottomConstraint.constant = 0;
|
|
412
725
|
this._contentViewLeftConstraint.constant = 0;
|
|
413
|
-
this._contentViewRightConstraint.constant = -
|
|
726
|
+
this._contentViewRightConstraint.constant = -indicatorHeight;
|
|
414
727
|
break;
|
|
415
728
|
case BMPopoverIndicatorDirection.Left:
|
|
416
|
-
frame.
|
|
417
|
-
|
|
418
|
-
frame.origin.y = location.y - frame.size.height / 2 | 0;
|
|
419
|
-
|
|
420
|
-
if (frame.origin.y < this._edgeInsets.top) {
|
|
421
|
-
frame.origin.y = this._edgeInsets.top;
|
|
422
|
-
}
|
|
423
|
-
if (frame.bottom > window.innerHeight - this._edgeInsets.bottom) {
|
|
424
|
-
frame.origin.y = window.innerHeight - frame.size.height - this._edgeInsets.bottom;
|
|
425
|
-
}
|
|
426
|
-
|
|
729
|
+
frame.size.width += indicatorHeight;
|
|
427
730
|
this._contentViewTopConstraint.constant = 0;
|
|
428
731
|
this._contentViewBottomConstraint.constant = 0;
|
|
429
|
-
this._contentViewLeftConstraint.constant =
|
|
732
|
+
this._contentViewLeftConstraint.constant = indicatorHeight;
|
|
430
733
|
this._contentViewRightConstraint.constant = 0;
|
|
431
734
|
break;
|
|
432
735
|
}
|
|
433
736
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
let indicatorPosition;
|
|
438
|
-
switch (direction) {
|
|
439
|
-
case BMPopoverIndicatorDirection.Bottom:
|
|
440
|
-
case BMPopoverIndicatorDirection.Top:
|
|
441
|
-
indicatorPosition = BMNumberByConstrainingNumberToBounds(location.x - frame.origin.x, 12, frame.size.width - 12);
|
|
442
|
-
break;
|
|
443
|
-
case BMPopoverIndicatorDirection.Left:
|
|
444
|
-
case BMPopoverIndicatorDirection.Right:
|
|
445
|
-
indicatorPosition = BMNumberByConstrainingNumberToBounds(location.y - frame.origin.y, 12, frame.size.height - 12);
|
|
446
|
-
break;
|
|
447
|
-
}
|
|
737
|
+
const indicatorPosition = config._indicatorPosition;
|
|
738
|
+
const borderRadius = config._borderRadius;
|
|
739
|
+
const indicatorSize = config._indicatorSize;
|
|
448
740
|
|
|
449
741
|
// Create an inner frame to be used by the various paths
|
|
450
742
|
const innerFrame = frame.copy();
|
|
451
743
|
innerFrame.origin = BMPointMake();
|
|
452
744
|
|
|
453
|
-
const pathContent = `${this._pathForPopoverWithFrame(innerFrame, {indicatorSize
|
|
454
|
-
const outlinePathContent = `${this._pathForPopoverWithFrame(innerFrame, {indicatorSize
|
|
455
|
-
const boxShadowPathContent = `${this._pathForPopoverWithFrame(innerFrame, {indicatorSize
|
|
745
|
+
const pathContent = `${this._pathForPopoverWithFrame(innerFrame, {indicatorSize, position: indicatorPosition, direction, radius: borderRadius})}`;
|
|
746
|
+
const outlinePathContent = `${this._pathForPopoverWithFrame(innerFrame, {indicatorSize, inset: 1, position: indicatorPosition, direction, radius: borderRadius - 1.5})}`;
|
|
747
|
+
const boxShadowPathContent = `${this._pathForPopoverWithFrame(innerFrame, {indicatorSize, position: indicatorPosition, direction, radius: borderRadius + 1.5})}`;
|
|
456
748
|
|
|
457
749
|
if (!this._clipPathUUID && !CSS.supports('clip-path', `path('${pathContent}')`)) {
|
|
458
750
|
// If inline path definitions are not supported by the browsers, create an UUID for a SVG clip path and create it
|
|
@@ -531,26 +823,85 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
531
823
|
let transformOriginX, transformOriginY;
|
|
532
824
|
switch (direction) {
|
|
533
825
|
case BMPopoverIndicatorDirection.Bottom:
|
|
534
|
-
transformOriginX = ((indicatorPosition /
|
|
826
|
+
transformOriginX = ((indicatorPosition / frame.size.width) * 100) + '%';
|
|
535
827
|
transformOriginY = '100%';
|
|
536
828
|
break;
|
|
537
829
|
case BMPopoverIndicatorDirection.Top:
|
|
538
|
-
transformOriginX = ((indicatorPosition /
|
|
830
|
+
transformOriginX = ((indicatorPosition / frame.size.width) * 100) + '%';
|
|
539
831
|
transformOriginY = '0%';
|
|
540
832
|
break;
|
|
541
833
|
case BMPopoverIndicatorDirection.Left:
|
|
542
834
|
transformOriginX = '0%';
|
|
543
|
-
transformOriginY = ((indicatorPosition /
|
|
835
|
+
transformOriginY = ((indicatorPosition / frame.size.height) * 100) + '%';
|
|
544
836
|
break;
|
|
545
837
|
case BMPopoverIndicatorDirection.Right:
|
|
546
838
|
transformOriginX = '100%';
|
|
547
|
-
transformOriginY = ((indicatorPosition /
|
|
839
|
+
transformOriginY = ((indicatorPosition / frame.size.height) * 100) + '%';
|
|
548
840
|
break;
|
|
549
841
|
}
|
|
550
842
|
|
|
551
843
|
for (const layer of popoverLayers) {
|
|
552
844
|
layer.style.transformOrigin = `${transformOriginX} ${transformOriginY}`;
|
|
553
845
|
}
|
|
846
|
+
|
|
847
|
+
this.frame = frame;
|
|
848
|
+
this.layoutIfNeeded();
|
|
849
|
+
},
|
|
850
|
+
|
|
851
|
+
/**
|
|
852
|
+
* The number of display configuration animations running currently against this popover's display configuration.
|
|
853
|
+
*/
|
|
854
|
+
_displayConfigurationAnimations: 0, // <Number>
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* A display configuration that will be applied to this popover at the end of any current
|
|
858
|
+
* animations affecting the display configuration.
|
|
859
|
+
*/
|
|
860
|
+
_pendingDisplayConfiguration: undefined, // <_BMPopoverDisplayConfiguration>
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Animatable. Invoked by CoreUI to update this popover's position and recalculate the various paths used by it.
|
|
864
|
+
*/
|
|
865
|
+
_updatePosition() {
|
|
866
|
+
// If the popover is not currently visible, there is not action to take
|
|
867
|
+
if (!this.isVisible) {
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
const config = this._createDisplayConfiguration();
|
|
872
|
+
|
|
873
|
+
const context = BMAnimationContextGetCurrent();
|
|
874
|
+
if (context) {
|
|
875
|
+
const controller = context.controllerForObject(this, {node: this.node});
|
|
876
|
+
controller.registerAnimatableProperty('_displayConfiguration', {targetValue: config});
|
|
877
|
+
|
|
878
|
+
this._displayConfigurationAnimations++;
|
|
879
|
+
// When all animations finish on this popover, if there was any pending display configuration, apply it then
|
|
880
|
+
BMAnimationContextAddCompletionHandler(() => {
|
|
881
|
+
this._displayConfigurationAnimations--;
|
|
882
|
+
|
|
883
|
+
if (!this.isVisible) {
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
if (!this._displayConfigurationAnimations && this._pendingDisplayConfiguration) {
|
|
888
|
+
BMAnimationContextBeginStatic(); {
|
|
889
|
+
this._displayConfiguration = this._pendingDisplayConfiguration;
|
|
890
|
+
this._pendingDisplayConfiguration = undefined;
|
|
891
|
+
} BMAnimationApplyBlocking();
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
else {
|
|
896
|
+
if (this._displayConfigurationAnimations) {
|
|
897
|
+
// If an animation is in progress, wait for it to finish before applying the new configuration
|
|
898
|
+
this._pendingDisplayConfiguration = config;
|
|
899
|
+
}
|
|
900
|
+
else {
|
|
901
|
+
// Else apply the configuration directly
|
|
902
|
+
this._displayConfiguration = config;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
554
905
|
},
|
|
555
906
|
|
|
556
907
|
/**
|
|
@@ -723,6 +1074,138 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
723
1074
|
return path;
|
|
724
1075
|
},
|
|
725
1076
|
|
|
1077
|
+
/**
|
|
1078
|
+
* Controls whether an in-progress drag can detach this popover.
|
|
1079
|
+
*/
|
|
1080
|
+
_canDetach: NO, // <Boolean>
|
|
1081
|
+
|
|
1082
|
+
/**
|
|
1083
|
+
* @protected
|
|
1084
|
+
* Controls whether this popover is detachable. Defaults to the result provided
|
|
1085
|
+
* by the delegate.
|
|
1086
|
+
* @return <Boolean> `YES` if the popover is detachable, `NO` otherwise.
|
|
1087
|
+
*/
|
|
1088
|
+
isDetachable() {
|
|
1089
|
+
return this.delegate?.popoverCanDetach?.(this) ?? NO;
|
|
1090
|
+
},
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* During a drag operation set to the point where the drag began.
|
|
1094
|
+
*/
|
|
1095
|
+
_initialDragPosition: undefined, // <BMPoint, nullable>
|
|
1096
|
+
|
|
1097
|
+
// @override - BMWindow
|
|
1098
|
+
dragBeganAtPosition(position, {withEvent: event}) {
|
|
1099
|
+
this._canDetach = this.isDetachable();
|
|
1100
|
+
|
|
1101
|
+
// If the popover is neither detached nor can it detach, drags cannot be performed
|
|
1102
|
+
if (!this._canDetach && !this._isDetached) {
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
this._initialDragPosition = position.copy();
|
|
1107
|
+
BMWindow.prototype.dragBeganAtPosition.apply(this, arguments);
|
|
1108
|
+
},
|
|
1109
|
+
|
|
1110
|
+
// @override - BMWindow
|
|
1111
|
+
dragPositionDidChangeFromPosition(fromPosition, {toPosition, event}) {
|
|
1112
|
+
if (!this._canDetach && !this._isDetached) {
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
if (!this._isDetached) {
|
|
1117
|
+
// If not detached, apply a displacement to this popover that is half of the regular
|
|
1118
|
+
// drag distance, until this popover is fully detached
|
|
1119
|
+
BMHook(this.node, {
|
|
1120
|
+
translateX: `${(toPosition.x - this._initialDragPosition.x) / 3 | 0}px`,
|
|
1121
|
+
translateY: `${(toPosition.y - this._initialDragPosition.y) / 3 | 0}px`,
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1124
|
+
const distance = toPosition.distanceToPoint(this._initialDragPosition);
|
|
1125
|
+
if (distance > BMPopoverDragThreshold) {
|
|
1126
|
+
// If the movement exceeds the detachment threshold, detach this popover
|
|
1127
|
+
this.detachAnimated(YES);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
else {
|
|
1131
|
+
// If this is detached, update the popover's position
|
|
1132
|
+
this._position = BMPointMake(
|
|
1133
|
+
BMNumberByConstrainingNumberToBounds(this._position.x + toPosition.x - fromPosition.x, 0, window.innerWidth - this.frame.size.width),
|
|
1134
|
+
BMNumberByConstrainingNumberToBounds(this._position.y + toPosition.y - fromPosition.y, 0, window.innerHeight - this.frame.size.height),
|
|
1135
|
+
);
|
|
1136
|
+
this._displayConfiguration = this._createDisplayConfiguration();
|
|
1137
|
+
}
|
|
1138
|
+
},
|
|
1139
|
+
|
|
1140
|
+
// @override - BMWindow
|
|
1141
|
+
dragEndedAtPosition(position, {withEvent: event}) {
|
|
1142
|
+
BMWindow.prototype.dragEndedAtPosition.apply(this, arguments);
|
|
1143
|
+
|
|
1144
|
+
if (!this._isDetached && this._canDetach) {
|
|
1145
|
+
// If the drag operation didn't cause this popover to detach, animate it back to its
|
|
1146
|
+
// regular position
|
|
1147
|
+
BMAnimateWithBlock(() => {
|
|
1148
|
+
const controller = BMAnimationContextGetCurrent().controllerForObject(this, {node: this.node});
|
|
1149
|
+
controller.registerBuiltInPropertiesWithDictionary({
|
|
1150
|
+
translateX: '0px',
|
|
1151
|
+
translateY: '0px',
|
|
1152
|
+
});
|
|
1153
|
+
}, {duration: 500, easing: 'easeInOutQuart'});
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
this._canDetach = NO;
|
|
1157
|
+
},
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* Detaches this popover from its anchor and allows it to be freely movable.
|
|
1161
|
+
* @param animated <Boolean, nullable> Defaults to `YES`. When set to `YES`, this change will be animated,
|
|
1162
|
+
* otherwise it will be instant.
|
|
1163
|
+
* @returns <Promise<void>> A promise that resolves when the operation completes.
|
|
1164
|
+
*/
|
|
1165
|
+
detachAnimated(animated) {
|
|
1166
|
+
// If this popover is already detached, this method has no effect
|
|
1167
|
+
if (this._isDetached) {
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
// If this change is animated and there isn't already an active animation context, start one
|
|
1172
|
+
let animationContextStarted = NO;
|
|
1173
|
+
if (animated && !BMAnimationContextGetCurrent()) {
|
|
1174
|
+
animationContextStarted = YES;
|
|
1175
|
+
BMAnimationBeginWithDuration(300, {easing: 'easeInOutQuart'});
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
this._isDetached = YES;
|
|
1179
|
+
this._displayConfiguration = this._createDisplayConfiguration();
|
|
1180
|
+
this._position = this.frame.origin.copy();
|
|
1181
|
+
|
|
1182
|
+
let promise;
|
|
1183
|
+
|
|
1184
|
+
// If a temporary transform was applied to this node, clear it
|
|
1185
|
+
if (BMAnimationContextGetCurrent()) {
|
|
1186
|
+
const controller = BMAnimationContextGetCurrent().controllerForObject(this, {node: this.node});
|
|
1187
|
+
controller.registerBuiltInPropertiesWithDictionary({
|
|
1188
|
+
translateX: '0px',
|
|
1189
|
+
translateY: '0px',
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
promise = new Promise(r => BMAnimationContextAddCompletionHandler(r));
|
|
1193
|
+
}
|
|
1194
|
+
else {
|
|
1195
|
+
BMHook(this.node, {translateX: '0px', translateY: '0px'});
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
if (animationContextStarted) {
|
|
1199
|
+
BMAnimationApplyBlocking(YES);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
if (!promise) {
|
|
1203
|
+
promise = Promise.resolve();
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
return promise;
|
|
1207
|
+
},
|
|
1208
|
+
|
|
726
1209
|
// @override - BMWindow
|
|
727
1210
|
animateInWithCompletionHandler(completionHandler) {
|
|
728
1211
|
const popoverLayers = [this.contentNode, this._background, this._dropShadowContainer];
|
|
@@ -763,7 +1246,7 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
763
1246
|
bringToFrontAnimated(animated, args) {
|
|
764
1247
|
if (!this.anchorNode && !this.anchorPoint && !this.anchorRect) throw new Error('The anchorPoint, anchorRect or anchorNode must be set prior to showing this popover.');
|
|
765
1248
|
|
|
766
|
-
this.
|
|
1249
|
+
this._displayConfiguration = this._createDisplayConfiguration();
|
|
767
1250
|
|
|
768
1251
|
BMWindow.prototype.bringToFrontAnimated.apply(this, arguments);
|
|
769
1252
|
},
|
|
@@ -780,7 +1263,7 @@ BMPopover.prototype = BMExtend(Object.create(BMWindow.prototype), {
|
|
|
780
1263
|
});
|
|
781
1264
|
|
|
782
1265
|
/**
|
|
783
|
-
* Constructs and returns a popover with the
|
|
1266
|
+
* Constructs and returns a popover with the specified size.
|
|
784
1267
|
* @param size <BMSize> The popover's size.
|
|
785
1268
|
* @return <BMPopover> A popover.
|
|
786
1269
|
*/
|
|
@@ -788,4 +1271,25 @@ BMPopover.popoverWithSize = function (size) {
|
|
|
788
1271
|
return (new BMPopover).initWithSize(size);
|
|
789
1272
|
}
|
|
790
1273
|
|
|
1274
|
+
/**
|
|
1275
|
+
* Controls whether popovers retain the direction that was set to them when they were first
|
|
1276
|
+
* displayed, by default. When set to `NO`, whenever a popover's size or attributes change it will try
|
|
1277
|
+
* to find a new direction around the anchor. When set to `YES`, the current direction or the
|
|
1278
|
+
* initial display direction will be kept regardless of how the popover changes.
|
|
1279
|
+
*/
|
|
1280
|
+
BMPopover._retainsDirection = NO; // <Boolean>
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* Controls whether popovers retain the direction that was set to them when they were first
|
|
1284
|
+
* displayed, by default. When set to `NO`, whenever a popover's size or attributes change it will try
|
|
1285
|
+
* to find a new direction around the anchor. When set to `YES`, the current direction or the
|
|
1286
|
+
* initial display direction will be kept regardless of how the popover changes.
|
|
1287
|
+
* @param retains <Boolean, nullable> Defaults to `NO`. When set to `YES`, popovers will retain their
|
|
1288
|
+
* initial direction, otherwise they will recalculate their direction
|
|
1289
|
+
* whenever any update occurs.
|
|
1290
|
+
*/
|
|
1291
|
+
BMPopover.setRetainsDirection = function (retains) {
|
|
1292
|
+
BMPopover._retainsDirection = retains || NO;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
791
1295
|
// @endtype
|