@ionic/core 8.6.4-nightly.20250708 → 8.6.4

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.
@@ -30,6 +30,24 @@ export const setContent = async (page, html, testInfo, options) => {
30
30
  palette = options.palette;
31
31
  }
32
32
  const baseUrl = process.env.PLAYWRIGHT_TEST_BASE_URL;
33
+ // The Ionic bundle is included locally by default unless the test
34
+ // config passes in the importIonicFromCDN option. This is useful
35
+ // when testing with the CDN version of Ionic.
36
+ let ionicCSSImports = `
37
+ <link href="${baseUrl}/css/ionic.bundle.css" rel="stylesheet" />
38
+ `;
39
+ let ionicJSImports = `
40
+ <script type="module" src="${baseUrl}/dist/ionic/ionic.esm.js"></script>
41
+ `;
42
+ if (options === null || options === void 0 ? void 0 : options.importIonicFromCDN) {
43
+ ionicCSSImports = `
44
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" />
45
+ `;
46
+ ionicJSImports = `
47
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
48
+ <script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
49
+ `;
50
+ }
33
51
  const output = `
34
52
  <!DOCTYPE html>
35
53
  <html dir="${direction}" lang="en">
@@ -37,11 +55,11 @@ export const setContent = async (page, html, testInfo, options) => {
37
55
  <title>Ionic Playwright Test</title>
38
56
  <meta charset="UTF-8" />
39
57
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
40
- <link href="${baseUrl}/css/ionic.bundle.css" rel="stylesheet" />
58
+ ${ionicCSSImports}
41
59
  <link href="${baseUrl}/scripts/testing/styles.css" rel="stylesheet" />
42
60
  ${palette !== 'light' ? `<link href="${baseUrl}/css/palettes/${palette}.always.css" rel="stylesheet" />` : ''}
43
61
  <script src="${baseUrl}/scripts/testing/scripts.js"></script>
44
- <script type="module" src="${baseUrl}/dist/ionic/ionic.esm.js"></script>
62
+ ${ionicJSImports}
45
63
  <script>
46
64
  window.Ionic = {
47
65
  config: {
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2025-07-08T06:10:29",
2
+ "timestamp": "2025-07-09T20:11:49",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.33.1",
@@ -20226,7 +20226,14 @@
20226
20226
  "docsTags": []
20227
20227
  }
20228
20228
  ],
20229
- "listeners": [],
20229
+ "listeners": [
20230
+ {
20231
+ "event": "resize",
20232
+ "target": "window",
20233
+ "capture": false,
20234
+ "passive": true
20235
+ }
20236
+ ],
20230
20237
  "styles": [
20231
20238
  {
20232
20239
  "name": "--backdrop-opacity",
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * (C) Ionic http://ionicframework.com - MIT License
3
3
  */
4
- import { r as registerInstance, d as createEvent, m as printIonWarning, w as writeTask, e as getIonMode, l as config, h, j as Host, k as getElement } from './index-B_U9CtaY.js';
4
+ import { r as registerInstance, d as createEvent, e as getIonMode, m as printIonWarning, w as writeTask, l as config, h, j as Host, k as getElement } from './index-B_U9CtaY.js';
5
5
  import { f as findClosestIonContent, i as isIonContent, d as disableContentScrollY, r as resetContentScrollY, a as findIonContent, p as printIonContentErrorMsg } from './index-BlJTBdxG.js';
6
6
  import { C as CoreDelegate, a as attachComponent, d as detachComponent } from './framework-delegate-DxcnWic_.js';
7
7
  import { e as clamp, g as getElementRoot, r as raf, b as inheritAttributes, h as hasLazyBuild } from './helpers-1O4D2b7y.js';
@@ -587,7 +587,7 @@ const iosEnterAnimation = (baseEl, opts) => {
587
587
  baseAnimation.addAnimation(contentAnimation);
588
588
  }
589
589
  if (presentingEl) {
590
- const isMobile = window.innerWidth < 768;
590
+ const isPortrait = window.innerWidth < 768;
591
591
  const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
592
592
  const presentingElRoot = getElementRoot(presentingEl);
593
593
  const presentingAnimation = createAnimation().beforeStyles({
@@ -596,7 +596,7 @@ const iosEnterAnimation = (baseEl, opts) => {
596
596
  overflow: 'hidden',
597
597
  });
598
598
  const bodyEl = document.body;
599
- if (isMobile) {
599
+ if (isPortrait) {
600
600
  /**
601
601
  * Fallback for browsers that does not support `max()` (ex: Firefox)
602
602
  * No need to worry about statusbar padding since engines like Gecko
@@ -674,7 +674,7 @@ const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
674
674
  .duration(duration)
675
675
  .addAnimation(wrapperAnimation);
676
676
  if (presentingEl) {
677
- const isMobile = window.innerWidth < 768;
677
+ const isPortrait = window.innerWidth < 768;
678
678
  const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
679
679
  const presentingElRoot = getElementRoot(presentingEl);
680
680
  const presentingAnimation = createAnimation()
@@ -692,7 +692,7 @@ const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
692
692
  }
693
693
  });
694
694
  const bodyEl = document.body;
695
- if (isMobile) {
695
+ if (isPortrait) {
696
696
  const transformOffset = !CSS.supports('width', 'max(0px, 1px)') ? '30px' : 'max(30px, var(--ion-safe-area-top))';
697
697
  const modalTransform = hasCardModal ? '-10px' : transformOffset;
698
698
  const toPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
@@ -739,6 +739,163 @@ const iosLeaveAnimation = (baseEl, opts, duration = 500) => {
739
739
  return baseAnimation;
740
740
  };
741
741
 
742
+ /**
743
+ * Transition animation from portrait view to landscape view
744
+ * This handles the case where a card modal is open in portrait view
745
+ * and the user switches to landscape view
746
+ */
747
+ const portraitToLandscapeTransition = (baseEl, opts, duration = 300) => {
748
+ const { presentingEl } = opts;
749
+ if (!presentingEl) {
750
+ // No transition needed for non-card modals
751
+ return createAnimation('portrait-to-landscape-transition');
752
+ }
753
+ const presentingElIsCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
754
+ const presentingElRoot = getElementRoot(presentingEl);
755
+ const bodyEl = document.body;
756
+ const baseAnimation = createAnimation('portrait-to-landscape-transition')
757
+ .addElement(baseEl)
758
+ .easing('cubic-bezier(0.32,0.72,0,1)')
759
+ .duration(duration);
760
+ const presentingAnimation = createAnimation().beforeStyles({
761
+ transform: 'translateY(0)',
762
+ 'transform-origin': 'top center',
763
+ overflow: 'hidden',
764
+ });
765
+ if (!presentingElIsCardModal) {
766
+ // The presenting element is not a card modal, so we do not
767
+ // need to care about layering and modal-specific styles.
768
+ const root = getElementRoot(baseEl);
769
+ const wrapperAnimation = createAnimation()
770
+ .addElement(root.querySelectorAll('.modal-wrapper, .modal-shadow'))
771
+ .fromTo('opacity', '1', '1'); // Keep wrapper visible in landscape
772
+ const backdropAnimation = createAnimation()
773
+ .addElement(root.querySelector('ion-backdrop'))
774
+ .fromTo('opacity', 'var(--backdrop-opacity)', 'var(--backdrop-opacity)'); // Keep backdrop visible
775
+ // Animate presentingEl from portrait state back to normal
776
+ const transformOffset = !CSS.supports('width', 'max(0px, 1px)') ? '30px' : 'max(30px, var(--ion-safe-area-top))';
777
+ const toPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
778
+ const fromTransform = `translateY(${transformOffset}) scale(${toPresentingScale})`;
779
+ presentingAnimation
780
+ .addElement(presentingEl)
781
+ .afterStyles({
782
+ transform: 'translateY(0px) scale(1)',
783
+ 'border-radius': '0px',
784
+ })
785
+ .beforeAddWrite(() => bodyEl.style.setProperty('background-color', ''))
786
+ .fromTo('transform', fromTransform, 'translateY(0px) scale(1)')
787
+ .fromTo('filter', 'contrast(0.85)', 'contrast(1)')
788
+ .fromTo('border-radius', '10px 10px 0 0', '0px');
789
+ baseAnimation.addAnimation([presentingAnimation, wrapperAnimation, backdropAnimation]);
790
+ }
791
+ else {
792
+ // The presenting element is a card modal, so we do
793
+ // need to care about layering and modal-specific styles.
794
+ const toPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
795
+ const fromTransform = `translateY(-10px) scale(${toPresentingScale})`;
796
+ const toTransform = `translateY(-10px) scale(${toPresentingScale})`;
797
+ presentingAnimation
798
+ .addElement(presentingElRoot.querySelector('.modal-wrapper'))
799
+ .afterStyles({
800
+ transform: toTransform,
801
+ })
802
+ .fromTo('transform', fromTransform, toTransform)
803
+ .fromTo('filter', 'contrast(0.85)', 'contrast(0.85)'); // Keep same contrast for card
804
+ const shadowAnimation = createAnimation()
805
+ .addElement(presentingElRoot.querySelector('.modal-shadow'))
806
+ .afterStyles({
807
+ transform: toTransform,
808
+ })
809
+ .fromTo('opacity', '0', '0') // Shadow stays hidden in landscape for card modals
810
+ .fromTo('transform', fromTransform, toTransform);
811
+ baseAnimation.addAnimation([presentingAnimation, shadowAnimation]);
812
+ }
813
+ return baseAnimation;
814
+ };
815
+ /**
816
+ * Transition animation from landscape view to portrait view
817
+ * This handles the case where a card modal is open in landscape view
818
+ * and the user switches to portrait view
819
+ */
820
+ const landscapeToPortraitTransition = (baseEl, opts, duration = 300) => {
821
+ const { presentingEl } = opts;
822
+ if (!presentingEl) {
823
+ // No transition needed for non-card modals
824
+ return createAnimation('landscape-to-portrait-transition');
825
+ }
826
+ const presentingElIsCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
827
+ const presentingElRoot = getElementRoot(presentingEl);
828
+ const bodyEl = document.body;
829
+ const baseAnimation = createAnimation('landscape-to-portrait-transition')
830
+ .addElement(baseEl)
831
+ .easing('cubic-bezier(0.32,0.72,0,1)')
832
+ .duration(duration);
833
+ const presentingAnimation = createAnimation().beforeStyles({
834
+ transform: 'translateY(0)',
835
+ 'transform-origin': 'top center',
836
+ overflow: 'hidden',
837
+ });
838
+ if (!presentingElIsCardModal) {
839
+ // The presenting element is not a card modal, so we do not
840
+ // need to care about layering and modal-specific styles.
841
+ const root = getElementRoot(baseEl);
842
+ const wrapperAnimation = createAnimation()
843
+ .addElement(root.querySelectorAll('.modal-wrapper, .modal-shadow'))
844
+ .fromTo('opacity', '1', '1'); // Keep wrapper visible
845
+ const backdropAnimation = createAnimation()
846
+ .addElement(root.querySelector('ion-backdrop'))
847
+ .fromTo('opacity', 'var(--backdrop-opacity)', 'var(--backdrop-opacity)'); // Keep backdrop visible
848
+ // Animate presentingEl from normal state to portrait state
849
+ const transformOffset = !CSS.supports('width', 'max(0px, 1px)') ? '30px' : 'max(30px, var(--ion-safe-area-top))';
850
+ const toPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
851
+ const toTransform = `translateY(${transformOffset}) scale(${toPresentingScale})`;
852
+ presentingAnimation
853
+ .addElement(presentingEl)
854
+ .beforeStyles({
855
+ transform: 'translateY(0px) scale(1)',
856
+ 'transform-origin': 'top center',
857
+ overflow: 'hidden',
858
+ })
859
+ .afterStyles({
860
+ transform: toTransform,
861
+ 'border-radius': '10px 10px 0 0',
862
+ filter: 'contrast(0.85)',
863
+ overflow: 'hidden',
864
+ 'transform-origin': 'top center',
865
+ })
866
+ .beforeAddWrite(() => bodyEl.style.setProperty('background-color', 'black'))
867
+ .keyframes([
868
+ { offset: 0, transform: 'translateY(0px) scale(1)', filter: 'contrast(1)', borderRadius: '0px' },
869
+ { offset: 0.2, transform: 'translateY(0px) scale(1)', filter: 'contrast(1)', borderRadius: '10px 10px 0 0' },
870
+ { offset: 1, transform: toTransform, filter: 'contrast(0.85)', borderRadius: '10px 10px 0 0' },
871
+ ]);
872
+ baseAnimation.addAnimation([presentingAnimation, wrapperAnimation, backdropAnimation]);
873
+ }
874
+ else {
875
+ // The presenting element is also a card modal, so we need
876
+ // to handle layering and modal-specific styles.
877
+ const toPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
878
+ const fromTransform = `translateY(-10px) scale(${toPresentingScale})`;
879
+ const toTransform = `translateY(-10px) scale(${toPresentingScale})`;
880
+ presentingAnimation
881
+ .addElement(presentingElRoot.querySelector('.modal-wrapper'))
882
+ .afterStyles({
883
+ transform: toTransform,
884
+ })
885
+ .fromTo('transform', fromTransform, toTransform)
886
+ .fromTo('filter', 'contrast(0.85)', 'contrast(0.85)'); // Keep same contrast for card
887
+ const shadowAnimation = createAnimation()
888
+ .addElement(presentingElRoot.querySelector('.modal-shadow'))
889
+ .afterStyles({
890
+ transform: toTransform,
891
+ })
892
+ .fromTo('opacity', '0', '0') // Shadow stays hidden
893
+ .fromTo('transform', fromTransform, toTransform);
894
+ baseAnimation.addAnimation([presentingAnimation, shadowAnimation]);
895
+ }
896
+ return baseAnimation;
897
+ };
898
+
742
899
  const createEnterAnimation = () => {
743
900
  const backdropAnimation = createAnimation()
744
901
  .fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
@@ -1508,6 +1665,16 @@ const Modal = class {
1508
1665
  triggerController.addClickListener(el, trigger);
1509
1666
  }
1510
1667
  }
1668
+ onWindowResize() {
1669
+ // Only handle resize for iOS card modals when no custom animations are provided
1670
+ if (getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
1671
+ return;
1672
+ }
1673
+ clearTimeout(this.resizeTimeout);
1674
+ this.resizeTimeout = setTimeout(() => {
1675
+ this.handleViewTransition();
1676
+ }, 50); // Debounce to avoid excessive calls during active resizing
1677
+ }
1511
1678
  breakpointsChanged(breakpoints) {
1512
1679
  if (breakpoints !== undefined) {
1513
1680
  this.sortedBreakpoints = breakpoints.sort((a, b) => a - b);
@@ -1520,6 +1687,7 @@ const Modal = class {
1520
1687
  }
1521
1688
  disconnectedCallback() {
1522
1689
  this.triggerController.removeClickListener();
1690
+ this.cleanupViewTransitionListener();
1523
1691
  }
1524
1692
  componentWillLoad() {
1525
1693
  var _a;
@@ -1730,6 +1898,8 @@ const Modal = class {
1730
1898
  else if (hasCardModal) {
1731
1899
  this.initSwipeToClose();
1732
1900
  }
1901
+ // Initialize view transition listener for iOS card modals
1902
+ this.initViewTransitionListener();
1733
1903
  unlock();
1734
1904
  }
1735
1905
  initSwipeToClose() {
@@ -1883,6 +2053,7 @@ const Modal = class {
1883
2053
  if (this.gesture) {
1884
2054
  this.gesture.destroy();
1885
2055
  }
2056
+ this.cleanupViewTransitionListener();
1886
2057
  }
1887
2058
  this.currentBreakpoint = undefined;
1888
2059
  this.animation = undefined;
@@ -1958,6 +2129,108 @@ const Modal = class {
1958
2129
  await this.setCurrentBreakpoint(nextBreakpoint);
1959
2130
  return true;
1960
2131
  }
2132
+ initViewTransitionListener() {
2133
+ // Only enable for iOS card modals when no custom animations are provided
2134
+ if (getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
2135
+ return;
2136
+ }
2137
+ // Set initial view state
2138
+ this.currentViewIsPortrait = window.innerWidth < 768;
2139
+ }
2140
+ handleViewTransition() {
2141
+ const isPortrait = window.innerWidth < 768;
2142
+ // Only transition if view state actually changed
2143
+ if (this.currentViewIsPortrait === isPortrait) {
2144
+ return;
2145
+ }
2146
+ // Cancel any ongoing transition animation
2147
+ if (this.viewTransitionAnimation) {
2148
+ this.viewTransitionAnimation.destroy();
2149
+ this.viewTransitionAnimation = undefined;
2150
+ }
2151
+ const { presentingElement } = this;
2152
+ if (!presentingElement) {
2153
+ return;
2154
+ }
2155
+ // Create transition animation
2156
+ let transitionAnimation;
2157
+ if (this.currentViewIsPortrait && !isPortrait) {
2158
+ // Portrait to landscape transition
2159
+ transitionAnimation = portraitToLandscapeTransition(this.el, {
2160
+ presentingEl: presentingElement});
2161
+ }
2162
+ else {
2163
+ // Landscape to portrait transition
2164
+ transitionAnimation = landscapeToPortraitTransition(this.el, {
2165
+ presentingEl: presentingElement});
2166
+ }
2167
+ // Update state and play animation
2168
+ this.currentViewIsPortrait = isPortrait;
2169
+ this.viewTransitionAnimation = transitionAnimation;
2170
+ transitionAnimation.play().then(() => {
2171
+ this.viewTransitionAnimation = undefined;
2172
+ // After orientation transition, recreate the swipe-to-close gesture
2173
+ // with updated animation that reflects the new presenting element state
2174
+ this.reinitSwipeToClose();
2175
+ });
2176
+ }
2177
+ cleanupViewTransitionListener() {
2178
+ // Clear any pending resize timeout
2179
+ if (this.resizeTimeout) {
2180
+ clearTimeout(this.resizeTimeout);
2181
+ this.resizeTimeout = undefined;
2182
+ }
2183
+ if (this.viewTransitionAnimation) {
2184
+ this.viewTransitionAnimation.destroy();
2185
+ this.viewTransitionAnimation = undefined;
2186
+ }
2187
+ }
2188
+ reinitSwipeToClose() {
2189
+ // Only reinitialize if we have a presenting element and are on iOS
2190
+ if (getIonMode(this) !== 'ios' || !this.presentingElement) {
2191
+ return;
2192
+ }
2193
+ // Clean up existing gesture and animation
2194
+ if (this.gesture) {
2195
+ this.gesture.destroy();
2196
+ this.gesture = undefined;
2197
+ }
2198
+ if (this.animation) {
2199
+ // Properly end the progress-based animation at initial state before destroying
2200
+ // to avoid leaving modal in intermediate swipe position
2201
+ this.animation.progressEnd(0, 0, 0);
2202
+ this.animation.destroy();
2203
+ this.animation = undefined;
2204
+ }
2205
+ // Force the modal back to the correct position or it could end up
2206
+ // in a weird state after destroying the animation
2207
+ raf(() => {
2208
+ this.ensureCorrectModalPosition();
2209
+ this.initSwipeToClose();
2210
+ });
2211
+ }
2212
+ ensureCorrectModalPosition() {
2213
+ const { el, presentingElement } = this;
2214
+ const root = getElementRoot(el);
2215
+ const wrapperEl = root.querySelector('.modal-wrapper');
2216
+ if (wrapperEl) {
2217
+ wrapperEl.style.transform = 'translateY(0vh)';
2218
+ wrapperEl.style.opacity = '1';
2219
+ }
2220
+ if (presentingElement) {
2221
+ const isPortrait = window.innerWidth < 768;
2222
+ if (isPortrait) {
2223
+ const transformOffset = !CSS.supports('width', 'max(0px, 1px)')
2224
+ ? '30px'
2225
+ : 'max(30px, var(--ion-safe-area-top))';
2226
+ const scale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
2227
+ presentingElement.style.transform = `translateY(${transformOffset}) scale(${scale})`;
2228
+ }
2229
+ else {
2230
+ presentingElement.style.transform = 'translateY(0px) scale(1)';
2231
+ }
2232
+ }
2233
+ }
1961
2234
  render() {
1962
2235
  const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap, expandToScroll, } = this;
1963
2236
  const showHandle = handle !== false && isSheetModal;
@@ -1965,20 +2238,20 @@ const Modal = class {
1965
2238
  const isCardModal = presentingElement !== undefined && mode === 'ios';
1966
2239
  const isHandleCycle = handleBehavior === 'cycle';
1967
2240
  const isSheetModalWithHandle = isSheetModal && showHandle;
1968
- return (h(Host, Object.assign({ key: '8add05bb43a2cdb5e3cf180147d31eb85a018fe0', "no-router": true,
2241
+ return (h(Host, Object.assign({ key: '1980fa23331381c568a2be8091d888e09754fc52', "no-router": true,
1969
2242
  // Allow the modal to be navigable when the handle is focusable
1970
2243
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
1971
2244
  zIndex: `${20000 + this.overlayIndex}`,
1972
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: '90a6605a9564a699d6f66cf71cf6b506796a2963', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: 'a97d071395333bf803c0a9347bda000cf7500d8d', class: "modal-shadow" }), h("div", Object.assign({ key: 'e7b7985c7414a13e3ba8dcecf497b76e92edf53e',
2245
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, [`modal-no-expand-scroll`]: isSheetModal && !expandToScroll, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle, onFocus: this.onModalFocus }), h("ion-backdrop", { key: 'ba94b055c064e2907eabbe6d7a43cb52adff1048', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '991f47859250d2143275ebb9b0b01a6ea8c491c0', class: "modal-shadow" }), h("div", Object.assign({ key: '02ecf8ac6a5bdb309ff993cc74a3911e99502a89',
1973
2246
  /*
1974
2247
  role and aria-modal must be used on the
1975
2248
  same element. They must also be set inside the
1976
2249
  shadow DOM otherwise ion-button will not be highlighted
1977
2250
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
1978
2251
  */
1979
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '8258b65570b11a8ee9c9df2537d6419cd2e34536', class: "modal-handle",
2252
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '0180a4d6952e41bfd736272d1a49d47d86ca7fef', class: "modal-handle",
1980
2253
  // Prevents the handle from receiving keyboard focus when it does not cycle
1981
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: '394370d0ed03ee03152f8f8abae7ff7664ca5c13' }))));
2254
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle", ref: (el) => (this.dragHandleEl = el) })), h("slot", { key: 'd062f330675f730ad70c23267baed200ca9b43b0' }))));
1982
2255
  }
1983
2256
  get el() { return getElement(this); }
1984
2257
  static get watchers() { return {