diff --git a/CHANGELOG.md b/CHANGELOG.md
index fde95d3ae8..526131caa8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## [6.3.3](https://github.com/ionic-team/ionic-framework/compare/v6.3.2...v6.3.3) (2022-10-26)
+
+
+### Bug Fixes
+
+* **datetime:** empty string is treated as no value ([#26131](https://github.com/ionic-team/ionic-framework/issues/26131)) ([51ab5f6](https://github.com/ionic-team/ionic-framework/commit/51ab5f67b50013c0ed8ca3160d6dfc56bc269f2a)), closes [#26116](https://github.com/ionic-team/ionic-framework/issues/26116)
+* **datetime:** preferWheel can now show title ([#26101](https://github.com/ionic-team/ionic-framework/issues/26101)) ([479d56b](https://github.com/ionic-team/ionic-framework/commit/479d56b3b26d45bfd03d4095458c37ed00485c54)), closes [#26095](https://github.com/ionic-team/ionic-framework/issues/26095)
+* **datetime:** values are adjusted to be in bounds ([#26125](https://github.com/ionic-team/ionic-framework/issues/26125)) ([0548fe8](https://github.com/ionic-team/ionic-framework/commit/0548fe858854f0187e0dfe00efaec142cd5bb6cf)), closes [#25894](https://github.com/ionic-team/ionic-framework/issues/25894) [#25708](https://github.com/ionic-team/ionic-framework/issues/25708)
+* **dependencies:** latest patch is installed ([#26148](https://github.com/ionic-team/ionic-framework/issues/26148)) ([74be79e](https://github.com/ionic-team/ionic-framework/commit/74be79e9d81fd5431ae2fc442fd6387cf37b2015)), closes [#26137](https://github.com/ionic-team/ionic-framework/issues/26137)
+* **many:** haptics only fire on supported platforms ([#26130](https://github.com/ionic-team/ionic-framework/issues/26130)) ([d4d569a](https://github.com/ionic-team/ionic-framework/commit/d4d569ac09ab25ab5a490825cf1fc655fe97bb87)), closes [#26109](https://github.com/ionic-team/ionic-framework/issues/26109)
+* **react:** inline overlays can be conditionally rendered ([#26111](https://github.com/ionic-team/ionic-framework/issues/26111)) ([8ec350a](https://github.com/ionic-team/ionic-framework/commit/8ec350ae652095ae29e2f02a7f105cb709a72583)), closes [#25590](https://github.com/ionic-team/ionic-framework/issues/25590)
+
+
+
+
+
## [6.3.2](https://github.com/ionic-team/ionic-framework/compare/v6.3.1...v6.3.2) (2022-10-17)
diff --git a/angular/CHANGELOG.md b/angular/CHANGELOG.md
index d6c9362498..5c706838f1 100644
--- a/angular/CHANGELOG.md
+++ b/angular/CHANGELOG.md
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## [6.3.3](https://github.com/ionic-team/ionic/compare/v6.3.2...v6.3.3) (2022-10-26)
+
+
+### Bug Fixes
+
+* **datetime:** empty string is treated as no value ([#26131](https://github.com/ionic-team/ionic/issues/26131)) ([51ab5f6](https://github.com/ionic-team/ionic/commit/51ab5f67b50013c0ed8ca3160d6dfc56bc269f2a)), closes [#26116](https://github.com/ionic-team/ionic/issues/26116)
+* **dependencies:** latest patch is installed ([#26148](https://github.com/ionic-team/ionic/issues/26148)) ([74be79e](https://github.com/ionic-team/ionic/commit/74be79e9d81fd5431ae2fc442fd6387cf37b2015)), closes [#26137](https://github.com/ionic-team/ionic/issues/26137)
+
+
+
+
+
## [6.3.2](https://github.com/ionic-team/ionic/compare/v6.3.1...v6.3.2) (2022-10-17)
**Note:** Version bump only for package @ionic/angular
diff --git a/angular/package-lock.json b/angular/package-lock.json
index fc96e1aca9..b9108213ae 100644
--- a/angular/package-lock.json
+++ b/angular/package-lock.json
@@ -1,15 +1,15 @@
{
"name": "@ionic/angular",
- "version": "6.3.2",
+ "version": "6.3.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular",
- "version": "6.3.2",
+ "version": "6.3.3",
"license": "MIT",
"dependencies": {
- "@ionic/core": "^6.3.2",
+ "@ionic/core": "^6.3.3",
"jsonc-parser": "^3.0.0",
"tslib": "^2.0.0"
},
@@ -1023,9 +1023,9 @@
"dev": true
},
"node_modules/@ionic/core": {
- "version": "6.3.2",
- "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.2.tgz",
- "integrity": "sha512-L4xqJyixmGApwYc5fQgGoK80wXGCrbjL8vGfeNbjYqxxP0ZIKGAhURPoMAtSTqLLK9gdhh4Mv6gw4gNKvxodPA==",
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.3.tgz",
+ "integrity": "sha512-I7eRsni/3blStScsQcITb4seuunNzS4mIK0GxHljeRRb8oQI9Xy/oP4rq9weo9lsuEVD0sHIqBIS7/Oo9iEymQ==",
"dependencies": {
"@stencil/core": "^2.18.0",
"ionicons": "^6.0.3",
@@ -7951,9 +7951,9 @@
"dev": true
},
"@ionic/core": {
- "version": "6.3.2",
- "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.2.tgz",
- "integrity": "sha512-L4xqJyixmGApwYc5fQgGoK80wXGCrbjL8vGfeNbjYqxxP0ZIKGAhURPoMAtSTqLLK9gdhh4Mv6gw4gNKvxodPA==",
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.3.tgz",
+ "integrity": "sha512-I7eRsni/3blStScsQcITb4seuunNzS4mIK0GxHljeRRb8oQI9Xy/oP4rq9weo9lsuEVD0sHIqBIS7/Oo9iEymQ==",
"requires": {
"@stencil/core": "^2.18.0",
"ionicons": "^6.0.3",
diff --git a/angular/package.json b/angular/package.json
index ec7bae05e9..4314e2255a 100644
--- a/angular/package.json
+++ b/angular/package.json
@@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
- "version": "6.3.2",
+ "version": "6.3.3",
"description": "Angular specific wrappers for @ionic/core",
"keywords": [
"ionic",
@@ -45,7 +45,7 @@
"validate": "npm i && npm run lint && npm run test && npm run build"
},
"dependencies": {
- "@ionic/core": "^6.3.2",
+ "@ionic/core": "^6.3.3",
"jsonc-parser": "^3.0.0",
"tslib": "^2.0.0"
},
diff --git a/angular/src/directives/control-value-accessors/value-accessor.ts b/angular/src/directives/control-value-accessors/value-accessor.ts
index 615d736828..69e053f343 100644
--- a/angular/src/directives/control-value-accessors/value-accessor.ts
+++ b/angular/src/directives/control-value-accessors/value-accessor.ts
@@ -19,7 +19,7 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
writeValue(value: any): void {
/**
- * TODO for Ionic 6:
+ * TODO FW-2646
* Change `value == null ? '' : value;`
* to `value`. This was a fix for IE9, but IE9
* is no longer supported; however, this change
diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md
index be3589ab7a..a416ba63ca 100644
--- a/core/CHANGELOG.md
+++ b/core/CHANGELOG.md
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## [6.3.3](https://github.com/ionic-team/ionic/compare/v6.3.2...v6.3.3) (2022-10-26)
+
+
+### Bug Fixes
+
+* **datetime:** empty string is treated as no value ([#26131](https://github.com/ionic-team/ionic/issues/26131)) ([51ab5f6](https://github.com/ionic-team/ionic/commit/51ab5f67b50013c0ed8ca3160d6dfc56bc269f2a)), closes [#26116](https://github.com/ionic-team/ionic/issues/26116)
+* **datetime:** preferWheel can now show title ([#26101](https://github.com/ionic-team/ionic/issues/26101)) ([479d56b](https://github.com/ionic-team/ionic/commit/479d56b3b26d45bfd03d4095458c37ed00485c54)), closes [#26095](https://github.com/ionic-team/ionic/issues/26095)
+* **datetime:** values are adjusted to be in bounds ([#26125](https://github.com/ionic-team/ionic/issues/26125)) ([0548fe8](https://github.com/ionic-team/ionic/commit/0548fe858854f0187e0dfe00efaec142cd5bb6cf)), closes [#25894](https://github.com/ionic-team/ionic/issues/25894) [#25708](https://github.com/ionic-team/ionic/issues/25708)
+* **many:** haptics only fire on supported platforms ([#26130](https://github.com/ionic-team/ionic/issues/26130)) ([d4d569a](https://github.com/ionic-team/ionic/commit/d4d569ac09ab25ab5a490825cf1fc655fe97bb87)), closes [#26109](https://github.com/ionic-team/ionic/issues/26109)
+
+
+
+
+
## [6.3.2](https://github.com/ionic-team/ionic/compare/v6.3.1...v6.3.2) (2022-10-17)
diff --git a/core/package-lock.json b/core/package-lock.json
index ad938eceb8..7140e95437 100644
--- a/core/package-lock.json
+++ b/core/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@ionic/core",
- "version": "6.3.2",
+ "version": "6.3.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/core",
- "version": "6.3.2",
+ "version": "6.3.3",
"license": "MIT",
"dependencies": {
"@stencil/core": "^2.18.0",
diff --git a/core/package.json b/core/package.json
index 09e398c4ab..9c630fc5e5 100644
--- a/core/package.json
+++ b/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
- "version": "6.3.2",
+ "version": "6.3.3",
"description": "Base components for Ionic",
"keywords": [
"ionic",
diff --git a/core/src/components/datetime-button/datetime-button.tsx b/core/src/components/datetime-button/datetime-button.tsx
index f4d85c17ef..69f4dba659 100644
--- a/core/src/components/datetime-button/datetime-button.tsx
+++ b/core/src/components/datetime-button/datetime-button.tsx
@@ -160,7 +160,8 @@ export class DatetimeButton implements ComponentInterface {
* to keep checking if the datetime value is `string` or `string[]`.
*/
private getParsedDateValues = (value?: string[] | string | null): string[] => {
- if (value === undefined || value === null) {
+ // TODO FW-2646 Remove value === ''
+ if (value === '' || value === undefined || value === null) {
return [];
}
diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx
index 6420b48d68..e7410c9086 100644
--- a/core/src/components/datetime/datetime.tsx
+++ b/core/src/components/datetime/datetime.tsx
@@ -585,7 +585,7 @@ export class Datetime implements ComponentInterface {
};
private setActiveParts = (parts: DatetimeParts, removeDate = false) => {
- const { multiple, activePartsClone } = this;
+ const { multiple, minParts, maxParts, activePartsClone } = this;
/**
* When setting the active parts, it is possible
@@ -597,7 +597,7 @@ export class Datetime implements ComponentInterface {
* Additionally, we need to update the working parts
* too in the event that the validated parts are different.
*/
- const validatedParts = validateParts(parts);
+ const validatedParts = validateParts(parts, minParts, maxParts);
this.setWorkingParts(validatedParts);
if (multiple) {
@@ -1154,8 +1154,11 @@ export class Datetime implements ComponentInterface {
}
private processValue = (value?: string | string[] | null) => {
- const hasValue = value !== null && value !== undefined;
- let valueToProcess = parseDate(value ?? getToday());
+ /**
+ * TODO FW-2646 remove value !== ''
+ */
+ const hasValue = value !== '' && value !== null && value !== undefined;
+ let valueToProcess = parseDate(hasValue ? value : getToday());
const { minParts, maxParts, multiple } = this;
if (!multiple && Array.isArray(value)) {
@@ -2102,12 +2105,8 @@ export class Datetime implements ComponentInterface {
,
];
}
- private renderCalendarViewHeader() {
- const hasSlottedTitle = this.el.querySelector('[slot="title"]') !== null;
- if (!hasSlottedTitle && !this.showDefaultTitle) {
- return;
- }
+ private getHeaderSelectedDateText() {
const { activeParts, multiple, titleSelectedDatesFormatter } = this;
const isArray = Array.isArray(activeParts);
@@ -2126,12 +2125,21 @@ export class Datetime implements ComponentInterface {
headerText = getMonthAndDay(this.locale, this.getDefaultPart());
}
+ return headerText;
+ }
+
+ private renderCalendarViewHeader(showExpandedHeader = true) {
+ const hasSlottedTitle = this.el.querySelector('[slot="title"]') !== null;
+ if (!hasSlottedTitle && !this.showDefaultTitle) {
+ return;
+ }
+
return (
);
}
@@ -2178,7 +2186,7 @@ export class Datetime implements ComponentInterface {
*/
const hasWheelVariant = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
if (preferWheel && hasWheelVariant) {
- return [this.renderWheelView(), this.renderFooter()];
+ return [this.renderCalendarViewHeader(false), this.renderWheelView(), this.renderFooter()];
}
switch (presentation) {
diff --git a/core/src/components/datetime/test/manipulation.spec.ts b/core/src/components/datetime/test/manipulation.spec.ts
index 864ba4b775..f2c8188295 100644
--- a/core/src/components/datetime/test/manipulation.spec.ts
+++ b/core/src/components/datetime/test/manipulation.spec.ts
@@ -14,6 +14,7 @@ import {
calculateHourFromAMPM,
subtractDays,
addDays,
+ validateParts,
} from '../utils/manipulation';
describe('addDays()', () => {
@@ -487,3 +488,72 @@ describe('getPreviousYear()', () => {
});
});
});
+
+describe('validateParts()', () => {
+ it('should move day in bounds', () => {
+ expect(validateParts({ month: 2, day: 31, year: 2022, hour: 8, minute: 0 })).toEqual({
+ month: 2,
+ day: 28,
+ year: 2022,
+ hour: 8,
+ minute: 0,
+ });
+ });
+ it('should move the hour back in bounds according to the min', () => {
+ expect(
+ validateParts(
+ { month: 1, day: 1, year: 2022, hour: 8, minute: 0 },
+ { month: 1, day: 1, year: 2022, hour: 9, minute: 0 }
+ )
+ ).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 0 });
+ });
+ it('should move the minute back in bounds according to the min', () => {
+ expect(
+ validateParts(
+ { month: 1, day: 1, year: 2022, hour: 9, minute: 20 },
+ { month: 1, day: 1, year: 2022, hour: 9, minute: 30 }
+ )
+ ).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
+ });
+ it('should move the hour and minute back in bounds according to the min', () => {
+ expect(
+ validateParts(
+ { month: 1, day: 1, year: 2022, hour: 8, minute: 30 },
+ { month: 1, day: 1, year: 2022, hour: 9, minute: 0 }
+ )
+ ).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 0 });
+ });
+ it('should move the hour back in bounds according to the max', () => {
+ expect(
+ validateParts({ month: 1, day: 1, year: 2022, hour: 10, minute: 0 }, undefined, {
+ month: 1,
+ day: 1,
+ year: 2022,
+ hour: 9,
+ minute: 0,
+ })
+ ).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 0 });
+ });
+ it('should move the minute back in bounds according to the max', () => {
+ expect(
+ validateParts({ month: 1, day: 1, year: 2022, hour: 9, minute: 40 }, undefined, {
+ month: 1,
+ day: 1,
+ year: 2022,
+ hour: 9,
+ minute: 30,
+ })
+ ).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
+ });
+ it('should move the hour and minute back in bounds according to the max', () => {
+ expect(
+ validateParts({ month: 1, day: 1, year: 2022, hour: 10, minute: 20 }, undefined, {
+ month: 1,
+ day: 1,
+ year: 2022,
+ hour: 9,
+ minute: 30,
+ })
+ ).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
+ });
+});
diff --git a/core/src/components/datetime/test/minmax/datetime.e2e.ts b/core/src/components/datetime/test/minmax/datetime.e2e.ts
index 7cc7207a19..27e39281bb 100644
--- a/core/src/components/datetime/test/minmax/datetime.e2e.ts
+++ b/core/src/components/datetime/test/minmax/datetime.e2e.ts
@@ -234,4 +234,53 @@ test.describe('datetime: minmax', () => {
);
await expect(hourPickerItems).toHaveText(['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']);
});
+
+ test.describe('minmax value adjustment when out of bounds', () => {
+ test.beforeEach(({ skip }) => {
+ skip.rtl();
+ skip.mode('ios', 'This implementation is the same across modes.');
+ });
+ test('should reset to min time if out of bounds', async ({ page }) => {
+ await page.setContent(`
+
+ `);
+
+ await page.waitForSelector('.datetime-ready');
+
+ const datetime = page.locator('ion-datetime');
+ const ionChange = await page.spyOnEvent('ionChange');
+ const dayButton = page.locator('ion-datetime .calendar-day[data-day="10"][data-month="10"][data-year="2022"]');
+ await dayButton.click();
+
+ await ionChange.next();
+
+ const value = await datetime.evaluate((el: HTMLIonDatetimeElement) => el.value);
+ await expect(typeof value).toBe('string');
+ await expect(value!.includes('2022-10-10T08:00')).toBe(true);
+ });
+ test('should reset to max time if out of bounds', async ({ page }) => {
+ await page.setContent(`
+
+ `);
+
+ await page.waitForSelector('.datetime-ready');
+
+ const datetime = page.locator('ion-datetime');
+ const ionChange = await page.spyOnEvent('ionChange');
+ const dayButton = page.locator('ion-datetime .calendar-day[data-day="10"][data-month="10"][data-year="2022"]');
+ await dayButton.click();
+
+ await ionChange.next();
+
+ const value = await datetime.evaluate((el: HTMLIonDatetimeElement) => el.value);
+ await expect(typeof value).toBe('string');
+ await expect(value!.includes('2022-10-10T08:00')).toBe(true);
+ });
+ });
});
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts
index e39f139dc3..e7102c402a 100644
--- a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts
+++ b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts
@@ -40,6 +40,18 @@ test.describe('datetime: prefer wheel', () => {
`datetime-wheel-time-date-diff-${page.getSnapshotSettings()}.png`
);
});
+ test('should render a condense header when specified', async ({ page }) => {
+ await page.setContent(`
+ My Custom Title
+ `);
+ await page.waitForSelector('.datetime-ready');
+
+ const datetime = page.locator('ion-datetime');
+
+ expect(await datetime.screenshot()).toMatchSnapshot(
+ `datetime-wheel-header-diff-${page.getSnapshotSettings()}.png`
+ );
+ });
});
test.describe('datetime: date wheel', () => {
test.beforeEach(({ skip }) => {
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..15ee7c6f00
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..58e06f8ca5
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..8d7aeab63f
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..d3fc7ed8be
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..59d83e1156
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..c98821778f
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..0bd51d34c7
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..b15b79f4f8
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..e9127f64bc
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..fbb775b6e0
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..26b68c42de
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..0cd4974b4b
Binary files /dev/null and b/core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts-snapshots/datetime-wheel-header-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/datetime/test/values/datetime.e2e.ts b/core/src/components/datetime/test/values/datetime.e2e.ts
index 788e5692f7..42c23da19c 100644
--- a/core/src/components/datetime/test/values/datetime.e2e.ts
+++ b/core/src/components/datetime/test/values/datetime.e2e.ts
@@ -50,3 +50,17 @@ test.describe('datetime: values', () => {
await expect(items).toHaveText(['01', '02', '03']);
});
});
+
+test('setting value to empty string should treat it as having no date', async ({ page, skip }) => {
+ skip.rtl();
+ skip.mode('ios');
+ await page.setContent(`
+
+ `);
+
+ await page.waitForSelector('.datetime-ready');
+
+ // Should render current month with today outlined.
+ const calendarDayToday = page.locator('ion-datetime .calendar-day-today');
+ await expect(calendarDayToday).toBeVisible();
+});
diff --git a/core/src/components/datetime/utils/manipulation.ts b/core/src/components/datetime/utils/manipulation.ts
index 98f25750af..34ac4af7d4 100644
--- a/core/src/components/datetime/utils/manipulation.ts
+++ b/core/src/components/datetime/utils/manipulation.ts
@@ -1,5 +1,6 @@
import type { DatetimeParts } from '../datetime-interface';
+import { isSameDay } from './comparison';
import { getNumDaysInMonth } from './helpers';
const twoDigit = (val: number | undefined): string => {
@@ -345,7 +346,11 @@ export const calculateHourFromAMPM = (currentParts: DatetimeParts, newAMPM: 'am'
* values are valid. For days that do not exist,
* the closest valid day is used.
*/
-export const validateParts = (parts: DatetimeParts): DatetimeParts => {
+export const validateParts = (
+ parts: DatetimeParts,
+ minParts?: DatetimeParts,
+ maxParts?: DatetimeParts
+): DatetimeParts => {
const { month, day, year } = parts;
const partsCopy = { ...parts };
@@ -361,5 +366,66 @@ export const validateParts = (parts: DatetimeParts): DatetimeParts => {
partsCopy.day = numDays;
}
+ /**
+ * If value is same day as min day,
+ * make sure the time value is in bounds.
+ */
+ if (minParts !== undefined && isSameDay(partsCopy, minParts)) {
+ /**
+ * If the hour is out of bounds,
+ * update both the hour and minute.
+ * This is done so that the new time
+ * is closest to what the user selected.
+ */
+ if (partsCopy.hour !== undefined && minParts.hour !== undefined) {
+ if (partsCopy.hour < minParts.hour) {
+ partsCopy.hour = minParts.hour;
+ partsCopy.minute = minParts.minute;
+
+ /**
+ * If only the minute is out of bounds,
+ * set it to the min minute.
+ */
+ } else if (
+ partsCopy.hour === minParts.hour &&
+ partsCopy.minute !== undefined &&
+ minParts.minute !== undefined &&
+ partsCopy.minute < minParts.minute
+ ) {
+ partsCopy.minute = minParts.minute;
+ }
+ }
+ }
+
+ /**
+ * If value is same day as max day,
+ * make sure the time value is in bounds.
+ */
+ if (maxParts !== undefined && isSameDay(parts, maxParts)) {
+ /**
+ * If the hour is out of bounds,
+ * update both the hour and minute.
+ * This is done so that the new time
+ * is closest to what the user selected.
+ */
+ if (partsCopy.hour !== undefined && maxParts.hour !== undefined) {
+ if (partsCopy.hour > maxParts.hour) {
+ partsCopy.hour = maxParts.hour;
+ partsCopy.minute = maxParts.minute;
+ /**
+ * If only the minute is out of bounds,
+ * set it to the max minute.
+ */
+ } else if (
+ partsCopy.hour === maxParts.hour &&
+ partsCopy.minute !== undefined &&
+ maxParts.minute !== undefined &&
+ partsCopy.minute > maxParts.minute
+ ) {
+ partsCopy.minute = maxParts.minute;
+ }
+ }
+ }
+
return partsCopy;
};
diff --git a/core/src/components/footer/test/basic/e2e.ts b/core/src/components/footer/test/basic/e2e.ts
deleted file mode 100644
index 82cc1c55ee..0000000000
--- a/core/src/components/footer/test/basic/e2e.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { newE2EPage } from '@stencil/core/testing';
-
-test('footer: basic', async () => {
- const page = await newE2EPage({
- url: '/src/components/footer/test/basic?ionic:_testing=true',
- });
-
- const compare = await page.compareScreenshot();
- expect(compare).toMatchScreenshot();
-});
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts b/core/src/components/footer/test/basic/footer.e2e.ts
new file mode 100644
index 0000000000..155bb94ab2
--- /dev/null
+++ b/core/src/components/footer/test/basic/footer.e2e.ts
@@ -0,0 +1,57 @@
+import { expect } from '@playwright/test';
+import { test } from '@utils/test/playwright';
+
+test.describe('footer: basic', () => {
+ test.describe('footer: rendering', () => {
+ test('should not have visual regressions with basic footer', async ({ page }) => {
+ await page.setContent(`
+
+
+ Footer - Default
+
+
+ `);
+
+ const footer = page.locator('ion-footer');
+ expect(await footer.screenshot()).toMatchSnapshot(`footer-diff-${page.getSnapshotSettings()}.png`);
+ });
+ });
+
+ test.describe('footer: feature rendering', () => {
+ test.beforeEach(({ skip }) => {
+ skip.rtl();
+ });
+
+ test('should not have visual regressions with no border', async ({ page }) => {
+ await page.setContent(`
+
+
+ Footer - No Border
+
+
+ `);
+
+ const footer = page.locator('ion-footer');
+ expect(await footer.screenshot()).toMatchSnapshot(`footer-no-border-diff-${page.getSnapshotSettings()}.png`);
+ });
+
+ test('should not have visual regressions with translucent footer', async ({ page, skip }) => {
+ skip.mode('md', 'Translucent effect is only available in iOS mode.');
+ skip.browser('firefox', 'Firefox has some issues rendering translucent effects on Linux.');
+
+ await page.setContent(`
+
+
+

+
+
+ Footer - Translucent
+
+
+ `);
+
+ const footer = page.locator('ion-footer');
+ expect(await footer.screenshot()).toMatchSnapshot(`footer-translucent-diff-${page.getSnapshotSettings()}.png`);
+ });
+ });
+});
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..eaf5115dda
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..194e58051d
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..64ecaa0fe1
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..eaf5115dda
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..194e58051d
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Safari-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..64ecaa0fe1
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..cae9bfb58f
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..20aa854180
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..f52c7d0a07
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Chrome-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..433f06246d
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Firefox-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..c1355394d9
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Safari-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..8176f1ea20
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-diff-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..432dccd7e7
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..9267557401
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..164e1152aa
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Chrome-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..3cbe28a291
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Firefox-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..97a42667e9
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Safari-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..d32036669e
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-no-border-diff-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-translucent-diff-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-translucent-diff-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..3e0375dc6a
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-translucent-diff-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-translucent-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-translucent-diff-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..615344ad8d
Binary files /dev/null and b/core/src/components/footer/test/basic/footer.e2e.ts-snapshots/footer-translucent-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/footer/test/basic/index.html b/core/src/components/footer/test/basic/index.html
index 669c4070a9..7929cd8426 100644
--- a/core/src/components/footer/test/basic/index.html
+++ b/core/src/components/footer/test/basic/index.html
@@ -15,23 +15,14 @@
-
-
-
-
-
- Footer - Default
-
-
-
-
-
-
-
- Footer - No Border
-
-
+
+ Content
+
+
+ Footer
+
+