@ionic/core 8.5.8-dev.11748388365.11ad9dfe → 8.5.8-dev.11748525800.1cdc649b

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 (67) hide show
  1. package/components/button.js +5 -23
  2. package/components/ion-datetime.js +51 -27
  3. package/components/ion-input-password-toggle.js +2 -2
  4. package/components/ion-searchbar.js +4 -4
  5. package/components/modal.js +97 -159
  6. package/components/picker-column2.js +3 -3
  7. package/css/core.css +1 -1
  8. package/css/core.css.map +1 -1
  9. package/css/ionic.bundle.css +1 -1
  10. package/css/ionic.bundle.css.map +1 -1
  11. package/dist/cjs/ion-button_2.cjs.entry.js +3 -19
  12. package/dist/cjs/ion-datetime_3.cjs.entry.js +54 -30
  13. package/dist/cjs/ion-input-password-toggle.cjs.entry.js +2 -2
  14. package/dist/cjs/ion-modal.cjs.entry.js +97 -159
  15. package/dist/cjs/ion-searchbar.cjs.entry.js +4 -4
  16. package/dist/cjs/ionic.cjs.js +1 -1
  17. package/dist/cjs/loader.cjs.js +1 -1
  18. package/dist/collection/components/button/button.js +3 -23
  19. package/dist/collection/components/datetime/datetime.js +51 -27
  20. package/dist/collection/components/input-password-toggle/input-password-toggle.js +2 -2
  21. package/dist/collection/components/modal/animations/ios.enter.js +1 -41
  22. package/dist/collection/components/modal/animations/ios.leave.js +2 -24
  23. package/dist/collection/components/modal/animations/md.enter.js +1 -41
  24. package/dist/collection/components/modal/animations/md.leave.js +2 -24
  25. package/dist/collection/components/modal/gestures/sheet.js +91 -29
  26. package/dist/collection/components/picker-legacy-column/picker-column.js +3 -3
  27. package/dist/collection/components/searchbar/searchbar.js +5 -5
  28. package/dist/docs.json +2 -2
  29. package/dist/esm/ion-button_2.entry.js +4 -20
  30. package/dist/esm/ion-datetime_3.entry.js +54 -30
  31. package/dist/esm/ion-input-password-toggle.entry.js +2 -2
  32. package/dist/esm/ion-modal.entry.js +97 -159
  33. package/dist/esm/ion-searchbar.entry.js +4 -4
  34. package/dist/esm/ionic.js +1 -1
  35. package/dist/esm/loader.js +1 -1
  36. package/dist/esm-es5/ion-button_2.entry.js +1 -1
  37. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  38. package/dist/esm-es5/ion-input-password-toggle.entry.js +1 -1
  39. package/dist/esm-es5/ion-modal.entry.js +1 -1
  40. package/dist/esm-es5/ion-searchbar.entry.js +1 -1
  41. package/dist/esm-es5/ionic.js +1 -1
  42. package/dist/esm-es5/loader.js +1 -1
  43. package/dist/html.html-data.json +1 -1
  44. package/dist/ionic/ionic.esm.js +1 -1
  45. package/dist/ionic/{p-3cee5d7c.system.entry.js → p-50cb2e8b.system.entry.js} +2 -2
  46. package/dist/ionic/p-57957c0f.entry.js +4 -0
  47. package/dist/ionic/p-5dbf1f31.entry.js +4 -0
  48. package/dist/ionic/p-6b8530f5.system.entry.js +4 -0
  49. package/dist/ionic/{p-3ec227cd.system.entry.js → p-7611ede3.system.entry.js} +1 -1
  50. package/dist/ionic/p-76407fc5.system.entry.js +4 -0
  51. package/dist/ionic/{p-e7f732ef.entry.js → p-891553d8.entry.js} +1 -1
  52. package/dist/ionic/{p-ffa2125f.entry.js → p-a835aca8.entry.js} +1 -1
  53. package/dist/ionic/p-b5432d15.entry.js +4 -0
  54. package/dist/ionic/p-c1b7d311.system.entry.js +4 -0
  55. package/dist/ionic/p-f725bf9e.system.js +2 -2
  56. package/dist/types/components/button/button.d.ts +0 -11
  57. package/dist/types/components/searchbar/searchbar.d.ts +1 -1
  58. package/dist/types/components.d.ts +2 -2
  59. package/hydrate/index.js +160 -213
  60. package/hydrate/index.mjs +160 -213
  61. package/package.json +2 -2
  62. package/dist/ionic/p-12914457.entry.js +0 -4
  63. package/dist/ionic/p-3d2b2787.system.entry.js +0 -4
  64. package/dist/ionic/p-4090ce24.entry.js +0 -4
  65. package/dist/ionic/p-8b8b4530.system.entry.js +0 -4
  66. package/dist/ionic/p-94a18d00.entry.js +0 -4
  67. package/dist/ionic/p-cec902a0.system.entry.js +0 -4
package/hydrate/index.js CHANGED
@@ -7990,19 +7990,6 @@ 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
- }
8006
7993
  /**
8007
7994
  * This is responsible for rendering a hidden native
8008
7995
  * button element inside the associated form. This allows
@@ -8140,7 +8127,7 @@ class Button {
8140
8127
  {
8141
8128
  type !== 'button' && this.renderHiddenButton();
8142
8129
  }
8143
- return (hAsync(Host, { key: 'b105ad09215adb3ca2298acdadf0dc9154bbb9b0', onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: createColorClasses$1(color, {
8130
+ return (hAsync(Host, { key: 'e213b0bb76b3f90f883b1a0ea463bb86c2df69c3', onClick: this.handleClick, "aria-disabled": disabled ? 'true' : null, class: createColorClasses$1(color, {
8144
8131
  [mode]: true,
8145
8132
  [buttonType]: true,
8146
8133
  [`${buttonType}-${expand}`]: expand !== undefined,
@@ -8155,13 +8142,11 @@ class Button {
8155
8142
  'button-disabled': disabled,
8156
8143
  'ion-activatable': true,
8157
8144
  'ion-focusable': true,
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 }))));
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 }))));
8159
8146
  }
8160
8147
  get el() { return getElement(this); }
8161
8148
  static get watchers() { return {
8162
- "disabled": ["disabledChanged"],
8163
- "aria-checked": ["onAriaChanged"],
8164
- "aria-label": ["onAriaChanged"]
8149
+ "disabled": ["disabledChanged"]
8165
8150
  }; }
8166
8151
  static get style() { return {
8167
8152
  ios: IonButtonIosStyle0,
@@ -11652,18 +11637,19 @@ class Datetime {
11652
11637
  warnIfValueOutOfBounds(valueToProcess, minParts, maxParts);
11653
11638
  }
11654
11639
  /**
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.
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.
11658
11643
  */
11659
- const singleValue = Array.isArray(valueToProcess) ? valueToProcess[valueToProcess.length - 1] : valueToProcess;
11644
+ const singleValue = Array.isArray(valueToProcess) ? valueToProcess[0] : valueToProcess;
11660
11645
  const targetValue = clampDate(singleValue, minParts, maxParts);
11661
11646
  const { month, day, year, hour, minute } = targetValue;
11662
11647
  const ampm = parseAmPm(hour);
11663
11648
  /**
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.
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.
11667
11653
  */
11668
11654
  if (hasValue) {
11669
11655
  if (Array.isArray(valueToProcess)) {
@@ -11688,28 +11674,51 @@ class Datetime {
11688
11674
  */
11689
11675
  this.activeParts = [];
11690
11676
  }
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
+ */
11691
11684
  const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
11692
11685
  const bodyIsVisible = el.classList.contains('datetime-ready');
11693
11686
  const { isGridStyle, showMonthAndYear } = this;
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);
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
+ }
11703
11696
  }
11704
- else {
11705
- this.setWorkingParts({
11706
- month,
11707
- day,
11708
- year,
11709
- hour,
11710
- minute,
11711
- ampm,
11712
- });
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
+ }
11713
11722
  }
11714
11723
  };
11715
11724
  this.animateToDate = async (targetValue) => {
@@ -12704,7 +12713,7 @@ class Datetime {
12704
12713
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
12705
12714
  const hasWheelVariant = hasDatePresentation && preferWheel;
12706
12715
  renderHiddenInput(true, el, name, formatValue(value), disabled);
12707
- return (hAsync(Host, { key: '20e64fb4cfe3fbd74b24038c89e00651d78b500c', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
12716
+ return (hAsync(Host, { key: 'c3dfea8f46fcbcef38eb9e8a69b1b46a4e4b82fd', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses$1(color, {
12708
12717
  [mode]: true,
12709
12718
  ['datetime-readonly']: readonly,
12710
12719
  ['datetime-disabled']: disabled,
@@ -12714,7 +12723,7 @@ class Datetime {
12714
12723
  [`datetime-size-${size}`]: true,
12715
12724
  [`datetime-prefer-wheel`]: hasWheelVariant,
12716
12725
  [`datetime-grid`]: isGridStyle,
12717
- })) }, hAsync("div", { key: '488fe7bf6b9052e208d65206a580d5d65b945a62', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
12726
+ })) }, hAsync("div", { key: '75c91243cf6a51f44b83d7cf7d8c0c96bfd3c83f', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
12718
12727
  }
12719
12728
  get el() { return getElement(this); }
12720
12729
  static get watchers() { return {
@@ -15688,14 +15697,14 @@ class InputPasswordToggle {
15688
15697
  const isPasswordVisible = type === 'text';
15689
15698
  return (hAsync(Host, { key: '1a28e078c83e74c72d8bb8189ece93ec2e3fa3d0', class: createColorClasses$1(color, {
15690
15699
  [mode]: true,
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) => {
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) => {
15692
15701
  /**
15693
15702
  * This prevents mobile browsers from
15694
15703
  * blurring the input when the password toggle
15695
15704
  * button is activated.
15696
15705
  */
15697
15706
  ev.preventDefault();
15698
- }, onClick: this.togglePasswordVisibility }, hAsync("ion-icon", { key: '9d98e6675d5e2adea5c0f56ab67e98b6f57521dd', slot: "icon-only", "aria-hidden": "true", icon: isPasswordVisible ? hidePasswordIcon : showPasswordIcon }))));
15707
+ }, onClick: this.togglePasswordVisibility }, hAsync("ion-icon", { key: '26477ee97b808c3d79944bf5e33d4e05f1ae0b3f', slot: "icon-only", "aria-hidden": "true", icon: isPasswordVisible ? hidePasswordIcon : showPasswordIcon }))));
15699
15708
  }
15700
15709
  get el() { return getElement(this); }
15701
15710
  static get watchers() { return {
@@ -19205,47 +19214,7 @@ const iosEnterAnimation$3 = (baseEl, opts) => {
19205
19214
  .addElement(baseEl)
19206
19215
  .easing('cubic-bezier(0.32,0.72,0,1)')
19207
19216
  .duration(500)
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
- });
19217
+ .addAnimation([wrapperAnimation]);
19249
19218
  if (contentAnimation) {
19250
19219
  baseAnimation.addAnimation(contentAnimation);
19251
19220
  }
@@ -19326,7 +19295,7 @@ const createLeaveAnimation$1 = () => {
19326
19295
  * iOS Modal Leave Animation
19327
19296
  */
19328
19297
  const iosLeaveAnimation$3 = (baseEl, opts, duration = 500) => {
19329
- const { presentingEl, currentBreakpoint, expandToScroll } = opts;
19298
+ const { presentingEl, currentBreakpoint } = opts;
19330
19299
  const root = getElementRoot(baseEl);
19331
19300
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation$1();
19332
19301
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -19335,29 +19304,7 @@ const iosLeaveAnimation$3 = (baseEl, opts, duration = 500) => {
19335
19304
  .addElement(baseEl)
19336
19305
  .easing('cubic-bezier(0.32,0.72,0,1)')
19337
19306
  .duration(duration)
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
- });
19307
+ .addAnimation(wrapperAnimation);
19361
19308
  if (presentingEl) {
19362
19309
  const isMobile = window.innerWidth < 768;
19363
19310
  const hasCardModal = presentingEl.tagName === 'ION-MODAL' && presentingEl.presentingElement !== undefined;
@@ -19453,47 +19400,7 @@ const mdEnterAnimation$2 = (baseEl, opts) => {
19453
19400
  .addElement(baseEl)
19454
19401
  .easing('cubic-bezier(0.36,0.66,0.04,1)')
19455
19402
  .duration(280)
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
- });
19403
+ .addAnimation([backdropAnimation, wrapperAnimation]);
19497
19404
  if (contentAnimation) {
19498
19405
  baseAnimation.addAnimation(contentAnimation);
19499
19406
  }
@@ -19512,7 +19419,7 @@ const createLeaveAnimation = () => {
19512
19419
  * Md Modal Leave Animation
19513
19420
  */
19514
19421
  const mdLeaveAnimation$2 = (baseEl, opts) => {
19515
- const { currentBreakpoint, expandToScroll } = opts;
19422
+ const { currentBreakpoint } = opts;
19516
19423
  const root = getElementRoot(baseEl);
19517
19424
  const { wrapperAnimation, backdropAnimation } = currentBreakpoint !== undefined ? createSheetLeaveAnimation(opts) : createLeaveAnimation();
19518
19425
  backdropAnimation.addElement(root.querySelector('ion-backdrop'));
@@ -19520,29 +19427,7 @@ const mdLeaveAnimation$2 = (baseEl, opts) => {
19520
19427
  const baseAnimation = createAnimation()
19521
19428
  .easing('cubic-bezier(0.47,0,0.745,0.715)')
19522
19429
  .duration(200)
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
- });
19430
+ .addAnimation([backdropAnimation, wrapperAnimation]);
19546
19431
  return baseAnimation;
19547
19432
  };
19548
19433
 
@@ -19574,6 +19459,9 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19574
19459
  let offset = 0;
19575
19460
  let canDismissBlocksGesture = false;
19576
19461
  let cachedScrollEl = null;
19462
+ let cachedFooterEl = null;
19463
+ let cachedFooterYPosition = null;
19464
+ let currentFooterState = null;
19577
19465
  const canDismissMaxStep = 0.95;
19578
19466
  const maxBreakpoint = breakpoints[breakpoints.length - 1];
19579
19467
  const minBreakpoint = breakpoints[0];
@@ -19603,29 +19491,66 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19603
19491
  baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
19604
19492
  };
19605
19493
  /**
19606
- * Toggles the visible modal footer when `expandToScroll` is disabled.
19607
- * @param footer The footer to show.
19494
+ * Toggles the footer to an absolute position while moving to prevent
19495
+ * it from shaking while the sheet is being dragged.
19496
+ * @param footer Whether the footer is in a moving or stationary position.
19608
19497
  */
19609
- const swapFooterVisibility = (footer) => {
19610
- const originalFooter = baseEl.querySelector('ion-footer');
19611
- if (!originalFooter) {
19612
- return;
19498
+ const swapFooterPosition = (newPosition) => {
19499
+ if (!cachedFooterEl) {
19500
+ cachedFooterEl = baseEl.querySelector('ion-footer');
19501
+ if (!cachedFooterEl) {
19502
+ return;
19503
+ }
19613
19504
  }
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
19505
  const page = baseEl.querySelector('.ion-page');
19620
- if (footer === 'original') {
19621
- page.style.removeProperty('padding-bottom');
19506
+ currentFooterState = newPosition;
19507
+ if (newPosition === 'stationary') {
19508
+ // Reset positioning styles to allow normal document flow
19509
+ cachedFooterEl.classList.remove('modal-footer-moving');
19510
+ cachedFooterEl.style.removeProperty('position');
19511
+ cachedFooterEl.style.removeProperty('width');
19512
+ cachedFooterEl.style.removeProperty('height');
19513
+ cachedFooterEl.style.removeProperty('top');
19514
+ cachedFooterEl.style.removeProperty('left');
19515
+ page === null || page === void 0 ? void 0 : page.style.removeProperty('padding-bottom');
19516
+ // Move to page
19517
+ page === null || page === void 0 ? void 0 : page.appendChild(cachedFooterEl);
19622
19518
  }
19623
19519
  else {
19624
- const pagePadding = footerToShow.clientHeight;
19625
- page.style.setProperty('padding-bottom', `${pagePadding}px`);
19520
+ // Get both the footer and document body positions
19521
+ const cachedFooterElRect = cachedFooterEl.getBoundingClientRect();
19522
+ const bodyRect = document.body.getBoundingClientRect();
19523
+ // Add padding to the parent element to prevent content from being hidden
19524
+ // when the footer is positioned absolutely. This has to be done before we
19525
+ // make the footer absolutely positioned or we may accidentally cause the
19526
+ // sheet to scroll.
19527
+ const footerHeight = cachedFooterEl.clientHeight;
19528
+ page === null || page === void 0 ? void 0 : page.style.setProperty('padding-bottom', `${footerHeight}px`);
19529
+ // Apply positioning styles to keep footer at bottom
19530
+ cachedFooterEl.classList.add('modal-footer-moving');
19531
+ // Calculate absolute position relative to body
19532
+ // We need to subtract the body's offsetTop to get true position within document.body
19533
+ const absoluteTop = cachedFooterElRect.top - bodyRect.top;
19534
+ const absoluteLeft = cachedFooterElRect.left - bodyRect.left;
19535
+ // Capture the footer's current dimensions and hard code them during the drag
19536
+ cachedFooterEl.style.setProperty('position', 'absolute');
19537
+ cachedFooterEl.style.setProperty('width', `${cachedFooterEl.clientWidth}px`);
19538
+ cachedFooterEl.style.setProperty('height', `${cachedFooterEl.clientHeight}px`);
19539
+ cachedFooterEl.style.setProperty('top', `${absoluteTop}px`);
19540
+ cachedFooterEl.style.setProperty('left', `${absoluteLeft}px`);
19541
+ // Also cache the footer Y position, which we use to determine if the
19542
+ // sheet has been moved below the footer. When that happens, we need to swap
19543
+ // the position back so it will collapse correctly.
19544
+ cachedFooterYPosition = absoluteTop;
19545
+ // If there's a toolbar, we need to combine the toolbar height with the footer position
19546
+ // because the toolbar moves with the drag handle, so when it starts overlapping the footer,
19547
+ // we need to account for that.
19548
+ const toolbar = baseEl.querySelector('ion-toolbar');
19549
+ if (toolbar) {
19550
+ cachedFooterYPosition -= toolbar.clientHeight;
19551
+ }
19552
+ document.body.appendChild(cachedFooterEl);
19626
19553
  }
19627
- footerToHide.style.setProperty('display', 'none');
19628
- footerToHide.setAttribute('aria-hidden', 'true');
19629
19554
  };
19630
19555
  /**
19631
19556
  * After the entering animation completes,
@@ -19719,12 +19644,11 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19719
19644
  }
19720
19645
  /**
19721
19646
  * If expandToScroll is disabled, we need to swap
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.
19647
+ * the footer position to moving so that it doesn't shake
19648
+ * while the sheet is being dragged.
19725
19649
  */
19726
19650
  if (!expandToScroll) {
19727
- swapFooterVisibility('original');
19651
+ swapFooterPosition('moving');
19728
19652
  }
19729
19653
  /**
19730
19654
  * If we are pulling down, then it is possible we are pulling on the content.
@@ -19743,6 +19667,21 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19743
19667
  animation.progressStart(true, 1 - currentBreakpoint);
19744
19668
  };
19745
19669
  const onMove = (detail) => {
19670
+ /**
19671
+ * If `expandToScroll` is disabled, we need to see if we're currently below
19672
+ * the footer element and the footer is in a stationary position. If so,
19673
+ * we need to make the stationary the original position so that the footer
19674
+ * collapses with the sheet.
19675
+ */
19676
+ if (!expandToScroll && cachedFooterYPosition !== null && currentFooterState !== null) {
19677
+ // Check if we need to swap the footer position
19678
+ if (detail.currentY >= cachedFooterYPosition && currentFooterState === 'moving') {
19679
+ swapFooterPosition('stationary');
19680
+ }
19681
+ else if (detail.currentY < cachedFooterYPosition && currentFooterState === 'stationary') {
19682
+ swapFooterPosition('moving');
19683
+ }
19684
+ }
19746
19685
  /**
19747
19686
  * If `expandToScroll` is disabled, and an upwards swipe gesture is done within
19748
19687
  * the scrollable content, we should not allow the swipe gesture to continue.
@@ -19876,14 +19815,6 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19876
19815
  * snapping animation completes.
19877
19816
  */
19878
19817
  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
- }
19887
19818
  if (shouldPreventDismiss) {
19888
19819
  handleCanDismiss(baseEl, animation);
19889
19820
  }
@@ -19900,10 +19831,26 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
19900
19831
  if (contentEl && (snapToBreakpoint === breakpoints[breakpoints.length - 1] || !expandToScroll)) {
19901
19832
  contentEl.scrollY = true;
19902
19833
  }
19834
+ /**
19835
+ * If expandToScroll is disabled and we're animating
19836
+ * to the close of the sheet, we need to swap
19837
+ * the footer position to stationary so that it
19838
+ * will collapse correctly. We cannot just always swap
19839
+ * here or it'll be jittery while animating movement.
19840
+ */
19841
+ if (!expandToScroll && snapToBreakpoint === 0) {
19842
+ swapFooterPosition('stationary');
19843
+ }
19903
19844
  return new Promise((resolve) => {
19904
19845
  animation
19905
19846
  .onFinish(() => {
19906
19847
  if (shouldRemainOpen) {
19848
+ /**
19849
+ * If expandToScroll is disabled, we need to swap
19850
+ * the footer position to stationary so that it
19851
+ * will act as it would by default
19852
+ */
19853
+ swapFooterPosition('stationary');
19907
19854
  /**
19908
19855
  * Once the snapping animation completes,
19909
19856
  * we need to reset the animation to go
@@ -23320,7 +23267,7 @@ class PickerColumnCmp {
23320
23267
  const colEl = this.optsEl;
23321
23268
  if (colEl) {
23322
23269
  // DOM READ
23323
- // We perfom a DOM read over a rendered item, this needs to happen after the first render or after the column has changed
23270
+ // We perfom a DOM read over a rendered item, this needs to happen after the first render or after the the column has changed
23324
23271
  this.optHeight = colEl.firstElementChild ? colEl.firstElementChild.clientHeight : 0;
23325
23272
  }
23326
23273
  this.refresh(forceRefresh, animated);
@@ -23328,9 +23275,9 @@ class PickerColumnCmp {
23328
23275
  render() {
23329
23276
  const col = this.col;
23330
23277
  const mode = getIonMode$1(this);
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: {
23278
+ 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: {
23332
23279
  'max-width': this.col.columnWidth,
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))));
23280
+ } }, 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))));
23334
23281
  }
23335
23282
  get el() { return getElement(this); }
23336
23283
  static get watchers() { return {
@@ -29042,8 +28989,8 @@ class Searchbar {
29042
28989
  const clearIcon = this.clearIcon || (mode === 'ios' ? closeCircle : closeSharp);
29043
28990
  const searchIcon = this.searchIcon || (mode === 'ios' ? searchOutline : searchSharp);
29044
28991
  const shouldShowCancelButton = this.shouldShowCancelButton();
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, {
28992
+ 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))));
28993
+ return (hAsync(Host, { key: 'd1a1972725e949fb102c91487aaa7b9d10c2d718', role: "search", "aria-disabled": this.disabled ? 'true' : null, class: createColorClasses$1(this.color, {
29047
28994
  [mode]: true,
29048
28995
  'searchbar-animated': animated,
29049
28996
  'searchbar-disabled': this.disabled,
@@ -29053,14 +29000,14 @@ class Searchbar {
29053
29000
  'searchbar-has-focus': this.focused,
29054
29001
  'searchbar-should-show-clear': this.shouldShowClearButton(),
29055
29002
  'searchbar-should-show-cancel': this.shouldShowCancelButton(),
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) => {
29003
+ }) }, 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) => {
29057
29004
  /**
29058
29005
  * This prevents mobile browsers from
29059
29006
  * blurring the input when the clear
29060
29007
  * button is activated.
29061
29008
  */
29062
29009
  ev.preventDefault();
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));
29010
+ }, 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));
29064
29011
  }
29065
29012
  get el() { return getElement(this); }
29066
29013
  static get watchers() { return {