@ionic/core 7.3.4-dev.11699991837.1bc64f72 → 7.3.4-dev.11700516018.128deb56

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 (150) hide show
  1. package/components/button-active.js +1 -1
  2. package/components/checkbox.js +3 -6
  3. package/components/data.js +7 -31
  4. package/components/index.js +2 -2
  5. package/components/index2.js +429 -203
  6. package/components/index3.js +203 -429
  7. package/components/ion-datetime-button.js +0 -3
  8. package/components/ion-datetime.js +92 -132
  9. package/components/ion-item-sliding.js +1 -1
  10. package/components/ion-menu.js +3 -3
  11. package/components/ion-modal.js +2 -2
  12. package/components/ion-nav.js +1 -1
  13. package/components/ion-range.js +3 -3
  14. package/components/ion-refresher.js +3 -3
  15. package/components/ion-reorder-group.js +1 -1
  16. package/components/ion-router-outlet.js +1 -1
  17. package/components/ion-segment.js +1 -1
  18. package/components/ion-toggle.js +4 -7
  19. package/components/ion-toolbar.js +2 -2
  20. package/components/ios.transition.js +1 -1
  21. package/components/md.transition.js +1 -1
  22. package/components/picker-column.js +1 -1
  23. package/components/popover.js +1 -1
  24. package/components/radio.js +3 -6
  25. package/components/swipe-back.js +1 -1
  26. package/dist/cjs/{data-db832785.js → data-967b9c15.js} +7 -31
  27. package/dist/cjs/index.cjs.js +9 -10
  28. package/dist/cjs/ion-app_8.cjs.entry.js +2 -2
  29. package/dist/cjs/ion-checkbox.cjs.entry.js +3 -5
  30. package/dist/cjs/ion-datetime-button.cjs.entry.js +1 -4
  31. package/dist/cjs/ion-datetime_3.cjs.entry.js +93 -132
  32. package/dist/cjs/ion-menu_3.cjs.entry.js +2 -2
  33. package/dist/cjs/ion-radio_2.cjs.entry.js +3 -5
  34. package/dist/cjs/ion-range.cjs.entry.js +2 -2
  35. package/dist/cjs/ion-toggle.cjs.entry.js +3 -5
  36. package/dist/cjs/ionic.cjs.js +1 -1
  37. package/dist/cjs/loader.cjs.js +1 -1
  38. package/dist/collection/components/checkbox/checkbox.ios.css +0 -35
  39. package/dist/collection/components/checkbox/checkbox.js +4 -24
  40. package/dist/collection/components/checkbox/checkbox.md.css +0 -35
  41. package/dist/collection/components/checkbox/test/item/checkbox.e2e.js +0 -13
  42. package/dist/collection/components/checkbox/test/label/checkbox.e2e.js +0 -16
  43. package/dist/collection/components/datetime/datetime.ios.css +29 -32
  44. package/dist/collection/components/datetime/datetime.js +93 -137
  45. package/dist/collection/components/datetime/datetime.md.css +28 -20
  46. package/dist/collection/components/datetime/test/basic/datetime.e2e.js +0 -25
  47. package/dist/collection/components/datetime/test/color/datetime.e2e.js +1 -1
  48. package/dist/collection/components/datetime/test/custom/datetime.e2e.js +1 -27
  49. package/dist/collection/components/datetime/test/prefer-wheel/datetime.e2e.js +0 -15
  50. package/dist/collection/components/datetime/test/set-value/datetime.e2e.js +12 -9
  51. package/dist/collection/components/datetime/utils/data.js +6 -14
  52. package/dist/collection/components/datetime/utils/parse.js +1 -18
  53. package/dist/collection/components/datetime-button/datetime-button.js +0 -3
  54. package/dist/collection/components/menu/menu.ios.css +0 -94
  55. package/dist/collection/components/menu/menu.md.css +0 -94
  56. package/dist/collection/components/radio/radio.ios.css +0 -35
  57. package/dist/collection/components/radio/radio.js +4 -24
  58. package/dist/collection/components/radio/radio.md.css +0 -35
  59. package/dist/collection/components/radio/test/item/radio.e2e.js +0 -15
  60. package/dist/collection/components/radio/test/label-placement/radio.e2e.js +0 -20
  61. package/dist/collection/components/range/range.ios.css +1 -41
  62. package/dist/collection/components/range/range.js +3 -3
  63. package/dist/collection/components/range/range.md.css +1 -41
  64. package/dist/collection/components/range/test/label/range.e2e.js +0 -48
  65. package/dist/collection/components/toggle/test/item/toggle.e2e.js +0 -15
  66. package/dist/collection/components/toggle/test/label/toggle.e2e.js +0 -16
  67. package/dist/collection/components/toggle/toggle.ios.css +1 -35
  68. package/dist/collection/components/toggle/toggle.js +4 -24
  69. package/dist/collection/components/toggle/toggle.md.css +1 -35
  70. package/dist/collection/components/toolbar/toolbar.ios.css +4 -2
  71. package/dist/collection/components/toolbar/toolbar.md.css +4 -2
  72. package/dist/collection/index.js +0 -1
  73. package/dist/docs.json +18 -147
  74. package/dist/esm/{data-009dbf15.js → data-4b448e3a.js} +7 -31
  75. package/dist/esm/index.js +2 -2
  76. package/dist/esm/ion-app_8.entry.js +2 -2
  77. package/dist/esm/ion-checkbox.entry.js +3 -5
  78. package/dist/esm/ion-datetime-button.entry.js +1 -4
  79. package/dist/esm/ion-datetime_3.entry.js +93 -132
  80. package/dist/esm/ion-menu_3.entry.js +2 -2
  81. package/dist/esm/ion-radio_2.entry.js +3 -5
  82. package/dist/esm/ion-range.entry.js +2 -2
  83. package/dist/esm/ion-toggle.entry.js +3 -5
  84. package/dist/esm/ionic.js +1 -1
  85. package/dist/esm/loader.js +1 -1
  86. package/dist/esm-es5/data-4b448e3a.js +4 -0
  87. package/dist/esm-es5/index.js +1 -1
  88. package/dist/esm-es5/ion-app_8.entry.js +1 -1
  89. package/dist/esm-es5/ion-checkbox.entry.js +1 -1
  90. package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
  91. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  92. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  93. package/dist/esm-es5/ion-radio_2.entry.js +1 -1
  94. package/dist/esm-es5/ion-range.entry.js +1 -1
  95. package/dist/esm-es5/ion-toggle.entry.js +1 -1
  96. package/dist/esm-es5/ionic.js +1 -1
  97. package/dist/esm-es5/loader.js +1 -1
  98. package/dist/html.html-data.json +4 -52
  99. package/dist/ionic/index.esm.js +1 -1
  100. package/dist/ionic/ionic.esm.js +1 -1
  101. package/dist/ionic/p-0053fe81.system.entry.js +4 -0
  102. package/dist/ionic/p-06902103.system.js +1 -1
  103. package/dist/ionic/p-091cd81e.entry.js +4 -0
  104. package/dist/ionic/p-28f5715a.system.entry.js +4 -0
  105. package/dist/ionic/p-2cdcd6f2.entry.js +4 -0
  106. package/dist/ionic/{p-a34669bf.system.entry.js → p-45ee211b.system.entry.js} +1 -1
  107. package/dist/ionic/p-5009cb46.entry.js +4 -0
  108. package/dist/ionic/p-5b88f780.entry.js +4 -0
  109. package/dist/ionic/p-601fd53c.js +4 -0
  110. package/dist/ionic/p-8843b046.system.js +4 -0
  111. package/dist/ionic/p-98b618ce.system.entry.js +4 -0
  112. package/dist/ionic/p-b1e8f045.entry.js +4 -0
  113. package/dist/ionic/p-b3394798.system.entry.js +4 -0
  114. package/dist/ionic/p-b3cfc6e1.system.entry.js +4 -0
  115. package/dist/ionic/{p-f9567c67.entry.js → p-c759a704.entry.js} +1 -1
  116. package/dist/ionic/p-cc8910e7.system.js +4 -0
  117. package/dist/ionic/{p-67b891af.entry.js → p-d3b8aebf.entry.js} +1 -1
  118. package/dist/ionic/p-e53b8af4.system.entry.js +4 -0
  119. package/dist/ionic/p-f78e60a5.entry.js +4 -0
  120. package/dist/ionic/p-fd42994b.system.entry.js +4 -0
  121. package/dist/types/components/checkbox/checkbox.d.ts +1 -8
  122. package/dist/types/components/datetime/datetime.d.ts +10 -23
  123. package/dist/types/components/datetime/utils/data.d.ts +1 -1
  124. package/dist/types/components/datetime/utils/parse.d.ts +3 -3
  125. package/dist/types/components/radio/radio.d.ts +1 -8
  126. package/dist/types/components/range/range.d.ts +1 -2
  127. package/dist/types/components/toast/toast-interface.d.ts +0 -3
  128. package/dist/types/components/toggle/toggle.d.ts +1 -8
  129. package/dist/types/components.d.ts +16 -40
  130. package/dist/types/index.d.ts +0 -1
  131. package/dist/types/interface.d.ts +0 -1
  132. package/hydrate/index.js +114 -196
  133. package/package.json +2 -2
  134. package/dist/esm-es5/data-009dbf15.js +0 -4
  135. package/dist/ionic/p-1f4adf06.system.entry.js +0 -4
  136. package/dist/ionic/p-218b6f33.entry.js +0 -4
  137. package/dist/ionic/p-2da6ba37.system.entry.js +0 -4
  138. package/dist/ionic/p-40138199.entry.js +0 -4
  139. package/dist/ionic/p-44ef7224.system.js +0 -4
  140. package/dist/ionic/p-4ca1ce6b.system.entry.js +0 -4
  141. package/dist/ionic/p-51b165af.system.js +0 -4
  142. package/dist/ionic/p-57f0efcc.entry.js +0 -4
  143. package/dist/ionic/p-7cfd253c.js +0 -4
  144. package/dist/ionic/p-82f5c07e.system.entry.js +0 -4
  145. package/dist/ionic/p-86c5c320.entry.js +0 -4
  146. package/dist/ionic/p-90ec5785.system.entry.js +0 -4
  147. package/dist/ionic/p-af986299.system.entry.js +0 -4
  148. package/dist/ionic/p-b321c999.entry.js +0 -4
  149. package/dist/ionic/p-d8a0267b.system.entry.js +0 -4
  150. package/dist/ionic/p-f5c19164.entry.js +0 -4
@@ -33,17 +33,16 @@ import { getCalendarDayState, getHighlightStyles, isDayDisabled, isMonthDisabled
33
33
  *
34
34
  * @part month-year-button - The button that opens the month/year picker when
35
35
  * using a grid style layout.
36
- *
37
- * @part calendar-day - The individual buttons that display a day inside of the datetime
38
- * calendar.
39
- * @part calendar-day active - The currently selected calendar day.
40
- * @part calendar-day today - The calendar day that contains the current day.
41
- * @part calendar-day disabled - The calendar day that is disabled.
42
36
  */
43
37
  export class Datetime {
44
38
  constructor() {
45
39
  this.inputId = `ion-dt-${datetimeIds++}`;
46
40
  this.prevPresentation = null;
41
+ /**
42
+ * Duplicate reference to `activeParts` that does not trigger a re-render of the component.
43
+ * Allows caching an instance of the `activeParts` in between render cycles.
44
+ */
45
+ this.activePartsClone = [];
47
46
  this.warnIfIncorrectValueUsage = () => {
48
47
  const { multiple, value } = this;
49
48
  if (!multiple && Array.isArray(value)) {
@@ -71,9 +70,9 @@ export class Datetime {
71
70
  * data. This should be used when rendering an
72
71
  * interface in an environment where the `value`
73
72
  * may not be set. This function works
74
- * by returning the first selected date and then
75
- * falling back to defaultParts if no active date
76
- * is selected.
73
+ * by returning the first selected date in
74
+ * "activePartsClone" and then falling back to
75
+ * defaultParts if no active date is selected.
77
76
  */
78
77
  this.getActivePartsWithFallback = () => {
79
78
  var _a;
@@ -81,8 +80,8 @@ export class Datetime {
81
80
  return (_a = this.getActivePart()) !== null && _a !== void 0 ? _a : defaultParts;
82
81
  };
83
82
  this.getActivePart = () => {
84
- const { activeParts } = this;
85
- return Array.isArray(activeParts) ? activeParts[0] : activeParts;
83
+ const { activePartsClone } = this;
84
+ return Array.isArray(activePartsClone) ? activePartsClone[0] : activePartsClone;
86
85
  };
87
86
  this.closeParentOverlay = () => {
88
87
  const popoverOrModal = this.el.closest('ion-modal, ion-popover');
@@ -94,7 +93,7 @@ export class Datetime {
94
93
  this.workingParts = Object.assign({}, parts);
95
94
  };
96
95
  this.setActiveParts = (parts, removeDate = false) => {
97
- const { multiple, minParts, maxParts, activeParts } = this;
96
+ const { multiple, minParts, maxParts, activePartsClone } = this;
98
97
  /**
99
98
  * When setting the active parts, it is possible
100
99
  * to set invalid data. For example,
@@ -108,7 +107,16 @@ export class Datetime {
108
107
  const validatedParts = validateParts(parts, minParts, maxParts);
109
108
  this.setWorkingParts(validatedParts);
110
109
  if (multiple) {
111
- const activePartsArray = Array.isArray(activeParts) ? activeParts : [activeParts];
110
+ /**
111
+ * We read from activePartsClone here because valueChanged() only updates that,
112
+ * so it's the more reliable source of truth. If we read from activeParts, then
113
+ * if you click July 1, manually set the value to July 2, and then click July 3,
114
+ * the new value would be [July 1, July 3], ignoring the value set.
115
+ *
116
+ * We can then pass the new value to activeParts (rather than activePartsClone)
117
+ * since the clone will be updated automatically by activePartsChanged().
118
+ */
119
+ const activePartsArray = Array.isArray(activePartsClone) ? activePartsClone : [activePartsClone];
112
120
  if (removeDate) {
113
121
  this.activeParts = activePartsArray.filter((p) => !isSameDay(p, validatedParts));
114
122
  }
@@ -233,7 +241,7 @@ export class Datetime {
233
241
  /**
234
242
  * Get the number of padding days so
235
243
  * we know how much to offset our next selector by
236
- * to grab the correct calendar-day element.
244
+ * to grab the correct calenday-day element.
237
245
  */
238
246
  const padding = currentMonth.querySelectorAll('.calendar-day-padding');
239
247
  const { day } = this.workingParts;
@@ -244,7 +252,7 @@ export class Datetime {
244
252
  * Get the calendar day element
245
253
  * and focus it.
246
254
  */
247
- const dayEl = currentMonth.querySelector(`.calendar-day-wrapper:nth-of-type(${padding.length + day}) .calendar-day`);
255
+ const dayEl = currentMonth.querySelector(`.calendar-day:nth-of-type(${padding.length + day})`);
248
256
  if (dayEl) {
249
257
  dayEl.focus();
250
258
  }
@@ -325,19 +333,6 @@ export class Datetime {
325
333
  const monthBox = month.getBoundingClientRect();
326
334
  if (Math.abs(monthBox.x - box.x) > 2)
327
335
  return;
328
- /**
329
- * If we're force-rendering a month, assume we've
330
- * scrolled to that and return it.
331
- *
332
- * If forceRenderDate is ever used in a context where the
333
- * forced month is not immediately auto-scrolled to, this
334
- * should be updated to also check whether `month` has the
335
- * same month and year as the forced date.
336
- */
337
- const { forceRenderDate } = this;
338
- if (forceRenderDate !== undefined) {
339
- return { month: forceRenderDate.month, year: forceRenderDate.year, day: forceRenderDate.day };
340
- }
341
336
  /**
342
337
  * From here, we can determine if the start
343
338
  * month or the end month was scrolled into view.
@@ -392,9 +387,6 @@ export class Datetime {
392
387
  this.setWorkingParts(Object.assign(Object.assign({}, this.workingParts), { month, day: day, year }));
393
388
  calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
394
389
  calendarBodyRef.style.removeProperty('overflow');
395
- if (this.resolveForceDateScrolling) {
396
- this.resolveForceDateScrolling();
397
- }
398
390
  });
399
391
  };
400
392
  /**
@@ -449,17 +441,10 @@ export class Datetime {
449
441
  }
450
442
  };
451
443
  this.processValue = (value) => {
452
- const hasValue = value !== null && value !== undefined && (!Array.isArray(value) || value.length > 0);
444
+ const hasValue = value !== null && value !== undefined;
453
445
  const valueToProcess = hasValue ? parseDate(value) : this.defaultParts;
454
- const { minParts, maxParts, workingParts, el } = this;
446
+ const { minParts, maxParts } = this;
455
447
  this.warnIfIncorrectValueUsage();
456
- /**
457
- * Return early if the value wasn't parsed correctly, such as
458
- * if an improperly formatted date string was provided.
459
- */
460
- if (!valueToProcess) {
461
- return;
462
- }
463
448
  /**
464
449
  * Datetime should only warn of out of bounds values
465
450
  * if set by the user. If the `value` is undefined,
@@ -477,9 +462,16 @@ export class Datetime {
477
462
  * that the values don't necessarily have to be in order.
478
463
  */
479
464
  const singleValue = Array.isArray(valueToProcess) ? valueToProcess[0] : valueToProcess;
480
- const targetValue = clampDate(singleValue, minParts, maxParts);
481
- const { month, day, year, hour, minute } = targetValue;
465
+ const { month, day, year, hour, minute } = clampDate(singleValue, minParts, maxParts);
482
466
  const ampm = parseAmPm(hour);
467
+ this.setWorkingParts({
468
+ month,
469
+ day,
470
+ year,
471
+ hour,
472
+ minute,
473
+ ampm,
474
+ });
483
475
  /**
484
476
  * Since `activeParts` indicates a value that
485
477
  * been explicitly selected either by the
@@ -509,62 +501,6 @@ export class Datetime {
509
501
  */
510
502
  this.activeParts = [];
511
503
  }
512
- /**
513
- * Only animate if:
514
- * 1. We're using grid style (wheel style pickers should just jump to new value)
515
- * 2. The month and/or year actually changed, and both are defined (otherwise there's nothing to animate to)
516
- * 3. The calendar body is visible (prevents animation when in collapsed datetime-button, for example)
517
- * 4. The month/year picker is not open (since you wouldn't see the animation anyway)
518
- */
519
- const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
520
- const bodyIsVisible = el.classList.contains('datetime-ready');
521
- const { isGridStyle, showMonthAndYear } = this;
522
- if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
523
- this.animateToDate(targetValue);
524
- }
525
- else {
526
- /**
527
- * We only need to do this if we didn't just animate to a new month,
528
- * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
529
- */
530
- this.setWorkingParts({
531
- month,
532
- day,
533
- year,
534
- hour,
535
- minute,
536
- ampm,
537
- });
538
- }
539
- };
540
- this.animateToDate = async (targetValue) => {
541
- const { workingParts } = this;
542
- /**
543
- * Tell other render functions that we need to force the
544
- * target month to appear in place of the actual next/prev month.
545
- * Because this is a State variable, a rerender will be triggered
546
- * automatically, updating the rendered months.
547
- */
548
- this.forceRenderDate = targetValue;
549
- /**
550
- * Flag that we've started scrolling to the forced date.
551
- * The resolve function will be called by the datetime's
552
- * scroll listener when it's done updating everything.
553
- * This is a replacement for making prev/nextMonth async,
554
- * since the logic we're waiting on is in a listener.
555
- */
556
- const forceDateScrollingPromise = new Promise((resolve) => {
557
- this.resolveForceDateScrolling = resolve;
558
- });
559
- /**
560
- * Animate smoothly to the forced month. This will also update
561
- * workingParts and correct the surrounding months for us.
562
- */
563
- const targetMonthIsBefore = isBefore(targetValue, workingParts);
564
- targetMonthIsBefore ? this.prevMonth() : this.nextMonth();
565
- await forceDateScrollingPromise;
566
- this.resolveForceDateScrolling = undefined;
567
- this.forceRenderDate = undefined;
568
504
  };
569
505
  this.onFocus = () => {
570
506
  this.ionFocus.emit();
@@ -620,7 +556,6 @@ export class Datetime {
620
556
  ampm: 'pm',
621
557
  };
622
558
  this.isTimePopoverOpen = false;
623
- this.forceRenderDate = undefined;
624
559
  this.color = 'primary';
625
560
  this.name = this.inputId;
626
561
  this.disabled = false;
@@ -660,11 +595,6 @@ export class Datetime {
660
595
  maxChanged() {
661
596
  this.processMaxParts();
662
597
  }
663
- get isGridStyle() {
664
- const { presentation, preferWheel } = this;
665
- const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
666
- return hasDatePresentation && !preferWheel;
667
- }
668
598
  yearValuesChanged() {
669
599
  this.parsedYearValues = convertToArrayOfNumbers(this.yearValues);
670
600
  }
@@ -680,13 +610,51 @@ export class Datetime {
680
610
  minuteValuesChanged() {
681
611
  this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues);
682
612
  }
613
+ activePartsChanged() {
614
+ this.activePartsClone = this.activeParts;
615
+ }
683
616
  /**
684
617
  * Update the datetime value when the value changes
685
618
  */
686
- async valueChanged() {
687
- const { value } = this;
619
+ valueChanged() {
620
+ const { value, minParts, maxParts, workingParts } = this;
688
621
  if (this.hasValue()) {
689
- this.processValue(value);
622
+ this.warnIfIncorrectValueUsage();
623
+ /**
624
+ * Clones the value of the `activeParts` to the private clone, to update
625
+ * the date display on the current render cycle without causing another render.
626
+ *
627
+ * This allows us to update the current value's date/time display without
628
+ * refocusing or shifting the user's display (leaves the user in place).
629
+ */
630
+ const valueDateParts = parseDate(value);
631
+ if (valueDateParts) {
632
+ warnIfValueOutOfBounds(valueDateParts, minParts, maxParts);
633
+ if (Array.isArray(valueDateParts)) {
634
+ this.activePartsClone = [...valueDateParts];
635
+ }
636
+ else {
637
+ const { month, day, year, hour, minute } = valueDateParts;
638
+ const ampm = hour != null ? (hour >= 12 ? 'pm' : 'am') : undefined;
639
+ this.activePartsClone = Object.assign(Object.assign({}, this.activeParts), { month,
640
+ day,
641
+ year,
642
+ hour,
643
+ minute,
644
+ ampm });
645
+ /**
646
+ * The working parts am/pm value must be updated when the value changes, to
647
+ * ensure the time picker hour column values are generated correctly.
648
+ *
649
+ * Note that we don't need to do this if valueDateParts is an array, since
650
+ * multiple="true" does not apply to time pickers.
651
+ */
652
+ this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { ampm }));
653
+ }
654
+ }
655
+ else {
656
+ printIonWarning(`Unable to parse date string: ${value}. Please provide a valid ISO 8601 datetime string.`);
657
+ }
690
658
  }
691
659
  this.emitStyle();
692
660
  this.ionValueChange.emit({ value });
@@ -889,6 +857,8 @@ export class Datetime {
889
857
  printIonWarning('The highlightedDates property is not supported with preferWheel="true".', el);
890
858
  }
891
859
  }
860
+ this.processMinParts();
861
+ this.processMaxParts();
892
862
  const hourValues = (this.parsedHourValues = convertToArrayOfNumbers(this.hourValues));
893
863
  const minuteValues = (this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues));
894
864
  const monthValues = (this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues));
@@ -896,8 +866,6 @@ export class Datetime {
896
866
  const dayValues = (this.parsedDayValues = convertToArrayOfNumbers(this.dayValues));
897
867
  const todayParts = (this.todayParts = parseDate(getToday()));
898
868
  this.defaultParts = getClosestValidDate(todayParts, monthValues, dayValues, yearValues, hourValues, minuteValues);
899
- this.processMinParts();
900
- this.processMaxParts();
901
869
  this.processValue(this.value);
902
870
  this.emitStyle();
903
871
  }
@@ -1282,7 +1250,7 @@ export class Datetime {
1282
1250
  const { el, highlightedDates, isDateEnabled, multiple } = this;
1283
1251
  const referenceParts = { month, day, year };
1284
1252
  const isCalendarPadding = day === null;
1285
- const { isActive, isToday, ariaLabel, ariaSelected, disabled, text } = getCalendarDayState(this.locale, referenceParts, this.activeParts, this.todayParts, this.minParts, this.maxParts, this.parsedDayValues);
1253
+ const { isActive, isToday, ariaLabel, ariaSelected, disabled, text } = getCalendarDayState(this.locale, referenceParts, this.activePartsClone, this.todayParts, this.minParts, this.maxParts, this.parsedDayValues);
1286
1254
  const dateIsoString = convertDataToISO(referenceParts);
1287
1255
  let isCalDayDisabled = isCalMonthDisabled || disabled;
1288
1256
  if (!isCalDayDisabled && isDateEnabled !== undefined) {
@@ -1306,30 +1274,14 @@ export class Datetime {
1306
1274
  if (highlightedDates !== undefined && !isActive && day !== null) {
1307
1275
  dateStyle = getHighlightStyles(highlightedDates, dateIsoString, el);
1308
1276
  }
1309
- let dateParts = undefined;
1310
- // "Filler days" at the beginning of the grid should not get the calendar day
1311
- // CSS parts added to them
1312
- if (!isCalendarPadding) {
1313
- dateParts = `calendar-day${isActive ? ' active' : ''}${isToday ? ' today' : ''}${isCalDayDisabled ? ' disabled' : ''}`;
1314
- }
1315
- return (h("div", { class: "calendar-day-wrapper" }, h("button", {
1316
- // We need to use !important for the inline styles here because
1317
- // otherwise the CSS shadow parts will override these styles.
1318
- // See https://github.com/WICG/webcomponents/issues/847
1319
- // Both the CSS shadow parts and highlightedDates styles are
1320
- // provided by the developer, but highlightedDates styles should
1321
- // always take priority.
1322
- ref: (el) => {
1323
- if (el) {
1324
- el.style.setProperty('color', `${dateStyle ? dateStyle.textColor : ''}`, 'important');
1325
- el.style.setProperty('background-color', `${dateStyle ? dateStyle.backgroundColor : ''}`, 'important');
1326
- }
1327
- }, tabindex: "-1", "data-day": day, "data-month": month, "data-year": year, "data-index": index, "data-day-of-week": dayOfWeek, disabled: isCalDayDisabled, class: {
1277
+ return (h("button", { tabindex: "-1", "data-day": day, "data-month": month, "data-year": year, "data-index": index, "data-day-of-week": dayOfWeek, disabled: isCalDayDisabled, class: {
1328
1278
  'calendar-day-padding': isCalendarPadding,
1329
1279
  'calendar-day': true,
1330
1280
  'calendar-day-active': isActive,
1331
1281
  'calendar-day-today': isToday,
1332
- }, part: dateParts, "aria-hidden": isCalendarPadding ? 'true' : null, "aria-selected": ariaSelected, "aria-label": ariaLabel, onClick: () => {
1282
+ }, style: dateStyle && {
1283
+ color: dateStyle.textColor,
1284
+ }, "aria-hidden": isCalendarPadding ? 'true' : null, "aria-selected": ariaSelected, "aria-label": ariaLabel, onClick: () => {
1333
1285
  if (isCalendarPadding) {
1334
1286
  return;
1335
1287
  }
@@ -1349,12 +1301,13 @@ export class Datetime {
1349
1301
  day,
1350
1302
  year }));
1351
1303
  }
1352
- }
1353
- }, text)));
1304
+ } }, h("div", { class: "calendar-day-highlight", style: {
1305
+ backgroundColor: dateStyle === null || dateStyle === void 0 ? void 0 : dateStyle.backgroundColor,
1306
+ } }), text));
1354
1307
  }))));
1355
1308
  }
1356
1309
  renderCalendarBody() {
1357
- return (h("div", { class: "calendar-body ion-focusable", ref: (el) => (this.calendarBodyRef = el), tabindex: "0" }, generateMonths(this.workingParts, this.forceRenderDate).map(({ month, year }) => {
1310
+ return (h("div", { class: "calendar-body ion-focusable", ref: (el) => (this.calendarBodyRef = el), tabindex: "0" }, generateMonths(this.workingParts).map(({ month, year }) => {
1358
1311
  return this.renderMonth(month, year);
1359
1312
  })));
1360
1313
  }
@@ -1509,13 +1462,14 @@ export class Datetime {
1509
1462
  }
1510
1463
  }
1511
1464
  render() {
1512
- const { name, value, disabled, el, color, readonly, showMonthAndYear, preferWheel, presentation, size, isGridStyle, } = this;
1465
+ const { name, value, disabled, el, color, readonly, showMonthAndYear, preferWheel, presentation, size } = this;
1513
1466
  const mode = getIonMode(this);
1514
1467
  const isMonthAndYearPresentation = presentation === 'year' || presentation === 'month' || presentation === 'month-year';
1515
1468
  const shouldShowMonthAndYear = showMonthAndYear || isMonthAndYearPresentation;
1516
1469
  const monthYearPickerOpen = showMonthAndYear && !isMonthAndYearPresentation;
1517
1470
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
1518
1471
  const hasWheelVariant = hasDatePresentation && preferWheel;
1472
+ const hasGrid = hasDatePresentation && !preferWheel;
1519
1473
  renderHiddenInput(true, el, name, formatValue(value), disabled);
1520
1474
  return (h(Host, { "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1521
1475
  [mode]: true,
@@ -1526,7 +1480,7 @@ export class Datetime {
1526
1480
  [`datetime-presentation-${presentation}`]: true,
1527
1481
  [`datetime-size-${size}`]: true,
1528
1482
  [`datetime-prefer-wheel`]: hasWheelVariant,
1529
- [`datetime-grid`]: isGridStyle,
1483
+ [`datetime-grid`]: hasGrid,
1530
1484
  })) }, this.renderDatetime(mode)));
1531
1485
  }
1532
1486
  static get is() { return "ion-datetime"; }
@@ -2085,8 +2039,7 @@ export class Datetime {
2085
2039
  "showMonthAndYear": {},
2086
2040
  "activeParts": {},
2087
2041
  "workingParts": {},
2088
- "isTimePopoverOpen": {},
2089
- "forceRenderDate": {}
2042
+ "isTimePopoverOpen": {}
2090
2043
  };
2091
2044
  }
2092
2045
  static get events() {
@@ -2314,6 +2267,9 @@ export class Datetime {
2314
2267
  }, {
2315
2268
  "propName": "minuteValues",
2316
2269
  "methodName": "minuteValuesChanged"
2270
+ }, {
2271
+ "propName": "activeParts",
2272
+ "methodName": "activePartsChanged"
2317
2273
  }, {
2318
2274
  "propName": "value",
2319
2275
  "methodName": "valueChanged"
@@ -281,8 +281,6 @@ ion-picker-column-internal {
281
281
  }
282
282
 
283
283
  :host .calendar-body .calendar-month {
284
- display: flex;
285
- flex-flow: column;
286
284
  /**
287
285
  * Swiping should snap to at
288
286
  * most one month at a time.
@@ -316,21 +314,11 @@ ion-picker-column-internal {
316
314
  grid-template-columns: repeat(7, 1fr);
317
315
  }
318
316
 
319
- :host .calendar-day-wrapper {
320
- display: flex;
321
- align-items: center;
322
- justify-content: center;
323
- min-width: 0;
324
- min-height: 0;
325
- overflow: visible;
326
- }
327
-
328
317
  /**
329
318
  * Center the day text vertically
330
319
  * and horizontally within its grid cell.
331
320
  */
332
321
  :host .calendar-day {
333
- border-radius: 50%;
334
322
  -webkit-padding-start: 0px;
335
323
  padding-inline-start: 0px;
336
324
  -webkit-padding-end: 0px;
@@ -362,9 +350,18 @@ ion-picker-column-internal {
362
350
  opacity: 0.4;
363
351
  }
364
352
 
365
- .calendar-day:focus {
366
- background: rgba(var(--ion-color-base-rgb), 0.2);
367
- box-shadow: 0px 0px 0px 4px rgba(var(--ion-color-base-rgb), 0.2);
353
+ .calendar-day-highlight {
354
+ border-radius: 32px;
355
+ -webkit-padding-start: 4px;
356
+ padding-inline-start: 4px;
357
+ -webkit-padding-end: 4px;
358
+ padding-inline-end: 4px;
359
+ padding-top: 4px;
360
+ padding-bottom: 4px;
361
+ position: absolute;
362
+ width: 32px;
363
+ height: 32px;
364
+ z-index: -1;
368
365
  }
369
366
 
370
367
  :host .datetime-time {
@@ -483,21 +480,32 @@ ion-picker-column-internal {
483
480
  }
484
481
 
485
482
  :host .calendar-day {
486
- width: 42px;
487
- min-width: 42px;
488
- height: 42px;
483
+ -webkit-padding-start: 0px;
484
+ padding-inline-start: 0px;
485
+ -webkit-padding-end: 0;
486
+ padding-inline-end: 0;
487
+ padding-top: 13px;
488
+ padding-bottom: 13px;
489
489
  font-size: 14px;
490
490
  }
491
491
 
492
+ .calendar-day:focus .calendar-day-highlight {
493
+ background: rgba(var(--ion-color-base-rgb), 0.2);
494
+ box-shadow: 0px 0px 0px 4px rgba(var(--ion-color-base-rgb), 0.2);
495
+ }
496
+
492
497
  /**
493
498
  * Day that today but not selected
494
499
  * should have ion-color for text color.
495
500
  */
496
501
  :host .calendar-day.calendar-day-today {
497
- border: 1px solid var(--ion-color-base);
498
502
  color: var(--ion-color-base);
499
503
  }
500
504
 
505
+ .calendar-day.calendar-day-today .calendar-day-highlight {
506
+ border: 1px solid var(--ion-color-base);
507
+ }
508
+
501
509
  /**
502
510
  * Day that is not today but
503
511
  * is selected should have ion-color for
@@ -507,7 +515,7 @@ ion-picker-column-internal {
507
515
  color: var(--ion-color-contrast);
508
516
  }
509
517
 
510
- .calendar-day.calendar-day-active {
518
+ .calendar-day.calendar-day-active .calendar-day-highlight {
511
519
  border: 1px solid var(--ion-color-base);
512
520
  background: var(--ion-color-base);
513
521
  }
@@ -348,28 +348,3 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
348
348
  });
349
349
  });
350
350
  });
351
- /**
352
- * This behavior does not differ across
353
- * directions.
354
- */
355
- configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
356
- test.describe(title('datetime: focus'), () => {
357
- test('should focus the selected day and then the day after', async ({ page }) => {
358
- await page.setContent(`
359
- <ion-datetime value="2023-08-01"></ion-datetime>
360
- `, config);
361
- await page.waitForSelector('.datetime-ready');
362
- const datetime = page.locator('ion-datetime');
363
- const day = datetime.locator(`.calendar-day[data-day='1'][data-month='8']`);
364
- await day.focus();
365
- await page.waitForChanges();
366
- await expect(day).toBeFocused();
367
- await expect(datetime).toHaveScreenshot(screenshot(`datetime-focus-selected-calendar-day`));
368
- await page.keyboard.press('ArrowRight');
369
- await page.waitForChanges();
370
- const nextDay = datetime.locator(`.calendar-day[data-day='2'][data-month='8']`);
371
- await expect(nextDay).toBeFocused();
372
- await expect(datetime).toHaveScreenshot(screenshot(`datetime-focus-calendar-day`));
373
- });
374
- });
375
- });
@@ -10,7 +10,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
10
10
  test.describe(title('datetime: color'), () => {
11
11
  test('should not have visual regressions', async ({ page }) => {
12
12
  await page.goto('/src/components/datetime/test/color', config);
13
- const datetime = page.locator('#color-datetime');
13
+ const datetime = page.locator('ion-datetime');
14
14
  await expect(datetime).toHaveScreenshot(screenshot(`datetime-color`));
15
15
  await page.evaluate(() => document.body.classList.toggle('dark'));
16
16
  await page.waitForChanges();
@@ -13,7 +13,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
13
13
  await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-wheel`));
14
14
  });
15
15
  test('should allow styling time picker in grid style datetimes', async ({ page }) => {
16
- const timeButton = page.locator('#custom-grid .time-body');
16
+ const timeButton = page.locator('ion-datetime .time-body');
17
17
  const popover = page.locator('.popover-viewport');
18
18
  const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
19
19
  await expect(timeButton).toHaveScreenshot(screenshot(`datetime-custom-time-button`));
@@ -22,31 +22,5 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
22
22
  await expect(popover).toHaveScreenshot(screenshot(`datetime-custom-time-picker`));
23
23
  await expect(timeButton).toHaveScreenshot(screenshot(`datetime-custom-time-button-active`));
24
24
  });
25
- test('should allow styling calendar days in grid style datetimes', async ({ page }) => {
26
- const datetime = page.locator('#custom-calendar-days');
27
- await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-calendar-days`));
28
- });
29
- });
30
- });
31
- /**
32
- * This behavior does not differ across
33
- * directions.
34
- */
35
- configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
36
- test.describe(title('datetime: custom focus'), () => {
37
- test('should focus the selected day and then the day after', async ({ page }) => {
38
- await page.goto(`/src/components/datetime/test/custom`, config);
39
- const datetime = page.locator('#custom-calendar-days');
40
- const day = datetime.locator(`.calendar-day[data-day='15'][data-month='6']`);
41
- await day.focus();
42
- await page.waitForChanges();
43
- await expect(day).toBeFocused();
44
- await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-focus-selected-calendar-day`));
45
- await page.keyboard.press('ArrowRight');
46
- await page.waitForChanges();
47
- const nextDay = datetime.locator(`.calendar-day[data-day='16'][data-month='6']`);
48
- await expect(nextDay).toBeFocused();
49
- await expect(datetime).toHaveScreenshot(screenshot(`datetime-custom-focus-calendar-day`));
50
- });
51
25
  });
52
26
  });
@@ -184,21 +184,6 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
184
184
  await yearValues.nth(10).click();
185
185
  await ionChange.next();
186
186
  });
187
- test('should jump to selected date when programmatically updating value', async ({ page }) => {
188
- await page.setContent(`
189
- <ion-datetime presentation="date" prefer-wheel="true" min="2019-05-05" max="2023-10-01" value="2019-05-30"></ion-datetime>
190
- `, config);
191
- await page.waitForSelector('.datetime-ready');
192
- const datetime = page.locator('ion-datetime');
193
- await datetime.evaluate((el) => (el.value = '2021-05-25T12:40:00.000Z'));
194
- await page.waitForChanges();
195
- const selectedMonth = datetime.locator('.month-column .picker-item-active');
196
- const selectedDay = datetime.locator('.day-column .picker-item-active');
197
- const selectedYear = datetime.locator('.year-column .picker-item-active');
198
- await expect(selectedMonth).toHaveText(/May/);
199
- await expect(selectedDay).toHaveText(/25/);
200
- await expect(selectedYear).toHaveText(/2021/);
201
- });
202
187
  test.describe('datetime: date wheel localization', () => {
203
188
  test('should correctly localize the date data', async ({ page }) => {
204
189
  await page.setContent(`
@@ -30,21 +30,24 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
30
30
  await page.waitForSelector('.datetime-ready');
31
31
  const datetime = page.locator('ion-datetime');
32
32
  const activeDayButton = page.locator('.calendar-day-active');
33
+ const monthYearButton = page.locator('.calendar-month-year');
34
+ const monthColumn = page.locator('.month-column');
35
+ const ionChange = await page.spyOnEvent('ionChange');
33
36
  await datetime.evaluate((el) => (el.value = '2021-10-05'));
37
+ // Open month/year picker
38
+ await monthYearButton.click();
39
+ await page.waitForChanges();
40
+ // Select October 2021
41
+ // The year will automatically switch to 2021 when selecting 10
42
+ await monthColumn.locator('.picker-item[data-value="10"]').click();
43
+ await ionChange.next();
44
+ // Close month/year picker
45
+ await monthYearButton.click();
34
46
  await page.waitForChanges();
35
47
  // Check that correct day is highlighted
36
48
  await expect(activeDayButton).toHaveAttribute('data-day', '5');
37
49
  await expect(activeDayButton).toHaveAttribute('data-month', '10');
38
50
  await expect(activeDayButton).toHaveAttribute('data-year', '2021');
39
51
  });
40
- test('should scroll to new month when value is initially set and then updated', async ({ page }) => {
41
- await page.goto('/src/components/datetime/test/set-value', config);
42
- await page.waitForSelector('.datetime-ready');
43
- const datetime = page.locator('ion-datetime');
44
- await datetime.evaluate((el) => (el.value = '2021-05-25T12:40:00.000Z'));
45
- await page.waitForChanges();
46
- const calendarHeader = datetime.locator('.calendar-month-year');
47
- await expect(calendarHeader).toHaveText(/May 2021/);
48
- });
49
52
  });
50
53
  });