chore(): sync feature-7.0 with main
chore(): sync feature-7.0 with main
2
.github/CODEOWNERS
vendored
@@ -12,4 +12,4 @@
|
||||
# This should make it easy to add new rules without breaking existing ones.
|
||||
|
||||
# Global owners
|
||||
* @ionic-team/framework-core
|
||||
* @ionic-team/framework
|
||||
|
||||
19
CHANGELOG.md
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.2.8](https://github.com/ionic-team/ionic-framework/compare/v6.2.7...v6.2.8) (2022-09-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** account for 12AM with min times and 12 hour format ([#25952](https://github.com/ionic-team/ionic-framework/issues/25952)) ([55ebd6c](https://github.com/ionic-team/ionic-framework/commit/55ebd6cdf39c01b401e876b76e755bfa04db8f65)), closes [#25183](https://github.com/ionic-team/ionic-framework/issues/25183)
|
||||
* **item:** show the highlight on iOS when --highlight-height is set ([#25905](https://github.com/ionic-team/ionic-framework/issues/25905)) ([d7db133](https://github.com/ionic-team/ionic-framework/commit/d7db1333f13834ecb447b4b1da62cfffed9fb333))
|
||||
* **overlays:** focus trapping no longer includes disabled elements ([#25949](https://github.com/ionic-team/ionic-framework/issues/25949)) ([6cb5827](https://github.com/ionic-team/ionic-framework/commit/6cb5827d069c255ab0a9a8c319aba9994a4c5196))
|
||||
* **overlays:** focus trapping no longer includes hidden elements ([#25948](https://github.com/ionic-team/ionic-framework/issues/25948)) ([5c10f98](https://github.com/ionic-team/ionic-framework/commit/5c10f98ceb3ae42d3363b38ba786b9122676a59c))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **card:** avoid force compositing on ios ([#25942](https://github.com/ionic-team/ionic-framework/issues/25942)) ([174c3b3](https://github.com/ionic-team/ionic-framework/commit/174c3b30a0bce7e7ab13e5605348ec107af69dd6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.2.7](https://github.com/ionic-team/ionic-framework/compare/v6.2.6...v6.2.7) (2022-09-14)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.2.8](https://github.com/ionic-team/ionic/compare/v6.2.7...v6.2.8) (2022-09-21)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.2.7](https://github.com/ionic-team/ionic/compare/v6.2.6...v6.2.7) (2022-09-14)
|
||||
|
||||
|
||||
|
||||
18
angular/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.7",
|
||||
"version": "6.2.8",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.7",
|
||||
"version": "6.2.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.2.7",
|
||||
"@ionic/core": "^6.2.8",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
@@ -1023,9 +1023,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "6.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.7.tgz",
|
||||
"integrity": "sha512-pQWcIqr5zfCX5De/MQ9kFs+nhaPCr8HIh5QjmydxvmlLv6WU4vlny/Mg0y1+JwLE0qxPD0T9sMykawWH9e3y5Q==",
|
||||
"version": "6.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.8.tgz",
|
||||
"integrity": "sha512-tUUdvCPo9Z4RQXjvxNXBXQsVTFDAH2ju/HAhzZiAvdfwpHfpA39DWkXwAQeoV9gfFFblaOmCmeSq/8JP/FRn4A==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.17.4",
|
||||
"ionicons": "^6.0.3",
|
||||
@@ -7951,9 +7951,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "6.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.7.tgz",
|
||||
"integrity": "sha512-pQWcIqr5zfCX5De/MQ9kFs+nhaPCr8HIh5QjmydxvmlLv6WU4vlny/Mg0y1+JwLE0qxPD0T9sMykawWH9e3y5Q==",
|
||||
"version": "6.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.8.tgz",
|
||||
"integrity": "sha512-tUUdvCPo9Z4RQXjvxNXBXQsVTFDAH2ju/HAhzZiAvdfwpHfpA39DWkXwAQeoV9gfFFblaOmCmeSq/8JP/FRn4A==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.17.4",
|
||||
"ionicons": "^6.0.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.7",
|
||||
"version": "6.2.8",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -44,7 +44,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.2.7",
|
||||
"@ionic/core": "^6.2.8",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.2.8](https://github.com/ionic-team/ionic/compare/v6.2.7...v6.2.8) (2022-09-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** account for 12AM with min times and 12 hour format ([#25952](https://github.com/ionic-team/ionic/issues/25952)) ([55ebd6c](https://github.com/ionic-team/ionic/commit/55ebd6cdf39c01b401e876b76e755bfa04db8f65)), closes [#25183](https://github.com/ionic-team/ionic/issues/25183)
|
||||
* **item:** show the highlight on iOS when --highlight-height is set ([#25905](https://github.com/ionic-team/ionic/issues/25905)) ([d7db133](https://github.com/ionic-team/ionic/commit/d7db1333f13834ecb447b4b1da62cfffed9fb333))
|
||||
* **overlays:** focus trapping no longer includes disabled elements ([#25949](https://github.com/ionic-team/ionic/issues/25949)) ([6cb5827](https://github.com/ionic-team/ionic/commit/6cb5827d069c255ab0a9a8c319aba9994a4c5196))
|
||||
* **overlays:** focus trapping no longer includes hidden elements ([#25948](https://github.com/ionic-team/ionic/issues/25948)) ([5c10f98](https://github.com/ionic-team/ionic/commit/5c10f98ceb3ae42d3363b38ba786b9122676a59c))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **card:** avoid force compositing on ios ([#25942](https://github.com/ionic-team/ionic/issues/25942)) ([174c3b3](https://github.com/ionic-team/ionic/commit/174c3b30a0bce7e7ab13e5605348ec107af69dd6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.2.7](https://github.com/ionic-team/ionic/compare/v6.2.6...v6.2.7) (2022-09-14)
|
||||
|
||||
|
||||
|
||||
4
core/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "6.2.7",
|
||||
"version": "6.2.8",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "6.2.7",
|
||||
"version": "6.2.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.17.4",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "6.2.7",
|
||||
"version": "6.2.8",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('card-header: basic', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/card-header/test/basic`);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`card-header-diff-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 90 KiB |
@@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('card-header: basic', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/card-header/test/basic?ionic:_testing=true',
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -47,14 +47,6 @@
|
||||
</ion-card-header>
|
||||
<ion-card-content> Custom background, color=secondary on ion-card-header </ion-card-content>
|
||||
</ion-card>
|
||||
|
||||
<ion-card color="danger">
|
||||
<ion-card-header>
|
||||
<ion-card-subtitle>Card Subtitle</ion-card-subtitle>
|
||||
<ion-card-title>Card Title</ion-card-title>
|
||||
</ion-card-header>
|
||||
<ion-card-content> color=danger on ion-card-header </ion-card-content>
|
||||
</ion-card>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
<style>
|
||||
|
||||
15
core/src/components/content/test/basic/content.e2e.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('content: basic', () => {
|
||||
test('should not have visual regressions', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('ios', 'ion-content does not have mode-specific styling');
|
||||
|
||||
await page.goto(`/src/components/content/test/basic`);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`content-diff-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 51 KiB |
@@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('content: basic', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/content/test/basic?ionic:_testing=true',
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -29,7 +29,6 @@
|
||||
<ion-content class="ion-padding" style="text-align: center; flex: 2" id="content">
|
||||
<ion-content id="content-part">
|
||||
<f style="height: 50%"></f>
|
||||
<ion-button onclick="toggleFullscreen()">Toggle content.fullscreen</ion-button>
|
||||
<p>
|
||||
<ion-button onclick="toggleDisplay('header')" color="secondary">Toggle header</ion-button>
|
||||
<ion-button onclick="toggleDisplay('footer')" color="secondary">Toggle footer</ion-button>
|
||||
@@ -45,11 +44,6 @@
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
<f></f>
|
||||
</ion-content>
|
||||
</ion-content>
|
||||
<ion-content class="ion-padding" style="display: none" id="content3">
|
||||
@@ -79,16 +73,7 @@
|
||||
|
||||
<script>
|
||||
const content = document.getElementById('content');
|
||||
content.scrollEvents = true;
|
||||
content.addEventListener('ionScrollStart', () => console.log('scroll start'));
|
||||
content.addEventListener('ionScroll', (ev) => console.log('scroll', ev.detail));
|
||||
content.addEventListener('ionScrollEnd', () => console.log('scroll end'));
|
||||
|
||||
function toggleFullscreen() {
|
||||
const content = document.getElementById('content');
|
||||
content.fullscreen = !content.fullscreen;
|
||||
console.log('content.fullscren =', content.fullscreen);
|
||||
}
|
||||
function toggleDisplay(id) {
|
||||
const el = document.getElementById(id);
|
||||
el.style.display = !el.style.display ? 'none' : null;
|
||||
|
||||
14
core/src/components/content/test/fixed/content.e2e.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('content: fixed', () => {
|
||||
test('should not have visual regressions', async ({ page, skip }) => {
|
||||
skip.mode('ios', 'ion-content does not have mode-specific styling');
|
||||
|
||||
await page.goto(`/src/components/content/test/fixed`);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`content-fixed-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 60 KiB |
@@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('content: fixed', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/content/test/fixed?ionic:_testing=true',
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -27,7 +27,7 @@
|
||||
<div slot="fixed">
|
||||
<h1>Fixed content</h1>
|
||||
<p>Fixed paragraph</p>
|
||||
<ion-button>Button</ion-button>
|
||||
<ion-button>Fixed button</ion-button>
|
||||
</div>
|
||||
<ion-fab vertical="top" horizontal="end" slot="fixed">
|
||||
<ion-fab-button>
|
||||
|
||||
15
core/src/components/content/test/fullscreen/content.e2e.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('content: fullscreen', () => {
|
||||
test('should not have visual regressions', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('ios', 'ion-content does not have mode-specific styling');
|
||||
|
||||
await page.goto(`/src/components/content/test/fullscreen`);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`content-fullscreen-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 335 KiB |
|
After Width: | Height: | Size: 920 KiB |
@@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('content: fullscreen', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/content/test/fullscreen?ionic:_testing=true',
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -49,18 +49,6 @@
|
||||
Integer luctus faucibus nunc, non mattis nisl consectetur at. Interdum et malesuada fames ac ante ipsum primis
|
||||
in faucibus.
|
||||
</p>
|
||||
<p>
|
||||
Suspendisse et arcu nec odio lobortis lacinia a congue ligula. Duis libero lacus, blandit ac lectus et,
|
||||
laoreet condimentum est. Suspendisse potenti. Praesent ligula dui, laoreet sed pellentesque vitae, congue at
|
||||
leo. Mauris pharetra, tellus vel viverra viverra, tellus felis mollis magna, volutpat pharetra augue nunc a
|
||||
dolor. Donec ex turpis, iaculis id consectetur quis, posuere a purus. Morbi eu massa sed erat tristique
|
||||
hendrerit. Morbi eleifend, nisi eleifend condimentum euismod, lacus erat porta arcu, consequat rutrum ipsum
|
||||
arcu at metus. Sed tellus nulla, pellentesque sit amet justo at, venenatis imperdiet dui. Aenean odio eros,
|
||||
posuere at dui pharetra, laoreet posuere nulla. Vestibulum interdum odio eu odio ornare, quis maximus lacus
|
||||
semper. Quisque purus dolor, ullamcorper mollis lorem at, sodales aliquet velit. Interdum et malesuada fames
|
||||
ac ante ipsum primis in faucibus. Vivamus purus felis, elementum ut est ut, finibus sagittis tellus. Etiam
|
||||
neque mauris, lobortis sed orci in, dictum eleifend turpis. Morbi eu odio quis mauris gravida tristique.
|
||||
</p>
|
||||
<p>
|
||||
Vestibulum blandit quam a odio lobortis dictum. Nulla pellentesque mauris ornare neque ultricies sagittis.
|
||||
Aenean molestie placerat fermentum. Morbi ac tortor vel felis imperdiet suscipit. Ut id pellentesque nulla.
|
||||
|
||||
15
core/src/components/content/test/standalone/content.e2e.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('content: standalone', () => {
|
||||
test('should not have visual regressions', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('ios', 'ion-content does not have mode-specific styling');
|
||||
|
||||
await page.goto(`/src/components/content/test/standalone`);
|
||||
|
||||
expect(await page.screenshot({ fullPage: true })).toMatchSnapshot(
|
||||
`content-standalone-${page.getSnapshotSettings()}.png`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 56 KiB |
@@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('content: standalone', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/content/test/standalone?ionic:_testing=true',
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -53,46 +53,11 @@
|
||||
</ion-content>
|
||||
</div>
|
||||
|
||||
<div class="content-height">
|
||||
<ion-content class="ion-padding outer-content">
|
||||
<h1>Heading</h1>
|
||||
<h2>Heading</h2>
|
||||
<h3>Heading</h3>
|
||||
<hr />
|
||||
<h4>Heading</h4>
|
||||
<h5>Heading</h5>
|
||||
<h6>Heading</h6>
|
||||
<p>Paragraph</p>
|
||||
</ion-content>
|
||||
</div>
|
||||
|
||||
<div class="content-height">
|
||||
<ion-content class="ion-padding outer-content">
|
||||
<h1>Heading</h1>
|
||||
<h2>Heading</h2>
|
||||
<h3>Heading</h3>
|
||||
<hr />
|
||||
<h4>Heading</h4>
|
||||
<h5>Heading</h5>
|
||||
<h6>Heading</h6>
|
||||
<p>Paragraph</p>
|
||||
</ion-content>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.content-height {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
/* TODO should this be in content? */
|
||||
ion-content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.outer-content {
|
||||
--background: #f2f2f2;
|
||||
}
|
||||
|
||||
.custom-color {
|
||||
--background: blue;
|
||||
--color: white;
|
||||
|
||||
@@ -45,6 +45,7 @@ import {
|
||||
getPreviousWeek,
|
||||
getPreviousYear,
|
||||
getStartOfWeek,
|
||||
validateParts,
|
||||
} from './utils/manipulation';
|
||||
import {
|
||||
clampDate,
|
||||
@@ -583,6 +584,19 @@ export class Datetime implements ComponentInterface {
|
||||
private setActiveParts = (parts: DatetimeParts, removeDate = false) => {
|
||||
const { multiple, activePartsClone, highlightActiveParts } = this;
|
||||
|
||||
/**
|
||||
* When setting the active parts, it is possible
|
||||
* to set invalid data. For example,
|
||||
* when updating January 31 to February,
|
||||
* February 31 does not exist. As a result
|
||||
* we need to validate the active parts and
|
||||
* ensure that we are only setting valid dates.
|
||||
* Additionally, we need to update the working parts
|
||||
* too in the event that the validated parts are different.
|
||||
*/
|
||||
const validatedParts = validateParts(parts);
|
||||
this.setWorkingParts(validatedParts);
|
||||
|
||||
if (multiple) {
|
||||
/**
|
||||
* We read from activePartsClone here because valueChanged() only updates that,
|
||||
@@ -595,20 +609,20 @@ export class Datetime implements ComponentInterface {
|
||||
*/
|
||||
const activePartsArray = Array.isArray(activePartsClone) ? activePartsClone : [activePartsClone];
|
||||
if (removeDate) {
|
||||
this.activeParts = activePartsArray.filter((p) => !isSameDay(p, parts));
|
||||
this.activeParts = activePartsArray.filter((p) => !isSameDay(p, validatedParts));
|
||||
} else if (highlightActiveParts) {
|
||||
this.activeParts = [...activePartsArray, parts];
|
||||
this.activeParts = [...activePartsArray, validatedParts];
|
||||
} 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];
|
||||
this.activeParts = [validatedParts];
|
||||
}
|
||||
} else {
|
||||
this.activeParts = {
|
||||
...parts,
|
||||
...validatedParts,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ describe('generateTime()', () => {
|
||||
};
|
||||
const { hours, minutes } = generateTime(today, 'h12', min);
|
||||
|
||||
expect(hours.length).toEqual(11);
|
||||
expect(hours.length).toEqual(10);
|
||||
expect(minutes.length).toEqual(60);
|
||||
});
|
||||
it('should not filter according to min if not on reference day', () => {
|
||||
@@ -103,7 +103,7 @@ describe('generateTime()', () => {
|
||||
};
|
||||
const { hours, minutes } = generateTime(today, 'h12', undefined, max);
|
||||
|
||||
expect(hours.length).toEqual(7);
|
||||
expect(hours.length).toEqual(8);
|
||||
expect(minutes.length).toEqual(45);
|
||||
});
|
||||
it('should not filter according to min if not on reference day', () => {
|
||||
|
||||
48
core/src/components/datetime/test/datetime.e2e.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('datetime: switching months with different number of days', () => {
|
||||
test.beforeEach(async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('ios');
|
||||
|
||||
await page.setContent(`
|
||||
<ion-datetime locale="en-US" presentation="date" value="2022-01-31"></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
});
|
||||
|
||||
test('should switch the calendar header when moving to a month with a different number of days', async ({ page }) => {
|
||||
const monthYearToggle = page.locator('ion-datetime .calendar-month-year');
|
||||
const monthColumnItems = page.locator('ion-datetime .month-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
await expect(monthYearToggle).toContainText('January 2022');
|
||||
|
||||
await monthYearToggle.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
// February
|
||||
await monthColumnItems.nth(1).click();
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(monthYearToggle).toContainText('February 2022');
|
||||
});
|
||||
|
||||
test('should adjust the selected day when moving to a month with a different number of days', async ({ page }) => {
|
||||
const monthYearToggle = page.locator('ion-datetime .calendar-month-year');
|
||||
const monthColumnItems = page.locator('ion-datetime .month-column .picker-item:not(.picker-item-empty)');
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
|
||||
await monthYearToggle.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
// February
|
||||
await monthColumnItems.nth(1).click();
|
||||
|
||||
await ionChange.next();
|
||||
await expect(ionChange).toHaveReceivedEventTimes(1);
|
||||
await expect(datetime).toHaveJSProperty('value', '2022-02-28');
|
||||
});
|
||||
});
|
||||
@@ -57,7 +57,7 @@ describe('getMonthAndDay()', () => {
|
||||
describe('getFormattedHour()', () => {
|
||||
it('should only add padding if using 24 hour time', () => {
|
||||
expect(getFormattedHour(0, true)).toEqual('00');
|
||||
expect(getFormattedHour(0, false)).toEqual('0');
|
||||
expect(getFormattedHour(0, false)).toEqual('12');
|
||||
|
||||
expect(getFormattedHour(10, true)).toEqual('10');
|
||||
expect(getFormattedHour(10, false)).toEqual('10');
|
||||
|
||||
@@ -188,4 +188,50 @@ test.describe('datetime: minmax', () => {
|
||||
|
||||
await expect(datetimeMonthDidChange).toHaveReceivedEventTimes(1);
|
||||
});
|
||||
|
||||
test('should not include 12AM when minimum is greater than 12AM', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/25183',
|
||||
});
|
||||
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="time"
|
||||
min="2022-04-25T08:30:00"
|
||||
max="2022-04-25T21:30:00"
|
||||
value="2022-04-25T08:30:00"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
const hourPickerItems = page.locator(
|
||||
'ion-datetime ion-picker-column-internal:first-of-type .picker-item:not(.picker-item-empty)'
|
||||
);
|
||||
await expect(hourPickerItems).toHaveText(['8', '9', '10', '11']);
|
||||
});
|
||||
|
||||
test('should include 12PM when minimum is greater than 12', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/25183',
|
||||
});
|
||||
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
locale="en-US"
|
||||
presentation="time"
|
||||
min="2022-07-29T08:00:00"
|
||||
value="2022-07-29T12:00:00"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
const hourPickerItems = page.locator(
|
||||
'ion-datetime ion-picker-column-internal:first-of-type .picker-item:not(.picker-item-empty)'
|
||||
);
|
||||
await expect(hourPickerItems).toHaveText(['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@ const minutes = [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
];
|
||||
const hour12 = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
||||
const hour12 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
||||
const hour23 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23];
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,16 +49,26 @@ export const addTimePadding = (value: number): string => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the hour value so that it
|
||||
* is always 2 digits. Only applies
|
||||
* if using 12 hour format.
|
||||
* Formats 24 hour times so that
|
||||
* it always has 2 digits. For
|
||||
* 12 hour times it ensures that
|
||||
* hour 0 is formatted as '12'.
|
||||
*/
|
||||
export const getFormattedHour = (hour: number, use24Hour: boolean): string => {
|
||||
if (!use24Hour) {
|
||||
return hour.toString();
|
||||
if (use24Hour) {
|
||||
return addTimePadding(hour);
|
||||
}
|
||||
|
||||
return addTimePadding(hour);
|
||||
/**
|
||||
* If using 12 hour
|
||||
* format, make sure hour
|
||||
* 0 is formatted as '12'.
|
||||
*/
|
||||
if (hour === 0) {
|
||||
return '12';
|
||||
}
|
||||
|
||||
return hour.toString();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -339,3 +339,27 @@ export const calculateHourFromAMPM = (currentParts: DatetimeParts, newAMPM: 'am'
|
||||
|
||||
return newHour;
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates parts to ensure that month and day
|
||||
* values are valid. For days that do not exist,
|
||||
* the closest valid day is used.
|
||||
*/
|
||||
export const validateParts = (parts: DatetimeParts): DatetimeParts => {
|
||||
const { month, day, year } = parts;
|
||||
const partsCopy = { ...parts };
|
||||
|
||||
const numDays = getNumDaysInMonth(month, year);
|
||||
|
||||
/**
|
||||
* If the max number of days
|
||||
* is greater than the day we want
|
||||
* to set, update the DatetimeParts
|
||||
* day field to be the max days.
|
||||
*/
|
||||
if (day !== null && numDays < day) {
|
||||
partsCopy.day = numDays;
|
||||
}
|
||||
|
||||
return partsCopy;
|
||||
};
|
||||
|
||||
16
core/src/components/fab-button/test/a11y/fab-button.e2e.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('fab-button: aria attributes', () => {
|
||||
test('should inherit aria attributes to inner button', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('ios');
|
||||
|
||||
await page.setContent(`
|
||||
<ion-fab-button aria-label="Hello World">My Button</ion-fab-button>
|
||||
`);
|
||||
|
||||
const nativeButton = page.locator('ion-fab-button button');
|
||||
await expect(nativeButton).toHaveAttribute('aria-label', 'Hello World');
|
||||
});
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
import { newSpecPage } from '@stencil/core/testing';
|
||||
|
||||
import { FabButton } from '../fab-button';
|
||||
|
||||
describe('fab-button: aria attributes', () => {
|
||||
it('should inherit aria attributes to inner <button>', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [FabButton],
|
||||
html: `
|
||||
<ion-fab-button aria-label="Hello World">My Button</ion-fab-button>
|
||||
`,
|
||||
});
|
||||
|
||||
const fabButton = page.body.querySelector('ion-fab-button');
|
||||
const root = fabButton.shadowRoot;
|
||||
const nativeButton = root.querySelector('button');
|
||||
expect(nativeButton.getAttribute('aria-label')).toEqual('Hello World');
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('fab-button: standalone', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/fab-button/test/standalone?ionic:_testing=true',
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -1,142 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Floating Action Button - Standalone</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<link href="../../../../../css/core.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h3>Default</h3>
|
||||
<p>
|
||||
<ion-fab-button>Default</ion-fab-button>
|
||||
<ion-fab-button><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button size="small">Mini</ion-fab-button>
|
||||
<ion-fab-button size="small"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list">In List</ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button size="small" class="fab-button-in-list"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list ion-activated"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button size="small" class="fab-button-in-list ion-activated"
|
||||
><ion-icon name="star"></ion-icon
|
||||
></ion-fab-button>
|
||||
</p>
|
||||
|
||||
<h3>Colors</h3>
|
||||
<p>
|
||||
<ion-fab-button color="primary"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="secondary"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="tertiary"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="success"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="warning"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="danger"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="light"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="medium"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="dark"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
</p>
|
||||
<p>
|
||||
<ion-fab-button color="primary" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="secondary" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="tertiary" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="success" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="warning" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="danger" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="light" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="medium" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="dark" class="ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
</p>
|
||||
|
||||
<h3>Custom</h3>
|
||||
|
||||
<!-- Custom Font -->
|
||||
<ion-fab-button class="large">large</ion-fab-button>
|
||||
|
||||
<!-- Custom Colors -->
|
||||
<ion-fab-button class="custom"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button class="custom ion-activated"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button color="secondary" class="custom"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
|
||||
<!-- Custom Colors Fab In List -->
|
||||
<ion-fab-button class="fab-button-in-list custom-white">White</ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-white ion-activated">White</ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-white"><ion-icon name="heart"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-white ion-activated"
|
||||
><ion-icon name="heart"></ion-icon
|
||||
></ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-blue"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-blue ion-activated"
|
||||
><ion-icon name="star"></ion-icon
|
||||
></ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-border">Border</ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-border ion-activated">Border</ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-border"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
<ion-fab-button class="fab-button-in-list custom-border ion-activated"
|
||||
><ion-icon name="star"></ion-icon
|
||||
></ion-fab-button>
|
||||
|
||||
<ion-fab slot="fixed" horizontal="center" vertical="bottom">
|
||||
<ion-fab-button class="custom-close"><ion-icon name="star"></ion-icon></ion-fab-button>
|
||||
|
||||
<ion-fab-list side="top">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="heart"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button>
|
||||
<ion-icon name="square"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button>
|
||||
<ion-icon name="triangle"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<style>
|
||||
ion-fab-button {
|
||||
display: inline-block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.large {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.custom {
|
||||
--background: lightpink;
|
||||
--background-activated: green;
|
||||
--color: blue;
|
||||
--color-activated: white;
|
||||
}
|
||||
|
||||
.custom-white {
|
||||
--background: white;
|
||||
--background-activated: #f6f6f6;
|
||||
}
|
||||
|
||||
.custom-blue {
|
||||
--background: #add8e6;
|
||||
--background-activated: #7cb2c4;
|
||||
}
|
||||
|
||||
.custom-border {
|
||||
--border-radius: 10px;
|
||||
--border-width: 2px;
|
||||
--border-style: dashed;
|
||||
--border-color: red;
|
||||
}
|
||||
|
||||
.custom-close::part(close-icon) {
|
||||
color: red;
|
||||
|
||||
font-size: 44px;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,17 +0,0 @@
|
||||
import { testDisabledFab, testFab } from '../test.utils';
|
||||
|
||||
test('fab: basic', async () => {
|
||||
await testFab('basic', '#fab1');
|
||||
});
|
||||
|
||||
test('fab:rtl: basic', async () => {
|
||||
await testFab('basic', '#fab1', true);
|
||||
});
|
||||
|
||||
test('fab: disabled', async () => {
|
||||
await testDisabledFab('basic', '#fab2');
|
||||
});
|
||||
|
||||
test('fab:rtl: disabled', async () => {
|
||||
await testDisabledFab('basic', '#fab2', true);
|
||||
});
|
||||
72
core/src/components/fab/test/basic/fab.e2e.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('fab: basic (visual checks)', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(`/src/components/fab/test/basic`);
|
||||
});
|
||||
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.setIonViewport();
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`fab-basic-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
|
||||
test('should not have visual regressions when open', async ({ page }) => {
|
||||
// this fab has multiple buttons on each side, so it covers all the bases
|
||||
const fab = page.locator('#fab5');
|
||||
|
||||
await fab.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
/**
|
||||
* fab.screenshot doesn't work since ion-fab's bounding box only covers the
|
||||
* central button. This viewport size crops extra white space while also
|
||||
* containing all the buttons in the open fab.
|
||||
*/
|
||||
await page.setViewportSize({
|
||||
width: 320,
|
||||
height: 415,
|
||||
});
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`fab-open-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('fab: basic (functionality checks)', () => {
|
||||
test.beforeEach(async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('ios');
|
||||
|
||||
await page.goto(`/src/components/fab/test/basic`);
|
||||
});
|
||||
|
||||
test('should toggle active state when clicked', async ({ page }) => {
|
||||
const fab = page.locator('#fab1');
|
||||
const fabList = fab.locator('ion-fab-list');
|
||||
|
||||
expect(fabList).not.toHaveClass(/fab-list-active/);
|
||||
|
||||
// open fab
|
||||
await fab.click();
|
||||
await page.waitForChanges();
|
||||
expect(fabList).toHaveClass(/fab-list-active/);
|
||||
|
||||
// close fab
|
||||
await fab.click();
|
||||
await page.waitForChanges();
|
||||
expect(fabList).not.toHaveClass(/fab-list-active/);
|
||||
});
|
||||
|
||||
test('should not open when disabled', async ({ page }) => {
|
||||
const fab = page.locator('#fab2');
|
||||
const fabList = fab.locator('ion-fab-list');
|
||||
|
||||
expect(fabList).not.toHaveClass(/fab-list-active/);
|
||||
|
||||
// attempt to open fab
|
||||
await fab.click();
|
||||
await page.waitForChanges();
|
||||
expect(fabList).not.toHaveClass(/fab-list-active/);
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 145 KiB |
|
After Width: | Height: | Size: 151 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 144 KiB |
@@ -26,117 +26,108 @@
|
||||
<f></f>
|
||||
<f></f>
|
||||
|
||||
<pre id="log" style="right: 10px; bottom: 50px; text-shadow: 0 0 2px rgba(0, 0, 0, 0.24)" slot="fixed">log</pre>
|
||||
<ion-button>Test</ion-button>
|
||||
<ion-fab-button disabled href="#path" onclick="throw 'no clickable'">FAB</ion-fab-button>
|
||||
|
||||
<ion-fab vertical="top" horizontal="end" edge id="fab1" slot="fixed">
|
||||
<ion-fab-button onclick="clickMainFAB('fab1')" size="small" class="e2eFabTopRight">
|
||||
<ion-fab-button size="small" class="e2eFabTopRight">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list>
|
||||
<ion-fab-button onclick="openSocial('facebook', 'fab1')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('twitter', 'fab1')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-twitter"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('vimeo', 'fab1')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('instagram', 'fab1')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab vertical="bottom" horizontal="end" edge id="fab2" slot="fixed">
|
||||
<ion-fab-button onclick="clickMainFAB('fab2')" color="dark" class="e2eFabBottomRight" disabled>
|
||||
<ion-icon name="arrow-back-circle"></ion-icon>
|
||||
<ion-fab vertical="bottom" horizontal="start" edge id="fab2" slot="fixed">
|
||||
<ion-fab-button color="dark" class="e2eFabBottomRight" disabled>
|
||||
<ion-icon name="arrow-up-circle"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="start">
|
||||
<ion-fab-button onclick="openSocial('facebook', 'fab2')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('twitter', 'fab2')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-twitter"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('vimeo', 'fab2')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('instagram', 'fab2')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab vertical="top" horizontal="start" id="fab3" slot="fixed">
|
||||
<ion-fab-button onclick="clickMainFAB('fab3')" color="secondary" class="e2eFabTopLeft">
|
||||
<ion-fab-button color="secondary" class="e2eFabTopLeft">
|
||||
<ion-icon name="arrow-forward-circle"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="end">
|
||||
<ion-fab-button onclick="openSocial('facebook', 'fab3')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('twitter', 'fab3')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-twitter"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('vimeo', 'fab3')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('instagram', 'fab3')">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab vertical="bottom" horizontal="start" id="fab4" slot="fixed">
|
||||
<ion-fab-button onclick="clickMainFAB('fab4')" color="light" class="e2eFabBottomLeft">
|
||||
<ion-icon name="arrow-up-circle"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="top">
|
||||
<ion-fab-button onclick="openSocial('facebook', 'fab4')">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('twitter', 'fab4')">
|
||||
<ion-icon name="logo-twitter"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('vimeo', 'fab4')">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button onclick="openSocial('instagram', 'fab4')">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab vertical="center" horizontal="center" id="fab5" slot="fixed">
|
||||
<ion-fab-button onclick="clickMainFAB('fab5')" class="e2eFabCenter">
|
||||
<ion-fab-button class="e2eFabCenter">
|
||||
<ion-icon name="share"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="top">
|
||||
<ion-fab-button onclick="openSocial('vimeo', 'fab5')" color="primary">
|
||||
<ion-fab-button color="primary">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="bottom">
|
||||
<ion-fab-button onclick="openSocial('facebook', 'fab5')" color="secondary">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="start">
|
||||
<ion-fab-button onclick="openSocial('instagram', 'fab5')" color="light">
|
||||
<ion-fab-button color="light">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="end">
|
||||
<ion-fab-button onclick="openSocial('twitter', 'fab5')" color="dark">
|
||||
<ion-fab-list side="bottom">
|
||||
<ion-fab-button color="secondary">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button color="dark">
|
||||
<ion-icon name="logo-twitter"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="start">
|
||||
<ion-fab-button color="light">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button color="primary">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="end">
|
||||
<ion-fab-button color="dark">
|
||||
<ion-icon name="logo-twitter"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button color="secondary">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab horizontal="end" vertical="center" slot="fixed">
|
||||
<ion-fab horizontal="end" vertical="bottom" slot="fixed">
|
||||
<ion-fab-button color="danger" onclick="add()">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
@@ -157,28 +148,10 @@
|
||||
referenceNode.parentNode.insertBefore(el, referenceNode.nextSibling);
|
||||
}
|
||||
|
||||
function insertLog(message) {
|
||||
console.log(message);
|
||||
var el = document.querySelector('#log');
|
||||
const oldHTML = el.innerHTML;
|
||||
el.innerHTML = oldHTML + '\n' + message;
|
||||
}
|
||||
|
||||
function add() {
|
||||
var newEle = document.createElement('f');
|
||||
var ref = document.querySelector('f');
|
||||
insertAfter(newEle, ref);
|
||||
insertLog('add');
|
||||
}
|
||||
|
||||
function clickMainFAB(container) {
|
||||
let message = 'Clicked open social menu';
|
||||
insertLog(message);
|
||||
}
|
||||
|
||||
function openSocial(network, container) {
|
||||
let message = 'Share in ' + network;
|
||||
insertLog(message);
|
||||
}
|
||||
|
||||
function closeLists() {
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('fab: standalone', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/fab/test/standalone?ionic:_testing=true',
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -1,78 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Floating Action Button - Standalone</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<link href="../../../../../css/core.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-fab-button href="https://ionicframework.com">
|
||||
<ion-icon name="logo-ionitron"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button href="https://ionicframework.com" target="_blank">
|
||||
<ion-icon name="logo-ionitron"></ion-icon>
|
||||
</ion-fab-button>
|
||||
|
||||
<ion-button href="https://ionicframework.com" target="_blank">
|
||||
<ion-icon name="logo-ionitron"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
<script>
|
||||
function insertAfter(el, referenceNode) {
|
||||
referenceNode.parentNode.insertBefore(el, referenceNode.nextSibling);
|
||||
}
|
||||
|
||||
function add() {
|
||||
var newEle = document.createElement('f');
|
||||
var ref = document.querySelector('f');
|
||||
insertAfter(newEle, ref);
|
||||
console.log('add');
|
||||
}
|
||||
|
||||
function clickMainFAB(container) {
|
||||
let message = 'Clicked open social menu';
|
||||
console.log(message);
|
||||
|
||||
openLists(container);
|
||||
}
|
||||
|
||||
function openSocial(network, container) {
|
||||
let message = 'Share in ' + network;
|
||||
console.log(message);
|
||||
|
||||
openLists(container);
|
||||
}
|
||||
|
||||
function openLists(container) {
|
||||
var fabLists = document.getElementById(container).querySelectorAll('ion-fab-list');
|
||||
|
||||
for (var i = 0; i < fabLists.length; i++) {
|
||||
fabLists[i].activated = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
f {
|
||||
display: block;
|
||||
margin: 15px auto;
|
||||
max-width: 150px;
|
||||
height: 150px;
|
||||
background: blue;
|
||||
}
|
||||
|
||||
f:last-of-type {
|
||||
background: yellow;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('fab: states', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/fab/test/states?ionic:_testing=true',
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
11
core/src/components/fab/test/states/fab.e2e.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test('should not have visual regressions', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
await page.goto(`/src/components/fab/test/states`);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
expect(await page.screenshot()).toMatchSnapshot(`fab-states-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
|
After Width: | Height: | Size: 224 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 194 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 245 KiB |
@@ -17,26 +17,6 @@
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-content>
|
||||
<ion-fab slot="fixed" horizontal="end">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="share-social"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="bottom">
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-twitter"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button>
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<h3>Default</h3>
|
||||
<p>
|
||||
<ion-fab-button>
|
||||
@@ -169,18 +149,6 @@
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
|
||||
<script>
|
||||
var buttons = document.querySelectorAll('ion-fab-button');
|
||||
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
buttons[i].addEventListener('click', (event) => onClick(event));
|
||||
}
|
||||
|
||||
function onClick(ev) {
|
||||
console.log('clicked the button', ev.target.innerText);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h3 {
|
||||
padding-left: 16px;
|
||||
|
||||