@ionic/core 8.5.8-dev.11748364689.107665ad → 8.5.8-dev.11748388365.11ad9dfe

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 (63) hide show
  1. package/components/button.js +23 -5
  2. package/components/ion-datetime.js +27 -51
  3. package/components/ion-input-password-toggle.js +2 -2
  4. package/components/ion-searchbar.js +4 -4
  5. package/components/modal.js +157 -58
  6. package/components/picker-column2.js +3 -3
  7. package/dist/cjs/ion-button_2.cjs.entry.js +19 -3
  8. package/dist/cjs/ion-datetime_3.cjs.entry.js +30 -54
  9. package/dist/cjs/ion-input-password-toggle.cjs.entry.js +2 -2
  10. package/dist/cjs/ion-modal.cjs.entry.js +157 -58
  11. package/dist/cjs/ion-searchbar.cjs.entry.js +4 -4
  12. package/dist/cjs/ionic.cjs.js +1 -1
  13. package/dist/cjs/loader.cjs.js +1 -1
  14. package/dist/collection/components/button/button.js +23 -3
  15. package/dist/collection/components/datetime/datetime.js +27 -51
  16. package/dist/collection/components/input-password-toggle/input-password-toggle.js +2 -2
  17. package/dist/collection/components/modal/animations/ios.enter.js +41 -1
  18. package/dist/collection/components/modal/animations/ios.leave.js +24 -2
  19. package/dist/collection/components/modal/animations/md.enter.js +41 -1
  20. package/dist/collection/components/modal/animations/md.leave.js +24 -2
  21. package/dist/collection/components/modal/gestures/sheet.js +27 -52
  22. package/dist/collection/components/picker-legacy-column/picker-column.js +3 -3
  23. package/dist/collection/components/searchbar/searchbar.js +5 -5
  24. package/dist/docs.json +2 -2
  25. package/dist/esm/ion-button_2.entry.js +20 -4
  26. package/dist/esm/ion-datetime_3.entry.js +30 -54
  27. package/dist/esm/ion-input-password-toggle.entry.js +2 -2
  28. package/dist/esm/ion-modal.entry.js +157 -58
  29. package/dist/esm/ion-searchbar.entry.js +4 -4
  30. package/dist/esm/ionic.js +1 -1
  31. package/dist/esm/loader.js +1 -1
  32. package/dist/esm-es5/ion-button_2.entry.js +1 -1
  33. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  34. package/dist/esm-es5/ion-input-password-toggle.entry.js +1 -1
  35. package/dist/esm-es5/ion-modal.entry.js +1 -1
  36. package/dist/esm-es5/ion-searchbar.entry.js +1 -1
  37. package/dist/esm-es5/ionic.js +1 -1
  38. package/dist/esm-es5/loader.js +1 -1
  39. package/dist/html.html-data.json +1 -1
  40. package/dist/ionic/ionic.esm.js +1 -1
  41. package/dist/ionic/p-12914457.entry.js +4 -0
  42. package/dist/ionic/{p-50cb2e8b.system.entry.js → p-3cee5d7c.system.entry.js} +2 -2
  43. package/dist/ionic/p-3d2b2787.system.entry.js +4 -0
  44. package/dist/ionic/{p-7611ede3.system.entry.js → p-3ec227cd.system.entry.js} +1 -1
  45. package/dist/ionic/p-4090ce24.entry.js +4 -0
  46. package/dist/ionic/p-8b8b4530.system.entry.js +4 -0
  47. package/dist/ionic/p-94a18d00.entry.js +4 -0
  48. package/dist/ionic/p-cec902a0.system.entry.js +4 -0
  49. package/dist/ionic/{p-891553d8.entry.js → p-e7f732ef.entry.js} +1 -1
  50. package/dist/ionic/p-f725bf9e.system.js +2 -2
  51. package/dist/ionic/{p-a835aca8.entry.js → p-ffa2125f.entry.js} +1 -1
  52. package/dist/types/components/button/button.d.ts +11 -0
  53. package/dist/types/components/searchbar/searchbar.d.ts +1 -1
  54. package/dist/types/components.d.ts +2 -2
  55. package/hydrate/index.js +211 -121
  56. package/hydrate/index.mjs +211 -121
  57. package/package.json +2 -2
  58. package/dist/ionic/p-451706f5.entry.js +0 -4
  59. package/dist/ionic/p-57957c0f.entry.js +0 -4
  60. package/dist/ionic/p-6b8530f5.system.entry.js +0 -4
  61. package/dist/ionic/p-b5432d15.entry.js +0 -4
  62. package/dist/ionic/p-c1b7d311.system.entry.js +0 -4
  63. package/dist/ionic/p-c8731f25.system.entry.js +0 -4
package/hydrate/index.js CHANGED
@@ -7990,6 +7990,19 @@ class Button {
7990
7990
  this.formButtonEl.disabled = disabled;
7991
7991
  }
7992
7992
  }
7993
+ /**
7994
+ * This component is used within the `ion-input-password-toggle` component
7995
+ * to toggle the visibility of the password input.
7996
+ * These attributes need to update based on the state of the password input.
7997
+ * Otherwise, the values will be stale.
7998
+ *
7999
+ * @param newValue
8000
+ * @param _oldValue
8001
+ * @param propName
8002
+ */
8003
+ onAriaChanged(newValue, _oldValue, propName) {
8004
+ this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { [propName]: newValue });
8005
+ }
7993
8006
  /**
7994
8007
  * This is responsible for rendering a hidden native
7995
8008
  * button element inside the associated form. This allows
@@ -8127,7 +8140,7 @@ class Button {
8127
8140
  {
8128
8141
  type !== 'button' && this.renderHiddenButton();
8129
8142
  }
8130
- return (hAsync(Host, { key: 'e213b0bb76b3f90f883b1a0ea463bb86c2df69c3', onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: createColorClasses$1(color, {
8143
+ return (hAsync(Host, { key: 'b105ad09215adb3ca2298acdadf0dc9154bbb9b0', onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: createColorClasses$1(color, {
8131
8144
  [mode]: true,
8132
8145
  [buttonType]: true,
8133
8146
  [`${buttonType}-${expand}`]: expand !== undefined,
@@ -8142,11 +8155,13 @@ class Button {
8142
8155
  'button-disabled': disabled,
8143
8156
  'ion-activatable': true,
8144
8157
  'ion-focusable': true,
8145
- }) }, hAsync(TagType, Object.assign({ key: 'b7c2a46fb994024841219316f4089335fa463d84' }, attrs, { class: "button-native", part: "native", disabled: disabled, onFocus: this.onFocus, onBlur: this.onBlur }, inheritedAttributes), hAsync("span", { key: '3e07a5c9f86836f9fbaefc6c617bdde6eb6f70cd', class: "button-inner" }, hAsync("slot", { key: '41c08ae09aed16faaa57707d229ff75d97f0731c', name: "icon-only", onSlotchange: this.slotChanged }), hAsync("slot", { key: 'ab8b749e4572884cc04970a7594466b4a24c886e', name: "start" }), hAsync("slot", { key: '397f7ff48ea45e82029414be95d29ae86e12c3a9' }), hAsync("slot", { key: '9a5627713002e8be3738d392b616f6e951b70e12', name: "end" })), mode === 'md' && hAsync("ion-ripple-effect", { key: '105566543ceda102474edab7ca8a44c7e71af589', type: this.rippleType }))));
8158
+ }) }, hAsync(TagType, Object.assign({ key: '66b4e7112bcb9e41d5a723fbbadb0a3104f9ee1d' }, attrs, { class: "button-native", part: "native", disabled: disabled, onFocus: this.onFocus, onBlur: this.onBlur }, inheritedAttributes), hAsync("span", { key: '1439fc3da280221028dcf7ce8ec9dab273c4d4bb', class: "button-inner" }, hAsync("slot", { key: 'd5269ae1afc87ec7b99746032f59cbae93720a9f', name: "icon-only", onSlotchange: this.slotChanged }), hAsync("slot", { key: '461c83e97aa246aa86d83e14f1e15a288d35041e', name: "start" }), hAsync("slot", { key: '807170d47101f9f6a333dd4ff489c89284f306fe' }), hAsync("slot", { key: 'e67f116dd0349a0d27893e4f3ff0ccef1d402f80', name: "end" })), mode === 'md' && hAsync("ion-ripple-effect", { key: '273f0bd9645a36c1bfd18a5c2ab4f81e22b7b989', type: this.rippleType }))));
8146
8159
  }
8147
8160
  get el() { return getElement(this); }
8148
8161
  static get watchers() { return {
8149
- "disabled": ["disabledChanged"]
8162
+ "disabled": ["disabledChanged"],
8163
+ "aria-checked": ["onAriaChanged"],
8164
+ "aria-label": ["onAriaChanged"]
8150
8165
  }; }
8151
8166
  static get style() { return {
8152
8167
  ios: IonButtonIosStyle0,
@@ -11637,19 +11652,18 @@ class Datetime {
11637
11652
  warnIfValueOutOfBounds(valueToProcess, minParts, maxParts);
11638
11653
  }
11639
11654
  /**
11640
- * If there are multiple values, pick an arbitrary one to clamp to. This way,
11641
- * if the values are across months, we always show at least one of them. Note
11642
- * that the values don't necessarily have to be in order.
11655
+ * If there are multiple values, clamp to the last one.
11656
+ * This is because the last value is the one that the user
11657
+ * has most recently interacted with.
11643
11658
  */
11644
- const singleValue = Array.isArray(valueToProcess) ? valueToProcess[0] : valueToProcess;
11659
+ const singleValue = Array.isArray(valueToProcess) ? valueToProcess[valueToProcess.length - 1] : valueToProcess;
11645
11660
  const targetValue = clampDate(singleValue, minParts, maxParts);
11646
11661
  const { month, day, year, hour, minute } = targetValue;
11647
11662
  const ampm = parseAmPm(hour);
11648
11663
  /**
11649
- * Since `activeParts` indicates a value that
11650
- * been explicitly selected either by the
11651
- * user or the app, only update `activeParts`
11652
- * if the `value` property is set.
11664
+ * Since `activeParts` indicates a value that been explicitly selected
11665
+ * either by the user or the app, only update `activeParts` if the
11666
+ * `value` property is set.
11653
11667
  */
11654
11668
  if (hasValue) {
11655
11669
  if (Array.isArray(valueToProcess)) {
@@ -11674,51 +11688,28 @@ class Datetime {
11674
11688
  */
11675
11689
  this.activeParts = [];
11676
11690
  }
11677
- /**
11678
- * Only animate if:
11679
- * 1. We're using grid style (wheel style pickers should just jump to new value)
11680
- * 2. The month and/or year actually changed, and both are defined (otherwise there's nothing to animate to)
11681
- * 3. The calendar body is visible (prevents animation when in collapsed datetime-button, for example)
11682
- * 4. The month/year picker is not open (since you wouldn't see the animation anyway)
11683
- */
11684
11691
  const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
11685
11692
  const bodyIsVisible = el.classList.contains('datetime-ready');
11686
11693
  const { isGridStyle, showMonthAndYear } = this;
11687
- let areAllSelectedDatesInSameMonth = true;
11688
- if (Array.isArray(valueToProcess)) {
11689
- const firstMonth = valueToProcess[0].month;
11690
- for (const date of valueToProcess) {
11691
- if (date.month !== firstMonth) {
11692
- areAllSelectedDatesInSameMonth = false;
11693
- break;
11694
- }
11695
- }
11694
+ if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
11695
+ /**
11696
+ * Only animate if:
11697
+ * 1. We're using grid style (wheel style pickers should just jump to new value)
11698
+ * 2. The month and/or year actually changed, and both are defined (otherwise there's nothing to animate to)
11699
+ * 3. The calendar body is visible (prevents animation when in collapsed datetime-button, for example)
11700
+ * 4. The month/year picker is not open (since you wouldn't see the animation anyway)
11701
+ */
11702
+ this.animateToDate(targetValue);
11696
11703
  }
11697
- /**
11698
- * If there is more than one date selected
11699
- * and the dates aren't all in the same month,
11700
- * then we should neither animate to the date
11701
- * nor update the working parts because we do
11702
- * not know which date the user wants to view.
11703
- */
11704
- if (areAllSelectedDatesInSameMonth) {
11705
- if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
11706
- this.animateToDate(targetValue);
11707
- }
11708
- else {
11709
- /**
11710
- * We only need to do this if we didn't just animate to a new month,
11711
- * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
11712
- */
11713
- this.setWorkingParts({
11714
- month,
11715
- day,
11716
- year,
11717
- hour,
11718
- minute,
11719
- ampm,
11720
- });
11721
- }
11704
+ else {
11705
+ this.setWorkingParts({
11706
+ month,
11707
+ day,
11708
+ year,
11709
+ hour,
11710
+ minute,
11711
+ ampm,
11712
+ });
11722
11713
  }
11723
11714
  };
11724
11715
  this.animateToDate = async (targetValue) => {
@@ -12713,7 +12704,7 @@ class Datetime {
12713
12704
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
12714
12705
  const hasWheelVariant = hasDatePresentation && preferWheel;
12715
12706
  renderHiddenInput(true, el, name, formatValue(value), disabled);
12716
- return (hAsync(Host, { key: 'c3dfea8f46fcbcef38eb9e8a69b1b46a4e4b82fd', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
12707
+ return (hAsync(Host, { key: '20e64fb4cfe3fbd74b24038c89e00651d78b500c', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
12717
12708
  [mode]: true,
12718
12709
  ['datetime-readonly']: readonly,
12719
12710
  ['datetime-disabled']: disabled,
@@ -12723,7 +12714,7 @@ class Datetime {
12723
12714
  [`datetime-size-${size}`]: true,
12724
12715
  [`datetime-prefer-wheel`]: hasWheelVariant,
12725
12716
  [`datetime-grid`]: isGridStyle,
12726
- })) }, hAsync("div", { key: '75c91243cf6a51f44b83d7cf7d8c0c96bfd3c83f', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
12717
+ })) }, hAsync("div", { key: '488fe7bf6b9052e208d65206a580d5d65b945a62', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
12727
12718
  }
12728
12719
  get el() { return getElement(this); }
12729
12720
  static get watchers() { return {
@@ -15697,14 +15688,14 @@ class InputPasswordToggle {
15697
15688
  const isPasswordVisible = type === 'text';
15698
15689
  return (hAsync(Host, { key: '1a28e078c83e74c72d8bb8189ece93ec2e3fa3d0', class: createColorClasses$1(color, {
15699
15690
  [mode]: true,
15700
- }) }, hAsync("ion-button", { key: '039d1bab764093bb6fe4a34299b0872abda087fd', mode: mode, color: color, fill: "clear", shape: "round", "aria-checked": isPasswordVisible ? 'true' : 'false', "aria-label": "show password", role: "switch", type: "button", onPointerDown: (ev) => {
15691
+ }) }, hAsync("ion-button", { key: '61591d11d97f3065240e51d8887f831339fd36cf', mode: mode, color: color, fill: "clear", shape: "round", "aria-checked": isPasswordVisible ? 'true' : 'false', "aria-label": isPasswordVisible ? 'Hide password' : 'Show password', role: "switch", type: "button", onPointerDown: (ev) => {
15701
15692
  /**
15702
15693
  * This prevents mobile browsers from
15703
15694
  * blurring the input when the password toggle
15704
15695
  * button is activated.
15705
15696
  */
15706
15697
  ev.preventDefault();
15707
- }, onClick: this.togglePasswordVisibility }, hAsync("ion-icon", { key: '26477ee97b808c3d79944bf5e33d4e05f1ae0b3f', slot: "icon-only", "aria-hidden": "true", icon: isPasswordVisible ? hidePasswordIcon : showPasswordIcon }))));
15698
+ }, onClick: this.togglePasswordVisibility }, hAsync("ion-icon", { key: '9d98e6675d5e2adea5c0f56ab67e98b6f57521dd', slot: "icon-only", "aria-hidden": "true", icon: isPasswordVisible ? hidePasswordIcon : showPasswordIcon }))));
15708
15699
  }
15709
15700
  get el() { return getElement(this); }
15710
15701
  static get watchers() { return {
@@ -19214,7 +19205,47 @@ const iosEnterAnimation$3 = (baseEl, opts) => {
19214
19205
  .addElement(baseEl)
19215
19206
  .easing('cubic-bezier(0.32,0.72,0,1)')
19216
19207
  .duration(500)
19217
- .addAnimation([wrapperAnimation]);
19208
+ .addAnimation([wrapperAnimation])
19209
+ .beforeAddWrite(() => {
19210
+ if (expandToScroll) {
19211
+ // Scroll can only be done when the modal is fully expanded.
19212
+ return;
19213
+ }
19214
+ /**
19215
+ * There are some browsers that causes flickering when
19216
+ * dragging the content when scroll is enabled at every
19217
+ * breakpoint. This is due to the wrapper element being
19218
+ * transformed off the screen and having a snap animation.
19219
+ *
19220
+ * A workaround is to clone the footer element and append
19221
+ * it outside of the wrapper element. This way, the footer
19222
+ * is still visible and the drag can be done without
19223
+ * flickering. The original footer is hidden until the modal
19224
+ * is dismissed. This maintains the animation of the footer
19225
+ * when the modal is dismissed.
19226
+ *
19227
+ * The workaround needs to be done before the animation starts
19228
+ * so there are no flickering issues.
19229
+ */
19230
+ const ionFooter = baseEl.querySelector('ion-footer');
19231
+ /**
19232
+ * This check is needed to prevent more than one footer
19233
+ * from being appended to the shadow root.
19234
+ * Otherwise, iOS and MD enter animations would append
19235
+ * the footer twice.
19236
+ */
19237
+ const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
19238
+ if (ionFooter && !ionFooterAlreadyAppended) {
19239
+ const footerHeight = ionFooter.clientHeight;
19240
+ const clonedFooter = ionFooter.cloneNode(true);
19241
+ baseEl.shadowRoot.appendChild(clonedFooter);
19242
+ ionFooter.style.setProperty('display', 'none');
19243
+ ionFooter.setAttribute('aria-hidden', 'true');
19244
+ // Padding is added to prevent some content from being hidden.
19245
+ const page = baseEl.querySelector('.ion-page');
19246
+ page.style.setProperty('padding-bottom', `${footerHeight}px`);
19247
+ }
19248
+ });
19218
19249
  if (contentAnimation) {
19219
19250
  baseAnimation.addAnimation(contentAnimation);
19220
19251
  }
@@ -19295,7 +19326,7 @@ const createLeaveAnimation$1 = () => {
19295
19326
  * iOS Modal Leave Animation
19296
19327
  */
19297
19328
  const iosLeaveAnimation$3 = (baseEl, opts, duration = 500) => {
19298
- const { presentingEl, currentBreakpoint } = opts;
19329
+ const { presentingEl, currentBreakpoint, expandToScroll } = opts;
19299
19330
  const root = getElementRoot(baseEl);
19300
19331
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation$1();
19301
19332
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -19304,7 +19335,29 @@ const iosLeaveAnimation$3 = (baseEl, opts, duration = 500) => {
19304
19335
  .addElement(baseEl)
19305
19336
  .easing('cubic-bezier(0.32,0.72,0,1)')
19306
19337
  .duration(duration)
19307
- .addAnimation(wrapperAnimation);
19338
+ .addAnimation(wrapperAnimation)
19339
+ .beforeAddWrite(() => {
19340
+ if (expandToScroll) {
19341
+ // Scroll can only be done when the modal is fully expanded.
19342
+ return;
19343
+ }
19344
+ /**
19345
+ * If expandToScroll is disabled, we need to swap
19346
+ * the visibility to the original, so the footer
19347
+ * dismisses with the modal and doesn't stay
19348
+ * until the modal is removed from the DOM.
19349
+ */
19350
+ const ionFooter = baseEl.querySelector('ion-footer');
19351
+ if (ionFooter) {
19352
+ const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
19353
+ ionFooter.style.removeProperty('display');
19354
+ ionFooter.removeAttribute('aria-hidden');
19355
+ clonedFooter.style.setProperty('display', 'none');
19356
+ clonedFooter.setAttribute('aria-hidden', 'true');
19357
+ const page = baseEl.querySelector('.ion-page');
19358
+ page.style.removeProperty('padding-bottom');
19359
+ }
19360
+ });
19308
19361
  if (presentingEl) {
19309
19362
  const isMobile = window.innerWidth < 768;
19310
19363
  const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
@@ -19400,7 +19453,47 @@ const mdEnterAnimation$2 = (baseEl, opts) => {
19400
19453
  .addElement(baseEl)
19401
19454
  .easing('cubic-bezier(0.36,0.66,0.04,1)')
19402
19455
  .duration(280)
19403
- .addAnimation([backdropAnimation, wrapperAnimation]);
19456
+ .addAnimation([backdropAnimation, wrapperAnimation])
19457
+ .beforeAddWrite(() => {
19458
+ if (expandToScroll) {
19459
+ // Scroll can only be done when the modal is fully expanded.
19460
+ return;
19461
+ }
19462
+ /**
19463
+ * There are some browsers that causes flickering when
19464
+ * dragging the content when scroll is enabled at every
19465
+ * breakpoint. This is due to the wrapper element being
19466
+ * transformed off the screen and having a snap animation.
19467
+ *
19468
+ * A workaround is to clone the footer element and append
19469
+ * it outside of the wrapper element. This way, the footer
19470
+ * is still visible and the drag can be done without
19471
+ * flickering. The original footer is hidden until the modal
19472
+ * is dismissed. This maintains the animation of the footer
19473
+ * when the modal is dismissed.
19474
+ *
19475
+ * The workaround needs to be done before the animation starts
19476
+ * so there are no flickering issues.
19477
+ */
19478
+ const ionFooter = baseEl.querySelector('ion-footer');
19479
+ /**
19480
+ * This check is needed to prevent more than one footer
19481
+ * from being appended to the shadow root.
19482
+ * Otherwise, iOS and MD enter animations would append
19483
+ * the footer twice.
19484
+ */
19485
+ const ionFooterAlreadyAppended = baseEl.shadowRoot.querySelector('ion-footer');
19486
+ if (ionFooter && !ionFooterAlreadyAppended) {
19487
+ const footerHeight = ionFooter.clientHeight;
19488
+ const clonedFooter = ionFooter.cloneNode(true);
19489
+ baseEl.shadowRoot.appendChild(clonedFooter);
19490
+ ionFooter.style.setProperty('display', 'none');
19491
+ ionFooter.setAttribute('aria-hidden', 'true');
19492
+ // Padding is added to prevent some content from being hidden.
19493
+ const page = baseEl.querySelector('.ion-page');
19494
+ page.style.setProperty('padding-bottom', `${footerHeight}px`);
19495
+ }
19496
+ });
19404
19497
  if (contentAnimation) {
19405
19498
  baseAnimation.addAnimation(contentAnimation);
19406
19499
  }
@@ -19419,7 +19512,7 @@ const createLeaveAnimation = () => {
19419
19512
  * Md Modal Leave Animation
19420
19513
  */
19421
19514
  const mdLeaveAnimation$2 = (baseEl, opts) => {
19422
- const { currentBreakpoint } = opts;
19515
+ const { currentBreakpoint, expandToScroll } = opts;
19423
19516
  const root = getElementRoot(baseEl);
19424
19517
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
19425
19518
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -19427,7 +19520,29 @@ const mdLeaveAnimation$2 = (baseEl, opts) => {
19427
19520
  const baseAnimation = createAnimation()
19428
19521
  .easing('cubic-bezier(0.47,0,0.745,0.715)')
19429
19522
  .duration(200)
19430
- .addAnimation([backdropAnimation, wrapperAnimation]);
19523
+ .addAnimation([backdropAnimation, wrapperAnimation])
19524
+ .beforeAddWrite(() => {
19525
+ if (expandToScroll) {
19526
+ // Scroll can only be done when the modal is fully expanded.
19527
+ return;
19528
+ }
19529
+ /**
19530
+ * If expandToScroll is disabled, we need to swap
19531
+ * the visibility to the original, so the footer
19532
+ * dismisses with the modal and doesn't stay
19533
+ * until the modal is removed from the DOM.
19534
+ */
19535
+ const ionFooter = baseEl.querySelector('ion-footer');
19536
+ if (ionFooter) {
19537
+ const clonedFooter = baseEl.shadowRoot.querySelector('ion-footer');
19538
+ ionFooter.style.removeProperty('display');
19539
+ ionFooter.removeAttribute('aria-hidden');
19540
+ clonedFooter.style.setProperty('display', 'none');
19541
+ clonedFooter.setAttribute('aria-hidden', 'true');
19542
+ const page = baseEl.querySelector('.ion-page');
19543
+ page.style.removeProperty('padding-bottom');
19544
+ }
19545
+ });
19431
19546
  return baseAnimation;
19432
19547
  };
19433
19548
 
@@ -19459,8 +19574,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19459
19574
  let offset = 0;
19460
19575
  let canDismissBlocksGesture = false;
19461
19576
  let cachedScrollEl = null;
19462
- let cachedFooterYPosition = null;
19463
- let currentFooterState = null;
19464
19577
  const canDismissMaxStep = 0.95;
19465
19578
  const maxBreakpoint = breakpoints[breakpoints.length - 1];
19466
19579
  const minBreakpoint = breakpoints[0];
@@ -19490,38 +19603,29 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19490
19603
  baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
19491
19604
  };
19492
19605
  /**
19493
- * Toggles the footer to an absolute position while moving to prevent
19494
- * it from shaking while the sheet is being dragged.
19495
- * @param footer Whether the footer is in a moving or stationary position.
19606
+ * Toggles the visible modal footer when `expandToScroll` is disabled.
19607
+ * @param footer The footer to show.
19496
19608
  */
19497
- const swapFooterPosition = (newPosition) => {
19498
- var _a, _b;
19609
+ const swapFooterVisibility = (footer) => {
19499
19610
  const originalFooter = baseEl.querySelector('ion-footer');
19500
19611
  if (!originalFooter) {
19501
19612
  return;
19502
19613
  }
19503
- currentFooterState = newPosition;
19504
- if (newPosition === 'stationary') {
19505
- // Reset positioning styles to allow normal document flow
19506
- originalFooter.style.removeProperty('position');
19507
- originalFooter.style.removeProperty('bottom');
19508
- (_a = originalFooter.parentElement) === null || _a === void 0 ? void 0 : _a.style.removeProperty('padding-bottom');
19614
+ const clonedFooter = wrapperEl.nextElementSibling;
19615
+ const footerToHide = footer === 'original' ? clonedFooter : originalFooter;
19616
+ const footerToShow = footer === 'original' ? originalFooter : clonedFooter;
19617
+ footerToShow.style.removeProperty('display');
19618
+ footerToShow.removeAttribute('aria-hidden');
19619
+ const page = baseEl.querySelector('.ion-page');
19620
+ if (footer === 'original') {
19621
+ page.style.removeProperty('padding-bottom');
19509
19622
  }
19510
19623
  else {
19511
- // Add padding to the parent element to prevent content from being hidden
19512
- // when the footer is positioned absolutely. This has to be done before we
19513
- // make the footer absolutely positioned or we may accidentally cause the
19514
- // sheet to scroll.
19515
- const footerHeight = originalFooter.clientHeight;
19516
- (_b = originalFooter.parentElement) === null || _b === void 0 ? void 0 : _b.style.setProperty('padding-bottom', `${footerHeight}px`);
19517
- // Apply positioning styles to keep footer at bottom
19518
- originalFooter.style.setProperty('position', 'absolute');
19519
- originalFooter.style.setProperty('bottom', '0');
19520
- // Also cache the footer Y position, which we use to determine if the
19521
- // sheet has been moved below the footer. When that happens, we need to swap
19522
- // the position back so it will collapse correctly.
19523
- cachedFooterYPosition = originalFooter.getBoundingClientRect().top + window.scrollY;
19624
+ const pagePadding = footerToShow.clientHeight;
19625
+ page.style.setProperty('padding-bottom', `${pagePadding}px`);
19524
19626
  }
19627
+ footerToHide.style.setProperty('display', 'none');
19628
+ footerToHide.setAttribute('aria-hidden', 'true');
19525
19629
  };
19526
19630
  /**
19527
19631
  * After the entering animation completes,
@@ -19615,11 +19719,12 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19615
19719
  }
19616
19720
  /**
19617
19721
  * If expandToScroll is disabled, we need to swap
19618
- * the footer position to moving so that it doesn't shake
19619
- * while the sheet is being dragged.
19722
+ * the footer visibility to the original, so if the modal
19723
+ * is dismissed, the footer dismisses with the modal
19724
+ * and doesn't stay on the screen after the modal is gone.
19620
19725
  */
19621
19726
  if (!expandToScroll) {
19622
- swapFooterPosition('moving');
19727
+ swapFooterVisibility('original');
19623
19728
  }
19624
19729
  /**
19625
19730
  * If we are pulling down, then it is possible we are pulling on the content.
@@ -19638,21 +19743,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19638
19743
  animation.progressStart(true, 1 - currentBreakpoint);
19639
19744
  };
19640
19745
  const onMove = (detail) => {
19641
- /**
19642
- * If `expandToScroll` is disabled, we need to see if we're currently below
19643
- * the footer element and the footer is in a stationary position. If so,
19644
- * we need to make the stationary the original position so that the footer
19645
- * collapses with the sheet.
19646
- */
19647
- if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
19648
- // Check if we need to swap the footer position
19649
- if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
19650
- swapFooterPosition('stationary');
19651
- }
19652
- else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
19653
- swapFooterPosition('moving');
19654
- }
19655
- }
19656
19746
  /**
19657
19747
  * If `expandToScroll` is disabled, and an upwards swipe gesture is done within
19658
19748
  * the scrollable content, we should not allow the swipe gesture to continue.
@@ -19786,6 +19876,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19786
19876
  * snapping animation completes.
19787
19877
  */
19788
19878
  gesture.enable(false);
19879
+ /**
19880
+ * If expandToScroll is disabled, we need to swap
19881
+ * the footer visibility to the cloned one so the footer
19882
+ * doesn't flicker when the sheet's height is animated.
19883
+ */
19884
+ if (!expandToScroll && shouldRemainOpen) {
19885
+ swapFooterVisibility('cloned');
19886
+ }
19789
19887
  if (shouldPreventDismiss) {
19790
19888
  handleCanDismiss(baseEl, animation);
19791
19889
  }
@@ -19806,14 +19904,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19806
19904
  animation
19807
19905
  .onFinish(() => {
19808
19906
  if (shouldRemainOpen) {
19809
- /**
19810
- * If expandToScroll is disabled, we need to swap
19811
- * the footer position to stationary so that it
19812
- * will act as it would by default
19813
- */
19814
- if (!expandToScroll) {
19815
- swapFooterPosition('stationary');
19816
- }
19817
19907
  /**
19818
19908
  * Once the snapping animation completes,
19819
19909
  * we need to reset the animation to go
@@ -23230,7 +23320,7 @@ class PickerColumnCmp {
23230
23320
  const colEl = this.optsEl;
23231
23321
  if (colEl) {
23232
23322
  // DOM READ
23233
- // We perfom a DOM read over a rendered item, this needs to happen after the first render or after the the column has changed
23323
+ // We perfom a DOM read over a rendered item, this needs to happen after the first render or after the column has changed
23234
23324
  this.optHeight = colEl.firstElementChild ? colEl.firstElementChild.clientHeight : 0;
23235
23325
  }
23236
23326
  this.refresh(forceRefresh, animated);
@@ -23238,9 +23328,9 @@ class PickerColumnCmp {
23238
23328
  render() {
23239
23329
  const col = this.col;
23240
23330
  const mode = getIonMode$1(this);
23241
- return (hAsync(Host, { key: '88a3c9397c9ac92dd814074c8ae6ecf8e3420a2c', class: Object.assign({ [mode]: true, 'picker-col': true, 'picker-opts-left': this.col.align === 'left', 'picker-opts-right': this.col.align === 'right' }, getClassMap(col.cssClass)), style: {
23331
+ return (hAsync(Host, { key: '10ef653cbae8e1ed92a23fa17f3396082e35951f', class: Object.assign({ [mode]: true, 'picker-col': true, 'picker-opts-left': this.col.align === 'left', 'picker-opts-right': this.col.align === 'right' }, getClassMap(col.cssClass)), style: {
23242
23332
  'max-width': this.col.columnWidth,
23243
- } }, col.prefix && (hAsync("div", { key: '4491a705d15337e6f45f3cf6fd21af5242474729', class: "picker-prefix", style: { width: col.prefixWidth } }, col.prefix)), hAsync("div", { key: 'b0dd4b7a7a4c1edc4b73e7fb134ac85264072365', class: "picker-opts", style: { maxWidth: col.optionsWidth }, ref: (el) => (this.optsEl = el) }, col.options.map((o, index) => (hAsync("button", { "aria-label": o.ariaLabel, class: { 'picker-opt': true, 'picker-opt-disabled': !!o.disabled }, "opt-index": index }, o.text)))), col.suffix && (hAsync("div", { key: 'c16419ce6481d60fc3ba6b8d102a4edf0ede02aa', class: "picker-suffix", style: { width: col.suffixWidth } }, col.suffix))));
23333
+ } }, col.prefix && (hAsync("div", { key: '253066708012034206b1d3d466ea48d0a3be3323', class: "picker-prefix", style: { width: col.prefixWidth } }, col.prefix)), hAsync("div", { key: '15fa07307d4d2b4994504a5bf2de8db05b51cd2c', class: "picker-opts", style: { maxWidth: col.optionsWidth }, ref: (el) => (this.optsEl = el) }, col.options.map((o, index) => (hAsync("button", { "aria-label": o.ariaLabel, class: { 'picker-opt': true, 'picker-opt-disabled': !!o.disabled }, "opt-index": index }, o.text)))), col.suffix && (hAsync("div", { key: '4db779830b1e6aa6b324e5a72541d4f610ac1ff5', class: "picker-suffix", style: { width: col.suffixWidth } }, col.suffix))));
23244
23334
  }
23245
23335
  get el() { return getElement(this); }
23246
23336
  static get watchers() { return {
@@ -28952,8 +29042,8 @@ class Searchbar {
28952
29042
  const clearIcon = this.clearIcon || (mode === 'ios' ? closeCircle : closeSharp);
28953
29043
  const searchIcon = this.searchIcon || (mode === 'ios' ? searchOutline : searchSharp);
28954
29044
  const shouldShowCancelButton = this.shouldShowCancelButton();
28955
- const cancelButton = this.showCancelButton !== 'never' && (hAsync("button", { key: '989f3e84c472ada6e66dd9b249d0d268bf17ce26', "aria-label": cancelButtonText, "aria-hidden": shouldShowCancelButton ? undefined : 'true', type: "button", tabIndex: mode === 'ios' && !shouldShowCancelButton ? -1 : undefined, onMouseDown: this.onCancelSearchbar, onTouchStart: this.onCancelSearchbar, class: "searchbar-cancel-button" }, hAsync("div", { key: '7d335d4fde33822dc79d26b748ba2e98db7494bb', "aria-hidden": "true" }, mode === 'md' ? (hAsync("ion-icon", { "aria-hidden": "true", mode: mode, icon: this.cancelButtonIcon, lazy: false })) : (cancelButtonText))));
28956
- return (hAsync(Host, { key: 'd1a1972725e949fb102c91487aaa7b9d10c2d718', role: "search", "aria-disabled": this.disabled ? 'true' : null, class: createColorClasses$1(this.color, {
29045
+ const cancelButton = this.showCancelButton !== 'never' && (hAsync("button", { key: '4a4bddfaf44acb9ea71d37d11c3fc11450134a5c', "aria-label": cancelButtonText, "aria-hidden": shouldShowCancelButton ? undefined : 'true', type: "button", tabIndex: mode === 'ios' && !shouldShowCancelButton ? -1 : undefined, onMouseDown: this.onCancelSearchbar, onTouchStart: this.onCancelSearchbar, class: "searchbar-cancel-button" }, hAsync("div", { key: '24424547e34a80422f617f5597965724a3ef65f0', "aria-hidden": "true" }, mode === 'md' ? (hAsync("ion-icon", { "aria-hidden": "true", mode: mode, icon: this.cancelButtonIcon, lazy: false })) : (cancelButtonText))));
29046
+ return (hAsync(Host, { key: '0c0e7334cb2af87081a278e5a3f6be3dc646a073', role: "search", "aria-disabled": this.disabled ? 'true' : null, class: createColorClasses$1(this.color, {
28957
29047
  [mode]: true,
28958
29048
  'searchbar-animated': animated,
28959
29049
  'searchbar-disabled': this.disabled,
@@ -28963,14 +29053,14 @@ class Searchbar {
28963
29053
  'searchbar-has-focus': this.focused,
28964
29054
  'searchbar-should-show-clear': this.shouldShowClearButton(),
28965
29055
  'searchbar-should-show-cancel': this.shouldShowCancelButton(),
28966
- }) }, hAsync("div", { key: 'add53640b2994cb6b2bf02792dafe51aba6b1684', class: "searchbar-input-container" }, hAsync("input", Object.assign({ key: '160cc36459a4a652e7f41ccd14dcdc782278779e', "aria-label": "search text", disabled: this.disabled, ref: (el) => (this.nativeInput = el), class: "searchbar-input", inputMode: this.inputmode, enterKeyHint: this.enterkeyhint, name: this.name, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, minLength: this.minlength, maxLength: this.maxlength, placeholder: this.placeholder, type: this.type, value: this.getValue(), autoCapitalize: autocapitalize === 'default' ? undefined : autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, spellcheck: this.spellcheck }, this.inheritedAttributes)), mode === 'md' && cancelButton, hAsync("ion-icon", { key: '8825fd13af0d2dea451ccc0e00ae7b5021dc01c4', "aria-hidden": "true", mode: mode, icon: searchIcon, lazy: false, class: "searchbar-search-icon" }), hAsync("button", { key: '8a7b56da278b9ca5c4f5a4ee9c01924fd5ae29d8', "aria-label": "reset", type: "button", "no-blur": true, class: "searchbar-clear-button", onPointerDown: (ev) => {
29056
+ }) }, hAsync("div", { key: '859da78b062b9059701eba166be3bc5417f7395b', class: "searchbar-input-container" }, hAsync("input", Object.assign({ key: '840fd06a1e4b5a8d7f6d7439d02aef9fcb9720b6', "aria-label": "search text", disabled: this.disabled, ref: (el) => (this.nativeInput = el), class: "searchbar-input", inputMode: this.inputmode, enterKeyHint: this.enterkeyhint, name: this.name, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, minLength: this.minlength, maxLength: this.maxlength, placeholder: this.placeholder, type: this.type, value: this.getValue(), autoCapitalize: autocapitalize === 'default' ? undefined : autocapitalize, autoComplete: this.autocomplete, autoCorrect: this.autocorrect, spellcheck: this.spellcheck }, this.inheritedAttributes)), mode === 'md' && cancelButton, hAsync("ion-icon", { key: 'a5aaa6a2204d38433cac283dd47b6197499fa585', "aria-hidden": "true", mode: mode, icon: searchIcon, lazy: false, class: "searchbar-search-icon" }), hAsync("button", { key: 'cf62c8969c5c916ac838e122a0ad45b2ae234791', "aria-label": "reset", type: "button", "no-blur": true, class: "searchbar-clear-button", onPointerDown: (ev) => {
28967
29057
  /**
28968
29058
  * This prevents mobile browsers from
28969
29059
  * blurring the input when the clear
28970
29060
  * button is activated.
28971
29061
  */
28972
29062
  ev.preventDefault();
28973
- }, onClick: () => this.onClearInput(true) }, hAsync("ion-icon", { key: '24c55274516ab012d8c25f03525c6cdb9409e52f', "aria-hidden": "true", mode: mode, icon: clearIcon, lazy: false, class: "searchbar-clear-icon" }))), mode === 'ios' && cancelButton));
29063
+ }, onClick: () => this.onClearInput(true) }, hAsync("ion-icon", { key: 'b1a75f0964fc2119479e246dc27bef7cc33bd19f', "aria-hidden": "true", mode: mode, icon: clearIcon, lazy: false, class: "searchbar-clear-icon" }))), mode === 'ios' && cancelButton));
28974
29064
  }
28975
29065
  get el() { return getElement(this); }
28976
29066
  static get watchers() { return {