@ionic/core 8.8.20-dev.11791579113.1f843ab0 → 8.8.20-dev.11792194859.16be5d7f

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 (33) hide show
  1. package/components/ion-datetime-button.js +1 -1
  2. package/components/ion-datetime.js +1 -1
  3. package/components/{p-BE21dB_a.js → p-Bpr3edV8.js} +1 -1
  4. package/dist/cjs/ion-datetime-button.cjs.entry.js +28 -10
  5. package/dist/cjs/ion-datetime_3.cjs.entry.js +354 -30
  6. package/dist/cjs/ionic.cjs.js +1 -1
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/collection/components/datetime/datetime.ionic.css +144 -1
  9. package/dist/collection/components/datetime/datetime.ios.css +118 -0
  10. package/dist/collection/components/datetime/datetime.js +407 -27
  11. package/dist/collection/components/datetime/datetime.md.css +117 -0
  12. package/dist/collection/components/datetime/utils/state.js +18 -1
  13. package/dist/collection/components/datetime-button/datetime-button.js +28 -10
  14. package/dist/docs.json +151 -1
  15. package/dist/esm/{format-2WlZcMvG.js → format-BNGmd1mx.js} +1 -1
  16. package/dist/esm/ion-datetime-button.entry.js +29 -11
  17. package/dist/esm/ion-datetime_3.entry.js +355 -31
  18. package/dist/esm/ionic.js +1 -1
  19. package/dist/esm/loader.js +1 -1
  20. package/dist/html.html-data.json +20 -0
  21. package/dist/ionic/ionic.esm.js +1 -1
  22. package/dist/ionic/p-4aa6153d.entry.js +4 -0
  23. package/dist/ionic/p-4f2e482f.entry.js +4 -0
  24. package/dist/ionic/{p-7k7Q1A38.js → p-CrgdPEJR.js} +1 -1
  25. package/dist/types/components/datetime/datetime-interface.d.ts +4 -0
  26. package/dist/types/components/datetime/datetime.d.ts +66 -2
  27. package/dist/types/components/datetime/utils/state.d.ts +5 -2
  28. package/dist/types/components.d.ts +33 -0
  29. package/hydrate/index.js +390 -40
  30. package/hydrate/index.mjs +390 -40
  31. package/package.json +1 -1
  32. package/dist/ionic/p-3a4f9b8a.entry.js +0 -4
  33. package/dist/ionic/p-f6768728.entry.js +0 -4
@@ -349,11 +349,83 @@
349
349
 
350
350
  :host .calendar-day-wrapper {
351
351
  display: flex;
352
+ position: relative;
352
353
  align-items: center;
353
354
  justify-content: center;
354
355
  min-width: 0;
355
356
  min-height: 0;
356
357
  overflow: visible;
358
+ /**
359
+ * Create a stacking context so the range track
360
+ * (::before with z-index: -1) stays behind the
361
+ * day button but above the host background.
362
+ */
363
+ z-index: 0;
364
+ }
365
+
366
+ /**
367
+ * The ::before pseudo-element on the calendar-day-wrapper
368
+ * draws the colored background track that connects the
369
+ * range start to the range end. The track is vertically
370
+ * centered and sized to match the day button height.
371
+ *
372
+ * @prop --range-background: The background color of the range selection track.
373
+ */
374
+ :host .calendar-day-wrapper-range-start::before,
375
+ :host .calendar-day-wrapper-in-range::before,
376
+ :host .calendar-day-wrapper-range-end::before {
377
+ position: absolute;
378
+ /**
379
+ * Vertically center the track and size it to
380
+ * match the calendar day button height.
381
+ */
382
+ top: 50%;
383
+ height: var(--range-track-height);
384
+ transform: translateY(-50%);
385
+ background: var(--range-background);
386
+ content: "";
387
+ z-index: -1;
388
+ }
389
+
390
+ :host .calendar-day-wrapper-range-start::before {
391
+ inset-inline-start: 50%;
392
+ inset-inline-end: 0;
393
+ }
394
+
395
+ :host .calendar-day-wrapper-in-range::before {
396
+ inset-inline-start: 0;
397
+ inset-inline-end: 0;
398
+ }
399
+
400
+ :host .calendar-day-wrapper-range-end::before {
401
+ inset-inline-start: 0;
402
+ inset-inline-end: 50%;
403
+ }
404
+
405
+ /**
406
+ * When a single day is both the start and end of the range,
407
+ * do not show a track since there is nothing to connect.
408
+ */
409
+ :host .calendar-day-wrapper-range-start.calendar-day-wrapper-range-end::before {
410
+ display: none;
411
+ }
412
+
413
+ /**
414
+ * When the component is disabled, move the opacity to the wrapper
415
+ * so both the track and day button fade equally. Without this,
416
+ * the day button becomes semi-transparent (via native disabled opacity)
417
+ * while the track stays opaque, causing a visible overlap.
418
+ */
419
+ :host(.datetime-disabled) .calendar-day-wrapper-range-start,
420
+ :host(.datetime-disabled) .calendar-day-wrapper-in-range,
421
+ :host(.datetime-disabled) .calendar-day-wrapper-range-end {
422
+ opacity: 0.4;
423
+ }
424
+
425
+ :host(.datetime-disabled) .calendar-day-wrapper-range-start .calendar-day[disabled],
426
+ :host(.datetime-disabled) .calendar-day-wrapper-in-range .calendar-day[disabled],
427
+ :host(.datetime-disabled) .calendar-day-wrapper-range-end .calendar-day[disabled] {
428
+ opacity: 1;
357
429
  }
358
430
 
359
431
  /**
@@ -864,6 +936,51 @@ ion-picker {
864
936
  color: var(--ion-color-step-500, var(--ion-text-color-step-500, gray));
865
937
  }
866
938
 
939
+ :host {
940
+ --range-background: rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.2);
941
+ --range-track-height: 42px;
942
+ }
943
+
944
+ :host(.ion-color) {
945
+ --range-background: rgba(var(--ion-color-base-rgb), 0.2);
946
+ }
947
+
948
+ :host .calendar-day.calendar-day-range-start {
949
+ border-radius: 50% 0 0 50%;
950
+ background: var(--ion-color-primary, #0054e9);
951
+ color: var(--ion-color-primary-contrast, #fff);
952
+ }
953
+
954
+ :host .calendar-day.calendar-day-range-end {
955
+ border-radius: 0 50% 50% 0;
956
+ background: var(--ion-color-primary, #0054e9);
957
+ color: var(--ion-color-primary-contrast, #fff);
958
+ }
959
+
960
+ :host .calendar-day.calendar-day-range-start.calendar-day-range-end {
961
+ border-radius: 50%;
962
+ }
963
+
964
+ :host .calendar-day.calendar-day-in-range {
965
+ border-radius: 0;
966
+ background: none;
967
+ }
968
+
969
+ :host(.ion-color) .calendar-day.calendar-day-range-start,
970
+ :host(.ion-color) .calendar-day.calendar-day-range-end {
971
+ background: var(--ion-color-base);
972
+ color: var(--ion-color-contrast);
973
+ }
974
+
975
+ :host .calendar-day.calendar-day-today.calendar-day-in-range {
976
+ border: none;
977
+ color: var(--ion-color-primary, #0054e9);
978
+ }
979
+
980
+ :host(.ion-color) .calendar-day.calendar-day-today.calendar-day-in-range {
981
+ color: var(--ion-color-base);
982
+ }
983
+
867
984
  :host .datetime-time {
868
985
  -webkit-padding-start: 16px;
869
986
  padding-inline-start: 16px;
@@ -74,7 +74,7 @@ export const isDayDisabled = (refParts, minParts, maxParts, dayValues) => {
74
74
  * Given a locale, a date, the selected date(s), and today's date,
75
75
  * generate the state for a given calendar day button.
76
76
  */
77
- export const getCalendarDayState = (locale, refParts, activeParts, todayParts, minParts, maxParts, dayValues) => {
77
+ export const getCalendarDayState = (locale, refParts, activeParts, todayParts, minParts, maxParts, dayValues, rangeParts) => {
78
78
  /**
79
79
  * activeParts signals what day(s) are currently selected in the datetime.
80
80
  * If multiple="true", this will be an array, but the logic in this util
@@ -90,6 +90,20 @@ export const getCalendarDayState = (locale, refParts, activeParts, todayParts, m
90
90
  const isActive = activePartsArray.find((parts) => isSameDay(refParts, parts)) !== undefined;
91
91
  const isToday = isSameDay(refParts, todayParts);
92
92
  const disabled = isDayDisabled(refParts, minParts, maxParts, dayValues);
93
+ /**
94
+ * Range state: determine if this day is the range start, end, or in between.
95
+ */
96
+ let isRangeStart = false;
97
+ let isRangeEnd = false;
98
+ let isInRange = false;
99
+ if (rangeParts) {
100
+ const { start, end } = rangeParts;
101
+ isRangeStart = isSameDay(refParts, start);
102
+ if (end) {
103
+ isRangeEnd = isSameDay(refParts, end);
104
+ isInRange = !disabled && !isRangeStart && !isRangeEnd && isAfter(refParts, start) && isBefore(refParts, end);
105
+ }
106
+ }
93
107
  /**
94
108
  * Note that we always return one object regardless of whether activeParts
95
109
  * was an array, since we pare down to one value for isActive.
@@ -98,6 +112,9 @@ export const getCalendarDayState = (locale, refParts, activeParts, todayParts, m
98
112
  disabled,
99
113
  isActive,
100
114
  isToday,
115
+ isRangeStart,
116
+ isRangeEnd,
117
+ isInRange,
101
118
  ariaSelected: isActive ? 'true' : null,
102
119
  ariaLabel: generateDayAriaLabel(locale, isToday, refParts),
103
120
  text: refParts.day != null ? getDay(locale, refParts) : null,
@@ -55,12 +55,12 @@ export class DatetimeButton {
55
55
  * to the locale specified on ion-datetime.
56
56
  */
57
57
  this.setDateTimeText = async () => {
58
- var _a, _b, _c, _d, _e;
58
+ var _a, _b, _c, _d;
59
59
  const { datetimeEl, datetimePresentation } = this;
60
60
  if (!datetimeEl) {
61
61
  return;
62
62
  }
63
- const { value, locale, formatOptions, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
63
+ const { value, locale, formatOptions, hourCycle, preferWheel, multiple, selectionMode, titleSelectedDatesFormatter, } = datetimeEl;
64
64
  const parsedValues = this.getParsedDateValues(value);
65
65
  /**
66
66
  * Both ion-datetime and ion-datetime-button default to today's date and
@@ -72,6 +72,8 @@ export class DatetimeButton {
72
72
  if (!parsedDatetimes) {
73
73
  return;
74
74
  }
75
+ const isRangeMode = selectionMode === 'range';
76
+ const isMultipleMode = selectionMode === 'multiple' || (selectionMode === undefined && multiple);
75
77
  /**
76
78
  * If developers incorrectly use multiple="true"
77
79
  * with non "date" datetimes, then just select
@@ -81,11 +83,12 @@ export class DatetimeButton {
81
83
  */
82
84
  const firstParsedDatetime = parsedDatetimes[0];
83
85
  const computedHourCycle = getHourCycle(locale, hourCycle);
86
+ const dateFormatOptions = (_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _a !== void 0 ? _a : { month: 'short', day: 'numeric', year: 'numeric' };
84
87
  this.dateText = this.timeText = undefined;
85
88
  switch (datetimePresentation) {
86
89
  case 'date-time':
87
90
  case 'time-date':
88
- const dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _a !== void 0 ? _a : { month: 'short', day: 'numeric', year: 'numeric' });
91
+ const dateText = getLocalizedDateTime(locale, firstParsedDatetime, dateFormatOptions);
89
92
  const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time);
90
93
  if (preferWheel) {
91
94
  this.dateText = `${dateText} ${timeText}`;
@@ -96,7 +99,22 @@ export class DatetimeButton {
96
99
  }
97
100
  break;
98
101
  case 'date':
99
- if (multiple && parsedValues.length !== 1) {
102
+ if (isRangeMode && parsedValues.length === 2) {
103
+ // Range mode: display "startDate - endDate"
104
+ const startDate = getLocalizedDateTime(locale, parsedDatetimes[0], dateFormatOptions);
105
+ const endDate = getLocalizedDateTime(locale, parsedDatetimes.length > 1 ? parsedDatetimes[1] : parsedDatetimes[0], dateFormatOptions);
106
+ let rangeText = `${startDate} - ${endDate}`;
107
+ if (titleSelectedDatesFormatter !== undefined) {
108
+ try {
109
+ rangeText = titleSelectedDatesFormatter(parsedValues);
110
+ }
111
+ catch (e) {
112
+ printIonError('[ion-datetime-button] - Exception in provided `titleSelectedDatesFormatter`:', e);
113
+ }
114
+ }
115
+ this.dateText = rangeText;
116
+ }
117
+ else if (isMultipleMode && parsedValues.length !== 1) {
100
118
  let headerText = `${parsedValues.length} days`; // default/fallback for multiple selection
101
119
  if (titleSelectedDatesFormatter !== undefined) {
102
120
  try {
@@ -109,20 +127,20 @@ export class DatetimeButton {
109
127
  this.dateText = headerText;
110
128
  }
111
129
  else {
112
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_b = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _b !== void 0 ? _b : { month: 'short', day: 'numeric', year: 'numeric' });
130
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, dateFormatOptions);
113
131
  }
114
132
  break;
115
133
  case 'time':
116
134
  this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time);
117
135
  break;
118
136
  case 'month-year':
119
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_c = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _c !== void 0 ? _c : { month: 'long', year: 'numeric' });
137
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_b = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _b !== void 0 ? _b : { month: 'long', year: 'numeric' });
120
138
  break;
121
139
  case 'month':
122
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_d = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _d !== void 0 ? _d : { month: 'long' });
140
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_c = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _c !== void 0 ? _c : { month: 'long' });
123
141
  break;
124
142
  case 'year':
125
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_e = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _e !== void 0 ? _e : { year: 'numeric' });
143
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_d = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _d !== void 0 ? _d : { year: 'numeric' });
126
144
  break;
127
145
  }
128
146
  };
@@ -343,11 +361,11 @@ export class DatetimeButton {
343
361
  render() {
344
362
  const { color, dateText, timeText, selectedButton, datetimeActive, disabled } = this;
345
363
  const theme = getIonTheme(this);
346
- return (h(Host, { key: '8cdd9935131b68d84ac601f78d5967383eaaf25e', class: createColorClasses(color, {
364
+ return (h(Host, { key: 'b1bc06c9642af956c42e886af07e27176ba4a13a', class: createColorClasses(color, {
347
365
  [theme]: true,
348
366
  [`${selectedButton}-active`]: datetimeActive,
349
367
  ['datetime-button-disabled']: disabled,
350
- }) }, dateText && (h("button", { key: 'dfd6d83cdca3673383a21e213dae825b5643600d', class: "ion-activatable", id: "date-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleDateClick, disabled: disabled, part: "native", ref: (el) => (this.dateTargetEl = el) }, h("slot", { key: 'f7cabbcd6474c66283fb0681a3d75f36a88750d6', name: "date-target" }, dateText), theme === 'md' && h("ion-ripple-effect", { key: '3aace053cea80aa3bb30a06c8e1f1d18650d8796' }))), timeText && (h("button", { key: 'c8fac088f4e6ee2486110a59574bd95cd3be870b', class: "ion-activatable", id: "time-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleTimeClick, disabled: disabled, part: "native", ref: (el) => (this.timeTargetEl = el) }, h("slot", { key: '195df2d17f6bd28c9cf6ad657e55948472544985', name: "time-target" }, timeText), theme === 'md' && h("ion-ripple-effect", { key: 'aa1a1f5ea120558174b166c2b2d5fa970ca00d2c' })))));
368
+ }) }, dateText && (h("button", { key: '3939366688b3be6db62b70b6a3b717819934560f', class: "ion-activatable", id: "date-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleDateClick, disabled: disabled, part: "native", ref: (el) => (this.dateTargetEl = el) }, h("slot", { key: 'e4cf933fcfdb2c7559806af448c4ec8dfd5a5e14', name: "date-target" }, dateText), theme === 'md' && h("ion-ripple-effect", { key: 'b1c11e4c67bce14f5dfa8b69a15cde5b367b1c4a' }))), timeText && (h("button", { key: '708c2070eecabf09e3db6d8f8a45a76ecd53ccf8', class: "ion-activatable", id: "time-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleTimeClick, disabled: disabled, part: "native", ref: (el) => (this.timeTargetEl = el) }, h("slot", { key: '2885629c3fb033b234bfae0ec9038874e109b0de', name: "time-target" }, timeText), theme === 'md' && h("ion-ripple-effect", { key: '4eed69bef9ed46fb1fd53605bcd05cd104e2505b' })))));
351
369
  }
352
370
  static get is() { return "ion-datetime-button"; }
353
371
  static get encapsulation() { return "shadow"; }
package/dist/docs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-10-09T20:55:27",
2
+ "timestamp": "2026-10-16T23:57:18",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.43.5",
@@ -10811,6 +10811,22 @@
10811
10811
  "name": "part",
10812
10812
  "text": "calendar-day disabled - The calendar day that is disabled."
10813
10813
  },
10814
+ {
10815
+ "name": "part",
10816
+ "text": "range-start - The calendar day button that is the start of a range selection."
10817
+ },
10818
+ {
10819
+ "name": "part",
10820
+ "text": "range-end - The calendar day button that is the end of a range selection."
10821
+ },
10822
+ {
10823
+ "name": "part",
10824
+ "text": "range-selection - The calendar day button that is part of a range selection (includes start and end)."
10825
+ },
10826
+ {
10827
+ "name": "part",
10828
+ "text": "range-track - The calendar day wrapper element whose ::before pseudo-element draws the range highlight track."
10829
+ },
10814
10830
  {
10815
10831
  "name": "part",
10816
10832
  "text": "datetime-header - The datetime header contains the content for the `title` slot and the selected date."
@@ -11049,6 +11065,35 @@
11049
11065
  "getter": false,
11050
11066
  "setter": false
11051
11067
  },
11068
+ {
11069
+ "name": "endDateLabel",
11070
+ "type": "string",
11071
+ "complexType": {
11072
+ "original": "string",
11073
+ "resolved": "string",
11074
+ "references": {}
11075
+ },
11076
+ "mutable": false,
11077
+ "attr": "end-date-label",
11078
+ "reflectToAttr": false,
11079
+ "docs": "The text shown in the datetime header when the end of the range\nis empty, also used by screen readers to announce the end date.\nOnly applies when `selectionMode=\"range\"`.",
11080
+ "docsTags": [
11081
+ {
11082
+ "name": "default",
11083
+ "text": "'End date'"
11084
+ }
11085
+ ],
11086
+ "default": "'End date'",
11087
+ "values": [
11088
+ {
11089
+ "type": "string"
11090
+ }
11091
+ ],
11092
+ "optional": false,
11093
+ "required": false,
11094
+ "getter": false,
11095
+ "setter": false
11096
+ },
11052
11097
  {
11053
11098
  "name": "firstDayOfWeek",
11054
11099
  "type": "number",
@@ -11445,12 +11490,17 @@
11445
11490
  "reflectToAttr": false,
11446
11491
  "docs": "If `true`, multiple dates can be selected at once. Only\napplies to `presentation=\"date\"` and `preferWheel=\"false\"`.",
11447
11492
  "docsTags": [
11493
+ {
11494
+ "name": "deprecated",
11495
+ "text": "Use `selectionMode=\"multiple\"` instead."
11496
+ },
11448
11497
  {
11449
11498
  "name": "default",
11450
11499
  "text": "false"
11451
11500
  }
11452
11501
  ],
11453
11502
  "default": "false",
11503
+ "deprecation": "Use `selectionMode=\"multiple\"` instead.",
11454
11504
  "values": [
11455
11505
  {
11456
11506
  "type": "boolean"
@@ -11609,6 +11659,37 @@
11609
11659
  "getter": false,
11610
11660
  "setter": false
11611
11661
  },
11662
+ {
11663
+ "name": "selectionMode",
11664
+ "type": "\"multiple\" | \"range\" | undefined",
11665
+ "complexType": {
11666
+ "original": "'multiple' | 'range'",
11667
+ "resolved": "\"multiple\" | \"range\" | undefined",
11668
+ "references": {}
11669
+ },
11670
+ "mutable": false,
11671
+ "attr": "selection-mode",
11672
+ "reflectToAttr": false,
11673
+ "docs": "Controls the date selection behavior.\n`'multiple'` enables selecting multiple individual dates.\n`'range'` enables selecting a start and end date range.\nWhen unset, single-date selection is used.\n\nRange selection only works with `presentation=\"date\"` and `preferWheel=\"false\"`.",
11674
+ "docsTags": [],
11675
+ "values": [
11676
+ {
11677
+ "value": "multiple",
11678
+ "type": "string"
11679
+ },
11680
+ {
11681
+ "value": "range",
11682
+ "type": "string"
11683
+ },
11684
+ {
11685
+ "type": "undefined"
11686
+ }
11687
+ ],
11688
+ "optional": true,
11689
+ "required": false,
11690
+ "getter": false,
11691
+ "setter": false
11692
+ },
11612
11693
  {
11613
11694
  "name": "showAdjacentDays",
11614
11695
  "type": "boolean",
@@ -11788,6 +11869,35 @@
11788
11869
  "getter": false,
11789
11870
  "setter": false
11790
11871
  },
11872
+ {
11873
+ "name": "startDateLabel",
11874
+ "type": "string",
11875
+ "complexType": {
11876
+ "original": "string",
11877
+ "resolved": "string",
11878
+ "references": {}
11879
+ },
11880
+ "mutable": false,
11881
+ "attr": "start-date-label",
11882
+ "reflectToAttr": false,
11883
+ "docs": "The text shown in the datetime header when the start of the range\nis empty, also used by screen readers to announce the start date.\nOnly applies when `selectionMode=\"range\"`.",
11884
+ "docsTags": [
11885
+ {
11886
+ "name": "default",
11887
+ "text": "'Start date'"
11888
+ }
11889
+ ],
11890
+ "default": "'Start date'",
11891
+ "values": [
11892
+ {
11893
+ "type": "string"
11894
+ }
11895
+ ],
11896
+ "optional": false,
11897
+ "required": false,
11898
+ "getter": false,
11899
+ "setter": false
11900
+ },
11791
11901
  {
11792
11902
  "name": "theme",
11793
11903
  "type": "\"ios\" | \"md\" | \"ionic\"",
@@ -11969,6 +12079,12 @@
11969
12079
  "Promise": {
11970
12080
  "location": "global",
11971
12081
  "id": "global::Promise"
12082
+ },
12083
+ "DatetimeParts": {
12084
+ "location": "import",
12085
+ "path": "./datetime-interface",
12086
+ "id": "src/components/datetime/datetime-interface.ts::DatetimeParts",
12087
+ "referenceLocation": "DatetimeParts"
11972
12088
  }
11973
12089
  },
11974
12090
  "return": "Promise<void>"
@@ -12138,6 +12254,24 @@
12138
12254
  "docs": "The width of the ring around the focused element.",
12139
12255
  "mode": "ionic"
12140
12256
  },
12257
+ {
12258
+ "name": "--range-background",
12259
+ "annotation": "prop",
12260
+ "docs": "The background color of the range selection track.",
12261
+ "mode": "ionic"
12262
+ },
12263
+ {
12264
+ "name": "--range-background",
12265
+ "annotation": "prop",
12266
+ "docs": "The background color of the range selection track.",
12267
+ "mode": "ios"
12268
+ },
12269
+ {
12270
+ "name": "--range-background",
12271
+ "annotation": "prop",
12272
+ "docs": "The background color of the range selection track.",
12273
+ "mode": "md"
12274
+ },
12141
12275
  {
12142
12276
  "name": "--title-color",
12143
12277
  "annotation": "prop",
@@ -12254,6 +12388,22 @@
12254
12388
  "name": "previous-button",
12255
12389
  "docs": "The button used to navigate to the previous month when using a grid style layout."
12256
12390
  },
12391
+ {
12392
+ "name": "range-end",
12393
+ "docs": "The calendar day button that is the end of a range selection."
12394
+ },
12395
+ {
12396
+ "name": "range-selection",
12397
+ "docs": "The calendar day button that is part of a range selection (includes start and end)."
12398
+ },
12399
+ {
12400
+ "name": "range-start",
12401
+ "docs": "The calendar day button that is the start of a range selection."
12402
+ },
12403
+ {
12404
+ "name": "range-track",
12405
+ "docs": "The calendar day wrapper element whose ::before pseudo-element draws the range highlight track."
12406
+ },
12257
12407
  {
12258
12408
  "name": "time-button",
12259
12409
  "docs": "The button that opens the time picker when using a grid style\nlayout with `presentation=\"date-time\"` or `\"time-date\"`."
@@ -1112,4 +1112,4 @@ const formatValue = (value) => {
1112
1112
  return Array.isArray(value) ? value.join(',') : value;
1113
1113
  };
1114
1114
 
1115
- export { getNextWeek as A, parseMinParts as B, parseMaxParts as C, parseDate as D, warnIfValueOutOfBounds as E, parseAmPm as F, clampDate as G, convertToArrayOfNumbers as H, convertDataToISO as I, getClosestValidDate as J, isMonthFirstLocale as K, isLocaleDayPeriodRTL as L, calculateHourFromAMPM as M, getMonthAndYear as N, getLocalizedTime as O, getLocalizedDateTime as P, formatValue as Q, getPreviousMonth as a, getTodayLabel as b, getYear as c, getHourCycle as d, getInternalHourValue as e, getFormattedHour as f, getNextMonth as g, addTimePadding as h, isSameDay as i, getLocalizedDayPeriod as j, isBefore as k, isAfter as l, is24Hour as m, getNumDaysInMonth as n, getDay as o, generateDayAriaLabel as p, getPartsFromCalendarDay as q, removeDateTzOffset as r, getNextYear as s, getPreviousYear as t, getEndOfWeek as u, validateParts as v, getStartOfWeek as w, getPreviousDay as x, getNextDay as y, getPreviousWeek as z };
1115
+ export { getPreviousWeek as A, getNextWeek as B, parseMinParts as C, parseMaxParts as D, parseDate as E, warnIfValueOutOfBounds as F, clampDate as G, parseAmPm as H, convertToArrayOfNumbers as I, getClosestValidDate as J, isMonthFirstLocale as K, isLocaleDayPeriodRTL as L, calculateHourFromAMPM as M, getMonthAndYear as N, getLocalizedTime as O, getLocalizedDateTime as P, formatValue as Q, getPreviousMonth as a, getTodayLabel as b, getYear as c, getHourCycle as d, getInternalHourValue as e, getFormattedHour as f, getNextMonth as g, addTimePadding as h, isSameDay as i, getLocalizedDayPeriod as j, isBefore as k, isAfter as l, is24Hour as m, getNumDaysInMonth as n, getDay as o, generateDayAriaLabel as p, getNextDay as q, removeDateTzOffset as r, convertDataToISO as s, getPartsFromCalendarDay as t, getNextYear as u, validateParts as v, getPreviousYear as w, getEndOfWeek as x, getStartOfWeek as y, getPreviousDay as z };
@@ -5,7 +5,7 @@ import { r as registerInstance, j as printIonError, h, d as Host, g as getElemen
5
5
  import { f as addEventListener, c as componentOnReady } from './helpers-ChPZH7zh.js';
6
6
  import { c as createColorClasses } from './theme-DaJxRxSQ.js';
7
7
  import { c as getIonTheme } from './ionic-global-BJDU78B6.js';
8
- import { D as parseDate, d as getHourCycle, P as getLocalizedDateTime, O as getLocalizedTime } from './format-2WlZcMvG.js';
8
+ import { E as parseDate, d as getHourCycle, P as getLocalizedDateTime, O as getLocalizedTime } from './format-BNGmd1mx.js';
9
9
  import './focus-visible-vXpMhGrs.js';
10
10
  import './dir-o8OKV5aD.js';
11
11
 
@@ -53,12 +53,12 @@ const DatetimeButton = class {
53
53
  * to the locale specified on ion-datetime.
54
54
  */
55
55
  this.setDateTimeText = async () => {
56
- var _a, _b, _c, _d, _e;
56
+ var _a, _b, _c, _d;
57
57
  const { datetimeEl, datetimePresentation } = this;
58
58
  if (!datetimeEl) {
59
59
  return;
60
60
  }
61
- const { value, locale, formatOptions, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
61
+ const { value, locale, formatOptions, hourCycle, preferWheel, multiple, selectionMode, titleSelectedDatesFormatter, } = datetimeEl;
62
62
  const parsedValues = this.getParsedDateValues(value);
63
63
  /**
64
64
  * Both ion-datetime and ion-datetime-button default to today's date and
@@ -70,6 +70,8 @@ const DatetimeButton = class {
70
70
  if (!parsedDatetimes) {
71
71
  return;
72
72
  }
73
+ const isRangeMode = selectionMode === 'range';
74
+ const isMultipleMode = selectionMode === 'multiple' || (selectionMode === undefined && multiple);
73
75
  /**
74
76
  * If developers incorrectly use multiple="true"
75
77
  * with non "date" datetimes, then just select
@@ -79,11 +81,12 @@ const DatetimeButton = class {
79
81
  */
80
82
  const firstParsedDatetime = parsedDatetimes[0];
81
83
  const computedHourCycle = getHourCycle(locale, hourCycle);
84
+ const dateFormatOptions = (_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _a !== void 0 ? _a : { month: 'short', day: 'numeric', year: 'numeric' };
82
85
  this.dateText = this.timeText = undefined;
83
86
  switch (datetimePresentation) {
84
87
  case 'date-time':
85
88
  case 'time-date':
86
- const dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _a !== void 0 ? _a : { month: 'short', day: 'numeric', year: 'numeric' });
89
+ const dateText = getLocalizedDateTime(locale, firstParsedDatetime, dateFormatOptions);
87
90
  const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time);
88
91
  if (preferWheel) {
89
92
  this.dateText = `${dateText} ${timeText}`;
@@ -94,7 +97,22 @@ const DatetimeButton = class {
94
97
  }
95
98
  break;
96
99
  case 'date':
97
- if (multiple && parsedValues.length !== 1) {
100
+ if (isRangeMode && parsedValues.length === 2) {
101
+ // Range mode: display "startDate - endDate"
102
+ const startDate = getLocalizedDateTime(locale, parsedDatetimes[0], dateFormatOptions);
103
+ const endDate = getLocalizedDateTime(locale, parsedDatetimes.length > 1 ? parsedDatetimes[1] : parsedDatetimes[0], dateFormatOptions);
104
+ let rangeText = `${startDate} - ${endDate}`;
105
+ if (titleSelectedDatesFormatter !== undefined) {
106
+ try {
107
+ rangeText = titleSelectedDatesFormatter(parsedValues);
108
+ }
109
+ catch (e) {
110
+ printIonError('[ion-datetime-button] - Exception in provided `titleSelectedDatesFormatter`:', e);
111
+ }
112
+ }
113
+ this.dateText = rangeText;
114
+ }
115
+ else if (isMultipleMode && parsedValues.length !== 1) {
98
116
  let headerText = `${parsedValues.length} days`; // default/fallback for multiple selection
99
117
  if (titleSelectedDatesFormatter !== undefined) {
100
118
  try {
@@ -107,20 +125,20 @@ const DatetimeButton = class {
107
125
  this.dateText = headerText;
108
126
  }
109
127
  else {
110
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_b = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _b !== void 0 ? _b : { month: 'short', day: 'numeric', year: 'numeric' });
128
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, dateFormatOptions);
111
129
  }
112
130
  break;
113
131
  case 'time':
114
132
  this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time);
115
133
  break;
116
134
  case 'month-year':
117
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_c = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _c !== void 0 ? _c : { month: 'long', year: 'numeric' });
135
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_b = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _b !== void 0 ? _b : { month: 'long', year: 'numeric' });
118
136
  break;
119
137
  case 'month':
120
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_d = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _d !== void 0 ? _d : { month: 'long' });
138
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_c = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _c !== void 0 ? _c : { month: 'long' });
121
139
  break;
122
140
  case 'year':
123
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_e = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _e !== void 0 ? _e : { year: 'numeric' });
141
+ this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_d = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _d !== void 0 ? _d : { year: 'numeric' });
124
142
  break;
125
143
  }
126
144
  };
@@ -341,11 +359,11 @@ const DatetimeButton = class {
341
359
  render() {
342
360
  const { color, dateText, timeText, selectedButton, datetimeActive, disabled } = this;
343
361
  const theme = getIonTheme(this);
344
- return (h(Host, { key: '8cdd9935131b68d84ac601f78d5967383eaaf25e', class: createColorClasses(color, {
362
+ return (h(Host, { key: 'b1bc06c9642af956c42e886af07e27176ba4a13a', class: createColorClasses(color, {
345
363
  [theme]: true,
346
364
  [`${selectedButton}-active`]: datetimeActive,
347
365
  ['datetime-button-disabled']: disabled,
348
- }) }, dateText && (h("button", { key: 'dfd6d83cdca3673383a21e213dae825b5643600d', class: "ion-activatable", id: "date-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleDateClick, disabled: disabled, part: "native", ref: (el) => (this.dateTargetEl = el) }, h("slot", { key: 'f7cabbcd6474c66283fb0681a3d75f36a88750d6', name: "date-target" }, dateText), theme === 'md' && h("ion-ripple-effect", { key: '3aace053cea80aa3bb30a06c8e1f1d18650d8796' }))), timeText && (h("button", { key: 'c8fac088f4e6ee2486110a59574bd95cd3be870b', class: "ion-activatable", id: "time-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleTimeClick, disabled: disabled, part: "native", ref: (el) => (this.timeTargetEl = el) }, h("slot", { key: '195df2d17f6bd28c9cf6ad657e55948472544985', name: "time-target" }, timeText), theme === 'md' && h("ion-ripple-effect", { key: 'aa1a1f5ea120558174b166c2b2d5fa970ca00d2c' })))));
366
+ }) }, dateText && (h("button", { key: '3939366688b3be6db62b70b6a3b717819934560f', class: "ion-activatable", id: "date-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleDateClick, disabled: disabled, part: "native", ref: (el) => (this.dateTargetEl = el) }, h("slot", { key: 'e4cf933fcfdb2c7559806af448c4ec8dfd5a5e14', name: "date-target" }, dateText), theme === 'md' && h("ion-ripple-effect", { key: 'b1c11e4c67bce14f5dfa8b69a15cde5b367b1c4a' }))), timeText && (h("button", { key: '708c2070eecabf09e3db6d8f8a45a76ecd53ccf8', class: "ion-activatable", id: "time-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleTimeClick, disabled: disabled, part: "native", ref: (el) => (this.timeTargetEl = el) }, h("slot", { key: '2885629c3fb033b234bfae0ec9038874e109b0de', name: "time-target" }, timeText), theme === 'md' && h("ion-ripple-effect", { key: '4eed69bef9ed46fb1fd53605bcd05cd104e2505b' })))));
349
367
  }
350
368
  get el() { return getElement(this); }
351
369
  };