Compare commits
74 Commits
dev-build-
...
ld/icon-te
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccd503d2fb | ||
|
|
4f43d5ce08 | ||
|
|
4c87a06858 | ||
|
|
b7273c4613 | ||
|
|
8601977aa7 | ||
|
|
dcbbc36bfd | ||
|
|
c37b3d8bf4 | ||
|
|
be9743475c | ||
|
|
8450564eba | ||
|
|
b5261e0f41 | ||
|
|
be8e5ba1b3 | ||
|
|
a1690441e5 | ||
|
|
6da82aab81 | ||
|
|
e6031fbef0 | ||
|
|
d5f0c776df | ||
|
|
00767a02e4 | ||
|
|
fac5a97262 | ||
|
|
cfbc6e9952 | ||
|
|
3259da0de1 | ||
|
|
470c119a05 | ||
|
|
72b389993d | ||
|
|
b297529afc | ||
|
|
897ff6f749 | ||
|
|
7375dd6aba | ||
|
|
a6e4fc4feb | ||
|
|
1167a9325f | ||
|
|
3f03299847 | ||
|
|
dc75392e9d | ||
|
|
865bd2a004 | ||
|
|
2429caa168 | ||
|
|
a8517f4fcf | ||
|
|
01167fc185 | ||
|
|
14eb906352 | ||
|
|
a04a11be35 | ||
|
|
f5df28e2c7 | ||
|
|
b2562e7c6a | ||
|
|
ac2c8e6c22 | ||
|
|
70e9177e2c | ||
|
|
51b7ceb5be | ||
|
|
597bc3f085 | ||
|
|
597bec7534 | ||
|
|
eb41b556b5 | ||
|
|
355d95d4d8 | ||
|
|
078964447a | ||
|
|
45bcd4c22b | ||
|
|
71a7af0f52 | ||
|
|
d0d9e35c37 | ||
|
|
0b7f6cf573 | ||
|
|
bd0ee0b316 | ||
|
|
28f2ec9c62 | ||
|
|
6b9c6fcd4d | ||
|
|
dad7e66cf6 | ||
|
|
28deb56e9c | ||
|
|
3720ae6a09 | ||
|
|
01c34738a6 | ||
|
|
fd0f25aa72 | ||
|
|
0afa14ed7a | ||
|
|
e5b7f5ff55 | ||
|
|
e57759f4b6 | ||
|
|
ca53682684 | ||
|
|
c65e08dcd1 | ||
|
|
84212acce4 | ||
|
|
104b9547e5 | ||
|
|
e44a02632d | ||
|
|
c52a0972b9 | ||
|
|
8a97e406a0 | ||
|
|
37acdf9711 | ||
|
|
9f20780d66 | ||
|
|
3ea7488b47 | ||
|
|
de48493a16 | ||
|
|
5b31439ca0 | ||
|
|
291b1310a6 | ||
|
|
af68808e69 | ||
|
|
4553425502 |
11
.github/workflows/stencil-nightly.yml
vendored
@@ -8,7 +8,12 @@ on:
|
||||
# at 6:00 UTC (6:00 am UTC)
|
||||
- cron: '00 06 * * 1-5'
|
||||
workflow_dispatch:
|
||||
# allows for manual invocations in the GitHub UI
|
||||
inputs:
|
||||
npm_release_tag:
|
||||
required: true
|
||||
type: string
|
||||
description: What version should be pulled from NPM?
|
||||
default: nightly
|
||||
|
||||
# When pushing a new commit we should
|
||||
# cancel the previous test run to not
|
||||
@@ -24,7 +29,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-core-stencil-prerelease
|
||||
with:
|
||||
stencil-version: nightly
|
||||
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
|
||||
|
||||
test-core-clean-build:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
@@ -47,7 +52,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-spec
|
||||
with:
|
||||
stencil-version: nightly
|
||||
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
|
||||
|
||||
test-core-screenshot:
|
||||
strategy:
|
||||
|
||||
24
CHANGELOG.md
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [7.4.3](https://github.com/ionic-team/ionic-framework/compare/v7.4.2...v7.4.3) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **fab-button:** position is correct with custom sizes ([#28195](https://github.com/ionic-team/ionic-framework/issues/28195)) ([eb41b55](https://github.com/ionic-team/ionic-framework/commit/eb41b556b57c97139b9c36dc3e3be3711d8afaca)), closes [#22564](https://github.com/ionic-team/ionic-framework/issues/22564)
|
||||
* **range:** knob positions are correct on initial render with custom elements build ([#28257](https://github.com/ionic-team/ionic-framework/issues/28257)) ([ac2c8e6](https://github.com/ionic-team/ionic-framework/commit/ac2c8e6c22da4d0d8224def24ddef56ee9d26246)), closes [#25444](https://github.com/ionic-team/ionic-framework/issues/25444)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.4.2](https://github.com/ionic-team/ionic-framework/compare/v7.4.1...v7.4.2) (2023-09-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **react:** Nav unmounts component while invoking popTo or popToRoot ([#27821](https://github.com/ionic-team/ionic-framework/issues/27821)) ([0edcb2c](https://github.com/ionic-team/ionic-framework/commit/0edcb2cd85133ae8c304c53c37ca829e5fbad447)), closes [#27798](https://github.com/ionic-team/ionic-framework/issues/27798)
|
||||
* **title:** large title uses custom font on transition ([#28231](https://github.com/ionic-team/ionic-framework/issues/28231)) ([71a7af0](https://github.com/ionic-team/ionic-framework/commit/71a7af0f52fe62937b1dea1ca2739e78801a2a6d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.4.1](https://github.com/ionic-team/ionic-framework/compare/v7.4.0...v7.4.1) (2023-09-20)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,29 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [7.4.3](https://github.com/ionic-team/ionic-framework/compare/v7.4.2...v7.4.3) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **fab-button:** position is correct with custom sizes ([#28195](https://github.com/ionic-team/ionic-framework/issues/28195)) ([eb41b55](https://github.com/ionic-team/ionic-framework/commit/eb41b556b57c97139b9c36dc3e3be3711d8afaca)), closes [#22564](https://github.com/ionic-team/ionic-framework/issues/22564)
|
||||
* **range:** knob positions are correct on initial render with custom elements build ([#28257](https://github.com/ionic-team/ionic-framework/issues/28257)) ([ac2c8e6](https://github.com/ionic-team/ionic-framework/commit/ac2c8e6c22da4d0d8224def24ddef56ee9d26246)), closes [#25444](https://github.com/ionic-team/ionic-framework/issues/25444)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.4.2](https://github.com/ionic-team/ionic-framework/compare/v7.4.1...v7.4.2) (2023-09-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **title:** large title uses custom font on transition ([#28231](https://github.com/ionic-team/ionic-framework/issues/28231)) ([71a7af0](https://github.com/ionic-team/ionic-framework/commit/71a7af0f52fe62937b1dea1ca2739e78801a2a6d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.4.1](https://github.com/ionic-team/ionic-framework/compare/v7.4.0...v7.4.1) (2023-09-20)
|
||||
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ ion-datetime,prop,disabled,boolean,false,false,false
|
||||
ion-datetime,prop,doneText,string,'Done',false,false
|
||||
ion-datetime,prop,firstDayOfWeek,number,0,false,false
|
||||
ion-datetime,prop,highlightedDates,((dateIsoString: string) => DatetimeHighlightStyle | undefined) | DatetimeHighlight[] | undefined,undefined,false,false
|
||||
ion-datetime,prop,hourCycle,"h12" | "h23" | undefined,undefined,false,false
|
||||
ion-datetime,prop,hourCycle,"h11" | "h12" | "h23" | "h24" | undefined,undefined,false,false
|
||||
ion-datetime,prop,hourValues,number | number[] | string | undefined,undefined,false,false
|
||||
ion-datetime,prop,isDateEnabled,((dateIsoString: string) => boolean) | undefined,undefined,false,false
|
||||
ion-datetime,prop,locale,string,'default',false,false
|
||||
@@ -1445,6 +1445,7 @@ ion-toast,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefin
|
||||
ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,false
|
||||
ion-toast,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-toast,prop,position,"bottom" | "middle" | "top",'bottom',false,false
|
||||
ion-toast,prop,positionAnchor,HTMLElement | string | undefined,undefined,false,false
|
||||
ion-toast,prop,translucent,boolean,false,false,false
|
||||
ion-toast,prop,trigger,string | undefined,undefined,false,false
|
||||
ion-toast,method,dismiss,dismiss(data?: any, role?: string) => Promise<boolean>
|
||||
|
||||
590
core/package-lock.json
generated
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"ionicons": "7.1.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "^7.1.2",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.7.3",
|
||||
"@capacitor/core": "^5.4.1",
|
||||
"@capacitor/core": "^5.4.2",
|
||||
"@capacitor/haptics": "^5.0.6",
|
||||
"@capacitor/keyboard": "^5.0.6",
|
||||
"@capacitor/status-bar": "^5.0.6",
|
||||
@@ -27,12 +27,12 @@
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/angular-output-target": "^0.8.2",
|
||||
"@stencil/react-output-target": "^0.5.3",
|
||||
"@stencil/sass": "^3.0.5",
|
||||
"@stencil/sass": "^3.0.6",
|
||||
"@stencil/vue-output-target": "^0.8.6",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^14.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
||||
"@typescript-eslint/parser": "^5.17.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||
"@typescript-eslint/parser": "^6.7.2",
|
||||
"clean-css-cli": "^5.6.1",
|
||||
"domino": "^2.1.6",
|
||||
"eslint": "^7.32.0",
|
||||
@@ -47,8 +47,7 @@
|
||||
"sass": "^1.26.10",
|
||||
"serve": "^14.0.1",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"typescript": "^4.0.5"
|
||||
"stylelint-order": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"custom-rules": {
|
||||
@@ -607,9 +606,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@capacitor/core": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.4.1.tgz",
|
||||
"integrity": "sha512-QG9gORuxw2WNcVpLHT1W3LzACOJvFWRuHcz4b9edzxehSELqiSQ4DoGWLp4PuNBBp2oV/fGA4FMNmfZ1jIAAWg==",
|
||||
"version": "5.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.4.2.tgz",
|
||||
"integrity": "sha512-XbR1vldJFzBWHeoGPpgfNy3Zhjf0NxXdHEaGNANWVBg0ZWG2gwFr1dcRALUUQtbwrEEkCCNiLYg4YiQPRk7SEQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
@@ -642,6 +641,30 @@
|
||||
"@capacitor/core": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||
"integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint-community/regexpp": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz",
|
||||
"integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
|
||||
@@ -1630,9 +1653,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -1651,9 +1674,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/sass": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-3.0.5.tgz",
|
||||
"integrity": "sha512-9nyllMXOEvHywo6fP2iwXgnq32A+OOUE36Aq7iUjzwT3wdr04qsvupO1JNIyRvmvCDF15hOKXztrZH1/wDu2Zg==",
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-3.0.6.tgz",
|
||||
"integrity": "sha512-d+k8qCvDgzI/vIV7M5QavIS6b75X4yn+YQH80KA/L0oL/hKD8KeF3wMOd7P1nDhGLIGRNw5tBDbe0GeIsGVU7A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12.0.0",
|
||||
@@ -1785,9 +1808,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
|
||||
"version": "7.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz",
|
||||
"integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
@@ -1844,6 +1867,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.2.tgz",
|
||||
"integrity": "sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/stack-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
|
||||
@@ -1863,31 +1892,33 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.17.0.tgz",
|
||||
"integrity": "sha512-qVstvQilEd89HJk3qcbKt/zZrfBZ+9h2ynpAGlWjWiizA7m/MtLT9RoX6gjtpE500vfIg8jogAkDzdCxbsFASQ==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz",
|
||||
"integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.17.0",
|
||||
"@typescript-eslint/type-utils": "5.17.0",
|
||||
"@typescript-eslint/utils": "5.17.0",
|
||||
"debug": "^4.3.2",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"ignore": "^5.1.8",
|
||||
"regexpp": "^3.2.0",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
"@eslint-community/regexpp": "^4.5.1",
|
||||
"@typescript-eslint/scope-manager": "6.7.2",
|
||||
"@typescript-eslint/type-utils": "6.7.2",
|
||||
"@typescript-eslint/utils": "6.7.2",
|
||||
"@typescript-eslint/visitor-keys": "6.7.2",
|
||||
"debug": "^4.3.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.4",
|
||||
"natural-compare": "^1.4.0",
|
||||
"semver": "^7.5.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "^5.0.0",
|
||||
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
"@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
|
||||
"eslint": "^7.0.0 || ^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
@@ -1895,30 +1926,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.17.0.tgz",
|
||||
"integrity": "sha512-DVvndq1QoxQH+hFv+MUQHrrWZ7gQ5KcJzyjhzcqB1Y2Xes1UQQkTRPUfRpqhS8mhTWsSb2+iyvDW1Lef5DD7vA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@typescript-eslint/scope-manager": "5.17.0",
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/typescript-estree": "5.17.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -1937,9 +1944,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
@@ -2091,25 +2098,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.17.0.tgz",
|
||||
"integrity": "sha512-aRzW9Jg5Rlj2t2/crzhA2f23SIYFlF9mchGudyP0uiD6SenIxzKoLjwzHbafgHn39dNV/TV7xwQkLfFTZlJ4ig==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz",
|
||||
"integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.17.0",
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/typescript-estree": "5.17.0",
|
||||
"debug": "^4.3.2"
|
||||
"@typescript-eslint/scope-manager": "6.7.2",
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"@typescript-eslint/typescript-estree": "6.7.2",
|
||||
"@typescript-eslint/visitor-keys": "6.7.2",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
"eslint": "^7.0.0 || ^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
@@ -2135,16 +2143,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.17.0.tgz",
|
||||
"integrity": "sha512-062iCYQF/doQ9T2WWfJohQKKN1zmmXVfAcS3xaiialiw8ZUGy05Em6QVNYJGO34/sU1a7a+90U3dUNfqUDHr3w==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz",
|
||||
"integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/visitor-keys": "5.17.0"
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"@typescript-eslint/visitor-keys": "6.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -2152,24 +2160,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.17.0.tgz",
|
||||
"integrity": "sha512-3hU0RynUIlEuqMJA7dragb0/75gZmwNwFf/QJokWzPehTZousP/MNifVSgjxNcDCkM5HI2K22TjQWUmmHUINSg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz",
|
||||
"integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/utils": "5.17.0",
|
||||
"debug": "^4.3.2",
|
||||
"tsutils": "^3.21.0"
|
||||
"@typescript-eslint/typescript-estree": "6.7.2",
|
||||
"@typescript-eslint/utils": "6.7.2",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "*"
|
||||
"eslint": "^7.0.0 || ^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
@@ -2177,30 +2186,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.17.0.tgz",
|
||||
"integrity": "sha512-DVvndq1QoxQH+hFv+MUQHrrWZ7gQ5KcJzyjhzcqB1Y2Xes1UQQkTRPUfRpqhS8mhTWsSb2+iyvDW1Lef5DD7vA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@typescript-eslint/scope-manager": "5.17.0",
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/typescript-estree": "5.17.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -2219,12 +2204,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.17.0.tgz",
|
||||
"integrity": "sha512-AgQ4rWzmCxOZLioFEjlzOI3Ch8giDWx8aUDxyNw9iOeCvD3GEYAB7dxWGQy4T/rPVe8iPmu73jPHuaSqcjKvxw==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz",
|
||||
"integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -2232,21 +2217,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.17.0.tgz",
|
||||
"integrity": "sha512-X1gtjEcmM7Je+qJRhq7ZAAaNXYhTgqMkR10euC4Si6PIjb+kwEQHSxGazXUQXFyqfEXdkGf6JijUu5R0uceQzg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz",
|
||||
"integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/visitor-keys": "5.17.0",
|
||||
"debug": "^4.3.2",
|
||||
"globby": "^11.0.4",
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"@typescript-eslint/visitor-keys": "6.7.2",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
"semver": "^7.5.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -2276,9 +2261,49 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz",
|
||||
"integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "6.7.2",
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"@typescript-eslint/typescript-estree": "6.7.2",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils/node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
@@ -2291,16 +2316,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.17.0.tgz",
|
||||
"integrity": "sha512-6K/zlc4OfCagUu7Am/BD5k8PSWQOgh34Nrv9Rxe2tBzlJ7uOeJ/h7ugCGDCeEZHT6k2CJBhbk9IsbkPI0uvUkA==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz",
|
||||
"integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"eslint-visitor-keys": "^3.0.0"
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -4154,12 +4179,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-visitor-keys": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
|
||||
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/@babel/code-frame": {
|
||||
@@ -4981,6 +5009,12 @@
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/hard-rejection": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
|
||||
@@ -5177,9 +5211,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
|
||||
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
@@ -5294,9 +5328,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ionicons": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.0.tgz",
|
||||
"integrity": "sha512-iE4GuEdEHARJpp0sWL7WJZCzNCf5VxpNRhAjW0fLnZPnNL5qZOJUcfup2Z2Ty7Jk8Q5hacrHfGEB1lCwOdXqGg==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.2.tgz",
|
||||
"integrity": "sha512-zZ4njAqSP39H8RRvZhJvkHsv7cBjYE/VfInH218Osf2UVxJITSOutTTd25MW+tAXKN5fheYzclUXUsF55JHUDg==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.18.0"
|
||||
}
|
||||
@@ -9724,6 +9758,18 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
|
||||
"integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
|
||||
@@ -9826,16 +9872,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
||||
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
@@ -10802,9 +10849,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@capacitor/core": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.4.1.tgz",
|
||||
"integrity": "sha512-QG9gORuxw2WNcVpLHT1W3LzACOJvFWRuHcz4b9edzxehSELqiSQ4DoGWLp4PuNBBp2oV/fGA4FMNmfZ1jIAAWg==",
|
||||
"version": "5.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.4.2.tgz",
|
||||
"integrity": "sha512-XbR1vldJFzBWHeoGPpgfNy3Zhjf0NxXdHEaGNANWVBg0ZWG2gwFr1dcRALUUQtbwrEEkCCNiLYg4YiQPRk7SEQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^2.1.0"
|
||||
@@ -10831,6 +10878,21 @@
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@eslint-community/eslint-utils": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||
"integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-visitor-keys": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"@eslint-community/regexpp": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz",
|
||||
"integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
|
||||
@@ -11536,9 +11598,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A=="
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg=="
|
||||
},
|
||||
"@stencil/react-output-target": {
|
||||
"version": "0.5.3",
|
||||
@@ -11548,9 +11610,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@stencil/sass": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-3.0.5.tgz",
|
||||
"integrity": "sha512-9nyllMXOEvHywo6fP2iwXgnq32A+OOUE36Aq7iUjzwT3wdr04qsvupO1JNIyRvmvCDF15hOKXztrZH1/wDu2Zg==",
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-3.0.6.tgz",
|
||||
"integrity": "sha512-d+k8qCvDgzI/vIV7M5QavIS6b75X4yn+YQH80KA/L0oL/hKD8KeF3wMOd7P1nDhGLIGRNw5tBDbe0GeIsGVU7A==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
@@ -11667,9 +11729,9 @@
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
|
||||
"version": "7.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz",
|
||||
"integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/json5": {
|
||||
@@ -11726,6 +11788,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/semver": {
|
||||
"version": "7.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.2.tgz",
|
||||
"integrity": "sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/stack-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
|
||||
@@ -11745,36 +11813,24 @@
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.17.0.tgz",
|
||||
"integrity": "sha512-qVstvQilEd89HJk3qcbKt/zZrfBZ+9h2ynpAGlWjWiizA7m/MtLT9RoX6gjtpE500vfIg8jogAkDzdCxbsFASQ==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz",
|
||||
"integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "5.17.0",
|
||||
"@typescript-eslint/type-utils": "5.17.0",
|
||||
"@typescript-eslint/utils": "5.17.0",
|
||||
"debug": "^4.3.2",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"ignore": "^5.1.8",
|
||||
"regexpp": "^3.2.0",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
"@eslint-community/regexpp": "^4.5.1",
|
||||
"@typescript-eslint/scope-manager": "6.7.2",
|
||||
"@typescript-eslint/type-utils": "6.7.2",
|
||||
"@typescript-eslint/utils": "6.7.2",
|
||||
"@typescript-eslint/visitor-keys": "6.7.2",
|
||||
"debug": "^4.3.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.4",
|
||||
"natural-compare": "^1.4.0",
|
||||
"semver": "^7.5.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/utils": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.17.0.tgz",
|
||||
"integrity": "sha512-DVvndq1QoxQH+hFv+MUQHrrWZ7gQ5KcJzyjhzcqB1Y2Xes1UQQkTRPUfRpqhS8mhTWsSb2+iyvDW1Lef5DD7vA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@typescript-eslint/scope-manager": "5.17.0",
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/typescript-estree": "5.17.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -11785,9 +11841,9 @@
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
@@ -11877,15 +11933,16 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.17.0.tgz",
|
||||
"integrity": "sha512-aRzW9Jg5Rlj2t2/crzhA2f23SIYFlF9mchGudyP0uiD6SenIxzKoLjwzHbafgHn39dNV/TV7xwQkLfFTZlJ4ig==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz",
|
||||
"integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "5.17.0",
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/typescript-estree": "5.17.0",
|
||||
"debug": "^4.3.2"
|
||||
"@typescript-eslint/scope-manager": "6.7.2",
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"@typescript-eslint/typescript-estree": "6.7.2",
|
||||
"@typescript-eslint/visitor-keys": "6.7.2",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
@@ -11900,40 +11957,27 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.17.0.tgz",
|
||||
"integrity": "sha512-062iCYQF/doQ9T2WWfJohQKKN1zmmXVfAcS3xaiialiw8ZUGy05Em6QVNYJGO34/sU1a7a+90U3dUNfqUDHr3w==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz",
|
||||
"integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/visitor-keys": "5.17.0"
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"@typescript-eslint/visitor-keys": "6.7.2"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/type-utils": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.17.0.tgz",
|
||||
"integrity": "sha512-3hU0RynUIlEuqMJA7dragb0/75gZmwNwFf/QJokWzPehTZousP/MNifVSgjxNcDCkM5HI2K22TjQWUmmHUINSg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz",
|
||||
"integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/utils": "5.17.0",
|
||||
"debug": "^4.3.2",
|
||||
"tsutils": "^3.21.0"
|
||||
"@typescript-eslint/typescript-estree": "6.7.2",
|
||||
"@typescript-eslint/utils": "6.7.2",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/utils": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.17.0.tgz",
|
||||
"integrity": "sha512-DVvndq1QoxQH+hFv+MUQHrrWZ7gQ5KcJzyjhzcqB1Y2Xes1UQQkTRPUfRpqhS8mhTWsSb2+iyvDW1Lef5DD7vA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@typescript-eslint/scope-manager": "5.17.0",
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/typescript-estree": "5.17.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -11946,24 +11990,24 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.17.0.tgz",
|
||||
"integrity": "sha512-AgQ4rWzmCxOZLioFEjlzOI3Ch8giDWx8aUDxyNw9iOeCvD3GEYAB7dxWGQy4T/rPVe8iPmu73jPHuaSqcjKvxw==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz",
|
||||
"integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.17.0.tgz",
|
||||
"integrity": "sha512-X1gtjEcmM7Je+qJRhq7ZAAaNXYhTgqMkR10euC4Si6PIjb+kwEQHSxGazXUQXFyqfEXdkGf6JijUu5R0uceQzg==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz",
|
||||
"integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"@typescript-eslint/visitor-keys": "5.17.0",
|
||||
"debug": "^4.3.2",
|
||||
"globby": "^11.0.4",
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"@typescript-eslint/visitor-keys": "6.7.2",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
"semver": "^7.5.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
@@ -11976,9 +12020,35 @@
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/utils": {
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz",
|
||||
"integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "6.7.2",
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"@typescript-eslint/typescript-estree": "6.7.2",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
@@ -11987,13 +12057,13 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.17.0.tgz",
|
||||
"integrity": "sha512-6K/zlc4OfCagUu7Am/BD5k8PSWQOgh34Nrv9Rxe2tBzlJ7uOeJ/h7ugCGDCeEZHT6k2CJBhbk9IsbkPI0uvUkA==",
|
||||
"version": "6.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz",
|
||||
"integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.17.0",
|
||||
"eslint-visitor-keys": "^3.0.0"
|
||||
"@typescript-eslint/types": "6.7.2",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"@zeit/schemas": {
|
||||
@@ -13542,9 +13612,9 @@
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
|
||||
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"dev": true
|
||||
},
|
||||
"espree": {
|
||||
@@ -13994,6 +14064,12 @@
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
|
||||
"dev": true
|
||||
},
|
||||
"hard-rejection": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
|
||||
@@ -14136,9 +14212,9 @@
|
||||
}
|
||||
},
|
||||
"ignore": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
|
||||
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"import-fresh": {
|
||||
@@ -14221,9 +14297,9 @@
|
||||
}
|
||||
},
|
||||
"ionicons": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.0.tgz",
|
||||
"integrity": "sha512-iE4GuEdEHARJpp0sWL7WJZCzNCf5VxpNRhAjW0fLnZPnNL5qZOJUcfup2Z2Ty7Jk8Q5hacrHfGEB1lCwOdXqGg==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.1.2.tgz",
|
||||
"integrity": "sha512-zZ4njAqSP39H8RRvZhJvkHsv7cBjYE/VfInH218Osf2UVxJITSOutTTd25MW+tAXKN5fheYzclUXUsF55JHUDg==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.18.0"
|
||||
},
|
||||
@@ -17500,6 +17576,13 @@
|
||||
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
|
||||
"dev": true
|
||||
},
|
||||
"ts-api-utils": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
|
||||
"integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"tsconfig-paths": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
|
||||
@@ -17582,10 +17665,11 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
|
||||
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
|
||||
"dev": true
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"unbox-primitive": {
|
||||
"version": "1.0.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.3",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -31,13 +31,13 @@
|
||||
"loader/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"ionicons": "7.1.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "^7.1.2",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.7.3",
|
||||
"@capacitor/core": "^5.4.1",
|
||||
"@capacitor/core": "^5.4.2",
|
||||
"@capacitor/haptics": "^5.0.6",
|
||||
"@capacitor/keyboard": "^5.0.6",
|
||||
"@capacitor/status-bar": "^5.0.6",
|
||||
@@ -49,12 +49,12 @@
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/angular-output-target": "^0.8.2",
|
||||
"@stencil/react-output-target": "^0.5.3",
|
||||
"@stencil/sass": "^3.0.5",
|
||||
"@stencil/sass": "^3.0.6",
|
||||
"@stencil/vue-output-target": "^0.8.6",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^14.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
||||
"@typescript-eslint/parser": "^5.17.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||
"@typescript-eslint/parser": "^6.7.2",
|
||||
"clean-css-cli": "^5.6.1",
|
||||
"domino": "^2.1.6",
|
||||
"eslint": "^7.32.0",
|
||||
@@ -69,8 +69,7 @@
|
||||
"sass": "^1.26.10",
|
||||
"serve": "^14.0.1",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"typescript": "^4.0.5"
|
||||
"stylelint-order": "^4.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run clean && npm run build.css && stencil build --es5 --docs-json dist/docs.json",
|
||||
@@ -95,6 +94,7 @@
|
||||
"test.spec": "stencil test --spec --max-workers=2",
|
||||
"test.spec.debug": "npx --node-arg=\"--inspect-brk\" stencil test --spec",
|
||||
"test.e2e": "npx playwright test",
|
||||
"test.e2e.update-snapshots": "npm run test.e2e -- --update-snapshots",
|
||||
"test.watch": "jest --watch --no-cache",
|
||||
"test.treeshake": "node scripts/treeshaking.js dist/index.js",
|
||||
"validate": "npm run lint && npm run test && npm run build && npm run test.treeshake"
|
||||
|
||||
25
core/src/components.d.ts
vendored
@@ -15,7 +15,7 @@ import { RouteID, RouterDirection, RouterEventDetail, RouteWrite } from "./compo
|
||||
import { BreadcrumbCollapsedClickEventDetail } from "./components/breadcrumb/breadcrumb-interface";
|
||||
import { CheckboxChangeEventDetail } from "./components/checkbox/checkbox-interface";
|
||||
import { ScrollBaseDetail, ScrollDetail } from "./components/content/content-interface";
|
||||
import { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
|
||||
import { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimeHourCycle, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
|
||||
import { SpinnerTypes } from "./components/spinner/spinner-configs";
|
||||
import { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
|
||||
import { CounterFormatter } from "./components/item/item-interface";
|
||||
@@ -39,7 +39,7 @@ import { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from "./com
|
||||
import { SelectPopoverOption } from "./components/select-popover/select-popover-interface";
|
||||
import { TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout } from "./components/tab-bar/tab-bar-interface";
|
||||
import { TextareaChangeEventDetail, TextareaInputEventDetail } from "./components/textarea/textarea-interface";
|
||||
import { ToastButton, ToastLayout, ToastPosition } from "./components/toast/toast-interface";
|
||||
import { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions } from "./components/toast/toast-interface";
|
||||
import { ToggleChangeEventDetail } from "./components/toggle/toggle-interface";
|
||||
export { AccordionGroupChangeEventDetail } from "./components/accordion-group/accordion-group-interface";
|
||||
export { AnimationBuilder, AutocompleteTypes, Color, ComponentProps, ComponentRef, FrameworkDelegate, StyleEventDetail, TextFieldTypes } from "./interface";
|
||||
@@ -51,7 +51,7 @@ export { RouteID, RouterDirection, RouterEventDetail, RouteWrite } from "./compo
|
||||
export { BreadcrumbCollapsedClickEventDetail } from "./components/breadcrumb/breadcrumb-interface";
|
||||
export { CheckboxChangeEventDetail } from "./components/checkbox/checkbox-interface";
|
||||
export { ScrollBaseDetail, ScrollDetail } from "./components/content/content-interface";
|
||||
export { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
|
||||
export { DatetimeChangeEventDetail, DatetimeHighlight, DatetimeHighlightCallback, DatetimeHourCycle, DatetimePresentation, TitleSelectedDatesFormatter } from "./components/datetime/datetime-interface";
|
||||
export { SpinnerTypes } from "./components/spinner/spinner-configs";
|
||||
export { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
|
||||
export { CounterFormatter } from "./components/item/item-interface";
|
||||
@@ -75,7 +75,7 @@ export { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from "./com
|
||||
export { SelectPopoverOption } from "./components/select-popover/select-popover-interface";
|
||||
export { TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout } from "./components/tab-bar/tab-bar-interface";
|
||||
export { TextareaChangeEventDetail, TextareaInputEventDetail } from "./components/textarea/textarea-interface";
|
||||
export { ToastButton, ToastLayout, ToastPosition } from "./components/toast/toast-interface";
|
||||
export { ToastButton, ToastDismissOptions, ToastLayout, ToastPosition, ToastPresentOptions } from "./components/toast/toast-interface";
|
||||
export { ToggleChangeEventDetail } from "./components/toggle/toggle-interface";
|
||||
export namespace Components {
|
||||
interface IonAccordion {
|
||||
@@ -865,7 +865,7 @@ export namespace Components {
|
||||
/**
|
||||
* The hour cycle of the `ion-datetime`. If no value is set, this is specified by the current locale.
|
||||
*/
|
||||
"hourCycle"?: 'h23' | 'h12';
|
||||
"hourCycle"?: DatetimeHourCycle;
|
||||
/**
|
||||
* Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers.
|
||||
*/
|
||||
@@ -3157,9 +3157,13 @@ export namespace Components {
|
||||
"onWillDismiss": <T = any>() => Promise<OverlayEventDetail<T>>;
|
||||
"overlayIndex": number;
|
||||
/**
|
||||
* The position of the toast on the screen.
|
||||
* The starting position of the toast on the screen. Can be tweaked further using the `positionAnchor` property.
|
||||
*/
|
||||
"position": ToastPosition;
|
||||
/**
|
||||
* The element to anchor the toast's position to. Can be set as a direct reference or the ID of the element. With `position="bottom"`, the toast will sit above the chosen element. With `position="top"`, the toast will sit below the chosen element. With `position="middle"`, the value of `positionAnchor` is ignored.
|
||||
*/
|
||||
"positionAnchor"?: HTMLElement | string;
|
||||
/**
|
||||
* Present the toast overlay after it has been created.
|
||||
*/
|
||||
@@ -4889,7 +4893,7 @@ declare namespace LocalJSX {
|
||||
/**
|
||||
* The hour cycle of the `ion-datetime`. If no value is set, this is specified by the current locale.
|
||||
*/
|
||||
"hourCycle"?: 'h23' | 'h12';
|
||||
"hourCycle"?: DatetimeHourCycle;
|
||||
/**
|
||||
* Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers.
|
||||
*/
|
||||
@@ -6976,6 +6980,7 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"mode"?: "ios" | "md";
|
||||
"onIonTabBarChanged"?: (event: IonTabBarCustomEvent<TabBarChangedEventDetail>) => void;
|
||||
"onIonTabBarLoaded"?: (event: IonTabBarCustomEvent<void>) => void;
|
||||
/**
|
||||
* The selected tab component
|
||||
*/
|
||||
@@ -7307,9 +7312,13 @@ declare namespace LocalJSX {
|
||||
"onWillPresent"?: (event: IonToastCustomEvent<void>) => void;
|
||||
"overlayIndex": number;
|
||||
/**
|
||||
* The position of the toast on the screen.
|
||||
* The starting position of the toast on the screen. Can be tweaked further using the `positionAnchor` property.
|
||||
*/
|
||||
"position"?: ToastPosition;
|
||||
/**
|
||||
* The element to anchor the toast's position to. Can be set as a direct reference or the ID of the element. With `position="bottom"`, the toast will sit above the chosen element. With `position="top"`, the toast will sit below the chosen element. With `position="middle"`, the value of `positionAnchor` is ignored.
|
||||
*/
|
||||
"positionAnchor"?: HTMLElement | string;
|
||||
/**
|
||||
* If `true`, the toast will be translucent. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility).
|
||||
*/
|
||||
|
||||
@@ -228,6 +228,15 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
onKeydown(ev: any) {
|
||||
const inputTypes = new Set(this.processedInputs.map((i) => i.type));
|
||||
|
||||
/**
|
||||
* Based on keyboard navigation requirements, the
|
||||
* checkbox should not respond to the enter keydown event.
|
||||
*/
|
||||
if (inputTypes.has('checkbox') && ev.key === 'Enter') {
|
||||
ev.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// The only inputs we want to navigate between using arrow keys are the radios
|
||||
// ignore the keydown event if it is not on a radio button
|
||||
if (
|
||||
|
||||
@@ -76,5 +76,22 @@ configs({ directions: ['ltr'] }).forEach(({ config, title }) => {
|
||||
await expect(alertButton).toHaveAttribute('aria-labelledby', 'close-label');
|
||||
await expect(alertButton).toHaveAttribute('aria-label', 'close button');
|
||||
});
|
||||
|
||||
test('should not toggle the checkbox when pressing the Enter key', async ({ page }) => {
|
||||
const didPresent = await page.spyOnEvent('ionAlertDidPresent');
|
||||
|
||||
const button = page.locator('#checkbox');
|
||||
await button.click();
|
||||
|
||||
await didPresent.next();
|
||||
|
||||
const alertCheckbox = page.locator('ion-alert .alert-checkbox');
|
||||
const ariaChecked = await alertCheckbox.getAttribute('aria-checked');
|
||||
|
||||
await expect(alertCheckbox).toHaveAttribute('aria-checked', ariaChecked!);
|
||||
|
||||
await alertCheckbox.press('Enter');
|
||||
await expect(alertCheckbox).toHaveAttribute('aria-checked', ariaChecked!);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<ion-button id="noMessage" expand="block" onclick="presentNoMessage()">No Message</ion-button>
|
||||
<ion-button id="customAria" expand="block" onclick="presentCustomAria()">Custom Aria</ion-button>
|
||||
<ion-button id="ariaLabelButton" expand="block" onclick="presentAriaLabelButton()">Aria Label Button</ion-button>
|
||||
<ion-button id="checkbox" expand="block" onclick="presentAlertCheckbox()">Checkbox</ion-button>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
@@ -94,6 +95,21 @@
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function presentAlertCheckbox() {
|
||||
openAlert({
|
||||
header: 'Checkbox',
|
||||
inputs: [
|
||||
{
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 1',
|
||||
value: 'value1',
|
||||
checked: true,
|
||||
},
|
||||
],
|
||||
buttons: ['OK'],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -1,6 +1,6 @@
|
||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||
import { Build, Component, Element, Event, Host, Listen, Method, Prop, forceUpdate, h, readTask } from '@stencil/core';
|
||||
import { componentOnReady } from '@utils/helpers';
|
||||
import { componentOnReady, hasLazyBuild } from '@utils/helpers';
|
||||
import { isPlatform } from '@utils/platform';
|
||||
import { isRTL } from '@utils/rtl';
|
||||
import { createColorClasses, hostContext } from '@utils/theme';
|
||||
@@ -34,6 +34,9 @@ export class Content implements ComponentInterface {
|
||||
private isMainContent = true;
|
||||
private resizeTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
private tabsElement: HTMLElement | null = null;
|
||||
private tabsLoadCallback?: () => void;
|
||||
|
||||
// Detail is used in a hot loop in the scroll event, by allocating it here
|
||||
// V8 will be able to inline any read/write to it since it's a monomorphic class.
|
||||
// https://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html
|
||||
@@ -115,15 +118,61 @@ export class Content implements ComponentInterface {
|
||||
|
||||
connectedCallback() {
|
||||
this.isMainContent = this.el.closest('ion-menu, ion-popover, ion-modal') === null;
|
||||
|
||||
/**
|
||||
* The fullscreen content offsets need to be
|
||||
* computed after the tab bar has loaded. Since
|
||||
* lazy evaluation means components are not hydrated
|
||||
* at the same time, we need to wait for the ionTabBarLoaded
|
||||
* event to fire. This does not impact dist-custom-elements
|
||||
* because there is no hydration there.
|
||||
*/
|
||||
if (hasLazyBuild(this.el)) {
|
||||
/**
|
||||
* We need to cache the reference to the tabs.
|
||||
* If just the content is unmounted then we won't
|
||||
* be able to query for the closest tabs on disconnectedCallback
|
||||
* since the content has been removed from the DOM tree.
|
||||
*/
|
||||
const closestTabs = (this.tabsElement = this.el.closest('ion-tabs'));
|
||||
if (closestTabs !== null) {
|
||||
/**
|
||||
* When adding and removing the event listener
|
||||
* we need to make sure we pass the same function reference
|
||||
* otherwise the event listener will not be removed properly.
|
||||
* We can't only pass `this.resize` because "this" in the function
|
||||
* context becomes a reference to IonTabs instead of IonContent.
|
||||
*
|
||||
* Additionally, we listen for ionTabBarLoaded on the IonTabs
|
||||
* instance rather than the IonTabBar instance. It's possible for
|
||||
* a tab bar to be conditionally rendered/mounted. Since ionTabBarLoaded
|
||||
* bubbles, we can catch any instances of child tab bars loading by listening
|
||||
* on IonTabs.
|
||||
*/
|
||||
this.tabsLoadCallback = () => this.resize();
|
||||
closestTabs.addEventListener('ionTabBarLoaded', this.tabsLoadCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.onScrollEnd();
|
||||
}
|
||||
|
||||
@Listen('appload', { target: 'window' })
|
||||
onAppLoad() {
|
||||
this.resize();
|
||||
if (hasLazyBuild(this.el)) {
|
||||
/**
|
||||
* The event listener and tabs caches need to
|
||||
* be cleared otherwise this will create a memory
|
||||
* leak where the IonTabs instance can never be
|
||||
* garbage collected.
|
||||
*/
|
||||
const { tabsElement, tabsLoadCallback } = this;
|
||||
if (tabsElement !== null && tabsLoadCallback !== undefined) {
|
||||
tabsElement.removeEventListener('ionTabBarLoaded', tabsLoadCallback);
|
||||
}
|
||||
|
||||
this.tabsElement = null;
|
||||
this.tabsLoadCallback = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { Color } from '../../interface';
|
||||
import type { DatetimePresentation } from '../datetime/datetime-interface';
|
||||
import { getToday } from '../datetime/utils/data';
|
||||
import { getMonthAndYear, getMonthDayAndYear, getLocalizedDateTime, getLocalizedTime } from '../datetime/utils/format';
|
||||
import { is24Hour } from '../datetime/utils/helpers';
|
||||
import { getHourCycle } from '../datetime/utils/helpers';
|
||||
import { parseDate } from '../datetime/utils/parse';
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
@@ -218,7 +218,7 @@ export class DatetimeButton implements ComponentInterface {
|
||||
* warning in the console.
|
||||
*/
|
||||
const firstParsedDatetime = parsedDatetimes[0];
|
||||
const use24Hour = is24Hour(locale, hourCycle);
|
||||
const computedHourCycle = getHourCycle(locale, hourCycle);
|
||||
|
||||
this.dateText = this.timeText = undefined;
|
||||
|
||||
@@ -226,7 +226,7 @@ export class DatetimeButton implements ComponentInterface {
|
||||
case 'date-time':
|
||||
case 'time-date':
|
||||
const dateText = getMonthDayAndYear(locale, firstParsedDatetime);
|
||||
const timeText = getLocalizedTime(locale, firstParsedDatetime, use24Hour);
|
||||
const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
|
||||
if (preferWheel) {
|
||||
this.dateText = `${dateText} ${timeText}`;
|
||||
} else {
|
||||
@@ -250,7 +250,7 @@ export class DatetimeButton implements ComponentInterface {
|
||||
}
|
||||
break;
|
||||
case 'time':
|
||||
this.timeText = getLocalizedTime(locale, firstParsedDatetime, use24Hour);
|
||||
this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
|
||||
break;
|
||||
case 'month-year':
|
||||
this.dateText = getMonthAndYear(locale, firstParsedDatetime);
|
||||
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -34,3 +34,5 @@ export type DatetimeHighlightStyle =
|
||||
export type DatetimeHighlight = { date: string } & DatetimeHighlightStyle;
|
||||
|
||||
export type DatetimeHighlightCallback = (dateIsoString: string) => DatetimeHighlightStyle | undefined;
|
||||
|
||||
export type DatetimeHourCycle = 'h11' | 'h12' | 'h23' | 'h24';
|
||||
|
||||
@@ -19,6 +19,7 @@ import type {
|
||||
DatetimeHighlight,
|
||||
DatetimeHighlightStyle,
|
||||
DatetimeHighlightCallback,
|
||||
DatetimeHourCycle,
|
||||
} from './datetime-interface';
|
||||
import { isSameDay, warnIfValueOutOfBounds, isBefore, isAfter } from './utils/comparison';
|
||||
import {
|
||||
@@ -33,7 +34,7 @@ import {
|
||||
getCombinedDateColumnData,
|
||||
} from './utils/data';
|
||||
import { formatValue, getLocalizedTime, getMonthAndDay, getMonthAndYear } from './utils/format';
|
||||
import { is24Hour, isLocaleDayPeriodRTL, isMonthFirstLocale, getNumDaysInMonth } from './utils/helpers';
|
||||
import { isLocaleDayPeriodRTL, isMonthFirstLocale, getNumDaysInMonth, getHourCycle } from './utils/helpers';
|
||||
import {
|
||||
calculateHourFromAMPM,
|
||||
convertDataToISO,
|
||||
@@ -422,7 +423,7 @@ export class Datetime implements ComponentInterface {
|
||||
* The hour cycle of the `ion-datetime`. If no value is set, this is
|
||||
* specified by the current locale.
|
||||
*/
|
||||
@Prop() hourCycle?: 'h23' | 'h12';
|
||||
@Prop() hourCycle?: DatetimeHourCycle;
|
||||
|
||||
/**
|
||||
* If `cover`, the `ion-datetime` will expand to cover the full width of its container.
|
||||
@@ -2237,7 +2238,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
private renderTimeOverlay() {
|
||||
const { hourCycle, isTimePopoverOpen, locale } = this;
|
||||
const use24Hour = is24Hour(locale, hourCycle);
|
||||
const computedHourCycle = getHourCycle(locale, hourCycle);
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return [
|
||||
@@ -2270,7 +2271,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getLocalizedTime(locale, activePart, use24Hour)}
|
||||
{getLocalizedTime(locale, activePart, computedHourCycle)}
|
||||
</button>,
|
||||
<ion-popover
|
||||
alignment="center"
|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
@@ -1,4 +1,125 @@
|
||||
import { generateMonths, getDaysOfWeek, generateTime, getToday, getCombinedDateColumnData } from '../utils/data';
|
||||
import {
|
||||
generateMonths,
|
||||
getDaysOfWeek,
|
||||
generateTime,
|
||||
getToday,
|
||||
getCombinedDateColumnData,
|
||||
getTimeColumnsData,
|
||||
} from '../utils/data';
|
||||
|
||||
// The minutes are the same across all hour cycles, so we don't check those
|
||||
describe('getTimeColumnsData()', () => {
|
||||
it('should generate formatted h12 hours and AM/PM data data', () => {
|
||||
const refParts = { month: 5, year: 2021, day: 1, hour: 4, minute: 30 };
|
||||
const results = getTimeColumnsData('en-US', refParts, 'h12');
|
||||
|
||||
expect(results.hoursData).toEqual([
|
||||
{ text: '12', value: 0 },
|
||||
{ text: '1', value: 1 },
|
||||
{ text: '2', value: 2 },
|
||||
{ text: '3', value: 3 },
|
||||
{ text: '4', value: 4 },
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '6', value: 6 },
|
||||
{ text: '7', value: 7 },
|
||||
{ text: '8', value: 8 },
|
||||
{ text: '9', value: 9 },
|
||||
{ text: '10', value: 10 },
|
||||
{ text: '11', value: 11 },
|
||||
]);
|
||||
expect(results.dayPeriodData).toEqual([
|
||||
{ text: 'AM', value: 'am' },
|
||||
{ text: 'PM', value: 'pm' },
|
||||
]);
|
||||
});
|
||||
it('should generate formatted h23 hours and AM/PM data data', () => {
|
||||
const refParts = { month: 5, year: 2021, day: 1, hour: 4, minute: 30 };
|
||||
const results = getTimeColumnsData('en-US', refParts, 'h23');
|
||||
|
||||
expect(results.hoursData).toEqual([
|
||||
{ text: '00', value: 0 },
|
||||
{ text: '01', value: 1 },
|
||||
{ text: '02', value: 2 },
|
||||
{ text: '03', value: 3 },
|
||||
{ text: '04', value: 4 },
|
||||
{ text: '05', value: 5 },
|
||||
{ text: '06', value: 6 },
|
||||
{ text: '07', value: 7 },
|
||||
{ text: '08', value: 8 },
|
||||
{ text: '09', value: 9 },
|
||||
{ text: '10', value: 10 },
|
||||
{ text: '11', value: 11 },
|
||||
{ text: '12', value: 12 },
|
||||
{ text: '13', value: 13 },
|
||||
{ text: '14', value: 14 },
|
||||
{ text: '15', value: 15 },
|
||||
{ text: '16', value: 16 },
|
||||
{ text: '17', value: 17 },
|
||||
{ text: '18', value: 18 },
|
||||
{ text: '19', value: 19 },
|
||||
{ text: '20', value: 20 },
|
||||
{ text: '21', value: 21 },
|
||||
{ text: '22', value: 22 },
|
||||
{ text: '23', value: 23 },
|
||||
]);
|
||||
expect(results.dayPeriodData).toEqual([]);
|
||||
});
|
||||
it('should generate formatted h11 hours and AM/PM data data', () => {
|
||||
const refParts = { month: 5, year: 2021, day: 1, hour: 4, minute: 30 };
|
||||
const results = getTimeColumnsData('en-US', refParts, 'h11');
|
||||
|
||||
expect(results.hoursData).toEqual([
|
||||
{ text: '0', value: 0 },
|
||||
{ text: '1', value: 1 },
|
||||
{ text: '2', value: 2 },
|
||||
{ text: '3', value: 3 },
|
||||
{ text: '4', value: 4 },
|
||||
{ text: '5', value: 5 },
|
||||
{ text: '6', value: 6 },
|
||||
{ text: '7', value: 7 },
|
||||
{ text: '8', value: 8 },
|
||||
{ text: '9', value: 9 },
|
||||
{ text: '10', value: 10 },
|
||||
{ text: '11', value: 11 },
|
||||
]);
|
||||
expect(results.dayPeriodData).toEqual([
|
||||
{ text: 'AM', value: 'am' },
|
||||
{ text: 'PM', value: 'pm' },
|
||||
]);
|
||||
});
|
||||
it('should generate formatted h24 hours and AM/PM data data', () => {
|
||||
const refParts = { month: 5, year: 2021, day: 1, hour: 4, minute: 30 };
|
||||
const results = getTimeColumnsData('en-US', refParts, 'h24');
|
||||
|
||||
expect(results.hoursData).toEqual([
|
||||
{ text: '01', value: 1 },
|
||||
{ text: '02', value: 2 },
|
||||
{ text: '03', value: 3 },
|
||||
{ text: '04', value: 4 },
|
||||
{ text: '05', value: 5 },
|
||||
{ text: '06', value: 6 },
|
||||
{ text: '07', value: 7 },
|
||||
{ text: '08', value: 8 },
|
||||
{ text: '09', value: 9 },
|
||||
{ text: '10', value: 10 },
|
||||
{ text: '11', value: 11 },
|
||||
{ text: '12', value: 12 },
|
||||
{ text: '13', value: 13 },
|
||||
{ text: '14', value: 14 },
|
||||
{ text: '15', value: 15 },
|
||||
{ text: '16', value: 16 },
|
||||
{ text: '17', value: 17 },
|
||||
{ text: '18', value: 18 },
|
||||
{ text: '19', value: 19 },
|
||||
{ text: '20', value: 20 },
|
||||
{ text: '21', value: 21 },
|
||||
{ text: '22', value: 22 },
|
||||
{ text: '23', value: 23 },
|
||||
{ text: '24', value: 0 },
|
||||
]);
|
||||
expect(results.dayPeriodData).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateMonths()', () => {
|
||||
it('should generate correct month data', () => {
|
||||
@@ -41,7 +162,7 @@ describe('generateTime()', () => {
|
||||
hour: 5,
|
||||
minute: 43,
|
||||
};
|
||||
const { hours, minutes } = generateTime(today);
|
||||
const { hours, minutes } = generateTime('en-US', today);
|
||||
|
||||
expect(hours.length).toEqual(12);
|
||||
expect(minutes.length).toEqual(60);
|
||||
@@ -61,7 +182,7 @@ describe('generateTime()', () => {
|
||||
hour: 2,
|
||||
minute: 40,
|
||||
};
|
||||
const { hours, minutes } = generateTime(today, 'h12', min);
|
||||
const { hours, minutes } = generateTime('en-US', today, 'h12', min);
|
||||
|
||||
expect(hours.length).toEqual(10);
|
||||
expect(minutes.length).toEqual(60);
|
||||
@@ -81,7 +202,7 @@ describe('generateTime()', () => {
|
||||
hour: 2,
|
||||
minute: 40,
|
||||
};
|
||||
const { hours, minutes } = generateTime(today, 'h12', min);
|
||||
const { hours, minutes } = generateTime('en-US', today, 'h12', min);
|
||||
|
||||
expect(hours.length).toEqual(12);
|
||||
expect(minutes.length).toEqual(60);
|
||||
@@ -101,7 +222,7 @@ describe('generateTime()', () => {
|
||||
hour: 7,
|
||||
minute: 44,
|
||||
};
|
||||
const { hours, minutes } = generateTime(today, 'h12', undefined, max);
|
||||
const { hours, minutes } = generateTime('en-US', today, 'h12', undefined, max);
|
||||
|
||||
expect(hours.length).toEqual(8);
|
||||
expect(minutes.length).toEqual(45);
|
||||
@@ -121,7 +242,7 @@ describe('generateTime()', () => {
|
||||
hour: 2,
|
||||
minute: 40,
|
||||
};
|
||||
const { hours, minutes } = generateTime(today, 'h12', undefined, max);
|
||||
const { hours, minutes } = generateTime('en-US', today, 'h12', undefined, max);
|
||||
|
||||
expect(hours.length).toEqual(12);
|
||||
expect(minutes.length).toEqual(60);
|
||||
@@ -141,7 +262,7 @@ describe('generateTime()', () => {
|
||||
hour: 2,
|
||||
minute: 40,
|
||||
};
|
||||
const { hours, minutes } = generateTime(today, 'h12', min);
|
||||
const { hours, minutes } = generateTime('en-US', today, 'h12', min);
|
||||
|
||||
expect(hours.length).toEqual(0);
|
||||
expect(minutes.length).toEqual(0);
|
||||
@@ -161,7 +282,7 @@ describe('generateTime()', () => {
|
||||
hour: 2,
|
||||
minute: 40,
|
||||
};
|
||||
const { hours, minutes } = generateTime(today, 'h12', undefined, max);
|
||||
const { hours, minutes } = generateTime('en-US', today, 'h12', undefined, max);
|
||||
|
||||
expect(hours.length).toEqual(0);
|
||||
expect(minutes.length).toEqual(0);
|
||||
@@ -185,7 +306,7 @@ describe('generateTime()', () => {
|
||||
year: 2021,
|
||||
};
|
||||
|
||||
const { hours, minutes } = generateTime(today, 'h12', min, max);
|
||||
const { hours, minutes } = generateTime('en-US', today, 'h12', min, max);
|
||||
|
||||
expect(hours.length).toEqual(12);
|
||||
expect(minutes.length).toEqual(60);
|
||||
@@ -199,7 +320,7 @@ describe('generateTime()', () => {
|
||||
minute: 43,
|
||||
};
|
||||
|
||||
const { hours, minutes } = generateTime(today, 'h12', undefined, undefined, [1, 2, 3], [10, 15, 20]);
|
||||
const { hours, minutes } = generateTime('en-US', today, 'h12', undefined, undefined, [1, 2, 3], [10, 15, 20]);
|
||||
|
||||
expect(hours).toStrictEqual([1, 2, 3]);
|
||||
expect(minutes).toStrictEqual([10, 15, 20]);
|
||||
@@ -229,7 +350,7 @@ describe('generateTime()', () => {
|
||||
minute: 14,
|
||||
};
|
||||
|
||||
const { am, pm } = generateTime(today, 'h12', min, max);
|
||||
const { am, pm } = generateTime('en-US', today, 'h12', min, max);
|
||||
|
||||
expect(am).toBe(true);
|
||||
expect(pm).toBe(true);
|
||||
@@ -253,7 +374,7 @@ describe('generateTime()', () => {
|
||||
minute: 50,
|
||||
};
|
||||
|
||||
const { hours } = generateTime(refValue, 'h23', minParts);
|
||||
const { hours } = generateTime('en-US', refValue, 'h23', minParts);
|
||||
|
||||
expect(hours).toStrictEqual([19, 20, 21, 22, 23]);
|
||||
});
|
||||
@@ -276,7 +397,7 @@ describe('generateTime()', () => {
|
||||
minute: 30,
|
||||
};
|
||||
|
||||
const { hours, minutes } = generateTime(refValue, 'h23', minParts);
|
||||
const { hours, minutes } = generateTime('en-US', refValue, 'h23', minParts);
|
||||
|
||||
expect(hours).toStrictEqual([19, 20, 21, 22, 23]);
|
||||
expect(minutes.length).toEqual(60);
|
||||
@@ -308,7 +429,7 @@ describe('generateTime()', () => {
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
const { hours } = generateTime(refValue, 'h23', minParts, maxParts);
|
||||
const { hours } = generateTime('en-US', refValue, 'h23', minParts, maxParts);
|
||||
|
||||
expect(hours).toStrictEqual([19, 20]);
|
||||
});
|
||||
@@ -330,7 +451,7 @@ describe('generateTime()', () => {
|
||||
minute: 2,
|
||||
};
|
||||
|
||||
const { minutes } = generateTime(refValue, 'h23', undefined, maxParts);
|
||||
const { minutes } = generateTime('en-US', refValue, 'h23', undefined, maxParts);
|
||||
|
||||
expect(minutes).toStrictEqual([0, 1, 2]);
|
||||
});
|
||||
@@ -352,7 +473,7 @@ describe('generateTime()', () => {
|
||||
minute: 2,
|
||||
};
|
||||
|
||||
const { minutes } = generateTime(refValue, 'h23', undefined, maxParts);
|
||||
const { minutes } = generateTime('en-US', refValue, 'h23', undefined, maxParts);
|
||||
|
||||
expect(minutes.length).toEqual(60);
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@@ -56,11 +56,17 @@ 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('12');
|
||||
expect(getFormattedHour(1, 'h11')).toEqual('1');
|
||||
expect(getFormattedHour(1, 'h12')).toEqual('1');
|
||||
expect(getFormattedHour(1, 'h23')).toEqual('01');
|
||||
expect(getFormattedHour(1, 'h24')).toEqual('01');
|
||||
});
|
||||
|
||||
expect(getFormattedHour(10, true)).toEqual('10');
|
||||
expect(getFormattedHour(10, false)).toEqual('10');
|
||||
it('should return correct hour value for hour cycle', () => {
|
||||
expect(getFormattedHour(0, 'h11')).toEqual('0');
|
||||
expect(getFormattedHour(0, 'h12')).toEqual('12');
|
||||
expect(getFormattedHour(0, 'h23')).toEqual('00');
|
||||
expect(getFormattedHour(0, 'h24')).toEqual('24');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -111,7 +117,7 @@ describe('getLocalizedTime', () => {
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
expect(getLocalizedTime('en-US', datetimeParts, false)).toEqual('1:40 PM');
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12')).toEqual('1:40 PM');
|
||||
});
|
||||
|
||||
it('should localize the time to AM', () => {
|
||||
@@ -123,7 +129,7 @@ describe('getLocalizedTime', () => {
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
expect(getLocalizedTime('en-US', datetimeParts, false)).toEqual('9:40 AM');
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12')).toEqual('9:40 AM');
|
||||
});
|
||||
|
||||
it('should avoid Chromium bug when using 12 hour time in a 24 hour locale', () => {
|
||||
@@ -135,7 +141,7 @@ describe('getLocalizedTime', () => {
|
||||
minute: 0,
|
||||
};
|
||||
|
||||
expect(getLocalizedTime('en-GB', datetimeParts, false)).toEqual('12:00 am');
|
||||
expect(getLocalizedTime('en-GB', datetimeParts, 'h12')).toEqual('12:00 am');
|
||||
});
|
||||
it('should parse time-only values correctly', () => {
|
||||
const datetimeParts = {
|
||||
@@ -143,7 +149,7 @@ describe('getLocalizedTime', () => {
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
expect(getLocalizedTime('en-US', datetimeParts, false)).toEqual('10:40 PM');
|
||||
expect(getLocalizedTime('en-US', datetimeParts, true)).toEqual('22:40');
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12')).toEqual('10:40 PM');
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h23')).toEqual('22:40');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isLeapYear, getNumDaysInMonth, is24Hour, isMonthFirstLocale } from '../utils/helpers';
|
||||
import { isLeapYear, getNumDaysInMonth, is24Hour, isMonthFirstLocale, getHourCycle } from '../utils/helpers';
|
||||
|
||||
describe('daysInMonth()', () => {
|
||||
it('should return correct days in month for month and year', () => {
|
||||
@@ -37,14 +37,29 @@ describe('isLeapYear()', () => {
|
||||
|
||||
describe('is24Hour()', () => {
|
||||
it('should return true if the locale uses 24 hour time', () => {
|
||||
expect(is24Hour('en-US')).toBe(false);
|
||||
expect(is24Hour('en-US', 'h23')).toBe(true);
|
||||
expect(is24Hour('en-US', 'h12')).toBe(false);
|
||||
expect(is24Hour('en-US-u-hc-h23')).toBe(true);
|
||||
expect(is24Hour('en-GB')).toBe(true);
|
||||
expect(is24Hour('en-GB', 'h23')).toBe(true);
|
||||
expect(is24Hour('en-GB', 'h12')).toBe(false);
|
||||
expect(is24Hour('en-GB-u-hc-h12')).toBe(false);
|
||||
expect(is24Hour('h11')).toBe(false);
|
||||
expect(is24Hour('h12')).toBe(false);
|
||||
expect(is24Hour('h23')).toBe(true);
|
||||
expect(is24Hour('h24')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getHourCycle()', () => {
|
||||
it('should return the correct hour cycle', () => {
|
||||
expect(getHourCycle('en-US')).toBe('h12');
|
||||
expect(getHourCycle('en-US', 'h23')).toBe('h23');
|
||||
expect(getHourCycle('en-US', 'h12')).toBe('h12');
|
||||
expect(getHourCycle('en-US-u-hc-h23')).toBe('h23');
|
||||
expect(getHourCycle('en-GB')).toBe('h23');
|
||||
expect(getHourCycle('en-GB', 'h23')).toBe('h23');
|
||||
expect(getHourCycle('en-GB', 'h12')).toBe('h12');
|
||||
expect(getHourCycle('en-GB-u-hc-h12')).toBe('h12');
|
||||
|
||||
expect(getHourCycle('en-GB', 'h11')).toBe('h11');
|
||||
expect(getHourCycle('en-GB-u-hc-h11')).toBe('h11');
|
||||
|
||||
expect(getHourCycle('en-GB', 'h24')).toBe('h24');
|
||||
expect(getHourCycle('en-GB-u-hc-h24')).toBe('h24');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -25,5 +25,27 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
const timeButton = page.locator('ion-datetime .time-body');
|
||||
await expect(timeButton).toHaveText('4:30 PM');
|
||||
});
|
||||
test('should set the h11 hour cycle correctly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime hour-cycle="h11" value="2022-01-01T00:30:00"></ion-datetime>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const timeButton = page.locator('ion-datetime .time-body');
|
||||
await expect(timeButton).toHaveText('0:30 AM');
|
||||
});
|
||||
test('should set the h24 hour cycle correctly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime hour-cycle="h24" value="2022-01-01T00:30:00"></ion-datetime>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const timeButton = page.locator('ion-datetime .time-body');
|
||||
await expect(timeButton).toHaveText('24:30');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -51,6 +51,14 @@
|
||||
<h2>h12 Hour cycle</h2>
|
||||
<ion-datetime hour-cycle="h12"></ion-datetime>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>h11 Hour cycle</h2>
|
||||
<ion-datetime hour-cycle="h11"></ion-datetime>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>h24 Hour cycle</h2>
|
||||
<ion-datetime hour-cycle="h24"></ion-datetime>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>h23 Hour cycle (Extension Tag)</h2>
|
||||
<ion-datetime locale="en-US-u-hc-h23"></ion-datetime>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@@ -1,6 +1,6 @@
|
||||
import type { Mode } from '../../../interface';
|
||||
import type { PickerColumnItem } from '../../picker-column-internal/picker-column-internal-interfaces';
|
||||
import type { DatetimeParts } from '../datetime-interface';
|
||||
import type { DatetimeParts, DatetimeHourCycle } from '../datetime-interface';
|
||||
|
||||
import { isAfter, isBefore, isSameDay } from './comparison';
|
||||
import {
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
getTodayLabel,
|
||||
getYear,
|
||||
} from './format';
|
||||
import { getNumDaysInMonth, is24Hour } from './helpers';
|
||||
import { getNumDaysInMonth, is24Hour, getHourCycle } from './helpers';
|
||||
import { getNextMonth, getPreviousMonth, getInternalHourValue } from './manipulation';
|
||||
|
||||
/**
|
||||
@@ -44,9 +44,19 @@ 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,
|
||||
];
|
||||
|
||||
// h11 hour system uses 0-11. Midnight starts at 0:00am.
|
||||
const hour11 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
||||
|
||||
// h12 hour system uses 0-12. Midnight starts at 12:00am.
|
||||
const hour12 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
||||
|
||||
// h23 hour system uses 0-23. Midnight starts at 0:00.
|
||||
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];
|
||||
|
||||
// h24 hour system uses 1-24. Midnight starts at 24:00.
|
||||
const hour24 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0];
|
||||
|
||||
/**
|
||||
* Given a locale and a mode,
|
||||
* return an array with formatted days
|
||||
@@ -125,21 +135,42 @@ export const getDaysOfMonth = (month: number, year: number, firstDayOfWeek: numb
|
||||
return days;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an array of pre-defined hour
|
||||
* values based on the provided hourCycle.
|
||||
*/
|
||||
const getHourData = (hourCycle: DatetimeHourCycle) => {
|
||||
switch (hourCycle) {
|
||||
case 'h11':
|
||||
return hour11;
|
||||
case 'h12':
|
||||
return hour12;
|
||||
case 'h23':
|
||||
return hour23;
|
||||
case 'h24':
|
||||
return hour24;
|
||||
default:
|
||||
throw new Error(`Invalid hour cycle "${hourCycle}"`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a local, reference datetime parts and option
|
||||
* max/min bound datetime parts, calculate the acceptable
|
||||
* hour and minute values according to the bounds and locale.
|
||||
*/
|
||||
export const generateTime = (
|
||||
locale: string,
|
||||
refParts: DatetimeParts,
|
||||
hourCycle: 'h12' | 'h23' = 'h12',
|
||||
hourCycle: DatetimeHourCycle = 'h12',
|
||||
minParts?: DatetimeParts,
|
||||
maxParts?: DatetimeParts,
|
||||
hourValues?: number[],
|
||||
minuteValues?: number[]
|
||||
) => {
|
||||
const use24Hour = hourCycle === 'h23';
|
||||
let processedHours = use24Hour ? hour23 : hour12;
|
||||
const computedHourCycle = getHourCycle(locale, hourCycle);
|
||||
const use24Hour = is24Hour(computedHourCycle);
|
||||
let processedHours = getHourData(computedHourCycle);
|
||||
let processedMinutes = minutes;
|
||||
let isAMAllowed = true;
|
||||
let isPMAllowed = true;
|
||||
@@ -540,16 +571,18 @@ export const getCombinedDateColumnData = (
|
||||
export const getTimeColumnsData = (
|
||||
locale: string,
|
||||
refParts: DatetimeParts,
|
||||
hourCycle?: 'h23' | 'h12',
|
||||
hourCycle?: DatetimeHourCycle,
|
||||
minParts?: DatetimeParts,
|
||||
maxParts?: DatetimeParts,
|
||||
allowedHourValues?: number[],
|
||||
allowedMinuteValues?: number[]
|
||||
): { [key: string]: PickerColumnItem[] } => {
|
||||
const use24Hour = is24Hour(locale, hourCycle);
|
||||
const computedHourCycle = getHourCycle(locale, hourCycle);
|
||||
const use24Hour = is24Hour(computedHourCycle);
|
||||
const { hours, minutes, am, pm } = generateTime(
|
||||
locale,
|
||||
refParts,
|
||||
use24Hour ? 'h23' : 'h12',
|
||||
computedHourCycle,
|
||||
minParts,
|
||||
maxParts,
|
||||
allowedHourValues,
|
||||
@@ -558,7 +591,7 @@ export const getTimeColumnsData = (
|
||||
|
||||
const hoursItems = hours.map((hour) => {
|
||||
return {
|
||||
text: getFormattedHour(hour, use24Hour),
|
||||
text: getFormattedHour(hour, computedHourCycle),
|
||||
value: getInternalHourValue(hour, use24Hour, refParts.ampm),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { DatetimeParts } from '../datetime-interface';
|
||||
import type { DatetimeParts, DatetimeHourCycle } from '../datetime-interface';
|
||||
|
||||
import { is24Hour } from './helpers';
|
||||
import { convertDataToISO } from './manipulation';
|
||||
|
||||
const getFormattedDayPeriod = (dayPeriod?: string) => {
|
||||
@@ -10,7 +11,7 @@ const getFormattedDayPeriod = (dayPeriod?: string) => {
|
||||
return dayPeriod.toUpperCase();
|
||||
};
|
||||
|
||||
export const getLocalizedTime = (locale: string, refParts: DatetimeParts, use24Hour: boolean): string => {
|
||||
export const getLocalizedTime = (locale: string, refParts: DatetimeParts, hourCycle: DatetimeHourCycle): string => {
|
||||
const timeParts: Pick<DatetimeParts, 'hour' | 'minute'> = {
|
||||
hour: refParts.hour,
|
||||
minute: refParts.minute,
|
||||
@@ -34,7 +35,7 @@ export const getLocalizedTime = (locale: string, refParts: DatetimeParts, use24H
|
||||
* We use hourCycle here instead of hour12 due to:
|
||||
* https://bugs.chromium.org/p/chromium/issues/detail?id=1347316&q=hour12&can=2
|
||||
*/
|
||||
hourCycle: use24Hour ? 'h23' : 'h12',
|
||||
hourCycle,
|
||||
/**
|
||||
* Setting Z at the end indicates that this
|
||||
* date string is in the UTC time zone. This
|
||||
@@ -83,18 +84,34 @@ export const addTimePadding = (value: number): string => {
|
||||
* 12 hour times it ensures that
|
||||
* hour 0 is formatted as '12'.
|
||||
*/
|
||||
export const getFormattedHour = (hour: number, use24Hour: boolean): string => {
|
||||
if (use24Hour) {
|
||||
return addTimePadding(hour);
|
||||
}
|
||||
|
||||
export const getFormattedHour = (hour: number, hourCycle: DatetimeHourCycle): string => {
|
||||
/**
|
||||
* If using 12 hour
|
||||
* format, make sure hour
|
||||
* 0 is formatted as '12'.
|
||||
* Midnight for h11 starts at 0:00am
|
||||
* Midnight for h12 starts at 12:00am
|
||||
* Midnight for h23 starts at 00:00
|
||||
* Midnight for h24 starts at 24:00
|
||||
*/
|
||||
if (hour === 0) {
|
||||
return '12';
|
||||
switch (hourCycle) {
|
||||
case 'h11':
|
||||
return '0';
|
||||
case 'h12':
|
||||
return '12';
|
||||
case 'h23':
|
||||
return '00';
|
||||
case 'h24':
|
||||
return '24';
|
||||
default:
|
||||
throw new Error(`Invalid hour cycle "${hourCycle}"`);
|
||||
}
|
||||
}
|
||||
|
||||
const use24Hour = is24Hour(hourCycle);
|
||||
/**
|
||||
* h23 and h24 use 24 hour times.
|
||||
*/
|
||||
if (use24Hour) {
|
||||
return addTimePadding(hour);
|
||||
}
|
||||
|
||||
return hour.toString();
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/**
|
||||
* Typescript 4.x does not recognize hourCycle as a valid option.
|
||||
* See https://github.com/microsoft/TypeScript/issues/34399.
|
||||
*/
|
||||
interface DatetimeFormatOptions extends Intl.ResolvedDateTimeFormatOptions {
|
||||
hourCycle?: 'h11' | 'h12' | 'h23' | 'h24';
|
||||
}
|
||||
import type { DatetimeHourCycle } from '../datetime-interface';
|
||||
|
||||
/**
|
||||
* Determines if given year is a
|
||||
@@ -16,13 +10,19 @@ export const isLeapYear = (year: number) => {
|
||||
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
||||
};
|
||||
|
||||
export const is24Hour = (locale: string, hourCycle?: 'h23' | 'h12') => {
|
||||
/**
|
||||
* Determines the hour cycle for a user.
|
||||
* If the hour cycle is explicitly defined, just use that.
|
||||
* Otherwise, we try to derive it from either the specified
|
||||
* locale extension tags or from Intl.DateTimeFormat directly.
|
||||
*/
|
||||
export const getHourCycle = (locale: string, hourCycle?: DatetimeHourCycle) => {
|
||||
/**
|
||||
* If developer has explicitly enabled h23 time
|
||||
* If developer has explicitly enabled 24-hour time
|
||||
* then return early and do not look at the system default.
|
||||
*/
|
||||
if (hourCycle !== undefined) {
|
||||
return hourCycle === 'h23';
|
||||
return hourCycle;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,9 +32,9 @@ export const is24Hour = (locale: string, hourCycle?: 'h23' | 'h12') => {
|
||||
* option into the locale string. Example: `en-US-u-hc-h23`
|
||||
*/
|
||||
const formatted = new Intl.DateTimeFormat(locale, { hour: 'numeric' });
|
||||
const options = formatted.resolvedOptions() as DatetimeFormatOptions;
|
||||
const options = formatted.resolvedOptions();
|
||||
if (options.hourCycle !== undefined) {
|
||||
return options.hourCycle === 'h23';
|
||||
return options.hourCycle;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +50,34 @@ export const is24Hour = (locale: string, hourCycle?: 'h23' | 'h12') => {
|
||||
throw new Error('Hour value not found from DateTimeFormat');
|
||||
}
|
||||
|
||||
return hour.value === '00';
|
||||
/**
|
||||
* Midnight for h11 starts at 0:00am
|
||||
* Midnight for h12 starts at 12:00am
|
||||
* Midnight for h23 starts at 00:00
|
||||
* Midnight for h24 starts at 24:00
|
||||
*/
|
||||
switch (hour.value) {
|
||||
case '0':
|
||||
return 'h11';
|
||||
case '12':
|
||||
return 'h12';
|
||||
case '00':
|
||||
return 'h23';
|
||||
case '24':
|
||||
return 'h24';
|
||||
default:
|
||||
throw new Error(`Invalid hour cycle "${hourCycle}"`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if the hour cycle uses a 24-hour format.
|
||||
* Returns true for h23 and h24. Returns false otherwise.
|
||||
* If you don't know the hourCycle, use getHourCycle above
|
||||
* and pass the result into this function.
|
||||
*/
|
||||
export const is24Hour = (hourCycle: DatetimeHourCycle) => {
|
||||
return hourCycle === 'h23' || hourCycle === 'h24';
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.fab-button-small) {
|
||||
@include margin(($fab-size - $fab-small-size) * 0.5);
|
||||
@include margin($fab-button-small-margin);
|
||||
|
||||
width: #{$fab-small-size};
|
||||
height: #{$fab-small-size};
|
||||
|
||||
@@ -11,3 +11,6 @@ $fab-small-size: 40px !default;
|
||||
|
||||
/// @prop - Border radius of the FAB button
|
||||
$fab-border-radius: 50% !default;
|
||||
|
||||
/// @prop - Margin applied to the small FAB button
|
||||
$fab-button-small-margin: 8px !default;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
:host {
|
||||
@include margin($fab-size + $fab-list-margin, 0);
|
||||
@include margin(calc(100% + #{$fab-list-margin}), 0);
|
||||
|
||||
display: none;
|
||||
position: absolute;
|
||||
@@ -13,8 +13,15 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
min-width: $fab-size;
|
||||
min-height: $fab-size;
|
||||
/**
|
||||
* The list should be centered relative to the parent
|
||||
* FAB button. We set minimum dimensions so the
|
||||
* FAB list can be centered relative to the small FAB button.
|
||||
* However, the small FAB button adds start/end margin, so we need
|
||||
* to account for that in the FAB list dimensions.
|
||||
*/
|
||||
min-width: $fab-small-size + ($fab-button-small-margin * 2);
|
||||
min-height: $fab-small-size + ($fab-button-small-margin * 2);
|
||||
}
|
||||
|
||||
:host(.fab-list-active) {
|
||||
@@ -59,14 +66,14 @@
|
||||
}
|
||||
|
||||
:host(.fab-list-side-start) {
|
||||
@include margin(0, $fab-size + $fab-list-margin);
|
||||
@include margin(0, calc(100% + #{$fab-list-margin}));
|
||||
@include position-horizontal(null, 0);
|
||||
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
:host(.fab-list-side-end) {
|
||||
@include margin(0, $fab-size + $fab-list-margin);
|
||||
@include margin(0, calc(100% + #{$fab-list-margin}));
|
||||
@include position(null, null, null, 0);
|
||||
|
||||
flex-direction: row;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "./fab.vars";
|
||||
@import "../fab-list/fab-list.vars";
|
||||
|
||||
// Floating Action Button Container
|
||||
// --------------------------------------------------
|
||||
@@ -6,6 +7,9 @@
|
||||
:host {
|
||||
position: absolute;
|
||||
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
|
||||
z-index: $z-index-fixed-content;
|
||||
}
|
||||
|
||||
@@ -14,8 +18,8 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.fab-horizontal-center) {
|
||||
@include position(null, null, null, 50%);
|
||||
@include margin-horizontal(-$fab-size * 0.5, null);
|
||||
@include position(null, 0px, null, 0px);
|
||||
@include margin(null, auto);
|
||||
}
|
||||
|
||||
:host(.fab-horizontal-start) {
|
||||
@@ -38,22 +42,93 @@
|
||||
top: $fab-content-margin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the top value since edge
|
||||
* styles use margin-top.
|
||||
*/
|
||||
:host(.fab-vertical-top.fab-edge) {
|
||||
top: -$fab-size * 0.5;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to adjust the parent FAB button up by half
|
||||
* its height so that half of it sits on the header. As a result,
|
||||
* we target the slotted ion-fab-button instead of targeting the host.
|
||||
*/
|
||||
:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-button) {
|
||||
margin-top: -50%;
|
||||
}
|
||||
|
||||
/**
|
||||
* The small FAB button adds top and bottom margin. We need to account for
|
||||
* that margin when we adjust the FAB button for edge styles since we
|
||||
* are overriding the margin-top value below.
|
||||
*/
|
||||
:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-button.fab-button-small) {
|
||||
margin-top: calc((-100% + $fab-button-small-margin * 2) / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since we are adjusting the FAB button we also need
|
||||
* to adjust the sibling ion-fab-list otherwise there will be
|
||||
* a gap between the parent FAB button and the associated list.
|
||||
*/
|
||||
:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-list.fab-list-side-start),
|
||||
:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-list.fab-list-side-end) {
|
||||
@include margin(-50%, null, null, null);
|
||||
}
|
||||
|
||||
:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-list.fab-list-side-top),
|
||||
:host(.fab-vertical-top.fab-edge) ::slotted(ion-fab-list.fab-list-side-bottom) {
|
||||
@include margin(calc(50% + #{$fab-list-margin}) null, null, null);
|
||||
}
|
||||
|
||||
:host(.fab-vertical-bottom) {
|
||||
bottom: $fab-content-margin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the bottom value since edge
|
||||
* styles use margin-bottom.
|
||||
*/
|
||||
:host(.fab-vertical-bottom.fab-edge) {
|
||||
bottom: -$fab-size * 0.5;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to adjust the parent FAB button down by half
|
||||
* its height so that half of it sits on the footer. As a result,
|
||||
* we target the slotted ion-fab-button instead of targeting the host.
|
||||
*/
|
||||
:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-button) {
|
||||
margin-bottom: -50%;
|
||||
}
|
||||
|
||||
/**
|
||||
* The small FAB button adds top and bottom margin. We need to account for
|
||||
* that margin when we adjust the FAB button for edge styles since we
|
||||
* are overriding the margin-bottom value below.
|
||||
*/
|
||||
:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-button.fab-button-small) {
|
||||
margin-bottom: calc((-100% + $fab-button-small-margin * 2) / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since we are adjusting the FAB button we also need
|
||||
* to adjust the sibling ion-fab-list otherwise there will be
|
||||
* a gap between the parent FAB button and the associated list.
|
||||
*/
|
||||
:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-list.fab-list-side-start),
|
||||
:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-list.fab-list-side-end) {
|
||||
@include margin(null, null, -50%, null);
|
||||
}
|
||||
|
||||
:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-list.fab-list-side-top),
|
||||
:host(.fab-vertical-bottom.fab-edge) ::slotted(ion-fab-list.fab-list-side-bottom) {
|
||||
@include margin(null, null, calc(50% + #{$fab-list-margin}) null);
|
||||
}
|
||||
|
||||
:host(.fab-vertical-center) {
|
||||
@include margin(-$fab-size * 0.5, null, null, null);
|
||||
|
||||
top: 50%;
|
||||
@include position(0px, null, 0px, null);
|
||||
@include margin(auto, null);
|
||||
}
|
||||
|
||||
17
core/src/components/fab/test/custom-size/fab.e2e.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test, Viewports } from '@utils/test/playwright';
|
||||
|
||||
/**
|
||||
* This behavior does not vary across modes
|
||||
*/
|
||||
configs({ modes: ['ios'] }).forEach(({ title, config, screenshot }) => {
|
||||
test.describe(title('fab: custom size'), () => {
|
||||
test('should position fabs correctly with custom sizes', async ({ page }) => {
|
||||
await page.goto(`/src/components/fab/test/custom-size`, config);
|
||||
|
||||
await page.setViewportSize(Viewports.tablet.landscape);
|
||||
|
||||
await expect(page).toHaveScreenshot(screenshot(`fab-custom-size`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 68 KiB |
241
core/src/components/fab/test/custom-size/index.html
Normal file
@@ -0,0 +1,241 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Floating Action Button - Custom Size</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
|
||||
/>
|
||||
<link href="../../../../../css/ionic.bundle.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>
|
||||
<style>
|
||||
.ruler-y {
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
|
||||
background: red;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
margin: 0 auto;
|
||||
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.ruler-x {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
|
||||
background: red;
|
||||
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
margin: 0 auto;
|
||||
|
||||
z-index: 10000;
|
||||
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
ion-fab-button {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Floating Action Button - Custom Size</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding" id="content">
|
||||
<div class="ruler-y"></div>
|
||||
<div class="ruler-x"></div>
|
||||
|
||||
<ion-fab vertical="top" horizontal="start" slot="fixed" edge="true">
|
||||
<ion-fab-button activated="true">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="bottom" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="end" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab vertical="top" horizontal="end" slot="fixed" edge="true">
|
||||
<ion-fab-button activated="true">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="start" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="bottom" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab vertical="bottom" horizontal="start" slot="fixed" edge="true">
|
||||
<ion-fab-button activated="true">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="top" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="end" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab vertical="bottom" horizontal="end" slot="fixed" edge="true">
|
||||
<ion-fab-button activated="true">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="start" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="top" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
|
||||
<ion-fab vertical="center" horizontal="center" slot="fixed">
|
||||
<ion-fab-button activated="true">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-list side="start" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="top" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="bottom" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="end" activated="true">
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-vimeo"></ion-icon>
|
||||
</ion-fab-button>
|
||||
<ion-fab-button show="true">
|
||||
<ion-icon name="logo-instagram"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
|
||||
<ion-footer>
|
||||
<ion-toolbar>
|
||||
<ion-title>Floating Action Button - Basic</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
@@ -107,3 +107,28 @@
|
||||
.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main header is only hidden once the collapsible large
|
||||
* title is configured. As a result, if the main header loads
|
||||
* before the collapsible large title is configured then the
|
||||
* main header will be visible briefly before being hidden
|
||||
* by the collapsible large title.
|
||||
*
|
||||
* The following selector ensures that any main header
|
||||
* on a page with a collapsible large title is hidden
|
||||
* before the collapsible large title is configured.
|
||||
* Once the collapsible large title is configured the main
|
||||
* header will have the ".header-collapse-main" class, and
|
||||
* this selector will no longer apply.
|
||||
*
|
||||
* The :has(...) part of the selector ensures a couple things:
|
||||
* 1. This will only apply within a page view since the content
|
||||
* must be a subsequent-sibling of the header (~ ion-content).
|
||||
* 2. This will only apply when that content has a collapse header (ion-header[collapse="condense"])
|
||||
*
|
||||
* We use opacity: 0 to avoid a layout shift.
|
||||
*/
|
||||
ion-header:not(.header-collapse-main):has(~ ion-content ion-header[collapse="condense"]) {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
@@ -30,7 +30,6 @@ export interface MenuControllerI {
|
||||
_setOpen(menu: MenuI, shouldOpen: boolean, animated: boolean): Promise<boolean>;
|
||||
_register(menu: MenuI): void;
|
||||
_unregister(menu: MenuI): void;
|
||||
_setActiveMenu(menu: MenuI): void;
|
||||
|
||||
getMenus(): Promise<HTMLIonMenuElement[]>;
|
||||
getOpenSync(): HTMLIonMenuElement | undefined;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||
import { Build, Component, Element, Event, Host, Listen, Method, Prop, State, Watch, h } from '@stencil/core';
|
||||
import { getTimeGivenProgression } from '@utils/animation/cubic-bezier';
|
||||
import { doc } from '@utils/browser';
|
||||
import { GESTURE_CONTROLLER } from '@utils/gesture';
|
||||
import type { Attributes } from '@utils/helpers';
|
||||
import { inheritAriaAttributes, assert, clamp, isEndSide as isEnd } from '@utils/helpers';
|
||||
@@ -40,6 +39,15 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
private blocker = GESTURE_CONTROLLER.createBlocker({ disableScroll: true });
|
||||
private didLoad = false;
|
||||
|
||||
/**
|
||||
* Flag used to determine if an open/close
|
||||
* operation was cancelled. For example, if
|
||||
* an app calls "menu.open" then disables the menu
|
||||
* part way through the animation, then this would
|
||||
* be considered a cancelled operation.
|
||||
*/
|
||||
private operationCancelled = false;
|
||||
|
||||
isAnimating = false;
|
||||
width!: number;
|
||||
_isOpen = false;
|
||||
@@ -432,6 +440,17 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
|
||||
await this.loadAnimation();
|
||||
await this.startAnimation(shouldOpen, animated);
|
||||
|
||||
/**
|
||||
* If the animation was cancelled then
|
||||
* return false because the operation
|
||||
* did not succeed.
|
||||
*/
|
||||
if (this.operationCancelled) {
|
||||
this.operationCancelled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.afterAnimation(shouldOpen);
|
||||
|
||||
return true;
|
||||
@@ -472,18 +491,24 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
const easingReverse = mode === 'ios' ? iosEasingReverse : mdEasingReverse;
|
||||
const ani = (this.animation as Animation)!
|
||||
.direction(isReversed ? 'reverse' : 'normal')
|
||||
.easing(isReversed ? easingReverse : easing)
|
||||
.onFinish(() => {
|
||||
if (ani.getDirection() === 'reverse') {
|
||||
ani.direction('normal');
|
||||
}
|
||||
});
|
||||
.easing(isReversed ? easingReverse : easing);
|
||||
|
||||
if (animated) {
|
||||
await ani.play();
|
||||
} else {
|
||||
ani.play({ sync: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* We run this after the play invocation
|
||||
* instead of using ani.onFinish so that
|
||||
* multiple onFinish callbacks do not get
|
||||
* run if an animation is played, stopped,
|
||||
* and then played again.
|
||||
*/
|
||||
if (ani.getDirection() === 'reverse') {
|
||||
ani.direction('normal');
|
||||
}
|
||||
}
|
||||
|
||||
private _isActive() {
|
||||
@@ -643,8 +668,6 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
}
|
||||
|
||||
private afterAnimation(isOpen: boolean) {
|
||||
assert(this.isAnimating, '_before() should be called while animating');
|
||||
|
||||
// keep opening/closing the menu disabled for a touch more yet
|
||||
// only add listeners/css if it's enabled and isOpen
|
||||
// and only remove listeners/css if it's not open
|
||||
@@ -713,36 +736,31 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
this.gesture.enable(isActive && this.swipeGesture);
|
||||
}
|
||||
|
||||
// Close menu immediately
|
||||
if (!isActive && this._isOpen) {
|
||||
// close if this menu is open, and should not be enabled
|
||||
this.forceClosing();
|
||||
}
|
||||
|
||||
if (doc?.contains(this.el)) {
|
||||
/**
|
||||
* If the menu is disabled but it is still open
|
||||
* then we should close the menu immediately.
|
||||
* Additionally, if the menu is in the process
|
||||
* of animating {open, close} and the menu is disabled
|
||||
* then it should still be closed immediately.
|
||||
*/
|
||||
if (!isActive) {
|
||||
/**
|
||||
* Only set the active menu if the menu element is
|
||||
* present in the DOM. Otherwise if it was destructively
|
||||
* re-hydrated (through Angular Universal), then ignore
|
||||
* setting the removed node as the active menu.
|
||||
* It is possible to disable the menu while
|
||||
* it is mid-animation. When this happens, we
|
||||
* need to set the operationCancelled flag
|
||||
* so that this._setOpen knows to return false
|
||||
* and not run the "afterAnimation" callback.
|
||||
*/
|
||||
if (!this.disabled) {
|
||||
menuController._setActiveMenu(this);
|
||||
if (this.isAnimating) {
|
||||
this.operationCancelled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the menu is disabled then we should
|
||||
* forcibly close the menu even if it is open.
|
||||
*/
|
||||
this.afterAnimation(false);
|
||||
}
|
||||
|
||||
assert(!this.isAnimating, 'can not be animating');
|
||||
}
|
||||
|
||||
private forceClosing() {
|
||||
assert(this._isOpen, 'menu cannot be closed');
|
||||
|
||||
this.isAnimating = true;
|
||||
|
||||
const ani = (this.animation as Animation)!.direction('reverse');
|
||||
ani.play({ sync: true });
|
||||
|
||||
this.afterAnimation(false);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
41
core/src/components/menu/test/disable/index.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Menu - Disable</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
|
||||
/>
|
||||
<link href="../../../../../css/ionic.bundle.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-app>
|
||||
<ion-menu side="start" id="start-menu" menu-id="start-menu" content-id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar color="primary">
|
||||
<ion-title>Menu</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding"> Menu Content </ion-content>
|
||||
</ion-menu>
|
||||
|
||||
<div class="ion-page" id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Menu - Disable</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">Content</ion-content>
|
||||
</div>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
66
core/src/components/menu/test/disable/menu.e2e.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
/**
|
||||
* This behavior does not vary across modes/directions
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('menu: disable'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(`/src/components/menu/test/disable`, config);
|
||||
});
|
||||
|
||||
test('should disable when menu is fully open', async ({ page }) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'error') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
const menu = page.locator('ion-menu');
|
||||
|
||||
// Should be visible on initial presentation
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
// Disabling menu should hide it
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => (el.disabled = true));
|
||||
await expect(menu).toBeHidden();
|
||||
|
||||
// Re-enabling menu and opening it show make it visible
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => (el.disabled = false));
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
expect(logs.length).toBe(0);
|
||||
});
|
||||
|
||||
test('should disable when menu is animating', async ({ page }) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'error') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
const menu = page.locator('ion-menu');
|
||||
|
||||
// Opening and quickly disabling menu should hide it
|
||||
menu.evaluate((el: HTMLIonMenuElement) => {
|
||||
el.open();
|
||||
setTimeout(() => (el.disabled = true), 0);
|
||||
});
|
||||
await expect(menu).toBeHidden();
|
||||
|
||||
// Re-enabling menu and opening it show make it visible
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => (el.disabled = false));
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
expect(logs.length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
74
core/src/components/menu/test/multiple/index.html
Normal file
@@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Menu - Multiple</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
|
||||
/>
|
||||
<link href="../../../../../css/ionic.bundle.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>
|
||||
<script type="module">
|
||||
import { menuController } from '../../../../dist/ionic/index.esm.js';
|
||||
window.menuController = menuController;
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-menu side="start" menu-id="primary-menu" id="primary-menu" content-id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar color="primary">
|
||||
<ion-title>Primary</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding"> Menu Content </ion-content>
|
||||
</ion-menu>
|
||||
|
||||
<ion-menu side="start" menu-id="secondary-menu" id="secondary-menu" content-id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar color="secondary">
|
||||
<ion-title>Secondary</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding"> Menu Content </ion-content>
|
||||
</ion-menu>
|
||||
|
||||
<ion-menu disabled="true" side="end" menu-id="success-menu" id="success-menu" content-id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar color="success">
|
||||
<ion-title>Success</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding"> Menu Content </ion-content>
|
||||
</ion-menu>
|
||||
|
||||
<ion-menu disabled="true" side="end" menu-id="danger-menu" id="danger-menu" content-id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar color="danger">
|
||||
<ion-title>Danger</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding"> Menu Content </ion-content>
|
||||
</ion-menu>
|
||||
|
||||
<div class="ion-page" id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-menu-button menu="primary-menu" color="primary"></ion-menu-button>
|
||||
<ion-menu-button menu="secondary-menu" color="secondary"></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Menu - Multiple</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">Content</ion-content>
|
||||
</div>
|
||||
</ion-app>
|
||||
</body>
|
||||
<scrip
|
||||
</html>
|
||||
79
core/src/components/menu/test/multiple/menu.e2e.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
/**
|
||||
* This behavior does not vary across modes/directions
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('menu: multiple'), () => {
|
||||
test.beforeEach(async ({ page }, testInfo) => {
|
||||
testInfo.annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/18974',
|
||||
});
|
||||
|
||||
await page.goto(`/src/components/menu/test/multiple`, config);
|
||||
});
|
||||
|
||||
test('should present each menu on the same side individually', async ({ page }) => {
|
||||
const primaryMenu = page.locator('ion-menu#primary-menu');
|
||||
const secondaryMenu = page.locator('ion-menu#secondary-menu');
|
||||
|
||||
await primaryMenu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(primaryMenu).toBeVisible();
|
||||
|
||||
await primaryMenu.evaluate((el: HTMLIonMenuElement) => el.close());
|
||||
await expect(primaryMenu).toBeHidden();
|
||||
|
||||
await secondaryMenu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(secondaryMenu).toBeVisible();
|
||||
|
||||
await secondaryMenu.evaluate((el: HTMLIonMenuElement) => el.close());
|
||||
await expect(secondaryMenu).toBeHidden();
|
||||
});
|
||||
|
||||
test('should close first menu when showing another menu on same side', async ({ page }) => {
|
||||
const primaryMenu = page.locator('ion-menu#primary-menu');
|
||||
const secondaryMenu = page.locator('ion-menu#secondary-menu');
|
||||
|
||||
await primaryMenu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(primaryMenu).toBeVisible();
|
||||
|
||||
await secondaryMenu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(primaryMenu).toBeHidden();
|
||||
await expect(secondaryMenu).toBeVisible();
|
||||
});
|
||||
|
||||
test('passing side to the menuController when multiple menus have that side should result in a warning', async ({
|
||||
page,
|
||||
}) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'warning') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
await page.evaluate(() => (window as any).menuController.open('start'));
|
||||
|
||||
expect(logs.length).toBe(1);
|
||||
});
|
||||
|
||||
test('passing side to the menuController when multiple disabled menus have that side should result in a warning', async ({
|
||||
page,
|
||||
}) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'warning') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
await page.evaluate(() => (window as any).menuController.open('end'));
|
||||
|
||||
expect(logs.length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -6,6 +6,5 @@
|
||||
position: absolute;
|
||||
|
||||
contain: layout size style;
|
||||
overflow: hidden;
|
||||
z-index: $z-index-page-container;
|
||||
}
|
||||
|
||||
@@ -901,6 +901,7 @@ export class Nav implements NavOutlet {
|
||||
: undefined;
|
||||
const mode = getIonMode(this);
|
||||
const enteringEl = enteringView.element!;
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
||||
const leavingEl = leavingView && leavingView.element!;
|
||||
const animationOpts: TransitionOptions = {
|
||||
mode,
|
||||
|
||||
@@ -39,7 +39,7 @@ export async function testPickerColumn(
|
||||
await page.waitForChanges();
|
||||
|
||||
screenshots.push({
|
||||
name: `picker-${description}-column-diff-${i}-${page.getSnapshotSettings()}.png`,
|
||||
name: screenshot(`picker-${description}-column-diff-${i}`),
|
||||
screenshot: await page.screenshot(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -319,6 +319,7 @@ export class Range implements ComponentInterface {
|
||||
componentDidLoad() {
|
||||
this.originalIonInput = this.ionInput;
|
||||
this.setupGesture();
|
||||
this.updateRatio();
|
||||
this.didLoad = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,5 @@
|
||||
position: absolute;
|
||||
|
||||
contain: layout size style;
|
||||
overflow: hidden;
|
||||
z-index: $z-index-page-container;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Component, Element, Event, Method, Prop, Watch, h } from '@stencil/core
|
||||
import { getTimeGivenProgression } from '@utils/animation/cubic-bezier';
|
||||
import { attachComponent, detachComponent } from '@utils/framework-delegate';
|
||||
import { shallowEqualStringMap, hasLazyBuild } from '@utils/helpers';
|
||||
import { createLockController } from '@utils/lock-controller';
|
||||
import { transition } from '@utils/transition';
|
||||
|
||||
import { config } from '../../global/config';
|
||||
@@ -24,11 +25,11 @@ import type { RouteID, RouterDirection, RouteWrite, NavOutlet } from '../router/
|
||||
shadow: true,
|
||||
})
|
||||
export class RouterOutlet implements ComponentInterface, NavOutlet {
|
||||
private readonly lockController = createLockController();
|
||||
private activeEl: HTMLElement | undefined;
|
||||
// TODO(FW-2832): types
|
||||
private activeComponent: any;
|
||||
private activeParams: any;
|
||||
private waitPromise?: Promise<void>;
|
||||
private gesture?: Gesture;
|
||||
private ani?: Animation;
|
||||
private gestureOrAnimationInProgress = false;
|
||||
@@ -140,7 +141,7 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
|
||||
leavingEl: HTMLElement | undefined,
|
||||
opts?: RouterOutletOptions
|
||||
): Promise<boolean> {
|
||||
const unlock = await this.lock();
|
||||
const unlock = await this.lockController.lock();
|
||||
let changed = false;
|
||||
try {
|
||||
changed = await this.transition(enteringEl, leavingEl, opts);
|
||||
@@ -285,18 +286,6 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: FW-5048 - Remove this code in favor of using lock controller from utils
|
||||
private async lock() {
|
||||
const p = this.waitPromise;
|
||||
let resolve!: () => void;
|
||||
this.waitPromise = new Promise((r) => (resolve = r));
|
||||
|
||||
if (p !== undefined) {
|
||||
await p;
|
||||
}
|
||||
return resolve;
|
||||
}
|
||||
|
||||
render() {
|
||||
return <slot></slot>;
|
||||
}
|
||||
|
||||