@ionic/core 7.5.4-dev.11699469920.1af6ea12 → 7.5.4-dev.11699632730.1e6d9b70

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 (121) hide show
  1. package/components/ion-modal.js +2 -2
  2. package/components/ion-select.js +1 -23
  3. package/components/ion-toast.js +67 -417
  4. package/components/overlays.js +1 -2
  5. package/components/radio-group.js +2 -0
  6. package/components/radio.js +40 -2
  7. package/css/ionic.bundle.css +1 -1
  8. package/css/ionic.bundle.css.map +1 -1
  9. package/css/themes/dark.css +135 -0
  10. package/css/themes/dark.css.map +1 -0
  11. package/css/utils.bundle.css +133 -0
  12. package/css/utils.bundle.css.map +1 -1
  13. package/dist/cjs/compare-with-utils-c0444525.js +44 -0
  14. package/dist/cjs/index.cjs.js +1 -1
  15. package/dist/cjs/ion-action-sheet.cjs.entry.js +1 -1
  16. package/dist/cjs/ion-alert.cjs.entry.js +1 -1
  17. package/dist/cjs/ion-datetime_3.cjs.entry.js +1 -1
  18. package/dist/cjs/ion-loading.cjs.entry.js +1 -1
  19. package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
  20. package/dist/cjs/ion-modal.cjs.entry.js +2 -2
  21. package/dist/cjs/ion-popover.cjs.entry.js +1 -1
  22. package/dist/cjs/ion-radio_2.cjs.entry.js +4 -1
  23. package/dist/cjs/ion-select_3.cjs.entry.js +6 -27
  24. package/dist/cjs/ion-toast.cjs.entry.js +83 -430
  25. package/dist/cjs/ionic.cjs.js +1 -1
  26. package/dist/cjs/loader.cjs.js +1 -1
  27. package/dist/cjs/{overlays-ba1a1e21.js → overlays-d80a2cf2.js} +0 -2
  28. package/dist/collection/components/modal/gestures/swipe-to-close.js +1 -2
  29. package/dist/collection/components/radio/radio.js +3 -2
  30. package/dist/collection/components/radio-group/radio-group.js +24 -0
  31. package/dist/collection/components/select/select.js +2 -24
  32. package/dist/collection/components/toast/animations/ios.enter.js +1 -2
  33. package/dist/collection/components/toast/animations/md.enter.js +1 -2
  34. package/dist/collection/components/toast/animations/utils.js +0 -11
  35. package/dist/collection/components/toast/toast.js +1 -104
  36. package/dist/collection/utils/forms/compare-with-utils.js +39 -0
  37. package/dist/collection/utils/forms/index.js +1 -0
  38. package/dist/collection/utils/overlays.js +0 -1
  39. package/dist/docs.json +43 -38
  40. package/dist/esm/compare-with-utils-4928c09d.js +41 -0
  41. package/dist/esm/index.js +1 -1
  42. package/dist/esm/ion-action-sheet.entry.js +1 -1
  43. package/dist/esm/ion-alert.entry.js +1 -1
  44. package/dist/esm/ion-datetime_3.entry.js +1 -1
  45. package/dist/esm/ion-loading.entry.js +1 -1
  46. package/dist/esm/ion-menu_3.entry.js +1 -1
  47. package/dist/esm/ion-modal.entry.js +2 -2
  48. package/dist/esm/ion-popover.entry.js +1 -1
  49. package/dist/esm/ion-radio_2.entry.js +4 -1
  50. package/dist/esm/ion-select_3.entry.js +2 -23
  51. package/dist/esm/ion-toast.entry.js +66 -413
  52. package/dist/esm/ionic.js +1 -1
  53. package/dist/esm/loader.js +1 -1
  54. package/dist/esm/{overlays-d79b34b4.js → overlays-a31c8878.js} +1 -2
  55. package/dist/esm-es5/compare-with-utils-4928c09d.js +4 -0
  56. package/dist/esm-es5/index.js +1 -1
  57. package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
  58. package/dist/esm-es5/ion-alert.entry.js +1 -1
  59. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  60. package/dist/esm-es5/ion-loading.entry.js +1 -1
  61. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  62. package/dist/esm-es5/ion-modal.entry.js +1 -1
  63. package/dist/esm-es5/ion-popover.entry.js +1 -1
  64. package/dist/esm-es5/ion-radio_2.entry.js +1 -1
  65. package/dist/esm-es5/ion-select_3.entry.js +1 -1
  66. package/dist/esm-es5/ion-toast.entry.js +1 -1
  67. package/dist/esm-es5/ionic.js +1 -1
  68. package/dist/esm-es5/loader.js +1 -1
  69. package/dist/esm-es5/{overlays-d79b34b4.js → overlays-a31c8878.js} +1 -1
  70. package/dist/html.html-data.json +5 -10
  71. package/dist/ionic/index.esm.js +1 -1
  72. package/dist/ionic/ionic.esm.js +1 -1
  73. package/dist/ionic/p-02663394.system.js +1 -1
  74. package/dist/ionic/p-139bd79d.system.entry.js +4 -0
  75. package/dist/ionic/{p-3dedd258.system.entry.js → p-1e59dd04.system.entry.js} +1 -1
  76. package/dist/ionic/{p-938c4956.js → p-307963db.js} +1 -1
  77. package/dist/ionic/{p-1fc6b5a5.system.entry.js → p-3a769110.system.entry.js} +1 -1
  78. package/dist/ionic/p-3bc3d880.system.js +4 -0
  79. package/dist/ionic/p-43716898.js +4 -0
  80. package/dist/ionic/{p-1511dc35.system.js → p-4c75cb48.system.js} +1 -1
  81. package/dist/ionic/p-539c09e8.system.entry.js +4 -0
  82. package/dist/ionic/{p-e525dbea.entry.js → p-53b1930e.entry.js} +1 -1
  83. package/dist/ionic/{p-ab1908ba.system.entry.js → p-59107f99.system.entry.js} +1 -1
  84. package/dist/ionic/p-6b45cfd0.system.entry.js +4 -0
  85. package/dist/ionic/{p-664cc492.entry.js → p-75338011.entry.js} +1 -1
  86. package/dist/ionic/p-7d68e4ea.entry.js +4 -0
  87. package/dist/ionic/{p-78a8e1e8.entry.js → p-8140a084.entry.js} +1 -1
  88. package/dist/ionic/{p-2151a4a4.system.entry.js → p-90020ef0.system.entry.js} +1 -1
  89. package/dist/ionic/{p-53f75103.system.js → p-98c70e3c.system.js} +1 -1
  90. package/dist/ionic/p-999a7271.entry.js +4 -0
  91. package/dist/ionic/p-a4e4dba1.entry.js +4 -0
  92. package/dist/ionic/{p-138a4a93.entry.js → p-b86c6c05.entry.js} +1 -1
  93. package/dist/ionic/p-be499f29.entry.js +4 -0
  94. package/dist/ionic/{p-a9424586.entry.js → p-c09fa14d.entry.js} +1 -1
  95. package/dist/ionic/{p-020dd47f.entry.js → p-c32a6c04.entry.js} +1 -1
  96. package/dist/ionic/{p-81bdfa1c.system.entry.js → p-d54a8393.system.entry.js} +1 -1
  97. package/dist/ionic/p-e66f7d10.system.entry.js +4 -0
  98. package/dist/ionic/{p-cb6c380e.system.entry.js → p-e91c7eb4.system.entry.js} +1 -1
  99. package/dist/types/components/radio-group/radio-group-interface.d.ts +1 -0
  100. package/dist/types/components/radio-group/radio-group.d.ts +8 -1
  101. package/dist/types/components/select/select.d.ts +4 -1
  102. package/dist/types/components/toast/animations/utils.d.ts +0 -9
  103. package/dist/types/components/toast/toast-interface.d.ts +0 -1
  104. package/dist/types/components/toast/toast.d.ts +1 -28
  105. package/dist/types/components.d.ts +14 -14
  106. package/dist/types/utils/forms/compare-with-utils.d.ts +18 -0
  107. package/dist/types/utils/forms/index.d.ts +1 -0
  108. package/dist/types/utils/overlays.d.ts +0 -1
  109. package/hydrate/index.js +107 -436
  110. package/package.json +1 -1
  111. package/dist/collection/components/toast/gestures/swipe-to-dismiss.js +0 -267
  112. package/dist/collection/components/toast/test/swipe-gesture/toast.e2e.js +0 -84
  113. package/dist/ionic/p-344706aa.entry.js +0 -4
  114. package/dist/ionic/p-637d836a.system.entry.js +0 -4
  115. package/dist/ionic/p-6c89025e.system.entry.js +0 -4
  116. package/dist/ionic/p-8414ed31.entry.js +0 -4
  117. package/dist/ionic/p-d075c0aa.system.entry.js +0 -4
  118. package/dist/ionic/p-e3b7a2d0.system.entry.js +0 -4
  119. package/dist/ionic/p-ea1650b0.entry.js +0 -4
  120. package/dist/ionic/p-f2d4e3c8.entry.js +0 -4
  121. package/dist/types/components/toast/gestures/swipe-to-dismiss.d.ts +0 -9
@@ -8,7 +8,7 @@ import { g as getElementRoot, m as clamp, r as raf, d as inheritAttributes, l as
8
8
  import { c as createLockController } from './lock-controller.js';
9
9
  import { p as printIonWarning } from './index6.js';
10
10
  import { g as getCapacitor } from './capacitor.js';
11
- import { G as GESTURE, O as OVERLAY_GESTURE_PRIORITY, e as createTriggerController, B as BACKDROP, j as prepareOverlay, k as setOverlayId, f as present, q as activeAnimations, g as dismiss, h as eventMethod } from './overlays.js';
11
+ import { G as GESTURE, e as createTriggerController, B as BACKDROP, j as prepareOverlay, k as setOverlayId, f as present, q as activeAnimations, g as dismiss, h as eventMethod } from './overlays.js';
12
12
  import { g as getClassMap } from './theme.js';
13
13
  import { e as deepReady, w as waitForMount } from './index2.js';
14
14
  import { b as getIonMode, c as config } from './ionic-global.js';
@@ -502,7 +502,7 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) =>
502
502
  const gesture = createGesture({
503
503
  el,
504
504
  gestureName: 'modalSwipeToClose',
505
- gesturePriority: OVERLAY_GESTURE_PRIORITY,
505
+ gesturePriority: 39,
506
506
  direction: 'y',
507
507
  threshold: 10,
508
508
  canStart,
@@ -4,6 +4,7 @@
4
4
  import { proxyCustomElement, HTMLElement, createEvent, h, Host, forceUpdate } from '@stencil/core/internal/client';
5
5
  import { c as createLegacyFormController } from './form-controller.js';
6
6
  import { c as createNotchController } from './notch-controller.js';
7
+ import { i as isOptionSelected, c as compareOptions, d as defineCustomElement$5 } from './radio.js';
7
8
  import { d as inheritAttributes, f as focusElement, k as findItemLabel, e as renderHiddenInput, j as getAriaLabel } from './helpers.js';
8
9
  import { p as printIonWarning } from './index6.js';
9
10
  import { c as popoverController, b as actionSheetController, a as alertController } from './overlays.js';
@@ -23,7 +24,6 @@ import { d as defineCustomElement$9 } from './list.js';
23
24
  import { d as defineCustomElement$8 } from './list-header.js';
24
25
  import { d as defineCustomElement$7 } from './note.js';
25
26
  import { d as defineCustomElement$6 } from './popover.js';
26
- import { d as defineCustomElement$5 } from './radio.js';
27
27
  import { d as defineCustomElement$4 } from './radio-group.js';
28
28
  import { d as defineCustomElement$3 } from './ripple-effect.js';
29
29
  import { d as defineCustomElement$2 } from './select-popover.js';
@@ -688,17 +688,6 @@ Developers can use the "legacy" property to continue using the legacy form marku
688
688
  "placeholder": ["styleChanged"],
689
689
  "value": ["styleChanged"]
690
690
  }]);
691
- const isOptionSelected = (currentValue, compareValue, compareWith) => {
692
- if (currentValue === undefined) {
693
- return false;
694
- }
695
- if (Array.isArray(currentValue)) {
696
- return currentValue.some((val) => compareOptions(val, compareValue, compareWith));
697
- }
698
- else {
699
- return compareOptions(currentValue, compareValue, compareWith);
700
- }
701
- };
702
691
  const getOptionValue = (el) => {
703
692
  const value = el.value;
704
693
  return value === undefined ? el.textContent || '' : value;
@@ -712,17 +701,6 @@ const parseValue = (value) => {
712
701
  }
713
702
  return value.toString();
714
703
  };
715
- const compareOptions = (currentValue, compareValue, compareWith) => {
716
- if (typeof compareWith === 'function') {
717
- return compareWith(currentValue, compareValue);
718
- }
719
- else if (typeof compareWith === 'string') {
720
- return currentValue[compareWith] === compareValue[compareWith];
721
- }
722
- else {
723
- return Array.isArray(compareValue) ? compareValue.includes(currentValue) : currentValue === compareValue;
724
- }
725
- };
726
704
  const generateText = (opts, value, compareWith) => {
727
705
  if (value === undefined) {
728
706
  return '';
@@ -1,107 +1,19 @@
1
1
  /*!
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
- import { Build, proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
4
+ import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
5
5
  import { E as ENABLE_HTML_CONTENT_DEFAULT, a as sanitizeDOMString } from './config.js';
6
6
  import { g as getElementRoot, r as raf } from './helpers.js';
7
7
  import { c as createLockController } from './lock-controller.js';
8
8
  import { p as printIonWarning } from './index6.js';
9
- import { O as OVERLAY_GESTURE_PRIORITY, d as createDelegateController, e as createTriggerController, i as isCancel, j as prepareOverlay, k as setOverlayId, f as present, g as dismiss, h as eventMethod, s as safeCall, G as GESTURE } from './overlays.js';
9
+ import { d as createDelegateController, e as createTriggerController, i as isCancel, j as prepareOverlay, k as setOverlayId, f as present, g as dismiss, h as eventMethod, s as safeCall } from './overlays.js';
10
10
  import { g as getClassMap, c as createColorClasses } from './theme.js';
11
11
  import { c as config, b as getIonMode } from './ionic-global.js';
12
12
  import { c as createAnimation } from './animation.js';
13
13
  import { w as win } from './index5.js';
14
- import { createGesture } from './index3.js';
15
14
  import { d as defineCustomElement$3 } from './icon.js';
16
15
  import { d as defineCustomElement$2 } from './ripple-effect.js';
17
16
 
18
- /**
19
- * Calculate the CSS top and bottom position of the toast, to be used
20
- * as starting points for the animation keyframes.
21
- *
22
- * The default animations for both MD and iOS
23
- * use translateY, which calculates from the
24
- * top edge of the screen. This behavior impacts
25
- * how we compute the offset when a toast has
26
- * position='bottom' since we need to calculate from
27
- * the bottom edge of the screen instead.
28
- *
29
- * @param position The value of the toast's position prop.
30
- * @param positionAnchor The element the toast should be anchored to,
31
- * if applicable.
32
- * @param mode The toast component's mode (md, ios, etc).
33
- * @param toast A reference to the toast element itself.
34
- */
35
- function getAnimationPosition(position, positionAnchor, mode, toast) {
36
- /**
37
- * Start with a predefined offset from the edge the toast will be
38
- * positioned relative to, whether on the screen or anchor element.
39
- */
40
- let offset;
41
- if (mode === 'md') {
42
- offset = position === 'top' ? 8 : -8;
43
- }
44
- else {
45
- offset = position === 'top' ? 10 : -10;
46
- }
47
- /**
48
- * If positionAnchor is defined, add in the distance from the target
49
- * screen edge to the target anchor edge. For position="top", the
50
- * bottom anchor edge is targeted. For position="bottom", the top
51
- * anchor edge is targeted.
52
- */
53
- if (positionAnchor && win) {
54
- warnIfAnchorIsHidden(positionAnchor, toast);
55
- const box = positionAnchor.getBoundingClientRect();
56
- if (position === 'top') {
57
- offset += box.bottom;
58
- }
59
- else if (position === 'bottom') {
60
- /**
61
- * Just box.top is the distance from the top edge of the screen
62
- * to the top edge of the anchor. We want to calculate from the
63
- * bottom edge of the screen instead.
64
- */
65
- offset -= win.innerHeight - box.top;
66
- }
67
- /**
68
- * We don't include safe area here because that should already be
69
- * accounted for when checking the position of the anchor.
70
- */
71
- return {
72
- top: `${offset}px`,
73
- bottom: `${offset}px`,
74
- };
75
- }
76
- else {
77
- return {
78
- top: `calc(${offset}px + var(--ion-safe-area-top, 0px))`,
79
- bottom: `calc(${offset}px - var(--ion-safe-area-bottom, 0px))`,
80
- };
81
- }
82
- }
83
- /**
84
- * If the anchor element is hidden, getBoundingClientRect()
85
- * will return all 0s for it, which can cause unexpected
86
- * results in the position calculation when animating.
87
- */
88
- function warnIfAnchorIsHidden(positionAnchor, toast) {
89
- if (positionAnchor.offsetParent === null) {
90
- printIonWarning('The positionAnchor element for ion-toast was found in the DOM, but appears to be hidden. This may lead to unexpected positioning of the toast.', toast);
91
- }
92
- }
93
- /**
94
- * Returns the top offset required to place
95
- * the toast in the middle of the screen.
96
- * Only needed when position="toast".
97
- * @param toastHeight: The height of the ion-toast element
98
- * @param wrapperHeight: The height of the .toast-wrapper element
99
- * inside the toast's shadow root.
100
- */
101
- const getOffsetForMiddlePosition = (toastHeight, wrapperHeight) => {
102
- return Math.floor(toastHeight / 2 - wrapperHeight / 2);
103
- };
104
-
105
17
  /**
106
18
  * iOS Toast Enter Animation
107
19
  */
@@ -117,7 +29,7 @@ const iosEnterAnimation = (baseEl, opts) => {
117
29
  wrapperAnimation.fromTo('transform', 'translateY(-100%)', `translateY(${top})`);
118
30
  break;
119
31
  case 'middle':
120
- const topPosition = getOffsetForMiddlePosition(baseEl.clientHeight, wrapperEl.clientHeight);
32
+ const topPosition = Math.floor(baseEl.clientHeight / 2 - wrapperEl.clientHeight / 2);
121
33
  wrapperEl.style.top = `${topPosition}px`;
122
34
  wrapperAnimation.fromTo('opacity', 0.01, 1);
123
35
  break;
@@ -168,7 +80,7 @@ const mdEnterAnimation = (baseEl, opts) => {
168
80
  wrapperAnimation.fromTo('opacity', 0.01, 1);
169
81
  break;
170
82
  case 'middle':
171
- const topPosition = getOffsetForMiddlePosition(baseEl.clientHeight, wrapperEl.clientHeight);
83
+ const topPosition = Math.floor(baseEl.clientHeight / 2 - wrapperEl.clientHeight / 2);
172
84
  wrapperEl.style.top = `${topPosition}px`;
173
85
  wrapperAnimation.fromTo('opacity', 0.01, 1);
174
86
  break;
@@ -193,263 +105,80 @@ const mdLeaveAnimation = (baseEl) => {
193
105
  };
194
106
 
195
107
  /**
196
- * Create a gesture that allows the Toast
197
- * to be swiped to dismiss.
198
- * @param el - The Toast element
199
- * @param toastPosition - The last computed position of the Toast. This is computed in the "present" method.
200
- * @param onDismiss - A callback to fire when the Toast was swiped to dismiss.
108
+ * Calculate the CSS top and bottom position of the toast, to be used
109
+ * as starting points for the animation keyframes.
110
+ *
111
+ * The default animations for both MD and iOS
112
+ * use translateY, which calculates from the
113
+ * top edge of the screen. This behavior impacts
114
+ * how we compute the offset when a toast has
115
+ * position='bottom' since we need to calculate from
116
+ * the bottom edge of the screen instead.
117
+ *
118
+ * @param position The value of the toast's position prop.
119
+ * @param positionAnchor The element the toast should be anchored to,
120
+ * if applicable.
121
+ * @param mode The toast component's mode (md, ios, etc).
122
+ * @param toast A reference to the toast element itself.
201
123
  */
202
- const createSwipeToDismissGesture = (el, toastPosition, onDismiss) => {
203
- /**
204
- * Users should swipe on the visible toast wrapper
205
- * rather than on ion-toast which covers the entire screen.
206
- * When testing the class instance the inner wrapper will not
207
- * be defined. As a result, we use a placeholder element in those environments.
208
- */
209
- const wrapperEl = Build.isTesting
210
- ? document.createElement('div')
211
- : getElementRoot(el).querySelector('.toast-wrapper');
212
- const hostElHeight = el.clientHeight;
213
- const wrapperElBox = wrapperEl.getBoundingClientRect();
214
- /**
215
- * The maximum amount that
216
- * the toast can be swiped. This should
217
- * account for the wrapper element's height
218
- * too so the toast can be swiped offscreen
219
- * completely.
220
- */
221
- let MAX_SWIPE_DISTANCE = 0;
222
- /**
223
- * The step value at which a toast
224
- * is eligible for dismissing via gesture.
225
- */
226
- const DISMISS_THRESHOLD = 0.5;
227
- /**
228
- * The middle position Toast starts 50% of the way
229
- * through the animation, so we need to use this
230
- * as the starting point for our step values.
231
- */
232
- const STEP_OFFSET = el.position === 'middle' ? 0.5 : 0;
124
+ function getAnimationPosition(position, positionAnchor, mode, toast) {
233
125
  /**
234
- * When the Toast is at the top users will be
235
- * swiping up. As a result, the delta values will be
236
- * negative numbers which will result in negative steps
237
- * and thresholds. As a result, we need to make those numbers
238
- * positive.
126
+ * Start with a predefined offset from the edge the toast will be
127
+ * positioned relative to, whether on the screen or anchor element.
239
128
  */
240
- const INVERSION_FACTOR = el.position === 'top' ? -1 : 1;
129
+ let offset;
130
+ if (mode === 'md') {
131
+ offset = position === 'top' ? 8 : -8;
132
+ }
133
+ else {
134
+ offset = position === 'top' ? 10 : -10;
135
+ }
241
136
  /**
242
- * The top offset that places the
243
- * toast in the middle of the screen.
244
- * Only needed when position="middle".
137
+ * If positionAnchor is defined, add in the distance from the target
138
+ * screen edge to the target anchor edge. For position="top", the
139
+ * bottom anchor edge is targeted. For position="bottom", the top
140
+ * anchor edge is targeted.
245
141
  */
246
- const topPosition = getOffsetForMiddlePosition(hostElHeight, wrapperElBox.height);
247
- const SWIPE_UP_DOWN_KEYFRAMES = [
248
- { offset: 0, transform: `translateY(-${topPosition + wrapperElBox.height}px)` },
249
- { offset: 0.5, transform: `translateY(0px)` },
250
- { offset: 1, transform: `translateY(${topPosition + wrapperElBox.height}px)` },
251
- ];
252
- const swipeAnimation = createAnimation('toast-swipe-to-dismiss-animation')
253
- .addElement(wrapperEl)
254
- /**
255
- * The specific value here does not actually
256
- * matter. We just need this to be a positive
257
- * value so the animation does not jump
258
- * to the end when the user beings to drag.
259
- */
260
- .duration(100);
261
- switch (el.position) {
262
- case 'middle':
263
- MAX_SWIPE_DISTANCE = hostElHeight + wrapperElBox.height;
264
- swipeAnimation.keyframes(SWIPE_UP_DOWN_KEYFRAMES);
265
- /**
266
- * Toast can be swiped up or down but
267
- * should start in the middle of the screen.
268
- */
269
- swipeAnimation.progressStart(true, 0.5);
270
- break;
271
- case 'top':
272
- /**
273
- * The bottom edge of the wrapper
274
- * includes the distance between the top
275
- * of the screen and the top of the wrapper
276
- * as well as the wrapper height so the wrapper
277
- * can be dragged fully offscreen.
278
- */
279
- MAX_SWIPE_DISTANCE = wrapperElBox.bottom;
280
- swipeAnimation.keyframes([
281
- { offset: 0, transform: `translateY(${toastPosition.top})` },
282
- { offset: 1, transform: 'translateY(-100%)' },
283
- ]);
284
- swipeAnimation.progressStart(true, 0);
285
- break;
286
- case 'bottom':
287
- default:
288
- /**
289
- * This computes the distance between the
290
- * top of the wrapper and the bottom of the
291
- * screen including the height of the wrapper
292
- * element so it can be dragged fully offscreen.
293
- */
294
- MAX_SWIPE_DISTANCE = hostElHeight - wrapperElBox.top;
295
- swipeAnimation.keyframes([
296
- { offset: 0, transform: `translateY(${toastPosition.bottom})` },
297
- { offset: 1, transform: 'translateY(100%)' },
298
- ]);
299
- swipeAnimation.progressStart(true, 0);
300
- break;
301
- }
302
- const computeStep = (delta) => {
303
- return (delta * INVERSION_FACTOR) / MAX_SWIPE_DISTANCE;
304
- };
305
- const onMove = (detail) => {
306
- const step = STEP_OFFSET + computeStep(detail.deltaY);
307
- swipeAnimation.progressStep(step);
308
- };
309
- const onEnd = (detail) => {
310
- const velocity = detail.velocityY;
311
- const threshold = ((detail.deltaY + velocity * 1000) / MAX_SWIPE_DISTANCE) * INVERSION_FACTOR;
312
- /**
313
- * Disable the gesture for the remainder of the animation.
314
- * It will be re-enabled if the toast animates back to
315
- * its initial presented position.
316
- */
317
- gesture.enable(false);
318
- let shouldDismiss = true;
319
- let playTo = 1;
320
- let step = 0;
321
- let remainingDistance = 0;
322
- if (el.position === 'middle') {
323
- /**
324
- * A middle positioned Toast appears
325
- * in the middle of the screen (at animation offset 0.5).
326
- * As a result, the threshold will be calculated relative
327
- * to this starting position. In other words at animation offset 0.5
328
- * the threshold will be 0. We want the middle Toast to be eligible
329
- * for dismiss when the user has swiped either half way up or down the
330
- * screen. As a result, we divide DISMISS_THRESHOLD in half. We also
331
- * consider when the threshold is a negative in the event the
332
- * user drags up (since the deltaY will also be negative).
333
- */
334
- shouldDismiss = threshold >= DISMISS_THRESHOLD / 2 || threshold <= -DISMISS_THRESHOLD / 2;
335
- /**
336
- * Since we are replacing the keyframes
337
- * below the animation always starts from
338
- * the beginning of the new keyframes.
339
- * Similarly, we are always playing to
340
- * the end of the new keyframes.
341
- */
342
- playTo = 1;
343
- step = 0;
344
- /**
345
- * The Toast should animate from wherever its
346
- * current position is to the desired end state.
347
- *
348
- * To begin, we get the current position of the
349
- * Toast for its starting state.
350
- */
351
- const wrapperElBox = wrapperEl.getBoundingClientRect();
352
- const startOffset = wrapperElBox.top - topPosition;
353
- const startPosition = `${startOffset}px`;
354
- /**
355
- * If the deltaY is negative then the user is swiping
356
- * up, so the Toast should animate to the top of the screen.
357
- * If the deltaY is positive then the user is swiping
358
- * down, so the Toast should animate to the bottom of the screen.
359
- * We also account for when the deltaY is 0, but realistically
360
- * that should never happen because it means the user did not drag
361
- * the toast.
362
- */
363
- const offsetFactor = detail.deltaY <= 0 ? -1 : 1;
364
- const endOffset = (topPosition + wrapperElBox.height) * offsetFactor;
365
- /**
366
- * If the Toast should dismiss
367
- * then we need to figure out which edge of
368
- * the screen it should animate towards.
369
- * By default, the Toast will come
370
- * back to its default state in the
371
- * middle of the screen.
372
- */
373
- const endPosition = shouldDismiss ? `${endOffset}px` : '0px';
374
- const KEYFRAMES = [
375
- { offset: 0, transform: `translateY(${startPosition})` },
376
- { offset: 1, transform: `translateY(${endPosition})` },
377
- ];
378
- swipeAnimation.keyframes(KEYFRAMES);
379
- /**
380
- * Compute the remaining amount of pixels the
381
- * toast needs to move to be fully dismissed.
382
- */
383
- remainingDistance = endOffset - startOffset;
142
+ if (positionAnchor && win) {
143
+ warnIfAnchorIsHidden(positionAnchor, toast);
144
+ const box = positionAnchor.getBoundingClientRect();
145
+ if (position === 'top') {
146
+ offset += box.bottom;
384
147
  }
385
- else {
386
- shouldDismiss = threshold >= DISMISS_THRESHOLD;
387
- playTo = shouldDismiss ? 1 : 0;
388
- step = computeStep(detail.deltaY);
148
+ else if (position === 'bottom') {
389
149
  /**
390
- * Compute the remaining amount of pixels the
391
- * toast needs to move to be fully dismissed.
150
+ * Just box.top is the distance from the top edge of the screen
151
+ * to the top edge of the anchor. We want to calculate from the
152
+ * bottom edge of the screen instead.
392
153
  */
393
- const remainingStepAmount = shouldDismiss ? 1 - step : step;
394
- remainingDistance = remainingStepAmount * MAX_SWIPE_DISTANCE;
154
+ offset -= win.innerHeight - box.top;
395
155
  }
396
156
  /**
397
- * The animation speed should depend on how quickly
398
- * the user flicks the toast across the screen. However,
399
- * it should be no slower than 200ms.
400
- * We use Math.abs on the remainingDistance because that value
401
- * can be negative when swiping up on a middle position toast.
402
- */
403
- const duration = Math.min(Math.abs(remainingDistance) / Math.abs(velocity), 200);
404
- swipeAnimation
405
- .onFinish(() => {
406
- if (shouldDismiss) {
407
- onDismiss();
408
- swipeAnimation.destroy();
409
- }
410
- else {
411
- if (el.position === 'middle') {
412
- /**
413
- * If the toast snapped back to
414
- * the middle of the screen we need
415
- * to reset the keyframes
416
- * so the toast can be swiped
417
- * up or down again.
418
- */
419
- swipeAnimation.keyframes(SWIPE_UP_DOWN_KEYFRAMES).progressStart(true, 0.5);
420
- }
421
- else {
422
- swipeAnimation.progressStart(true, 0);
423
- }
424
- /**
425
- * If the toast did not dismiss then
426
- * the user should be able to swipe again.
427
- */
428
- gesture.enable(true);
429
- }
430
- /**
431
- * This must be a one time callback
432
- * otherwise a new callback will
433
- * be added every time onEnd runs.
434
- */
435
- }, { oneTimeCallback: true })
436
- .progressEnd(playTo, step, duration);
437
- };
438
- const gesture = createGesture({
439
- el: wrapperEl,
440
- gestureName: 'toast-swipe-to-dismiss',
441
- gesturePriority: OVERLAY_GESTURE_PRIORITY,
442
- /**
443
- * Toast only supports vertical swipes.
444
- * This needs to be updated if we later
445
- * support horizontal swipes.
157
+ * We don't include safe area here because that should already be
158
+ * accounted for when checking the position of the anchor.
446
159
  */
447
- direction: 'y',
448
- onMove,
449
- onEnd,
450
- });
451
- return gesture;
452
- };
160
+ return {
161
+ top: `${offset}px`,
162
+ bottom: `${offset}px`,
163
+ };
164
+ }
165
+ else {
166
+ return {
167
+ top: `calc(${offset}px + var(--ion-safe-area-top, 0px))`,
168
+ bottom: `calc(${offset}px - var(--ion-safe-area-bottom, 0px))`,
169
+ };
170
+ }
171
+ }
172
+ /**
173
+ * If the anchor element is hidden, getBoundingClientRect()
174
+ * will return all 0s for it, which can cause unexpected
175
+ * results in the position calculation when animating.
176
+ */
177
+ function warnIfAnchorIsHidden(positionAnchor, toast) {
178
+ if (positionAnchor.offsetParent === null) {
179
+ printIonWarning('The positionAnchor element for ion-toast was found in the DOM, but appears to be hidden. This may lead to unexpected positioning of the toast.', toast);
180
+ }
181
+ }
453
182
 
454
183
  const toastIosCss = ":host{--border-width:0;--border-style:none;--border-color:initial;--box-shadow:none;--min-width:auto;--width:auto;--min-height:auto;--height:auto;--max-height:auto;--white-space:normal;top:0;display:block;position:absolute;width:100%;height:100%;outline:none;color:var(--color);font-family:var(--ion-font-family, inherit);contain:strict;z-index:1001;pointer-events:none}@supports (inset-inline-start: 0){:host{inset-inline-start:0}}@supports not (inset-inline-start: 0){:host{left:0}:host-context([dir=rtl]){left:unset;right:unset;right:0}@supports selector(:dir(rtl)){:host(:dir(rtl)){left:unset;right:unset;right:0}}}:host(.overlay-hidden){display:none}:host(.ion-color){--button-color:inherit;color:var(--ion-color-contrast)}:host(.ion-color) .toast-button-cancel{color:inherit}:host(.ion-color) .toast-wrapper{background:var(--ion-color-base)}.toast-wrapper{border-radius:var(--border-radius);width:var(--width);min-width:var(--min-width);max-width:var(--max-width);height:var(--height);min-height:var(--min-height);max-height:var(--max-height);border-width:var(--border-width);border-style:var(--border-style);border-color:var(--border-color);background:var(--background);-webkit-box-shadow:var(--box-shadow);box-shadow:var(--box-shadow)}@supports (inset-inline-start: 0){.toast-wrapper{inset-inline-start:var(--start);inset-inline-end:var(--end)}}@supports not (inset-inline-start: 0){.toast-wrapper{left:var(--start);right:var(--end)}:host-context([dir=rtl]) .toast-wrapper{left:unset;right:unset;left:var(--end);right:var(--start)}[dir=rtl] .toast-wrapper{left:unset;right:unset;left:var(--end);right:var(--start)}@supports selector(:dir(rtl)){.toast-wrapper:dir(rtl){left:unset;right:unset;left:var(--end);right:var(--start)}}}.toast-wrapper.toast-top{-webkit-transform:translate3d(0, -100%, 0);transform:translate3d(0, -100%, 0);top:0}.toast-wrapper.toast-bottom{-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0);bottom:0}.toast-container{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;pointer-events:auto;height:inherit;min-height:inherit;max-height:inherit;contain:content}.toast-layout-stacked .toast-container{-ms-flex-wrap:wrap;flex-wrap:wrap}.toast-layout-baseline .toast-content{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center}.toast-icon{-webkit-margin-start:16px;margin-inline-start:16px}.toast-content{min-width:0}.toast-message{-ms-flex:1;flex:1;white-space:var(--white-space)}.toast-button-group{display:-ms-flexbox;display:flex}.toast-layout-stacked .toast-button-group{-ms-flex-pack:end;justify-content:end;width:100%}.toast-button{border:0;outline:none;color:var(--button-color);z-index:0}.toast-icon,.toast-button-icon{font-size:1.4em}.toast-button-inner{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}@media (any-hover: hover){.toast-button:hover{cursor:pointer}}:host{--background:var(--ion-color-step-50, #f2f2f2);--border-radius:14px;--button-color:var(--ion-color-primary, #3880ff);--color:var(--ion-color-step-850, #262626);--max-width:700px;--max-height:478px;--start:10px;--end:10px;font-size:clamp(14px, 0.875rem, 43.4px)}.toast-wrapper{-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;margin-top:auto;margin-bottom:auto;display:block;position:absolute;z-index:10}@supports ((-webkit-backdrop-filter: blur(0)) or (backdrop-filter: blur(0))){:host(.toast-translucent) .toast-wrapper{background:rgba(var(--ion-background-color-rgb, 255, 255, 255), 0.8);-webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}:host(.ion-color.toast-translucent) .toast-wrapper{background:rgba(var(--ion-color-base-rgb), 0.8)}}.toast-wrapper.toast-middle{opacity:0.01}.toast-content{-webkit-padding-start:15px;padding-inline-start:15px;-webkit-padding-end:15px;padding-inline-end:15px;padding-top:15px;padding-bottom:15px}.toast-header{margin-bottom:2px;font-weight:500}.toast-button{-webkit-padding-start:15px;padding-inline-start:15px;-webkit-padding-end:15px;padding-inline-end:15px;padding-top:10px;padding-bottom:10px;min-height:44px;-webkit-transition:background-color, opacity 100ms linear;transition:background-color, opacity 100ms linear;border:0;background-color:transparent;font-family:var(--ion-font-family);font-size:clamp(17px, 1.0625rem, 21.998px);font-weight:500;overflow:hidden}.toast-button.ion-activated{opacity:0.4}@media (any-hover: hover){.toast-button:hover{opacity:0.6}}";
455
184
 
@@ -480,41 +209,6 @@ const Toast = /*@__PURE__*/ proxyCustomElement(class Toast extends HTMLElement {
480
209
  this.callButtonHandler(cancelButton);
481
210
  }
482
211
  };
483
- /**
484
- * Create a new swipe gesture so Toast
485
- * can be swiped to dismiss.
486
- */
487
- this.createSwipeGesture = (toastPosition) => {
488
- const gesture = (this.gesture = createSwipeToDismissGesture(this.el, toastPosition, () => {
489
- /**
490
- * If the gesture completed then
491
- * we should dismiss the toast.
492
- */
493
- this.dismiss(undefined, GESTURE);
494
- }));
495
- gesture.enable(true);
496
- };
497
- /**
498
- * Destroy an existing swipe gesture
499
- * so Toast can no longer be swiped to dismiss.
500
- */
501
- this.destroySwipeGesture = () => {
502
- const { gesture } = this;
503
- if (gesture === undefined) {
504
- return;
505
- }
506
- gesture.destroy();
507
- this.gesture = undefined;
508
- };
509
- /**
510
- * Returns `true` if swipeGesture
511
- * is configured to a value that enables the swipe behavior.
512
- * Returns `false` otherwise.
513
- */
514
- this.prefersSwipeGesture = () => {
515
- const { swipeGesture } = this;
516
- return swipeGesture === 'vertical';
517
- };
518
212
  this.revealContentToScreenReader = false;
519
213
  this.overlayIndex = undefined;
520
214
  this.delegate = undefined;
@@ -535,37 +229,9 @@ const Toast = /*@__PURE__*/ proxyCustomElement(class Toast extends HTMLElement {
535
229
  this.animated = true;
536
230
  this.icon = undefined;
537
231
  this.htmlAttributes = undefined;
538
- this.swipeGesture = undefined;
539
232
  this.isOpen = false;
540
233
  this.trigger = undefined;
541
234
  }
542
- swipeGestureChanged() {
543
- /**
544
- * If the Toast is presented, then we need to destroy
545
- * any actives gestures before a new gesture is potentially
546
- * created below.
547
- *
548
- * If the Toast is dismissed, then no gesture should be available
549
- * since the Toast is not visible. This case should never
550
- * happen since the "dismiss" method handles destroying
551
- * any active swipe gestures, but we keep this code
552
- * around to handle the first case.
553
- */
554
- this.destroySwipeGesture();
555
- /**
556
- * A new swipe gesture should only be created
557
- * if the Toast is presented. If the Toast is not
558
- * yet presented then the "present" method will
559
- * handle calling the swipe gesture setup function.
560
- */
561
- if (this.presented && this.prefersSwipeGesture()) {
562
- /**
563
- * If the Toast is presented then
564
- * lastPresentedPosition is defined.
565
- */
566
- this.createSwipeGesture(this.lastPresentedPosition);
567
- }
568
- }
569
235
  onIsOpenChange(newValue, oldValue) {
570
236
  if (newValue === true && oldValue === false) {
571
237
  this.present();
@@ -627,14 +293,6 @@ const Toast = /*@__PURE__*/ proxyCustomElement(class Toast extends HTMLElement {
627
293
  if (this.duration > 0) {
628
294
  this.durationTimeout = setTimeout(() => this.dismiss(undefined, 'timeout'), this.duration);
629
295
  }
630
- /**
631
- * If the Toast has a swipe gesture then we can
632
- * create the gesture so users can swipe the
633
- * presented Toast.
634
- */
635
- if (this.prefersSwipeGesture()) {
636
- this.createSwipeGesture(animationPosition);
637
- }
638
296
  unlock();
639
297
  }
640
298
  /**
@@ -669,11 +327,6 @@ const Toast = /*@__PURE__*/ proxyCustomElement(class Toast extends HTMLElement {
669
327
  this.revealContentToScreenReader = false;
670
328
  }
671
329
  this.lastPresentedPosition = undefined;
672
- /**
673
- * If the Toast has a swipe gesture then we can
674
- * safely destroy it now that it is dismissed.
675
- */
676
- this.destroySwipeGesture();
677
330
  unlock();
678
331
  return dismissed;
679
332
  }
@@ -818,7 +471,6 @@ const Toast = /*@__PURE__*/ proxyCustomElement(class Toast extends HTMLElement {
818
471
  }
819
472
  get el() { return this; }
820
473
  static get watchers() { return {
821
- "swipeGesture": ["swipeGestureChanged"],
822
474
  "isOpen": ["onIsOpenChange"],
823
475
  "trigger": ["triggerChanged"]
824
476
  }; }
@@ -846,7 +498,6 @@ const Toast = /*@__PURE__*/ proxyCustomElement(class Toast extends HTMLElement {
846
498
  "animated": [4],
847
499
  "icon": [1],
848
500
  "htmlAttributes": [16],
849
- "swipeGesture": [1, "swipe-gesture"],
850
501
  "isOpen": [4, "is-open"],
851
502
  "trigger": [1],
852
503
  "revealContentToScreenReader": [32],
@@ -855,7 +506,6 @@ const Toast = /*@__PURE__*/ proxyCustomElement(class Toast extends HTMLElement {
855
506
  "onDidDismiss": [64],
856
507
  "onWillDismiss": [64]
857
508
  }, undefined, {
858
- "swipeGesture": ["swipeGestureChanged"],
859
509
  "isOpen": ["onIsOpenChange"],
860
510
  "trigger": ["triggerChanged"]
861
511
  }]);
@@ -562,7 +562,6 @@ const safeCall = (handler, arg) => {
562
562
  };
563
563
  const BACKDROP = 'backdrop';
564
564
  const GESTURE = 'gesture';
565
- const OVERLAY_GESTURE_PRIORITY = 39;
566
565
  /**
567
566
  * Creates a delegate controller.
568
567
  *
@@ -690,4 +689,4 @@ const createTriggerController = () => {
690
689
  };
691
690
  };
692
691
 
693
- export { BACKDROP as B, GESTURE as G, OVERLAY_GESTURE_PRIORITY as O, alertController as a, actionSheetController as b, popoverController as c, createDelegateController as d, createTriggerController as e, present as f, dismiss as g, eventMethod as h, isCancel as i, prepareOverlay as j, setOverlayId as k, loadingController as l, modalController as m, focusFirstDescendant as n, getPresentedOverlay as o, pickerController as p, activeAnimations as q, safeCall as s, toastController as t };
692
+ export { BACKDROP as B, GESTURE as G, alertController as a, actionSheetController as b, popoverController as c, createDelegateController as d, createTriggerController as e, present as f, dismiss as g, eventMethod as h, isCancel as i, prepareOverlay as j, setOverlayId as k, loadingController as l, modalController as m, focusFirstDescendant as n, getPresentedOverlay as o, pickerController as p, activeAnimations as q, safeCall as s, toastController as t };