@ionic/core 7.3.5-nightly.20230914 → 7.4.0
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.
- package/components/button-active.js +1 -1
- package/components/checkbox.js +6 -3
- package/components/data.js +31 -7
- package/components/index.js +2 -2
- package/components/index2.js +203 -429
- package/components/index3.js +429 -203
- package/components/ion-datetime-button.js +3 -0
- package/components/ion-datetime.js +132 -92
- package/components/ion-item-sliding.js +1 -1
- package/components/ion-menu.js +1 -1
- package/components/ion-modal.js +2 -2
- package/components/ion-nav.js +1 -1
- package/components/ion-range.js +3 -3
- package/components/ion-refresher.js +3 -3
- package/components/ion-reorder-group.js +1 -1
- package/components/ion-router-outlet.js +1 -1
- package/components/ion-segment.js +1 -1
- package/components/ion-toggle.js +7 -4
- package/components/ios.transition.js +1 -1
- package/components/md.transition.js +1 -1
- package/components/notch-controller.js +1 -1
- package/components/picker-column.js +1 -1
- package/components/popover.js +1 -1
- package/components/radio.js +6 -3
- package/components/swipe-back.js +1 -1
- package/css/core.css.map +1 -1
- package/css/ionic.bundle.css.map +1 -1
- package/dist/cjs/{data-967b9c15.js → data-db832785.js} +31 -7
- package/dist/cjs/index.cjs.js +10 -9
- package/dist/cjs/ion-checkbox.cjs.entry.js +5 -3
- package/dist/cjs/ion-datetime-button.cjs.entry.js +4 -1
- package/dist/cjs/ion-datetime_3.cjs.entry.js +132 -93
- package/dist/cjs/ion-input.cjs.entry.js +1 -1
- package/dist/cjs/ion-radio_2.cjs.entry.js +5 -3
- package/dist/cjs/ion-range.cjs.entry.js +2 -2
- package/dist/cjs/ion-select_3.cjs.entry.js +1 -1
- package/dist/cjs/ion-textarea.cjs.entry.js +1 -1
- package/dist/cjs/ion-toggle.cjs.entry.js +5 -3
- package/dist/cjs/ionic.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{notch-controller-c27fe0b7.js → notch-controller-f4f6af5d.js} +1 -1
- package/dist/collection/components/checkbox/checkbox.ios.css +67 -0
- package/dist/collection/components/checkbox/checkbox.js +24 -4
- package/dist/collection/components/checkbox/checkbox.md.css +67 -0
- package/dist/collection/components/checkbox/test/item/checkbox.e2e.js +13 -0
- package/dist/collection/components/checkbox/test/label/checkbox.e2e.js +27 -0
- package/dist/collection/components/datetime/datetime.ios.css +32 -29
- package/dist/collection/components/datetime/datetime.js +137 -93
- package/dist/collection/components/datetime/datetime.md.css +20 -28
- package/dist/collection/components/datetime/test/basic/datetime.e2e.js +25 -0
- package/dist/collection/components/datetime/test/color/datetime.e2e.js +1 -1
- package/dist/collection/components/datetime/test/custom/datetime.e2e.js +27 -1
- package/dist/collection/components/datetime/test/prefer-wheel/datetime.e2e.js +15 -0
- package/dist/collection/components/datetime/test/set-value/datetime.e2e.js +9 -12
- package/dist/collection/components/datetime/utils/data.js +14 -6
- package/dist/collection/components/datetime/utils/parse.js +18 -1
- package/dist/collection/components/datetime-button/datetime-button.js +3 -0
- package/dist/collection/components/radio/radio.ios.css +67 -0
- package/dist/collection/components/radio/radio.js +24 -4
- package/dist/collection/components/radio/radio.md.css +67 -0
- package/dist/collection/components/radio/test/item/radio.e2e.js +15 -0
- package/dist/collection/components/radio/test/label-placement/radio.e2e.js +31 -0
- package/dist/collection/components/range/range.ios.css +66 -1
- package/dist/collection/components/range/range.js +3 -3
- package/dist/collection/components/range/range.md.css +66 -1
- package/dist/collection/components/range/test/item/range.e2e.js +15 -0
- package/dist/collection/components/range/test/label/range.e2e.js +59 -0
- package/dist/collection/components/toggle/test/item/toggle.e2e.js +15 -0
- package/dist/collection/components/toggle/test/label/toggle.e2e.js +27 -0
- package/dist/collection/components/toggle/toggle.ios.css +67 -1
- package/dist/collection/components/toggle/toggle.js +24 -4
- package/dist/collection/components/toggle/toggle.md.css +67 -1
- package/dist/collection/index.js +1 -0
- package/dist/collection/utils/forms/notch-controller.js +1 -1
- package/dist/docs.json +147 -18
- package/dist/esm/{data-4b448e3a.js → data-009dbf15.js} +31 -7
- package/dist/esm/index.js +2 -2
- package/dist/esm/ion-checkbox.entry.js +5 -3
- package/dist/esm/ion-datetime-button.entry.js +4 -1
- package/dist/esm/ion-datetime_3.entry.js +132 -93
- package/dist/esm/ion-input.entry.js +1 -1
- package/dist/esm/ion-radio_2.entry.js +5 -3
- package/dist/esm/ion-range.entry.js +2 -2
- package/dist/esm/ion-select_3.entry.js +1 -1
- package/dist/esm/ion-textarea.entry.js +1 -1
- package/dist/esm/ion-toggle.entry.js +5 -3
- package/dist/esm/ionic.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{notch-controller-cb5bbe6a.js → notch-controller-8c9c0e54.js} +1 -1
- package/dist/esm-es5/data-009dbf15.js +4 -0
- package/dist/esm-es5/index.js +1 -1
- package/dist/esm-es5/ion-checkbox.entry.js +1 -1
- package/dist/esm-es5/ion-datetime-button.entry.js +1 -1
- package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
- package/dist/esm-es5/ion-input.entry.js +1 -1
- package/dist/esm-es5/ion-radio_2.entry.js +1 -1
- package/dist/esm-es5/ion-range.entry.js +1 -1
- package/dist/esm-es5/ion-select_3.entry.js +1 -1
- package/dist/esm-es5/ion-textarea.entry.js +1 -1
- package/dist/esm-es5/ion-toggle.entry.js +1 -1
- package/dist/esm-es5/ionic.js +1 -1
- package/dist/esm-es5/loader.js +1 -1
- package/dist/html.html-data.json +52 -4
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/{p-dc4c9086.system.entry.js → p-264b5dd9.system.entry.js} +1 -1
- package/dist/ionic/{p-4d2807fa.entry.js → p-37c9e295.entry.js} +1 -1
- package/dist/ionic/p-3d575698.system.entry.js +4 -0
- package/dist/ionic/p-44ef7224.system.js +4 -0
- package/dist/ionic/{p-1c236453.system.entry.js → p-46058a1e.system.entry.js} +1 -1
- package/dist/ionic/{p-68deb933.entry.js → p-52edd6b0.entry.js} +1 -1
- package/dist/ionic/p-60f22efc.system.entry.js +4 -0
- package/dist/ionic/p-6d640b2b.entry.js +4 -0
- package/dist/ionic/p-74ef17ea.system.entry.js +4 -0
- package/dist/ionic/p-7cfd253c.js +4 -0
- package/dist/ionic/p-9fccec52.system.js +4 -0
- package/dist/ionic/p-aa702daf.entry.js +4 -0
- package/dist/ionic/p-ab051966.entry.js +4 -0
- package/dist/ionic/p-c005eb67.system.entry.js +4 -0
- package/dist/ionic/p-c68a8814.system.js +1 -1
- package/dist/ionic/p-cc758251.system.entry.js +4 -0
- package/dist/ionic/{p-0ce43a8f.system.entry.js → p-d0d09178.system.entry.js} +1 -1
- package/dist/ionic/p-dfee12f6.entry.js +4 -0
- package/dist/ionic/{p-8db97b90.entry.js → p-e3ca182a.entry.js} +1 -1
- package/dist/ionic/p-f0c28fbd.entry.js +4 -0
- package/dist/ionic/p-fdfc7b98.entry.js +4 -0
- package/dist/ionic/p-ff0611e6.system.entry.js +4 -0
- package/dist/types/components/checkbox/checkbox.d.ts +8 -1
- package/dist/types/components/datetime/datetime.d.ts +23 -10
- package/dist/types/components/datetime/utils/data.d.ts +1 -1
- package/dist/types/components/datetime/utils/parse.d.ts +3 -3
- package/dist/types/components/radio/radio.d.ts +8 -1
- package/dist/types/components/range/range.d.ts +2 -1
- package/dist/types/components/toast/toast-interface.d.ts +3 -0
- package/dist/types/components/toggle/toggle.d.ts +8 -1
- package/dist/types/components.d.ts +40 -16
- package/dist/types/index.d.ts +1 -0
- package/dist/types/interface.d.ts +1 -0
- package/hydrate/index.js +193 -111
- package/package.json +1 -1
- package/dist/esm-es5/data-4b448e3a.js +0 -4
- package/dist/ionic/p-17e961cf.entry.js +0 -4
- package/dist/ionic/p-1b533a76.system.entry.js +0 -4
- package/dist/ionic/p-44a6f15d.system.entry.js +0 -4
- package/dist/ionic/p-4f7109fa.entry.js +0 -4
- package/dist/ionic/p-601fd53c.js +0 -4
- package/dist/ionic/p-7106c152.system.js +0 -4
- package/dist/ionic/p-9eaaa910.entry.js +0 -4
- package/dist/ionic/p-af6125d1.system.entry.js +0 -4
- package/dist/ionic/p-b8d7f0eb.system.entry.js +0 -4
- package/dist/ionic/p-b9179eab.entry.js +0 -4
- package/dist/ionic/p-cc8910e7.system.js +0 -4
- package/dist/ionic/p-dc7d392d.entry.js +0 -4
- package/dist/ionic/p-e65aed58.system.entry.js +0 -4
- package/dist/ionic/p-f3ec1f2b.entry.js +0 -4
- package/dist/ionic/p-fb26fa56.system.entry.js +0 -4
- /package/dist/esm-es5/{notch-controller-cb5bbe6a.js → notch-controller-8c9c0e54.js} +0 -0
- /package/dist/ionic/{p-4b37d92d.js → p-3bad5c1a.js} +0 -0
- /package/dist/ionic/{p-46b2991d.system.js → p-ab4cff27.system.js} +0 -0
|
@@ -33,16 +33,17 @@ 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.
|
|
36
42
|
*/
|
|
37
43
|
export class Datetime {
|
|
38
44
|
constructor() {
|
|
39
45
|
this.inputId = `ion-dt-${datetimeIds++}`;
|
|
40
46
|
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 = [];
|
|
46
47
|
this.warnIfIncorrectValueUsage = () => {
|
|
47
48
|
const { multiple, value } = this;
|
|
48
49
|
if (!multiple && Array.isArray(value)) {
|
|
@@ -70,9 +71,9 @@ export class Datetime {
|
|
|
70
71
|
* data. This should be used when rendering an
|
|
71
72
|
* interface in an environment where the `value`
|
|
72
73
|
* may not be set. This function works
|
|
73
|
-
* by returning the first selected date
|
|
74
|
-
*
|
|
75
|
-
*
|
|
74
|
+
* by returning the first selected date and then
|
|
75
|
+
* falling back to defaultParts if no active date
|
|
76
|
+
* is selected.
|
|
76
77
|
*/
|
|
77
78
|
this.getActivePartsWithFallback = () => {
|
|
78
79
|
var _a;
|
|
@@ -80,8 +81,8 @@ export class Datetime {
|
|
|
80
81
|
return (_a = this.getActivePart()) !== null && _a !== void 0 ? _a : defaultParts;
|
|
81
82
|
};
|
|
82
83
|
this.getActivePart = () => {
|
|
83
|
-
const {
|
|
84
|
-
return Array.isArray(
|
|
84
|
+
const { activeParts } = this;
|
|
85
|
+
return Array.isArray(activeParts) ? activeParts[0] : activeParts;
|
|
85
86
|
};
|
|
86
87
|
this.closeParentOverlay = () => {
|
|
87
88
|
const popoverOrModal = this.el.closest('ion-modal, ion-popover');
|
|
@@ -93,7 +94,7 @@ export class Datetime {
|
|
|
93
94
|
this.workingParts = Object.assign({}, parts);
|
|
94
95
|
};
|
|
95
96
|
this.setActiveParts = (parts, removeDate = false) => {
|
|
96
|
-
const { multiple, minParts, maxParts,
|
|
97
|
+
const { multiple, minParts, maxParts, activeParts } = this;
|
|
97
98
|
/**
|
|
98
99
|
* When setting the active parts, it is possible
|
|
99
100
|
* to set invalid data. For example,
|
|
@@ -107,16 +108,7 @@ export class Datetime {
|
|
|
107
108
|
const validatedParts = validateParts(parts, minParts, maxParts);
|
|
108
109
|
this.setWorkingParts(validatedParts);
|
|
109
110
|
if (multiple) {
|
|
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];
|
|
111
|
+
const activePartsArray = Array.isArray(activeParts) ? activeParts : [activeParts];
|
|
120
112
|
if (removeDate) {
|
|
121
113
|
this.activeParts = activePartsArray.filter((p) => !isSameDay(p, validatedParts));
|
|
122
114
|
}
|
|
@@ -241,7 +233,7 @@ export class Datetime {
|
|
|
241
233
|
/**
|
|
242
234
|
* Get the number of padding days so
|
|
243
235
|
* we know how much to offset our next selector by
|
|
244
|
-
* to grab the correct
|
|
236
|
+
* to grab the correct calendar-day element.
|
|
245
237
|
*/
|
|
246
238
|
const padding = currentMonth.querySelectorAll('.calendar-day-padding');
|
|
247
239
|
const { day } = this.workingParts;
|
|
@@ -252,7 +244,7 @@ export class Datetime {
|
|
|
252
244
|
* Get the calendar day element
|
|
253
245
|
* and focus it.
|
|
254
246
|
*/
|
|
255
|
-
const dayEl = currentMonth.querySelector(`.calendar-day:nth-of-type(${padding.length + day})`);
|
|
247
|
+
const dayEl = currentMonth.querySelector(`.calendar-day-wrapper:nth-of-type(${padding.length + day}) .calendar-day`);
|
|
256
248
|
if (dayEl) {
|
|
257
249
|
dayEl.focus();
|
|
258
250
|
}
|
|
@@ -333,6 +325,19 @@ export class Datetime {
|
|
|
333
325
|
const monthBox = month.getBoundingClientRect();
|
|
334
326
|
if (Math.abs(monthBox.x - box.x) > 2)
|
|
335
327
|
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
|
+
}
|
|
336
341
|
/**
|
|
337
342
|
* From here, we can determine if the start
|
|
338
343
|
* month or the end month was scrolled into view.
|
|
@@ -387,6 +392,9 @@ export class Datetime {
|
|
|
387
392
|
this.setWorkingParts(Object.assign(Object.assign({}, this.workingParts), { month, day: day, year }));
|
|
388
393
|
calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
|
|
389
394
|
calendarBodyRef.style.removeProperty('overflow');
|
|
395
|
+
if (this.resolveForceDateScrolling) {
|
|
396
|
+
this.resolveForceDateScrolling();
|
|
397
|
+
}
|
|
390
398
|
});
|
|
391
399
|
};
|
|
392
400
|
/**
|
|
@@ -441,10 +449,17 @@ export class Datetime {
|
|
|
441
449
|
}
|
|
442
450
|
};
|
|
443
451
|
this.processValue = (value) => {
|
|
444
|
-
const hasValue = value !== null && value !== undefined;
|
|
452
|
+
const hasValue = value !== null && value !== undefined && (!Array.isArray(value) || value.length > 0);
|
|
445
453
|
const valueToProcess = hasValue ? parseDate(value) : this.defaultParts;
|
|
446
|
-
const { minParts, maxParts } = this;
|
|
454
|
+
const { minParts, maxParts, workingParts, el } = this;
|
|
447
455
|
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
|
+
}
|
|
448
463
|
/**
|
|
449
464
|
* Datetime should only warn of out of bounds values
|
|
450
465
|
* if set by the user. If the `value` is undefined,
|
|
@@ -462,16 +477,9 @@ export class Datetime {
|
|
|
462
477
|
* that the values don't necessarily have to be in order.
|
|
463
478
|
*/
|
|
464
479
|
const singleValue = Array.isArray(valueToProcess) ? valueToProcess[0] : valueToProcess;
|
|
465
|
-
const
|
|
480
|
+
const targetValue = clampDate(singleValue, minParts, maxParts);
|
|
481
|
+
const { month, day, year, hour, minute } = targetValue;
|
|
466
482
|
const ampm = parseAmPm(hour);
|
|
467
|
-
this.setWorkingParts({
|
|
468
|
-
month,
|
|
469
|
-
day,
|
|
470
|
-
year,
|
|
471
|
-
hour,
|
|
472
|
-
minute,
|
|
473
|
-
ampm,
|
|
474
|
-
});
|
|
475
483
|
/**
|
|
476
484
|
* Since `activeParts` indicates a value that
|
|
477
485
|
* been explicitly selected either by the
|
|
@@ -501,6 +509,62 @@ export class Datetime {
|
|
|
501
509
|
*/
|
|
502
510
|
this.activeParts = [];
|
|
503
511
|
}
|
|
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;
|
|
504
568
|
};
|
|
505
569
|
this.onFocus = () => {
|
|
506
570
|
this.ionFocus.emit();
|
|
@@ -556,6 +620,7 @@ export class Datetime {
|
|
|
556
620
|
ampm: 'pm',
|
|
557
621
|
};
|
|
558
622
|
this.isTimePopoverOpen = false;
|
|
623
|
+
this.forceRenderDate = undefined;
|
|
559
624
|
this.color = 'primary';
|
|
560
625
|
this.name = this.inputId;
|
|
561
626
|
this.disabled = false;
|
|
@@ -595,6 +660,11 @@ export class Datetime {
|
|
|
595
660
|
maxChanged() {
|
|
596
661
|
this.processMaxParts();
|
|
597
662
|
}
|
|
663
|
+
get isGridStyle() {
|
|
664
|
+
const { presentation, preferWheel } = this;
|
|
665
|
+
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
666
|
+
return hasDatePresentation && !preferWheel;
|
|
667
|
+
}
|
|
598
668
|
yearValuesChanged() {
|
|
599
669
|
this.parsedYearValues = convertToArrayOfNumbers(this.yearValues);
|
|
600
670
|
}
|
|
@@ -610,51 +680,13 @@ export class Datetime {
|
|
|
610
680
|
minuteValuesChanged() {
|
|
611
681
|
this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues);
|
|
612
682
|
}
|
|
613
|
-
activePartsChanged() {
|
|
614
|
-
this.activePartsClone = this.activeParts;
|
|
615
|
-
}
|
|
616
683
|
/**
|
|
617
684
|
* Update the datetime value when the value changes
|
|
618
685
|
*/
|
|
619
|
-
valueChanged() {
|
|
620
|
-
const { value
|
|
686
|
+
async valueChanged() {
|
|
687
|
+
const { value } = this;
|
|
621
688
|
if (this.hasValue()) {
|
|
622
|
-
this.
|
|
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
|
-
}
|
|
689
|
+
this.processValue(value);
|
|
658
690
|
}
|
|
659
691
|
this.emitStyle();
|
|
660
692
|
this.ionValueChange.emit({ value });
|
|
@@ -857,8 +889,6 @@ export class Datetime {
|
|
|
857
889
|
printIonWarning('The highlightedDates property is not supported with preferWheel="true".', el);
|
|
858
890
|
}
|
|
859
891
|
}
|
|
860
|
-
this.processMinParts();
|
|
861
|
-
this.processMaxParts();
|
|
862
892
|
const hourValues = (this.parsedHourValues = convertToArrayOfNumbers(this.hourValues));
|
|
863
893
|
const minuteValues = (this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues));
|
|
864
894
|
const monthValues = (this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues));
|
|
@@ -866,6 +896,8 @@ export class Datetime {
|
|
|
866
896
|
const dayValues = (this.parsedDayValues = convertToArrayOfNumbers(this.dayValues));
|
|
867
897
|
const todayParts = (this.todayParts = parseDate(getToday()));
|
|
868
898
|
this.defaultParts = getClosestValidDate(todayParts, monthValues, dayValues, yearValues, hourValues, minuteValues);
|
|
899
|
+
this.processMinParts();
|
|
900
|
+
this.processMaxParts();
|
|
869
901
|
this.processValue(this.value);
|
|
870
902
|
this.emitStyle();
|
|
871
903
|
}
|
|
@@ -1250,7 +1282,7 @@ export class Datetime {
|
|
|
1250
1282
|
const { el, highlightedDates, isDateEnabled, multiple } = this;
|
|
1251
1283
|
const referenceParts = { month, day, year };
|
|
1252
1284
|
const isCalendarPadding = day === null;
|
|
1253
|
-
const { isActive, isToday, ariaLabel, ariaSelected, disabled, text } = getCalendarDayState(this.locale, referenceParts, this.
|
|
1285
|
+
const { isActive, isToday, ariaLabel, ariaSelected, disabled, text } = getCalendarDayState(this.locale, referenceParts, this.activeParts, this.todayParts, this.minParts, this.maxParts, this.parsedDayValues);
|
|
1254
1286
|
const dateIsoString = convertDataToISO(referenceParts);
|
|
1255
1287
|
let isCalDayDisabled = isCalMonthDisabled || disabled;
|
|
1256
1288
|
if (!isCalDayDisabled && isDateEnabled !== undefined) {
|
|
@@ -1274,14 +1306,30 @@ export class Datetime {
|
|
|
1274
1306
|
if (highlightedDates !== undefined && !isActive && day !== null) {
|
|
1275
1307
|
dateStyle = getHighlightStyles(highlightedDates, dateIsoString, el);
|
|
1276
1308
|
}
|
|
1277
|
-
|
|
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: {
|
|
1278
1328
|
'calendar-day-padding': isCalendarPadding,
|
|
1279
1329
|
'calendar-day': true,
|
|
1280
1330
|
'calendar-day-active': isActive,
|
|
1281
1331
|
'calendar-day-today': isToday,
|
|
1282
|
-
},
|
|
1283
|
-
color: dateStyle.textColor,
|
|
1284
|
-
}, "aria-hidden": isCalendarPadding ? 'true' : null, "aria-selected": ariaSelected, "aria-label": ariaLabel, onClick: () => {
|
|
1332
|
+
}, part: dateParts, "aria-hidden": isCalendarPadding ? 'true' : null, "aria-selected": ariaSelected, "aria-label": ariaLabel, onClick: () => {
|
|
1285
1333
|
if (isCalendarPadding) {
|
|
1286
1334
|
return;
|
|
1287
1335
|
}
|
|
@@ -1301,13 +1349,12 @@ export class Datetime {
|
|
|
1301
1349
|
day,
|
|
1302
1350
|
year }));
|
|
1303
1351
|
}
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
} }), text));
|
|
1352
|
+
}
|
|
1353
|
+
}, text)));
|
|
1307
1354
|
}))));
|
|
1308
1355
|
}
|
|
1309
1356
|
renderCalendarBody() {
|
|
1310
|
-
return (h("div", { class: "calendar-body ion-focusable", ref: (el) => (this.calendarBodyRef = el), tabindex: "0" }, generateMonths(this.workingParts).map(({ month, year }) => {
|
|
1357
|
+
return (h("div", { class: "calendar-body ion-focusable", ref: (el) => (this.calendarBodyRef = el), tabindex: "0" }, generateMonths(this.workingParts, this.forceRenderDate).map(({ month, year }) => {
|
|
1311
1358
|
return this.renderMonth(month, year);
|
|
1312
1359
|
})));
|
|
1313
1360
|
}
|
|
@@ -1462,14 +1509,13 @@ export class Datetime {
|
|
|
1462
1509
|
}
|
|
1463
1510
|
}
|
|
1464
1511
|
render() {
|
|
1465
|
-
const { name, value, disabled, el, color, readonly, showMonthAndYear, preferWheel, presentation, size } = this;
|
|
1512
|
+
const { name, value, disabled, el, color, readonly, showMonthAndYear, preferWheel, presentation, size, isGridStyle, } = this;
|
|
1466
1513
|
const mode = getIonMode(this);
|
|
1467
1514
|
const isMonthAndYearPresentation = presentation === 'year' || presentation === 'month' || presentation === 'month-year';
|
|
1468
1515
|
const shouldShowMonthAndYear = showMonthAndYear || isMonthAndYearPresentation;
|
|
1469
1516
|
const monthYearPickerOpen = showMonthAndYear && !isMonthAndYearPresentation;
|
|
1470
1517
|
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
|
1471
1518
|
const hasWheelVariant = hasDatePresentation && preferWheel;
|
|
1472
|
-
const hasGrid = hasDatePresentation && !preferWheel;
|
|
1473
1519
|
renderHiddenInput(true, el, name, formatValue(value), disabled);
|
|
1474
1520
|
return (h(Host, { "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
|
|
1475
1521
|
[mode]: true,
|
|
@@ -1480,7 +1526,7 @@ export class Datetime {
|
|
|
1480
1526
|
[`datetime-presentation-${presentation}`]: true,
|
|
1481
1527
|
[`datetime-size-${size}`]: true,
|
|
1482
1528
|
[`datetime-prefer-wheel`]: hasWheelVariant,
|
|
1483
|
-
[`datetime-grid`]:
|
|
1529
|
+
[`datetime-grid`]: isGridStyle,
|
|
1484
1530
|
})) }, this.renderDatetime(mode)));
|
|
1485
1531
|
}
|
|
1486
1532
|
static get is() { return "ion-datetime"; }
|
|
@@ -2039,7 +2085,8 @@ export class Datetime {
|
|
|
2039
2085
|
"showMonthAndYear": {},
|
|
2040
2086
|
"activeParts": {},
|
|
2041
2087
|
"workingParts": {},
|
|
2042
|
-
"isTimePopoverOpen": {}
|
|
2088
|
+
"isTimePopoverOpen": {},
|
|
2089
|
+
"forceRenderDate": {}
|
|
2043
2090
|
};
|
|
2044
2091
|
}
|
|
2045
2092
|
static get events() {
|
|
@@ -2267,9 +2314,6 @@ export class Datetime {
|
|
|
2267
2314
|
}, {
|
|
2268
2315
|
"propName": "minuteValues",
|
|
2269
2316
|
"methodName": "minuteValuesChanged"
|
|
2270
|
-
}, {
|
|
2271
|
-
"propName": "activeParts",
|
|
2272
|
-
"methodName": "activePartsChanged"
|
|
2273
2317
|
}, {
|
|
2274
2318
|
"propName": "value",
|
|
2275
2319
|
"methodName": "valueChanged"
|
|
@@ -281,6 +281,8 @@ ion-picker-column-internal {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
:host .calendar-body .calendar-month {
|
|
284
|
+
display: flex;
|
|
285
|
+
flex-flow: column;
|
|
284
286
|
/**
|
|
285
287
|
* Swiping should snap to at
|
|
286
288
|
* most one month at a time.
|
|
@@ -314,11 +316,21 @@ ion-picker-column-internal {
|
|
|
314
316
|
grid-template-columns: repeat(7, 1fr);
|
|
315
317
|
}
|
|
316
318
|
|
|
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
|
+
|
|
317
328
|
/**
|
|
318
329
|
* Center the day text vertically
|
|
319
330
|
* and horizontally within its grid cell.
|
|
320
331
|
*/
|
|
321
332
|
:host .calendar-day {
|
|
333
|
+
border-radius: 50%;
|
|
322
334
|
-webkit-padding-start: 0px;
|
|
323
335
|
padding-inline-start: 0px;
|
|
324
336
|
-webkit-padding-end: 0px;
|
|
@@ -350,18 +362,9 @@ ion-picker-column-internal {
|
|
|
350
362
|
opacity: 0.4;
|
|
351
363
|
}
|
|
352
364
|
|
|
353
|
-
.calendar-day
|
|
354
|
-
|
|
355
|
-
-
|
|
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;
|
|
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);
|
|
365
368
|
}
|
|
366
369
|
|
|
367
370
|
:host .datetime-time {
|
|
@@ -480,30 +483,19 @@ ion-picker-column-internal {
|
|
|
480
483
|
}
|
|
481
484
|
|
|
482
485
|
:host .calendar-day {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
padding-inline-end: 0;
|
|
487
|
-
padding-top: 13px;
|
|
488
|
-
padding-bottom: 13px;
|
|
486
|
+
width: 42px;
|
|
487
|
+
min-width: 42px;
|
|
488
|
+
height: 42px;
|
|
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
|
-
|
|
497
492
|
/**
|
|
498
493
|
* Day that today but not selected
|
|
499
494
|
* should have ion-color for text color.
|
|
500
495
|
*/
|
|
501
496
|
:host .calendar-day.calendar-day-today {
|
|
502
|
-
color: var(--ion-color-base);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
.calendar-day.calendar-day-today .calendar-day-highlight {
|
|
506
497
|
border: 1px solid var(--ion-color-base);
|
|
498
|
+
color: var(--ion-color-base);
|
|
507
499
|
}
|
|
508
500
|
|
|
509
501
|
/**
|
|
@@ -515,7 +507,7 @@ ion-picker-column-internal {
|
|
|
515
507
|
color: var(--ion-color-contrast);
|
|
516
508
|
}
|
|
517
509
|
|
|
518
|
-
.calendar-day.calendar-day-active
|
|
510
|
+
.calendar-day.calendar-day-active {
|
|
519
511
|
border: 1px solid var(--ion-color-base);
|
|
520
512
|
background: var(--ion-color-base);
|
|
521
513
|
}
|
|
@@ -348,3 +348,28 @@ 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('
|
|
13
|
+
const datetime = page.locator('#color-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('
|
|
16
|
+
const timeButton = page.locator('#custom-grid .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,5 +22,31 @@ 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
|
+
});
|
|
25
51
|
});
|
|
26
52
|
});
|
|
@@ -184,6 +184,21 @@ 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
|
+
});
|
|
187
202
|
test.describe('datetime: date wheel localization', () => {
|
|
188
203
|
test('should correctly localize the date data', async ({ page }) => {
|
|
189
204
|
await page.setContent(`
|
|
@@ -30,24 +30,21 @@ 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');
|
|
36
33
|
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();
|
|
46
34
|
await page.waitForChanges();
|
|
47
35
|
// Check that correct day is highlighted
|
|
48
36
|
await expect(activeDayButton).toHaveAttribute('data-day', '5');
|
|
49
37
|
await expect(activeDayButton).toHaveAttribute('data-month', '10');
|
|
50
38
|
await expect(activeDayButton).toHaveAttribute('data-year', '2021');
|
|
51
39
|
});
|
|
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
|
+
});
|
|
52
49
|
});
|
|
53
50
|
});
|