`,
inputs: [
'animated',
+ 'keepContentsMounted',
'backdropBreakpoint',
'backdropDismiss',
'breakpoints',
@@ -89,6 +94,7 @@ export declare interface IonModal extends Components.IonModal {
'enterAnimation',
'event',
'handle',
+ 'handleBehavior',
'initialBreakpoint',
'isOpen',
'keyboardClose',
diff --git a/angular/src/directives/overlays/popover.ts b/angular/src/directives/overlays/popover.ts
index 0bcf5f7e26..aedbb97f9c 100644
--- a/angular/src/directives/overlays/popover.ts
+++ b/angular/src/directives/overlays/popover.ts
@@ -51,6 +51,7 @@ export declare interface IonPopover extends Components.IonPopover {
'alignment',
'animated',
'arrow',
+ 'keepContentsMounted',
'backdropDismiss',
'cssClass',
'dismissOnSelect',
@@ -73,11 +74,12 @@ export declare interface IonPopover extends Components.IonPopover {
@Component({
selector: 'ion-popover',
changeDetection: ChangeDetectionStrategy.OnPush,
- template: ``,
+ template: ``,
inputs: [
'alignment',
'animated',
'arrow',
+ 'keepContentsMounted',
'backdropDismiss',
'cssClass',
'dismissOnSelect',
diff --git a/angular/src/directives/proxies-list.txt b/angular/src/directives/proxies-list.txt
index 1ec13c5c85..06d60e7c6f 100644
--- a/angular/src/directives/proxies-list.txt
+++ b/angular/src/directives/proxies-list.txt
@@ -23,6 +23,7 @@ export const DIRECTIVES = [
d.IonCol,
d.IonContent,
d.IonDatetime,
+ d.IonDatetimeButton,
d.IonFab,
d.IonFabButton,
d.IonFabList,
diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts
index 69aa81283b..f600ad7fde 100644
--- a/angular/src/directives/proxies.ts
+++ b/angular/src/directives/proxies.ts
@@ -524,14 +524,14 @@ export declare interface IonDatetime extends Components.IonDatetime {
@ProxyCmp({
defineCustomElementFn: undefined,
- inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'name', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'value', 'yearValues'],
+ inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'value', 'yearValues'],
methods: ['confirm', 'reset', 'cancel']
})
@Component({
selector: 'ion-datetime',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
- inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'name', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'value', 'yearValues']
+ inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'value', 'yearValues']
})
export class IonDatetime {
protected el: HTMLElement;
@@ -543,6 +543,27 @@ export class IonDatetime {
}
+export declare interface IonDatetimeButton extends Components.IonDatetimeButton {}
+
+@ProxyCmp({
+ defineCustomElementFn: undefined,
+ inputs: ['color', 'datetime', 'disabled', 'mode']
+})
+@Component({
+ selector: 'ion-datetime-button',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ template: '',
+ inputs: ['color', 'datetime', 'disabled', 'mode']
+})
+export class IonDatetimeButton {
+ protected el: HTMLElement;
+ constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
+ c.detach();
+ this.el = r.nativeElement;
+ }
+}
+
+
export declare interface IonFab extends Components.IonFab {}
@ProxyCmp({
@@ -1304,13 +1325,13 @@ mouse drag, touch gesture, or keyboard interaction.
@ProxyCmp({
defineCustomElementFn: undefined,
- inputs: ['color', 'debounce', 'disabled', 'dualKnobs', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
+ inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
})
@Component({
selector: 'ion-range',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
- inputs: ['color', 'debounce', 'disabled', 'dualKnobs', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
+ inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
})
export class IonRange {
protected el: HTMLElement;
@@ -1979,13 +2000,13 @@ export declare interface IonToggle extends Components.IonToggle {
@ProxyCmp({
defineCustomElementFn: undefined,
- inputs: ['checked', 'color', 'disabled', 'mode', 'name', 'value']
+ inputs: ['checked', 'color', 'disabled', 'enableOnOffLabels', 'mode', 'name', 'value']
})
@Component({
selector: 'ion-toggle',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
- inputs: ['checked', 'color', 'disabled', 'mode', 'name', 'value']
+ inputs: ['checked', 'color', 'disabled', 'enableOnOffLabels', 'mode', 'name', 'value']
})
export class IonToggle {
protected el: HTMLElement;
diff --git a/angular/test/test-app/e2e/src/keep-contents-mounted.spec.ts b/angular/test/test-app/e2e/src/keep-contents-mounted.spec.ts
new file mode 100644
index 0000000000..a4bc99167f
--- /dev/null
+++ b/angular/test/test-app/e2e/src/keep-contents-mounted.spec.ts
@@ -0,0 +1,60 @@
+describe('overlays - keepContentsMounted', () => {
+ describe('modal', () => {
+ it('should not mount component if false', () => {
+ cy.visit('/modal-inline');
+
+ cy.get('ion-modal ion-content').should('not.exist');
+ });
+
+ it('should mount component if true', () => {
+ cy.visit('/keep-contents-mounted');
+
+ cy.get('ion-modal ion-content').should('exist');
+ });
+
+ it('should keep component mounted after dismissing if true', () => {
+ cy.visit('/keep-contents-mounted');
+
+ cy.get('#open-modal').click();
+
+ cy.get('ion-modal ion-content').should('exist');
+
+ cy.get('ion-modal ion-button').click();
+
+ cy.get('ion-modal')
+ .should('not.be.visible')
+ .should('have.class', 'overlay-hidden');
+
+ cy.get('ion-modal ion-content').should('exist');
+ });
+ })
+ describe('popover', () => {
+ it('should not mount component if false', () => {
+ cy.visit('/popover-inline');
+
+ cy.get('ion-popover ion-content').should('not.exist');
+ });
+
+ it('should mount component if true', () => {
+ cy.visit('/keep-contents-mounted');
+
+ cy.get('ion-popover ion-content').should('exist');
+ });
+
+ it('should keep component mounted after dismissing if true', () => {
+ cy.visit('/keep-contents-mounted');
+
+ cy.get('#open-popover').click();
+
+ cy.get('ion-popover ion-content').should('exist');
+
+ cy.get('ion-popover ion-button').click();
+
+ cy.get('ion-popover')
+ .should('not.be.visible')
+ .should('have.class', 'overlay-hidden');
+
+ cy.get('ion-popover ion-content').should('exist');
+ });
+ });
+});
diff --git a/angular/test/test-app/e2e/src/popover.spec.ts b/angular/test/test-app/e2e/src/popover.spec.ts
index abf1c06fa1..17f8fe6445 100644
--- a/angular/test/test-app/e2e/src/popover.spec.ts
+++ b/angular/test/test-app/e2e/src/popover.spec.ts
@@ -4,10 +4,17 @@ describe('Popovers: Inline', () => {
});
it('should initially have no items', () => {
+ cy.get('ion-button').click();
+
+ cy.get('ion-popover').should('be.visible');
cy.get('ion-list ion-item').should('not.exist');
});
it('should have items after 1500ms', () => {
+ cy.get('ion-button').click();
+
+ cy.get('ion-popover').should('be.visible');
+
cy.wait(1500);
cy.get('ion-list ion-item:nth-child(1)').should('have.text', 'A');
diff --git a/angular/test/test-app/src/app/app-routing.module.ts b/angular/test/test-app/src/app/app-routing.module.ts
index be5ad94bb5..6ffdfd8d32 100644
--- a/angular/test/test-app/src/app/app-routing.module.ts
+++ b/angular/test/test-app/src/app/app-routing.module.ts
@@ -31,6 +31,7 @@ const routes: Routes = [
{ path: 'modals', component: ModalComponent },
{ path: 'modal-inline', loadChildren: () => import('./modal-inline').then(m => m.ModalInlineModule) },
{ path: 'view-child', component: ViewChildComponent },
+ { path: 'keep-contents-mounted', loadChildren: () => import('./keep-contents-mounted').then(m => m.OverlayAutoMountModule) },
{ path: 'popover-inline', loadChildren: () => import('./popover-inline').then(m => m.PopoverInlineModule) },
{ path: 'providers', component: ProvidersComponent },
{ path: 'router-link', component: RouterLinkComponent },
diff --git a/angular/test/test-app/src/app/keep-contents-mounted/index.ts b/angular/test/test-app/src/app/keep-contents-mounted/index.ts
new file mode 100644
index 0000000000..c949db9a98
--- /dev/null
+++ b/angular/test/test-app/src/app/keep-contents-mounted/index.ts
@@ -0,0 +1,2 @@
+export * from './keep-contents-mounted.component';
+export * from './keep-contents-mounted.module';
diff --git a/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted-routing.module.ts b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted-routing.module.ts
new file mode 100644
index 0000000000..e453cb212e
--- /dev/null
+++ b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted-routing.module.ts
@@ -0,0 +1,16 @@
+import { NgModule } from "@angular/core";
+import { RouterModule } from "@angular/router";
+import { OverlayKeepContentsMounted } from ".";
+
+@NgModule({
+ imports: [
+ RouterModule.forChild([
+ {
+ path: '',
+ component: OverlayKeepContentsMounted
+ }
+ ])
+ ],
+ exports: [RouterModule]
+})
+export class OverlayKeepContentsMountedRoutingModule { }
diff --git a/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.html b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.html
new file mode 100644
index 0000000000..8311ecd5a7
--- /dev/null
+++ b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.html
@@ -0,0 +1,22 @@
+
+ Open Modal
+ Open Popover
+
+
+
+
+ Dismiss
+ Modal Content
+
+
+
+
+
+
+
+ Dismiss
+ Popover Content
+
+
+
+
diff --git a/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.ts b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.ts
new file mode 100644
index 0000000000..ccf0e90165
--- /dev/null
+++ b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.ts
@@ -0,0 +1,13 @@
+import { Component } from "@angular/core";
+
+/**
+ * Validates that inline modals correctly mount
+ * inner components when keepContentsMounted is
+ * enabled.
+ */
+@Component({
+ selector: 'app-keep-contents-mounted',
+ templateUrl: 'keep-contents-mounted.component.html'
+})
+export class OverlayKeepContentsMounted {
+}
diff --git a/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.module.ts b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.module.ts
new file mode 100644
index 0000000000..265e850126
--- /dev/null
+++ b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.module.ts
@@ -0,0 +1,12 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { IonicModule } from "@ionic/angular";
+import { OverlayKeepContentsMountedRoutingModule } from "./keep-contents-mounted-routing.module";
+import { OverlayKeepContentsMounted } from "./keep-contents-mounted.component";
+
+@NgModule({
+ imports: [CommonModule, IonicModule, OverlayKeepContentsMountedRoutingModule],
+ declarations: [OverlayKeepContentsMounted],
+ exports: [OverlayKeepContentsMounted]
+})
+export class OverlayAutoMountModule { }
diff --git a/angular/test/test-app/src/app/popover-inline/popover-inline.component.html b/angular/test/test-app/src/app/popover-inline/popover-inline.component.html
index 1de4bc20af..f4f311646c 100644
--- a/angular/test/test-app/src/app/popover-inline/popover-inline.component.html
+++ b/angular/test/test-app/src/app/popover-inline/popover-inline.component.html
@@ -1,4 +1,6 @@
-
+Open Popover
+
+
diff --git a/angular/test/test-app/src/app/popover-inline/popover-inline.component.ts b/angular/test/test-app/src/app/popover-inline/popover-inline.component.ts
index d162795795..36e472900c 100644
--- a/angular/test/test-app/src/app/popover-inline/popover-inline.component.ts
+++ b/angular/test/test-app/src/app/popover-inline/popover-inline.component.ts
@@ -1,4 +1,4 @@
-import { AfterViewInit, Component } from "@angular/core";
+import { Component } from "@angular/core";
/**
* Validates that inline popovers will correctly display
@@ -9,11 +9,13 @@ import { AfterViewInit, Component } from "@angular/core";
selector: 'app-popover-inline',
templateUrl: 'popover-inline.component.html'
})
-export class PopoverInlineComponent implements AfterViewInit {
+export class PopoverInlineComponent {
items: string[] = [];
- ngAfterViewInit(): void {
+ openPopover(popover: HTMLIonPopoverElement) {
+ popover.present();
+
setTimeout(() => {
this.items = ['A', 'B', 'C', 'D'];
}, 1000);
diff --git a/core/api.txt b/core/api.txt
index 0c5bcdcf33..8a7ed74c34 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -387,7 +387,9 @@ ion-datetime,prop,min,string | undefined,undefined,false,false
ion-datetime,prop,minuteValues,number | number[] | string | undefined,undefined,false,false
ion-datetime,prop,mode,"ios" | "md",undefined,false,false
ion-datetime,prop,monthValues,number | number[] | string | undefined,undefined,false,false
+ion-datetime,prop,multiple,boolean,false,false,false
ion-datetime,prop,name,string,this.inputId,false,false
+ion-datetime,prop,preferWheel,boolean,false,false,false
ion-datetime,prop,presentation,"date" | "date-time" | "month" | "month-year" | "time" | "time-date" | "year",'date-time',false,false
ion-datetime,prop,readonly,boolean,false,false,false
ion-datetime,prop,showClearButton,boolean,false,false,false
@@ -395,7 +397,7 @@ ion-datetime,prop,showDefaultButtons,boolean,false,false,false
ion-datetime,prop,showDefaultTimeLabel,boolean,true,false,false
ion-datetime,prop,showDefaultTitle,boolean,false,false,false
ion-datetime,prop,size,"cover" | "fixed",'fixed',false,false
-ion-datetime,prop,value,null | string | undefined,undefined,false,false
+ion-datetime,prop,value,null | string | string[] | undefined,undefined,false,false
ion-datetime,prop,yearValues,number | number[] | string | undefined,undefined,false,false
ion-datetime,method,cancel,cancel(closeOverlay?: boolean) => Promise
ion-datetime,method,confirm,confirm(closeOverlay?: boolean) => Promise
@@ -408,6 +410,13 @@ ion-datetime,css-prop,--background
ion-datetime,css-prop,--background-rgb
ion-datetime,css-prop,--title-color
+ion-datetime-button,shadow
+ion-datetime-button,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,'primary',false,true
+ion-datetime-button,prop,datetime,string | undefined,undefined,false,false
+ion-datetime-button,prop,disabled,boolean,false,false,true
+ion-datetime-button,prop,mode,"ios" | "md",undefined,false,false
+ion-datetime-button,part,native
+
ion-fab,shadow
ion-fab,prop,activated,boolean,false,false,false
ion-fab,prop,edge,boolean,false,false,false
@@ -772,9 +781,11 @@ ion-modal,prop,breakpoints,number[] | undefined,undefined,false,false
ion-modal,prop,canDismiss,(() => Promise) | boolean | undefined,undefined,false,false
ion-modal,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-modal,prop,handle,boolean | undefined,undefined,false,false
+ion-modal,prop,handleBehavior,"cycle" | "none" | undefined,'none',false,false
ion-modal,prop,htmlAttributes,undefined | { [key: string]: any; },undefined,false,false
ion-modal,prop,initialBreakpoint,number | undefined,undefined,false,false
ion-modal,prop,isOpen,boolean,false,false,false
+ion-modal,prop,keepContentsMounted,boolean,false,false,false
ion-modal,prop,keyboardClose,boolean,true,false,false
ion-modal,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-modal,prop,mode,"ios" | "md",undefined,false,false
@@ -894,6 +905,7 @@ ion-popover,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undef
ion-popover,prop,event,any,undefined,false,false
ion-popover,prop,htmlAttributes,undefined | { [key: string]: any; },undefined,false,false
ion-popover,prop,isOpen,boolean,false,false,false
+ion-popover,prop,keepContentsMounted,boolean,false,false,false
ion-popover,prop,keyboardClose,boolean,true,false,false
ion-popover,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-popover,prop,mode,"ios" | "md",undefined,false,false
@@ -967,6 +979,7 @@ ion-radio-group,prop,value,any,undefined,false,false
ion-radio-group,event,ionChange,RadioGroupChangeEventDetail,true
ion-range,shadow
+ion-range,prop,activeBarStart,number | undefined,undefined,false,false
ion-range,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true
ion-range,prop,debounce,number,0,false,false
ion-range,prop,disabled,boolean,false,false,false
@@ -1413,6 +1426,7 @@ ion-toggle,shadow
ion-toggle,prop,checked,boolean,false,false,false
ion-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true
ion-toggle,prop,disabled,boolean,false,false,false
+ion-toggle,prop,enableOnOffLabels,boolean | undefined,undefined,false,false
ion-toggle,prop,mode,"ios" | "md",undefined,false,false
ion-toggle,prop,name,string,this.inputId,false,false
ion-toggle,prop,value,null | string | undefined,'on',false,false
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 2a8d858022..f2b1fbe72e 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -5,7 +5,7 @@
* It contains typing information for all components that exist in this project.
*/
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
-import { AccordionGroupChangeEventDetail, ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, BreadcrumbCollapsedClickEventDetail, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, ModalBreakpointChangeEventDetail, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, PopoverSize, PositionAlign, PositionReference, PositionSide, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, TriggerAction, ViewController } from "./interface";
+import { AccordionGroupChangeEventDetail, ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, BreadcrumbCollapsedClickEventDetail, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimePresentation, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, ModalBreakpointChangeEventDetail, ModalHandleBehavior, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, PopoverSize, PositionAlign, PositionReference, PositionSide, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, TriggerAction, ViewController } from "./interface";
import { IonicSafeString } from "./utils/sanitization";
import { AlertAttributes } from "./components/alert/alert-interface";
import { CounterFormatter } from "./components/item/item-interface";
@@ -785,14 +785,22 @@ export namespace Components {
* Values used to create the list of selectable months. By default the month values range from `1` to `12`. However, to control exactly which months to display, the `monthValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if only summer months should be shown, then this input value would be `monthValues="6,7,8"`. Note that month numbers do *not* have a zero-based index, meaning January's value is `1`, and December's is `12`.
*/
"monthValues"?: number[] | number | string;
+ /**
+ * If `true`, multiple dates can be selected at once. Only applies to `presentation="date"` and `preferWheel="false"`.
+ */
+ "multiple": boolean;
/**
* The name of the control, which is submitted with the form data.
*/
"name": string;
+ /**
+ * If `true`, a wheel picker will be rendered instead of a calendar grid where possible. If `false`, a calendar grid will be rendered instead of a wheel picker where possible. A wheel picker can be rendered instead of a grid when `presentation` is one of the following values: `'date'`, `'date-time'`, or `'time-date'`. A wheel picker will always be rendered regardless of the `preferWheel` value when `presentation` is one of the following values: `'time'`, `'month'`, `'month-year'`, or `'year'`.
+ */
+ "preferWheel": boolean;
/**
* Which values you want to select. `'date'` will show a calendar picker to select the month, day, and year. `'time'` will show a time picker to select the hour, minute, and (optionally) AM/PM. `'date-time'` will show the date picker first and time picker second. `'time-date'` will show the time picker first and date picker second.
*/
- "presentation": 'date-time' | 'time-date' | 'date' | 'time' | 'month' | 'year' | 'month-year';
+ "presentation": DatetimePresentation;
/**
* If `true`, the datetime appears normal but is not interactive.
*/
@@ -822,14 +830,32 @@ export namespace Components {
*/
"size": 'cover' | 'fixed';
/**
- * The value of the datetime as a valid ISO 8601 datetime string.
+ * The value of the datetime as a valid ISO 8601 datetime string. Should be an array of strings if `multiple="true"`.
*/
- "value"?: string | null;
+ "value"?: string | string[] | null;
/**
* Values used to create the list of selectable years. By default the year values range between the `min` and `max` datetime inputs. However, to control exactly which years to display, the `yearValues` input can take a number, an array of numbers, or string of comma separated numbers. For example, to show upcoming and recent leap years, then this input's value would be `yearValues="2024,2020,2016,2012,2008"`.
*/
"yearValues"?: number[] | number | string;
}
+ interface IonDatetimeButton {
+ /**
+ * The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
+ */
+ "color"?: Color;
+ /**
+ * The ID of the `ion-datetime` instance associated with the datetime button.
+ */
+ "datetime"?: string;
+ /**
+ * If `true`, the user cannot interact with the button.
+ */
+ "disabled": boolean;
+ /**
+ * The mode determines which platform styles to use.
+ */
+ "mode"?: "ios" | "md";
+ }
interface IonFab {
/**
* If `true`, both the `ion-fab-button` and all `ion-fab-list` inside `ion-fab` will become active. That means `ion-fab-button` will become a `close` icon and `ion-fab-list` will become visible.
@@ -1554,6 +1580,10 @@ export namespace Components {
* The horizontal line that displays at the top of a sheet modal. It is `true` by default when setting the `breakpoints` and `initialBreakpoint` properties.
*/
"handle"?: boolean;
+ /**
+ * The interaction behavior for the sheet modal when the handle is pressed. Defaults to `"none"`, which means the modal will not change size or position when the handle is pressed. Set to `"cycle"` to let the modal cycle between available breakpoints when pressed. Handle behavior is unavailable when the `handle` property is set to `false` or when the `breakpoints` property is not set (using a fullscreen or card modal).
+ */
+ "handleBehavior"?: ModalHandleBehavior;
"hasController": boolean;
/**
* Additional attributes to pass to the modal.
@@ -1567,6 +1597,10 @@ export namespace Components {
* If `true`, the modal will open. If `false`, the modal will close. Use this if you need finer grained control over presentation, otherwise just use the modalController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the modal dismisses. You will need to do that in your code.
*/
"isOpen": boolean;
+ /**
+ * If `true`, the component passed into `ion-modal` will automatically be mounted when the modal is created. The component will remain mounted even when the modal is dismissed. However, the component will be destroyed when the modal is destroyed. This property is not reactive and should only be used when initially creating a modal. Note: This feature only applies to inline modals in JavaScript frameworks such as Angular, React, and Vue.
+ */
+ "keepContentsMounted": boolean;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -1936,6 +1970,10 @@ export namespace Components {
* If `true`, the popover will open. If `false`, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the popover dismisses. You will need to do that in your code.
*/
"isOpen": boolean;
+ /**
+ * If `true`, the component passed into `ion-popover` will automatically be mounted when the popover is created. The component will remain mounted even when the popover is dismissed. However, the component will be destroyed when the popover is destroyed. This property is not reactive and should only be used when initially creating a popover. Note: This feature only applies to inline popovers in JavaScript frameworks such as Angular, React, and Vue.
+ */
+ "keepContentsMounted": boolean;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -2060,6 +2098,10 @@ export namespace Components {
"value"?: any | null;
}
interface IonRange {
+ /**
+ * The start position of the range active bar. This feature is only available with a single knob (dualKnobs="false"). Valid values are greater than or equal to the min value and less than or equal to the max value.
+ */
+ "activeBarStart"?: number;
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
@@ -2967,6 +3009,10 @@ export namespace Components {
* If `true`, the user cannot interact with the toggle.
*/
"disabled": boolean;
+ /**
+ * Enables the on/off accessibility switch labels within the toggle.
+ */
+ "enableOnOffLabels": boolean | undefined;
/**
* The mode determines which platform styles to use.
*/
@@ -3385,6 +3431,12 @@ declare global {
prototype: HTMLIonDatetimeElement;
new (): HTMLIonDatetimeElement;
};
+ interface HTMLIonDatetimeButtonElement extends Components.IonDatetimeButton, HTMLStencilElement {
+ }
+ var HTMLIonDatetimeButtonElement: {
+ prototype: HTMLIonDatetimeButtonElement;
+ new (): HTMLIonDatetimeButtonElement;
+ };
interface HTMLIonFabElement extends Components.IonFab, HTMLStencilElement {
}
var HTMLIonFabElement: {
@@ -3829,6 +3881,7 @@ declare global {
"ion-col": HTMLIonColElement;
"ion-content": HTMLIonContentElement;
"ion-datetime": HTMLIonDatetimeElement;
+ "ion-datetime-button": HTMLIonDatetimeButtonElement;
"ion-fab": HTMLIonFabElement;
"ion-fab-button": HTMLIonFabButtonElement;
"ion-fab-list": HTMLIonFabListElement;
@@ -4688,6 +4741,10 @@ declare namespace LocalJSX {
* Values used to create the list of selectable months. By default the month values range from `1` to `12`. However, to control exactly which months to display, the `monthValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if only summer months should be shown, then this input value would be `monthValues="6,7,8"`. Note that month numbers do *not* have a zero-based index, meaning January's value is `1`, and December's is `12`.
*/
"monthValues"?: number[] | number | string;
+ /**
+ * If `true`, multiple dates can be selected at once. Only applies to `presentation="date"` and `preferWheel="false"`.
+ */
+ "multiple"?: boolean;
/**
* The name of the control, which is submitted with the form data.
*/
@@ -4708,14 +4765,22 @@ declare namespace LocalJSX {
* Emitted when the datetime has focus.
*/
"onIonFocus"?: (event: IonDatetimeCustomEvent) => void;
+ /**
+ * Emitted when componentDidRender is fired.
+ */
+ "onIonRender"?: (event: IonDatetimeCustomEvent) => void;
/**
* Emitted when the styles change.
*/
"onIonStyle"?: (event: IonDatetimeCustomEvent) => void;
+ /**
+ * If `true`, a wheel picker will be rendered instead of a calendar grid where possible. If `false`, a calendar grid will be rendered instead of a wheel picker where possible. A wheel picker can be rendered instead of a grid when `presentation` is one of the following values: `'date'`, `'date-time'`, or `'time-date'`. A wheel picker will always be rendered regardless of the `preferWheel` value when `presentation` is one of the following values: `'time'`, `'month'`, `'month-year'`, or `'year'`.
+ */
+ "preferWheel"?: boolean;
/**
* Which values you want to select. `'date'` will show a calendar picker to select the month, day, and year. `'time'` will show a time picker to select the hour, minute, and (optionally) AM/PM. `'date-time'` will show the date picker first and time picker second. `'time-date'` will show the time picker first and date picker second.
*/
- "presentation"?: 'date-time' | 'time-date' | 'date' | 'time' | 'month' | 'year' | 'month-year';
+ "presentation"?: DatetimePresentation;
/**
* If `true`, the datetime appears normal but is not interactive.
*/
@@ -4741,14 +4806,32 @@ declare namespace LocalJSX {
*/
"size"?: 'cover' | 'fixed';
/**
- * The value of the datetime as a valid ISO 8601 datetime string.
+ * The value of the datetime as a valid ISO 8601 datetime string. Should be an array of strings if `multiple="true"`.
*/
- "value"?: string | null;
+ "value"?: string | string[] | null;
/**
* Values used to create the list of selectable years. By default the year values range between the `min` and `max` datetime inputs. However, to control exactly which years to display, the `yearValues` input can take a number, an array of numbers, or string of comma separated numbers. For example, to show upcoming and recent leap years, then this input's value would be `yearValues="2024,2020,2016,2012,2008"`.
*/
"yearValues"?: number[] | number | string;
}
+ interface IonDatetimeButton {
+ /**
+ * The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
+ */
+ "color"?: Color;
+ /**
+ * The ID of the `ion-datetime` instance associated with the datetime button.
+ */
+ "datetime"?: string;
+ /**
+ * If `true`, the user cannot interact with the button.
+ */
+ "disabled"?: boolean;
+ /**
+ * The mode determines which platform styles to use.
+ */
+ "mode"?: "ios" | "md";
+ }
interface IonFab {
/**
* If `true`, both the `ion-fab-button` and all `ion-fab-list` inside `ion-fab` will become active. That means `ion-fab-button` will become a `close` icon and `ion-fab-list` will become visible.
@@ -5467,6 +5550,10 @@ declare namespace LocalJSX {
* The horizontal line that displays at the top of a sheet modal. It is `true` by default when setting the `breakpoints` and `initialBreakpoint` properties.
*/
"handle"?: boolean;
+ /**
+ * The interaction behavior for the sheet modal when the handle is pressed. Defaults to `"none"`, which means the modal will not change size or position when the handle is pressed. Set to `"cycle"` to let the modal cycle between available breakpoints when pressed. Handle behavior is unavailable when the `handle` property is set to `false` or when the `breakpoints` property is not set (using a fullscreen or card modal).
+ */
+ "handleBehavior"?: ModalHandleBehavior;
"hasController"?: boolean;
/**
* Additional attributes to pass to the modal.
@@ -5480,6 +5567,10 @@ declare namespace LocalJSX {
* If `true`, the modal will open. If `false`, the modal will close. Use this if you need finer grained control over presentation, otherwise just use the modalController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the modal dismisses. You will need to do that in your code.
*/
"isOpen"?: boolean;
+ /**
+ * If `true`, the component passed into `ion-modal` will automatically be mounted when the modal is created. The component will remain mounted even when the modal is dismissed. However, the component will be destroyed when the modal is destroyed. This property is not reactive and should only be used when initially creating a modal. Note: This feature only applies to inline modals in JavaScript frameworks such as Angular, React, and Vue.
+ */
+ "keepContentsMounted"?: boolean;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -5771,6 +5862,10 @@ declare namespace LocalJSX {
* If `true`, the popover will open. If `false`, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the popover dismisses. You will need to do that in your code.
*/
"isOpen"?: boolean;
+ /**
+ * If `true`, the component passed into `ion-popover` will automatically be mounted when the popover is created. The component will remain mounted even when the popover is dismissed. However, the component will be destroyed when the popover is destroyed. This property is not reactive and should only be used when initially creating a popover. Note: This feature only applies to inline popovers in JavaScript frameworks such as Angular, React, and Vue.
+ */
+ "keepContentsMounted"?: boolean;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -5925,6 +6020,10 @@ declare namespace LocalJSX {
"value"?: any | null;
}
interface IonRange {
+ /**
+ * The start position of the range active bar. This feature is only available with a single knob (dualKnobs="false"). Valid values are greater than or equal to the min value and less than or equal to the max value.
+ */
+ "activeBarStart"?: number;
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
@@ -6903,6 +7002,10 @@ declare namespace LocalJSX {
* If `true`, the user cannot interact with the toggle.
*/
"disabled"?: boolean;
+ /**
+ * Enables the on/off accessibility switch labels within the toggle.
+ */
+ "enableOnOffLabels"?: boolean | undefined;
/**
* The mode determines which platform styles to use.
*/
@@ -7021,6 +7124,7 @@ declare namespace LocalJSX {
"ion-col": IonCol;
"ion-content": IonContent;
"ion-datetime": IonDatetime;
+ "ion-datetime-button": IonDatetimeButton;
"ion-fab": IonFab;
"ion-fab-button": IonFabButton;
"ion-fab-list": IonFabList;
@@ -7120,6 +7224,7 @@ declare module "@stencil/core" {
"ion-col": LocalJSX.IonCol & JSXBase.HTMLAttributes;
"ion-content": LocalJSX.IonContent & JSXBase.HTMLAttributes;
"ion-datetime": LocalJSX.IonDatetime & JSXBase.HTMLAttributes;
+ "ion-datetime-button": LocalJSX.IonDatetimeButton & JSXBase.HTMLAttributes;
"ion-fab": LocalJSX.IonFab & JSXBase.HTMLAttributes;
"ion-fab-button": LocalJSX.IonFabButton & JSXBase.HTMLAttributes;
"ion-fab-list": LocalJSX.IonFabList & JSXBase.HTMLAttributes;
diff --git a/core/src/components/accordion/test/standalone/accordion.e2e.ts b/core/src/components/accordion/test/standalone/accordion.e2e.ts
index 46470182e8..48bb7327ba 100644
--- a/core/src/components/accordion/test/standalone/accordion.e2e.ts
+++ b/core/src/components/accordion/test/standalone/accordion.e2e.ts
@@ -11,7 +11,8 @@ test.describe('accordion: standalone', () => {
expect(results.violations).toEqual([]);
});
- test('should not have visual regressions', async ({ page }) => {
+ // TODO(FW-1842) Re-enable when flakiness has been addressed.
+ test.skip('should not have visual regressions', async ({ page }) => {
await page.goto(`/src/components/accordion/test/standalone`);
expect(await page.screenshot({ fullPage: true })).toMatchSnapshot(
diff --git a/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-ios-ltr-Mobile-Safari-linux.png b/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-ios-ltr-Mobile-Safari-linux.png
index 497cfb1a56..1c985494d6 100644
Binary files a/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-ios-rtl-Mobile-Safari-linux.png b/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-ios-rtl-Mobile-Safari-linux.png
index 91980dc95c..fe09385354 100644
Binary files a/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-md-rtl-Mobile-Safari-linux.png b/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-md-rtl-Mobile-Safari-linux.png
index 2b21eb8dad..10fd895d34 100644
Binary files a/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-md-rtl-Mobile-Safari-linux.png and b/core/src/components/accordion/test/standalone/accordion.e2e.ts-snapshots/accordion-standalone-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/datetime-button.scss b/core/src/components/datetime-button/datetime-button.scss
new file mode 100644
index 0000000000..3a87b88128
--- /dev/null
+++ b/core/src/components/datetime-button/datetime-button.scss
@@ -0,0 +1,50 @@
+@import "../../themes/ionic.globals";
+
+// Datetime Button
+// --------------------------------------------------
+
+:host {
+ display: flex;
+
+ align-items: center;
+
+ justify-content: center;
+}
+
+:host button {
+ @include border-radius(8px);
+ @include padding(6px, 12px, 6px, 12px);
+ @include margin(0px, 2px, 0px, 2px);
+
+ position: relative;
+
+ transition: 150ms color ease-in-out;
+
+ border: none;
+
+ background: var(--ion-color-step-300, #edeef0);
+
+ color: $text-color;
+
+ font-family: inherit;
+ font-size: inherit;
+
+ cursor: pointer;
+
+ appearance: none;
+
+ overflow: hidden;
+}
+
+:host(.time-active) #time-button,
+:host(.date-active) #date-button {
+ color: current-color(base);
+}
+
+:host(.datetime-button-disabled) {
+ pointer-events: none;
+}
+
+:host(.datetime-button-disabled) button {
+ opacity: 0.4;
+}
diff --git a/core/src/components/datetime-button/datetime-button.tsx b/core/src/components/datetime-button/datetime-button.tsx
new file mode 100644
index 0000000000..a5536f4738
--- /dev/null
+++ b/core/src/components/datetime-button/datetime-button.tsx
@@ -0,0 +1,414 @@
+import type { ComponentInterface } from '@stencil/core';
+import { Component, Element, Host, Prop, State, h } from '@stencil/core';
+
+import { getIonMode } from '../../global/ionic-global';
+import type { Color, DatetimePresentation, DatetimeParts } from '../../interface';
+import { componentOnReady, addEventListener } from '../../utils/helpers';
+import { printIonError, printIonWarning } from '../../utils/logging';
+import { createColorClasses } from '../../utils/theme';
+import { getToday } from '../datetime/utils/data';
+import { getMonthAndYear, getMonthDayAndYear, getLocalizedDateTime, getLocalizedTime } from '../datetime/utils/format';
+import { is24Hour } from '../datetime/utils/helpers';
+import { parseDate } from '../datetime/utils/parse';
+/**
+ * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
+ *
+ * @slot date-target - Content displayed inside of the date button.
+ * @slot time-target - Content displayed inside of the time button.
+ *
+ * @part native - The native HTML button that wraps the slotted text.
+ */
+@Component({
+ tag: 'ion-datetime-button',
+ styleUrls: {
+ ios: 'datetime-button.scss',
+ md: 'datetime-button.scss',
+ },
+ shadow: true,
+})
+export class DatetimeButton implements ComponentInterface {
+ private datetimeEl: HTMLIonDatetimeElement | null = null;
+ private overlayEl: HTMLIonModalElement | HTMLIonPopoverElement | null = null;
+ private dateTargetEl: HTMLElement | undefined;
+ private timeTargetEl: HTMLElement | undefined;
+
+ @Element() el!: HTMLIonDatetimeButtonElement;
+
+ @State() datetimePresentation?: DatetimePresentation = 'date-time';
+ @State() dateText?: string;
+ @State() timeText?: string;
+ @State() datetimeActive = false;
+ @State() selectedButton?: 'date' | 'time';
+
+ /**
+ * The color to use from your application's color palette.
+ * Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
+ * For more information on colors, see [theming](/docs/theming/basics).
+ */
+ @Prop({ reflect: true }) color?: Color = 'primary';
+
+ /**
+ * If `true`, the user cannot interact with the button.
+ */
+ @Prop({ reflect: true }) disabled = false;
+
+ /**
+ * The ID of the `ion-datetime` instance
+ * associated with the datetime button.
+ */
+ @Prop() datetime?: string;
+
+ async componentWillLoad() {
+ const { datetime } = this;
+ if (!datetime) {
+ printIonError(
+ 'An ID associated with an ion-datetime instance is required for ion-datetime-button to function properly.',
+ this.el
+ );
+ return;
+ }
+
+ const datetimeEl = (this.datetimeEl = document.getElementById(datetime) as HTMLIonDatetimeElement | null);
+ if (!datetimeEl) {
+ printIonError(`No ion-datetime instance found for ID '${datetime}'.`, this.el);
+ return;
+ }
+
+ /**
+ * Since the datetime can be used in any context (overlays, accordion, etc)
+ * we track when it is visible to determine when it is active.
+ * This informs which button is highlighted as well as the
+ * aria-expanded state.
+ */
+ const io = new IntersectionObserver(
+ (entries: IntersectionObserverEntry[]) => {
+ const ev = entries[0];
+ this.datetimeActive = ev.isIntersecting;
+ },
+ {
+ threshold: 0.01,
+ }
+ );
+
+ io.observe(datetimeEl);
+
+ /**
+ * Get a reference to any modal/popover
+ * the datetime is being used in so we can
+ * correctly size it when it is presented.
+ */
+ const overlayEl = (this.overlayEl = datetimeEl.closest('ion-modal, ion-popover'));
+
+ /**
+ * The .ion-datetime-button-overlay class contains
+ * styles that allow any modal/popover to be
+ * sized according to the dimensions of the datetime.
+ * If developers want a smaller/larger overlay all they need
+ * to do is change the width/height of the datetime.
+ * Additionally, this lets us avoid having to set
+ * explicit widths on each variant of datetime.
+ */
+ if (overlayEl) {
+ overlayEl.classList.add('ion-datetime-button-overlay');
+ }
+
+ componentOnReady(datetimeEl, () => {
+ const datetimePresentation = (this.datetimePresentation = datetimeEl.presentation || 'date-time');
+
+ /**
+ * Set the initial display
+ * in the rendered buttons.
+ *
+ * From there, we need to listen
+ * for ionChange to be emitted
+ * from datetime so we know when
+ * to re-render the displayed
+ * text in the buttons.
+ */
+ this.setDateTimeText();
+ addEventListener(datetimeEl, 'ionChange', this.setDateTimeText);
+
+ /**
+ * Configure the initial selected button
+ * in the event that the datetime is displayed
+ * without clicking one of the datetime buttons.
+ * For example, a datetime could be expanded
+ * in an accordion. In this case users only
+ * need to click the accordion header to show
+ * the datetime.
+ */
+ switch (datetimePresentation) {
+ case 'date-time':
+ case 'date':
+ case 'month-year':
+ case 'month':
+ case 'year':
+ this.selectedButton = 'date';
+ break;
+ case 'time-date':
+ case 'time':
+ this.selectedButton = 'time';
+ break;
+ }
+ });
+ }
+
+ /**
+ * Check the value property on the linked
+ * ion-datetime and then format it according
+ * to the locale specified on ion-datetime.
+ */
+ private setDateTimeText = () => {
+ const { datetimeEl, datetimePresentation } = this;
+
+ if (!datetimeEl) {
+ return;
+ }
+
+ const { value, locale, hourCycle, preferWheel, multiple } = datetimeEl;
+
+ if (multiple) {
+ printIonWarning(
+ `Multi-date selection cannot be used with ion-datetime-button.
+
+Please upvote https://github.com/ionic-team/ionic-framework/issues/25668 if you are interested in seeing this functionality added.
+ `,
+ this.el
+ );
+ return;
+ }
+
+ /**
+ * Both ion-datetime and ion-datetime-button default
+ * to today's date and time if no value is set.
+ */
+ const parsedDatetime = parseDate(value || getToday()) as DatetimeParts;
+ const use24Hour = is24Hour(locale, hourCycle);
+
+ // TODO(FW-1865) - Remove once FW-1831 is fixed.
+ parsedDatetime.tzOffset = undefined;
+
+ this.dateText = this.timeText = undefined;
+
+ switch (datetimePresentation) {
+ case 'date-time':
+ case 'time-date':
+ const dateText = getMonthDayAndYear(locale, parsedDatetime);
+ const timeText = getLocalizedTime(locale, parsedDatetime, use24Hour);
+ if (preferWheel) {
+ this.dateText = `${dateText} ${timeText}`;
+ } else {
+ this.dateText = dateText;
+ this.timeText = timeText;
+ }
+ break;
+ case 'date':
+ this.dateText = getMonthDayAndYear(locale, parsedDatetime);
+ break;
+ case 'time':
+ this.timeText = getLocalizedTime(locale, parsedDatetime, use24Hour);
+ break;
+ case 'month-year':
+ this.dateText = getMonthAndYear(locale, parsedDatetime);
+ break;
+ case 'month':
+ this.dateText = getLocalizedDateTime(locale, parsedDatetime, { month: 'long' });
+ break;
+ case 'year':
+ this.dateText = getLocalizedDateTime(locale, parsedDatetime, { year: 'numeric' });
+ break;
+ }
+ };
+
+ /**
+ * Waits for the ion-datetime to re-render.
+ * This is needed in order to correctly position
+ * a popover relative to the trigger element.
+ */
+ private waitForDatetimeChanges = async () => {
+ const { datetimeEl } = this;
+ if (!datetimeEl) {
+ return Promise.resolve();
+ }
+
+ return new Promise((resolve) => {
+ addEventListener(datetimeEl, 'ionRender', resolve, { once: true });
+ });
+ };
+
+ private handleDateClick = async (ev: Event) => {
+ const { datetimeEl, datetimePresentation } = this;
+
+ if (!datetimeEl) {
+ return;
+ }
+
+ let needsPresentationChange = false;
+
+ /**
+ * When clicking the date button,
+ * we need to make sure that only a date
+ * picker is displayed. For presentation styles
+ * that display content other than a date picker,
+ * we need to update the presentation style.
+ */
+ switch (datetimePresentation) {
+ case 'date-time':
+ case 'time-date':
+ const needsChange = datetimeEl.presentation !== 'date';
+ /**
+ * The date+time wheel picker
+ * shows date and time together,
+ * so do not adjust the presentation
+ * in that case.
+ */
+ if (!datetimeEl.preferWheel && needsChange) {
+ datetimeEl.presentation = 'date';
+ needsPresentationChange = true;
+ }
+ break;
+ }
+
+ /**
+ * Track which button was clicked
+ * so that it can have the correct
+ * activated styles applied when
+ * the modal/popover containing
+ * the datetime is opened.
+ */
+ this.selectedButton = 'date';
+
+ this.presentOverlay(ev, needsPresentationChange, this.dateTargetEl);
+ };
+
+ private handleTimeClick = (ev: Event) => {
+ const { datetimeEl, datetimePresentation } = this;
+
+ if (!datetimeEl) {
+ return;
+ }
+
+ let needsPresentationChange = false;
+
+ /**
+ * When clicking the time button,
+ * we need to make sure that only a time
+ * picker is displayed. For presentation styles
+ * that display content other than a time picker,
+ * we need to update the presentation style.
+ */
+ switch (datetimePresentation) {
+ case 'date-time':
+ case 'time-date':
+ const needsChange = datetimeEl.presentation !== 'time';
+ if (needsChange) {
+ datetimeEl.presentation = 'time';
+ needsPresentationChange = true;
+ }
+ break;
+ }
+
+ /**
+ * Track which button was clicked
+ * so that it can have the correct
+ * activated styles applied when
+ * the modal/popover containing
+ * the datetime is opened.
+ */
+ this.selectedButton = 'time';
+
+ this.presentOverlay(ev, needsPresentationChange, this.timeTargetEl);
+ };
+
+ /**
+ * If the datetime is presented in an
+ * overlay, the datetime and overlay
+ * should be appropriately sized.
+ * These classes provide default sizing values
+ * that developers can customize.
+ * The goal is to provide an overlay that is
+ * reasonably sized with a datetime that
+ * fills the entire container.
+ */
+ private presentOverlay = async (ev: Event, needsPresentationChange: boolean, triggerEl?: HTMLElement) => {
+ const { overlayEl } = this;
+
+ if (!overlayEl) {
+ return;
+ }
+
+ if (overlayEl.tagName === 'ION-POPOVER') {
+ /**
+ * When the presentation on datetime changes,
+ * we need to wait for the component to re-render
+ * otherwise the computed width/height of the
+ * popover content will be wrong, causing
+ * the popover to not align with the trigger element.
+ */
+
+ if (needsPresentationChange) {
+ await this.waitForDatetimeChanges();
+ }
+
+ /**
+ * We pass the trigger button element
+ * so that the popover aligns with the individual
+ * button that was clicked, not the component container.
+ */
+ (overlayEl as HTMLIonPopoverElement).present({
+ ...ev,
+ detail: {
+ ionShadowTarget: triggerEl,
+ },
+ } as CustomEvent);
+ } else {
+ overlayEl.present();
+ }
+ };
+
+ render() {
+ const { color, dateText, timeText, selectedButton, datetimeActive, disabled } = this;
+
+ const mode = getIonMode(this);
+
+ return (
+
+ {dateText && (
+
+ )}
+
+ {timeText && (
+
+ )}
+
+ );
+ }
+}
diff --git a/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts b/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts
new file mode 100644
index 0000000000..6654ddf87b
--- /dev/null
+++ b/core/src/components/datetime-button/test/basic/datetime-button.e2e.ts
@@ -0,0 +1,186 @@
+import { expect } from '@playwright/test';
+import { test } from '@utils/test/playwright';
+
+test.describe('datetime-button: switching to correct view', () => {
+ test.beforeEach(async ({ page }, testInfo) => {
+ test.skip(testInfo.project.metadata.rtl === 'rtl', 'No layout tests');
+ test.skip(testInfo.project.metadata.mode === 'ios', 'No mode-specific logic');
+
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+ });
+ test('should switch to a date-only view when the date button is clicked', async ({ page }) => {
+ const datetime = page.locator('ion-datetime');
+ expect(datetime).toHaveJSProperty('presentation', 'date-time');
+
+ await page.locator('#date-button').click();
+
+ expect(datetime).toHaveJSProperty('presentation', 'date');
+ });
+ test('should switch to a time-only view when the time button is clicked', async ({ page }) => {
+ const datetime = page.locator('ion-datetime');
+ expect(datetime).toHaveJSProperty('presentation', 'date-time');
+
+ await page.locator('#time-button').click();
+
+ expect(datetime).toHaveJSProperty('presentation', 'time');
+ });
+});
+
+test.describe('datetime-button: labels', () => {
+ // eslint-disable-next-line no-empty-pattern
+ test.beforeEach(({}, testInfo) => {
+ test.skip(testInfo.project.metadata.rtl === 'rtl', 'No layout tests');
+ test.skip(testInfo.project.metadata.mode === 'ios', 'No mode-specific logic');
+ });
+ test('should set date and time labels in separate buttons', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#date-button')).toContainText('Jan 1, 2022');
+ await expect(page.locator('#time-button')).toContainText('6:30 AM');
+ });
+ test('should set only month and year', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#date-button')).toContainText('January 2022');
+ await expect(page.locator('#time-button')).toBeHidden();
+ });
+ test('should set only year', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#date-button')).toContainText('2022');
+ await expect(page.locator('#time-button')).toBeHidden();
+ });
+ test('should set only month', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#date-button')).toContainText('January');
+ await expect(page.locator('#time-button')).toBeHidden();
+ });
+ test('should set only time', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#time-button')).toContainText('6:30 AM');
+ await expect(page.locator('#date-button')).toBeHidden();
+ });
+ test('should update the label when the value of the datetime changes', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ const datetime = page.locator('ion-datetime');
+ const dateTarget = page.locator('#date-button');
+
+ await expect(dateTarget).toContainText('Jan 1, 2022');
+
+ await datetime.evaluate((el: HTMLIonDatetimeElement) => (el.value = '2023-05-10'));
+ await page.waitForChanges();
+
+ await expect(dateTarget).toContainText('May 10, 2023');
+ });
+});
+
+test.describe('datetime-button: locale', () => {
+ // eslint-disable-next-line no-empty-pattern
+ test.beforeEach(({}, testInfo) => {
+ test.skip(testInfo.project.metadata.rtl === 'rtl', 'No layout tests');
+ test.skip(testInfo.project.metadata.mode === 'ios', 'No mode-specific logic');
+ });
+ test('should use the same locale as datetime', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ /**
+ * The entire text reads 1 ene 2022, but some browsers will add
+ * a period after "ene". Just checking ene allows us to verify the
+ * behavior while avoiding these cross browser differences.
+ */
+ await expect(page.locator('#date-button')).toContainText(/ene/);
+ await expect(page.locator('#time-button')).toContainText('6:30');
+ });
+ test('should respect hour cycle even if different from locale default', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#time-button')).toContainText('16:30');
+ });
+ test('should ignore the timezone when selecting a date', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ const timeTarget = page.locator('#time-button');
+ await expect(timeTarget).toContainText('6:30');
+
+ const firstOfMonth = page.locator('ion-datetime .calendar-day[data-month="1"][data-day="1"]');
+ await firstOfMonth.click();
+ await page.waitForChanges();
+
+ await expect(timeTarget).toContainText('6:30');
+ });
+});
+
+test.describe('datetime-button: wheel', () => {
+ // eslint-disable-next-line no-empty-pattern
+ test.beforeEach(({}, testInfo) => {
+ test.skip(testInfo.project.metadata.rtl === 'rtl', 'No layout tests');
+ test.skip(testInfo.project.metadata.mode === 'ios', 'No mode-specific logic');
+ });
+ test('should only show a single date button when presentation="date-time" and prefer-wheel="true"', async ({
+ page,
+ }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#date-button')).toContainText('Jan 1, 2022 6:30 AM');
+ await expect(page.locator('#time-button')).not.toBeVisible();
+ });
+ test('should only show a single date button when presentation="time-date" and prefer-wheel="true"', async ({
+ page,
+ }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#date-button')).toContainText('Jan 1, 2022 6:30 AM');
+ await expect(page.locator('#time-button')).not.toBeVisible();
+ });
+});
diff --git a/core/src/components/datetime-button/test/basic/index.html b/core/src/components/datetime-button/test/basic/index.html
new file mode 100644
index 0000000000..c446544a0a
--- /dev/null
+++ b/core/src/components/datetime-button/test/basic/index.html
@@ -0,0 +1,222 @@
+
+
+
+
+ Datetime Button - Basic
+
+
+
+
+
+
+
+
+
+
+
+ Datetime Button - Basic
+
+
+
+
+
+
Date/Time
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
+
Date Only
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
+
Time Only
+
+
+ Start Time
+
+
+
+
+
+
+
+
+
Time Only (24 hour)
+
+
+ Start Time
+
+
+
+
+
+
+
+
+
Time/Date
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
Month
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
Month/Year
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
Year
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
preferWheel / date
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
+
preferWheel / date-time
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/datetime-button/test/buttons/index.html b/core/src/components/datetime-button/test/buttons/index.html
new file mode 100644
index 0000000000..2b6f1f7bcc
--- /dev/null
+++ b/core/src/components/datetime-button/test/buttons/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+ Datetime Button - Custom Buttons
+
+
+
+
+
+
+
+
+
+
+ Datetime Button - Custom Buttons
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts
new file mode 100644
index 0000000000..c9e23913a6
--- /dev/null
+++ b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts
@@ -0,0 +1,30 @@
+import { expect } from '@playwright/test';
+import { test } from '@utils/test/playwright';
+
+test.describe('datetime-button: disabled buttons', () => {
+ test('buttons should not be enabled when component is disabled', async ({ page }, testInfo) => {
+ test.skip(testInfo.project.metadata.rtl === 'rtl', 'No layout tests');
+ test.skip(testInfo.project.metadata.mode === 'ios', 'No mode-specific logic');
+
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ await expect(page.locator('#date-button')).toBeDisabled();
+ await expect(page.locator('#time-button')).toBeDisabled();
+ });
+ test('buttons should visually be disabled', async ({ page }) => {
+ await page.setContent(`
+
+
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ const datetimeButton = page.locator('ion-datetime-button');
+ expect(await datetimeButton.screenshot()).toMatchSnapshot(
+ `datetime-button-disabled-${page.getSnapshotSettings()}.png`
+ );
+ });
+});
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..ea6feb18f4
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..4d16e9d498
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..38a885fa46
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..a86e4b54a1
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..acbb4da0db
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..bfc90a5912
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..0063e48b2f
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..d73f47ad46
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..a8ebc64e22
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..b10eff5574
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..8f9e8b1931
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..f70372d833
Binary files /dev/null and b/core/src/components/datetime-button/test/disabled/datetime-button.e2e.ts-snapshots/datetime-button-disabled-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/disabled/index.html b/core/src/components/datetime-button/test/disabled/index.html
new file mode 100644
index 0000000000..a6bd1dc7ea
--- /dev/null
+++ b/core/src/components/datetime-button/test/disabled/index.html
@@ -0,0 +1,74 @@
+
+
+
+
+ Datetime Button - Disabled
+
+
+
+
+
+
+
+
+
+
+
+ Datetime Button - Disabled
+
+
+
+
+
+
Datetime Button Disabled
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
Custom Button Disabled
+
+
+ Start Date
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts
new file mode 100644
index 0000000000..49d18c5637
--- /dev/null
+++ b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts
@@ -0,0 +1,162 @@
+import { expect } from '@playwright/test';
+import type { Locator } from '@playwright/test';
+import { test } from '@utils/test/playwright';
+import type { EventSpy } from '@utils/test/playwright';
+
+test.describe('datetime-button: rendering', () => {
+ test('should size the modal correctly', async ({ page }) => {
+ await page.setContent(`
+
+
+
+
+ `);
+
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+ const dateButton = page.locator('ion-datetime-button #date-button');
+ await dateButton.click();
+ await ionModalDidPresent.next();
+
+ expect(await page.screenshot()).toMatchSnapshot(`datetime-overlay-modal-${page.getSnapshotSettings()}.png`);
+ });
+
+ test('should size the popover correctly', async ({ page }) => {
+ await page.setContent(`
+
+
+
+
+ `);
+
+ const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
+ const dateButton = page.locator('ion-datetime-button #date-button');
+ await dateButton.click();
+ await ionPopoverDidPresent.next();
+
+ expect(await page.screenshot()).toMatchSnapshot(`datetime-overlay-popover-${page.getSnapshotSettings()}.png`);
+ });
+});
+
+test.describe('datetime-button: popover', () => {
+ let datetime: Locator;
+ let popover: Locator;
+ let ionPopoverDidPresent: EventSpy;
+ let ionPopoverDidDismiss: EventSpy;
+ test.beforeEach(async ({ page }, testInfo) => {
+ test.skip(testInfo.project.metadata.rtl === 'rtl', 'No layout tests');
+ test.skip(testInfo.project.metadata.mode === 'ios', 'No mode-specific logic');
+
+ await page.setContent(`
+
+
+
+
+
+ `);
+
+ datetime = page.locator('ion-datetime');
+ popover = page.locator('ion-popover');
+ ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
+ ionPopoverDidDismiss = await page.spyOnEvent('ionPopoverDidDismiss');
+ });
+ test('should open the date popover', async ({ page }) => {
+ await page.locator('#date-button').click();
+
+ await ionPopoverDidPresent.next();
+
+ expect(datetime).toBeVisible();
+ });
+ test('should open the time popover', async ({ page }) => {
+ await page.locator('#time-button').click();
+
+ await ionPopoverDidPresent.next();
+
+ expect(datetime).toBeVisible();
+ });
+ test('should open the date popover then the time popover', async ({ page }) => {
+ await page.locator('#date-button').click();
+ await ionPopoverDidPresent.next();
+ expect(datetime).toBeVisible();
+
+ await popover.evaluate((el: HTMLIonPopoverElement) => el.dismiss());
+ await ionPopoverDidDismiss.next();
+
+ await page.locator('#time-button').click();
+ await ionPopoverDidPresent.next();
+ expect(datetime).toBeVisible();
+ });
+ test('should open the time popover then the date popover', async ({ page }) => {
+ await page.locator('#time-button').click();
+ await ionPopoverDidPresent.next();
+ expect(datetime).toBeVisible();
+
+ await popover.evaluate((el: HTMLIonPopoverElement) => el.dismiss());
+ await ionPopoverDidDismiss.next();
+
+ await page.locator('#date-button').click();
+ await ionPopoverDidPresent.next();
+ expect(datetime).toBeVisible();
+ });
+});
+
+test.describe('datetime-button: modal', () => {
+ let datetime: Locator;
+ let modal: Locator;
+ let ionModalDidPresent: EventSpy;
+ let ionModalDidDismiss: EventSpy;
+ test.beforeEach(async ({ page }, testInfo) => {
+ test.skip(testInfo.project.metadata.rtl === 'rtl', 'No layout tests');
+ test.skip(testInfo.project.metadata.mode === 'ios', 'No mode-specific logic');
+
+ await page.setContent(`
+
+
+
+
+
+ `);
+
+ datetime = page.locator('ion-datetime');
+ modal = page.locator('ion-modal');
+ ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+ ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss');
+ });
+ test('should open the date modal', async ({ page }) => {
+ await page.locator('#date-button').click();
+
+ await ionModalDidPresent.next();
+
+ expect(datetime).toBeVisible();
+ });
+ test('should open the time modal', async ({ page }) => {
+ await page.locator('#time-button').click();
+
+ await ionModalDidPresent.next();
+
+ expect(datetime).toBeVisible();
+ });
+ test('should open the date modal then the time modal', async ({ page }) => {
+ await page.locator('#date-button').click();
+ await ionModalDidPresent.next();
+ expect(datetime).toBeVisible();
+
+ await modal.evaluate((el: HTMLIonModalElement) => el.dismiss());
+ await ionModalDidDismiss.next();
+
+ await page.locator('#time-button').click();
+ await ionModalDidPresent.next();
+ expect(datetime).toBeVisible();
+ });
+ test('should open the time modal then the date modal', async ({ page }) => {
+ await page.locator('#time-button').click();
+ await ionModalDidPresent.next();
+ expect(datetime).toBeVisible();
+
+ await modal.evaluate((el: HTMLIonModalElement) => el.dismiss());
+ await ionModalDidDismiss.next();
+
+ await page.locator('#date-button').click();
+ await ionModalDidPresent.next();
+ expect(datetime).toBeVisible();
+ });
+});
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..a7e751103a
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..17ae661d72
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..9fbd2ed454
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..e226527ecb
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..a9920562b4
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..ba7b0872ed
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..7e9514c23b
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..e730ef1879
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..93e1117e64
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..b7e5ce0647
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..7a986b79bc
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..8281b2fd15
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-modal-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..85159b4fcf
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..b14b873670
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..cab65a42bc
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..366bcc821d
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..14de14bda4
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..17f42dadb2
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..38ff7b13da
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..3138117aa3
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..5d2e271a42
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..4c473322fb
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..85edfe5507
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..13afce1f84
Binary files /dev/null and b/core/src/components/datetime-button/test/overlays/datetime-button.e2e.ts-snapshots/datetime-overlay-popover-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime-button/test/overlays/index.html b/core/src/components/datetime-button/test/overlays/index.html
new file mode 100644
index 0000000000..78722979f2
--- /dev/null
+++ b/core/src/components/datetime-button/test/overlays/index.html
@@ -0,0 +1,118 @@
+
+
+
+
+ Datetime Button - Overlays
+
+
+
+
+
+
+
+
+
+
+
+ Datetime Button - Overlays
+
+
+
+
+
+
Popover - Default
+
+
+
+
+
+
+
+
+
+
+
Modal - Default
+
+
+
+
+
+
+
+
+
+
+
Popover - Custom
+
+
+
+
+
+
+
+
Custom select a Date
+
+
+
+
+
Modal - Custom
+
+
+
+
+
+
+
+
Custom select a Date
+
+
+
+
+
+
+
+
diff --git a/core/src/components/datetime-button/test/style/index.html b/core/src/components/datetime-button/test/style/index.html
new file mode 100644
index 0000000000..f4bb659a85
--- /dev/null
+++ b/core/src/components/datetime-button/test/style/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+ Datetime Button - Custom Style
+
+
+
+
+
+
+
+
+
+
+ Datetime Button - Custom Style
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/datetime/datetime-interface.ts b/core/src/components/datetime/datetime-interface.ts
index b2fd944c83..8c2ce79da8 100644
--- a/core/src/components/datetime/datetime-interface.ts
+++ b/core/src/components/datetime/datetime-interface.ts
@@ -3,7 +3,7 @@ export interface DatetimeOptions {
}
export interface DatetimeChangeEventDetail {
- value?: string | null;
+ value?: string | string[] | null;
}
export interface DatetimeCustomEvent extends CustomEvent {
@@ -21,3 +21,5 @@ export interface DatetimeParts {
ampm?: 'am' | 'pm';
tzOffset?: number;
}
+
+export type DatetimePresentation = 'date-time' | 'time-date' | 'date' | 'time' | 'month' | 'year' | 'month-year';
diff --git a/core/src/components/datetime/datetime.ios.scss b/core/src/components/datetime/datetime.ios.scss
index bc3b010552..c7b60299d5 100644
--- a/core/src/components/datetime/datetime.ios.scss
+++ b/core/src/components/datetime/datetime.ios.scss
@@ -8,9 +8,9 @@
--title-color: #{$text-color-step-400};
}
-:host(.datetime-presentation-date-time),
-:host(.datetime-presentation-time-date),
-:host(.datetime-presentation-date) {
+:host(.datetime-presentation-date-time:not(.datetime-prefer-wheel)),
+:host(.datetime-presentation-time-date:not(.datetime-prefer-wheel)),
+:host(.datetime-presentation-date:not(.datetime-prefer-wheel)) {
min-height: 350px;
}
diff --git a/core/src/components/datetime/datetime.scss b/core/src/components/datetime/datetime.scss
index 3d70d71e62..309e347de6 100644
--- a/core/src/components/datetime/datetime.scss
+++ b/core/src/components/datetime/datetime.scss
@@ -19,12 +19,37 @@
overflow: hidden;
}
+/**
+ * When using the wheel picker to switch
+ * between months, sometimes the allowed
+ * dates may be filtered. As a result, it
+ * is possible to get a layout shift as
+ * the picker column will shrink to fit the
+ * widest item in the column. Setting a minimum
+ * width avoids this layout shifting.
+ */
+ion-picker-column-internal {
+ min-width: 26px;
+}
+
:host(.datetime-size-fixed) {
width: auto;
- max-width: 350px;
height: auto;
}
+:host(.datetime-size-fixed:not(.datetime-prefer-wheel)) {
+ max-width: 350px;
+}
+
+/**
+ * This ensures that the picker is apppropriately
+ * sized and never truncates the text.
+ */
+:host(.datetime-size-fixed.datetime-prefer-wheel) {
+ min-width: 350px;
+ max-width: max-content;
+}
+
:host(.datetime-size-cover) {
width: 100%;
}
@@ -58,21 +83,19 @@
* the order we need to manually switch
* the text alignment too.
*/
-:host .datetime-year .order-month-first .month-column {
- order: 1;
-}
+:host .wheel-order-year-first .day-column {
+ order: 3;
-:host .datetime-year .order-month-first .year-column {
- order: 2;
+ text-align: end;
}
-:host .datetime-year .order-year-first .month-column {
+:host .wheel-order-year-first .month-column {
order: 2;
text-align: end;
}
-:host .datetime-year .order-year-first .year-column {
+:host .wheel-order-year-first .year-column {
order: 1;
text-align: start;
diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx
index 8008e4a8fe..2bd214e74d 100644
--- a/core/src/components/datetime/datetime.tsx
+++ b/core/src/components/datetime/datetime.tsx
@@ -3,7 +3,14 @@ import { Component, Element, Event, Host, Method, Prop, State, Watch, h, writeTa
import { caretDownSharp, caretUpSharp, chevronBack, chevronDown, chevronForward } from 'ionicons/icons';
import { getIonMode } from '../../global/ionic-global';
-import type { Color, DatetimeChangeEventDetail, DatetimeParts, Mode, StyleEventDetail } from '../../interface';
+import type {
+ Color,
+ DatetimePresentation,
+ DatetimeChangeEventDetail,
+ DatetimeParts,
+ Mode,
+ StyleEventDetail,
+} from '../../interface';
import { startFocusVisible } from '../../utils/focus-visible';
import { getElementRoot, raf, renderHiddenInput } from '../../utils/helpers';
import { printIonError, printIonWarning } from '../../utils/logging';
@@ -11,23 +18,24 @@ import { isRTL } from '../../utils/rtl';
import { createColorClasses } from '../../utils/theme';
import type { PickerColumnItem } from '../picker-column-internal/picker-column-internal-interfaces';
-import { warnIfValueOutOfBounds } from './utils/comparison';
+import { isSameDay, warnIfValueOutOfBounds } from './utils/comparison';
import {
generateMonths,
- generateTime,
- getCalendarYears,
getDaysOfMonth,
getDaysOfWeek,
- getPickerMonths,
getToday,
+ getMonthColumnData,
+ getDayColumnData,
+ getYearColumnData,
+ getTimeColumnsData,
+ getCombinedDateColumnData,
} from './utils/data';
-import { addTimePadding, getFormattedHour, getFormattedTime, getMonthAndDay, getMonthAndYear } from './utils/format';
-import { is24Hour, isMonthFirstLocale } from './utils/helpers';
+import { formatValue, getLocalizedTime, getMonthAndDay, getMonthAndYear } from './utils/format';
+import { is24Hour, isLocaleDayPeriodRTL, isMonthFirstLocale } from './utils/helpers';
import {
calculateHourFromAMPM,
convertDataToISO,
getEndOfWeek,
- getInternalHourValue,
getNextDay,
getNextMonth,
getNextWeek,
@@ -38,7 +46,7 @@ import {
getPreviousYear,
getStartOfWeek,
} from './utils/manipulation';
-import { clampDate, convertToArrayOfNumbers, getPartsFromCalendarDay, parseDate } from './utils/parse';
+import { clampDate, convertToArrayOfNumbers, getPartsFromCalendarDay, parseAmPm, parseDate } from './utils/parse';
import {
getCalendarDayState,
isDayDisabled,
@@ -97,11 +105,11 @@ export class Datetime implements ComponentInterface {
* Duplicate reference to `activeParts` that does not trigger a re-render of the component.
* Allows caching an instance of the `activeParts` in between render cycles.
*/
- private activePartsClone!: DatetimeParts;
+ private activePartsClone!: DatetimeParts | DatetimeParts[];
@State() showMonthAndYear = false;
- @State() activeParts: DatetimeParts = {
+ @State() activeParts: DatetimeParts | DatetimeParts[] = {
month: 5,
day: 28,
year: 2021,
@@ -203,7 +211,7 @@ export class Datetime implements ComponentInterface {
* AM/PM. `'date-time'` will show the date picker first and time picker second.
* `'time-date'` will show the time picker first and date picker second.
*/
- @Prop() presentation: 'date-time' | 'time-date' | 'date' | 'time' | 'month' | 'year' | 'month-year' = 'date-time';
+ @Prop() presentation: DatetimePresentation = 'date-time';
/**
* The text to display on the picker's cancel button.
@@ -305,17 +313,31 @@ export class Datetime implements ComponentInterface {
*/
@Prop() firstDayOfWeek = 0;
+ /**
+ * If `true`, multiple dates can be selected at once. Only
+ * applies to `presentation="date"` and `preferWheel="false"`.
+ */
+ @Prop() multiple = false;
+
/**
* The value of the datetime as a valid ISO 8601 datetime string.
+ * Should be an array of strings if `multiple="true"`.
*/
- @Prop({ mutable: true }) value?: string | null;
+ @Prop({ mutable: true }) value?: string | string[] | null;
/**
* Update the datetime value when the value changes
*/
@Watch('value')
protected valueChanged() {
+ const { value, minParts, maxParts, workingParts, multiple } = this;
+
if (this.hasValue()) {
+ if (!multiple && Array.isArray(value)) {
+ this.value = value[0];
+ return; // setting this.value will trigger re-run of this function
+ }
+
/**
* Clones the value of the `activeParts` to the private clone, to update
* the date display on the current render cycle without causing another render.
@@ -323,40 +345,45 @@ export class Datetime implements ComponentInterface {
* This allows us to update the current value's date/time display without
* refocusing or shifting the user's display (leaves the user in place).
*/
- const valueDateParts = parseDate(this.value);
+ const valueDateParts = parseDate(value);
if (valueDateParts) {
- warnIfValueOutOfBounds(valueDateParts, this.minParts, this.maxParts);
-
- const { month, day, year, hour, minute } = valueDateParts;
- const ampm = hour >= 12 ? 'pm' : 'am';
-
- this.activePartsClone = {
- ...this.activeParts,
- month,
- day,
- year,
- hour,
- minute,
- ampm,
- };
+ warnIfValueOutOfBounds(valueDateParts, minParts, maxParts);
- /**
- * The working parts am/pm value must be updated when the value changes, to
- * ensure the time picker hour column values are generated correctly.
- */
- this.setWorkingParts({
- ...this.workingParts,
- ampm,
- });
+ if (Array.isArray(valueDateParts)) {
+ this.activePartsClone = [...valueDateParts];
+ } else {
+ const { month, day, year, hour, minute } = valueDateParts;
+ const ampm = hour ? (hour >= 12 ? 'pm' : 'am') : undefined;
+
+ this.activePartsClone = {
+ ...this.activeParts,
+ month,
+ day,
+ year,
+ hour,
+ minute,
+ ampm,
+ };
+
+ /**
+ * The working parts am/pm value must be updated when the value changes, to
+ * ensure the time picker hour column values are generated correctly.
+ *
+ * Note that we don't need to do this if valueDateParts is an array, since
+ * multiple="true" does not apply to time pickers.
+ */
+ this.setWorkingParts({
+ ...workingParts,
+ ampm,
+ });
+ }
} else {
- printIonWarning(`Unable to parse date string: ${this.value}. Please provide a valid ISO 8601 datetime string.`);
+ printIonWarning(`Unable to parse date string: ${value}. Please provide a valid ISO 8601 datetime string.`);
}
}
this.emitStyle();
- this.ionChange.emit({
- value: this.value,
- });
+ this.ionChange.emit({ value });
}
/**
@@ -409,6 +436,20 @@ export class Datetime implements ComponentInterface {
*/
@Prop() size: 'cover' | 'fixed' = 'fixed';
+ /**
+ * If `true`, a wheel picker will be rendered instead of a calendar grid
+ * where possible. If `false`, a calendar grid will be rendered instead of
+ * a wheel picker where possible.
+ *
+ * A wheel picker can be rendered instead of a grid when `presentation` is
+ * one of the following values: `'date'`, `'date-time'`, or `'time-date'`.
+ *
+ * A wheel picker will always be rendered regardless of
+ * the `preferWheel` value when `presentation` is one of the following values:
+ * `'time'`, `'month'`, `'month-year'`, or `'year'`.
+ */
+ @Prop() preferWheel = false;
+
/**
* Emitted when the datetime selection was cancelled.
*/
@@ -435,6 +476,12 @@ export class Datetime implements ComponentInterface {
*/
@Event() ionStyle!: EventEmitter;
+ /**
+ * Emitted when componentDidRender is fired.
+ * @internal
+ */
+ @Event() ionRender!: EventEmitter;
+
/**
* Confirms the selected datetime value, updates the
* `value` property, and optionally closes the popover
@@ -442,6 +489,8 @@ export class Datetime implements ComponentInterface {
*/
@Method()
async confirm(closeOverlay = false) {
+ const { highlightActiveParts, isCalendarPicker, activeParts } = this;
+
/**
* We only update the value if the presentation is not a calendar picker,
* or if `highlightActiveParts` is true; indicating that the user
@@ -449,20 +498,32 @@ export class Datetime implements ComponentInterface {
*
* Otherwise "today" would accidentally be set as the value.
*/
- if (this.highlightActiveParts || !this.isCalendarPicker) {
- /**
- * Prevent convertDataToISO from doing any
- * kind of transformation based on timezone
- * This cancels out any change it attempts to make
- *
- * Important: Take the timezone offset based on
- * the date that is currently selected, otherwise
- * there can be 1 hr difference when dealing w/ DST
- */
- const date = new Date(convertDataToISO(this.activeParts));
- this.activeParts.tzOffset = date.getTimezoneOffset() * -1;
+ if (highlightActiveParts || !isCalendarPicker) {
+ const activePartsIsArray = Array.isArray(activeParts);
+ if (activePartsIsArray && activeParts.length === 0) {
+ this.value = undefined;
+ } else {
+ /**
+ * Prevent convertDataToISO from doing any
+ * kind of transformation based on timezone
+ * This cancels out any change it attempts to make
+ *
+ * Important: Take the timezone offset based on
+ * the date that is currently selected, otherwise
+ * there can be 1 hr difference when dealing w/ DST
+ */
+ if (activePartsIsArray) {
+ const dates = convertDataToISO(activeParts).map((str) => new Date(str));
+ for (let i = 0; i < dates.length; i++) {
+ activeParts[i].tzOffset = dates[i].getTimezoneOffset() * -1;
+ }
+ } else {
+ const date = new Date(convertDataToISO(activeParts));
+ activeParts.tzOffset = date.getTimezoneOffset() * -1;
+ }
- this.value = convertDataToISO(this.activeParts);
+ this.value = convertDataToISO(activeParts);
+ }
}
if (closeOverlay) {
@@ -511,10 +572,49 @@ export class Datetime implements ComponentInterface {
};
};
- private setActiveParts = (parts: DatetimeParts) => {
- this.activeParts = {
- ...parts,
- };
+ private setActiveParts = (parts: DatetimeParts, removeDate = false) => {
+ const { multiple, activePartsClone, highlightActiveParts } = this;
+
+ if (multiple) {
+ /**
+ * We read from activePartsClone here because valueChanged() only updates that,
+ * so it's the more reliable source of truth. If we read from activeParts, then
+ * if you click July 1, manually set the value to July 2, and then click July 3,
+ * the new value would be [July 1, July 3], ignoring the value set.
+ *
+ * We can then pass the new value to activeParts (rather than activePartsClone)
+ * since the clone will be updated automatically by activePartsChanged().
+ */
+ const activePartsArray = Array.isArray(activePartsClone) ? activePartsClone : [activePartsClone];
+ if (removeDate) {
+ this.activeParts = activePartsArray.filter((p) => !isSameDay(p, parts));
+ } else if (highlightActiveParts) {
+ this.activeParts = [...activePartsArray, parts];
+ } else {
+ /**
+ * If highlightActiveParts is false, that means we just have a
+ * default value of today in activeParts; we need to replace that
+ * rather than adding to it since it's just a placeholder.
+ */
+ this.activeParts = [parts];
+ }
+ } else {
+ this.activeParts = {
+ ...parts,
+ };
+ }
+
+ /**
+ * Now that the user has interacted somehow to select something, we can
+ * show the solid highlight. This needs to be done after checking it above,
+ * but before the confirm call below.
+ *
+ * Note that for datetimes with confirm/cancel buttons, the value
+ * isn't updated until you call confirm(). We need to bring the
+ * solid circle back on day click for UX reasons, rather than only
+ * show the circle if `value` is truthy.
+ */
+ this.highlightActiveParts = true;
const hasSlottedButtons = this.el.querySelector('[slot="buttons"]') !== null;
if (hasSlottedButtons || this.showDefaultButtons) {
@@ -1034,16 +1134,33 @@ export class Datetime implements ComponentInterface {
* interfaces.
*/
this.showMonthAndYear = false;
+
+ raf(() => {
+ this.ionRender.emit();
+ });
}
- private processValue = (value?: string | null) => {
+ private processValue = (value?: string | string[] | null) => {
this.highlightActiveParts = !!value;
- const valueToProcess = parseDate(value || getToday());
+ let valueToProcess = parseDate(value || getToday());
+
+ const { minParts, maxParts, multiple } = this;
+ if (!multiple && Array.isArray(value)) {
+ this.value = value[0];
+ valueToProcess = (valueToProcess as DatetimeParts[])[0];
+ }
- const { minParts, maxParts } = this;
warnIfValueOutOfBounds(valueToProcess, minParts, maxParts);
- const { month, day, year, hour, minute, tzOffset } = clampDate(valueToProcess, minParts, maxParts);
+ /**
+ * If there are multiple values, pick an arbitrary one to clamp to. This way,
+ * if the values are across months, we always show at least one of them. Note
+ * that the values don't necessarily have to be in order.
+ */
+ const singleValue = Array.isArray(valueToProcess) ? valueToProcess[0] : valueToProcess;
+
+ const { month, day, year, hour, minute, tzOffset } = clampDate(singleValue, minParts, maxParts);
+ const ampm = parseAmPm(hour!);
this.setWorkingParts({
month,
@@ -1052,21 +1169,37 @@ export class Datetime implements ComponentInterface {
hour,
minute,
tzOffset,
- ampm: hour! >= 12 ? 'pm' : 'am',
+ ampm,
});
- this.activeParts = {
- month,
- day,
- year,
- hour,
- minute,
- tzOffset,
- ampm: hour! >= 12 ? 'pm' : 'am',
- };
+ if (Array.isArray(valueToProcess)) {
+ this.activeParts = [...valueToProcess];
+ } else {
+ this.activeParts = {
+ month,
+ day,
+ year,
+ hour,
+ minute,
+ tzOffset,
+ ampm,
+ };
+ }
};
componentWillLoad() {
+ const { el, multiple, presentation, preferWheel } = this;
+
+ if (multiple) {
+ if (presentation !== 'date') {
+ printIonWarning('Multiple date selection is only supported for presentation="date".', el);
+ }
+
+ if (preferWheel) {
+ printIonWarning('Multiple date selection is not supported with preferWheel="true".', el);
+ }
+ }
+
this.processMinParts();
this.processMaxParts();
this.processValue(this.value);
@@ -1136,6 +1269,16 @@ export class Datetime implements ComponentInterface {
});
};
+ private toggleMonthAndYearView = () => {
+ this.showMonthAndYear = !this.showMonthAndYear;
+ };
+
+ /**
+ * Universal render methods
+ * These are pieces of datetime that
+ * are rendered independently of presentation.
+ */
+
private renderFooter() {
const { showDefaultButtons, showClearButton } = this;
const hasSlottedButtons = this.el.querySelector('[slot="buttons"]') !== null;
@@ -1191,110 +1334,461 @@ export class Datetime implements ComponentInterface {
);
}
- private toggleMonthAndYearView = () => {
- this.showMonthAndYear = !this.showMonthAndYear;
- };
+ /**
+ * Wheel picker render methods
+ */
+
+ private renderWheelPicker(forcePresentation: string = this.presentation) {
+ /**
+ * If presentation="time-date" we switch the
+ * order of the render array here instead of
+ * manually reordering each date/time picker
+ * column with CSS. This allows for additional
+ * flexibility if we need to render subsets
+ * of the date/time data or do additional ordering
+ * within the child render functions.
+ */
+ const renderArray =
+ forcePresentation === 'time-date'
+ ? [this.renderTimePickerColumns(forcePresentation), this.renderDatePickerColumns(forcePresentation)]
+ : [this.renderDatePickerColumns(forcePresentation), this.renderTimePickerColumns(forcePresentation)];
+ return {renderArray};
+ }
+
+ private renderDatePickerColumns(forcePresentation: string) {
+ return forcePresentation === 'date-time' || forcePresentation === 'time-date'
+ ? this.renderCombinedDatePickerColumn()
+ : this.renderIndividualDatePickerColumns(forcePresentation);
+ }
+
+ private renderCombinedDatePickerColumn() {
+ const { activeParts, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
+
+ /**
+ * By default, generate a range of 3 months:
+ * Previous month, current month, and next month
+ */
+ const monthsToRender = generateMonths(workingParts);
+
+ /**
+ * generateMonths returns the day data as well,
+ * but we do not want the day value to act as a max/min
+ * on the data we are going to generate.
+ */
+ for (let i = 0; i <= monthsToRender.length - 1; i++) {
+ monthsToRender[i].day = null;
+ }
+
+ /**
+ * If developers have provided their own
+ * min/max values, use that instead. Otherwise,
+ * fallback to the default range of 3 months.
+ */
+ const min = minParts || monthsToRender[0];
+ const max = maxParts || monthsToRender[monthsToRender.length - 1];
+
+ const result = getCombinedDateColumnData(
+ locale,
+ workingParts,
+ todayParts,
+ min,
+ max,
+ this.parsedDayValues,
+ this.parsedMonthValues
+ );
+ let items = result.items;
+ const parts = result.parts;
+
+ if (isDateEnabled) {
+ items = items.map((itemObject, index) => {
+ const referenceParts = parts[index];
+
+ let disabled;
+ try {
+ /**
+ * The `isDateEnabled` implementation is try-catch wrapped
+ * to prevent exceptions in the user's function from
+ * interrupting the calendar rendering.
+ */
+ disabled = !isDateEnabled(convertDataToISO(referenceParts));
+ } catch (e) {
+ printIonError(
+ 'Exception thrown from provided `isDateEnabled` function. Please check your function and try again.',
+ e
+ );
+ }
+
+ return {
+ ...itemObject,
+ disabled,
+ };
+ });
+ }
+
+ /**
+ * If we have selected a day already, then default the column
+ * to that value. Otherwise, default it to today.
+ */
+ const todayString = workingParts.day
+ ? `${workingParts.year}-${workingParts.month}-${workingParts.day}`
+ : `${todayParts.year}-${todayParts.month}-${todayParts.day}`;
- private renderYearView() {
- const { presentation, workingParts, locale } = this;
- const calendarYears = getCalendarYears(this.todayParts, this.minParts, this.maxParts, this.parsedYearValues);
- const showMonth = presentation !== 'year';
- const showYear = presentation !== 'month';
-
- const months = getPickerMonths(locale, workingParts, this.minParts, this.maxParts, this.parsedMonthValues);
- const years = calendarYears.map((year) => {
- return {
- text: `${year}`,
- value: year,
- };
- });
- const showMonthFirst = isMonthFirstLocale(locale);
- const columnOrder = showMonthFirst ? 'month-first' : 'year-first';
return (
-
-
-
- {showMonth && (
- {
- // TODO(FW-1823) Remove this when iOS 14 support is dropped.
- // Due to a Safari 14 issue we need to destroy
- // the scroll listener before we update state
- // and trigger a re-render.
- if (this.destroyCalendarListener) {
- this.destroyCalendarListener();
- }
+ {
+ // TODO(FW-1823) Remove this when iOS 14 support is dropped.
+ // Due to a Safari 14 issue we need to destroy
+ // the scroll listener before we update state
+ // and trigger a re-render.
+ if (this.destroyCalendarListener) {
+ this.destroyCalendarListener();
+ }
- this.setWorkingParts({
- ...this.workingParts,
- month: ev.detail.value,
- });
+ const { value } = ev.detail;
+ const findPart = parts.find(({ month, day, year }) => value === `${year}-${month}-${day}`);
- if (presentation === 'month' || presentation === 'month-year') {
- this.setActiveParts({
- ...this.activeParts,
- month: ev.detail.value,
- });
- }
+ this.setWorkingParts({
+ ...workingParts,
+ ...findPart,
+ });
+
+ if (!Array.isArray(activeParts)) {
+ this.setActiveParts({
+ ...activeParts,
+ ...findPart,
+ });
+ }
- // We can re-attach the scroll listener after
- // the working parts have been updated.
- this.initializeCalendarListener();
+ // We can re-attach the scroll listener after
+ // the working parts have been updated.
+ this.initializeCalendarListener();
- ev.stopPropagation();
- }}
- >
- )}
- {showYear && (
- {
- // TODO(FW-1823) Remove this when iOS 14 support is dropped.
- // Due to a Safari 14 issue we need to destroy
- // the scroll listener before we update state
- // and trigger a re-render.
- if (this.destroyCalendarListener) {
- this.destroyCalendarListener();
- }
+ ev.stopPropagation();
+ }}
+ >
+ );
+ }
- this.setWorkingParts({
- ...this.workingParts,
- year: ev.detail.value,
- });
+ private renderIndividualDatePickerColumns(forcePresentation: string) {
+ const { workingParts, isDateEnabled } = this;
+ const shouldRenderMonths = forcePresentation !== 'year' && forcePresentation !== 'time';
+ const months = shouldRenderMonths
+ ? getMonthColumnData(this.locale, workingParts, this.minParts, this.maxParts, this.parsedMonthValues)
+ : [];
+
+ const shouldRenderDays = forcePresentation === 'date';
+ let days = shouldRenderDays
+ ? getDayColumnData(this.locale, workingParts, this.minParts, this.maxParts, this.parsedDayValues)
+ : [];
+
+ if (isDateEnabled) {
+ days = days.map((dayObject) => {
+ const { value } = dayObject;
+ const valueNum = typeof value === 'string' ? parseInt(value) : value;
+ const referenceParts: DatetimeParts = {
+ month: workingParts.month,
+ day: valueNum,
+ year: workingParts.year,
+ };
- if (presentation === 'year' || presentation === 'month-year') {
- this.setActiveParts({
- ...this.activeParts,
- year: ev.detail.value,
- });
- }
+ let disabled;
+ try {
+ /**
+ * The `isDateEnabled` implementation is try-catch wrapped
+ * to prevent exceptions in the user's function from
+ * interrupting the calendar rendering.
+ */
+ disabled = !isDateEnabled(convertDataToISO(referenceParts));
+ } catch (e) {
+ printIonError(
+ 'Exception thrown from provided `isDateEnabled` function. Please check your function and try again.',
+ e
+ );
+ }
+
+ return {
+ ...dayObject,
+ disabled,
+ };
+ });
+ }
- // We can re-attach the scroll listener after
- // the working parts have been updated.
- this.initializeCalendarListener();
+ const shouldRenderYears = forcePresentation !== 'month' && forcePresentation !== 'time';
+ const years = shouldRenderYears
+ ? getYearColumnData(this.todayParts, this.minParts, this.maxParts, this.parsedYearValues)
+ : [];
- ev.stopPropagation();
- }}
- >
- )}
-
-
+ return [this.renderMonthPickerColumn(months), this.renderDayPickerColumn(days), this.renderYearPickerColumn(years)];
+ }
+
+ private renderDayPickerColumn(days: PickerColumnItem[]) {
+ if (days.length === 0) {
+ return [];
+ }
+
+ const { activeParts, workingParts } = this;
+
+ return (
+ {
+ // TODO(FW-1823) Remove this when iOS 14 support is dropped.
+ // Due to a Safari 14 issue we need to destroy
+ // the scroll listener before we update state
+ // and trigger a re-render.
+ if (this.destroyCalendarListener) {
+ this.destroyCalendarListener();
+ }
+
+ this.setWorkingParts({
+ ...workingParts,
+ day: ev.detail.value,
+ });
+
+ if (!Array.isArray(activeParts)) {
+ this.setActiveParts({
+ ...activeParts,
+ day: ev.detail.value,
+ });
+ }
+
+ // We can re-attach the scroll listener after
+ // the working parts have been updated.
+ this.initializeCalendarListener();
+
+ ev.stopPropagation();
+ }}
+ >
+ );
+ }
+
+ private renderMonthPickerColumn(months: PickerColumnItem[]) {
+ if (months.length === 0) {
+ return [];
+ }
+
+ const { activeParts, workingParts } = this;
+
+ return (
+ {
+ // TODO(FW-1823) Remove this when iOS 14 support is dropped.
+ // Due to a Safari 14 issue we need to destroy
+ // the scroll listener before we update state
+ // and trigger a re-render.
+ if (this.destroyCalendarListener) {
+ this.destroyCalendarListener();
+ }
+
+ this.setWorkingParts({
+ ...workingParts,
+ month: ev.detail.value,
+ });
+
+ if (!Array.isArray(activeParts)) {
+ this.setActiveParts({
+ ...activeParts,
+ month: ev.detail.value,
+ });
+ }
+
+ // We can re-attach the scroll listener after
+ // the working parts have been updated.
+ this.initializeCalendarListener();
+
+ ev.stopPropagation();
+ }}
+ >
+ );
+ }
+ private renderYearPickerColumn(years: PickerColumnItem[]) {
+ if (years.length === 0) {
+ return [];
+ }
+
+ const { activeParts, workingParts } = this;
+
+ return (
+ {
+ // TODO(FW-1823) Remove this when iOS 14 support is dropped.
+ // Due to a Safari 14 issue we need to destroy
+ // the scroll listener before we update state
+ // and trigger a re-render.
+ if (this.destroyCalendarListener) {
+ this.destroyCalendarListener();
+ }
+
+ this.setWorkingParts({
+ ...workingParts,
+ year: ev.detail.value,
+ });
+
+ if (!Array.isArray(activeParts)) {
+ this.setActiveParts({
+ ...activeParts,
+ year: ev.detail.value,
+ });
+ }
+
+ // We can re-attach the scroll listener after
+ // the working parts have been updated.
+ this.initializeCalendarListener();
+
+ ev.stopPropagation();
+ }}
+ >
+ );
+ }
+ private renderTimePickerColumns(forcePresentation: string) {
+ if (['date', 'month', 'month-year', 'year'].includes(forcePresentation)) {
+ return [];
+ }
+
+ const { hoursData, minutesData, dayPeriodData } = getTimeColumnsData(
+ this.locale,
+ this.workingParts,
+ this.hourCycle,
+ this.value ? this.minParts : undefined,
+ this.value ? this.maxParts : undefined,
+ this.parsedHourValues,
+ this.parsedMinuteValues
+ );
+
+ return [
+ this.renderHourPickerColumn(hoursData),
+ this.renderMinutePickerColumn(minutesData),
+ this.renderDayPeriodPickerColumn(dayPeriodData),
+ ];
+ }
+
+ private renderHourPickerColumn(hoursData: PickerColumnItem[]) {
+ const { workingParts, activePartsClone } = this;
+ if (hoursData.length === 0) return [];
+
+ return (
+ {
+ this.setWorkingParts({
+ ...workingParts,
+ hour: ev.detail.value,
+ });
+
+ if (!Array.isArray(activePartsClone)) {
+ this.setActiveParts({
+ ...activePartsClone,
+ hour: ev.detail.value,
+ });
+ }
+
+ ev.stopPropagation();
+ }}
+ >
+ );
+ }
+ private renderMinutePickerColumn(minutesData: PickerColumnItem[]) {
+ const { workingParts, activePartsClone } = this;
+ if (minutesData.length === 0) return [];
+
+ return (
+ {
+ this.setWorkingParts({
+ ...workingParts,
+ minute: ev.detail.value,
+ });
+
+ if (!Array.isArray(activePartsClone)) {
+ this.setActiveParts({
+ ...activePartsClone,
+ minute: ev.detail.value,
+ });
+ }
+
+ ev.stopPropagation();
+ }}
+ >
+ );
+ }
+ private renderDayPeriodPickerColumn(dayPeriodData: PickerColumnItem[]) {
+ const { workingParts, activePartsClone } = this;
+ if (dayPeriodData.length === 0) {
+ return [];
+ }
+
+ const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
+
+ return (
+ {
+ const hour = calculateHourFromAMPM(workingParts, ev.detail.value);
+
+ this.setWorkingParts({
+ ...workingParts,
+ ampm: ev.detail.value,
+ hour,
+ });
+
+ if (!Array.isArray(activePartsClone)) {
+ this.setActiveParts({
+ ...activePartsClone,
+ ampm: ev.detail.value,
+ hour,
+ });
+ }
+
+ ev.stopPropagation();
+ }}
+ >
+ );
+ }
+
+ private renderWheelView(forcePresentation?: string) {
+ const { locale } = this;
+ const showMonthFirst = isMonthFirstLocale(locale);
+ const columnOrder = showMonthFirst ? 'month-first' : 'year-first';
+ return (
+
- );
+ /**
+ * Renders the month/year picker that is
+ * displayed on the calendar grid.
+ * The .datetime-year class has additional
+ * styles that let us show/hide the
+ * picker when the user clicks on the
+ * toggle in the calendar header.
+ */
+ private renderCalendarViewMonthYearPicker() {
+ return
{this.renderWheelView('month-year')}
;
}
+ /**
+ * Render entry point
+ * All presentation types are rendered from here.
+ */
+
private renderDatetime(mode: Mode) {
- const { presentation } = this;
+ const { presentation, preferWheel } = this;
+
+ /**
+ * Certain presentation types have separate grid and wheel displays.
+ * If preferWheel is true then we should show a wheel picker instead.
+ */
+ const hasWheelVariant = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
+ if (preferWheel && hasWheelVariant) {
+ return [this.renderWheelView(), this.renderFooter()];
+ }
+
switch (presentation) {
case 'date-time':
return [
this.renderCalendarViewHeader(mode),
this.renderCalendar(mode),
- this.renderYearView(),
+ this.renderCalendarViewMonthYearPicker(),
this.renderTime(),
this.renderFooter(),
];
@@ -1713,7 +2116,7 @@ export class Datetime implements ComponentInterface {
this.renderCalendarViewHeader(mode),
this.renderTime(),
this.renderCalendar(mode),
- this.renderYearView(),
+ this.renderCalendarViewMonthYearPicker(),
this.renderFooter(),
];
case 'time':
@@ -1721,26 +2124,41 @@ export class Datetime implements ComponentInterface {
case 'month':
case 'month-year':
case 'year':
- return [this.renderYearView(), this.renderFooter()];
+ return [this.renderWheelView(), this.renderFooter()];
default:
return [
this.renderCalendarViewHeader(mode),
this.renderCalendar(mode),
- this.renderYearView(),
+ this.renderCalendarViewMonthYearPicker(),
this.renderFooter(),
];
}
}
render() {
- const { name, value, disabled, el, color, isPresented, readonly, showMonthAndYear, presentation, size } = this;
+ const {
+ name,
+ value,
+ disabled,
+ el,
+ color,
+ isPresented,
+ readonly,
+ showMonthAndYear,
+ preferWheel,
+ presentation,
+ size,
+ } = this;
const mode = getIonMode(this);
const isMonthAndYearPresentation =
presentation === 'year' || presentation === 'month' || presentation === 'month-year';
const shouldShowMonthAndYear = showMonthAndYear || isMonthAndYearPresentation;
const monthYearPickerOpen = showMonthAndYear && !isMonthAndYearPresentation;
+ const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
+ const hasWheelVariant = hasDatePresentation && preferWheel;
+ const hasGrid = hasDatePresentation && !preferWheel;
- renderHiddenInput(true, el, name, value, disabled);
+ renderHiddenInput(true, el, name, formatValue(value), disabled);
return (
diff --git a/core/src/components/datetime/test/format.spec.ts b/core/src/components/datetime/test/format.spec.ts
index ae9bc1c0cc..23676b44de 100644
--- a/core/src/components/datetime/test/format.spec.ts
+++ b/core/src/components/datetime/test/format.spec.ts
@@ -4,6 +4,7 @@ import {
getFormattedHour,
addTimePadding,
getMonthAndYear,
+ getLocalizedDayPeriod,
} from '../utils/format';
describe('generateDayAriaLabel()', () => {
@@ -88,3 +89,13 @@ describe('getMonthAndYear()', () => {
expect(getMonthAndYear('es-ES', { month: 4, day: 1, year: 2006 })).toEqual('abril de 2006');
});
});
+
+describe('getLocalizedDayPeriod', () => {
+ it('should return AM when the date is in the morning', () => {
+ expect(getLocalizedDayPeriod('en-US', 'am'));
+ });
+
+ it('should return PM when the date is in the afternoon', () => {
+ expect(getLocalizedDayPeriod('en-US', 'pm'));
+ });
+});
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts b/core/src/components/datetime/test/locale/datetime.e2e.ts
new file mode 100644
index 0000000000..a15a23820d
--- /dev/null
+++ b/core/src/components/datetime/test/locale/datetime.e2e.ts
@@ -0,0 +1,146 @@
+import { expect } from '@playwright/test';
+import type { E2EPage } from '@utils/test/playwright';
+import { test } from '@utils/test/playwright';
+
+test.describe('datetime: locale', () => {
+ let datetimeFixture: DatetimeLocaleFixture;
+
+ test.beforeEach(async ({ page }) => {
+ datetimeFixture = new DatetimeLocaleFixture(page);
+ await datetimeFixture.goto();
+ });
+
+ test.describe('en-US', () => {
+ test.beforeEach(async () => {
+ await datetimeFixture.setLocale('en-US');
+ });
+
+ test('should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedDatePicker();
+ });
+
+ test('month/year picker should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedMonthYearPicker();
+ });
+
+ test('time picker should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedTimePicker();
+ });
+ });
+
+ test.describe('ta-IN', () => {
+ test.beforeEach(async () => {
+ await datetimeFixture.setLocale('ta-IN');
+ });
+
+ test('should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedDatePicker();
+ });
+
+ test('month/year picker should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedMonthYearPicker();
+ });
+
+ test('time picker should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedTimePicker();
+ });
+ });
+
+ test.describe('ja-JP', () => {
+ test.beforeEach(async () => {
+ await datetimeFixture.setLocale('ja-JP');
+ });
+
+ test('should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedDatePicker();
+ });
+
+ test('month/year picker should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedMonthYearPicker();
+ });
+
+ test('time picker should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedTimePicker();
+ });
+ });
+
+ test.describe('es-ES', () => {
+ test.beforeEach(async () => {
+ await datetimeFixture.setLocale('es-ES');
+ });
+
+ test('should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedDatePicker();
+ });
+
+ test('month/year picker should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedMonthYearPicker();
+ });
+
+ test('time picker should not have visual regressions', async () => {
+ await datetimeFixture.expectLocalizedTimePicker();
+ });
+ });
+});
+
+class DatetimeLocaleFixture {
+ readonly page: E2EPage;
+ locale = 'en-US';
+
+ constructor(page: E2EPage) {
+ this.page = page;
+ }
+
+ async goto() {
+ await this.page.goto(`/src/components/datetime/test/locale`);
+ }
+
+ async setLocale(locale: string) {
+ this.locale = locale;
+ await this.page.locator('select').selectOption(locale);
+ await this.page.waitForChanges();
+ }
+
+ async expectLocalizedDatePicker() {
+ await this.waitForDatetime();
+
+ await this.page.setIonViewport();
+ // Captures a screenshot of the datepicker with localized am/pm labels
+ expect(await this.page.screenshot()).toMatchSnapshot(
+ `datetime-locale-${this.locale}-diff-${this.page.getSnapshotSettings()}.png`
+ );
+ }
+
+ async expectLocalizedMonthYearPicker() {
+ await this.waitForDatetime();
+ await this.page.setIonViewport();
+ // Opens the month/year picker
+ const monthYearButton = this.page.locator('#am .calendar-month-year ion-item');
+ await monthYearButton.click();
+ await this.page.waitForChanges();
+ // Capture a screenshot of the month/year picker with localized month labels.
+ expect(await this.page.screenshot()).toMatchSnapshot(
+ `datetime-locale-${this.locale}-month-year-diff-${this.page.getSnapshotSettings()}.png`
+ );
+ }
+
+ async expectLocalizedTimePicker() {
+ await this.waitForDatetime();
+ await this.page.setIonViewport();
+ // Opens the timepicker
+ const timePickerButton = this.page.locator('#am .time-body');
+ const timePickerPopoverPresentSpy = await this.page.spyOnEvent('ionPopoverDidPresent');
+ await timePickerButton.click();
+ await timePickerPopoverPresentSpy.next();
+ // Capture a screenshot of the time picker with localized am/pm labels
+ expect(await this.page.screenshot()).toMatchSnapshot(
+ `datetime-locale-${this.locale}-time-diff-${this.page.getSnapshotSettings()}.png`
+ );
+ }
+
+ private async waitForDatetime() {
+ await this.page.locator('#am.datetime-ready').waitFor({ state: 'attached' });
+ await this.page.locator('#pm').scrollIntoViewIfNeeded();
+ await this.page.locator('#pm.datetime-ready').waitFor({ state: 'attached' });
+ }
+}
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..da46a88b19
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..139ac82032
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..0d9a9fdaeb
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..dced0a8f4b
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..b2c3509d2a
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..8bbbeaf4b9
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..e2a55be930
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..c6bb179a79
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..d0ab8cb5a6
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..a5cf52a768
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..9a2ba1c5ff
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..da9be10820
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..b37783ffdc
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..eb2e545fba
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..4a4aec62c9
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..e94a79ce1c
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..bc2eca9555
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..11459d447c
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..ce86ee944e
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..3dfd01d9c8
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..4820b9e842
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..2a58b1622e
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..8bbd0c2a88
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..d2af417fa4
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-month-year-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..534a3975a4
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..b960749057
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..360472ce30
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..c87cad400c
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..ff569b7b55
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..6711779046
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..7c90e182dd
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..20ed8f89b8
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..09cd1b3b4a
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..bde8a0cdb5
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..6c1f915fd4
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..9d9f07dd71
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-en-US-time-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..1dffbf8edb
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..533ae5aa5f
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..7417c40ba6
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..38c65e7a39
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..9dbbac87eb
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..40a4393998
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..258a69911d
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..fb83654c75
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..f26fe18436
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..0e86069927
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..88c4c1a98f
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..a5def520eb
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..ab4d658090
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..30db8e1df8
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..4ac4838e2d
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..24498f2633
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..fa8e13fdf2
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..c199537f53
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..bac9656bed
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..1abe50304e
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..2615c13946
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..5104bf1538
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..f305f7a409
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..1527c4c7cc
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-month-year-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..f33e67c62b
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..5c4a0a9561
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..a2c1ae647e
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..5dd5599233
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..7335055639
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..fa575af4e0
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..a8ffdf1090
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..12a6813c20
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..93efe6877c
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..bfdfc48079
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..715d2f9dc6
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..640b891dcc
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-es-ES-time-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..eb01fb871b
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..26339c94b3
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..4efd9dd839
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..a50cde4481
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..eee0582ac8
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..e7cb68ce29
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..21a9ba390d
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..8ef0690d8b
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..a8846aad75
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..239ae5f2c2
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..924f988e45
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..a78a36fedf
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..ef07a8ad40
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..d42a553a0d
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..b4e143bb48
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..0e64d6b3d5
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..4517a55fff
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..3d2bc47f2f
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..5b1ebfcc3f
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..2d6a7115f4
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..7cf75f9b86
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..9c82723d33
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..3477033b86
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..306f527d17
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-month-year-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..a1ef144a5c
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..2a0a19649a
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..4be6a2dac2
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..91508e6c8a
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..5dff24f909
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..5d530fa3db
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..ed54d36223
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..2489575ed0
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..b6b0851558
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..71f2e95813
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..47dcad4d43
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..4378392b53
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-time-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..43847bd060
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..b853fb3251
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..32f56a267c
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..273294b218
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..1478ba8a6d
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..fcd3ab5740
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..b0009961f1
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..83252ee537
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..6cc4043c3b
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..a735b8df6a
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..abebcf79c0
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..98590b9def
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..8d268bc2cf
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..e089552098
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..8cc02b69d6
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..b4c2afa04e
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..f0aad7cb4a
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..50518ddce5
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..4ad6b9ee4a
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..de83ca6422
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..66d8880ee0
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..d76848e786
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..1a00ec582a
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..f5e08eee07
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-month-year-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..2cef99d88f
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..556ef6d103
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..5e1f7fc9a4
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..aef0cb9263
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..d102b86478
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..7ade8875d5
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..02ee0263df
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..89d62ef710
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..929bcfd6f3
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..1081624db4
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..dcaf9952b3
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..7adebaf440
Binary files /dev/null and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ta-IN-time-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/locale/e2e.ts b/core/src/components/datetime/test/locale/e2e.ts
deleted file mode 100644
index 49497ab589..0000000000
--- a/core/src/components/datetime/test/locale/e2e.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import { newE2EPage } from '@stencil/core/testing';
-
-test('locale', async () => {
- const page = await newE2EPage({
- url: '/src/components/datetime/test/locale?ionic:_testing=true',
- });
-
- const screenshotCompares = [];
- const datetime = await page.find('ion-datetime');
-
- screenshotCompares.push(await page.compareScreenshot());
-
- datetime.setProperty('locale', 'es-ES');
- await page.waitForChanges();
-
- screenshotCompares.push(await page.compareScreenshot());
-
- for (const screenshotCompare of screenshotCompares) {
- expect(screenshotCompare).toMatchScreenshot();
- }
-});
-
-test('it should render month and year with an en-US locale', async () => {
- const page = await newE2EPage({
- url: '/src/components/datetime/test/locale?ionic:_testing=true',
- });
-
- const screenshotCompares = [];
- const datetime = await page.find('ion-datetime');
-
- datetime.setProperty('locale', 'en-US');
- await page.waitForChanges();
-
- const button = await page.find('ion-datetime >>> .calendar-month-year ion-item');
- await button.click();
- await page.waitForChanges();
-
- const yearBody = await page.find('ion-datetime >>> .datetime-year-body');
- expect(yearBody).toHaveClass('order-month-first');
-
- screenshotCompares.push(await page.compareScreenshot());
-
- for (const screenshotCompare of screenshotCompares) {
- expect(screenshotCompare).toMatchScreenshot();
- }
-});
-
-test('it should render year and month with a ja-JP locale', async () => {
- const page = await newE2EPage({
- url: '/src/components/datetime/test/locale?ionic:_testing=true',
- });
-
- const screenshotCompares = [];
- const datetime = await page.find('ion-datetime');
-
- datetime.setProperty('locale', 'ja-JP');
- await page.waitForChanges();
-
- const button = await page.find('ion-datetime >>> .calendar-month-year ion-item');
- await button.click();
- await page.waitForChanges();
-
- const yearBody = await page.find('ion-datetime >>> .datetime-year-body');
- expect(yearBody).toHaveClass('order-year-first');
-
- screenshotCompares.push(await page.compareScreenshot());
-
- for (const screenshotCompare of screenshotCompares) {
- expect(screenshotCompare).toMatchScreenshot();
- }
-});
diff --git a/core/src/components/datetime/test/locale/index.html b/core/src/components/datetime/test/locale/index.html
index 1efe928983..9a4f298116 100644
--- a/core/src/components/datetime/test/locale/index.html
+++ b/core/src/components/datetime/test/locale/index.html
@@ -11,9 +11,10 @@
+
Datetime - Locale
+
+
+