@ionic/core 8.7.17-dev.11771359170.1fda0949 → 8.7.17-dev.11771870864.19b2cde1

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 (51) hide show
  1. package/components/ion-datetime.js +5 -5
  2. package/components/ion-segment-view.js +11 -5
  3. package/components/ion-select.js +3 -3
  4. package/components/ion-textarea.js +4 -4
  5. package/components/modal.js +206 -43
  6. package/dist/cjs/ion-datetime_3.cjs.entry.js +5 -5
  7. package/dist/cjs/ion-modal.cjs.entry.js +206 -43
  8. package/dist/cjs/ion-segment-view.cjs.entry.js +10 -5
  9. package/dist/cjs/ion-select_3.cjs.entry.js +3 -3
  10. package/dist/cjs/ion-textarea.cjs.entry.js +2 -2
  11. package/dist/cjs/ionic.cjs.js +1 -1
  12. package/dist/cjs/loader.cjs.js +1 -1
  13. package/dist/collection/components/datetime/datetime.js +5 -12
  14. package/dist/collection/components/modal/gestures/sheet.js +108 -11
  15. package/dist/collection/components/modal/gestures/swipe-to-close.js +54 -1
  16. package/dist/collection/components/modal/modal.js +98 -31
  17. package/dist/collection/components/segment-view/segment-view.ios.css +2 -1
  18. package/dist/collection/components/segment-view/segment-view.js +28 -3
  19. package/dist/collection/components/segment-view/segment-view.md.css +2 -1
  20. package/dist/collection/components/select/select.js +6 -3
  21. package/dist/collection/components/textarea/textarea.js +4 -4
  22. package/dist/docs.json +115 -51
  23. package/dist/esm/ion-datetime_3.entry.js +5 -5
  24. package/dist/esm/ion-modal.entry.js +206 -43
  25. package/dist/esm/ion-segment-view.entry.js +10 -5
  26. package/dist/esm/ion-select_3.entry.js +3 -3
  27. package/dist/esm/ion-textarea.entry.js +2 -2
  28. package/dist/esm/ionic.js +1 -1
  29. package/dist/esm/loader.js +1 -1
  30. package/dist/html.html-data.json +4 -0
  31. package/dist/ionic/ionic.esm.js +1 -1
  32. package/dist/ionic/p-0f418a37.entry.js +4 -0
  33. package/dist/ionic/p-1838bed5.entry.js +4 -0
  34. package/dist/ionic/p-29721c43.entry.js +4 -0
  35. package/dist/ionic/p-9a2d390d.entry.js +4 -0
  36. package/dist/ionic/{p-c19f63d0.entry.js → p-e1d1f3cc.entry.js} +1 -1
  37. package/dist/types/components/datetime/datetime.d.ts +0 -7
  38. package/dist/types/components/modal/gestures/sheet.d.ts +2 -2
  39. package/dist/types/components/modal/gestures/swipe-to-close.d.ts +2 -2
  40. package/dist/types/components/modal/modal-interface.d.ts +7 -0
  41. package/dist/types/components/modal/modal.d.ts +17 -1
  42. package/dist/types/components/segment-view/segment-view.d.ts +4 -0
  43. package/dist/types/components/select/select.d.ts +3 -0
  44. package/dist/types/components.d.ts +27 -2
  45. package/hydrate/index.js +233 -68
  46. package/hydrate/index.mjs +233 -68
  47. package/package.json +1 -1
  48. package/dist/ionic/p-020af078.entry.js +0 -4
  49. package/dist/ionic/p-88367362.entry.js +0 -4
  50. package/dist/ionic/p-91840a80.entry.js +0 -4
  51. package/dist/ionic/p-9dcc3ae4.entry.js +0 -4
@@ -1579,11 +1579,11 @@ const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLEle
1579
1579
  const nextMonthDisabled = disabled || isNextMonthDisabled(this.workingParts, this.maxParts);
1580
1580
  // don't use the inheritAttributes util because it removes dir from the host, and we still need that
1581
1581
  const hostDir = this.el.getAttribute('dir') || undefined;
1582
- return (h("div", { class: "calendar-header", part: "calendar-header" }, h("div", { class: "calendar-action-buttons" }, h("div", { class: "calendar-month-year" }, h("button", { class: {
1582
+ return (h("div", { class: "calendar-header" }, h("div", { class: "calendar-action-buttons" }, h("div", { class: "calendar-month-year" }, h("button", { class: {
1583
1583
  'calendar-month-year-toggle': true,
1584
1584
  'ion-activatable': true,
1585
1585
  'ion-focusable': true,
1586
- }, part: "month-year-button", disabled: disabled, "aria-label": this.showMonthAndYear ? 'Hide year picker' : 'Show year picker', onClick: () => this.toggleMonthAndYearView() }, h("span", { id: "toggle-wrapper" }, getMonthAndYear(this.locale, this.workingParts), h("ion-icon", { "aria-hidden": "true", icon: this.showMonthAndYear ? expandedIcon : collapsedIcon, lazy: false, flipRtl: true })), mode === 'md' && h("ion-ripple-effect", null))), h("div", { class: "calendar-next-prev" }, h("ion-buttons", null, h("ion-button", { "aria-label": "Previous month", disabled: prevMonthDisabled, onClick: () => this.prevMonth(), part: "prev-next-buttons prev-button" }, h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: chevronBack, lazy: false, flipRtl: true })), h("ion-button", { "aria-label": "Next month", disabled: nextMonthDisabled, onClick: () => this.nextMonth(), part: "prev-next-buttons next-button" }, h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: chevronForward, lazy: false, flipRtl: true }))))), h("div", { class: "calendar-days-of-week", "aria-hidden": "true", part: "days-of-week" }, getDaysOfWeek(this.locale, mode, this.firstDayOfWeek % 7).map((d) => {
1586
+ }, part: "month-year-button", disabled: disabled, "aria-label": this.showMonthAndYear ? 'Hide year picker' : 'Show year picker', onClick: () => this.toggleMonthAndYearView() }, h("span", { id: "toggle-wrapper" }, getMonthAndYear(this.locale, this.workingParts), h("ion-icon", { "aria-hidden": "true", icon: this.showMonthAndYear ? expandedIcon : collapsedIcon, lazy: false, flipRtl: true })), mode === 'md' && h("ion-ripple-effect", null))), h("div", { class: "calendar-next-prev" }, h("ion-buttons", null, h("ion-button", { "aria-label": "Previous month", disabled: prevMonthDisabled, onClick: () => this.prevMonth() }, h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: chevronBack, lazy: false, flipRtl: true })), h("ion-button", { "aria-label": "Next month", disabled: nextMonthDisabled, onClick: () => this.nextMonth() }, h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: chevronForward, lazy: false, flipRtl: true }))))), h("div", { class: "calendar-days-of-week", "aria-hidden": "true" }, getDaysOfWeek(this.locale, mode, this.firstDayOfWeek % 7).map((d) => {
1587
1587
  return h("div", { class: "day-of-week" }, d);
1588
1588
  }))));
1589
1589
  }
@@ -1815,7 +1815,7 @@ const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLEle
1815
1815
  if (!hasSlottedTitle && !this.showDefaultTitle) {
1816
1816
  return;
1817
1817
  }
1818
- return (h("div", { class: "datetime-header", part: "datetime-header" }, h("div", { class: "datetime-title" }, h("slot", { name: "title" }, "Select Date")), showExpandedHeader && h("div", { class: "datetime-selected-date" }, this.getHeaderSelectedDateText())));
1818
+ return (h("div", { class: "datetime-header" }, h("div", { class: "datetime-title" }, h("slot", { name: "title" }, "Select Date")), showExpandedHeader && h("div", { class: "datetime-selected-date" }, this.getHeaderSelectedDateText())));
1819
1819
  }
1820
1820
  /**
1821
1821
  * Render time picker inside of datetime.
@@ -1895,7 +1895,7 @@ const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLEle
1895
1895
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
1896
1896
  const hasWheelVariant = hasDatePresentation && preferWheel;
1897
1897
  renderHiddenInput(true, el, name, formatValue(value), disabled);
1898
- return (h(Host, { key: '3d0787ecb3ad104c4a60d68a6e57140f018a70f2', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1898
+ return (h(Host, { key: '19e20c9b6b5f9467e91a2567b6dc7d9d38b56cc3', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1899
1899
  [mode]: true,
1900
1900
  ['datetime-readonly']: readonly,
1901
1901
  ['datetime-disabled']: disabled,
@@ -1905,7 +1905,7 @@ const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLEle
1905
1905
  [`datetime-size-${size}`]: true,
1906
1906
  [`datetime-prefer-wheel`]: hasWheelVariant,
1907
1907
  [`datetime-grid`]: isGridStyle,
1908
- })) }, h("div", { key: '6b245a0033d5ddd1918bc839f142141bf5ec54c5', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1908
+ })) }, h("div", { key: 'e31b5ef76cd6262dafd39f2d21980887880ec32e', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1909
1909
  }
1910
1910
  get el() { return this; }
1911
1911
  static get watchers() { return {
@@ -4,9 +4,9 @@
4
4
  import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
5
5
  import { i as isRTL } from './dir.js';
6
6
 
7
- const segmentViewIosCss = ":host{display:-ms-flexbox;display:flex;height:100%;overflow-x:scroll;-webkit-scroll-snap-type:x mandatory;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;scrollbar-width:none;-ms-overflow-style:none}:host::-webkit-scrollbar{display:none}:host(.segment-view-disabled){-ms-touch-action:none;touch-action:none;overflow-x:hidden}:host(.segment-view-scroll-disabled){pointer-events:none}:host(.segment-view-disabled){opacity:0.3}";
7
+ const segmentViewIosCss = ":host{display:-ms-flexbox;display:flex;height:100%;overflow-x:scroll;-webkit-scroll-snap-type:x mandatory;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;scrollbar-width:none;-ms-overflow-style:none}:host::-webkit-scrollbar{display:none}:host(.segment-view-disabled),:host(.segment-view-swipe-disabled){-ms-touch-action:none;touch-action:none;overflow-x:hidden}:host(.segment-view-scroll-disabled){pointer-events:none}:host(.segment-view-disabled){opacity:0.3}";
8
8
 
9
- const segmentViewMdCss = ":host{display:-ms-flexbox;display:flex;height:100%;overflow-x:scroll;-webkit-scroll-snap-type:x mandatory;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;scrollbar-width:none;-ms-overflow-style:none}:host::-webkit-scrollbar{display:none}:host(.segment-view-disabled){-ms-touch-action:none;touch-action:none;overflow-x:hidden}:host(.segment-view-scroll-disabled){pointer-events:none}:host(.segment-view-disabled){opacity:0.3}";
9
+ const segmentViewMdCss = ":host{display:-ms-flexbox;display:flex;height:100%;overflow-x:scroll;-webkit-scroll-snap-type:x mandatory;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;scrollbar-width:none;-ms-overflow-style:none}:host::-webkit-scrollbar{display:none}:host(.segment-view-disabled),:host(.segment-view-swipe-disabled){-ms-touch-action:none;touch-action:none;overflow-x:hidden}:host(.segment-view-scroll-disabled){pointer-events:none}:host(.segment-view-disabled){opacity:0.3}";
10
10
 
11
11
  const SegmentView = /*@__PURE__*/ proxyCustomElement(class SegmentView extends HTMLElement {
12
12
  constructor(registerHost) {
@@ -22,6 +22,10 @@ const SegmentView = /*@__PURE__*/ proxyCustomElement(class SegmentView extends H
22
22
  * If `true`, the segment view cannot be interacted with.
23
23
  */
24
24
  this.disabled = false;
25
+ /**
26
+ * If `true`, users will be able to swipe the segment view to navigate between segment contents.
27
+ */
28
+ this.swipeGesture = true;
25
29
  }
26
30
  handleScroll(ev) {
27
31
  var _a;
@@ -109,11 +113,12 @@ const SegmentView = /*@__PURE__*/ proxyCustomElement(class SegmentView extends H
109
113
  return Array.from(this.el.querySelectorAll('ion-segment-content'));
110
114
  }
111
115
  render() {
112
- const { disabled, isManualScroll } = this;
113
- return (h(Host, { key: 'e180b67bb3143a5f4611fb358c037be6fc782a8f', class: {
116
+ const { disabled, isManualScroll, swipeGesture } = this;
117
+ return (h(Host, { key: '565cccce7f0cfc4c71508777cc60292d6f24334f', class: {
114
118
  'segment-view-disabled': disabled,
115
119
  'segment-view-scroll-disabled': isManualScroll === false,
116
- } }, h("slot", { key: '41c11d6a7406a10f5c64a2e73abfc072afd8fc73' })));
120
+ 'segment-view-swipe-disabled': swipeGesture === false,
121
+ } }, h("slot", { key: '4118c240364467302b8f593e33c37837ea5d06f0' })));
117
122
  }
118
123
  get el() { return this; }
119
124
  static get style() { return {
@@ -122,6 +127,7 @@ const SegmentView = /*@__PURE__*/ proxyCustomElement(class SegmentView extends H
122
127
  }; }
123
128
  }, [289, "ion-segment-view", {
124
129
  "disabled": [4],
130
+ "swipeGesture": [4, "swipe-gesture"],
125
131
  "isManualScroll": [32],
126
132
  "setContent": [64]
127
133
  }, [[1, "scroll", "handleScroll"], [1, "touchstart", "handleScrollStart"], [1, "touchend", "handleTouchEnd"]]]);
@@ -779,7 +779,7 @@ const Select = /*@__PURE__*/ proxyCustomElement(class Select extends HTMLElement
779
779
  if (!hasHintText) {
780
780
  return;
781
781
  }
782
- return h("div", { class: "select-bottom" }, this.renderHintText());
782
+ return (h("div", { class: "select-bottom", part: "bottom" }, this.renderHintText()));
783
783
  }
784
784
  render() {
785
785
  const { disabled, el, isExpanded, expandedIcon, labelPlacement, justify, placeholder, fill, shape, name, value, hasFocus, } = this;
@@ -810,7 +810,7 @@ const Select = /*@__PURE__*/ proxyCustomElement(class Select extends HTMLElement
810
810
  * TODO(FW-5592): Remove hasStartEndSlots condition
811
811
  */
812
812
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || isExpanded || hasStartEndSlots));
813
- return (h(Host, { key: 'b7fa907f8fbc54fd63e2d07a9bb5156d94fd5057', onClick: this.onClick, class: createColorClasses(this.color, {
813
+ return (h(Host, { key: 'ada627c442ebcdd4a4ee96e5f5f3ec0e2181d689', onClick: this.onClick, class: createColorClasses(this.color, {
814
814
  [mode]: true,
815
815
  'in-item': inItem,
816
816
  'in-item-color': hostContext('ion-item.ion-color', el),
@@ -828,7 +828,7 @@ const Select = /*@__PURE__*/ proxyCustomElement(class Select extends HTMLElement
828
828
  [`select-justify-${justify}`]: justifyEnabled,
829
829
  [`select-shape-${shape}`]: shape !== undefined,
830
830
  [`select-label-placement-${labelPlacement}`]: true,
831
- }) }, h("label", { key: '11137e6a8b0374e93923ddb5a4629972ded5f43c', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '99e3c09b5e6c2e7be493ed5834f991fffe45cfff', class: "select-wrapper-inner" }, h("slot", { key: '740f0e5a913cb0209d5acae31c33a6ed8f672dfc', name: "start" }), h("div", { key: 'b20e33c8b60915a5194948fcf8e22d7789f0b050', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), h("slot", { key: '0199f338185d5fa2cdd977bb20516746bd9ddad5', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && h("div", { key: '3b54de893cc8fc66df8588cee22e30d6f10850b3', class: "select-highlight" })), this.renderBottomContent()));
831
+ }) }, h("label", { key: 'd1c4663e740cfdcd28f90a5e0297d05cf42cc4df', class: "select-wrapper", id: "select-label", onClick: this.onLabelClick, part: "wrapper" }, this.renderLabelContainer(), h("div", { key: 'cd671e0b543378e7b822ce649a7b4006094b111f', class: "select-wrapper-inner", part: "inner" }, h("slot", { key: '48e7df0c517a382195736273019b855e422a82ed', name: "start" }), h("div", { key: '822747ffb9101cb1d3ff947da55bc2e8e1f2c8e2', class: "native-wrapper", ref: (el) => (this.nativeWrapperEl = el), part: "container" }, this.renderSelectText(), this.renderListbox()), h("slot", { key: '349200d9f9ebf25e0b8708ac8683a76e7c6ed33c', name: "end" }), !hasFloatingOrStackedLabel && this.renderSelectIcon()), hasFloatingOrStackedLabel && this.renderSelectIcon(), shouldRenderHighlight && h("div", { key: '7eefb70d431cb9c01cc408d35349f7a3d0f2af35', class: "select-highlight" })), this.renderBottomContent()));
832
832
  }
833
833
  get el() { return this; }
834
834
  static get watchers() { return {
@@ -477,7 +477,7 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
477
477
  * TODO(FW-5592): Remove hasStartEndSlots condition
478
478
  */
479
479
  const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
480
- return (h(Host, { key: 'a70a62d7aae3831a50acd74f60b930925ada1326', class: createColorClasses(this.color, {
480
+ return (h(Host, { key: '543076e7ed730451b490a9008cabe8f4a5d1f347', class: createColorClasses(this.color, {
481
481
  [mode]: true,
482
482
  'has-value': hasValue,
483
483
  'has-focus': hasFocus,
@@ -486,7 +486,7 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
486
486
  [`textarea-shape-${shape}`]: shape !== undefined,
487
487
  [`textarea-label-placement-${labelPlacement}`]: true,
488
488
  'textarea-disabled': disabled,
489
- }) }, h("label", { key: '8a2dd59a60f7469df84018eb0ede3a9ec3862703', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '1bfc368236e3da7a225a45118c27fbfc1fe5fa46', class: "textarea-wrapper-inner" }, h("div", { key: '215cbb2635ff52e31a8973376989b85e7245d40f', class: "start-slot-wrapper" }, h("slot", { key: '9f6b461cdee9d629deb695d2bea054ece2f32305', name: "start" })), h("div", { key: 'c1af35a2d5bc452bebe0b22a26d15ff52b4e9fc8', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, h("textarea", Object.assign({ key: '69a69b3cf0932baafbe37e6e846f1a571608d3f2', class: "native-textarea", ref: (el) => (this.nativeInput = el), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, minLength: this.minlength, maxLength: this.maxlength, name: this.name, placeholder: this.placeholder || '', readOnly: this.readonly, required: this.required, spellcheck: this.spellcheck, cols: this.cols, rows: this.rows, wrap: this.wrap, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeyDown, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined }, this.inheritedAttributes), value)), h("div", { key: 'c053ea8b865d0e29763aed2e4939cc9c9e374c15', class: "end-slot-wrapper" }, h("slot", { key: '930aa641833b0df54b9ea10368fc2f46d5f491f6', name: "end" }))), shouldRenderHighlight && h("div", { key: '8d12597d15f5f429d80e8272ea99e64ed924e482', class: "textarea-highlight" })), this.renderBottomContent()));
489
+ }) }, h("label", { key: '3aebaa02edde10e19b2bbe2fbcc10f70b4faccff', class: "textarea-wrapper", htmlFor: inputId, onClick: this.onLabelClick }, this.renderLabelContainer(), h("div", { key: '73c1c7fee0ffffe65296060dd4110003d3975c44', class: "textarea-wrapper-inner" }, h("div", { key: '5a245b822afae0b9858ef0d176a2fe06983954e2', class: "start-slot-wrapper" }, h("slot", { key: '684305a1b558f93af6eb99825981ced1c09c7a8c', name: "start" })), h("div", { key: 'f2f723b674cff48cf76656450ff6c1362514ea90', class: "native-wrapper", ref: (el) => (this.textareaWrapper = el) }, h("textarea", Object.assign({ key: 'ae826e876a4b476502498b9c64ea020010c55db3', class: "native-textarea", ref: (el) => (this.nativeInput = el), id: inputId, disabled: disabled, autoCapitalize: this.autocapitalize, autoFocus: this.autofocus, enterKeyHint: this.enterkeyhint, inputMode: this.inputmode, minLength: this.minlength, maxLength: this.maxlength, name: this.name, placeholder: this.placeholder || '', readOnly: this.readonly, required: this.required, spellcheck: this.spellcheck, cols: this.cols, rows: this.rows, wrap: this.wrap, onInput: this.onInput, onChange: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeyDown, "aria-describedby": this.getHintTextID(), "aria-invalid": this.isInvalid ? 'true' : undefined }, this.inheritedAttributes), value)), h("div", { key: '018cbf061fb53aa1d1caf6173fd08348cbe3413a', class: "end-slot-wrapper" }, h("slot", { key: 'c383636f2d8a548e48848d0967f71ee1969b1411', name: "end" }))), shouldRenderHighlight && h("div", { key: '6522d2058f9842abad9e7223b542cb7e1af40477', class: "textarea-highlight" })), this.renderBottomContent()));
490
490
  }
491
491
  get el() { return this; }
492
492
  static get watchers() { return {
@@ -504,7 +504,7 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
504
504
  "autofocus": [4],
505
505
  "clearOnEdit": [4, "clear-on-edit"],
506
506
  "debounce": [2],
507
- "disabled": [4],
507
+ "disabled": [516],
508
508
  "fill": [1],
509
509
  "inputmode": [1],
510
510
  "enterkeyhint": [1],
@@ -512,7 +512,7 @@ const Textarea = /*@__PURE__*/ proxyCustomElement(class Textarea extends HTMLEle
512
512
  "minlength": [2],
513
513
  "name": [1],
514
514
  "placeholder": [1],
515
- "readonly": [4],
515
+ "readonly": [516],
516
516
  "required": [4],
517
517
  "spellcheck": [4],
518
518
  "cols": [514],
@@ -246,7 +246,7 @@ const calculateSpringStep = (t) => {
246
246
  const SwipeToCloseDefaults = {
247
247
  MIN_PRESENTING_SCALE: 0.915,
248
248
  };
249
- const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) => {
249
+ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss, onDragStart, onDragMove, onDragEnd) => {
250
250
  /**
251
251
  * The step value at which a card modal
252
252
  * is eligible for dismissing via gesture.
@@ -356,6 +356,7 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) =>
356
356
  disableContentScrollY(contentEl);
357
357
  }
358
358
  animation.progressStart(true, isOpen ? 1 : 0);
359
+ onDragStart();
359
360
  };
360
361
  const onMove = (detail) => {
361
362
  const { deltaY } = detail;
@@ -423,6 +424,13 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) =>
423
424
  setCardStatusBarDark();
424
425
  }
425
426
  lastStep = clampedStep;
427
+ const eventDetail = {
428
+ currentY: detail.currentY,
429
+ deltaY: detail.deltaY,
430
+ velocityY: detail.velocityY,
431
+ progress: calculateProgress(el, detail.deltaY),
432
+ };
433
+ onDragMove(eventDetail);
426
434
  };
427
435
  const onEnd = (detail) => {
428
436
  const velocity = detail.velocityY;
@@ -481,6 +489,13 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) =>
481
489
  else if (shouldComplete) {
482
490
  onDismiss();
483
491
  }
492
+ const eventDetail = {
493
+ currentY: detail.currentY,
494
+ deltaY: detail.deltaY,
495
+ velocityY: detail.velocityY,
496
+ progress: calculateProgress(el, detail.deltaY),
497
+ };
498
+ onDragEnd(eventDetail);
484
499
  };
485
500
  const gesture = createGesture({
486
501
  el,
@@ -498,6 +513,44 @@ const createSwipeToCloseGesture = (el, animation, statusBarStyle, onDismiss) =>
498
513
  const computeDuration = (remaining, velocity) => {
499
514
  return clamp(400, remaining / Math.abs(velocity * 1.1), 500);
500
515
  };
516
+ /**
517
+ * Calculates the progress of the swipe gesture.
518
+ *
519
+ * The progress is a value between 0 and 1 that represents how far
520
+ * the swipe has progressed towards closing the modal.
521
+ *
522
+ * A value closer to 1 means the modal is closer to being opened,
523
+ * while a value closer to 0 means the modal is closer to being closed.
524
+ *
525
+ * @param el The modal
526
+ * @param deltaY The change in Y position (positive when dragging down, negative when dragging up)
527
+ * @returns The progress of the swipe gesture
528
+ */
529
+ const calculateProgress = (el, deltaY) => {
530
+ const windowHeight = window.innerHeight;
531
+ // Position when fully open
532
+ const modalTop = el.getBoundingClientRect().top;
533
+ /**
534
+ * The distance between the top of the modal and the bottom of the screen
535
+ * is the total distance the modal needs to travel to be fully closed.
536
+ */
537
+ const totalDistance = windowHeight - modalTop;
538
+ /**
539
+ * The pull percentage is how far the user has swiped compared to the total
540
+ * distance needed to close the modal.
541
+ */
542
+ const pullPercentage = deltaY / totalDistance;
543
+ /**
544
+ * The progress is the inverse of the pull percentage because
545
+ * when the user starts swiping up, the progress should be close to 1,
546
+ * and when the user has swiped all the way down, the progress should be
547
+ * close to 0.
548
+ */
549
+ const progress = 1 - pullPercentage;
550
+ // Round to the nearest thousandth to avoid returning very small decimal
551
+ const roundedProgress = Math.round(progress * 1000) / 1000;
552
+ return Math.max(0, Math.min(1, roundedProgress));
553
+ };
501
554
 
502
555
  const createSheetEnterAnimation = (opts) => {
503
556
  const { currentBreakpoint, backdropBreakpoint, expandToScroll } = opts;
@@ -946,7 +999,7 @@ const mdLeaveAnimation = (baseEl, opts) => {
946
999
  return baseAnimation;
947
1000
  };
948
1001
 
949
- const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
1002
+ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], expandToScroll, getCurrentBreakpoint, onDismiss, onBreakpointChange, onDragStart, onDragMove, onDragEnd) => {
950
1003
  // Defaults for the sheet swipe animation
951
1004
  const defaultBackdrop = [
952
1005
  { offset: 0, opacity: 'var(--backdrop-opacity)' },
@@ -1209,6 +1262,7 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1209
1262
  baseEl.focus();
1210
1263
  });
1211
1264
  animation.progressStart(true, 1 - currentBreakpoint);
1265
+ onDragStart();
1212
1266
  };
1213
1267
  const onMove = (detail) => {
1214
1268
  /**
@@ -1277,6 +1331,15 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1277
1331
  : step;
1278
1332
  offset = clamp(0.0001, processedStep, maxStep);
1279
1333
  animation.progressStep(offset);
1334
+ const closest = calculateClosestBreakpoint(detail.velocityY, detail.deltaY);
1335
+ const eventDetail = {
1336
+ currentY: detail.currentY,
1337
+ deltaY: detail.deltaY,
1338
+ velocityY: detail.velocityY,
1339
+ progress: calculateProgress(detail.currentY),
1340
+ currentBreakpoint: closest,
1341
+ };
1342
+ onDragMove(eventDetail);
1280
1343
  };
1281
1344
  const onEnd = (detail) => {
1282
1345
  /**
@@ -1295,16 +1358,7 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1295
1358
  swapFooterPosition('stationary');
1296
1359
  return;
1297
1360
  }
1298
- /**
1299
- * When the gesture releases, we need to determine
1300
- * the closest breakpoint to snap to.
1301
- */
1302
- const velocity = detail.velocityY;
1303
- const threshold = (detail.deltaY + velocity * 350) / height;
1304
- const diff = currentBreakpoint - threshold;
1305
- const closest = breakpoints.reduce((a, b) => {
1306
- return Math.abs(b - diff) < Math.abs(a - diff) ? b : a;
1307
- });
1361
+ const closest = calculateClosestBreakpoint(detail.velocityY, detail.deltaY);
1308
1362
  moveSheetToBreakpoint({
1309
1363
  breakpoint: closest,
1310
1364
  breakpointOffset: offset,
@@ -1315,6 +1369,14 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1315
1369
  */
1316
1370
  animated: true,
1317
1371
  });
1372
+ const eventDetail = {
1373
+ currentY: detail.currentY,
1374
+ deltaY: detail.deltaY,
1375
+ velocityY: detail.velocityY,
1376
+ progress: calculateProgress(detail.currentY),
1377
+ currentBreakpoint: closest,
1378
+ };
1379
+ onDragEnd(eventDetail);
1318
1380
  };
1319
1381
  const moveSheetToBreakpoint = (options) => {
1320
1382
  const { breakpoint, canDismiss, breakpointOffset, animated } = options;
@@ -1454,6 +1516,94 @@ const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, ba
1454
1516
  .progressEnd(1, 0, animated ? 500 : 0);
1455
1517
  });
1456
1518
  };
1519
+ /**
1520
+ * Calculates the closest breakpoint based on the current velocity and deltaY.
1521
+ * This determines where the sheet should snap to when the user releases the
1522
+ * gesture.
1523
+ *
1524
+ * @param velocityY The current velocity of the gesture in the Y direction.
1525
+ * @param deltaY The change in Y position since the gesture started.
1526
+ * @returns The closest breakpoint value.
1527
+ */
1528
+ const calculateClosestBreakpoint = (velocityY, deltaY) => {
1529
+ const threshold = (deltaY + velocityY * 350) / height;
1530
+ const diff = currentBreakpoint - threshold;
1531
+ const closest = breakpoints.reduce((a, b) => {
1532
+ return Math.abs(b - diff) < Math.abs(a - diff) ? b : a;
1533
+ });
1534
+ return closest;
1535
+ };
1536
+ /**
1537
+ * Calculates the progress of the swipe gesture.
1538
+ *
1539
+ * The progress is a value between 0 and 1 that represents how far
1540
+ * the swipe has progressed towards closing the modal.
1541
+ *
1542
+ * A value closer to 1 means the modal is closer to being opened,
1543
+ * while a value closer to 0 means the modal is closer to being closed.
1544
+ *
1545
+ * @param currentY The current Y position of the gesture
1546
+ * @returns The progress of the sheet gesture
1547
+ */
1548
+ const calculateProgress = (currentY) => {
1549
+ const minBreakpoint = breakpoints[0];
1550
+ const maxBreakpoint = breakpoints[breakpoints.length - 1];
1551
+ // Convert breakpoints to pixel Y coordinates
1552
+ /**
1553
+ * The lowest point the sheet can be dragged to aka the point at which
1554
+ * the sheet is fully closed.
1555
+ */
1556
+ const maxY = convertBreakpointToY(minBreakpoint);
1557
+ /**
1558
+ * The highest point the sheet can be dragged to aka the point at which
1559
+ * the sheet is fully open.
1560
+ */
1561
+ const minY = convertBreakpointToY(maxBreakpoint);
1562
+ // The total distance between the fully open and fully closed positions.
1563
+ const totalDistance = maxY - minY;
1564
+ // The distance from the current position to the fully closed position.
1565
+ const distanceFromBottom = maxY - currentY;
1566
+ /**
1567
+ * The progress represents how far the sheet is from the bottom relative
1568
+ * to the total distance. When the user starts swiping up, the progress
1569
+ * should be close to 1, and when the user has swiped all the way down,
1570
+ * the progress should be close to 0.
1571
+ */
1572
+ const progress = distanceFromBottom / totalDistance;
1573
+ // Round to the nearest thousandth to avoid returning very small decimal
1574
+ const roundedProgress = Math.round(progress * 1000) / 1000;
1575
+ return Math.max(0, Math.min(1, roundedProgress));
1576
+ };
1577
+ /**
1578
+ * Converts a breakpoint value (0 to 1) into a pixel Y coordinate
1579
+ * on the screen.
1580
+ *
1581
+ * @param breakpoint The breakpoint value (e.g., 0.5 for half-open)
1582
+ * @returns The pixel Y coordinate on the screen
1583
+ */
1584
+ const convertBreakpointToY = (breakpoint) => {
1585
+ const rect = baseEl.getBoundingClientRect();
1586
+ const modalHeight = rect.height;
1587
+ // The bottom of the screen.
1588
+ const viewportBottom = window.innerHeight;
1589
+ /**
1590
+ * The active height is how much of the modal is actually showing
1591
+ * on the screen for this specific breakpoint.
1592
+ */
1593
+ const activeHeight = modalHeight * breakpoint;
1594
+ /**
1595
+ * To find the Y coordinate, start at the bottom of the screen
1596
+ * and move up by the active height of the modal.
1597
+ *
1598
+ * A breakpoint of 1.0 means the active height is the full modal height
1599
+ * (fully open). A breakpoint of 0.0 means the active height is 0
1600
+ * (fully closed).
1601
+ *
1602
+ * Since screen Y coordinates get smaller as you go up, we subtract the
1603
+ * active height from the viewport bottom.
1604
+ */
1605
+ return viewportBottom - activeHeight;
1606
+ };
1457
1607
  const gesture = createGesture({
1458
1608
  el: wrapperEl,
1459
1609
  gestureName: 'modalSheet',
@@ -1492,6 +1642,9 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
1492
1642
  this.willDismissShorthand = createEvent(this, "willDismiss", 7);
1493
1643
  this.didDismissShorthand = createEvent(this, "didDismiss", 7);
1494
1644
  this.ionMount = createEvent(this, "ionMount", 7);
1645
+ this.ionDragStart = createEvent(this, "ionDragStart", 7);
1646
+ this.ionDragMove = createEvent(this, "ionDragMove", 7);
1647
+ this.ionDragEnd = createEvent(this, "ionDragEnd", 7);
1495
1648
  this.lockController = createLockController();
1496
1649
  this.triggerController = createTriggerController();
1497
1650
  this.coreDelegate = CoreDelegate();
@@ -1959,32 +2112,7 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
1959
2112
  return;
1960
2113
  }
1961
2114
  const statusBarStyle = (_a = this.statusBarStyle) !== null && _a !== void 0 ? _a : Style.Default;
1962
- this.gesture = createSwipeToCloseGesture(el, ani, statusBarStyle, () => {
1963
- /**
1964
- * While the gesture animation is finishing
1965
- * it is possible for a user to tap the backdrop.
1966
- * This would result in the dismiss animation
1967
- * being played again. Typically this is avoided
1968
- * by setting `presented = false` on the overlay
1969
- * component; however, we cannot do that here as
1970
- * that would prevent the element from being
1971
- * removed from the DOM.
1972
- */
1973
- this.gestureAnimationDismissing = true;
1974
- /**
1975
- * Reset the status bar style as the dismiss animation
1976
- * starts otherwise the status bar will be the wrong
1977
- * color for the duration of the dismiss animation.
1978
- * The dismiss method does this as well, but
1979
- * in this case it's only called once the animation
1980
- * has finished.
1981
- */
1982
- setCardStatusBarDefault(this.statusBarStyle);
1983
- this.animation.onFinish(async () => {
1984
- await this.dismiss(undefined, GESTURE);
1985
- this.gestureAnimationDismissing = false;
1986
- });
1987
- });
2115
+ this.gesture = createSwipeToCloseGesture(el, ani, statusBarStyle, () => this.cardOnDismiss(), () => this.onDragStart(), (detail) => this.onDragMove(detail), (detail) => this.onDragEnd(detail));
1988
2116
  this.gesture.enable(true);
1989
2117
  }
1990
2118
  initSheetGesture() {
@@ -2005,7 +2133,7 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2005
2133
  this.currentBreakpoint = breakpoint;
2006
2134
  this.ionBreakpointDidChange.emit({ breakpoint });
2007
2135
  }
2008
- });
2136
+ }, () => this.onDragStart(), (detail) => this.onDragMove(detail), (detail) => this.onDragEnd(detail));
2009
2137
  this.gesture = gesture;
2010
2138
  this.moveSheetToBreakpoint = moveSheetToBreakpoint;
2011
2139
  this.gesture.enable(true);
@@ -2102,6 +2230,32 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2102
2230
  this.gestureAnimationDismissing = false;
2103
2231
  });
2104
2232
  }
2233
+ cardOnDismiss() {
2234
+ /**
2235
+ * While the gesture animation is finishing
2236
+ * it is possible for a user to tap the backdrop.
2237
+ * This would result in the dismiss animation
2238
+ * being played again. Typically this is avoided
2239
+ * by setting `presented = false` on the overlay
2240
+ * component; however, we cannot do that here as
2241
+ * that would prevent the element from being
2242
+ * removed from the DOM.
2243
+ */
2244
+ this.gestureAnimationDismissing = true;
2245
+ /**
2246
+ * Reset the status bar style as the dismiss animation
2247
+ * starts otherwise the status bar will be the wrong
2248
+ * color for the duration of the dismiss animation.
2249
+ * The dismiss method does this as well, but
2250
+ * in this case it's only called once the animation
2251
+ * has finished.
2252
+ */
2253
+ setCardStatusBarDefault(this.statusBarStyle);
2254
+ this.animation.onFinish(async () => {
2255
+ await this.dismiss(undefined, GESTURE);
2256
+ this.gestureAnimationDismissing = false;
2257
+ });
2258
+ }
2105
2259
  /**
2106
2260
  * Dismiss the modal overlay after it has been presented.
2107
2261
  * This is a no-op if the overlay has not been presented yet. If you want
@@ -2417,6 +2571,15 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2417
2571
  (_a = this.parentRemovalObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
2418
2572
  this.parentRemovalObserver = undefined;
2419
2573
  }
2574
+ onDragStart() {
2575
+ this.ionDragStart.emit();
2576
+ }
2577
+ onDragMove(detail) {
2578
+ this.ionDragMove.emit(detail);
2579
+ }
2580
+ onDragEnd(detail) {
2581
+ this.ionDragEnd.emit(detail);
2582
+ }
2420
2583
  render() {
2421
2584
  const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap, expandToScroll, } = this;
2422
2585
  const showHandle = handle !== false && isSheetModal;
@@ -2424,20 +2587,20 @@ const Modal = /*@__PURE__*/ proxyCustomElement(class Modal extends HTMLElement {
2424
2587
  const isCardModal = presentingElement !== undefined && mode === 'ios';
2425
2588
  const isHandleCycle = handleBehavior === 'cycle';
2426
2589
  const isSheetModalWithHandle = isSheetModal && showHandle;
2427
- return (h(Host, Object.assign({ key: '87328006ea6c75ebc518ace300438492a567223e', "no-router": true,
2590
+ return (h(Host, Object.assign({ key: 'bca3cbdb2ce8e5127d27eae7494c434aaeddaf88', "no-router": true,
2428
2591
  // Allow the modal to be navigable when the handle is focusable
2429
2592
  tabIndex: isHandleCycle && isSheetModalWithHandle ? 0 : -1 }, htmlAttributes, { style: {
2430
2593
  zIndex: `${20000 + this.overlayIndex}`,
2431
- }, 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: 'ee94ff8e09b691dd4ad4e4db1720f06bc3c5a469', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: 'bffd69b4635c22d9f249725bd952c1e93d5615c7', class: "modal-shadow" }), h("div", Object.assign({ key: '1d394d3c68916e464ff1fbf5242419f4a3d3cca1',
2594
+ }, 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: 'b1c4112123d84d8a9b9d455bcc17d884f99d9f28', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { key: '080c8e6d37b311a1b5ad2655d99f18668abae211', class: "modal-shadow" }), h("div", Object.assign({ key: '8ba05e9520b1b5529bf0caeb766da5bf612d4d14',
2432
2595
  /*
2433
2596
  role and aria-modal must be used on the
2434
2597
  same element. They must also be set inside the
2435
2598
  shadow DOM otherwise ion-button will not be highlighted
2436
2599
  when using VoiceOver: https://bugs.webkit.org/show_bug.cgi?id=247134
2437
2600
  */
2438
- role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '2dcf58792018e557e0c323baad2d672bc99c0bb1', class: "modal-handle",
2601
+ role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { key: '2d2d5d731f55755f32ebcbf557f97486dc6202a6', class: "modal-handle",
2439
2602
  // Prevents the handle from receiving keyboard focus when it does not cycle
2440
- 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: '44164b1e8710c3895400ad9f44ecd99873874ad5', onSlotchange: this.onSlotChange }))));
2603
+ 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: 'c717d19865dafba02e15db79bc0662c5d89e96fd', onSlotchange: this.onSlotChange }))));
2441
2604
  }
2442
2605
  get el() { return this; }
2443
2606
  static get watchers() { return {
@@ -1575,11 +1575,11 @@ const Datetime = class {
1575
1575
  const nextMonthDisabled = disabled || isNextMonthDisabled(this.workingParts, this.maxParts);
1576
1576
  // don't use the inheritAttributes util because it removes dir from the host, and we still need that
1577
1577
  const hostDir = this.el.getAttribute('dir') || undefined;
1578
- return (index.h("div", { class: "calendar-header", part: "calendar-header" }, index.h("div", { class: "calendar-action-buttons" }, index.h("div", { class: "calendar-month-year" }, index.h("button", { class: {
1578
+ return (index.h("div", { class: "calendar-header" }, index.h("div", { class: "calendar-action-buttons" }, index.h("div", { class: "calendar-month-year" }, index.h("button", { class: {
1579
1579
  'calendar-month-year-toggle': true,
1580
1580
  'ion-activatable': true,
1581
1581
  'ion-focusable': true,
1582
- }, part: "month-year-button", disabled: disabled, "aria-label": this.showMonthAndYear ? 'Hide year picker' : 'Show year picker', onClick: () => this.toggleMonthAndYearView() }, index.h("span", { id: "toggle-wrapper" }, data.getMonthAndYear(this.locale, this.workingParts), index.h("ion-icon", { "aria-hidden": "true", icon: this.showMonthAndYear ? expandedIcon : collapsedIcon, lazy: false, flipRtl: true })), mode === 'md' && index.h("ion-ripple-effect", null))), index.h("div", { class: "calendar-next-prev" }, index.h("ion-buttons", null, index.h("ion-button", { "aria-label": "Previous month", disabled: prevMonthDisabled, onClick: () => this.prevMonth(), part: "prev-next-buttons prev-button" }, index.h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: index$1.chevronBack, lazy: false, flipRtl: true })), index.h("ion-button", { "aria-label": "Next month", disabled: nextMonthDisabled, onClick: () => this.nextMonth(), part: "prev-next-buttons next-button" }, index.h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: index$1.chevronForward, lazy: false, flipRtl: true }))))), index.h("div", { class: "calendar-days-of-week", "aria-hidden": "true", part: "days-of-week" }, data.getDaysOfWeek(this.locale, mode, this.firstDayOfWeek % 7).map((d) => {
1582
+ }, part: "month-year-button", disabled: disabled, "aria-label": this.showMonthAndYear ? 'Hide year picker' : 'Show year picker', onClick: () => this.toggleMonthAndYearView() }, index.h("span", { id: "toggle-wrapper" }, data.getMonthAndYear(this.locale, this.workingParts), index.h("ion-icon", { "aria-hidden": "true", icon: this.showMonthAndYear ? expandedIcon : collapsedIcon, lazy: false, flipRtl: true })), mode === 'md' && index.h("ion-ripple-effect", null))), index.h("div", { class: "calendar-next-prev" }, index.h("ion-buttons", null, index.h("ion-button", { "aria-label": "Previous month", disabled: prevMonthDisabled, onClick: () => this.prevMonth() }, index.h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: index$1.chevronBack, lazy: false, flipRtl: true })), index.h("ion-button", { "aria-label": "Next month", disabled: nextMonthDisabled, onClick: () => this.nextMonth() }, index.h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: index$1.chevronForward, lazy: false, flipRtl: true }))))), index.h("div", { class: "calendar-days-of-week", "aria-hidden": "true" }, data.getDaysOfWeek(this.locale, mode, this.firstDayOfWeek % 7).map((d) => {
1583
1583
  return index.h("div", { class: "day-of-week" }, d);
1584
1584
  }))));
1585
1585
  }
@@ -1811,7 +1811,7 @@ const Datetime = class {
1811
1811
  if (!hasSlottedTitle && !this.showDefaultTitle) {
1812
1812
  return;
1813
1813
  }
1814
- return (index.h("div", { class: "datetime-header", part: "datetime-header" }, index.h("div", { class: "datetime-title" }, index.h("slot", { name: "title" }, "Select Date")), showExpandedHeader && index.h("div", { class: "datetime-selected-date" }, this.getHeaderSelectedDateText())));
1814
+ return (index.h("div", { class: "datetime-header" }, index.h("div", { class: "datetime-title" }, index.h("slot", { name: "title" }, "Select Date")), showExpandedHeader && index.h("div", { class: "datetime-selected-date" }, this.getHeaderSelectedDateText())));
1815
1815
  }
1816
1816
  /**
1817
1817
  * Render time picker inside of datetime.
@@ -1891,7 +1891,7 @@ const Datetime = class {
1891
1891
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
1892
1892
  const hasWheelVariant = hasDatePresentation && preferWheel;
1893
1893
  helpers.renderHiddenInput(true, el, name, data.formatValue(value), disabled);
1894
- return (index.h(index.Host, { key: '3d0787ecb3ad104c4a60d68a6e57140f018a70f2', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, theme.createColorClasses(color, {
1894
+ return (index.h(index.Host, { key: '19e20c9b6b5f9467e91a2567b6dc7d9d38b56cc3', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, theme.createColorClasses(color, {
1895
1895
  [mode]: true,
1896
1896
  ['datetime-readonly']: readonly,
1897
1897
  ['datetime-disabled']: disabled,
@@ -1901,7 +1901,7 @@ const Datetime = class {
1901
1901
  [`datetime-size-${size}`]: true,
1902
1902
  [`datetime-prefer-wheel`]: hasWheelVariant,
1903
1903
  [`datetime-grid`]: isGridStyle,
1904
- })) }, index.h("div", { key: '6b245a0033d5ddd1918bc839f142141bf5ec54c5', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1904
+ })) }, index.h("div", { key: 'e31b5ef76cd6262dafd39f2d21980887880ec32e', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1905
1905
  }
1906
1906
  get el() { return index.getElement(this); }
1907
1907
  static get watchers() { return {