@ionic/core 7.3.2-dev.11693262117.17edbf6d → 7.3.2-dev.11693321491.12123d27

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 (125) hide show
  1. package/components/action-sheet.js +17 -8
  2. package/components/alert.js +17 -8
  3. package/components/framework-delegate.js +5 -2
  4. package/components/ion-loading.js +17 -8
  5. package/components/ion-menu.js +1 -1
  6. package/components/ion-modal.js +34 -13
  7. package/components/ion-picker.js +17 -8
  8. package/components/ion-toast.js +17 -8
  9. package/components/overlays.js +1 -22
  10. package/components/popover.js +30 -9
  11. package/dist/cjs/{framework-delegate-e8174951.js → framework-delegate-91be3b84.js} +5 -2
  12. package/dist/cjs/index.cjs.js +2 -2
  13. package/dist/cjs/ion-action-sheet.cjs.entry.js +18 -9
  14. package/dist/cjs/ion-alert.cjs.entry.js +18 -9
  15. package/dist/cjs/ion-app_8.cjs.entry.js +1 -1
  16. package/dist/cjs/ion-datetime_3.cjs.entry.js +18 -9
  17. package/dist/cjs/ion-loading.cjs.entry.js +18 -9
  18. package/dist/cjs/ion-menu_3.cjs.entry.js +2 -2
  19. package/dist/cjs/ion-modal.cjs.entry.js +35 -14
  20. package/dist/cjs/ion-nav_2.cjs.entry.js +1 -1
  21. package/dist/cjs/ion-popover.cjs.entry.js +31 -10
  22. package/dist/cjs/ion-select_3.cjs.entry.js +2 -2
  23. package/dist/cjs/ion-tab_2.cjs.entry.js +1 -1
  24. package/dist/cjs/ion-toast.cjs.entry.js +18 -9
  25. package/dist/cjs/{overlays-2b9fa92e.js → overlays-cf7fa4cf.js} +1 -23
  26. package/dist/collection/components/action-sheet/action-sheet.js +17 -8
  27. package/dist/collection/components/alert/alert.js +17 -8
  28. package/dist/collection/components/loading/loading.js +17 -8
  29. package/dist/collection/components/modal/modal.js +34 -13
  30. package/dist/collection/components/picker/picker.js +17 -8
  31. package/dist/collection/components/popover/popover.js +30 -9
  32. package/dist/collection/components/popover/test/async/popover.e2e.js +20 -0
  33. package/dist/collection/components/toast/toast.js +17 -8
  34. package/dist/collection/utils/framework-delegate.js +5 -2
  35. package/dist/collection/utils/overlays.js +0 -21
  36. package/dist/docs.json +1 -1
  37. package/dist/esm/{framework-delegate-2b76c681.js → framework-delegate-43758c88.js} +5 -2
  38. package/dist/esm/index.js +2 -2
  39. package/dist/esm/ion-action-sheet.entry.js +18 -9
  40. package/dist/esm/ion-alert.entry.js +18 -9
  41. package/dist/esm/ion-app_8.entry.js +1 -1
  42. package/dist/esm/ion-datetime_3.entry.js +18 -9
  43. package/dist/esm/ion-loading.entry.js +18 -9
  44. package/dist/esm/ion-menu_3.entry.js +2 -2
  45. package/dist/esm/ion-modal.entry.js +35 -14
  46. package/dist/esm/ion-nav_2.entry.js +1 -1
  47. package/dist/esm/ion-popover.entry.js +31 -10
  48. package/dist/esm/ion-select_3.entry.js +2 -2
  49. package/dist/esm/ion-tab_2.entry.js +1 -1
  50. package/dist/esm/ion-toast.entry.js +18 -9
  51. package/dist/esm/{overlays-66222f79.js → overlays-236d01c6.js} +2 -23
  52. package/dist/esm-es5/framework-delegate-43758c88.js +4 -0
  53. package/dist/esm-es5/index.js +1 -1
  54. package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
  55. package/dist/esm-es5/ion-alert.entry.js +1 -1
  56. package/dist/esm-es5/ion-app_8.entry.js +1 -1
  57. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  58. package/dist/esm-es5/ion-loading.entry.js +1 -1
  59. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  60. package/dist/esm-es5/ion-modal.entry.js +1 -1
  61. package/dist/esm-es5/ion-nav_2.entry.js +1 -1
  62. package/dist/esm-es5/ion-popover.entry.js +1 -1
  63. package/dist/esm-es5/ion-select_3.entry.js +1 -1
  64. package/dist/esm-es5/ion-tab_2.entry.js +1 -1
  65. package/dist/esm-es5/ion-toast.entry.js +1 -1
  66. package/dist/esm-es5/{overlays-66222f79.js → overlays-236d01c6.js} +1 -1
  67. package/dist/ionic/index.esm.js +1 -1
  68. package/dist/ionic/ionic.esm.js +1 -1
  69. package/dist/ionic/{p-0494a5b7.system.entry.js → p-04515b10.system.entry.js} +1 -1
  70. package/dist/ionic/p-13df6e84.system.entry.js +4 -0
  71. package/dist/ionic/p-2bdc6097.entry.js +4 -0
  72. package/dist/ionic/p-2c88183e.system.entry.js +4 -0
  73. package/dist/ionic/p-2d37d114.system.entry.js +4 -0
  74. package/dist/ionic/p-2f6666a9.entry.js +4 -0
  75. package/dist/ionic/{p-8d9475b5.system.js → p-33dc95e4.system.js} +1 -1
  76. package/dist/ionic/{p-20087c90.entry.js → p-4852bb39.entry.js} +1 -1
  77. package/dist/ionic/p-4adb3257.entry.js +4 -0
  78. package/dist/ionic/{p-b2098e96.system.entry.js → p-50e474b3.system.entry.js} +1 -1
  79. package/dist/ionic/{p-229df0d8.entry.js → p-5c0754cd.entry.js} +1 -1
  80. package/dist/ionic/{p-a0ffdd91.system.js → p-5f5d78da.system.js} +1 -1
  81. package/dist/ionic/p-647c433f.entry.js +4 -0
  82. package/dist/ionic/p-721933ff.system.js +1 -1
  83. package/dist/ionic/p-870fee8d.system.entry.js +4 -0
  84. package/dist/ionic/p-8d1ef5d0.entry.js +4 -0
  85. package/dist/ionic/p-ad5a562b.system.entry.js +4 -0
  86. package/dist/ionic/{p-f8e4da48.system.js → p-c275a599.system.js} +1 -1
  87. package/dist/ionic/p-d3602489.entry.js +4 -0
  88. package/dist/ionic/p-e015fbd9.system.entry.js +4 -0
  89. package/dist/ionic/p-e30f020d.entry.js +4 -0
  90. package/dist/ionic/{p-7776d062.entry.js → p-e484ae56.entry.js} +1 -1
  91. package/dist/ionic/{p-5c96dc4e.entry.js → p-ed290b4a.entry.js} +1 -1
  92. package/dist/ionic/{p-8074bdd7.system.entry.js → p-f1bf45b2.system.entry.js} +1 -1
  93. package/dist/ionic/p-f2743457.js +4 -0
  94. package/dist/ionic/{p-6b9bf14c.system.entry.js → p-f2c1459b.system.entry.js} +1 -1
  95. package/dist/ionic/p-f4bbbc33.js +4 -0
  96. package/dist/ionic/p-f94cad00.system.entry.js +4 -0
  97. package/dist/ionic/{p-9888a5a7.entry.js → p-fb16e75c.entry.js} +1 -1
  98. package/dist/ionic/{p-d1356034.system.entry.js → p-ff0f2ef4.system.entry.js} +1 -1
  99. package/dist/types/components/action-sheet/action-sheet.d.ts +1 -1
  100. package/dist/types/components/alert/alert.d.ts +1 -1
  101. package/dist/types/components/loading/loading.d.ts +1 -1
  102. package/dist/types/components/modal/modal.d.ts +1 -1
  103. package/dist/types/components/picker/picker.d.ts +1 -1
  104. package/dist/types/components/popover/popover.d.ts +1 -1
  105. package/dist/types/components/toast/toast.d.ts +1 -1
  106. package/dist/types/utils/overlays.d.ts +0 -9
  107. package/hydrate/index.js +147 -78
  108. package/package.json +1 -1
  109. package/dist/esm-es5/framework-delegate-2b76c681.js +0 -4
  110. package/dist/ionic/p-16fd72f2.entry.js +0 -4
  111. package/dist/ionic/p-1c9e3bc7.entry.js +0 -4
  112. package/dist/ionic/p-2a51c81c.entry.js +0 -4
  113. package/dist/ionic/p-2a649b3e.system.entry.js +0 -4
  114. package/dist/ionic/p-3ef9e271.system.entry.js +0 -4
  115. package/dist/ionic/p-6d484719.system.entry.js +0 -4
  116. package/dist/ionic/p-70d137a0.js +0 -4
  117. package/dist/ionic/p-7ac9bdfa.system.entry.js +0 -4
  118. package/dist/ionic/p-8d53d5a5.entry.js +0 -4
  119. package/dist/ionic/p-a133c215.system.entry.js +0 -4
  120. package/dist/ionic/p-b34c1ae1.js +0 -4
  121. package/dist/ionic/p-c0b4ca5c.system.entry.js +0 -4
  122. package/dist/ionic/p-cf768a4f.entry.js +0 -4
  123. package/dist/ionic/p-ddffbfa9.entry.js +0 -4
  124. package/dist/ionic/p-e2e2c2b0.entry.js +0 -4
  125. package/dist/ionic/p-ebb442c4.system.entry.js +0 -4
@@ -9,11 +9,11 @@ const index = require('./index-484b1104.js');
9
9
  const config = require('./config-d5882735.js');
10
10
  const helpers = require('./helpers-ea4ccbcb.js');
11
11
  const index$1 = require('./index-cc7dfb7c.js');
12
- const overlays = require('./overlays-2b9fa92e.js');
12
+ const overlays = require('./overlays-cf7fa4cf.js');
13
13
  const theme = require('./theme-fbc56b3b.js');
14
14
  const ionicGlobal = require('./ionic-global-f81d8b73.js');
15
15
  const animation = require('./animation-2bb33618.js');
16
- require('./framework-delegate-e8174951.js');
16
+ require('./framework-delegate-91be3b84.js');
17
17
  require('./hardware-back-button-b67c8e75.js');
18
18
  require('./index-306a7476.js');
19
19
 
@@ -126,7 +126,6 @@ const Toast = class {
126
126
  this.willDismissShorthand = index.createEvent(this, "willDismiss", 7);
127
127
  this.didDismissShorthand = index.createEvent(this, "didDismiss", 7);
128
128
  this.delegateController = overlays.createDelegateController(this);
129
- this.lockController = overlays.createLockController();
130
129
  this.triggerController = overlays.createTriggerController();
131
130
  this.customHTMLEnabled = ionicGlobal.config.get('innerHTMLTemplatesEnabled', config.ENABLE_HTML_CONTENT_DEFAULT);
132
131
  this.presented = false;
@@ -196,19 +195,30 @@ const Toast = class {
196
195
  * Present the toast overlay after it has been created.
197
196
  */
198
197
  async present() {
199
- const unlock = await this.lockController.lock();
198
+ /**
199
+ * When using an inline toast
200
+ * and dismissing a toast it is possible to
201
+ * quickly present the toast while it is
202
+ * dismissing. We need to await any current
203
+ * transition to allow the dismiss to finish
204
+ * before presenting again.
205
+ */
206
+ if (this.currentTransition !== undefined) {
207
+ await this.currentTransition;
208
+ }
200
209
  await this.delegateController.attachViewToDom();
201
- await overlays.present(this, 'toastEnter', iosEnterAnimation, mdEnterAnimation, this.position);
210
+ this.currentTransition = overlays.present(this, 'toastEnter', iosEnterAnimation, mdEnterAnimation, this.position);
211
+ await this.currentTransition;
202
212
  /**
203
213
  * Content is revealed to screen readers after
204
214
  * the transition to avoid jank since this
205
215
  * state updates will cause a re-render.
206
216
  */
207
217
  this.revealContentToScreenReader = true;
218
+ this.currentTransition = undefined;
208
219
  if (this.duration > 0) {
209
220
  this.durationTimeout = setTimeout(() => this.dismiss(undefined, 'timeout'), this.duration);
210
221
  }
211
- unlock();
212
222
  }
213
223
  /**
214
224
  * Dismiss the toast overlay after it has been presented.
@@ -220,16 +230,15 @@ const Toast = class {
220
230
  * Some examples include: ``"cancel"`, `"destructive"`, "selected"`, and `"backdrop"`.
221
231
  */
222
232
  async dismiss(data, role) {
223
- const unlock = await this.lockController.lock();
224
233
  if (this.durationTimeout) {
225
234
  clearTimeout(this.durationTimeout);
226
235
  }
227
- const dismissed = await overlays.dismiss(this, data, role, 'toastLeave', iosLeaveAnimation, mdLeaveAnimation, this.position);
236
+ this.currentTransition = overlays.dismiss(this, data, role, 'toastLeave', iosLeaveAnimation, mdLeaveAnimation, this.position);
237
+ const dismissed = await this.currentTransition;
228
238
  if (dismissed) {
229
239
  this.delegateController.removeViewFromDom();
230
240
  this.revealContentToScreenReader = false;
231
241
  }
232
- unlock();
233
242
  return dismissed;
234
243
  }
235
244
  /**
@@ -4,7 +4,7 @@
4
4
  'use strict';
5
5
 
6
6
  const ionicGlobal = require('./ionic-global-f81d8b73.js');
7
- const frameworkDelegate = require('./framework-delegate-e8174951.js');
7
+ const frameworkDelegate = require('./framework-delegate-91be3b84.js');
8
8
  const hardwareBackButton = require('./hardware-back-button-b67c8e75.js');
9
9
  const helpers = require('./helpers-ea4ccbcb.js');
10
10
  const index = require('./index-cc7dfb7c.js');
@@ -619,27 +619,6 @@ const createDelegateController = (ref) => {
619
619
  removeViewFromDom,
620
620
  };
621
621
  };
622
- /**
623
- * Creates a lock controller.
624
- *
625
- * This function locks transitions.
626
- * The unlock() function within it calls resolve on this function, unlocking the transitions.
627
- */
628
- const createLockController = () => {
629
- let waitPromise;
630
- const lock = async () => {
631
- const p = waitPromise;
632
- let resolve;
633
- waitPromise = new Promise((r) => (resolve = r));
634
- if (p !== undefined) {
635
- await p;
636
- }
637
- return resolve;
638
- };
639
- return {
640
- lock,
641
- };
642
- };
643
622
  /**
644
623
  * Constructs a trigger interaction for an overlay.
645
624
  * Presents an overlay when the trigger is clicked.
@@ -697,7 +676,6 @@ exports.actionSheetController = actionSheetController;
697
676
  exports.activeAnimations = activeAnimations;
698
677
  exports.alertController = alertController;
699
678
  exports.createDelegateController = createDelegateController;
700
- exports.createLockController = createLockController;
701
679
  exports.createTriggerController = createTriggerController;
702
680
  exports.dismiss = dismiss;
703
681
  exports.eventMethod = eventMethod;
@@ -4,7 +4,7 @@
4
4
  import { Host, h, readTask } from "@stencil/core";
5
5
  import { createButtonActiveGesture } from "../../utils/gesture/button-active";
6
6
  import { raf } from "../../utils/helpers";
7
- import { BACKDROP, createDelegateController, createLockController, createTriggerController, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall, setOverlayId, } from "../../utils/overlays";
7
+ import { BACKDROP, createDelegateController, createTriggerController, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall, setOverlayId, } from "../../utils/overlays";
8
8
  import { getClassMap } from "../../utils/theme";
9
9
  import { getIonMode } from "../../global/ionic-global";
10
10
  import { iosEnterAnimation } from "./animations/ios.enter";
@@ -17,7 +17,6 @@ import { mdLeaveAnimation } from "./animations/md.leave";
17
17
  export class ActionSheet {
18
18
  constructor() {
19
19
  this.delegateController = createDelegateController(this);
20
- this.lockController = createLockController();
21
20
  this.triggerController = createTriggerController();
22
21
  this.presented = false;
23
22
  this.onBackdropTap = () => {
@@ -65,10 +64,21 @@ export class ActionSheet {
65
64
  * Present the action sheet overlay after it has been created.
66
65
  */
67
66
  async present() {
68
- const unlock = await this.lockController.lock();
67
+ /**
68
+ * When using an inline action sheet
69
+ * and dismissing a action sheet it is possible to
70
+ * quickly present the action sheet while it is
71
+ * dismissing. We need to await any current
72
+ * transition to allow the dismiss to finish
73
+ * before presenting again.
74
+ */
75
+ if (this.currentTransition !== undefined) {
76
+ await this.currentTransition;
77
+ }
69
78
  await this.delegateController.attachViewToDom();
70
- await present(this, 'actionSheetEnter', iosEnterAnimation, mdEnterAnimation);
71
- unlock();
79
+ this.currentTransition = present(this, 'actionSheetEnter', iosEnterAnimation, mdEnterAnimation);
80
+ await this.currentTransition;
81
+ this.currentTransition = undefined;
72
82
  }
73
83
  /**
74
84
  * Dismiss the action sheet overlay after it has been presented.
@@ -80,12 +90,11 @@ export class ActionSheet {
80
90
  * Some examples include: ``"cancel"`, `"destructive"`, "selected"`, and `"backdrop"`.
81
91
  */
82
92
  async dismiss(data, role) {
83
- const unlock = await this.lockController.lock();
84
- const dismissed = await dismiss(this, data, role, 'actionSheetLeave', iosLeaveAnimation, mdLeaveAnimation);
93
+ this.currentTransition = dismiss(this, data, role, 'actionSheetLeave', iosLeaveAnimation, mdLeaveAnimation);
94
+ const dismissed = await this.currentTransition;
85
95
  if (dismissed) {
86
96
  this.delegateController.removeViewFromDom();
87
97
  }
88
- unlock();
89
98
  return dismissed;
90
99
  }
91
100
  /**
@@ -5,7 +5,7 @@ import { Host, forceUpdate, h } from "@stencil/core";
5
5
  import { ENABLE_HTML_CONTENT_DEFAULT } from "../../utils/config";
6
6
  import { createButtonActiveGesture } from "../../utils/gesture/button-active";
7
7
  import { raf } from "../../utils/helpers";
8
- import { createDelegateController, createLockController, createTriggerController, BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall, setOverlayId, } from "../../utils/overlays";
8
+ import { createDelegateController, createTriggerController, BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall, setOverlayId, } from "../../utils/overlays";
9
9
  import { sanitizeDOMString } from "../../utils/sanitization/index";
10
10
  import { getClassMap } from "../../utils/theme";
11
11
  import { config } from "../../global/config";
@@ -21,7 +21,6 @@ import { mdLeaveAnimation } from "./animations/md.leave";
21
21
  export class Alert {
22
22
  constructor() {
23
23
  this.delegateController = createDelegateController(this);
24
- this.lockController = createLockController();
25
24
  this.triggerController = createTriggerController();
26
25
  this.customHTMLEnabled = config.get('innerHTMLTemplatesEnabled', ENABLE_HTML_CONTENT_DEFAULT);
27
26
  this.processedInputs = [];
@@ -188,10 +187,21 @@ export class Alert {
188
187
  * Present the alert overlay after it has been created.
189
188
  */
190
189
  async present() {
191
- const unlock = await this.lockController.lock();
190
+ /**
191
+ * When using an inline alert
192
+ * and dismissing an alert it is possible to
193
+ * quickly present the alert while it is
194
+ * dismissing. We need to await any current
195
+ * transition to allow the dismiss to finish
196
+ * before presenting again.
197
+ */
198
+ if (this.currentTransition !== undefined) {
199
+ await this.currentTransition;
200
+ }
192
201
  await this.delegateController.attachViewToDom();
193
- await present(this, 'alertEnter', iosEnterAnimation, mdEnterAnimation);
194
- unlock();
202
+ this.currentTransition = present(this, 'alertEnter', iosEnterAnimation, mdEnterAnimation);
203
+ await this.currentTransition;
204
+ this.currentTransition = undefined;
195
205
  }
196
206
  /**
197
207
  * Dismiss the alert overlay after it has been presented.
@@ -203,12 +213,11 @@ export class Alert {
203
213
  * Some examples include: ``"cancel"`, `"destructive"`, "selected"`, and `"backdrop"`.
204
214
  */
205
215
  async dismiss(data, role) {
206
- const unlock = await this.lockController.lock();
207
- const dismissed = await dismiss(this, data, role, 'alertLeave', iosLeaveAnimation, mdLeaveAnimation);
216
+ this.currentTransition = dismiss(this, data, role, 'alertLeave', iosLeaveAnimation, mdLeaveAnimation);
217
+ const dismissed = await this.currentTransition;
208
218
  if (dismissed) {
209
219
  this.delegateController.removeViewFromDom();
210
220
  }
211
- unlock();
212
221
  return dismissed;
213
222
  }
214
223
  /**
@@ -4,7 +4,7 @@
4
4
  import { Host, h } from "@stencil/core";
5
5
  import { ENABLE_HTML_CONTENT_DEFAULT } from "../../utils/config";
6
6
  import { raf } from "../../utils/helpers";
7
- import { BACKDROP, dismiss, eventMethod, prepareOverlay, present, createDelegateController, createLockController, createTriggerController, setOverlayId, } from "../../utils/overlays";
7
+ import { BACKDROP, dismiss, eventMethod, prepareOverlay, present, createDelegateController, createTriggerController, setOverlayId, } from "../../utils/overlays";
8
8
  import { sanitizeDOMString } from "../../utils/sanitization/index";
9
9
  import { getClassMap } from "../../utils/theme";
10
10
  import { config } from "../../global/config";
@@ -20,7 +20,6 @@ import { mdLeaveAnimation } from "./animations/md.leave";
20
20
  export class Loading {
21
21
  constructor() {
22
22
  this.delegateController = createDelegateController(this);
23
- this.lockController = createLockController();
24
23
  this.triggerController = createTriggerController();
25
24
  this.customHTMLEnabled = config.get('innerHTMLTemplatesEnabled', ENABLE_HTML_CONTENT_DEFAULT);
26
25
  this.presented = false;
@@ -86,13 +85,24 @@ export class Loading {
86
85
  * Present the loading overlay after it has been created.
87
86
  */
88
87
  async present() {
89
- const unlock = await this.lockController.lock();
88
+ /**
89
+ * When using an inline loading indicator
90
+ * and dismissing a loading indicator it is possible to
91
+ * quickly present the loading indicator while it is
92
+ * dismissing. We need to await any current
93
+ * transition to allow the dismiss to finish
94
+ * before presenting again.
95
+ */
96
+ if (this.currentTransition !== undefined) {
97
+ await this.currentTransition;
98
+ }
90
99
  await this.delegateController.attachViewToDom();
91
- await present(this, 'loadingEnter', iosEnterAnimation, mdEnterAnimation);
100
+ this.currentTransition = present(this, 'loadingEnter', iosEnterAnimation, mdEnterAnimation);
101
+ await this.currentTransition;
92
102
  if (this.duration > 0) {
93
103
  this.durationTimeout = setTimeout(() => this.dismiss(), this.duration + 10);
94
104
  }
95
- unlock();
105
+ this.currentTransition = undefined;
96
106
  }
97
107
  /**
98
108
  * Dismiss the loading overlay after it has been presented.
@@ -104,15 +114,14 @@ export class Loading {
104
114
  * Some examples include: ``"cancel"`, `"destructive"`, "selected"`, and `"backdrop"`.
105
115
  */
106
116
  async dismiss(data, role) {
107
- const unlock = await this.lockController.lock();
108
117
  if (this.durationTimeout) {
109
118
  clearTimeout(this.durationTimeout);
110
119
  }
111
- const dismissed = await dismiss(this, data, role, 'loadingLeave', iosLeaveAnimation, mdLeaveAnimation);
120
+ this.currentTransition = dismiss(this, data, role, 'loadingLeave', iosLeaveAnimation, mdLeaveAnimation);
121
+ const dismissed = await this.currentTransition;
112
122
  if (dismissed) {
113
123
  this.delegateController.removeViewFromDom();
114
124
  }
115
- unlock();
116
125
  return dismissed;
117
126
  }
118
127
  /**
@@ -7,7 +7,7 @@ import { CoreDelegate, attachComponent, detachComponent } from "../../utils/fram
7
7
  import { raf, inheritAttributes, hasLazyBuild } from "../../utils/helpers";
8
8
  import { printIonWarning } from "../../utils/logging/index";
9
9
  import { Style as StatusBarStyle, StatusBar } from "../../utils/native/status-bar";
10
- import { GESTURE, BACKDROP, activeAnimations, dismiss, eventMethod, prepareOverlay, present, createLockController, createTriggerController, setOverlayId, } from "../../utils/overlays";
10
+ import { GESTURE, BACKDROP, activeAnimations, dismiss, eventMethod, prepareOverlay, present, createTriggerController, setOverlayId, } from "../../utils/overlays";
11
11
  import { getClassMap } from "../../utils/theme";
12
12
  import { deepReady, waitForMount } from "../../utils/transition/index";
13
13
  import { config } from "../../global/config";
@@ -32,7 +32,6 @@ import { setCardStatusBarDark, setCardStatusBarDefault } from "./utils";
32
32
  */
33
33
  export class Modal {
34
34
  constructor() {
35
- this.lockController = createLockController();
36
35
  this.triggerController = createTriggerController();
37
36
  this.coreDelegate = CoreDelegate();
38
37
  this.isSheetModal = false;
@@ -200,16 +199,26 @@ export class Modal {
200
199
  if (this.presented) {
201
200
  return;
202
201
  }
203
- const unlock = await this.lockController.lock();
204
202
  const { presentingElement, el } = this;
203
+ /**
204
+ * When using an inline modal
205
+ * and dismissing a modal it is possible to
206
+ * quickly present the modal while it is
207
+ * dismissing. We need to await any current
208
+ * transition to allow the dismiss to finish
209
+ * before presenting again.
210
+ */
211
+ if (this.currentTransition !== undefined) {
212
+ await this.currentTransition;
213
+ }
205
214
  /**
206
215
  * If the modal is presented multiple times (inline modals), we
207
216
  * need to reset the current breakpoint to the initial breakpoint.
208
217
  */
209
218
  this.currentBreakpoint = this.initialBreakpoint;
210
219
  const { inline, delegate } = this.getDelegate(true);
211
- this.usersElement = await attachComponent(delegate, el, this.component, ['ion-page'], this.componentProps, inline);
212
220
  this.ionMount.emit();
221
+ this.usersElement = await attachComponent(delegate, el, this.component, ['ion-page'], this.componentProps, inline);
213
222
  /**
214
223
  * When using the lazy loaded build of Stencil, we need to wait
215
224
  * for every Stencil component instance to be ready before presenting
@@ -233,6 +242,11 @@ export class Modal {
233
242
  await waitForMount();
234
243
  }
235
244
  writeTask(() => this.el.classList.add('show-modal'));
245
+ this.currentTransition = present(this, 'modalEnter', iosEnterAnimation, mdEnterAnimation, {
246
+ presentingEl: presentingElement,
247
+ currentBreakpoint: this.initialBreakpoint,
248
+ backdropBreakpoint: this.backdropBreakpoint,
249
+ });
236
250
  /* tslint:disable-next-line */
237
251
  if (typeof window !== 'undefined') {
238
252
  /**
@@ -275,18 +289,14 @@ export class Modal {
275
289
  this.statusBarStyle = await StatusBar.getStyle();
276
290
  setCardStatusBarDark();
277
291
  }
278
- await present(this, 'modalEnter', iosEnterAnimation, mdEnterAnimation, {
279
- presentingEl: presentingElement,
280
- currentBreakpoint: this.initialBreakpoint,
281
- backdropBreakpoint: this.backdropBreakpoint,
282
- });
292
+ await this.currentTransition;
283
293
  if (this.isSheetModal) {
284
294
  this.initSheetGesture();
285
295
  }
286
296
  else if (hasCardModal) {
287
297
  this.initSwipeToClose();
288
298
  }
289
- unlock();
299
+ this.currentTransition = undefined;
290
300
  }
291
301
  initSwipeToClose() {
292
302
  var _a;
@@ -376,7 +386,6 @@ export class Modal {
376
386
  if (this.gestureAnimationDismissing && role !== GESTURE) {
377
387
  return false;
378
388
  }
379
- const unlock = await this.lockController.lock();
380
389
  /**
381
390
  * If a canDismiss handler is responsible
382
391
  * for calling the dismiss method, we should
@@ -400,12 +409,24 @@ export class Modal {
400
409
  window.removeEventListener(KEYBOARD_DID_OPEN, this.keyboardOpenCallback);
401
410
  this.keyboardOpenCallback = undefined;
402
411
  }
412
+ /**
413
+ * When using an inline modal
414
+ * and presenting a modal it is possible to
415
+ * quickly dismiss the modal while it is
416
+ * presenting. We need to await any current
417
+ * transition to allow the present to finish
418
+ * before dismissing again.
419
+ */
420
+ if (this.currentTransition !== undefined) {
421
+ await this.currentTransition;
422
+ }
403
423
  const enteringAnimation = activeAnimations.get(this) || [];
404
- const dismissed = await dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation, {
424
+ this.currentTransition = dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation, {
405
425
  presentingEl: presentingElement,
406
426
  currentBreakpoint: (_a = this.currentBreakpoint) !== null && _a !== void 0 ? _a : this.initialBreakpoint,
407
427
  backdropBreakpoint: this.backdropBreakpoint,
408
428
  });
429
+ const dismissed = await this.currentTransition;
409
430
  if (dismissed) {
410
431
  const { delegate } = this.getDelegate();
411
432
  await detachComponent(delegate, this.usersElement);
@@ -419,8 +440,8 @@ export class Modal {
419
440
  enteringAnimation.forEach((ani) => ani.destroy());
420
441
  }
421
442
  this.currentBreakpoint = undefined;
443
+ this.currentTransition = undefined;
422
444
  this.animation = undefined;
423
- unlock();
424
445
  return dismissed;
425
446
  }
426
447
  /**
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { Host, h } from "@stencil/core";
5
5
  import { raf } from "../../utils/helpers";
6
- import { createDelegateController, createLockController, createTriggerController, BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall, setOverlayId, } from "../../utils/overlays";
6
+ import { createDelegateController, createTriggerController, BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall, setOverlayId, } from "../../utils/overlays";
7
7
  import { getClassMap } from "../../utils/theme";
8
8
  import { getIonMode } from "../../global/ionic-global";
9
9
  import { iosEnterAnimation } from "./animations/ios.enter";
@@ -15,7 +15,6 @@ import { iosLeaveAnimation } from "./animations/ios.leave";
15
15
  export class Picker {
16
16
  constructor() {
17
17
  this.delegateController = createDelegateController(this);
18
- this.lockController = createLockController();
19
18
  this.triggerController = createTriggerController();
20
19
  this.onBackdropTap = () => {
21
20
  this.dismiss(undefined, BACKDROP);
@@ -82,13 +81,24 @@ export class Picker {
82
81
  * Present the picker overlay after it has been created.
83
82
  */
84
83
  async present() {
85
- const unlock = await this.lockController.lock();
84
+ /**
85
+ * When using an inline picker
86
+ * and dismissing an picker it is possible to
87
+ * quickly present the picker while it is
88
+ * dismissing. We need to await any current
89
+ * transition to allow the dismiss to finish
90
+ * before presenting again.
91
+ */
92
+ if (this.currentTransition !== undefined) {
93
+ await this.currentTransition;
94
+ }
86
95
  await this.delegateController.attachViewToDom();
87
- await present(this, 'pickerEnter', iosEnterAnimation, iosEnterAnimation, undefined);
96
+ this.currentTransition = present(this, 'pickerEnter', iosEnterAnimation, iosEnterAnimation, undefined);
97
+ await this.currentTransition;
98
+ this.currentTransition = undefined;
88
99
  if (this.duration > 0) {
89
100
  this.durationTimeout = setTimeout(() => this.dismiss(), this.duration);
90
101
  }
91
- unlock();
92
102
  }
93
103
  /**
94
104
  * Dismiss the picker overlay after it has been presented.
@@ -100,15 +110,14 @@ export class Picker {
100
110
  * Some examples include: ``"cancel"`, `"destructive"`, "selected"`, and `"backdrop"`.
101
111
  */
102
112
  async dismiss(data, role) {
103
- const unlock = await this.lockController.lock();
104
113
  if (this.durationTimeout) {
105
114
  clearTimeout(this.durationTimeout);
106
115
  }
107
- const dismissed = await dismiss(this, data, role, 'pickerLeave', iosLeaveAnimation, iosLeaveAnimation);
116
+ this.currentTransition = dismiss(this, data, role, 'pickerLeave', iosLeaveAnimation, iosLeaveAnimation);
117
+ const dismissed = await this.currentTransition;
108
118
  if (dismissed) {
109
119
  this.delegateController.removeViewFromDom();
110
120
  }
111
- unlock();
112
121
  return dismissed;
113
122
  }
114
123
  /**
@@ -5,7 +5,7 @@ import { Host, h } from "@stencil/core";
5
5
  import { CoreDelegate, attachComponent, detachComponent } from "../../utils/framework-delegate";
6
6
  import { addEventListener, raf, hasLazyBuild } from "../../utils/helpers";
7
7
  import { printIonWarning } from "../../utils/logging/index";
8
- import { BACKDROP, createLockController, dismiss, eventMethod, focusFirstDescendant, prepareOverlay, present, setOverlayId, } from "../../utils/overlays";
8
+ import { BACKDROP, dismiss, eventMethod, focusFirstDescendant, prepareOverlay, present, setOverlayId, } from "../../utils/overlays";
9
9
  import { isPlatform } from "../../utils/platform";
10
10
  import { getClassMap } from "../../utils/theme";
11
11
  import { deepReady, waitForMount } from "../../utils/transition/index";
@@ -29,7 +29,6 @@ export class Popover {
29
29
  constructor() {
30
30
  this.parentPopover = null;
31
31
  this.coreDelegate = CoreDelegate();
32
- this.lockController = createLockController();
33
32
  this.inline = false;
34
33
  this.focusDescendantOnPresent = false;
35
34
  this.onBackdropTap = () => {
@@ -206,15 +205,25 @@ export class Popover {
206
205
  if (this.presented) {
207
206
  return;
208
207
  }
209
- const unlock = await this.lockController.lock();
208
+ /**
209
+ * When using an inline popover
210
+ * and dismissing a popover it is possible to
211
+ * quickly present the popover while it is
212
+ * dismissing. We need to await any current
213
+ * transition to allow the dismiss to finish
214
+ * before presenting again.
215
+ */
216
+ if (this.currentTransition !== undefined) {
217
+ await this.currentTransition;
218
+ }
210
219
  const { el } = this;
211
220
  const { inline, delegate } = this.getDelegate(true);
221
+ this.ionMount.emit();
212
222
  this.usersElement = await attachComponent(delegate, el, this.component, ['popover-viewport'], this.componentProps, inline);
213
223
  if (!this.keyboardEvents) {
214
224
  this.configureKeyboardInteraction();
215
225
  }
216
226
  this.configureDismissInteraction();
217
- this.ionMount.emit();
218
227
  /**
219
228
  * When using the lazy loaded build of Stencil, we need to wait
220
229
  * for every Stencil component instance to be ready before presenting
@@ -237,7 +246,7 @@ export class Popover {
237
246
  else if (!this.keepContentsMounted) {
238
247
  await waitForMount();
239
248
  }
240
- await present(this, 'popoverEnter', iosEnterAnimation, mdEnterAnimation, {
249
+ this.currentTransition = present(this, 'popoverEnter', iosEnterAnimation, mdEnterAnimation, {
241
250
  event: event || this.event,
242
251
  size: this.size,
243
252
  trigger: this.triggerEl,
@@ -245,6 +254,8 @@ export class Popover {
245
254
  side: this.side,
246
255
  align: this.alignment,
247
256
  });
257
+ await this.currentTransition;
258
+ this.currentTransition = undefined;
248
259
  /**
249
260
  * If popover is nested and was
250
261
  * presented using the "Right" arrow key,
@@ -254,7 +265,6 @@ export class Popover {
254
265
  if (this.focusDescendantOnPresent) {
255
266
  focusFirstDescendant(this.el, this.el);
256
267
  }
257
- unlock();
258
268
  }
259
269
  /**
260
270
  * Dismiss the popover overlay after it has been presented.
@@ -265,12 +275,23 @@ export class Popover {
265
275
  * a parent popover if this popover is nested. Defaults to `true`.
266
276
  */
267
277
  async dismiss(data, role, dismissParentPopover = true) {
268
- const unlock = await this.lockController.lock();
278
+ /**
279
+ * When using an inline popover
280
+ * and presenting a popover it is possible to
281
+ * quickly dismiss the popover while it is
282
+ * presenting. We need to await any current
283
+ * transition to allow the present to finish
284
+ * before dismissing again.
285
+ */
286
+ if (this.currentTransition !== undefined) {
287
+ await this.currentTransition;
288
+ }
269
289
  const { destroyKeyboardInteraction, destroyDismissInteraction } = this;
270
290
  if (dismissParentPopover && this.parentPopover) {
271
291
  this.parentPopover.dismiss(data, role, dismissParentPopover);
272
292
  }
273
- const shouldDismiss = await dismiss(this, data, role, 'popoverLeave', iosLeaveAnimation, mdLeaveAnimation, this.event);
293
+ this.currentTransition = dismiss(this, data, role, 'popoverLeave', iosLeaveAnimation, mdLeaveAnimation, this.event);
294
+ const shouldDismiss = await this.currentTransition;
274
295
  if (shouldDismiss) {
275
296
  if (destroyKeyboardInteraction) {
276
297
  destroyKeyboardInteraction();
@@ -288,7 +309,7 @@ export class Popover {
288
309
  const { delegate } = this.getDelegate();
289
310
  await detachComponent(delegate, this.usersElement);
290
311
  }
291
- unlock();
312
+ this.currentTransition = undefined;
292
313
  return shouldDismiss;
293
314
  }
294
315
  /**
@@ -0,0 +1,20 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { expect } from "@playwright/test";
5
+ import { configs, test } from "../../../../utils/test/playwright/index";
6
+ /**
7
+ * This behavior does not vary across modes/directions
8
+ */
9
+ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
10
+ test.describe(title('popover: alignment with async component'), async () => {
11
+ test('should align popover centered with button when component is added async', async ({ page }) => {
12
+ await page.goto('/src/components/popover/test/async', config);
13
+ const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
14
+ const button = page.locator('#button');
15
+ await button.click();
16
+ await ionPopoverDidPresent.next();
17
+ await expect(page).toHaveScreenshot(screenshot(`popover-async`));
18
+ });
19
+ });
20
+ });