bm-core-ui 2.12.0-beta.5 → 2.12.0-beta.6

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.
@@ -5846,6 +5846,14 @@ export class BMDragSession implements EventHandlerObject {
5846
5846
  private _beginDrag(): void;
5847
5847
 
5848
5848
 
5849
+ /**
5850
+ * Invoked when a key is pressed while this drag session is in progress.
5851
+ * @param event The event.
5852
+ *
5853
+ */
5854
+ private _keyPressedWithEvent(event: KeyboardEvent): void;
5855
+
5856
+
5849
5857
  /**
5850
5858
  * Invoked whenever the pointer moves while this drag session is in progress.
5851
5859
  * @param event The event.
@@ -5856,11 +5864,11 @@ export class BMDragSession implements EventHandlerObject {
5856
5864
 
5857
5865
  /**
5858
5866
  * Invoked when the pointer is released or cancelled while this drag session is in progress.
5859
- * @param event The event.
5860
- * @return A promise that resolves when all associated animations finish.
5867
+ * @param event The event.
5868
+ * @return A promise that resolves when all associated animations finish.
5861
5869
  *
5862
5870
  */
5863
- private _dragDidFinishWithEvent(event: MouseEvent | TouchEvent): Promise<void>;
5871
+ private _dragDidFinishWithEvent(event: MouseEvent | TouchEvent | KeyboardEvent): Promise<void>;
5864
5872
 
5865
5873
 
5866
5874
  /**
@@ -7036,6 +7044,13 @@ export class _BMDragIndicator {
7036
7044
  */
7037
7045
  export class _BMDragPreviewSet {
7038
7046
 
7047
+ /**
7048
+ * The offset between the drag pointer and the center the from of the view from which the drag session
7049
+ * started, expressed in percentages relative to the view's frame.
7050
+ *
7051
+ */
7052
+ private _offsetPercent: BMPoint;
7053
+
7039
7054
  /**
7040
7055
  * The offset between the drag pointer and the center of the frames of the preview elements.
7041
7056
  *
@@ -7082,7 +7097,8 @@ export class _BMDragPreviewSet {
7082
7097
  * Initializes this drag preview set with the specified item previews and offset position.
7083
7098
  * @param previews The previews for items in the drag session.
7084
7099
  * @param pointerOffset The offset between the drag pointer and the
7085
- * center of the frames of the preview elements.
7100
+ * center of the frames of the view from which the
7101
+ * drag session started.
7086
7102
  * @return This preview set.
7087
7103
  *
7088
7104
  */
@@ -9975,6 +9991,13 @@ export class BMMenu {
9975
9991
  */
9976
9992
  _delaysClosing: boolean;
9977
9993
 
9994
+ /**
9995
+ * When set to `YES`, the menu item actions and item selection delegate callbacks will be invoked
9996
+ * with a slight delay to allow time for the menu closing animation to play.
9997
+ *
9998
+ */
9999
+ delaysActions: boolean;
10000
+
9978
10001
  /**
9979
10002
  * Initializes this menu with the specified items.
9980
10003
  * The menu will be hidden by default; the method showAtPoint(_) should be used to make the menu visible.
@@ -10011,6 +10034,20 @@ export class BMMenu {
10011
10034
  private _renderMenuItems(): void;
10012
10035
 
10013
10036
 
10037
+ /**
10038
+ * Temporarily set to the menu item that was selected until its action is performed.
10039
+ *
10040
+ */
10041
+ private _selectedMenuItem?: BMMenuItem | null | undefined;
10042
+
10043
+ /**
10044
+ * Performs the action for the specified menu item and invokes the delegate selection callback for it.
10045
+ * @param item The menu item whose action should be performed.
10046
+ *
10047
+ */
10048
+ private _performActionForMenuItem(item: BMMenuItem): void;
10049
+
10050
+
10014
10051
  /**
10015
10052
  * The kind of menu currently displayed.
10016
10053
  *
@@ -435,7 +435,10 @@ BMDragSession.prototype = {
435
435
  if (firstItemPreview._sourceNode) {
436
436
  const sourceNodeFrame = BMRectMakeWithNodeFrame(firstItemPreview._sourceNode);
437
437
  const center = sourceNodeFrame.center;
438
- pointerOffset = BMPointMake(center.x - this._position.x, center.y - this._position.y);
438
+ pointerOffset = BMPointMake(
439
+ (center.x - this._position.x) / sourceNodeFrame.size.width,
440
+ (center.y - this._position.y) / sourceNodeFrame.size.height,
441
+ );
439
442
  }
440
443
 
441
444
  // Obtain the drag previews for the remaining items
@@ -468,10 +471,16 @@ BMDragSession.prototype = {
468
471
  if (this._touchIdentifier !== undefined) {
469
472
  window.addEventListener('touchcancel', this, {capture: YES, passive: NO});
470
473
  }
474
+
475
+ // Register a key press event that will cancel the drag when escape is pressed
476
+ window.addEventListener('keydown', this, {capture: YES, passive: NO});
471
477
  },
472
478
 
473
- handleEvent(/** @type {MouseEvent | TouchEvent} */ event) {
474
- if (event.type == 'mousemove' || event.type == 'touchmove') {
479
+ handleEvent(/** @type {MouseEvent | TouchEvent | KeyboardEvent} */ event) {
480
+ if (event.type == 'keydown') {
481
+ this._keyPressedWithEvent(event);
482
+ }
483
+ else if (event.type == 'mousemove' || event.type == 'touchmove') {
475
484
  this._dragDidMoveWithEvent(event);
476
485
  }
477
486
  else {
@@ -479,6 +488,26 @@ BMDragSession.prototype = {
479
488
  }
480
489
  },
481
490
 
491
+ /**
492
+ * Invoked when a key is pressed while this drag session is in progress.
493
+ * @param event <KeyboardEvent> The event.
494
+ */
495
+ _keyPressedWithEvent(event) {
496
+ // Cancel the drag session when pressing escape or command + .
497
+ if (event.code != 'Escape' && (event.code != 'Period' || !event.metaKey)) {
498
+ return;
499
+ }
500
+
501
+ // Clear any drop target, set the drop action to ignore and immediately finish the session
502
+ event.stopPropagation();
503
+ event.preventDefault();
504
+ this._setDropTarget(undefined);
505
+ this._sourceDropAction = BMDragSessionAction.actionWithKind(BMDragSessionActionKind.Ignore);
506
+ this._updateDropAction();
507
+
508
+ this._dragDidFinishWithEvent();
509
+ },
510
+
482
511
  /**
483
512
  * Invoked whenever the pointer moves while this drag session is in progress.
484
513
  * @param event <MouseEvent or TouchEvent> The event.
@@ -551,8 +580,8 @@ BMDragSession.prototype = {
551
580
 
552
581
  /**
553
582
  * Invoked when the pointer is released or cancelled while this drag session is in progress.
554
- * @param event <MouseEvent or TouchEvent> The event.
555
- * @return <Promise<void>> A promise that resolves when all associated animations finish.
583
+ * @param event <MouseEvent or TouchEvent or KeyboardEvent> The event.
584
+ * @return <Promise<void>> A promise that resolves when all associated animations finish.
556
585
  */
557
586
  async _dragDidFinishWithEvent(event) {
558
587
  event.preventDefault();
@@ -575,6 +604,7 @@ BMDragSession.prototype = {
575
604
  if (this._touchIdentifier !== undefined) {
576
605
  window.removeEventListener('touchcancel', this, {capture: YES, passive: NO});
577
606
  }
607
+ window.removeEventListener('keydown', this, {capture: YES, passive: NO});
578
608
  this._releaseDropTargetHandlers();
579
609
 
580
610
  // If there is a drop target and its action is not ignore, instruct the delegate to perform the action
@@ -1199,6 +1199,12 @@ export function _BMDragPreviewSet() {} // <constructor>
1199
1199
 
1200
1200
  _BMDragPreviewSet.prototype = {
1201
1201
 
1202
+ /**
1203
+ * The offset between the drag pointer and the center the from of the view from which the drag session
1204
+ * started, expressed in percentages relative to the view's frame.
1205
+ */
1206
+ _offsetPercent: BMPointMake(), // <BMPoint>
1207
+
1202
1208
  /**
1203
1209
  * The offset between the drag pointer and the center of the frames of the preview elements.
1204
1210
  */
@@ -1239,7 +1245,8 @@ _BMDragPreviewSet.prototype = {
1239
1245
  * @param previews <[BMDragPreview]> The previews for items in the drag session.
1240
1246
  * {
1241
1247
  * @param pointerOffset <BMPoint> The offset between the drag pointer and the
1242
- * center of the frames of the preview elements.
1248
+ * center of the frames of the view from which the
1249
+ * drag session started.
1243
1250
  * }
1244
1251
  * @return <_BMDragPreviewSet> This preview set.
1245
1252
  */
@@ -1254,7 +1261,7 @@ _BMDragPreviewSet.prototype = {
1254
1261
  this._baseDragPreviews.set(preview._dragItem, preview);
1255
1262
  }
1256
1263
 
1257
- this._offset = pointerOffset.copy();
1264
+ this._offsetPercent = pointerOffset.copy();
1258
1265
 
1259
1266
  this._dragIndicator = new _BMDragIndicator().init();
1260
1267
 
@@ -1365,6 +1372,21 @@ _BMDragPreviewSet.prototype = {
1365
1372
  * @param position <BMPoint> The position of the drag session.
1366
1373
  */
1367
1374
  beginLiftAtPosition(position) {
1375
+ const firstPreview = this._dragPreviews.entries().next().value?.[1];
1376
+ const measureIterator = firstPreview?._attachAtPosition(BMPointMake());
1377
+ let measureIteratorResult = measureIterator.next();
1378
+ while (!measureIteratorResult.done) {
1379
+ measureIteratorResult = measureIterator.next();
1380
+ }
1381
+
1382
+ this._offset = BMPointMake(
1383
+ this._offsetPercent.x * (firstPreview?._frame.size.width ?? 0),
1384
+ this._offsetPercent.y * (firstPreview?._frame.size.height ?? 0),
1385
+ );
1386
+
1387
+ firstPreview._detach();
1388
+ firstPreview._measured = NO;
1389
+
1368
1390
  this._position = position.copy();
1369
1391
  const previewPosition = position.copy();
1370
1392
  previewPosition.x += this._offset.x;
@@ -1373,7 +1395,6 @@ _BMDragPreviewSet.prototype = {
1373
1395
  // Attach and measure the previews
1374
1396
  let attachIterators = [];
1375
1397
  let previousPreview;
1376
- let firstPreview;
1377
1398
  for (const [item, preview] of this._dragPreviews.entries()) {
1378
1399
 
1379
1400
  // For each preview other than the first, apply a random rotation between 15 and -15 degrees
@@ -1381,10 +1402,6 @@ _BMDragPreviewSet.prototype = {
1381
1402
  preview._transform.rotateZ = Math.random() * _BMDragPreviewMaxRotation * 2 - _BMDragPreviewMaxRotation;
1382
1403
  }
1383
1404
 
1384
- if (!firstPreview) {
1385
- firstPreview = preview;
1386
- }
1387
-
1388
1405
  const attachIterator = preview._attachAtPosition(previewPosition, {before: previousPreview?._previewNode});
1389
1406
  attachIterators.push(attachIterator);
1390
1407
  attachIterator.next();
@@ -460,6 +460,12 @@ BMMenu.prototype = {
460
460
  this.__delaysClosing = delays;
461
461
  },
462
462
 
463
+ /**
464
+ * When set to `YES`, the menu item actions and item selection delegate callbacks will be invoked
465
+ * with a slight delay to allow time for the menu closing animation to play.
466
+ */
467
+ delaysActions: NO, // <Boolean>
468
+
463
469
  /**
464
470
  * Initializes this menu with the specified items.
465
471
  * The menu will be hidden by default; the method showAtPoint(_) should be used to make the menu visible.
@@ -701,20 +707,13 @@ BMMenu.prototype = {
701
707
  // animation to play out
702
708
  this._delaysClosing = YES;
703
709
 
704
- if (item.action) {
705
- // Invoke the menu's action if configured
706
- item.action(item);
707
- }
710
+ this._selectedMenuItem = item;
708
711
 
709
712
  itemNode.classList.add('BMMenuItemActive');
710
-
711
- if (this.delegate && this.delegate.menuDidSelectItem) {
712
- this.delegate.menuDidSelectItem(this, item);
713
- }
714
713
  });
715
714
 
716
715
  // When moving the mouse over an item, set the highlight index to it,
717
- // allowing further keyboard navigation to continute from this item
716
+ // allowing further keyboard navigation to continue from this item
718
717
  itemNode.addEventListener('mouseover', event => {
719
718
  // Disabled items can't be highlighted and can't open submenus
720
719
  if (!item._enabled) {
@@ -747,6 +746,21 @@ BMMenu.prototype = {
747
746
  });
748
747
  },
749
748
 
749
+ /**
750
+ * Temporarily set to the menu item that was selected until its action is performed.
751
+ */
752
+ _selectedMenuItem: undefined, // <BMMenuItem, nullable>
753
+
754
+ /**
755
+ * Performs the action for the specified menu item and invokes the delegate selection callback for it.
756
+ * @param item <BMMenuItem> The menu item whose action should be performed.
757
+ */
758
+ _performActionForMenuItem(item) {
759
+ item.action?.(item);
760
+
761
+ this.delegate?.menuDidSelectItem?.(this, item);
762
+ },
763
+
750
764
  /**
751
765
  * The kind of menu currently displayed.
752
766
  */
@@ -1380,11 +1394,27 @@ BMMenu.prototype = {
1380
1394
  let delay = Math.min(this._itemsContainerNode.childNodes.length * 16, 150);
1381
1395
  delay = (delay < 0 ? 0 : delay);
1382
1396
 
1397
+ let selectedItemCallbackDelay = 0;
1398
+
1383
1399
  // If an item was clicked, further delay closing to allow the selection animation to play
1384
1400
  const delaysClosing = this._delaysClosing;
1385
1401
  this._delaysClosing = NO;
1386
1402
  if (delaysClosing && !this._sourceNodeShadow) {
1387
1403
  delay += 200;
1404
+
1405
+ selectedItemCallbackDelay = 200;
1406
+ }
1407
+
1408
+ const selectedMenuItem = this._selectedMenuItem;
1409
+ this._selectedMenuItem = undefined;
1410
+
1411
+ if (selectedMenuItem) {
1412
+ if (this.delaysActions && selectedItemCallbackDelay) {
1413
+ setTimeout(() => this._performActionForMenuItem(selectedMenuItem), selectedItemCallbackDelay);
1414
+ }
1415
+ else {
1416
+ this._performActionForMenuItem(selectedMenuItem);
1417
+ }
1388
1418
  }
1389
1419
 
1390
1420
  const sourceNodeShadow = this._sourceNodeShadow;
@@ -1598,11 +1628,7 @@ BMMenu.prototype = {
1598
1628
  // animation to play out
1599
1629
  this._delaysClosing = YES;
1600
1630
 
1601
- if (item.action) item.action(item);
1602
-
1603
- if (this.delegate && this.delegate.menuDidSelectItem) {
1604
- this.delegate.menuDidSelectItem(this, item);
1605
- }
1631
+ this._selectedMenuItem = item;
1606
1632
 
1607
1633
  const highlightedNode = item._node;
1608
1634
  if (highlightedNode) {
@@ -5846,6 +5846,14 @@ declare class BMDragSession implements EventHandlerObject {
5846
5846
  private _beginDrag(): void;
5847
5847
 
5848
5848
 
5849
+ /**
5850
+ * Invoked when a key is pressed while this drag session is in progress.
5851
+ * @param event The event.
5852
+ *
5853
+ */
5854
+ private _keyPressedWithEvent(event: KeyboardEvent): void;
5855
+
5856
+
5849
5857
  /**
5850
5858
  * Invoked whenever the pointer moves while this drag session is in progress.
5851
5859
  * @param event The event.
@@ -5856,11 +5864,11 @@ declare class BMDragSession implements EventHandlerObject {
5856
5864
 
5857
5865
  /**
5858
5866
  * Invoked when the pointer is released or cancelled while this drag session is in progress.
5859
- * @param event The event.
5860
- * @return A promise that resolves when all associated animations finish.
5867
+ * @param event The event.
5868
+ * @return A promise that resolves when all associated animations finish.
5861
5869
  *
5862
5870
  */
5863
- private _dragDidFinishWithEvent(event: MouseEvent | TouchEvent): Promise<void>;
5871
+ private _dragDidFinishWithEvent(event: MouseEvent | TouchEvent | KeyboardEvent): Promise<void>;
5864
5872
 
5865
5873
 
5866
5874
  /**
@@ -7036,6 +7044,13 @@ declare class _BMDragIndicator {
7036
7044
  */
7037
7045
  declare class _BMDragPreviewSet {
7038
7046
 
7047
+ /**
7048
+ * The offset between the drag pointer and the center the from of the view from which the drag session
7049
+ * started, expressed in percentages relative to the view's frame.
7050
+ *
7051
+ */
7052
+ private _offsetPercent: BMPoint;
7053
+
7039
7054
  /**
7040
7055
  * The offset between the drag pointer and the center of the frames of the preview elements.
7041
7056
  *
@@ -7082,7 +7097,8 @@ declare class _BMDragPreviewSet {
7082
7097
  * Initializes this drag preview set with the specified item previews and offset position.
7083
7098
  * @param previews The previews for items in the drag session.
7084
7099
  * @param pointerOffset The offset between the drag pointer and the
7085
- * center of the frames of the preview elements.
7100
+ * center of the frames of the view from which the
7101
+ * drag session started.
7086
7102
  * @return This preview set.
7087
7103
  *
7088
7104
  */
@@ -9975,6 +9991,13 @@ declare class BMMenu {
9975
9991
  */
9976
9992
  _delaysClosing: boolean;
9977
9993
 
9994
+ /**
9995
+ * When set to `YES`, the menu item actions and item selection delegate callbacks will be invoked
9996
+ * with a slight delay to allow time for the menu closing animation to play.
9997
+ *
9998
+ */
9999
+ delaysActions: boolean;
10000
+
9978
10001
  /**
9979
10002
  * Initializes this menu with the specified items.
9980
10003
  * The menu will be hidden by default; the method showAtPoint(_) should be used to make the menu visible.
@@ -10011,6 +10034,20 @@ declare class BMMenu {
10011
10034
  private _renderMenuItems(): void;
10012
10035
 
10013
10036
 
10037
+ /**
10038
+ * Temporarily set to the menu item that was selected until its action is performed.
10039
+ *
10040
+ */
10041
+ private _selectedMenuItem?: BMMenuItem | null | undefined;
10042
+
10043
+ /**
10044
+ * Performs the action for the specified menu item and invokes the delegate selection callback for it.
10045
+ * @param item The menu item whose action should be performed.
10046
+ *
10047
+ */
10048
+ private _performActionForMenuItem(item: BMMenuItem): void;
10049
+
10050
+
10014
10051
  /**
10015
10052
  * The kind of menu currently displayed.
10016
10053
  *