mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
376 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0cfe5a283 | ||
|
|
0cdd326a4a | ||
|
|
7b140b1e12 | ||
|
|
1c93b75e39 | ||
|
|
5fef3e7b21 | ||
|
|
b04fb6e849 | ||
|
|
8ac4d12f40 | ||
|
|
a0ff24b5d6 | ||
|
|
c8a3999da1 | ||
|
|
67617fbc0f | ||
|
|
c877061a32 | ||
|
|
2f54bc1469 | ||
|
|
2a253a1d33 | ||
|
|
4ce62b26a8 | ||
|
|
e4bf052794 | ||
|
|
630848ae5c | ||
|
|
f94e618a7b | ||
|
|
de58238333 | ||
|
|
1a2fd2fb6e | ||
|
|
a1f95264e7 | ||
|
|
e256d3f09f | ||
|
|
e828a9a693 | ||
|
|
dcf5317310 | ||
|
|
f022464cf8 | ||
|
|
38eb378d66 | ||
|
|
a2763afe8e | ||
|
|
943e3f6ae3 | ||
|
|
9282aa6871 | ||
|
|
b83e00934e | ||
|
|
dd1c8dbf3b | ||
|
|
9486e51f6d | ||
|
|
fb631742af | ||
|
|
0101a5fce2 | ||
|
|
06d4c8e6f1 | ||
|
|
cd8ffd82a0 | ||
|
|
b6b2714d70 | ||
|
|
8c1646a105 | ||
|
|
68a9b80053 | ||
|
|
26285bbc91 | ||
|
|
215eb5d4ef | ||
|
|
677d55ebe4 | ||
|
|
a4c38aca88 | ||
|
|
5300dcc693 | ||
|
|
b064fdebef | ||
|
|
c05476b88e | ||
|
|
0de75afbef | ||
|
|
19d63f6243 | ||
|
|
343f855147 | ||
|
|
da1b7a0e7a | ||
|
|
3a0465e7d6 | ||
|
|
8cb2ea6804 | ||
|
|
d46e074fb1 | ||
|
|
cb2c9b63e8 | ||
|
|
ff0f1da9f1 | ||
|
|
487349f02a | ||
|
|
b6b2d34fd4 | ||
|
|
1a5accc5f7 | ||
|
|
f7d4c21b64 | ||
|
|
fa515eb79b | ||
|
|
697bcf3420 | ||
|
|
bc17e24a03 | ||
|
|
ab1fc8f231 | ||
|
|
2a3ce9a74e | ||
|
|
e2d8e5c4dc | ||
|
|
7ecae2e4cb | ||
|
|
14e8441706 | ||
|
|
e1d6627bf0 | ||
|
|
348c50b7ea | ||
|
|
9e9a372497 | ||
|
|
64719f49f9 | ||
|
|
3d6ac1382e | ||
|
|
9a02ec8402 | ||
|
|
fbb777ab5a | ||
|
|
67b0853b28 | ||
|
|
e3a05bfeb5 | ||
|
|
5c27dd8032 | ||
|
|
b768181307 | ||
|
|
f891f66708 | ||
|
|
a01bdb8c8d | ||
|
|
09a5ed6a0d | ||
|
|
39bbb99f75 | ||
|
|
11a59133d9 | ||
|
|
1ef112ef12 | ||
|
|
78740d0dfc | ||
|
|
94518c9387 | ||
|
|
31f45cdcc9 | ||
|
|
61cf0c534e | ||
|
|
8d5ed47a28 | ||
|
|
a94e2a87fb | ||
|
|
818e387fe8 | ||
|
|
ff39d40255 | ||
|
|
91aaaab71a | ||
|
|
01afdc42e5 | ||
|
|
36939e10ae | ||
|
|
5ed73cdf4d | ||
|
|
0be79fe82b | ||
|
|
216f51b12a | ||
|
|
dc9faa6a0f | ||
|
|
4f4f31b65e | ||
|
|
9d04c127e8 | ||
|
|
181fc59ab7 | ||
|
|
53ec9cff5e | ||
|
|
d61456c46d | ||
|
|
07868354aa | ||
|
|
5275332e43 | ||
|
|
ea52db66f0 | ||
|
|
c45c8d5564 | ||
|
|
afcc46e1cc | ||
|
|
4e23aad3d9 | ||
|
|
a664ccbde9 | ||
|
|
8002114e72 | ||
|
|
04b874e32a | ||
|
|
c727419350 | ||
|
|
e1e23bc1a2 | ||
|
|
cdc2fb652f | ||
|
|
bb519b8724 | ||
|
|
1956f98968 | ||
|
|
3ed44993e1 | ||
|
|
f4ecc32c14 | ||
|
|
d5eb3a44e6 | ||
|
|
33768e1d0c | ||
|
|
ce4a381d4f | ||
|
|
2d878fc4f6 | ||
|
|
65bc99577c | ||
|
|
abad12fbdb | ||
|
|
d77a9d57ec | ||
|
|
813611a61b | ||
|
|
96d6012071 | ||
|
|
7214a8401b | ||
|
|
bf3f3bb3dc | ||
|
|
3a6fcc7d8b | ||
|
|
62dd16a5ee | ||
|
|
0956f8bc55 | ||
|
|
a4a64530ff | ||
|
|
e17c822bfb | ||
|
|
f5b0299729 | ||
|
|
1267945480 | ||
|
|
907cc7b159 | ||
|
|
e76f79d054 | ||
|
|
f130fb2b17 | ||
|
|
6b817f26b0 | ||
|
|
c356526520 | ||
|
|
caa3afa613 | ||
|
|
0a0cbd8f2a | ||
|
|
639314ab21 | ||
|
|
7512c90241 | ||
|
|
0eb643d563 | ||
|
|
971e4dc6c7 | ||
|
|
aec1d89454 | ||
|
|
41eac8abf4 | ||
|
|
3ab8e5d129 | ||
|
|
dd307b60b6 | ||
|
|
5a4d0c0217 | ||
|
|
9659ad6334 | ||
|
|
9752cd6371 | ||
|
|
daf6a92127 | ||
|
|
a9b2260100 | ||
|
|
91d041485c | ||
|
|
2fea36fc98 | ||
|
|
27191026ef | ||
|
|
04161c9512 | ||
|
|
023fb18412 | ||
|
|
69d72f9c17 | ||
|
|
b885299082 | ||
|
|
9f44966d85 | ||
|
|
67e570dc95 | ||
|
|
c83826aa73 | ||
|
|
c1455a839a | ||
|
|
5d548b8672 | ||
|
|
6fad0fe428 | ||
|
|
31f9bc81d6 | ||
|
|
561a4ac535 | ||
|
|
bcef804dea | ||
|
|
1a2e5322fb | ||
|
|
5ec5b43565 | ||
|
|
bf9283eb3e | ||
|
|
f1954e2d94 | ||
|
|
062a659c4a | ||
|
|
c5ab562eaa | ||
|
|
6e9e58ed61 | ||
|
|
05b5557655 | ||
|
|
6be8b8d89d | ||
|
|
dcdb7b6f4e | ||
|
|
11a75f5d2e | ||
|
|
c37c272dda | ||
|
|
b06ae16591 | ||
|
|
52f655c9d4 | ||
|
|
fff82d0bdc | ||
|
|
6026c65b1a | ||
|
|
181d322192 | ||
|
|
c74fd4147b | ||
|
|
16cf98ffbd | ||
|
|
bfc0b25e2a | ||
|
|
9eba5939b7 | ||
|
|
49da5f85e3 | ||
|
|
32196bc4e8 | ||
|
|
d371af48e3 | ||
|
|
18ad9efa4b | ||
|
|
39d2530427 | ||
|
|
b88186b939 | ||
|
|
c251c6a723 | ||
|
|
992580a383 | ||
|
|
6549330815 | ||
|
|
d746561ea2 | ||
|
|
c454c84ef4 | ||
|
|
1878c8e7e0 | ||
|
|
2bad1bb82e | ||
|
|
6849dd3483 | ||
|
|
f5d657c6cd | ||
|
|
66b4d11545 | ||
|
|
2373ff0d39 | ||
|
|
f42c688f46 | ||
|
|
f11adabbc8 | ||
|
|
ba894746d4 | ||
|
|
e6333c0923 | ||
|
|
2cf61378a7 | ||
|
|
ba4f07e270 | ||
|
|
dcf97c6bea | ||
|
|
0f2866738b | ||
|
|
18fb8855e0 | ||
|
|
a8fbb34844 | ||
|
|
25271897e2 | ||
|
|
2c6259c1f6 | ||
|
|
f81d18c6f9 | ||
|
|
d03807a443 | ||
|
|
1832be0597 | ||
|
|
25d3ea6b8d | ||
|
|
e84f80493c | ||
|
|
5e341643d4 | ||
|
|
aeda33d8ae | ||
|
|
cc45ad815c | ||
|
|
e9b2cc8453 | ||
|
|
1526bdfb49 | ||
|
|
baafe08927 | ||
|
|
ea0e0499e2 | ||
|
|
96596bade3 | ||
|
|
2e1b7463c0 | ||
|
|
c4064f7889 | ||
|
|
423e3f0b3a | ||
|
|
fe5fadf19c | ||
|
|
ca338864bf | ||
|
|
b76bfa36c2 | ||
|
|
f82bac1780 | ||
|
|
7e449a1ca6 | ||
|
|
a24a041064 | ||
|
|
6ac6810148 | ||
|
|
68afc49e9e | ||
|
|
9ca8b9de46 | ||
|
|
ec9e0a2ee7 | ||
|
|
f714c34699 | ||
|
|
5cdf68b674 | ||
|
|
74632fa960 | ||
|
|
bd675e42c7 | ||
|
|
fbe11582e9 | ||
|
|
c1fe16193e | ||
|
|
fe2cf22f5d | ||
|
|
0971478f1f | ||
|
|
9cb22be91a | ||
|
|
67fbb3b963 | ||
|
|
3ea92f5527 | ||
|
|
99f2532ee1 | ||
|
|
c72c7ffa98 | ||
|
|
8b85fe0d9e | ||
|
|
db2cac20fb | ||
|
|
a362234472 | ||
|
|
2efab94035 | ||
|
|
af2e6ca8d2 | ||
|
|
3d34b68fbd | ||
|
|
8227844cbc | ||
|
|
a7f564b818 | ||
|
|
5ffa65f84a | ||
|
|
74af3cb50b | ||
|
|
ba23ab3d66 | ||
|
|
4090250da7 | ||
|
|
b11e06cec1 | ||
|
|
ec7c023873 | ||
|
|
e02b33ac75 | ||
|
|
e82ac39af9 | ||
|
|
c458c83a7c | ||
|
|
f52b3061e0 | ||
|
|
3f1fe13c29 | ||
|
|
3ecd899d2b | ||
|
|
6878fb9eb9 | ||
|
|
22477fb9bf | ||
|
|
e4964ff77b | ||
|
|
bd4e931fbc | ||
|
|
36e4bf7dd7 | ||
|
|
e32b9afaaa | ||
|
|
6dae5d1dfe | ||
|
|
00eac33053 | ||
|
|
9f4b01e17f | ||
|
|
5c177d756f | ||
|
|
06ab66edc7 | ||
|
|
971789dc89 | ||
|
|
434befea5f | ||
|
|
753fd2f910 | ||
|
|
7fc13ffb2a | ||
|
|
481d38df09 | ||
|
|
ae47d77710 | ||
|
|
03c2f16e46 | ||
|
|
f58424f625 | ||
|
|
74468ab797 | ||
|
|
2eaab23f38 | ||
|
|
4476817825 | ||
|
|
97e32f3b0b | ||
|
|
bfddb17065 | ||
|
|
3c9d6ea5f5 | ||
|
|
8e1178b98b | ||
|
|
470478d387 | ||
|
|
cc73a1063e | ||
|
|
349e8cd5b0 | ||
|
|
bcbe8cbb8d | ||
|
|
03ca0c5968 | ||
|
|
fff4aec6cf | ||
|
|
eb592b8917 | ||
|
|
a15cd01bc3 | ||
|
|
4199762d3e | ||
|
|
79518468dd | ||
|
|
f4a08b7ed4 | ||
|
|
dbe6853884 | ||
|
|
096eef4a79 | ||
|
|
d4a5fbd955 | ||
|
|
591c133344 | ||
|
|
d297ecb87a | ||
|
|
a625c837a6 | ||
|
|
77464ef21a | ||
|
|
fa93dffdb4 | ||
|
|
6f200ac751 | ||
|
|
7c2d0c981a | ||
|
|
1351b2eafc | ||
|
|
88f1828bd8 | ||
|
|
020f3cc56c | ||
|
|
3cbf9e7c4c | ||
|
|
2664587749 | ||
|
|
f00ad8a835 | ||
|
|
81ef3f1ecd | ||
|
|
c171ccbd37 | ||
|
|
a0735b97bf | ||
|
|
b4423a816f | ||
|
|
ff23e4f267 | ||
|
|
97123cd6c3 | ||
|
|
1dcd9de50a | ||
|
|
c458523b0d | ||
|
|
a5e4669c4b | ||
|
|
9413aa0bac | ||
|
|
ce6e637787 | ||
|
|
7a29e0e3c7 | ||
|
|
8c79e2c5b5 | ||
|
|
26674f1dfa | ||
|
|
88f23b1626 | ||
|
|
a5b3750ee2 | ||
|
|
fbcd3f8c08 | ||
|
|
04ce642369 | ||
|
|
84c421a4b0 | ||
|
|
1decc13cb8 | ||
|
|
17308f247f | ||
|
|
d8b377ffeb | ||
|
|
24cfdc308f | ||
|
|
bcccc217b8 | ||
|
|
e968bd029a | ||
|
|
7c8f621536 | ||
|
|
edceac0745 | ||
|
|
2969f9f9f2 | ||
|
|
9223abc1f8 | ||
|
|
b37c158eea | ||
|
|
ce6448b068 | ||
|
|
fd65ceec84 | ||
|
|
0bf9449ee1 | ||
|
|
cf3035778c | ||
|
|
17375d2325 | ||
|
|
df408f91f1 | ||
|
|
e95b481a53 | ||
|
|
698e526b9f | ||
|
|
f34d3752e3 | ||
|
|
c8db0d5eeb | ||
|
|
a4f0bdb4c3 |
@@ -1,4 +1,4 @@
|
||||
version: 2
|
||||
version: 2.1
|
||||
|
||||
aliases:
|
||||
- &restore-cache
|
||||
@@ -31,16 +31,35 @@ aliases:
|
||||
|
||||
defaults: &defaults
|
||||
docker:
|
||||
- image: circleci/node:10-browsers
|
||||
- image: circleci/node:latest-browsers
|
||||
working_directory: /tmp/workspace
|
||||
environment:
|
||||
NODE_ENV: development
|
||||
|
||||
jobs:
|
||||
puppeteer-dependencies:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- run:
|
||||
name: Install headless Chrome dependencies
|
||||
command: |
|
||||
sudo apt-get install -yq \
|
||||
gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
|
||||
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
|
||||
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \
|
||||
libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \
|
||||
fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
|
||||
- run:
|
||||
name: Install Puppeteer with Chromium
|
||||
command: |
|
||||
npm i puppeteer
|
||||
|
||||
build:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache: *restore-cache
|
||||
- run: npm install
|
||||
- run: npm install --legacy-peer-deps
|
||||
- save_cache: *save-cache
|
||||
- persist_to_workspace:
|
||||
root: /tmp/workspace
|
||||
@@ -56,7 +75,7 @@ jobs:
|
||||
- restore_cache: *restore-cache-core
|
||||
- restore_cache: *restore-cache-core-stencil
|
||||
- run:
|
||||
command: npm install
|
||||
command: npm install --legacy-peer-deps
|
||||
working_directory: /tmp/workspace/core
|
||||
- save_cache: *save-cache-core
|
||||
- run:
|
||||
@@ -75,7 +94,7 @@ jobs:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm install
|
||||
command: npm install --legacy-peer-deps
|
||||
working_directory: /tmp/workspace/angular
|
||||
- run:
|
||||
command: sudo npm link
|
||||
@@ -98,7 +117,7 @@ jobs:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm install
|
||||
command: npm install --legacy-peer-deps
|
||||
working_directory: /tmp/workspace/packages/angular-server
|
||||
- run:
|
||||
command: npm run build.prod
|
||||
@@ -115,7 +134,7 @@ jobs:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm install
|
||||
command: npm install --legacy-peer-deps
|
||||
working_directory: /tmp/workspace/packages/react
|
||||
- run:
|
||||
command: sudo npm link
|
||||
@@ -130,7 +149,6 @@ jobs:
|
||||
root: /tmp/workspace
|
||||
paths:
|
||||
- "*"
|
||||
|
||||
build-react-router:
|
||||
<<: *defaults
|
||||
steps:
|
||||
@@ -138,7 +156,7 @@ jobs:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm install
|
||||
command: npm install --legacy-peer-deps
|
||||
working_directory: /tmp/workspace/packages/react-router
|
||||
- run:
|
||||
command: sudo npm link
|
||||
@@ -160,6 +178,52 @@ jobs:
|
||||
paths:
|
||||
- "*"
|
||||
|
||||
build-vue:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm install
|
||||
working_directory: /tmp/workspace/packages/vue
|
||||
- run:
|
||||
command: sudo npm link
|
||||
working_directory: /tmp/workspace/core
|
||||
- run:
|
||||
command: sudo npm link @ionic/core
|
||||
working_directory: /tmp/workspace/packages/vue
|
||||
- run:
|
||||
command: npm run build
|
||||
working_directory: /tmp/workspace/packages/vue
|
||||
- persist_to_workspace:
|
||||
root: /tmp/workspace
|
||||
paths:
|
||||
- "*"
|
||||
|
||||
build-vue-router:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm install
|
||||
working_directory: /tmp/workspace/packages/vue-router
|
||||
- run:
|
||||
command: sudo npm link
|
||||
working_directory: /tmp/workspace/packages/vue
|
||||
- run:
|
||||
command: sudo npm link @ionic/vue
|
||||
working_directory: /tmp/workspace/packages/vue-router
|
||||
- run:
|
||||
command: npm run build
|
||||
working_directory: /tmp/workspace/packages/vue-router
|
||||
- persist_to_workspace:
|
||||
root: /tmp/workspace
|
||||
paths:
|
||||
- "*"
|
||||
|
||||
test-core-clean-build:
|
||||
<<: *defaults
|
||||
steps:
|
||||
@@ -263,6 +327,26 @@ jobs:
|
||||
command: npm run lint
|
||||
working_directory: /tmp/workspace/packages/react-router
|
||||
|
||||
test-vue-lint:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm run lint
|
||||
working_directory: /tmp/workspace/packages/vue
|
||||
|
||||
test-vue-router-lint:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm run lint
|
||||
working_directory: /tmp/workspace/packages/vue-router
|
||||
|
||||
test-react-spec:
|
||||
<<: *defaults
|
||||
steps:
|
||||
@@ -301,6 +385,28 @@ jobs:
|
||||
command: npm run test.spec
|
||||
working_directory: /tmp/workspace/packages/react-router
|
||||
|
||||
test-vue-router-spec:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: sudo npm link
|
||||
working_directory: /tmp/workspace/core
|
||||
- run:
|
||||
command: sudo npm link @ionic/core
|
||||
working_directory: /tmp/workspace/packages/vue
|
||||
- run:
|
||||
command: sudo npm link
|
||||
working_directory: /tmp/workspace/packages/vue
|
||||
- run:
|
||||
command: sudo npm link @ionic/vue
|
||||
working_directory: /tmp/workspace/packages/vue-router
|
||||
- run:
|
||||
command: npm run test.spec
|
||||
working_directory: /tmp/workspace/packages/vue-router
|
||||
|
||||
test-angular-e2e:
|
||||
<<: *defaults
|
||||
steps:
|
||||
@@ -308,16 +414,17 @@ jobs:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm install
|
||||
command: npm install --legacy-peer-deps
|
||||
working_directory: /tmp/workspace/angular/test/test-app
|
||||
- run:
|
||||
command: npm test
|
||||
command: npm run test -- --protractor-config=e2e/protractor-ci.conf.js
|
||||
working_directory: /tmp/workspace/angular/test/test-app
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- puppeteer-dependencies
|
||||
- build
|
||||
- build-core:
|
||||
requires: [build]
|
||||
@@ -326,11 +433,14 @@ workflows:
|
||||
- test-core-lint:
|
||||
requires: [build-core]
|
||||
- test-core-e2e:
|
||||
requires: [build-core]
|
||||
requires: [puppeteer-dependencies, build-core]
|
||||
- test-core-spec:
|
||||
requires: [build-core]
|
||||
- test-core-treeshake:
|
||||
requires: [build-core]
|
||||
# Adam requested we skip this test for now
|
||||
# since it is failing on ES5 code which
|
||||
# will be removed in Ionic Framework v6
|
||||
#- test-core-treeshake:
|
||||
# requires: [build-core]
|
||||
- test-core-screenshot:
|
||||
requires: [build-core]
|
||||
filters:
|
||||
@@ -358,6 +468,16 @@ workflows:
|
||||
requires: [build-react]
|
||||
- test-react-router-spec:
|
||||
requires: [build-react-router]
|
||||
- build-vue:
|
||||
requires: [build-core]
|
||||
- build-vue-router:
|
||||
requires: [build-core, build-vue]
|
||||
- test-vue-lint:
|
||||
requires: [build-vue]
|
||||
- test-vue-router-lint:
|
||||
requires: [build-vue-router]
|
||||
- test-vue-router-spec:
|
||||
requires: [build-vue-router]
|
||||
- test-angular-lint:
|
||||
requires: [build-angular]
|
||||
- test-angular-e2e:
|
||||
|
||||
262
.github/COMPONENT-GUIDE.md
vendored
262
.github/COMPONENT-GUIDE.md
vendored
@@ -9,6 +9,9 @@
|
||||
* [Ripple Effect](#ripple-effect)
|
||||
* [Example Components](#example-components)
|
||||
* [References](#references)
|
||||
- [Accessibility](#accessibility)
|
||||
* [Checkbox](#checkbox)
|
||||
* [Switch](#switch)
|
||||
- [Rendering Anchor or Button](#rendering-anchor-or-button)
|
||||
* [Example Components](#example-components-1)
|
||||
* [Component Structure](#component-structure-1)
|
||||
@@ -362,6 +365,265 @@ ion-ripple-effect {
|
||||
- [iOS Buttons](https://developer.apple.com/design/human-interface-guidelines/ios/controls/buttons/)
|
||||
|
||||
|
||||
## Accessibility
|
||||
|
||||
### Checkbox
|
||||
|
||||
#### Example Components
|
||||
|
||||
- [ion-checkbox](https://github.com/ionic-team/ionic/tree/master/core/src/components/checkbox)
|
||||
|
||||
#### VoiceOver
|
||||
|
||||
In order for VoiceOver to work properly with a checkbox component there must be a native `input` with `type="checkbox"`, and `aria-checked` and `role="checkbox"` **must** be on the host element. The `aria-hidden` attribute needs to be added if the checkbox is disabled, preventing iOS users from selecting it:
|
||||
|
||||
```tsx
|
||||
render() {
|
||||
const { checked, disabled } = this;
|
||||
|
||||
return (
|
||||
<Host
|
||||
aria-checked={`${checked}`}
|
||||
aria-hidden={disabled ? 'true' : null}
|
||||
role="checkbox"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
/>
|
||||
...
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### NVDA
|
||||
|
||||
It is required to have `aria-checked` on the native input for checked to read properly and `disabled` to prevent tabbing to the input:
|
||||
|
||||
```tsx
|
||||
render() {
|
||||
const { checked, disabled } = this;
|
||||
|
||||
return (
|
||||
<Host
|
||||
aria-checked={`${checked}`}
|
||||
aria-hidden={disabled ? 'true' : null}
|
||||
role="checkbox"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
aria-checked={`${checked}`}
|
||||
disabled={disabled}
|
||||
/>
|
||||
...
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### Labels
|
||||
|
||||
A helper function has been created to get the proper `aria-label` for the checkbox. This can be imported as `getAriaLabel` like the following:
|
||||
|
||||
```tsx
|
||||
const { label, labelId, labelText } = getAriaLabel(el, inputId);
|
||||
```
|
||||
|
||||
where `el` and `inputId` are the following:
|
||||
|
||||
```tsx
|
||||
export class Checkbox implements ComponentInterface {
|
||||
private inputId = `ion-cb-${checkboxIds++}`;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
This can then be added to the `Host` like the following:
|
||||
|
||||
```tsx
|
||||
<Host
|
||||
aria-labelledby={label ? labelId : null}
|
||||
aria-checked={`${checked}`}
|
||||
aria-hidden={disabled ? 'true' : null}
|
||||
role="checkbox"
|
||||
>
|
||||
```
|
||||
|
||||
In addition to that, the checkbox input should have a label added:
|
||||
|
||||
```tsx
|
||||
<Host
|
||||
aria-labelledby={label ? labelId : null}
|
||||
aria-checked={`${checked}`}
|
||||
aria-hidden={disabled ? 'true' : null}
|
||||
role="checkbox"
|
||||
>
|
||||
<label htmlFor={inputId}>
|
||||
{labelText}
|
||||
</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
aria-checked={`${checked}`}
|
||||
disabled={disabled}
|
||||
id={inputId}
|
||||
/>
|
||||
```
|
||||
|
||||
#### Hidden Input
|
||||
|
||||
A helper function to render a hidden input has been added, it can be added in the `render`:
|
||||
|
||||
```tsx
|
||||
renderHiddenInput(true, el, name, (checked ? value : ''), disabled);
|
||||
```
|
||||
|
||||
> This is required for the checkbox to work with forms.
|
||||
|
||||
#### Known Issues
|
||||
|
||||
When using VoiceOver on macOS, Chrome will announce the following when you are focused on a checkbox:
|
||||
|
||||
```
|
||||
currently on a checkbox inside of a checkbox
|
||||
```
|
||||
|
||||
This is a compromise we have to make in order for it to work with the other screen readers & Safari.
|
||||
|
||||
|
||||
### Switch
|
||||
|
||||
#### Example Components
|
||||
|
||||
- [ion-toggle](https://github.com/ionic-team/ionic/tree/master/core/src/components/toggle)
|
||||
|
||||
#### Voiceover
|
||||
|
||||
In order for VoiceOver to work properly with a switch component there must be a native `input` with `type="checkbox"` and `role="switch"`, and `aria-checked` and `role="switch"` **must** be on the host element. The `aria-hidden` attribute needs to be added if the switch is disabled, preventing iOS users from selecting it:
|
||||
|
||||
```tsx
|
||||
render() {
|
||||
const { checked, disabled } = this;
|
||||
|
||||
return (
|
||||
<Host
|
||||
aria-checked={`${checked}`}
|
||||
aria-hidden={disabled ? 'true' : null}
|
||||
role="switch"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
/>
|
||||
...
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### NVDA
|
||||
|
||||
It is required to have `aria-checked` on the native input for checked to read properly and `disabled` to prevent tabbing to the input:
|
||||
|
||||
```tsx
|
||||
render() {
|
||||
const { checked, disabled } = this;
|
||||
|
||||
return (
|
||||
<Host
|
||||
aria-checked={`${checked}`}
|
||||
aria-hidden={disabled ? 'true' : null}
|
||||
role="switch"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
aria-checked={`${checked}`}
|
||||
disabled={disabled}
|
||||
/>
|
||||
...
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### Labels
|
||||
|
||||
A helper function has been created to get the proper `aria-label` for the switch. This can be imported as `getAriaLabel` like the following:
|
||||
|
||||
```tsx
|
||||
const { label, labelId, labelText } = getAriaLabel(el, inputId);
|
||||
```
|
||||
|
||||
where `el` and `inputId` are the following:
|
||||
|
||||
```tsx
|
||||
export class Toggle implements ComponentInterface {
|
||||
private inputId = `ion-tg-${toggleIds++}`;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
This can then be added to the `Host` like the following:
|
||||
|
||||
```tsx
|
||||
<Host
|
||||
aria-labelledby={label ? labelId : null}
|
||||
aria-checked={`${checked}`}
|
||||
aria-hidden={disabled ? 'true' : null}
|
||||
role="switch"
|
||||
>
|
||||
```
|
||||
|
||||
In addition to that, the checkbox input should have a label added:
|
||||
|
||||
```tsx
|
||||
<Host
|
||||
aria-labelledby={label ? labelId : null}
|
||||
aria-checked={`${checked}`}
|
||||
aria-hidden={disabled ? 'true' : null}
|
||||
role="switch"
|
||||
>
|
||||
<label htmlFor={inputId}>
|
||||
{labelText}
|
||||
</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
aria-checked={`${checked}`}
|
||||
disabled={disabled}
|
||||
id={inputId}
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
#### Hidden Input
|
||||
|
||||
A helper function to render a hidden input has been added, it can be added in the `render`:
|
||||
|
||||
```tsx
|
||||
renderHiddenInput(true, el, name, (checked ? value : ''), disabled);
|
||||
```
|
||||
|
||||
> This is required for the switch to work with forms.
|
||||
|
||||
|
||||
#### Known Issues
|
||||
|
||||
When using VoiceOver on macOS or iOS, Chrome will announce the switch as a checked or unchecked `checkbox`:
|
||||
|
||||
```
|
||||
You are currently on a switch. To select or deselect this checkbox, press Control-Option-Space.
|
||||
```
|
||||
|
||||
There is a WebKit bug open for this: https://bugs.webkit.org/show_bug.cgi?id=196354
|
||||
|
||||
|
||||
## Rendering Anchor or Button
|
||||
|
||||
Certain components can render an `<a>` or a `<button>` depending on the presence of an `href` attribute.
|
||||
|
||||
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
5
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -10,7 +10,7 @@ assignees: ''
|
||||
|
||||
<!-- Please make sure you are posting an issue pertaining to the Ionic Framework. If you are having an issue with the Ionic Appflow services (Ionic View, Ionic Deploy, etc.) please consult the Ionic Appflow support portal (https://ionic.zendesk.com/hc/en-us) -->
|
||||
|
||||
<!-- Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/ -->
|
||||
<!-- Please do not submit support requests or "How to" questions here. Instead, please use the Ionic Forum: https://forum.ionicframework.com/ -->
|
||||
|
||||
<!-- ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. -->
|
||||
|
||||
@@ -19,7 +19,8 @@ assignees: ''
|
||||
**Ionic version:**
|
||||
<!-- (For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1) -->
|
||||
<!-- (For Ionic 2.x & 3.x issues, please use https://github.com/ionic-team/ionic-v3) -->
|
||||
[x] **4.x**
|
||||
[ ] **4.x**
|
||||
[x] **5.x**
|
||||
|
||||
**Current behavior:**
|
||||
<!-- Describe how the bug manifests. -->
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/support_question.md
vendored
2
.github/ISSUE_TEMPLATE/support_question.md
vendored
@@ -8,4 +8,4 @@ assignees: ''
|
||||
|
||||
# Support Question
|
||||
|
||||
Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/
|
||||
Please do not submit support requests or "How to" questions here. Instead, please use the Ionic Forum: https://forum.ionicframework.com/
|
||||
|
||||
21
.github/ionic-issue-bot.yml
vendored
21
.github/ionic-issue-bot.yml
vendored
@@ -27,7 +27,10 @@ comment:
|
||||
is added to issues that need a code reproduction.
|
||||
|
||||
|
||||
Please provide a reproduction with the minimum amount of code required to reproduce the issue. Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.
|
||||
Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.
|
||||
|
||||
|
||||
If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.
|
||||
|
||||
|
||||
For a guide on how to create a good reproduction, see our [Contributing Guide](https://ionicframework.com/docs/contributing/how-to-contribute#creating-a-good-code-reproduction).
|
||||
@@ -130,22 +133,6 @@ noReproduction:
|
||||
lock: true
|
||||
dryRun: false
|
||||
|
||||
labelPullRequest:
|
||||
labels:
|
||||
- label: "package: angular"
|
||||
branch: master
|
||||
path: ^angular
|
||||
- label: "package: core"
|
||||
branch: master
|
||||
path: ^core
|
||||
- label: "package: react"
|
||||
branch: master
|
||||
path: ^react
|
||||
- label: "package: vue"
|
||||
branch: master
|
||||
path: ^vue
|
||||
dryRun: false
|
||||
|
||||
wrongRepo:
|
||||
repos:
|
||||
- label: "ionitron: capacitor"
|
||||
|
||||
21
.github/labeler.yml
vendored
Normal file
21
.github/labeler.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# This is used with the label workflow which
|
||||
# will triage pull requests and apply a label based on the
|
||||
# paths that are modified in the pull request.
|
||||
#
|
||||
# For more information, see:
|
||||
# https://github.com/actions/labeler
|
||||
|
||||
'package: core':
|
||||
- core/**/*
|
||||
|
||||
'package: angular':
|
||||
- angular/**/*
|
||||
- packages/angular-*/**/*
|
||||
|
||||
'package: react':
|
||||
- packages/react/**/*
|
||||
- packages/react-*/**/*
|
||||
|
||||
'package: vue':
|
||||
- packages/vue/**/*
|
||||
- packages/vue-*/**/*
|
||||
19
.github/workflows/label.yml
vendored
Normal file
19
.github/workflows/label.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# This workflow will triage pull requests and apply a label based on the
|
||||
# paths that are modified in the pull request.
|
||||
#
|
||||
# To use this workflow, you will need to set up a .github/labeler.yml
|
||||
# file with configuration. For more information, see:
|
||||
# https://github.com/actions/labeler
|
||||
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@main
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
sync-labels: true
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -58,6 +58,8 @@ prerender-static.html
|
||||
# stencil
|
||||
angular/css/
|
||||
packages/react/css/
|
||||
packages/vue/css/
|
||||
core/components/
|
||||
core/css/
|
||||
core/hydrate/
|
||||
core/loader/
|
||||
|
||||
@@ -14,7 +14,9 @@ const packages = [
|
||||
'angular',
|
||||
'packages/react',
|
||||
'packages/react-router',
|
||||
'packages/angular-server'
|
||||
'packages/angular-server',
|
||||
'packages/vue',
|
||||
'packages/vue-router'
|
||||
];
|
||||
|
||||
function readPkg(project) {
|
||||
@@ -131,7 +133,7 @@ function preparePackage(tasks, package, version, install) {
|
||||
title: `${pkg.name}: install npm dependencies`,
|
||||
task: async () => {
|
||||
await fs.remove(path.join(projectRoot, 'node_modules'));
|
||||
await execa('npm', ['i'], { cwd: projectRoot });
|
||||
await execa('npm', ['i', '--legacy-peer-deps'], { cwd: projectRoot });
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -141,13 +143,13 @@ function preparePackage(tasks, package, version, install) {
|
||||
if (package !== 'core') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link @ionic/core`,
|
||||
task: () => execa('npm', ['link', '@ionic/core'], { cwd: projectRoot })
|
||||
task: () => execa('npm', ['link', '@ionic/core', '--legacy-peer-deps'], { cwd: projectRoot })
|
||||
});
|
||||
|
||||
if (package === 'packages/react-router') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link @ionic/react`,
|
||||
task: () => execa('npm', ['link', '@ionic/react'], { cwd: projectRoot })
|
||||
task: () => execa('npm', ['link', '@ionic/react', '--legacy-peer-deps'], { cwd: projectRoot })
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -207,8 +209,15 @@ function prepareDevPackage(tasks, package, version) {
|
||||
if (package !== 'core') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link @ionic/core`,
|
||||
task: () => execa('npm', ['link', '@ionic/core'], { cwd: projectRoot })
|
||||
task: () => execa('npm', ['link', '@ionic/core', '--legacy-peer-deps'], { cwd: projectRoot })
|
||||
});
|
||||
|
||||
if (package === 'packages/react-router') {
|
||||
projectTasks.push({
|
||||
title: `${pkg.name}: npm link @ionic/react`,
|
||||
task: () => execa('npm', ['link', '@ionic/react', '--legacy-peer-deps'], { cwd: projectRoot })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
projectTasks.push({
|
||||
|
||||
@@ -78,6 +78,9 @@ async function setPackageVersionChanges(packages, version) {
|
||||
if (package !== 'core') {
|
||||
const pkg = common.readPkg(package);
|
||||
common.updateDependency(pkg, '@ionic/core', version);
|
||||
if(package === 'packages/react-router') {
|
||||
common.updateDependency(pkg, '@ionic/react', version);
|
||||
}
|
||||
common.writePkg(package, pkg);
|
||||
}
|
||||
const projectRoot = common.projectPath(package);
|
||||
|
||||
@@ -132,7 +132,7 @@ async function publishGithub(version, gitTag, changelog, npmTag) {
|
||||
|
||||
await octokit.repos.createRelease({
|
||||
owner: 'ionic-team',
|
||||
repo: 'ionic',
|
||||
repo: 'ionic-framework',
|
||||
target_commitish: branch,
|
||||
tag_name: gitTag,
|
||||
name: version,
|
||||
|
||||
@@ -7,7 +7,25 @@ const fs = require('fs');
|
||||
[
|
||||
// core
|
||||
{
|
||||
files: ['../core/dist/index.js', '../core/dist/ionic/index.esm.js']
|
||||
files: [
|
||||
'../core/css/core.css',
|
||||
'../core/css/core.css.map',
|
||||
'../core/css/normalize.css',
|
||||
'../core/css/normalize.css.map',
|
||||
'../core/components/index.js',
|
||||
'../core/components/index.d.ts',
|
||||
'../core/components/package.json',
|
||||
'../core/dist/index.js',
|
||||
'../core/dist/ionic/index.esm.js',
|
||||
]
|
||||
},
|
||||
// hydrate
|
||||
{
|
||||
files: [
|
||||
'../core/hydrate/index.js',
|
||||
'../core/hydrate/index.d.ts',
|
||||
'../core/hydrate/package.json'
|
||||
]
|
||||
},
|
||||
// angular
|
||||
{
|
||||
|
||||
501
CHANGELOG.md
501
CHANGELOG.md
@@ -1,3 +1,500 @@
|
||||
## [5.6.3](https://github.com/ionic-team/ionic/compare/v5.6.2...v5.6.3) (2021-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **react:** correctly show ion-back-button when going back ([#23069](https://github.com/ionic-team/ionic/issues/23069)) ([1c93b75](https://github.com/ionic-team/ionic/commit/1c93b75e397961e374620eb43bee3d6bb4389836)), closes [#22692](https://github.com/ionic-team/ionic/issues/22692)
|
||||
|
||||
|
||||
|
||||
## [5.6.2](https://github.com/ionic-team/ionic/compare/v5.6.1...v5.6.2) (2021-03-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **item:** detail icon now respects rtl mode ([#23081](https://github.com/ionic-team/ionic/issues/23081)) ([b04fb6e](https://github.com/ionic-team/ionic/commit/b04fb6e849bc9d6283271aaadc2b8aaae1f3961d)), closes [#23078](https://github.com/ionic-team/ionic/issues/23078)
|
||||
|
||||
|
||||
|
||||
## [5.6.1](https://github.com/ionic-team/ionic/compare/v5.6.0...v5.6.1) (2021-03-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **custom-elements:** overlays now present correctly when using custom elements build ([#23039](https://github.com/ionic-team/ionic/issues/23039)) ([e4bf052](https://github.com/ionic-team/ionic/commit/e4bf052794af9aac07f887013b9250d2a045eba3)), closes [#23029](https://github.com/ionic-team/ionic/issues/23029)
|
||||
* **item:** detail icon is no longer announced by screen readers ([#23055](https://github.com/ionic-team/ionic/issues/23055)) ([c877061](https://github.com/ionic-team/ionic/commit/c877061a328c6ab6fa7248b9880d0205c6c4f6c1)), closes [#23054](https://github.com/ionic-team/ionic/issues/23054)
|
||||
* **label:** properly float labels for non-input items ([#23060](https://github.com/ionic-team/ionic/issues/23060)) ([c8a3999](https://github.com/ionic-team/ionic/commit/c8a3999da109b1719777f2acb791ab5388d371ea))
|
||||
* **react:** only pass tab event props from IonTabs to IonTabBar if defined ([#23024](https://github.com/ionic-team/ionic/issues/23024)) ([f94e618](https://github.com/ionic-team/ionic/commit/f94e618a7b307b143eb39c061dc9e6b80e11f862)), closes [#23023](https://github.com/ionic-team/ionic/issues/23023)
|
||||
* **refresher:** progressEnd no longer errors when pulling quickly in MD native refresher ([#23056](https://github.com/ionic-team/ionic/issues/23056)) ([67617fb](https://github.com/ionic-team/ionic/commit/67617fbc0f7ec825f1fa4c6e7e2da70e3fcd2d66))
|
||||
* **virtual-scroll:** allow null in items property ([#23047](https://github.com/ionic-team/ionic/issues/23047)) ([2a253a1](https://github.com/ionic-team/ionic/commit/2a253a1d334ca2c6a478a5bc426e3115268a29af))
|
||||
* **vue:** passing params as props are correctly updated when switching pages ([#23049](https://github.com/ionic-team/ionic/issues/23049)) ([2f54bc1](https://github.com/ionic-team/ionic/commit/2f54bc14699656e6905452a4233d982f83d0001f)), closes [#23043](https://github.com/ionic-team/ionic/issues/23043)
|
||||
|
||||
|
||||
# [5.6.0 Argon](https://github.com/ionic-team/ionic/compare/v5.5.4...v5.6.0) (2021-03-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **all:** improve support for ids with special characters when getting label element ([#22680](https://github.com/ionic-team/ionic/issues/22680)) ([19d63f6](https://github.com/ionic-team/ionic/commit/19d63f62431ef9d8279f1726dd63fac2f0d4b46b)), closes [#22678](https://github.com/ionic-team/ionic/issues/22678)
|
||||
* **header:** collapsed toolbar is no longer incorrectly shown when using ion-refresher ([#22937](https://github.com/ionic-team/ionic/issues/22937)) ([5300dcc](https://github.com/ionic-team/ionic/commit/5300dcc693caf51a726f8c346cfc9a44474fd3d1)), closes [#22829](https://github.com/ionic-team/ionic/issues/22829)
|
||||
* **label:** only show placeholder with floating label when focused ([#22958](https://github.com/ionic-team/ionic/issues/22958)) ([9282aa6](https://github.com/ionic-team/ionic/commit/9282aa68715c088e9c8fcd915e78fb7ae91f551f)), closes [#17571](https://github.com/ionic-team/ionic/issues/17571)
|
||||
* **progress-bar:** use correct theme colors in dark mode ([#22965](https://github.com/ionic-team/ionic/issues/22965)) ([b6b2714](https://github.com/ionic-team/ionic/commit/b6b2714d70f71255315510c5e49708944875db72)), closes [#20098](https://github.com/ionic-team/ionic/issues/20098)
|
||||
* **radio-group:** pressing space no longer jumps screen to bottom of page ([#22892](https://github.com/ionic-team/ionic/issues/22892)) ([3a0465e](https://github.com/ionic-team/ionic/commit/3a0465e7d6f9e3cb01336a8bdbd7001e4ec34559)), closes [#22716](https://github.com/ionic-team/ionic/issues/22716)
|
||||
* **react:** IonRouterOutlet now respects animated={false} prop ([#22905](https://github.com/ionic-team/ionic/issues/22905)) ([da1b7a0](https://github.com/ionic-team/ionic/commit/da1b7a0e7a9a5e6a9120dc4d5459c97d8bca5390)), closes [#22903](https://github.com/ionic-team/ionic/issues/22903)
|
||||
* **react:** onIonTabsWillChange and onIonTabsDidChange event handlers are now properly bound to IonTabs ([#22233](https://github.com/ionic-team/ionic/issues/22233)) ([b064fde](https://github.com/ionic-team/ionic/commit/b064fdebef14018b77242b791914d5bb10863d39))
|
||||
* **react, vue:** navigating using ion-back-button now selects correct page ([#22974](https://github.com/ionic-team/ionic/issues/22974)) ([cd8ffd8](https://github.com/ionic-team/ionic/commit/cd8ffd82a03ee69ef4cbd7922544bfc39680def9)), closes [#22830](https://github.com/ionic-team/ionic/issues/22830)
|
||||
* **react, vue:** tab buttons no longer throw an error if href is undefined ([#22998](https://github.com/ionic-team/ionic/issues/22998)) ([943e3f6](https://github.com/ionic-team/ionic/commit/943e3f6ae37ecc56f21168f057dde77a05e4e144)), closes [#22997](https://github.com/ionic-team/ionic/issues/22997)
|
||||
* **refresher:** add correct dark mode styles ([#22639](https://github.com/ionic-team/ionic/issues/22639)) ([c05476b](https://github.com/ionic-team/ionic/commit/c05476b88e3e6884b4c490461c9c67dee3dca83d)), closes [#22637](https://github.com/ionic-team/ionic/issues/22637)
|
||||
* **vue:** correctly remove active state from tab button when navigating away from tab ([#23000](https://github.com/ionic-team/ionic/issues/23000)) ([a2763af](https://github.com/ionic-team/ionic/commit/a2763afe8e1fe1dc0decdbcb757a03bc5038045e)), closes [#22597](https://github.com/ionic-team/ionic/issues/22597)
|
||||
* **vue:** prevent race conditions when opening overlays ([#22883](https://github.com/ionic-team/ionic/issues/22883)) ([68a9b80](https://github.com/ionic-team/ionic/commit/68a9b800532f9c0b308a3b74ed18a7068a942301)), closes [#22880](https://github.com/ionic-team/ionic/issues/22880)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **custom-elements:** add experimental custom elements build ([#22863](https://github.com/ionic-team/ionic/issues/22863)) ([0de75af](https://github.com/ionic-team/ionic/commit/0de75afbefc521c1d76adcd587f77ba19c285a95))
|
||||
* **progress-bar:** add parts for more design customization ([#22938](https://github.com/ionic-team/ionic/issues/22938)) ([e256d3f](https://github.com/ionic-team/ionic/commit/e256d3f09fd6f231c4d9e1d0f0927612a591466b)), closes [#20062](https://github.com/ionic-team/ionic/issues/20062) [#21820](https://github.com/ionic-team/ionic/issues/21820)
|
||||
* **react:** add react hooks to control overlay components ([#22484](https://github.com/ionic-team/ionic/issues/22484)) ([b83e009](https://github.com/ionic-team/ionic/commit/b83e00934e794a936c9d3d23d7f94bbe89cedcd5))
|
||||
* **searchbar:** add showClearIcon property ([#22759](https://github.com/ionic-team/ionic/issues/22759)) ([215eb5d](https://github.com/ionic-team/ionic/commit/215eb5d4efbb9ade942dba1687469caf61da21e7)), closes [#22738](https://github.com/ionic-team/ionic/issues/22738)
|
||||
* **vue:** add composition API ionic lifecycle hooks ([#22970](https://github.com/ionic-team/ionic/issues/22970)) ([dd1c8db](https://github.com/ionic-team/ionic/commit/dd1c8dbf3b20fbd423f70c96846d9c366d90e7c5)), closes [#22769](https://github.com/ionic-team/ionic/issues/22769)
|
||||
|
||||
|
||||
|
||||
## [5.5.5](https://github.com/ionic-team/ionic/compare/v5.5.4...v5.5.5) (2021-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **vue:** account for event name changes in vue 3.0.6+ ([#22980](https://github.com/ionic-team/ionic/issues/22980)) ([7dd2e6d](https://github.com/ionic-team/ionic/commit/7dd2e6d287b47cca758e1d4a71928dd3dc9ac24d)), closes [#22977](https://github.com/ionic-team/ionic/issues/22977)
|
||||
|
||||
|
||||
|
||||
## [5.5.4](https://github.com/ionic-team/ionic/compare/v5.5.3...v5.5.4) (2021-02-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** update ngAdd schematic ([#22858](https://github.com/ionic-team/ionic/issues/22858)) ([487349f](https://github.com/ionic-team/ionic/commit/487349f02a41344db2478735d27bf79f2a1c99b3))
|
||||
* **app:** keyboard no longer hides when using contenteditable ([#22857](https://github.com/ionic-team/ionic/issues/22857)) ([b6b2d34](https://github.com/ionic-team/ionic/commit/b6b2d34fd446feb06cf0143946a014d19231a78e)), closes [#22856](https://github.com/ionic-team/ionic/issues/22856)
|
||||
* **ios**: scroll assist no longer prevents first click event from firing ([#22845](https://github.com/ionic-team/ionic/issues/22845)) ([f7d4c21](https://github.com/ionic-team/ionic/commit/f7d4c21b64e27f9b655bc1ab2522d6357dc6010f)), closes [#21871](https://github.com/ionic-team/ionic/issues/21871)
|
||||
* **select:** class on component now indicates when select is open ([#22846](https://github.com/ionic-team/ionic/issues/22846)) ([1a5accc](https://github.com/ionic-team/ionic/commit/1a5accc5f707f84063469c0bd3e5e153489f1e5d)), closes [#22801](https://github.com/ionic-team/ionic/issues/22801)
|
||||
* **vue:** ionChange events now propagate correctly ([#22872](https://github.com/ionic-team/ionic/issues/22872)) ([ff0f1da](https://github.com/ionic-team/ionic/commit/ff0f1da9f11915b48c4258af7c48c4513785f3fc)), closes [#22870](https://github.com/ionic-team/ionic/issues/22870)
|
||||
|
||||
|
||||
|
||||
## [5.5.3](https://github.com/ionic-team/ionic/compare/v5.5.2...v5.5.3) (2021-01-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **react:** do not unmount overlay inner component until overlay is dismissed ([#22813](https://github.com/ionic-team/ionic/issues/22813)) ([ab1fc8f](https://github.com/ionic-team/ionic/commit/ab1fc8f2311fd252146942c7a947ebc96efd054f)), closes [#22761](https://github.com/ionic-team/ionic/issues/22761)
|
||||
* **react:** adding dynamic class to ion-page no longer hides component ([#22666](https://github.com/ionic-team/ionic/issues/22666)) ([a01bdb8](https://github.com/ionic-team/ionic/commit/a01bdb8c8dfee760721eeb35a8b556954f3b5b13)), closes [#22631](https://github.com/ionic-team/ionic/issues/22631)
|
||||
* **react:** improve view matching logic ([#22569](https://github.com/ionic-team/ionic/issues/22569)) ([f891f66](https://github.com/ionic-team/ionic/commit/f891f667082d2deb5f1b5f0f27af46e46ed1ca0f))
|
||||
* **react, vue:** do not show back button when replacing to root page ([#22750](https://github.com/ionic-team/ionic/issues/22750)) ([9e9a372](https://github.com/ionic-team/ionic/commit/9e9a3724979e95f3df1a340be21d16d8664a013c)), closes [#22528](https://github.com/ionic-team/ionic/issues/22528)
|
||||
* **refresher:** correctly detect spinner when using native refresher ([#22800](https://github.com/ionic-team/ionic/issues/22800)) ([e2d8e5c](https://github.com/ionic-team/ionic/commit/e2d8e5c4dcf893ddd8aaa556c1dd8fcaf52411c9)), closes [#22706](https://github.com/ionic-team/ionic/issues/22706)
|
||||
* **title:** only add large title transition when using collapsible header ([#22762](https://github.com/ionic-team/ionic/issues/22762)) ([348c50b](https://github.com/ionic-team/ionic/commit/348c50b7ea5d4c74498c5d26e40c1c4fe923ee55)), closes [#22760](https://github.com/ionic-team/ionic/issues/22760)
|
||||
* **vue:** all ionic vue components can now use router link ([#22743](https://github.com/ionic-team/ionic/issues/22743)) ([3d6ac13](https://github.com/ionic-team/ionic/commit/3d6ac1382e23663a3d010fd253d3c6017d3923e4))
|
||||
* **vue:** correctly determine leaving view when transitioning to a new instance of a previous page ([#22655](https://github.com/ionic-team/ionic/issues/22655)) ([e3a05bf](https://github.com/ionic-team/ionic/commit/e3a05bfeb55d8eaa38aa08a37859aa4df6ffa2d4)), closes [#22654](https://github.com/ionic-team/ionic/issues/22654) [#22658](https://github.com/ionic-team/ionic/issues/22658)
|
||||
* **vue:** ensure v-model value is properly synced before ionChange event ([#22749](https://github.com/ionic-team/ionic/issues/22749)) ([e1d6627](https://github.com/ionic-team/ionic/commit/e1d6627bf0ef1f47f980db1573c6b2a3d16d7677)), closes [#22610](https://github.com/ionic-team/ionic/issues/22610)
|
||||
* **vue:** improve path matching with tabs, deprecated adding additional pages as children of tabs without a router outlet ([#22807](https://github.com/ionic-team/ionic/issues/22807)) ([2a3ce9a](https://github.com/ionic-team/ionic/commit/2a3ce9a74e85111a2f1f470b9d8bfe2cda793ca5)), closes [#22519](https://github.com/ionic-team/ionic/issues/22519)
|
||||
* **vue:** improve v-model binding sync between vue wrappers and web components ([#22745](https://github.com/ionic-team/ionic/issues/22745)) ([64719f4](https://github.com/ionic-team/ionic/commit/64719f49f979c0296a01827d3c02599a48ba93a6)), closes [#22731](https://github.com/ionic-team/ionic/issues/22731)
|
||||
* **vue:** output commonjs format for node environments ([#22766](https://github.com/ionic-team/ionic/issues/22766)) ([7ecae2e](https://github.com/ionic-team/ionic/commit/7ecae2e4cb5d0eebc6041a8a7a5acc156132c2e1))
|
||||
* **vue:** tab bar is now correctly hidden when keyboard is open ([#22687](https://github.com/ionic-team/ionic/issues/22687)) ([5c27dd8](https://github.com/ionic-team/ionic/commit/5c27dd8032d32ebb57c31e1f6c112dc513344b93))
|
||||
|
||||
|
||||
|
||||
## [5.5.2](https://github.com/ionic-team/ionic/compare/v5.5.1...v5.5.2) (2020-12-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **android:** setting hardwareBackButton: false in config now disables default webview behavior ([#22555](https://github.com/ionic-team/ionic/issues/22555)) ([dc9faa6](https://github.com/ionic-team/ionic/commit/dc9faa6a0fbebb64c83c107c79cfd486cc0c096a)), closes [#18237](https://github.com/ionic-team/ionic/issues/18237)
|
||||
* **button:** allow aria-label to be inherited on inner button ([#22632](https://github.com/ionic-team/ionic/issues/22632)) ([818e387](https://github.com/ionic-team/ionic/commit/818e387fe81ac7026fb374d8865116dadd433c87)), closes [#22629](https://github.com/ionic-team/ionic/issues/22629)
|
||||
* **react:** hardware back button now navigates correctly ([36939e1](https://github.com/ionic-team/ionic/commit/36939e10ae0b8ac9a9275ee06d8e0d345de7c64f))
|
||||
* **react:** setting a ref now allows other props to be passed in ([31f45cd](https://github.com/ionic-team/ionic/commit/31f45cdcc953b08749d9db08321fa5ec6cbe2532)), closes [#22609](https://github.com/ionic-team/ionic/issues/22609)
|
||||
* **refresher:** clean up old css if calling refresh method before native refresher is setup ([#22640](https://github.com/ionic-team/ionic/issues/22640)) ([8d5ed47](https://github.com/ionic-team/ionic/commit/8d5ed47a282f92a60a2c4126a673cc2a5733067e)), closes [#22636](https://github.com/ionic-team/ionic/issues/22636)
|
||||
* **refresher:** refresher correctly detects native refresher when shown asynchronously ([#22623](https://github.com/ionic-team/ionic/issues/22623)) ([5ed73cd](https://github.com/ionic-team/ionic/commit/5ed73cdf4d63eeee25ef28d9676fcaa4f8e07b47)), closes [#22616](https://github.com/ionic-team/ionic/issues/22616)
|
||||
* **vue:** adding non tab button elements inside ion-tab-bar no longer causes errors ([#22643](https://github.com/ionic-team/ionic/issues/22643)) ([61cf0c5](https://github.com/ionic-team/ionic/commit/61cf0c534e45ce09410be6bfb50bdc27b657d1bc)), closes [#22642](https://github.com/ionic-team/ionic/issues/22642)
|
||||
* **vue:** correctly handle navigation failures ([#22621](https://github.com/ionic-team/ionic/issues/22621)) ([216f51b](https://github.com/ionic-team/ionic/commit/216f51b12a8c4ae7b410f47ce3d350ea513b68a1)), closes [#22591](https://github.com/ionic-team/ionic/issues/22591)
|
||||
* **vue:** correctly remove old view when replacing route ([#22566](https://github.com/ionic-team/ionic/issues/22566)) ([4f4f31b](https://github.com/ionic-team/ionic/commit/4f4f31b65e48294c3130ff24ae00b1a2aa1f9d31)), closes [#22492](https://github.com/ionic-team/ionic/issues/22492)
|
||||
* **vue:** pass in correct route to props function ([#22605](https://github.com/ionic-team/ionic/issues/22605)) ([01afdc4](https://github.com/ionic-team/ionic/commit/01afdc42e5b1598d4d15cb51761bbb3eb5d13893)), closes [#22602](https://github.com/ionic-team/ionic/issues/22602)
|
||||
* **vue:** query strings are now correctly handled when navigating back ([#22615](https://github.com/ionic-team/ionic/issues/22615)) ([a94e2a8](https://github.com/ionic-team/ionic/commit/a94e2a87fb759e7b7daed2d0304c1199dbc7afd1)), closes [#22517](https://github.com/ionic-team/ionic/issues/22517)
|
||||
* **vue:** swipe back gesture is properly disabled when swipeBackEnabled config is false ([#22568](https://github.com/ionic-team/ionic/issues/22568)) ([9d04c12](https://github.com/ionic-team/ionic/commit/9d04c127e817676983940b034a4c7efc92fdfbc6)), closes [#22567](https://github.com/ionic-team/ionic/issues/22567)
|
||||
|
||||
### For Ionic Vue Developers
|
||||
|
||||
Vue Router 4 has been released! Be sure to update from the release candidate to the latest stable version of Vue Router.
|
||||
|
||||
For more information on the changes in Vue Router 4, see https://github.com/vuejs/vue-router-next/releases/tag/v4.0.0.
|
||||
|
||||
```
|
||||
npm install vue-router@4
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.5.1](https://github.com/ionic-team/ionic/compare/v5.5.0...v5.5.1) (2020-11-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **checkbox:** click handler now fires properly ([#22573](https://github.com/ionic-team/ionic/issues/22573)) ([0786835](https://github.com/ionic-team/ionic/commit/07868354aaf88deebf7472a5bf0f34d7c823de17)), closes [#22557](https://github.com/ionic-team/ionic/issues/22557)
|
||||
* **radio:** properly announce radios on screen readers and resolve axe errors ([#22507](https://github.com/ionic-team/ionic/issues/22507)) ([afcc46e](https://github.com/ionic-team/ionic/commit/afcc46e1cc4d7f6e9d1a50f8b367da4b1d0c3143))
|
||||
* **react:** eliminate use of deprecated `findDOMNode`, resolves [#20972](https://github.com/ionic-team/ionic/issues/20972) ([5275332](https://github.com/ionic-team/ionic/commit/5275332e43694f3ee8738a1726c0d202b16c3052))
|
||||
* **router:** navigation guards now fire when navigating to a page with params ([#22521](https://github.com/ionic-team/ionic/issues/22521)) ([1956f98](https://github.com/ionic-team/ionic/commit/1956f9896883dc4687488e5418e50ce0f6cbe6c9)), closes [#22516](https://github.com/ionic-team/ionic/issues/22516)
|
||||
* **select:** fix a11y issues with axe and screen readers ([#22494](https://github.com/ionic-team/ionic/issues/22494)) ([04b874e](https://github.com/ionic-team/ionic/commit/04b874e32a65588ca79eda9399ab7e9d86a3cb77)), closes [#21552](https://github.com/ionic-team/ionic/issues/21552) [#21548](https://github.com/ionic-team/ionic/issues/21548)
|
||||
* **select:** improvements for announcing placeholder and value on screenreaders ([#22556](https://github.com/ionic-team/ionic/issues/22556)) ([ea52db6](https://github.com/ionic-team/ionic/commit/ea52db66f05a185fed6b2e849734a7ffa1c6c6ea))
|
||||
* **vue:** onBeforeRouteLeave and onBeforeRouteUpdate hooks now fire properly ([#22542](https://github.com/ionic-team/ionic/issues/22542)) ([8002114](https://github.com/ionic-team/ionic/commit/8002114e720361e60d7a7fe2d15ab88b49a72e1b)), closes [#22540](https://github.com/ionic-team/ionic/issues/22540)
|
||||
* **vue:** tabs now correctly fire lifecycle events ([#22479](https://github.com/ionic-team/ionic/issues/22479)) ([cdc2fb6](https://github.com/ionic-team/ionic/commit/cdc2fb652fe5aa149eaa751a77fb506ac1f64195)), closes [#22466](https://github.com/ionic-team/ionic/issues/22466)
|
||||
* **vue:** unit testing a routerLink-capable component no longer warns of missing router dependency ([#22532](https://github.com/ionic-team/ionic/issues/22532)) ([4e23aad](https://github.com/ionic-team/ionic/commit/4e23aad3d911188e4a2706545463a81332c00ce9)), closes [#22506](https://github.com/ionic-team/ionic/issues/22506)
|
||||
|
||||
### For Ionic Vue Developers
|
||||
|
||||
When updating to Ionic Vue v5.5.1 make sure you are on the latest version of `vue-router@next` to take advantage of the bug fixes in this release:
|
||||
|
||||
```
|
||||
npm install vue-router@next
|
||||
```
|
||||
|
||||
|
||||
|
||||
# [5.5.0 Chlorine](https://github.com/ionic-team/ionic/compare/v5.4.4...v5.5.0) (2020-11-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **backdrop:** nvda no longer incorrectly announces backdrop ([#22481](https://github.com/ionic-team/ionic/issues/22481)) ([2d878fc](https://github.com/ionic-team/ionic/commit/2d878fc4f6c7a710dbfb722e188e3e402e1672f9)), closes [#22102](https://github.com/ionic-team/ionic/issues/22102)
|
||||
* **checkbox:** use a native input to fix a11y issues with axe and screen readers ([#22402](https://github.com/ionic-team/ionic/issues/22402)) ([7214a84](https://github.com/ionic-team/ionic/commit/7214a8401b709e1353155304cf6e9f97b2b4d294)), closes [#21644](https://github.com/ionic-team/ionic/issues/21644) [#20517](https://github.com/ionic-team/ionic/issues/20517) [#17796](https://github.com/ionic-team/ionic/issues/17796)
|
||||
* **input:** title attribute is now automatically inherited ([#22493](https://github.com/ionic-team/ionic/issues/22493)) ([abad12f](https://github.com/ionic-team/ionic/commit/abad12fbdb1378066282fe8e9b7761747951b685)), closes [#22055](https://github.com/ionic-team/ionic/issues/22055)
|
||||
* **refresher:** ios native refresher now works in side menu ([#22449](https://github.com/ionic-team/ionic/issues/22449)) ([a4a6453](https://github.com/ionic-team/ionic/commit/a4a64530ff083b83187b293dfdacb0fa45ad9f51))
|
||||
* **refresher:** md native refresher now works in side menu ([#22446](https://github.com/ionic-team/ionic/issues/22446)) ([6b817f2](https://github.com/ionic-team/ionic/commit/6b817f26b08d01d8367d16308db775b6192e7628)), closes [#20832](https://github.com/ionic-team/ionic/issues/20832)
|
||||
* **toggle:** use a native input to fix a11y issues with axe and screen readers ([#22477](https://github.com/ionic-team/ionic/issues/22477)) ([813611a](https://github.com/ionic-team/ionic/commit/813611a61b664c9827760ccaa889d0e2fcae7d94)), closes [#22011](https://github.com/ionic-team/ionic/issues/22011) [#21552](https://github.com/ionic-team/ionic/issues/21552)
|
||||
* **vue:** correctly pass route props to components ([#22476](https://github.com/ionic-team/ionic/issues/22476)) ([0956f8b](https://github.com/ionic-team/ionic/commit/0956f8bc5588836996c8c74f98166c347414a312)), closes [#22472](https://github.com/ionic-team/ionic/issues/22472)
|
||||
* **vue:** tab bar now works with slot="top" ([#22461](https://github.com/ionic-team/ionic/issues/22461)) ([e17c822](https://github.com/ionic-team/ionic/commit/e17c822bfbc2a876226738b77a4c95c02e0b5953)), closes [#22456](https://github.com/ionic-team/ionic/issues/22456)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **chip:** add disabled property ([#20658](https://github.com/ionic-team/ionic/issues/20658)) ([0a0cbd8](https://github.com/ionic-team/ionic/commit/0a0cbd8f2a505ad2b3d8afb60cb1e940ced52e0d)), closes [#19510](https://github.com/ionic-team/ionic/issues/19510)
|
||||
* **segment:** add swipeGesture property to allow for disabling of the swipe gesture ([#22087](https://github.com/ionic-team/ionic/issues/22087)) ([65bc995](https://github.com/ionic-team/ionic/commit/65bc99577c44cce653dafd9937c4d8f9c45fff61)), closes [#22048](https://github.com/ionic-team/ionic/issues/22048)
|
||||
* **vue:** composition api lifecycle methods ([#22241](https://github.com/ionic-team/ionic/issues/22241)) ([f5b0299](https://github.com/ionic-team/ionic/commit/f5b0299729c2c639e432612e62fb7eaa189ca969))
|
||||
* **vue:** vetur support ([#22403](https://github.com/ionic-team/ionic/issues/22403)) ([e76f79d](https://github.com/ionic-team/ionic/commit/e76f79d0548c97edd193808f5e0a19889cffae5b))
|
||||
* **vue:** web-types support ([#22428](https://github.com/ionic-team/ionic/issues/22428)) ([639314a](https://github.com/ionic-team/ionic/commit/639314ab218b65a9a2de6040417b0e1b363e47ef)), closes [#19522](https://github.com/ionic-team/ionic/issues/19522)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **ios:** move content to stacking context while preserving position: fixed behavior ([#22489](https://github.com/ionic-team/ionic/issues/22489)) ([d77a9d5](https://github.com/ionic-team/ionic/commit/d77a9d57ec02c69df43ec2a286eea674a85cae36)), closes [#22473](https://github.com/ionic-team/ionic/issues/22473)
|
||||
|
||||
|
||||
|
||||
## [5.4.4](https://github.com/ionic-team/ionic/compare/v5.4.3...v5.4.4) (2020-11-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** add missing es5 output ([228d349](https://github.com/ionic-team/ionic/commit/228d349c6e29b62cbfee5d5502883682cfa5032f))
|
||||
|
||||
|
||||
|
||||
## [5.4.3](https://github.com/ionic-team/ionic/compare/v5.4.2...v5.4.3) (2020-11-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **all** add missing vendor prefixes to css ([0989ea5](https://github.com/ionic-team/ionic/commit/0989ea5ac897f528e8fce5434861ca080b9b4a56))
|
||||
|
||||
|
||||
|
||||
## [5.4.2](https://github.com/ionic-team/ionic/compare/v5.4.1...v5.4.2) (2020-11-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **alert:** correctly position alert when keyboard is open ([#22425](https://github.com/ionic-team/ionic/issues/22425)) ([9752cd6](https://github.com/ionic-team/ionic/commit/9752cd6371bc4a720e45871161e389e4a9ad8e8f))
|
||||
* **ios:** contenteditable elements are now selectable on iOS ([#22404](https://github.com/ionic-team/ionic/issues/22404)) ([023fb18](https://github.com/ionic-team/ionic/commit/023fb1841259a61b361066ca369aeffd488efa3f)), closes [#18368](https://github.com/ionic-team/ionic/issues/18368)
|
||||
* **item:** only add click event listener to items with inputs ([#22352](https://github.com/ionic-team/ionic/issues/22352)) ([9659ad6](https://github.com/ionic-team/ionic/commit/9659ad63349d5123ca2bd2548a43e37d5ee817e7)), closes [#22011](https://github.com/ionic-team/ionic/issues/22011)
|
||||
* **range:** gesture is now properly re-created on connectedCallback ([#22407](https://github.com/ionic-team/ionic/issues/22407)) ([2fea36f](https://github.com/ionic-team/ionic/commit/2fea36fc98f772443a6560a9491f2f0e574366d1)), closes [#22335](https://github.com/ionic-team/ionic/issues/22335)
|
||||
* **refresher:** work properly in modal by waiting for content to be ready ([#22390](https://github.com/ionic-team/ionic/issues/22390)) ([91d0414](https://github.com/ionic-team/ionic/commit/91d041485cb3565fa81fea24c1811e48108f277a)), closes [#22256](https://github.com/ionic-team/ionic/issues/22256)
|
||||
* **segment-button:** color property is now reactive if previously undefined ([#22405](https://github.com/ionic-team/ionic/issues/22405)) ([04161c9](https://github.com/ionic-team/ionic/commit/04161c9512ed8e965c93698d7f5501a21485052f)), closes [#20831](https://github.com/ionic-team/ionic/issues/20831)
|
||||
* **vue:** correctly switch tabs after going back ([#22309](https://github.com/ionic-team/ionic/issues/22309)) ([daf6a92](https://github.com/ionic-team/ionic/commit/daf6a92127d36c20f3445f83bd7bd3e739bb1b27)), closes [#22307](https://github.com/ionic-team/ionic/issues/22307)
|
||||
* **vue:** ensure view is updated correctly when replacing a route outside of a nav guard ([#22429](https://github.com/ionic-team/ionic/issues/22429)) ([5a4d0c0](https://github.com/ionic-team/ionic/commit/5a4d0c0217ce93f98364bdd4d8d163679f82a6b3)), closes [#22412](https://github.com/ionic-team/ionic/issues/22412)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **ios:** move content to stacking context to improve scrolling performance on iOS devices ([#22180](https://github.com/ionic-team/ionic/issues/22180)) ([9f44966](https://github.com/ionic-team/ionic/commit/9f44966d8572a27d8296b38ae4f3e689c76c2e44))
|
||||
|
||||
|
||||
|
||||
## [5.4.1](https://github.com/ionic-team/ionic/compare/v5.4.0...v5.4.1) (2020-10-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **select:** properly align label with select in item in MD mode ([#22330](https://github.com/ionic-team/ionic/issues/22330)) ([1a2e532](https://github.com/ionic-team/ionic/commit/1a2e5322fb7ac0dd6bd3d0705b8e32f9d3649bfc)), closes [#19887](https://github.com/ionic-team/ionic/issues/19887)
|
||||
* **vue:** going back with query params now goes to correct view ([#22350](https://github.com/ionic-team/ionic/issues/22350)) ([561a4ac](https://github.com/ionic-team/ionic/commit/561a4ac535432873860c3d0a4ac60481929d9089)), closes [#22324](https://github.com/ionic-team/ionic/issues/22324)
|
||||
* **vue:** improve compatibility with route guards ([#22371](https://github.com/ionic-team/ionic/issues/22371)) ([31f9bc8](https://github.com/ionic-team/ionic/commit/31f9bc81d6d0fa81f9abe20172bb606651a2d75d)), closes [#22344](https://github.com/ionic-team/ionic/issues/22344)
|
||||
* **vue:** improve handling of parameterized urls ([#22360](https://github.com/ionic-team/ionic/issues/22360)) ([6fad0fe](https://github.com/ionic-team/ionic/commit/6fad0fe42814cde1126e6df264b99c069849c87a)), closes [#22359](https://github.com/ionic-team/ionic/issues/22359)
|
||||
* **vue:** lifecycle events are now fired in component context ([#22348](https://github.com/ionic-team/ionic/issues/22348)) ([bcef804](https://github.com/ionic-team/ionic/commit/bcef804deac4dea27def475460aff4cdf0d7d2fc)), closes [#22338](https://github.com/ionic-team/ionic/issues/22338)
|
||||
|
||||
|
||||
|
||||
# [5.4.0 Sulfur](https://github.com/ionic-team/ionic/compare/v5.3.0...v5.4.0) (2020-10-15)
|
||||
|
||||
> This is the first stable release of Ionic Vue.
|
||||
|
||||
Enjoy the Vue! :tada:
|
||||
|
||||
### New to Ionic Vue?
|
||||
|
||||
Check out our [Quickstart Guide](https://ionicframework.com/docs/vue/quickstart) to get up and running. Then be sure to check out our [Building Your First App Guide](https://ionicframework.com/docs/vue/your-first-app) to learn how build a cross platform Ionic Vue application from start to finish!
|
||||
|
||||
|
||||
|
||||
# [5.4.0-rc.3](https://github.com/ionic-team/ionic/compare/v5.4.0-rc.2...v5.4.0-rc.3) (2020-10-14)
|
||||
|
||||
> This version is dedicated to our upcoming Ionic Vue release.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **vue:** ion-page component is now properly shown with HMR ([#22319](https://github.com/ionic-team/ionic/issues/22319)) ([c5ab562](https://github.com/ionic-team/ionic/commit/c5ab562eaa098717407e6b3e8139abd2112246a2))
|
||||
|
||||
### Upgrade Steps
|
||||
|
||||
```
|
||||
npm install @ionic/vue@5.4.0-rc.3 @ionic/vue-router@5.4.0-rc.3 --save-exact
|
||||
```
|
||||
|
||||
### New to Ionic Vue?
|
||||
|
||||
Check out our [Quickstart Guide](https://ionicframework.com/docs/vue/quickstart) to get up and running. Then be sure to check out our [Building Your First App Guide](https://ionicframework.com/docs/vue/your-first-app) to learn how build a cross platform Ionic Vue application from start to finish!
|
||||
|
||||
|
||||
|
||||
# [5.4.0-rc.2](https://github.com/ionic-team/ionic/compare/v5.4.0-rc.1...v5.4.0-rc.2) (2020-10-13)
|
||||
|
||||
> This version is dedicated to our upcoming Ionic Vue release.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **vue:** do not hide page content when using ion-page in non-routing contexts ([#22302](https://github.com/ionic-team/ionic/issues/22302)) ([fff82d0](https://github.com/ionic-team/ionic/commit/fff82d0bdcd850e7c70947b39d554e88c4cdfd1e)), closes [#22300](https://github.com/ionic-team/ionic/issues/22300)
|
||||
* **vue:** going back from tabs page to a non-tabs page now selects correct page ([#22275](https://github.com/ionic-team/ionic/issues/22275)) ([b06ae16](https://github.com/ionic-team/ionic/commit/b06ae165912cbab811fe4a3c35b4e2b3fe0b425b)), closes [#22258](https://github.com/ionic-team/ionic/issues/22258)
|
||||
* **vue:** improve swipe to go back reliability ([#22288](https://github.com/ionic-team/ionic/issues/22288)) ([c74fd41](https://github.com/ionic-team/ionic/commit/c74fd4147b57e6b11c22dffdf6355568a763f30a)), closes [#22237](https://github.com/ionic-team/ionic/issues/22237)
|
||||
* **vue:** modal, popover, and nav are now created within application context ([#22282](https://github.com/ionic-team/ionic/issues/22282)) ([6026c65](https://github.com/ionic-team/ionic/commit/6026c65b1ae80af0f8604e7a3bcb220153267955)), closes [#22079](https://github.com/ionic-team/ionic/issues/22079)
|
||||
* **vue:** pages now render in correct outlet when using multiple nested outlets ([#22301](https://github.com/ionic-team/ionic/issues/22301)) ([52f655c](https://github.com/ionic-team/ionic/commit/52f655c9d40988cac36f88c88f24195b3f64c431)), closes [#22286](https://github.com/ionic-team/ionic/issues/22286)
|
||||
|
||||
### Upgrade Steps
|
||||
|
||||
```
|
||||
npm install @ionic/vue@5.4.0-rc.2 @ionic/vue-router@5.4.0-rc.2 --save-exact
|
||||
```
|
||||
|
||||
### New to Ionic Vue?
|
||||
|
||||
Check out our [Quickstart Guide](https://ionicframework.com/docs/vue/quickstart) to get up and running. Then be sure to check out our [Building Your First App Guide](https://ionicframework.com/docs/vue/your-first-app) to learn how build a cross platform Ionic Vue application from start to finish!
|
||||
|
||||
|
||||
|
||||
# [5.4.0-rc.1](https://github.com/ionic-team/ionic/compare/v5.3.5...v5.4.0-rc.1) (2020-10-08)
|
||||
|
||||
> This version is dedicated to our upcoming Ionic Vue release.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **vue:** correctly handle query params ([#22253](https://github.com/ionic-team/ionic/issues/22253)) ([6849dd3](https://github.com/ionic-team/ionic/commit/6849dd3483fb90aac1ff19834390a652c59a74de)), closes [#22229](https://github.com/ionic-team/ionic/issues/22229)
|
||||
* **vue:** correctly show ion-back-button when going back ([#22260](https://github.com/ionic-team/ionic/issues/22260)) ([39d2530](https://github.com/ionic-team/ionic/commit/39d2530427b1cd86975fc95ab2c8da9f4b0b27b3)), closes [#22217](https://github.com/ionic-team/ionic/issues/22217)
|
||||
* **vue:** hide layout shift on ion-page components ([#22254](https://github.com/ionic-team/ionic/issues/22254)) ([2bad1bb](https://github.com/ionic-team/ionic/commit/2bad1bb82e0fa3fe9e3db54403565d210f636120)), closes [#22052](https://github.com/ionic-team/ionic/issues/22052)
|
||||
* **vue:** ion-tab-bar no longer throws undefined error when re-creating tabs ([#22261](https://github.com/ionic-team/ionic/issues/22261)) ([d746561](https://github.com/ionic-team/ionic/commit/d746561ea29e61db2cfb55d2765b5548fd8b5a78)), closes [#22255](https://github.com/ionic-team/ionic/issues/22255)
|
||||
|
||||
### Upgrade Steps
|
||||
|
||||
```
|
||||
npm install @ionic/vue@5.4.0-rc.1 @ionic/vue-router@5.4.0-rc.1 --save-exact
|
||||
```
|
||||
|
||||
### New to Ionic Vue?
|
||||
|
||||
Check out our [Quickstart Guide](https://ionicframework.com/docs/vue/quickstart) to get up and running. Then be sure to check out our [Building Your First App Guide](https://ionicframework.com/docs/vue/your-first-app) to learn how build a cross platform Ionic Vue application from start to finish!
|
||||
|
||||
|
||||
|
||||
## [5.3.5](https://github.com/ionic-team/ionic/compare/v5.3.4...v5.3.5) (2020-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** allow any element type to use the "icon-only" slot ([#22168](https://github.com/ionic-team/ionic/issues/22168)) ([c454c84](https://github.com/ionic-team/ionic/commit/c454c84ef46322143467600334a0263d4e7df6cb))
|
||||
* **datetime:** do not set ampm when the column doesn't exist ([#22220](https://github.com/ionic-team/ionic/issues/22220)) ([18fb885](https://github.com/ionic-team/ionic/commit/18fb8855e0c45fe65843b33811812c51c74de90f)), closes [#22149](https://github.com/ionic-team/ionic/issues/22149)
|
||||
* **datetime:** remove the automatic switching from am to pm ([#22207](https://github.com/ionic-team/ionic/issues/22207)) ([f81d18c](https://github.com/ionic-team/ionic/commit/f81d18c6f9f1bce056afda1cac4cf6d6ace0a7ca)), closes [#18924](https://github.com/ionic-team/ionic/issues/18924) [#22171](https://github.com/ionic-team/ionic/issues/22171) [#22199](https://github.com/ionic-team/ionic/issues/22199)
|
||||
* **item:** properly align datetime and select with fixed or no labels ([#22221](https://github.com/ionic-team/ionic/issues/22221)) ([f42c688](https://github.com/ionic-team/ionic/commit/f42c688f4630e3dc5d10b947e7f2bee9d5967d8c)), closes [#18773](https://github.com/ionic-team/ionic/issues/18773) [#18761](https://github.com/ionic-team/ionic/issues/18761) [#18779](https://github.com/ionic-team/ionic/issues/18779)
|
||||
* **label:** keep color when focused on a floating or stacked label ([#18576](https://github.com/ionic-team/ionic/issues/18576)) ([992580a](https://github.com/ionic-team/ionic/commit/992580a3830321bdf9591681ebe38e823205389d)), closes [#18531](https://github.com/ionic-team/ionic/issues/18531)
|
||||
* **select:** do not close popover or set value when switching with arrow keys ([#22210](https://github.com/ionic-team/ionic/issues/22210)) ([1878c8e](https://github.com/ionic-team/ionic/commit/1878c8e7e01c02f06bdc5f1562af0d45531539cf)), closes [#22179](https://github.com/ionic-team/ionic/issues/22179)
|
||||
|
||||
|
||||
|
||||
## [5.3.4](https://github.com/ionic-team/ionic/compare/v5.3.3...v5.3.4) (2020-09-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **alert:** follow accessibility guidelines outlined by wai-aria ([#22159](https://github.com/ionic-team/ionic/issues/22159)) ([e9b2cc8](https://github.com/ionic-team/ionic/commit/e9b2cc8453f5e1c45d44397df738f60ea5b32efd)), closes [#21744](https://github.com/ionic-team/ionic/issues/21744)
|
||||
* **overlays:** return focus to presenting element after dismissal ([#22167](https://github.com/ionic-team/ionic/issues/22167)) ([cc45ad8](https://github.com/ionic-team/ionic/commit/cc45ad815c002c5d890f2e105c546b4c3b3a58c0)), closes [#21768](https://github.com/ionic-team/ionic/issues/21768)
|
||||
* **picker-column:** add cancelable check to avoid intervention error in chrome ([#22140](https://github.com/ionic-team/ionic/issues/22140)) ([a24a041](https://github.com/ionic-team/ionic/commit/a24a041064fd9ce6ca161d3522083d50e585e9dd)), closes [#22137](https://github.com/ionic-team/ionic/issues/22137)
|
||||
* **radio:** follow accessibility guidelines outlined by wai-aria ([#22113](https://github.com/ionic-team/ionic/issues/22113)) ([ea0e049](https://github.com/ionic-team/ionic/commit/ea0e0499e24865faad3d11f50f7037645f6cdcc8)), closes [#21743](https://github.com/ionic-team/ionic/issues/21743)
|
||||
* **reorder:** allow click event propagation when reorder group is disabled ([#21947](https://github.com/ionic-team/ionic/issues/21947)) ([baafe08](https://github.com/ionic-team/ionic/commit/baafe08927b7b858170496605781e6fa682e0147)), closes [#21017](https://github.com/ionic-team/ionic/issues/21017)
|
||||
* **segment:** do not allow text selection on desktop ([#22158](https://github.com/ionic-team/ionic/issues/22158)) ([1526bdf](https://github.com/ionic-team/ionic/commit/1526bdfb492c1fa8d71f8a1af8cd97abd9e62642))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **segment:** improve scrolling performance on ios when using segment ([#22110](https://github.com/ionic-team/ionic/issues/22110)) ([68afc49](https://github.com/ionic-team/ionic/commit/68afc49e9ed27acffb0b765b7be6b03e8574850d)), closes [#22095](https://github.com/ionic-team/ionic/issues/22095)
|
||||
|
||||
|
||||
|
||||
## [5.3.3](https://github.com/ionic-team/ionic/compare/v5.3.2...v5.3.3) (2020-09-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** do not reset to am when changing hour and pm is set ([#21997](https://github.com/ionic-team/ionic/issues/21997)) ([8b85fe0](https://github.com/ionic-team/ionic/commit/8b85fe0d9eea39adfdcf790bf00d8ef91d5edbe7)), closes [#19175](https://github.com/ionic-team/ionic/issues/19175) [#19260](https://github.com/ionic-team/ionic/issues/19260) [#20026](https://github.com/ionic-team/ionic/issues/20026) [#16630](https://github.com/ionic-team/ionic/issues/16630)
|
||||
* **input:** only focus the first input / textarea when clicking on the parent item ([#22049](https://github.com/ionic-team/ionic/issues/22049)) ([99f2532](https://github.com/ionic-team/ionic/commit/99f2532ee174da79e2b6a462cfa124673edc1170)), closes [#22037](https://github.com/ionic-team/ionic/issues/22037) [#22032](https://github.com/ionic-team/ionic/issues/22032)
|
||||
* **react:** Keep a hold of previous routes when doing a redirect, closes [#22053](https://github.com/ionic-team/ionic/issues/22053) ([74af3cb](https://github.com/ionic-team/ionic/commit/74af3cb50b089a6bd60d515158e03b18b86455b8))
|
||||
* **react:** redirect routes should unmount leaving component, fixes [#22022](https://github.com/ionic-team/ionic/issues/22022) ([#22029](https://github.com/ionic-team/ionic/issues/22029)) ([b11e06c](https://github.com/ionic-team/ionic/commit/b11e06cec1d3c28bab9f29185fe2c3a2975b092f))
|
||||
* **textarea:** do not generate duplicate IDs between ion-input and ion-textarea ([#22074](https://github.com/ionic-team/ionic/issues/22074)) ([c72c7ff](https://github.com/ionic-team/ionic/commit/c72c7ffa983af8885dd93f9adfcb3f2af232d2d9)), closes [#21542](https://github.com/ionic-team/ionic/issues/21542)
|
||||
|
||||
|
||||
|
||||
## [5.3.2](https://github.com/ionic-team/ionic/compare/v5.3.1...v5.3.2) (2020-08-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **input:** improve reliability of scroll assist when accessory bar is enabled ([#21936](https://github.com/ionic-team/ionic/issues/21936)) ([22477fb](https://github.com/ionic-team/ionic/commit/22477fb9bf7c0637aa5c8d0aab34c8ccc521b0b9)), closes [#21912](https://github.com/ionic-team/ionic/issues/21912)
|
||||
* **input:** properly focus the input when clicking the item padding in WebKit ([#21930](https://github.com/ionic-team/ionic/issues/21930)) ([e4964ff](https://github.com/ionic-team/ionic/commit/e4964ff77b317c92b201cf7c265787b55bdde4d4)), closes [#21509](https://github.com/ionic-team/ionic/issues/21509)
|
||||
* **input:** remain focused in the input after pressing the clear button ([#21985](https://github.com/ionic-team/ionic/issues/21985)) ([6878fb9](https://github.com/ionic-team/ionic/commit/6878fb9eb99c17908f5630019efaa762b5b006e0)), closes [#21549](https://github.com/ionic-team/ionic/issues/21549)
|
||||
* **label:** use translateY so input caret shows up due to webkit issue ([#21949](https://github.com/ionic-team/ionic/issues/21949)) ([00eac33](https://github.com/ionic-team/ionic/commit/00eac33053f49dbebf22ef95fddcb66570ed117a)), closes [#21943](https://github.com/ionic-team/ionic/issues/21943)
|
||||
* **overlays:** prevent focus from being stolen when presenting another overlay from within a modal ([#21856](https://github.com/ionic-team/ionic/issues/21856)) ([5c177d7](https://github.com/ionic-team/ionic/commit/5c177d756f7755e766d5b619d49825c4799aee47)), closes [#21840](https://github.com/ionic-team/ionic/issues/21840)
|
||||
* **range:** properly display stacked labels in an item with a range ([#21944](https://github.com/ionic-team/ionic/issues/21944)) ([9f4b01e](https://github.com/ionic-team/ionic/commit/9f4b01e17fd2f5e742d32bc9e080b6b394c43d37)), closes [#21625](https://github.com/ionic-team/ionic/issues/21625)
|
||||
* **react:** export correct animation types ([#21950](https://github.com/ionic-team/ionic/issues/21950)) ([36e4bf7](https://github.com/ionic-team/ionic/commit/36e4bf7dd76e396f910d28445566b5503cc84c8c))
|
||||
* **react:** removed exporting of ionRenderToString to decrease bundle size, closes [#21917](https://github.com/ionic-team/ionic/issues/21917) ([#21928](https://github.com/ionic-team/ionic/issues/21928)) ([434befe](https://github.com/ionic-team/ionic/commit/434befea5f31aa599ee5b1b7edf29238912c23d9))
|
||||
* **react:** setting active tab properly on mount, closes [#21830](https://github.com/ionic-team/ionic/issues/21830) ([#21833](https://github.com/ionic-team/ionic/issues/21833)) ([f58424f](https://github.com/ionic-team/ionic/commit/f58424f62596b9eb82bebb8e07c211e1725c025a))
|
||||
* **react:** fix tab currentHref when changing tabs, closes [#21834](https://github.com/ionic-team/ionic/issues/21834) ([#21835](https://github.com/ionic-team/ionic/issues/21835)) ([74468ab](https://github.com/ionic-team/ionic/commit/74468ab7972b174ba85bf239306c27080f253a4a))
|
||||
|
||||
|
||||
|
||||
## [5.3.1](https://github.com/ionic-team/ionic/compare/v5.3.0...v5.3.1) (2020-07-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **react:** properly extend HTMLElement for tabs ([bfddb17](https://github.com/ionic-team/ionic/commit/bfddb170659224d0f826762744dfe44a85813d36)), closes [#21803](https://github.com/ionic-team/ionic/issues/21803)
|
||||
|
||||
|
||||
|
||||
# [5.3.0 Phosphorus](https://github.com/ionic-team/ionic/compare/v5.2.3...v5.3.0) (2020-07-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** per-page animations now work with swipe to go back ([#21706](https://github.com/ionic-team/ionic/issues/21706)) ([2664587](https://github.com/ionic-team/ionic/commit/2664587749e45100a04f70796733de162b26cdf7)), closes [#21692](https://github.com/ionic-team/ionic/issues/21692)
|
||||
* **datetime:** remove unneeded combobox role ([#21708](https://github.com/ionic-team/ionic/issues/21708)) ([f00ad8a](https://github.com/ionic-team/ionic/commit/f00ad8a8357ccd7fe85631dad0c841f2d4c72487))
|
||||
* **input:** clear button can now be tabbed to ([#21633](https://github.com/ionic-team/ionic/issues/21633)) ([1dcd9de](https://github.com/ionic-team/ionic/commit/1dcd9de50ae16bfa102e98120a022de5b0287baa))
|
||||
* **ios:** improve scroll assist reliability on password inputs ([#21703](https://github.com/ionic-team/ionic/issues/21703)) ([3cbf9e7](https://github.com/ionic-team/ionic/commit/3cbf9e7c4c225d6b02237d8ea8f16fb924ba360e)), closes [#21688](https://github.com/ionic-team/ionic/issues/21688)
|
||||
* **keyboard:** keyboard events now consistently fire on android ([#21741](https://github.com/ionic-team/ionic/issues/21741)) ([020f3cc](https://github.com/ionic-team/ionic/commit/020f3cc56cb6dac23dd8766a3802422500b510e2)), closes [#21734](https://github.com/ionic-team/ionic/issues/21734)
|
||||
* **nav:** insertPages method correctly inserts multiple pages with props ([#21725](https://github.com/ionic-team/ionic/issues/21725)) ([eb592b8](https://github.com/ionic-team/ionic/commit/eb592b8917b8a7412d8c346f41b47d3b79002b95)), closes [#21724](https://github.com/ionic-team/ionic/issues/21724)
|
||||
* **overlays:** trap focus inside overlay components except toast ([#21716](https://github.com/ionic-team/ionic/issues/21716)) ([fff4aec](https://github.com/ionic-team/ionic/commit/fff4aec6cfbd48566594a05f4af57dd0578977a8)), closes [#21647](https://github.com/ionic-team/ionic/issues/21647)
|
||||
* **segment-button:** allow min-width to be overridden ([#21722](https://github.com/ionic-team/ionic/issues/21722)) ([88f1828](https://github.com/ionic-team/ionic/commit/88f1828bd8f6b9a1c1f3dcb220d93067bed7f404)), closes [#21105](https://github.com/ionic-team/ionic/issues/21105)
|
||||
* **title:** allow overriding of large title transform-origin ([#21770](https://github.com/ionic-team/ionic/issues/21770)) ([dbe6853](https://github.com/ionic-team/ionic/commit/dbe6853884bd76c3d8e229cd58e1571d9b3a7249)), closes [#21761](https://github.com/ionic-team/ionic/issues/21761)
|
||||
* **virtual-scroll:** properly calculate top offset when nested ([#21581](https://github.com/ionic-team/ionic/issues/21581)) ([d297ecb](https://github.com/ionic-team/ionic/commit/d297ecb87ad3e1c8f0988f0571a475081ce368f8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **card:** expose global card css variables ([#21756](https://github.com/ionic-team/ionic/issues/21756)) ([096eef4](https://github.com/ionic-team/ionic/commit/096eef4a79c2d05c37eb224466c6d7d512d2be20)), closes [#21694](https://github.com/ionic-team/ionic/issues/21694)
|
||||
* **input:** accept datetime-local, month, and week type values ([#21758](https://github.com/ionic-team/ionic/issues/21758)) ([fa93dff](https://github.com/ionic-team/ionic/commit/fa93dffdb4f350e8db8acc7f06b06761974eea8e)), closes [#21757](https://github.com/ionic-team/ionic/issues/21757)
|
||||
* **input, textarea:** expose native events for ionBlur and ionFocus ([#21777](https://github.com/ionic-team/ionic/issues/21777)) ([a625c83](https://github.com/ionic-team/ionic/commit/a625c837a60abc07ad71c696196a89f1a25a4c27)), closes [#17363](https://github.com/ionic-team/ionic/issues/17363)
|
||||
* **react:** add custom history to IonReactRouter ([#21775](https://github.com/ionic-team/ionic/issues/21775)) ([d4a5fbd](https://github.com/ionic-team/ionic/commit/d4a5fbd955e8ecccba8b77491943d81fdf5a5ef4)), closes [#20297](https://github.com/ionic-team/ionic/issues/20297)
|
||||
* **react:** add new react router ([#21693](https://github.com/ionic-team/ionic/issues/21693)) ([c171ccb](https://github.com/ionic-team/ionic/commit/c171ccbd37c1ee4b4934758a3a759170ff357cb2))
|
||||
* **router:** add navigation hooks ([#21709](https://github.com/ionic-team/ionic/issues/21709)) ([77464ef](https://github.com/ionic-team/ionic/commit/77464ef21aaaa5afa7a02e5417f3ec295b240601))
|
||||
* **segment-button, toast:** expose additional shadow parts ([#21532](https://github.com/ionic-team/ionic/issues/21532)) ([a5e4669](https://github.com/ionic-team/ionic/commit/a5e4669c4bcbcb2cdd605ed17c35e42438bd5596))
|
||||
* **select:** add optional generic typings ([#21514](https://github.com/ionic-team/ionic/issues/21514)) ([7c2d0c9](https://github.com/ionic-team/ionic/commit/7c2d0c981ab91930478c4b76220ce4ec4ed4e471))
|
||||
|
||||
|
||||
|
||||
## [5.2.3](https://github.com/ionic-team/ionic/compare/v5.2.2...v5.2.3) (2020-07-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** expose createAnimation in addition to AnimationController ([#21616](https://github.com/ionic-team/ionic/issues/21616)) ([a5b3750](https://github.com/ionic-team/ionic/commit/a5b3750ee2a7c005f80f8453b03c67dd1a5622ca)), closes [#21615](https://github.com/ionic-team/ionic/issues/21615)
|
||||
* **select:** change role to listbox ([#21609](https://github.com/ionic-team/ionic/issues/21609)) ([8c79e2c](https://github.com/ionic-team/ionic/commit/8c79e2c5b58ad562967f2d559c6b548e57536936))
|
||||
* **slides:** enable keyboard integration ([#21608](https://github.com/ionic-team/ionic/issues/21608)) ([26674f1](https://github.com/ionic-team/ionic/commit/26674f1dfa8c9a28f5525f1b16070e8ec494c232)), closes [#21554](https://github.com/ionic-team/ionic/issues/21554)
|
||||
* **textarea:** add aria-labelledby to native textarea ([#21606](https://github.com/ionic-team/ionic/issues/21606)) ([88f23b1](https://github.com/ionic-team/ionic/commit/88f23b1626eb400336f2f52a3e0d34ac3c161e64)), closes [#21600](https://github.com/ionic-team/ionic/issues/21600)
|
||||
|
||||
|
||||
|
||||
## [5.2.2](https://github.com/ionic-team/ionic/compare/v5.2.1...v5.2.2) (2020-06-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **action-sheet, alert:** resolve double click issue when running in iOS mode on chrome ([#21506](https://github.com/ionic-team/ionic/issues/21506)) ([bcccc21](https://github.com/ionic-team/ionic/commit/bcccc217b8833a284a1781e287db5e46043b3548)), closes [#21503](https://github.com/ionic-team/ionic/issues/21503)
|
||||
* **angular:** fix issue where navAnimation was being incorrectly overridden ([#21508](https://github.com/ionic-team/ionic/issues/21508)) ([e968bd0](https://github.com/ionic-team/ionic/commit/e968bd029a4fb37b4001d96a490c6091a948785a)), closes [#21495](https://github.com/ionic-team/ionic/issues/21495)
|
||||
* **input:** add aria-label to clear button ([#21538](https://github.com/ionic-team/ionic/issues/21538)) ([d8b377f](https://github.com/ionic-team/ionic/commit/d8b377ffeb88eaae23b33eadeae5c8e54e1bc77c)), closes [#21537](https://github.com/ionic-team/ionic/issues/21537)
|
||||
* **ios:** respect toolbar opacity when doing nav transition ([#21512](https://github.com/ionic-team/ionic/issues/21512)) ([24cfdc3](https://github.com/ionic-team/ionic/commit/24cfdc308f63b7a55969ac58806eafd67116b017))
|
||||
* **segment:** ensure checked classes get set after not having a value ([#21547](https://github.com/ionic-team/ionic/issues/21547)) ([17308f2](https://github.com/ionic-team/ionic/commit/17308f247f8750029ece39548c9f457e15326189)), closes [#21546](https://github.com/ionic-team/ionic/issues/21546)
|
||||
|
||||
|
||||
## [5.2.1](https://github.com/ionic-team/ionic/compare/v5.2.0...v5.2.1) (2020-06-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** resolve error when not using ngModel on components ([4083e32](https://github.com/ionic-team/ionic/commit/4083e32e103db71f6db86ed1ecd398fda407c28b))
|
||||
|
||||
|
||||
|
||||
# [5.2.0 Silicon](https://github.com/ionic-team/ionic/compare/v5.1.1...v5.2.0) (2020-06-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **action-sheet, toast:** allow button handler to return `Promise<void>` ([#21259](https://github.com/ionic-team/ionic/issues/21259)) ([7703da2](https://github.com/ionic-team/ionic/commit/7703da28f8181b02390b97a7d4d02df99b2ad34c))
|
||||
* **angular:** patch FormControl methods to properly sync Ionic form classes ([#21429](https://github.com/ionic-team/ionic/issues/21429)) ([e95b481](https://github.com/ionic-team/ionic/commit/e95b481a53191582bca635f322ad07eadbd62d64))
|
||||
* **datetime:** ensure year-only values are not affected by timezone when parsing ([#21309](https://github.com/ionic-team/ionic/issues/21309)) ([3937101](https://github.com/ionic-team/ionic/commit/3937101e5c2b181a6b7926eb8386c22b0f887716))
|
||||
* **header:** large title transition now works on older versions of iOS ([#21339](https://github.com/ionic-team/ionic/issues/21339)) ([2dac12c](https://github.com/ionic-team/ionic/commit/2dac12c577e0c7a5310857389dbda2b2b3dfadd1))
|
||||
* **img:** use setTimeout fallback on older versions of chrome ([#21358](https://github.com/ionic-team/ionic/issues/21358)) ([0bf9449](https://github.com/ionic-team/ionic/commit/0bf9449ee1f9b2498e35f61511cb3e018814c6ca))
|
||||
* **ios:** add haptic drag gesture for action sheet and alert components ([#21060](https://github.com/ionic-team/ionic/issues/21060)) ([33be1f0](https://github.com/ionic-team/ionic/commit/33be1f061ebbe27ee22e357c394f112af42ec360))
|
||||
* **item:** inherit align-items from parent item ([#19278](https://github.com/ionic-team/ionic/issues/19278)) ([882f8fe](https://github.com/ionic-team/ionic/commit/882f8fef07dfb6ebda17ca09046d1af281075098)), closes [#18703](https://github.com/ionic-team/ionic/issues/18703)
|
||||
* **item:** input-wrapper now inherits overflow ([#21282](https://github.com/ionic-team/ionic/issues/21282)) ([29d208d](https://github.com/ionic-team/ionic/commit/29d208de88f340e216e22badb6366bba4eda8bfb))
|
||||
* **menu-button:** screen readers now properly announce menu button ([#21324](https://github.com/ionic-team/ionic/issues/21324)) ([eaf4fb6](https://github.com/ionic-team/ionic/commit/eaf4fb6b2a6d68f5c3d8d49ef41b4885f096070d))
|
||||
* **modal:** card style modal no longer gets stuck when swiping quickly ([#21224](https://github.com/ionic-team/ionic/issues/21224)) ([448dfa0](https://github.com/ionic-team/ionic/commit/448dfa0a6955008ce4dc73354f5b8319ae1a1cc2))
|
||||
* **modal:** set card-style modal height using the --height css variable ([#21453](https://github.com/ionic-team/ionic/issues/21453)) ([a4f0bdb](https://github.com/ionic-team/ionic/commit/a4f0bdb4c3ceeeaf902d520e9aa72e04a6ec2302))
|
||||
* **reorder-group:** revert item to original position when passing false to complete ([#21396](https://github.com/ionic-team/ionic/issues/21396)) ([5f2001c](https://github.com/ionic-team/ionic/commit/5f2001c43c0846ec8973cbb8eb5662976ba7e31a)), closes [#19128](https://github.com/ionic-team/ionic/issues/19128)
|
||||
* **router:** use correct nav transition when going back ([#21301](https://github.com/ionic-team/ionic/issues/21301)) ([c8db0d5](https://github.com/ionic-team/ionic/commit/c8db0d5eeba6f10d1492e95e6df6b4d871d43400))
|
||||
* **scroll-assist:** improve scroll detection accuracy ([#21416](https://github.com/ionic-team/ionic/issues/21416)) ([137c49d](https://github.com/ionic-team/ionic/commit/137c49d70be45e1b0ee73d41fed6e9d69a2caa32))
|
||||
* **slides:** update Swiper dependency to resolve error when doing SSR ([#21350](https://github.com/ionic-team/ionic/issues/21350)) ([3290604](https://github.com/ionic-team/ionic/commit/32906048a491961ec7340ba2e085807ea8a9c118))
|
||||
* **textarea:** native textarea inherits max/min width and height ([#21333](https://github.com/ionic-team/ionic/issues/21333)) ([2377480](https://github.com/ionic-team/ionic/commit/237748049c7644ae8a7a74101ece5cfd7a160470))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **alert:** add destructive role to alert buttons ([#21269](https://github.com/ionic-team/ionic/issues/21269)) ([e53f024](https://github.com/ionic-team/ionic/commit/e53f0241e2bf91461c55097fde271ae85ca644ea))
|
||||
* **alert:** add support for custom input attributes ([#21365](https://github.com/ionic-team/ionic/issues/21365)) ([1ed8169](https://github.com/ionic-team/ionic/commit/1ed81693f225b6801a0897ef1a8314999c122484))
|
||||
* **all:** add all autocomplete values to input and searchbar ([#21297](https://github.com/ionic-team/ionic/issues/21297)) ([4fd7c0c](https://github.com/ionic-team/ionic/commit/4fd7c0cc5a6c97100fa380e4ff1be0bb84c7006b))
|
||||
* **all:** add optional generic typings for overlay component methods ([#21393](https://github.com/ionic-team/ionic/issues/21393)) ([5bf83b8](https://github.com/ionic-team/ionic/commit/5bf83b80d7d2749719dd1a280ae8e205fbc4b2a9))
|
||||
* **all:** add shadow parts to missing components ([#21436](https://github.com/ionic-team/ionic/issues/21436)) ([17375d2](https://github.com/ionic-team/ionic/commit/17375d232500b47ef1cacd7c028c38990d307984))
|
||||
* **all:** add support for configuring animations on a per-page basis ([#21433](https://github.com/ionic-team/ionic/issues/21433)) ([f34d375](https://github.com/ionic-team/ionic/commit/f34d3752e3462c9d81487fc86af5ec185cc3d1e3))
|
||||
* **angular:** expose activatedView ([#21302](https://github.com/ionic-team/ionic/issues/21302)) ([829a0d9](https://github.com/ionic-team/ionic/commit/829a0d9be5a20c5fc96b5c5f18fedc4eb5e5b9ec))
|
||||
* **angular:** expose getPlatforms and isPlatform ([#21308](https://github.com/ionic-team/ionic/issues/21308)) ([4af54a2](https://github.com/ionic-team/ionic/commit/4af54a2fea5d9cef843b1ebce849fb4a5c206f0b))
|
||||
* **angular:** add strongly typed Ionic lifecycle hooks ([#18044](https://github.com/ionic-team/ionic/issues/18044)) ([53fc8e3](https://github.com/ionic-team/ionic/commit/53fc8e37c89cea793d0e00246d52805166730108)), closes [#18043](https://github.com/ionic-team/ionic/issues/18043)
|
||||
* **fab-button:** add close icon font size css variable ([#19628](https://github.com/ionic-team/ionic/issues/19628)) ([df408f9](https://github.com/ionic-team/ionic/commit/df408f91f1aef903adaa5e635fef9bc7542e8739))
|
||||
* **fab-button:** add closeIcon property ([#19626](https://github.com/ionic-team/ionic/issues/19626)) ([698e526](https://github.com/ionic-team/ionic/commit/698e526b9f882e98efc4bf160999182c645b772c))
|
||||
* **select-option:** pass class from the option to the interface for individual styling ([#21304](https://github.com/ionic-team/ionic/issues/21304)) ([5285824](https://github.com/ionic-team/ionic/commit/5285824da5258ea638420fc60c50e0a19952f89c))
|
||||
|
||||
|
||||
|
||||
## [5.1.1](https://github.com/ionic-team/ionic/compare/v5.1.0...v5.1.1) (2020-05-13)
|
||||
|
||||
|
||||
@@ -198,9 +695,9 @@
|
||||
* **modal:** presenting multiple card-style modals now adds border radius properly ([#20476](https://github.com/ionic-team/ionic/issues/20476)) ([abf594a](https://github.com/ionic-team/ionic/commit/abf594aa611562a76e3baecfa38456d41a1410f3)), closes [#20475](https://github.com/ionic-team/ionic/issues/20475)
|
||||
* **modal:** prevent card style modal styles from being overridden ([#20470](https://github.com/ionic-team/ionic/issues/20470)) ([86ab77a](https://github.com/ionic-team/ionic/commit/86ab77a6e2cb124510c244110fc78a4bc0654cd1)), closes [#20469](https://github.com/ionic-team/ionic/issues/20469)
|
||||
* **react:** do a better job matching up route to sync ([#20446](https://github.com/ionic-team/ionic/issues/20446)) ([c0aadd6](https://github.com/ionic-team/ionic/commit/c0aadd60077e5ba379959d93006e3a9c1418263c)), closes [#20363](https://github.com/ionic-team/ionic/issues/20363)
|
||||
* **react:** do not remove pages when navigating between tabs ([#20431](https://github.com/ionic-team/ionic/issues/20431)) ([b6fbe98](https://github.com/ionic-team/ionic/commit/b6fbe98812fbab5ef9e0723802605c0711581dd2)), closes [#20398](https://github.com/ionic-team/ionic/issues/20398)
|
||||
* **react:** do not remove pages when navigating between tabs ([#20431](https://github.com/ionic-team/ionic/issues/20431)) ([b6fbe98](https://github.com/ionic-team/ionic/commit/b6fbe98812fbab5ef9e0723802605c0711581dd2)), closes [#20398](https://github.com/ionic-team/ionic/issues/20398)
|
||||
* **react:** icons with MD set should work in browser ([#20463](https://github.com/ionic-team/ionic/issues/20463)) ([82670fe](https://github.com/ionic-team/ionic/commit/82670fe4d0592451cbc243b3008beb3f8f483c30))
|
||||
* **react:** update paths of tab buttons when href changes in ion buttons ([#20480](https://github.com/ionic-team/ionic/issues/20480)) ([45d03ba](https://github.com/ionic-team/ionic/commit/45d03baf981d0e10eb1fe689908532adef2ba31d)), closes [#20321](https://github.com/ionic-team/ionic/issues/20321)
|
||||
* **react:** update paths of tab buttons when href changes in ion buttons ([#20480](https://github.com/ionic-team/ionic/issues/20480)) ([45d03ba](https://github.com/ionic-team/ionic/commit/45d03baf981d0e10eb1fe689908532adef2ba31d)), closes [#20321](https://github.com/ionic-team/ionic/issues/20321)
|
||||
* **searchbar:** properly align placeholder ([#20460](https://github.com/ionic-team/ionic/issues/20460)) ([4d6e15a](https://github.com/ionic-team/ionic/commit/4d6e15ab18fc894c3826b89362163256adc227f4)), closes [#20456](https://github.com/ionic-team/ionic/issues/20456)
|
||||
* **segment:** border radius applies to indicator on ios ([#20541](https://github.com/ionic-team/ionic/issues/20541)) ([9b5854d](https://github.com/ionic-team/ionic/commit/9b5854d79712356f8a3772442c0cc412db09d5e0)), closes [#20539](https://github.com/ionic-team/ionic/issues/20539)
|
||||
* **segment:** do not show ripple effect if disabled via config ([#20542](https://github.com/ionic-team/ionic/issues/20542)) ([7a461c5](https://github.com/ionic-team/ionic/commit/7a461c59c5d9a23de0bcdd53397f452d17251fd6)), closes [#20533](https://github.com/ionic-team/ionic/issues/20533)
|
||||
|
||||
@@ -1,11 +1,129 @@
|
||||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of the Ionic project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
Communication through any of Ionic's channels (GitHub, Slack, Forum, IRC, mailing lists, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
||||
## Our Pledge
|
||||
|
||||
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Ionic project to do the same.
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
If any member of the community violates this code of conduct, the maintainers of the Ionic project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at [hi@ionicframework.com](mailto:hi@ionicframework.com).
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include the ability to:
|
||||
|
||||
* Demonstrate empathy and kindness towards people
|
||||
* Be respectful of differing opinions, viewpoints, and experiences
|
||||
* Give and gracefully accept constructive feedback
|
||||
* Accept responsibility and apologize to those affected by our mistakes,
|
||||
and learn from the experience
|
||||
* Focus on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
[contact@ionic.io](mailto:contact@ionic.io).
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
|
||||
12
README.md
12
README.md
@@ -1,9 +1,9 @@
|
||||
# Ionic
|
||||
# Ionic Framework
|
||||
|
||||
[Ionic](https://ionicframework.com/) is the open-source mobile app development framework that makes it easy to
|
||||
[Ionic Framework](https://ionicframework.com/) is the open-source mobile app development framework that makes it easy to
|
||||
build top quality native and progressive web apps with web technologies.
|
||||
|
||||
Ionic is based on [Web Components](https://www.webcomponents.org/introduction) and comes with many significant performance, usability, and feature improvements over the past versions.
|
||||
Ionic Framework is based on [Web Components](https://www.webcomponents.org/introduction) and comes with many significant performance, usability, and feature improvements over the past versions.
|
||||
|
||||
|
||||
### Packages
|
||||
@@ -12,7 +12,7 @@ Ionic is based on [Web Components](https://www.webcomponents.org/introduction) a
|
||||
| ------- | ------- | ------- |:-----:|
|
||||
| **Core** | [`@ionic/core`](https://www.npmjs.com/package/@ionic/core) | [](https://www.npmjs.com/package/@ionic/core) | [`README.md`](core/README.md)
|
||||
| **Angular** | [`@ionic/angular`](https://www.npmjs.com/package/@ionic/angular) | [](https://www.npmjs.com/package/@ionic/angular) | [`README.md`](angular/README.md)
|
||||
| **Vue** | [`@ionic/vue`](https://www.npmjs.com/package/@ionic/vue) | [](https://www.npmjs.com/package/@ionic/vue) | [`README.md`](vue/README.md)
|
||||
| **Vue** | [`@ionic/vue`](https://www.npmjs.com/package/@ionic/vue) | [](https://www.npmjs.com/package/@ionic/vue) | [`README.md`](packages/vue/README.md)
|
||||
| **React** | [`@ionic/react`](https://www.npmjs.com/package/@ionic/react) | [](https://www.npmjs.com/package/@ionic/react) | [`README.md`](packages/react/README.md)
|
||||
|
||||
Looking for the `ionic-angular` package? Ionic 3 has been moved to the [`ionic-v3`](https://github.com/ionic-team/ionic-v3) repo. See [Earlier Versions](#earlier-versions).
|
||||
@@ -31,6 +31,8 @@ Thanks for your interest in contributing! Read up on our guidelines for
|
||||
and then look through our issues with a [help wanted](https://github.com/ionic-team/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
label.
|
||||
|
||||
Please note that this project is released with a [Contributor Code of Conduct](https://github.com/ionic-team/ionic/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -40,7 +42,7 @@ It is the perfect starting point for learning and building your own app.
|
||||
|
||||
### Future Goals
|
||||
|
||||
As Ionic components migrate to the web component standard, a goal of ours is to have Ionic components easily work within all of the popular frameworks.
|
||||
As Ionic Framework components migrate to the web component standard, a goal of ours is to have Ionic Framework easily work within all of the popular frameworks.
|
||||
|
||||
### Earlier Versions
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package-lock=false
|
||||
@@ -7,7 +7,6 @@ Ionic Angular specific building blocks on top of [@ionic/core](https://www.npmjs
|
||||
|
||||
* [Ionic Core Components](https://www.npmjs.com/package/@ionic/core)
|
||||
* [Ionic Documentation](https://ionicframework.com/docs/)
|
||||
* [Ionic Worldwide Slack](http://ionicworldwide.herokuapp.com/)
|
||||
* [Ionic Forum](https://forum.ionicframework.com/)
|
||||
* [Ionicons](http://ionicons.com/)
|
||||
* [Stencil](https://stenciljs.com/)
|
||||
|
||||
9085
angular/package-lock.json
generated
Normal file
9085
angular/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "5.1.1",
|
||||
"version": "5.6.3",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -42,7 +42,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "5.1.1",
|
||||
"@ionic/core": "5.6.3",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -67,12 +67,12 @@
|
||||
"ng-packagr": "^9.1.5",
|
||||
"rollup": "~1.17.0",
|
||||
"rollup-plugin-node-resolve": "~5.2.0",
|
||||
"rxjs": "^6.5.2",
|
||||
"tsickle": "^0.34.0",
|
||||
"rxjs": "^6.6.2",
|
||||
"tsickle": "^0.39.1",
|
||||
"tslint": "^5.12.1",
|
||||
"tslint-ionic-rules": "0.0.21",
|
||||
"typescript": "3.4.5",
|
||||
"zone.js": "^0.8.28"
|
||||
"zone.js": "^0.11.1"
|
||||
},
|
||||
"schematics": "./schematics/collection.json",
|
||||
"ngPackage": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
|
||||
export default {
|
||||
input: 'build/es2015/core.js',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor, setIonicClasses } from './value-accessor';
|
||||
@@ -16,8 +16,8 @@ import { ValueAccessor, setIonicClasses } from './value-accessor';
|
||||
})
|
||||
export class BooleanValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(el: ElementRef) {
|
||||
super(el);
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
writeValue(value: any) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor } from './value-accessor';
|
||||
@@ -16,8 +16,8 @@ import { ValueAccessor } from './value-accessor';
|
||||
})
|
||||
export class NumericValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(el: ElementRef) {
|
||||
super(el);
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor } from './value-accessor';
|
||||
@@ -16,8 +16,8 @@ import { ValueAccessor } from './value-accessor';
|
||||
})
|
||||
export class RadioValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(el: ElementRef) {
|
||||
super(el);
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionSelect', ['$event.target'])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor } from './value-accessor';
|
||||
@@ -16,8 +16,8 @@ import { ValueAccessor } from './value-accessor';
|
||||
})
|
||||
export class SelectValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(el: ElementRef) {
|
||||
super(el);
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor } from './value-accessor';
|
||||
@@ -16,8 +16,8 @@ import { ValueAccessor } from './value-accessor';
|
||||
})
|
||||
export class TextValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(el: ElementRef) {
|
||||
super(el);
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { ElementRef, HostListener } from '@angular/core';
|
||||
import { ControlValueAccessor } from '@angular/forms';
|
||||
import { AfterViewInit, ElementRef, HostListener, Injector, OnDestroy, Type } from '@angular/core';
|
||||
import { ControlValueAccessor, NgControl } from '@angular/forms';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { raf } from '../../util/util';
|
||||
|
||||
export class ValueAccessor implements ControlValueAccessor {
|
||||
export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDestroy {
|
||||
|
||||
private onChange: (value: any) => void = () => {/**/};
|
||||
private onTouched: () => void = () => {/**/};
|
||||
protected lastValue: any;
|
||||
private statusChanges?: Subscription;
|
||||
|
||||
constructor(protected el: ElementRef) {}
|
||||
constructor(protected injector: Injector, protected el: ElementRef) {}
|
||||
|
||||
writeValue(value: any) {
|
||||
/**
|
||||
@@ -52,6 +54,50 @@ export class ValueAccessor implements ControlValueAccessor {
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.el.nativeElement.disabled = isDisabled;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.statusChanges) {
|
||||
this.statusChanges.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
let ngControl;
|
||||
try {
|
||||
ngControl = this.injector.get<NgControl>(NgControl as Type<NgControl>);
|
||||
} catch { /* No FormControl or ngModel binding */ }
|
||||
|
||||
if (!ngControl) { return; }
|
||||
|
||||
// Listen for changes in validity, disabled, or pending states
|
||||
if (ngControl.statusChanges) {
|
||||
this.statusChanges = ngControl.statusChanges.subscribe(() => setIonicClasses(this.el));
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO Remove this in favor of https://github.com/angular/angular/issues/10887
|
||||
* whenever it is implemented. Currently, Ionic's form status classes
|
||||
* do not react to changes when developers manually call
|
||||
* Angular form control methods such as markAsTouched.
|
||||
* This results in Ionic's form status classes being out
|
||||
* of sync with the ng form status classes.
|
||||
* This patches the methods to manually sync
|
||||
* the classes until this feature is implemented in Angular.
|
||||
*/
|
||||
const formControl = ngControl.control;
|
||||
if (formControl) {
|
||||
const methodsToPatch = ['markAsTouched', 'markAllAsTouched', 'markAsUntouched', 'markAsDirty', 'markAsPristine'];
|
||||
methodsToPatch.forEach(method => {
|
||||
if (formControl[method]) {
|
||||
const oldFn = formControl[method].bind(formControl);
|
||||
formControl[method] = (...params) => {
|
||||
oldFn(...params);
|
||||
setIonicClasses(this.el);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const setIonicClasses = (element: ElementRef) => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Directive, HostListener, Optional } from '@angular/core';
|
||||
import { AnimationBuilder } from '@ionic/core';
|
||||
|
||||
import { Config } from '../../providers/config';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
@@ -7,11 +8,12 @@ import { IonRouterOutlet } from './ion-router-outlet';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-back-button',
|
||||
inputs: ['defaultHref'],
|
||||
inputs: ['defaultHref', 'routerAnimation'],
|
||||
})
|
||||
export class IonBackButtonDelegate {
|
||||
|
||||
defaultHref: string | undefined | null;
|
||||
routerAnimation?: AnimationBuilder;
|
||||
|
||||
constructor(
|
||||
@Optional() private routerOutlet: IonRouterOutlet,
|
||||
@@ -27,10 +29,11 @@ export class IonBackButtonDelegate {
|
||||
const defaultHref = this.defaultHref || this.config.get('backButtonDefaultHref');
|
||||
|
||||
if (this.routerOutlet && this.routerOutlet.canGoBack()) {
|
||||
this.navCtrl.setDirection('back', undefined, undefined, this.routerAnimation);
|
||||
this.routerOutlet.pop();
|
||||
ev.preventDefault();
|
||||
} else if (defaultHref != null) {
|
||||
this.navCtrl.navigateBack(defaultHref);
|
||||
this.navCtrl.navigateBack(defaultHref, { animation: this.routerAnimation });
|
||||
ev.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { Attribute, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, NgZone, OnDestroy, OnInit, Optional, Output, SkipSelf, ViewContainerRef } from '@angular/core';
|
||||
import { ActivatedRoute, ChildrenOutletContexts, OutletContext, PRIMARY_OUTLET, Router } from '@angular/router';
|
||||
import { componentOnReady } from '@ionic/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, switchMap } from 'rxjs/operators';
|
||||
|
||||
@@ -96,13 +97,12 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
this.activateWith(context.route, context.resolver || null);
|
||||
}
|
||||
}
|
||||
if ((this.nativeEl as any).componentOnReady) {
|
||||
this.nativeEl.componentOnReady().then(() => {
|
||||
if (this._swipeGesture === undefined) {
|
||||
this.swipeGesture = this.config.getBoolean('swipeBackEnabled', (this.nativeEl as any).mode === 'ios');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
new Promise(resolve => componentOnReady(this.nativeEl, resolve)).then(() => {
|
||||
if (this._swipeGesture === undefined) {
|
||||
this.swipeGesture = this.config.getBoolean('swipeBackEnabled', (this.nativeEl as any).mode === 'ios');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get isActivated(): boolean {
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
import { LocationStrategy } from '@angular/common';
|
||||
import { Directive, ElementRef, HostListener, Optional } from '@angular/core';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { RouterDirection } from '@ionic/core';
|
||||
import { AnimationBuilder, RouterDirection } from '@ionic/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
@Directive({
|
||||
selector: '[routerLink]',
|
||||
inputs: ['routerDirection']
|
||||
inputs: ['routerDirection', 'routerAnimation']
|
||||
})
|
||||
export class RouterLinkDelegate {
|
||||
|
||||
private subscription?: Subscription;
|
||||
|
||||
routerDirection: RouterDirection = 'forward';
|
||||
routerAnimation?: AnimationBuilder;
|
||||
|
||||
constructor(
|
||||
private locationStrategy: LocationStrategy,
|
||||
@@ -50,7 +51,7 @@ export class RouterLinkDelegate {
|
||||
*/
|
||||
@HostListener('click', ['$event'])
|
||||
onClick(ev: UIEvent) {
|
||||
this.navCtrl.setDirection(this.routerDirection);
|
||||
this.navCtrl.setDirection(this.routerDirection, undefined, undefined, this.routerAnimation);
|
||||
ev.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { ComponentRef, NgZone } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { RouterDirection } from '@ionic/core';
|
||||
import { AnimationBuilder, RouterDirection } from '@ionic/core';
|
||||
|
||||
import { bindLifecycleEvents } from '../../providers/angular-delegate';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
@@ -52,7 +52,8 @@ export class StackController {
|
||||
}
|
||||
|
||||
setActive(enteringView: RouteView): Promise<StackEvent> {
|
||||
let { direction, animation } = this.navCtrl.consumeTransition();
|
||||
const consumeResult = this.navCtrl.consumeTransition();
|
||||
let { direction, animation, animationBuilder } = consumeResult;
|
||||
const leavingView = this.activeView;
|
||||
const tabSwitch = isTabSwitch(enteringView, leavingView);
|
||||
if (tabSwitch) {
|
||||
@@ -105,6 +106,31 @@ export class StackController {
|
||||
enteringView.ref.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
/**
|
||||
* If we are going back from a page that
|
||||
* was presented using a custom animation
|
||||
* we should default to using that
|
||||
* unless the developer explicitly
|
||||
* provided another animation.
|
||||
*/
|
||||
const customAnimation = enteringView.animationBuilder;
|
||||
if (
|
||||
animationBuilder === undefined &&
|
||||
direction === 'back' &&
|
||||
!tabSwitch &&
|
||||
customAnimation !== undefined
|
||||
) {
|
||||
animationBuilder = customAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save any custom animation so that navigating
|
||||
* back will use this custom animation by default.
|
||||
*/
|
||||
if (leavingView) {
|
||||
leavingView.animationBuilder = animationBuilder;
|
||||
}
|
||||
|
||||
// Wait until previous transitions finish
|
||||
return this.zone.runOutsideAngular(() => {
|
||||
return this.wait(() => {
|
||||
@@ -116,7 +142,7 @@ export class StackController {
|
||||
// In case the enteringView is the same as the leavingPage we need to reattach()
|
||||
enteringView.ref.changeDetectorRef.reattach();
|
||||
|
||||
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false)
|
||||
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false, animationBuilder)
|
||||
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location))
|
||||
.then(() => ({
|
||||
enteringView,
|
||||
@@ -154,8 +180,8 @@ export class StackController {
|
||||
url = primaryOutlet.route._routerState.snapshot.url;
|
||||
}
|
||||
}
|
||||
|
||||
return this.navCtrl.navigateBack(url, view.savedExtras).then(() => true);
|
||||
const { animationBuilder } = this.navCtrl.consumeTransition();
|
||||
return this.navCtrl.navigateBack(url, { ...view.savedExtras, animation: animationBuilder }).then(() => true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -164,13 +190,16 @@ export class StackController {
|
||||
if (leavingView) {
|
||||
const views = this.getStack(leavingView.stackId);
|
||||
const enteringView = views[views.length - 2];
|
||||
const customAnimation = enteringView.animationBuilder;
|
||||
|
||||
return this.wait(() => {
|
||||
return this.transition(
|
||||
enteringView, // entering view
|
||||
leavingView, // leaving view
|
||||
'back',
|
||||
this.canGoBack(2),
|
||||
true
|
||||
true,
|
||||
customAnimation
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -225,7 +254,8 @@ export class StackController {
|
||||
leavingView: RouteView | undefined,
|
||||
direction: 'forward' | 'back' | undefined,
|
||||
showGoBack: boolean,
|
||||
progressAnimation: boolean
|
||||
progressAnimation: boolean,
|
||||
animationBuilder?: AnimationBuilder
|
||||
) {
|
||||
if (this.skipTransition) {
|
||||
this.skipTransition = false;
|
||||
@@ -250,7 +280,8 @@ export class StackController {
|
||||
duration: direction === undefined ? 0 : undefined,
|
||||
direction,
|
||||
showGoBack,
|
||||
progressAnimation
|
||||
progressAnimation,
|
||||
animationBuilder
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ComponentRef } from '@angular/core';
|
||||
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
||||
import { NavDirection, RouterDirection } from '@ionic/core';
|
||||
import { AnimationBuilder, NavDirection, RouterDirection } from '@ionic/core';
|
||||
|
||||
export const insertView = (views: RouteView[], view: RouteView, direction: RouterDirection) => {
|
||||
if (direction === 'root') {
|
||||
@@ -96,4 +96,5 @@ export interface RouteView {
|
||||
savedData?: any;
|
||||
savedExtras?: NavigationExtras;
|
||||
unlistenEvents: () => void;
|
||||
animationBuilder?: AnimationBuilder;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import * as d from './proxies';
|
||||
import type * as d from './proxies';
|
||||
|
||||
export const DIRECTIVES = [
|
||||
d.IonApp,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,7 @@ export declare interface IonVirtualScroll {
|
||||
* entire virtual scroll is reset, which is an expensive operation and
|
||||
* should be avoided if possible.
|
||||
*/
|
||||
items?: any[];
|
||||
items?: any[] | null;
|
||||
|
||||
/**
|
||||
* An optional function that maps each item within their height.
|
||||
|
||||
@@ -43,7 +43,7 @@ export * from './types/ionic-lifecycle-hooks';
|
||||
export { IonicModule } from './ionic-module';
|
||||
|
||||
// UTILS
|
||||
export { IonicSafeString, getPlatforms, isPlatform } from '@ionic/core';
|
||||
export { IonicSafeString, getPlatforms, isPlatform, createAnimation } from '@ionic/core';
|
||||
|
||||
// CORE TYPES
|
||||
export { Animation, AnimationBuilder, AnimationCallbackOptions, AnimationDirection, AnimationFill, AnimationKeyFrames, AnimationLifecycle, Gesture, GestureConfig, GestureDetail, mdTransitionAnimation, iosTransitionAnimation } from '@ionic/core';
|
||||
export { Animation, AnimationBuilder, AnimationCallbackOptions, AnimationDirection, AnimationFill, AnimationKeyFrames, AnimationLifecycle, Gesture, GestureConfig, GestureDetail, mdTransitionAnimation, iosTransitionAnimation, NavComponentWithProps } from '@ionic/core';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { Injectable, Optional } from '@angular/core';
|
||||
import { NavigationExtras, NavigationStart, Router, UrlSerializer, UrlTree } from '@angular/router';
|
||||
import { NavDirection, RouterDirection } from '@ionic/core';
|
||||
import { AnimationBuilder, NavDirection, RouterDirection } from '@ionic/core';
|
||||
|
||||
import { IonRouterOutlet } from '../directives/navigation/ion-router-outlet';
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Platform } from './platform';
|
||||
|
||||
export interface AnimationOptions {
|
||||
animated?: boolean;
|
||||
animation?: AnimationBuilder;
|
||||
animationDirection?: 'forward' | 'back';
|
||||
}
|
||||
|
||||
@@ -22,6 +23,7 @@ export class NavController {
|
||||
private topOutlet?: IonRouterOutlet;
|
||||
private direction: 'forward' | 'back' | 'root' | 'auto' = DEFAULT_DIRECTION;
|
||||
private animated?: NavDirection = DEFAULT_ANIMATED;
|
||||
private animationBuilder?: AnimationBuilder;
|
||||
private guessDirection: RouterDirection = 'forward';
|
||||
private guessAnimation?: NavDirection;
|
||||
private lastNavId = -1;
|
||||
@@ -65,7 +67,7 @@ export class NavController {
|
||||
* ```
|
||||
*/
|
||||
navigateForward(url: string | UrlTree | any[], options: NavigationOptions = {}): Promise<boolean> {
|
||||
this.setDirection('forward', options.animated, options.animationDirection);
|
||||
this.setDirection('forward', options.animated, options.animationDirection, options.animation);
|
||||
return this.navigate(url, options);
|
||||
}
|
||||
|
||||
@@ -88,7 +90,7 @@ export class NavController {
|
||||
* ```
|
||||
*/
|
||||
navigateBack(url: string | UrlTree | any[], options: NavigationOptions = {}): Promise<boolean> {
|
||||
this.setDirection('back', options.animated, options.animationDirection);
|
||||
this.setDirection('back', options.animated, options.animationDirection, options.animation);
|
||||
return this.navigate(url, options);
|
||||
}
|
||||
|
||||
@@ -111,7 +113,7 @@ export class NavController {
|
||||
* ```
|
||||
*/
|
||||
navigateRoot(url: string | UrlTree | any[], options: NavigationOptions = {}): Promise<boolean> {
|
||||
this.setDirection('root', options.animated, options.animationDirection);
|
||||
this.setDirection('root', options.animated, options.animationDirection, options.animation);
|
||||
return this.navigate(url, options);
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ export class NavController {
|
||||
* by default.
|
||||
*/
|
||||
back(options: AnimationOptions = { animated: true, animationDirection: 'back' }) {
|
||||
this.setDirection('back', options.animated, options.animationDirection);
|
||||
this.setDirection('back', options.animated, options.animationDirection, options.animation);
|
||||
return this.location.back();
|
||||
}
|
||||
|
||||
@@ -150,9 +152,10 @@ export class NavController {
|
||||
*
|
||||
* It's recommended to use `navigateForward()`, `navigateBack()` and `navigateRoot()` instead of `setDirection()`.
|
||||
*/
|
||||
setDirection(direction: RouterDirection, animated?: boolean, animationDirection?: 'forward' | 'back') {
|
||||
setDirection(direction: RouterDirection, animated?: boolean, animationDirection?: 'forward' | 'back', animationBuilder?: AnimationBuilder) {
|
||||
this.direction = direction;
|
||||
this.animated = getAnimation(direction, animated, animationDirection);
|
||||
this.animationBuilder = animationBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,6 +171,7 @@ export class NavController {
|
||||
consumeTransition() {
|
||||
let direction: RouterDirection = 'root';
|
||||
let animation: NavDirection | undefined;
|
||||
const animationBuilder = this.animationBuilder;
|
||||
|
||||
if (this.direction === 'auto') {
|
||||
direction = this.guessDirection;
|
||||
@@ -178,10 +182,12 @@ export class NavController {
|
||||
}
|
||||
this.direction = DEFAULT_DIRECTION;
|
||||
this.animated = DEFAULT_ANIMATED;
|
||||
this.animationBuilder = undefined;
|
||||
|
||||
return {
|
||||
direction,
|
||||
animation
|
||||
animation,
|
||||
animationBuilder
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -40,20 +40,23 @@ function addIonicAngularModuleToAppModule(projectSourceRoot: Path): Rule {
|
||||
function addIonicStyles(projectName: string, projectSourceRoot: Path): Rule {
|
||||
return (host: Tree) => {
|
||||
const ionicStyles = [
|
||||
'node_modules/@ionic/angular/css/core.css',
|
||||
'node_modules/@ionic/angular/css/normalize.css',
|
||||
'node_modules/@ionic/angular/css/structure.css',
|
||||
'node_modules/@ionic/angular/css/typography.css',
|
||||
'node_modules/@ionic/angular/css/core.css',
|
||||
'node_modules/@ionic/angular/css/display.css',
|
||||
'node_modules/@ionic/angular/css/padding.css',
|
||||
'node_modules/@ionic/angular/css/float-elements.css',
|
||||
'node_modules/@ionic/angular/css/text-alignment.css',
|
||||
'node_modules/@ionic/angular/css/text-transformation.css',
|
||||
'node_modules/@ionic/angular/css/flex-utils.css',
|
||||
`${projectSourceRoot}/theme/variables.css`
|
||||
].forEach(entry => {
|
||||
]
|
||||
|
||||
ionicStyles.forEach(entry => {
|
||||
addStyle(host, projectName, entry);
|
||||
});
|
||||
return host;
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,7 +67,8 @@ function addIonicons(projectName: string): Rule {
|
||||
input: 'node_modules/ionicons/dist/ionicons/svg',
|
||||
output: './svg'
|
||||
};
|
||||
addAsset(host, projectName, ioniconsGlob);
|
||||
addAsset(host, projectName, 'build', ioniconsGlob);
|
||||
addAsset(host, projectName, 'test', ioniconsGlob);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@ export function addStyle(host: Tree, projectName: string, stylePath: string) {
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
export function addAsset(host: Tree, projectName: string, asset: string | {glob: string; input: string; output: string}) {
|
||||
export function addAsset(host: Tree, projectName: string, architect: string, asset: string | {glob: string; input: string; output: string}) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect.build.options.assets.push(asset);
|
||||
appConfig.architect[architect].options.assets.push(asset);
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,6 @@ export interface IonicWindow extends Window {
|
||||
}
|
||||
|
||||
export interface HTMLStencilElement extends HTMLElement {
|
||||
componentOnReady(): Promise<this>;
|
||||
forceUpdate(): void;
|
||||
componentOnReady?(): Promise<this>;
|
||||
forceUpdate?(): void;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package-lock=false
|
||||
14
angular/test/test-app/e2e/protractor-ci.conf.js
Normal file
14
angular/test/test-app/e2e/protractor-ci.conf.js
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
// Protractor CI configuration file, see link for more information
|
||||
// https://angular.io/guide/testing#configure-cli-for-ci-testing-in-chrome
|
||||
|
||||
const config = require('./protractor.conf').config;
|
||||
|
||||
config.capabilities = {
|
||||
browserName: 'chrome',
|
||||
chromeOptions: {
|
||||
args: ['--headless', '--no-sandbox', '--window-size=1920,1080']
|
||||
}
|
||||
};
|
||||
|
||||
exports.config = config;
|
||||
@@ -1,4 +1,4 @@
|
||||
// @ts-check
|
||||
// @ts-check
|
||||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import { handleErrorMessages, setProperty, getText, waitTime } from './utils';
|
||||
import { handleErrorMessages, getProperty, setProperty, getText, waitTime } from './utils';
|
||||
|
||||
describe('form', () => {
|
||||
|
||||
@@ -7,6 +7,20 @@ describe('form', () => {
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
describe('status updates', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/form');
|
||||
await waitTime(30);
|
||||
});
|
||||
|
||||
it('should update Ionic form classes when calling form methods programatically', async () => {
|
||||
await element(by.css('form #input-touched')).click();
|
||||
await waitTime(100);
|
||||
const classList = (await getProperty('#touched-input-test', 'classList')) as string[];
|
||||
expect(classList.includes('ion-touched')).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('change', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/form');
|
||||
@@ -17,13 +31,13 @@ describe('form', () => {
|
||||
await testStatus('INVALID');
|
||||
expect(await getText('#submit')).toEqual('false');
|
||||
await testData({
|
||||
'datetime': '2010-08-20',
|
||||
'select': null,
|
||||
'toggle': false,
|
||||
'input': '',
|
||||
'input2': 'Default Value',
|
||||
'checkbox': false,
|
||||
'range': 5
|
||||
datetime: '2010-08-20',
|
||||
select: null,
|
||||
toggle: false,
|
||||
input: '',
|
||||
input2: 'Default Value',
|
||||
checkbox: false,
|
||||
range: 5
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,39 +49,39 @@ describe('form', () => {
|
||||
await setProperty('ion-range', 'value', 40);
|
||||
await testStatus('VALID');
|
||||
await testData({
|
||||
'datetime': '2010-08-20',
|
||||
'select': 'nes',
|
||||
'toggle': false,
|
||||
'input': 'Some value',
|
||||
'input2': 'Default Value',
|
||||
'checkbox': false,
|
||||
'range': 40
|
||||
datetime: '2010-08-20',
|
||||
select: 'nes',
|
||||
toggle: false,
|
||||
input: 'Some value',
|
||||
input2: 'Default Value',
|
||||
checkbox: false,
|
||||
range: 40
|
||||
});
|
||||
});
|
||||
|
||||
it('ion-toggle should change', async () => {
|
||||
await element(by.css('form ion-toggle')).click();
|
||||
await testData({
|
||||
'datetime': '2010-08-20',
|
||||
'select': null,
|
||||
'toggle': true,
|
||||
'input': '',
|
||||
'input2': 'Default Value',
|
||||
'checkbox': false,
|
||||
'range': 5
|
||||
datetime: '2010-08-20',
|
||||
select: null,
|
||||
toggle: true,
|
||||
input: '',
|
||||
input2: 'Default Value',
|
||||
checkbox: false,
|
||||
range: 5
|
||||
});
|
||||
});
|
||||
|
||||
it('ion-checkbox should change', async () => {
|
||||
await element(by.css('ion-checkbox')).click();
|
||||
await testData({
|
||||
'datetime': '2010-08-20',
|
||||
'select': null,
|
||||
'toggle': false,
|
||||
'input': '',
|
||||
'input2': 'Default Value',
|
||||
'checkbox': true,
|
||||
'range': 5
|
||||
datetime: '2010-08-20',
|
||||
select: null,
|
||||
toggle: false,
|
||||
input: '',
|
||||
input2: 'Default Value',
|
||||
checkbox: true,
|
||||
range: 5
|
||||
});
|
||||
});
|
||||
|
||||
@@ -88,23 +102,23 @@ describe('form', () => {
|
||||
it('ion-toggle should change only after blur', async () => {
|
||||
await element(by.css('form ion-toggle')).click();
|
||||
await testData({
|
||||
'datetime': '2010-08-20',
|
||||
'select': null,
|
||||
'toggle': false,
|
||||
'input': '',
|
||||
'input2': 'Default Value',
|
||||
'checkbox': false,
|
||||
'range': 5
|
||||
datetime: '2010-08-20',
|
||||
select: null,
|
||||
toggle: false,
|
||||
input: '',
|
||||
input2: 'Default Value',
|
||||
checkbox: false,
|
||||
range: 5
|
||||
});
|
||||
await element(by.css('ion-checkbox')).click();
|
||||
await testData({
|
||||
'datetime': '2010-08-20',
|
||||
'select': null,
|
||||
'toggle': true,
|
||||
'input': '',
|
||||
'input2': 'Default Value',
|
||||
'checkbox': false,
|
||||
'range': 5
|
||||
datetime: '2010-08-20',
|
||||
select: null,
|
||||
toggle: true,
|
||||
input: '',
|
||||
input2: 'Default Value',
|
||||
checkbox: false,
|
||||
range: 5
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -149,7 +149,7 @@ describe('tabs', () => {
|
||||
|
||||
it('should set root when clicking on an active tab to navigate to the root', async () => {
|
||||
const expectNestedTabUrlToContain = 'search=hello#fragment';
|
||||
let tab = await getSelectedTab() as ElementFinder;
|
||||
const tab = await getSelectedTab() as ElementFinder;
|
||||
const initialUrl = await browser.getCurrentUrl();
|
||||
await tab.$('#goto-nested-page1-with-query-params').click();
|
||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
@@ -176,7 +176,7 @@ describe('tabs', () => {
|
||||
it('should preserve root url navigation extras when clicking on an active tab to navigate to the root', async () => {
|
||||
await browser.get(rootUrl);
|
||||
|
||||
let tab = await getSelectedTab() as ElementFinder;
|
||||
const tab = await getSelectedTab() as ElementFinder;
|
||||
await tab.$('#goto-nested-page1-with-query-params').click();
|
||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
await testUrlContains(expectNestedTabUrlToContain);
|
||||
|
||||
@@ -37,7 +37,7 @@ export interface LifeCycleCount {
|
||||
}
|
||||
|
||||
export function handleErrorMessages() {
|
||||
return browser.manage().logs().get('browser').then(function (browserLog) {
|
||||
return browser.manage().logs().get('browser').then(browserLog => {
|
||||
for (let i = 0; i <= browserLog.length - 1; i++) {
|
||||
if (browserLog[i].level.name_ === 'SEVERE') {
|
||||
fail(browserLog[i].message);
|
||||
|
||||
@@ -26,6 +26,12 @@ module.exports = function (config) {
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
customLaunchers: {
|
||||
ChromeHeadlessCI: {
|
||||
base: 'ChromeHeadless',
|
||||
flags: ['--no-sandbox']
|
||||
}
|
||||
},
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
|
||||
14734
angular/test/test-app/package-lock.json
generated
Normal file
14734
angular/test/test-app/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,8 @@
|
||||
"sync:build": "sh scripts/build-ionic.sh",
|
||||
"sync": "sh scripts/sync.sh",
|
||||
"build": "npm run sync && ng build --prod --no-progress",
|
||||
"test": "ng e2e --prod",
|
||||
"pretest": "webdriver-manager update --versions.chrome 89.0.4389.23",
|
||||
"test": "ng e2e --prod --webdriver-update=false",
|
||||
"test.dev": "npm run sync && ng e2e",
|
||||
"lint": "ng lint",
|
||||
"postinstall": "npm run sync && ngcc",
|
||||
@@ -18,46 +19,49 @@
|
||||
"prerender": "ng run test-app:prerender"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^9.0.0-rc.2",
|
||||
"@angular/common": "^9.0.0-rc.2",
|
||||
"@angular/compiler": "^9.0.0-rc.2",
|
||||
"@angular/core": "^9.0.0-rc.2",
|
||||
"@angular/forms": "^9.0.0-rc.2",
|
||||
"@angular/platform-browser": "^9.0.0-rc.2",
|
||||
"@angular/platform-browser-dynamic": "^9.0.0-rc.2",
|
||||
"@angular/platform-server": "^9.0.0-rc.2",
|
||||
"@angular/router": "^9.0.0-rc.2",
|
||||
"@ionic/angular": "^4.7.0",
|
||||
"@ionic/angular-server": "^0.0.2",
|
||||
"@angular/animations": "^9.1.12",
|
||||
"@angular/common": "^9.1.12",
|
||||
"@angular/compiler": "^9.1.12",
|
||||
"@angular/core": "^9.1.12",
|
||||
"@angular/forms": "^9.1.12",
|
||||
"@angular/platform-browser": "^9.1.12",
|
||||
"@angular/platform-browser-dynamic": "^9.1.12",
|
||||
"@angular/platform-server": "^9.1.12",
|
||||
"@angular/router": "^9.1.12",
|
||||
"@ionic/angular": "^5.3.1",
|
||||
"@ionic/angular-server": "^5.3.1",
|
||||
"@nguniversal/express-engine": "9.0.0-next.9",
|
||||
"core-js": "^2.6.2",
|
||||
"angular-in-memory-web-api": "^0.11.0",
|
||||
"core-js": "^2.6.11",
|
||||
"express": "^4.15.2",
|
||||
"rxjs": "^6.5.3",
|
||||
"tslib": "^1.10.0",
|
||||
"zone.js": "~0.10.2"
|
||||
"jasmine-marbles": "^0.6.0",
|
||||
"rxjs": "^6.5.5",
|
||||
"tslib": "^1.13.0",
|
||||
"zone.js": "^0.10.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.900.0-rc.2",
|
||||
"@angular/cli": "^9.0.0-rc.2",
|
||||
"@angular/compiler-cli": "^9.0.0-rc.2",
|
||||
"@angular/language-service": "^9.0.0-rc.2",
|
||||
"@angular-devkit/build-angular": "^0.901.12",
|
||||
"@angular/cli": "^9.1.12",
|
||||
"@angular/compiler-cli": "^9.1.12",
|
||||
"@angular/language-service": "^9.1.12",
|
||||
"@nguniversal/builders": "9.0.0-next.9",
|
||||
"@types/express": "^4.17.0",
|
||||
"@types/jasmine": "3.4.1",
|
||||
"@types/node": "^12.11.1",
|
||||
"codelyzer": "^5.1.2",
|
||||
"jasmine-core": "~3.5.0",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~4.3.0",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.1.0",
|
||||
"karma-jasmine": "~2.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.4.2",
|
||||
"protractor": "~5.4.2",
|
||||
"ts-loader": "^6.1.2",
|
||||
"ts-node": "8.4.1",
|
||||
"tslint": "~5.18.0",
|
||||
"typescript": "~3.6.4",
|
||||
"webpack-cli": "^3.3.9"
|
||||
"@types/express": "^4.17.7",
|
||||
"@types/jasmine": "^3.5.13",
|
||||
"@types/jasminewd2": "^2.0.8",
|
||||
"@types/node": "^12.12.54",
|
||||
"codelyzer": "^5.2.2",
|
||||
"jasmine-core": "^3.5.0",
|
||||
"jasmine-spec-reporter": "^4.2.1",
|
||||
"karma": "^4.4.1",
|
||||
"karma-chrome-launcher": "^3.1.0",
|
||||
"karma-coverage-istanbul-reporter": "^2.1.1",
|
||||
"karma-jasmine": "^3.0.3",
|
||||
"karma-jasmine-html-reporter": "^1.5.4",
|
||||
"protractor": "^5.4.4",
|
||||
"ts-loader": "^6.2.2",
|
||||
"ts-node": "^8.3.0",
|
||||
"tslint": "^6.1.3",
|
||||
"typescript": "^3.8.3",
|
||||
"webpack-cli": "^3.3.12"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons>
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>
|
||||
Alert test
|
||||
</ion-title>
|
||||
|
||||
@@ -35,9 +35,11 @@
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Input (required)</ion-label>
|
||||
<ion-input formControlName="input" class="required"></ion-input>
|
||||
<ion-input formControlName="input" class="required" id="touched-input-test"></ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-button id="input-touched" (click)="setTouched()">Set Input Touched</ion-button>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Input</ion-label>
|
||||
<ion-input formControlName="input2"></ion-input>
|
||||
|
||||
@@ -25,6 +25,11 @@ export class FormComponent {
|
||||
});
|
||||
}
|
||||
|
||||
setTouched() {
|
||||
const formControl = this.profileForm.get('input');
|
||||
formControl.markAsTouched();
|
||||
}
|
||||
|
||||
onSubmit(_ev) {
|
||||
this.submitted = 'true';
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-item routerLink="/alerts">
|
||||
<ion-item routerLink="/alerts" [routerAnimation]="routerAnimation">
|
||||
<ion-label>
|
||||
Alerts test
|
||||
</ion-label>
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { AnimationBuilder, AnimationController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home-page',
|
||||
templateUrl: './home-page.component.html',
|
||||
})
|
||||
export class HomePageComponent {
|
||||
routerAnimation: AnimationBuilder = (_, opts) => {
|
||||
const { direction, enteringEl, leavingEl } = opts;
|
||||
const animation = this.animationCtrl.create().duration(500).easing('ease-out');
|
||||
const enteringAnimation = this.animationCtrl.create().addElement(enteringEl).beforeRemoveClass(['ion-page-invisible']);
|
||||
const leavingAnimation = this.animationCtrl.create().addElement(leavingEl).beforeRemoveClass(['ion-page-invisible']);
|
||||
if (direction === 'back') {
|
||||
enteringAnimation.fromTo('transform', 'translateX(-100%)', 'translateX(0%)');
|
||||
leavingAnimation.fromTo('transform', 'translateX(0%)', 'translateX(100%)');
|
||||
} else {
|
||||
enteringAnimation.fromTo('transform', 'translateX(100%)', 'translateX(0%)');
|
||||
leavingAnimation.fromTo('transform', 'translateX(0%)', 'translateX(-100%)');
|
||||
}
|
||||
return animation.addAnimation([enteringAnimation, leavingAnimation]);
|
||||
};
|
||||
|
||||
constructor(private animationCtrl: AnimationController) {}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package-lock=false
|
||||
@@ -1,121 +0,0 @@
|
||||
# Contribution guide
|
||||
|
||||
## Contribute to Ionic Core
|
||||
|
||||
Ionic Core is the fundation of Ionic v4. It's based in [Stencil](https://stenciljs.com) and consist in a set of web components a long of JS and CSS utils.
|
||||
|
||||
|
||||
### Installing dependencies
|
||||
|
||||
Before you can build ionic, we assume the following list of software is already installed in your system
|
||||
|
||||
- Git
|
||||
- Node 8 or higher
|
||||
- Npm 6.0 or higher
|
||||
|
||||
|
||||
### Fork repository
|
||||
|
||||
In order to contributo to Ionic, you must have a github account so you can push code and create a new Pull Request (PR).
|
||||
|
||||
Once you are all setup, following the Github's guide of how to fork a repository: https://guides.github.com/activities/forking/
|
||||
|
||||
|
||||
### Build Ionic Core
|
||||
|
||||
```bash
|
||||
# Clone your Github repository:
|
||||
git clone https://github.com/<github username>/ionic.git
|
||||
|
||||
# Go to the core directory:
|
||||
cd ionic/core
|
||||
|
||||
# Install npm dependencies
|
||||
npm install
|
||||
|
||||
# Run Ionic dev server
|
||||
npm start
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
|
||||
#### 1. Run Dev Server
|
||||
|
||||
```bash
|
||||
# Move to the core folder
|
||||
cd core
|
||||
|
||||
# Run dev server
|
||||
npm start
|
||||
```
|
||||
|
||||
You should be able to navigate to `http://localhost:3333` which will look like a file browser.
|
||||
|
||||
E2E tests are located inside the `src/components` folder, in the following way: `http://localhost:3333/src/components/{COMPONENT}/test/`
|
||||
|
||||
|
||||
**Path examples:**
|
||||
|
||||
- ActionSheet basic test: http://localhost:3333/src/components/action-sheet/test/basic
|
||||
- Nav basic test: http://localhost:3333/src/components/nav/test/basic
|
||||
- Button basic test:
|
||||
http://localhost:3333/src/components/button/test/basic
|
||||
|
||||
|
||||
**IMPORTANT**
|
||||
|
||||
Leave the dev server running in the background while you make changes. The dev server listen for changes and automatically recompile Ionic for you.
|
||||
|
||||
|
||||
|
||||
#### 2. Open `core` folder in your IDE
|
||||
|
||||
Components implementations live inside the `core/src/components` folder.
|
||||
|
||||
You can find each ionic component inside their directory.
|
||||
|
||||
|
||||
#### 3. Run test suite
|
||||
|
||||
Before commiting your changes make sure tests are passing:
|
||||
|
||||
```
|
||||
npm run validate
|
||||
```
|
||||
|
||||
#### 4. Create a branch and commit
|
||||
|
||||
```bash
|
||||
# Create a git branch
|
||||
git checkout -b my-improvement
|
||||
|
||||
# Add changes
|
||||
git add .
|
||||
|
||||
# Create commit
|
||||
git commit -m "fix(component): message"
|
||||
```
|
||||
|
||||
Create a PR:
|
||||
https://guides.github.com/activities/forking/
|
||||
|
||||
|
||||
### Summary
|
||||
|
||||
```bash
|
||||
# Clone repo
|
||||
git clone git@github.com:ionic-team/ionic.git
|
||||
|
||||
# Move to ionic/core folder
|
||||
cd ionic/core
|
||||
|
||||
# Install npm dependencies
|
||||
npm i
|
||||
|
||||
# Run dev server
|
||||
npm start
|
||||
|
||||
# Run test suite
|
||||
npm run validate
|
||||
```
|
||||
|
||||
@@ -40,6 +40,24 @@ The `@ionic/core` package can by used in simple HTML, or by vanilla JavaScript w
|
||||
* [@ionic/angular](https://www.npmjs.com/package/@ionic/angular)
|
||||
|
||||
|
||||
## Custom Elements Build (Experimental)
|
||||
|
||||
In addition to the default, self lazy-loading components built by Stencil, this package also comes with each component exported as a stand-alone custom element within `@ionic/core/components`. Each component extends `HTMLElement`, and does not lazy-load itself. Instead, this package is useful for projects already using a bundler such as Webpack or Rollup. While all components are available to be imported, the custom elements build also ensures bundlers only import what's used, and tree-shakes any unused components.
|
||||
|
||||
Below is an example of importing `ion-toggle`, and initializing Ionic so it's able to correctly load the "mode", such as Material Design or iOS. Additionally, the `initialize({...})` function can receive the Ionic config.
|
||||
|
||||
```typescript
|
||||
import { IonBadge } from "@ionic/core/components/ion-badge";
|
||||
import { initialize } from "@ionic/core/components";
|
||||
|
||||
initialize();
|
||||
|
||||
customElements.define("ion-badge", IonBadge);
|
||||
```
|
||||
|
||||
Notice how `IonBadge` is imported from `@ionic/core/components/ion-badge` rather than just `@ionic/core/components`. Additionally, the `initialize` function is imported from `@ionic/core/components` rather than `@ionic/core`. All of this helps to ensure bundlers do not pull in more code than is needed.
|
||||
|
||||
|
||||
## How to contribute
|
||||
|
||||
[Check out the CONTRIBUTE guide](CONTRIBUTING.md)
|
||||
@@ -47,7 +65,6 @@ The `@ionic/core` package can by used in simple HTML, or by vanilla JavaScript w
|
||||
## Related
|
||||
|
||||
* [Ionic Documentation](https://ionicframework.com/docs/)
|
||||
* [Ionic Worldwide Slack](http://ionicworldwide.herokuapp.com/)
|
||||
* [Ionic Forum](https://forum.ionicframework.com/)
|
||||
* [Ionicons](http://ionicons.com/)
|
||||
* [Stencil](https://stenciljs.com/)
|
||||
|
||||
61
core/api.txt
61
core/api.txt
@@ -85,6 +85,7 @@ ion-back-button,prop,defaultHref,string | undefined,undefined,false,false
|
||||
ion-back-button,prop,disabled,boolean,false,false,true
|
||||
ion-back-button,prop,icon,null | string | undefined,undefined,false,false
|
||||
ion-back-button,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-back-button,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-back-button,prop,text,null | string | undefined,undefined,false,false
|
||||
ion-back-button,prop,type,"button" | "reset" | "submit",'button',false,false
|
||||
ion-back-button,css-prop,--background
|
||||
@@ -119,6 +120,9 @@ ion-back-button,css-prop,--padding-start
|
||||
ion-back-button,css-prop,--padding-top
|
||||
ion-back-button,css-prop,--ripple-color
|
||||
ion-back-button,css-prop,--transition
|
||||
ion-back-button,part,icon
|
||||
ion-back-button,part,native
|
||||
ion-back-button,part,text
|
||||
|
||||
ion-backdrop,shadow
|
||||
ion-backdrop,prop,stopPropagation,boolean,true,false,false
|
||||
@@ -146,6 +150,7 @@ ion-button,prop,fill,"clear" | "default" | "outline" | "solid" | undefined,undef
|
||||
ion-button,prop,href,string | undefined,undefined,false,false
|
||||
ion-button,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-button,prop,rel,string | undefined,undefined,false,false
|
||||
ion-button,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-button,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
|
||||
ion-button,prop,shape,"round" | undefined,undefined,false,true
|
||||
ion-button,prop,size,"default" | "large" | "small" | undefined,undefined,false,true
|
||||
@@ -177,6 +182,7 @@ ion-button,css-prop,--padding-start
|
||||
ion-button,css-prop,--padding-top
|
||||
ion-button,css-prop,--ripple-color
|
||||
ion-button,css-prop,--transition
|
||||
ion-button,part,native
|
||||
|
||||
ion-buttons,scoped
|
||||
ion-buttons,prop,collapse,boolean,false,false,false
|
||||
@@ -189,11 +195,13 @@ ion-card,prop,download,string | undefined,undefined,false,false
|
||||
ion-card,prop,href,string | undefined,undefined,false,false
|
||||
ion-card,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-card,prop,rel,string | undefined,undefined,false,false
|
||||
ion-card,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-card,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
|
||||
ion-card,prop,target,string | undefined,undefined,false,false
|
||||
ion-card,prop,type,"button" | "reset" | "submit",'button',false,false
|
||||
ion-card,css-prop,--background
|
||||
ion-card,css-prop,--color
|
||||
ion-card,part,native
|
||||
|
||||
ion-card-content,none
|
||||
ion-card-content,prop,mode,"ios" | "md",undefined,false,false
|
||||
@@ -240,6 +248,7 @@ ion-checkbox,part,mark
|
||||
|
||||
ion-chip,shadow
|
||||
ion-chip,prop,color,string | undefined,undefined,false,false
|
||||
ion-chip,prop,disabled,boolean,false,false,false
|
||||
ion-chip,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-chip,prop,outline,boolean,false,false,false
|
||||
ion-chip,css-prop,--background
|
||||
@@ -288,7 +297,7 @@ ion-content,prop,scrollY,boolean,true,false,false
|
||||
ion-content,method,getScrollElement,getScrollElement() => Promise<HTMLElement>
|
||||
ion-content,method,scrollByPoint,scrollByPoint(x: number, y: number, duration: number) => Promise<void>
|
||||
ion-content,method,scrollToBottom,scrollToBottom(duration?: number) => Promise<void>
|
||||
ion-content,method,scrollToPoint,scrollToPoint(x: number | null | undefined, y: number | null | undefined, duration?: number) => Promise<void>
|
||||
ion-content,method,scrollToPoint,scrollToPoint(x: number | undefined | null, y: number | undefined | null, duration?: number) => Promise<void>
|
||||
ion-content,method,scrollToTop,scrollToTop(duration?: number) => Promise<void>
|
||||
ion-content,event,ionScroll,ScrollDetail,true
|
||||
ion-content,event,ionScrollEnd,ScrollBaseDetail,true
|
||||
@@ -324,7 +333,7 @@ ion-datetime,prop,monthShortNames,string | string[] | undefined,undefined,false,
|
||||
ion-datetime,prop,monthValues,number | number[] | string | undefined,undefined,false,false
|
||||
ion-datetime,prop,name,string,this.inputId,false,false
|
||||
ion-datetime,prop,pickerFormat,string | undefined,undefined,false,false
|
||||
ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: "ios" | "md" | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
|
||||
ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: Mode | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
|
||||
ion-datetime,prop,placeholder,null | string | undefined,undefined,false,false
|
||||
ion-datetime,prop,readonly,boolean,false,false,false
|
||||
ion-datetime,prop,value,null | string | undefined,undefined,false,false
|
||||
@@ -351,12 +360,14 @@ ion-fab,method,close,close() => Promise<void>
|
||||
|
||||
ion-fab-button,shadow
|
||||
ion-fab-button,prop,activated,boolean,false,false,false
|
||||
ion-fab-button,prop,closeIcon,string,'close',false,false
|
||||
ion-fab-button,prop,color,string | undefined,undefined,false,false
|
||||
ion-fab-button,prop,disabled,boolean,false,false,false
|
||||
ion-fab-button,prop,download,string | undefined,undefined,false,false
|
||||
ion-fab-button,prop,href,string | undefined,undefined,false,false
|
||||
ion-fab-button,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-fab-button,prop,rel,string | undefined,undefined,false,false
|
||||
ion-fab-button,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-fab-button,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
|
||||
ion-fab-button,prop,show,boolean,false,false,false
|
||||
ion-fab-button,prop,size,"small" | undefined,undefined,false,false
|
||||
@@ -377,6 +388,7 @@ ion-fab-button,css-prop,--border-radius
|
||||
ion-fab-button,css-prop,--border-style
|
||||
ion-fab-button,css-prop,--border-width
|
||||
ion-fab-button,css-prop,--box-shadow
|
||||
ion-fab-button,css-prop,--close-icon-font-size
|
||||
ion-fab-button,css-prop,--color
|
||||
ion-fab-button,css-prop,--color-activated
|
||||
ion-fab-button,css-prop,--color-focused
|
||||
@@ -387,6 +399,8 @@ ion-fab-button,css-prop,--padding-start
|
||||
ion-fab-button,css-prop,--padding-top
|
||||
ion-fab-button,css-prop,--ripple-color
|
||||
ion-fab-button,css-prop,--transition
|
||||
ion-fab-button,part,close-icon
|
||||
ion-fab-button,part,native
|
||||
|
||||
ion-fab-list,shadow
|
||||
ion-fab-list,prop,activated,boolean,false,false,false
|
||||
@@ -462,13 +476,13 @@ ion-input,prop,required,boolean,false,false,false
|
||||
ion-input,prop,size,number | undefined,undefined,false,false
|
||||
ion-input,prop,spellcheck,boolean,false,false,false
|
||||
ion-input,prop,step,string | undefined,undefined,false,false
|
||||
ion-input,prop,type,"date" | "email" | "number" | "password" | "search" | "tel" | "text" | "time" | "url",'text',false,false
|
||||
ion-input,prop,type,"date" | "datetime-local" | "email" | "month" | "number" | "password" | "search" | "tel" | "text" | "time" | "url" | "week",'text',false,false
|
||||
ion-input,prop,value,null | number | string | undefined,'',false,false
|
||||
ion-input,method,getInputElement,getInputElement() => Promise<HTMLInputElement>
|
||||
ion-input,method,setFocus,setFocus() => Promise<void>
|
||||
ion-input,event,ionBlur,void,true
|
||||
ion-input,event,ionBlur,FocusEvent,true
|
||||
ion-input,event,ionChange,InputChangeEventDetail,true
|
||||
ion-input,event,ionFocus,void,true
|
||||
ion-input,event,ionFocus,FocusEvent,true
|
||||
ion-input,event,ionInput,KeyboardEvent,true
|
||||
ion-input,css-prop,--background
|
||||
ion-input,css-prop,--color
|
||||
@@ -492,6 +506,7 @@ ion-item,prop,href,string | undefined,undefined,false,false
|
||||
ion-item,prop,lines,"full" | "inset" | "none" | undefined,undefined,false,false
|
||||
ion-item,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-item,prop,rel,string | undefined,undefined,false,false
|
||||
ion-item,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-item,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
|
||||
ion-item,prop,target,string | undefined,undefined,false,false
|
||||
ion-item,prop,type,"button" | "reset" | "submit",'button',false,false
|
||||
@@ -531,6 +546,7 @@ ion-item,css-prop,--padding-top
|
||||
ion-item,css-prop,--ripple-color
|
||||
ion-item,css-prop,--transition
|
||||
ion-item,part,detail-icon
|
||||
ion-item,part,native
|
||||
|
||||
ion-item-divider,shadow
|
||||
ion-item-divider,prop,color,string | undefined,undefined,false,false
|
||||
@@ -561,6 +577,7 @@ ion-item-option,prop,target,string | undefined,undefined,false,false
|
||||
ion-item-option,prop,type,"button" | "reset" | "submit",'button',false,false
|
||||
ion-item-option,css-prop,--background
|
||||
ion-item-option,css-prop,--color
|
||||
ion-item-option,part,native
|
||||
|
||||
ion-item-options,none
|
||||
ion-item-options,prop,side,"end" | "start",'end',false,false
|
||||
@@ -572,7 +589,7 @@ ion-item-sliding,method,close,close() => Promise<void>
|
||||
ion-item-sliding,method,closeOpened,closeOpened() => Promise<boolean>
|
||||
ion-item-sliding,method,getOpenAmount,getOpenAmount() => Promise<number>
|
||||
ion-item-sliding,method,getSlidingRatio,getSlidingRatio() => Promise<number>
|
||||
ion-item-sliding,method,open,open(side: "start" | "end" | undefined) => Promise<void>
|
||||
ion-item-sliding,method,open,open(side: Side | undefined) => Promise<void>
|
||||
ion-item-sliding,event,ionDrag,any,true
|
||||
|
||||
ion-label,scoped
|
||||
@@ -662,6 +679,7 @@ ion-menu-button,prop,autoHide,boolean,true,false,false
|
||||
ion-menu-button,prop,color,string | undefined,undefined,false,false
|
||||
ion-menu-button,prop,disabled,boolean,false,false,false
|
||||
ion-menu-button,prop,menu,string | undefined,undefined,false,false
|
||||
ion-menu-button,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-menu-button,prop,type,"button" | "reset" | "submit",'button',false,false
|
||||
ion-menu-button,css-prop,--background
|
||||
ion-menu-button,css-prop,--background-focused
|
||||
@@ -676,6 +694,8 @@ ion-menu-button,css-prop,--padding-bottom
|
||||
ion-menu-button,css-prop,--padding-end
|
||||
ion-menu-button,css-prop,--padding-start
|
||||
ion-menu-button,css-prop,--padding-top
|
||||
ion-menu-button,part,icon
|
||||
ion-menu-button,part,native
|
||||
|
||||
ion-menu-toggle,shadow
|
||||
ion-menu-toggle,prop,autoHide,boolean,true,false,false
|
||||
@@ -726,13 +746,13 @@ ion-nav,method,getActive,getActive() => Promise<ViewController | undefined>
|
||||
ion-nav,method,getByIndex,getByIndex(index: number) => Promise<ViewController | undefined>
|
||||
ion-nav,method,getPrevious,getPrevious(view?: ViewController | undefined) => Promise<ViewController | undefined>
|
||||
ion-nav,method,insert,insert<T extends NavComponent>(insertIndex: number, component: T, componentProps?: ComponentProps<T> | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,insertPages,insertPages(insertIndex: number, insertComponents: NavComponent[], opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,insertPages,insertPages(insertIndex: number, insertComponents: NavComponent[] | NavComponentWithProps[], opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,pop,pop(opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,popTo,popTo(indexOrViewCtrl: number | ViewController, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,popToRoot,popToRoot(opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,push,push<T extends NavComponent>(component: T, componentProps?: ComponentProps<T> | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,removeIndex,removeIndex(startIndex: number, removeCount?: number, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,setPages,setPages(views: any[], opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,setPages,setPages(views: NavComponent[] | NavComponentWithProps[], opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,method,setRoot,setRoot<T extends NavComponent>(component: T, componentProps?: ComponentProps<T> | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>
|
||||
ion-nav,event,ionNavDidChange,void,false
|
||||
ion-nav,event,ionNavWillChange,void,false
|
||||
@@ -740,6 +760,7 @@ ion-nav,event,ionNavWillChange,void,false
|
||||
ion-nav-link,none
|
||||
ion-nav-link,prop,component,Function | HTMLElement | ViewController | null | string | undefined,undefined,false,false
|
||||
ion-nav-link,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
|
||||
ion-nav-link,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-nav-link,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
|
||||
|
||||
ion-note,shadow
|
||||
@@ -823,6 +844,9 @@ ion-progress-bar,prop,value,number,0,false,false
|
||||
ion-progress-bar,css-prop,--background
|
||||
ion-progress-bar,css-prop,--buffer-background
|
||||
ion-progress-bar,css-prop,--progress-background
|
||||
ion-progress-bar,part,progress
|
||||
ion-progress-bar,part,stream
|
||||
ion-progress-bar,part,track
|
||||
|
||||
ion-radio,shadow
|
||||
ion-radio,prop,color,string | undefined,undefined,false,false
|
||||
@@ -913,6 +937,8 @@ ion-ripple-effect,prop,type,"bounded" | "unbounded",'bounded',false,false
|
||||
ion-ripple-effect,method,addRipple,addRipple(x: number, y: number) => Promise<() => void>
|
||||
|
||||
ion-route,none
|
||||
ion-route,prop,beforeEnter,(() => NavigationHookResult | Promise<NavigationHookResult>) | undefined,undefined,false,false
|
||||
ion-route,prop,beforeLeave,(() => NavigationHookResult | Promise<NavigationHookResult>) | undefined,undefined,false,false
|
||||
ion-route,prop,component,string,undefined,true,false
|
||||
ion-route,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
|
||||
ion-route,prop,url,string,'',false,false
|
||||
@@ -927,7 +953,7 @@ ion-router,none
|
||||
ion-router,prop,root,string,'/',false,false
|
||||
ion-router,prop,useHash,boolean,true,false,false
|
||||
ion-router,method,back,back() => Promise<void>
|
||||
ion-router,method,push,push(url: string, direction?: RouterDirection) => Promise<boolean>
|
||||
ion-router,method,push,push(url: string, direction?: RouterDirection, animation?: AnimationBuilder | undefined) => Promise<boolean>
|
||||
ion-router,event,ionRouteDidChange,RouterEventDetail,true
|
||||
ion-router,event,ionRouteWillChange,RouterEventDetail,true
|
||||
|
||||
@@ -935,6 +961,7 @@ ion-router-link,shadow
|
||||
ion-router-link,prop,color,string | undefined,undefined,false,false
|
||||
ion-router-link,prop,href,string | undefined,undefined,false,false
|
||||
ion-router-link,prop,rel,string | undefined,undefined,false,false
|
||||
ion-router-link,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-router-link,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
|
||||
ion-router-link,prop,target,string | undefined,undefined,false,false
|
||||
ion-router-link,css-prop,--background
|
||||
@@ -963,6 +990,7 @@ ion-searchbar,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-searchbar,prop,placeholder,string,'Search',false,false
|
||||
ion-searchbar,prop,searchIcon,string | undefined,undefined,false,false
|
||||
ion-searchbar,prop,showCancelButton,"always" | "focus" | "never",'never',false,false
|
||||
ion-searchbar,prop,showClearButton,"always" | "focus" | "never",'focus',false,false
|
||||
ion-searchbar,prop,spellcheck,boolean,false,false,false
|
||||
ion-searchbar,prop,type,"email" | "number" | "password" | "search" | "tel" | "text" | "url",'search',false,false
|
||||
ion-searchbar,prop,value,null | string | undefined,'',false,false
|
||||
@@ -991,6 +1019,7 @@ ion-segment,prop,color,string | undefined,undefined,false,false
|
||||
ion-segment,prop,disabled,boolean,false,false,false
|
||||
ion-segment,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-segment,prop,scrollable,boolean,false,false,false
|
||||
ion-segment,prop,swipeGesture,boolean,true,false,false
|
||||
ion-segment,prop,value,null | string | undefined,undefined,false,false
|
||||
ion-segment,event,ionChange,SegmentChangeEventDetail,true
|
||||
ion-segment,css-prop,--background
|
||||
@@ -1029,6 +1058,9 @@ ion-segment-button,css-prop,--padding-end
|
||||
ion-segment-button,css-prop,--padding-start
|
||||
ion-segment-button,css-prop,--padding-top
|
||||
ion-segment-button,css-prop,--transition
|
||||
ion-segment-button,part,indicator
|
||||
ion-segment-button,part,indicator-background
|
||||
ion-segment-button,part,native
|
||||
|
||||
ion-select,shadow
|
||||
ion-select,prop,cancelText,string,'Cancel',false,false
|
||||
@@ -1046,7 +1078,7 @@ ion-select,prop,value,any,undefined,false,false
|
||||
ion-select,method,open,open(event?: UIEvent | undefined) => Promise<any>
|
||||
ion-select,event,ionBlur,void,true
|
||||
ion-select,event,ionCancel,void,true
|
||||
ion-select,event,ionChange,SelectChangeEventDetail,true
|
||||
ion-select,event,ionChange,SelectChangeEventDetail<any>,true
|
||||
ion-select,event,ionFocus,void,true
|
||||
ion-select,css-prop,--padding-bottom
|
||||
ion-select,css-prop,--padding-end
|
||||
@@ -1166,6 +1198,7 @@ ion-tab-button,css-prop,--padding-end
|
||||
ion-tab-button,css-prop,--padding-start
|
||||
ion-tab-button,css-prop,--padding-top
|
||||
ion-tab-button,css-prop,--ripple-color
|
||||
ion-tab-button,part,native
|
||||
|
||||
ion-tabs,shadow
|
||||
ion-tabs,method,getSelected,getSelected() => Promise<string | undefined>
|
||||
@@ -1202,9 +1235,9 @@ ion-textarea,prop,value,null | string | undefined,'',false,false
|
||||
ion-textarea,prop,wrap,"hard" | "off" | "soft" | undefined,undefined,false,false
|
||||
ion-textarea,method,getInputElement,getInputElement() => Promise<HTMLTextAreaElement>
|
||||
ion-textarea,method,setFocus,setFocus() => Promise<void>
|
||||
ion-textarea,event,ionBlur,void,true
|
||||
ion-textarea,event,ionBlur,FocusEvent,true
|
||||
ion-textarea,event,ionChange,TextareaChangeEventDetail,true
|
||||
ion-textarea,event,ionFocus,void,true
|
||||
ion-textarea,event,ionFocus,FocusEvent,true
|
||||
ion-textarea,event,ionInput,KeyboardEvent,true
|
||||
ion-textarea,css-prop,--background
|
||||
ion-textarea,css-prop,--border-radius
|
||||
@@ -1266,6 +1299,10 @@ ion-toast,css-prop,--min-width
|
||||
ion-toast,css-prop,--start
|
||||
ion-toast,css-prop,--white-space
|
||||
ion-toast,css-prop,--width
|
||||
ion-toast,part,button
|
||||
ion-toast,part,container
|
||||
ion-toast,part,header
|
||||
ion-toast,part,message
|
||||
|
||||
ion-toggle,shadow
|
||||
ion-toggle,prop,checked,boolean,false,false,false
|
||||
|
||||
25078
core/package-lock.json
generated
Normal file
25078
core/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "5.1.1",
|
||||
"version": "5.6.3",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -15,53 +15,57 @@
|
||||
"progressive web app",
|
||||
"pwa"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs",
|
||||
"es2015": "dist/esm/index.mjs",
|
||||
"es2017": "dist/esm/index.mjs",
|
||||
"jsnext:main": "dist/esm/index.mjs",
|
||||
"main": "dist/index.cjs.js",
|
||||
"module": "dist/index.js",
|
||||
"es2015": "dist/esm/index.js",
|
||||
"es2017": "dist/esm/index.js",
|
||||
"jsnext:main": "dist/esm/index.js",
|
||||
"collection:main": "dist/collection/index.js",
|
||||
"collection": "dist/collection/collection-manifest.json",
|
||||
"types": "dist/types/interface.d.ts",
|
||||
"files": [
|
||||
"dist/",
|
||||
"components/",
|
||||
"css/",
|
||||
"dist/",
|
||||
"hydrate/",
|
||||
"loader/"
|
||||
],
|
||||
"dependencies": {
|
||||
"ionicons": "^5.0.1",
|
||||
"tslib": "^1.10.0"
|
||||
"@stencil/core": "^2.4.0",
|
||||
"ionicons": "^5.5.1",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@stencil/core": "1.13.0",
|
||||
"@stencil/sass": "1.3.1",
|
||||
"@types/jest": "24.9.1",
|
||||
"@types/node": "12.12.3",
|
||||
"@types/puppeteer": "1.19.1",
|
||||
"@types/swiper": "5.3.1",
|
||||
"aws-sdk": "^2.497.0",
|
||||
"@jest/core": "^26.6.3",
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/sass": "1.3.2",
|
||||
"@stencil/vue-output-target": "^0.4.1",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "^14.6.0",
|
||||
"@types/puppeteer": "5.4.3",
|
||||
"@types/swiper": "5.4.0",
|
||||
"aws-sdk": "^2.738.0",
|
||||
"clean-css-cli": "^4.1.11",
|
||||
"domino": "^2.1.3",
|
||||
"fs-extra": "^8.0.1",
|
||||
"jest": "24.9.0",
|
||||
"jest-cli": "24.9.0",
|
||||
"np": "^5.0.3",
|
||||
"domino": "^2.1.6",
|
||||
"fs-extra": "^9.0.1",
|
||||
"jest": "^26.4.1",
|
||||
"jest-cli": "^26.4.1",
|
||||
"np": "^6.4.0",
|
||||
"pixelmatch": "4.0.2",
|
||||
"puppeteer": "1.20.0",
|
||||
"rollup": "1.32.0",
|
||||
"rollup-plugin-node-resolve": "5.2.0",
|
||||
"rollup-plugin-virtual": "^1.0.1",
|
||||
"sass": "^1.22.9",
|
||||
"stylelint": "10.1.0",
|
||||
"stylelint-order": "3.0.1",
|
||||
"puppeteer": "^7.0.1",
|
||||
"rollup": "^2.26.4",
|
||||
"sass": "^1.26.10",
|
||||
"stylelint": "^13.6.1",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"swiper": "5.4.1",
|
||||
"tslint": "^5.10.0",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-ionic-rules": "0.0.21",
|
||||
"tslint-react": "^3.6.0"
|
||||
"tslint-react": "^5.0.0",
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run clean && npm run build.css && npm run build.vendor && stencil build --docs && npm run cdnloader",
|
||||
"build": "npm run clean && npm run build.css && npm run build.vendor && stencil build --docs --es5 --docs-json dist/docs.json && npm run cdnloader",
|
||||
"build.vendor": "rollup --config ./scripts/swiper.rollup.config.js",
|
||||
"build.css": "npm run css.sass && npm run css.minify",
|
||||
"build.debug": "npm run clean && stencil build --debug",
|
||||
@@ -73,7 +77,7 @@
|
||||
"css.sass": "sass src/css:./css",
|
||||
"lint": "npm run lint.ts && npm run lint.sass",
|
||||
"lint.fix": "npm run lint.ts.fix && npm run lint.sass.fix",
|
||||
"lint.sass": "stylelint 'src/**/*.scss'",
|
||||
"lint.sass": "stylelint \"src/**/*.scss\"",
|
||||
"lint.sass.fix": "npm run lint.sass -- --fix",
|
||||
"lint.ts": "tslint --project .",
|
||||
"lint.ts.fix": "tslint --project . --fix",
|
||||
@@ -87,7 +91,7 @@
|
||||
"test.screenshot": "stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/dev.js",
|
||||
"test.screenshot.ci": "stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci",
|
||||
"test.watch": "jest --watch --no-cache",
|
||||
"test.treeshake": "node scripts/treeshaking.js dist/index.mjs",
|
||||
"test.treeshake": "node scripts/treeshaking.js dist/index.js",
|
||||
"validate": "npm run lint && npm run test && npm run build && npm run test.treeshake"
|
||||
},
|
||||
"author": "Ionic Team",
|
||||
|
||||
2
core/scripts/custom-elements/custom-elements.d.ts
vendored
Normal file
2
core/scripts/custom-elements/custom-elements.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './index';
|
||||
export * from '../dist/types/interface';
|
||||
9
core/scripts/custom-elements/package.json
Normal file
9
core/scripts/custom-elements/package.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@ionic/core/components",
|
||||
"version": "0.0.0",
|
||||
"description": "Ionic Components exported as custom elements, extending HTMLElement.",
|
||||
"main": "./index.js",
|
||||
"types": "./custom-elements.d.ts",
|
||||
"private": true,
|
||||
"sideEffects": false
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
|
||||
export default {
|
||||
input: 'src/components/slides/swiper/swiper.js',
|
||||
|
||||
@@ -1,54 +1,51 @@
|
||||
|
||||
const path = require('path');
|
||||
const { rollup } = require('rollup');
|
||||
const virtual = require('rollup-plugin-virtual');
|
||||
const virtual = require('@rollup/plugin-virtual');
|
||||
const fs = require('fs');
|
||||
|
||||
function main() {
|
||||
const input = process.argv[2] || get_input();
|
||||
check(input).then(result => {
|
||||
const relative = path.relative(process.cwd(), input);
|
||||
async function main() {
|
||||
const input = process.argv[2] || getMainEntry();
|
||||
const result = await check(input);
|
||||
const relative = path.relative(process.cwd(), input);
|
||||
|
||||
if (result.shaken) {
|
||||
console.error(`Success! ${relative} is fully tree-shakeable`);
|
||||
} else {
|
||||
error(`Failed to tree-shake ${relative}`);
|
||||
}
|
||||
});
|
||||
if (result.shaken) {
|
||||
console.error(`Success! ${relative} is fully tree-shakeable`);
|
||||
} else {
|
||||
error(`Failed to tree-shake ${relative}`);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function error(msg) {
|
||||
console.error(msg);
|
||||
process.exit(1);
|
||||
console.error(msg);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function get_input() {
|
||||
function getMainEntry() {
|
||||
if (!fs.existsSync('package.json')) {
|
||||
error(`Could not find package.json`);
|
||||
}
|
||||
|
||||
const pkg = JSON.parse(fs.readFileSync('package.json'), 'utf-8');
|
||||
const pkg = JSON.parse(fs.readFileSync('package.json'), 'utf-8');
|
||||
|
||||
const unresolved = pkg.module || pkg.main || 'index';
|
||||
const resolved = resolve(unresolved);
|
||||
const unresolved = pkg.module || pkg.main || 'index';
|
||||
const resolved = resolve(unresolved);
|
||||
|
||||
if (!resolved) {
|
||||
error(`Could not resolve entry point`);
|
||||
}
|
||||
if (!resolved) {
|
||||
error(`Could not resolve entry point`);
|
||||
}
|
||||
|
||||
return resolved;
|
||||
return resolved;
|
||||
}
|
||||
|
||||
function resolve(file) {
|
||||
if (is_directory(file)) {
|
||||
return if_exists(`${file}/index.mjs`) || if_exists(`${file}/index.js`);
|
||||
if (isDirectory(file)) {
|
||||
return ifExists(`${file}/index.cjs.js`) || ifExists(`${file}/index.js`);
|
||||
}
|
||||
|
||||
return if_exists(file) || if_exists(`${file}.mjs`) || if_exists(`${file}.js`);
|
||||
return ifExists(file) || ifExists(`${file}.cjs.js`) || ifExists(`${file}.js`);
|
||||
}
|
||||
|
||||
function is_directory(file) {
|
||||
function isDirectory(file) {
|
||||
try {
|
||||
const stats = fs.statSync(file);
|
||||
return stats.isDirectory();
|
||||
@@ -57,33 +54,41 @@ function is_directory(file) {
|
||||
}
|
||||
}
|
||||
|
||||
function if_exists(file) {
|
||||
return fs.existsSync(file) ? file : null;
|
||||
function ifExists(file) {
|
||||
return fs.existsSync(file) ? file : null;
|
||||
}
|
||||
|
||||
const check = input => {
|
||||
const resolved = path.resolve(input);
|
||||
async function check(input) {
|
||||
const resolved = path.resolve(input);
|
||||
|
||||
return rollup({
|
||||
input: '__agadoo__',
|
||||
plugins: [
|
||||
virtual({
|
||||
__agadoo__: `import ${JSON.stringify(resolved)}`,
|
||||
'tslib': '',
|
||||
})
|
||||
],
|
||||
onwarn: (warning, handle) => {
|
||||
if (warning.code !== 'EMPTY_BUNDLE') handle(warning);
|
||||
}
|
||||
}).then(bundle => bundle.generate({
|
||||
format: 'es'
|
||||
})).then(o => {
|
||||
const output = o.output;
|
||||
console.log(output);
|
||||
return {
|
||||
shaken: output.length === 1 && output[0].code.trim() === ''
|
||||
};
|
||||
});
|
||||
};
|
||||
const bundle = await rollup({
|
||||
input: '__agadoo__',
|
||||
plugins: [
|
||||
virtual({
|
||||
__agadoo__: `import ${JSON.stringify(resolved)}`,
|
||||
tslib: `
|
||||
const noop = () => {};
|
||||
export const __awaiter = noop;
|
||||
export const __extends = noop;
|
||||
export const __generator = noop;
|
||||
export const __spreadArrays = noop;
|
||||
`,
|
||||
}),
|
||||
],
|
||||
onwarn: (warning, handle) => {
|
||||
if (warning.code !== 'EMPTY_BUNDLE') handle(warning);
|
||||
},
|
||||
});
|
||||
|
||||
const o = await bundle.generate({
|
||||
format: 'es',
|
||||
});
|
||||
|
||||
const output = o.output;
|
||||
console.log(output);
|
||||
return {
|
||||
shaken: output.length === 1 && output[0].code.trim() === '',
|
||||
};
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
480
core/src/components.d.ts
vendored
480
core/src/components.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@ import { mdLeaveAnimation } from './animations/md.leave';
|
||||
export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
|
||||
presented = false;
|
||||
lastFocus?: HTMLElement;
|
||||
animation?: any;
|
||||
private wrapperEl?: HTMLElement;
|
||||
private groupEl?: HTMLElement;
|
||||
@@ -117,7 +118,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
return present(this, 'actionSheetEnter', iosEnterAnimation, mdEnterAnimation);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
connectedCallback() {
|
||||
prepareOverlay(this.el);
|
||||
}
|
||||
|
||||
@@ -197,7 +198,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUnload() {
|
||||
disconnectedCallback() {
|
||||
if (this.gesture) {
|
||||
this.gesture.destroy();
|
||||
this.gesture = undefined;
|
||||
@@ -250,7 +251,10 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
onIonBackdropTap={this.onBackdropTap}
|
||||
>
|
||||
<ion-backdrop tappable={this.backdropDismiss}/>
|
||||
<div class="action-sheet-wrapper ion-wrapper" role="dialog" ref={el => this.wrapperEl = el}>
|
||||
|
||||
<div tabindex="0"></div>
|
||||
|
||||
<div class="action-sheet-wrapper ion-overlay-wrapper" role="dialog" ref={el => this.wrapperEl = el}>
|
||||
<div class="action-sheet-container">
|
||||
<div class="action-sheet-group" ref={el => this.groupEl = el}>
|
||||
{this.header !== undefined &&
|
||||
@@ -292,6 +296,8 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div tabindex="0"></div>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -155,6 +155,59 @@ async function presentActionSheet() {
|
||||
### React
|
||||
|
||||
```tsx
|
||||
/* Using with useIonActionSheet Hook */
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
IonButton,
|
||||
IonContent,
|
||||
IonPage,
|
||||
useIonActionSheet,
|
||||
} from '@ionic/react';
|
||||
|
||||
const ActionSheetExample: React.FC = () => {
|
||||
const [present, dismiss] = useIonActionSheet();
|
||||
|
||||
return (
|
||||
<IonPage>
|
||||
<IonContent>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() =>
|
||||
present({
|
||||
buttons: [{ text: 'Ok' }, { text: 'Cancel' }],
|
||||
header: 'Action Sheet'
|
||||
})
|
||||
}
|
||||
>
|
||||
Show ActionSheet
|
||||
</IonButton>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() =>
|
||||
present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet')
|
||||
}
|
||||
>
|
||||
Show ActionSheet using params
|
||||
</IonButton>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() => {
|
||||
present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet');
|
||||
setTimeout(dismiss, 3000);
|
||||
}}
|
||||
>
|
||||
Show ActionSheet, hide after 3 seconds
|
||||
</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
/* Using with IonActionSheet Component */
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { IonActionSheet, IonContent, IonButton } from '@ionic/react';
|
||||
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';
|
||||
@@ -280,16 +333,19 @@ export class ActionSheetExample {
|
||||
|
||||
```html
|
||||
<template>
|
||||
<IonVuePage :title="'Action Sheet'">
|
||||
<ion-button @click="presentActionSheet">Show Action Sheet</ion-button>
|
||||
</IonVuePage>
|
||||
<ion-button @click="presentActionSheet">Show Action Sheet</ion-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
import { IonButton, actionSheetController } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { caretForwardCircle, close, heart, trash, share } from 'ionicons/icons';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonButton },
|
||||
methods: {
|
||||
presentActionSheet() {
|
||||
return this.$ionic.actionSheetController
|
||||
async presentActionSheet() {
|
||||
const actionSheet = await actionSheetController
|
||||
.create({
|
||||
header: 'Albums',
|
||||
cssClass: 'my-custom-class',
|
||||
@@ -297,46 +353,117 @@ export default {
|
||||
{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
icon: trash,
|
||||
handler: () => {
|
||||
console.log('Delete clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
icon: share,
|
||||
handler: () => {
|
||||
console.log('Share clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
icon: caretForwardCircle,
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Favorite',
|
||||
icon: 'heart',
|
||||
icon: heart,
|
||||
handler: () => {
|
||||
console.log('Favorite clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Cancel',
|
||||
icon: 'close',
|
||||
icon: close,
|
||||
role: 'cancel',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked')
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return actionSheet.present();
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
Developers can also use this component directly in their template:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<ion-button @click="setOpen(true)">Show Action Sheet</ion-button>
|
||||
<ion-action-sheet
|
||||
:is-open="isOpenRef"
|
||||
header="Albums"
|
||||
css-class="my-custom-class"
|
||||
:buttons="buttons"
|
||||
@onDidDismiss="setOpen(false)"
|
||||
>
|
||||
</ion-action-sheet>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonActionSheet, IonButton } from '@ionic/vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { caretForwardCircle, close, heart, trash, share } from 'ionicons/icons';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonActionSheet, IonButton },
|
||||
setup() {
|
||||
const isOpenRef = ref(false);
|
||||
const setOpen = (state: boolean) => isOpenRef.value = state;
|
||||
const buttons = [
|
||||
{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: trash,
|
||||
handler: () => {
|
||||
console.log('Delete clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Share',
|
||||
icon: share,
|
||||
handler: () => {
|
||||
console.log('Share clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: caretForwardCircle,
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Favorite',
|
||||
icon: heart,
|
||||
handler: () => {
|
||||
console.log('Favorite clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Cancel',
|
||||
icon: close,
|
||||
role: 'cancel',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked')
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return { buttons, isOpenRef, setOpen }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,40 @@
|
||||
import { testActionSheet, testActionSheetAlert, testActionSheetBackdrop } from '../test.utils';
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
const DIRECTORY = 'basic';
|
||||
const getActiveElementText = async (page) => {
|
||||
const activeElement = await page.evaluateHandle(() => document.activeElement);
|
||||
return await page.evaluate(el => el && el.textContent, activeElement);
|
||||
}
|
||||
|
||||
test('action-sheet: focus trap', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/action-sheet/test/basic?ionic:_testing=true' });
|
||||
|
||||
await page.click('#basic');
|
||||
await page.waitForSelector('#basic');
|
||||
|
||||
let actionSheet = await page.find('ion-action-sheet');
|
||||
|
||||
expect(actionSheet).not.toBe(null);
|
||||
await actionSheet.waitForVisible();
|
||||
|
||||
await page.keyboard.press('Tab');
|
||||
|
||||
const activeElementText = await getActiveElementText(page);
|
||||
expect(activeElementText).toEqual('Delete');
|
||||
|
||||
await page.keyboard.down('Shift');
|
||||
await page.keyboard.press('Tab');
|
||||
await page.keyboard.up('Shift');
|
||||
|
||||
const activeElementTextTwo = await getActiveElementText(page);
|
||||
expect(activeElementTextTwo).toEqual('Cancel');
|
||||
|
||||
await page.keyboard.press('Tab');
|
||||
|
||||
const activeElementTextThree = await getActiveElementText(page);
|
||||
expect(activeElementTextThree).toEqual('Delete');
|
||||
});
|
||||
|
||||
test('action-sheet: basic', async () => {
|
||||
await testActionSheet(DIRECTORY, '#basic');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -71,7 +71,7 @@ export const testActionSheetAlert = async (
|
||||
|
||||
const alert = await page.find('ion-alert');
|
||||
await alert.waitForVisible();
|
||||
await page.waitFor(250);
|
||||
await page.waitForTimeout(250);
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`alert open`));
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,4 +1,57 @@
|
||||
```tsx
|
||||
/* Using with useIonActionSheet Hook */
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
IonButton,
|
||||
IonContent,
|
||||
IonPage,
|
||||
useIonActionSheet,
|
||||
} from '@ionic/react';
|
||||
|
||||
const ActionSheetExample: React.FC = () => {
|
||||
const [present, dismiss] = useIonActionSheet();
|
||||
|
||||
return (
|
||||
<IonPage>
|
||||
<IonContent>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() =>
|
||||
present({
|
||||
buttons: [{ text: 'Ok' }, { text: 'Cancel' }],
|
||||
header: 'Action Sheet'
|
||||
})
|
||||
}
|
||||
>
|
||||
Show ActionSheet
|
||||
</IonButton>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() =>
|
||||
present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet')
|
||||
}
|
||||
>
|
||||
Show ActionSheet using params
|
||||
</IonButton>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() => {
|
||||
present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet');
|
||||
setTimeout(dismiss, 3000);
|
||||
}}
|
||||
>
|
||||
Show ActionSheet, hide after 3 seconds
|
||||
</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
/* Using with IonActionSheet Component */
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { IonActionSheet, IonContent, IonButton } from '@ionic/react';
|
||||
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
```html
|
||||
<template>
|
||||
<IonVuePage :title="'Action Sheet'">
|
||||
<ion-button @click="presentActionSheet">Show Action Sheet</ion-button>
|
||||
</IonVuePage>
|
||||
<ion-button @click="presentActionSheet">Show Action Sheet</ion-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
import { IonButton, actionSheetController } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { caretForwardCircle, close, heart, trash, share } from 'ionicons/icons';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonButton },
|
||||
methods: {
|
||||
presentActionSheet() {
|
||||
return this.$ionic.actionSheetController
|
||||
async presentActionSheet() {
|
||||
const actionSheet = await actionSheetController
|
||||
.create({
|
||||
header: 'Albums',
|
||||
cssClass: 'my-custom-class',
|
||||
@@ -17,45 +20,116 @@ export default {
|
||||
{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
icon: trash,
|
||||
handler: () => {
|
||||
console.log('Delete clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
icon: share,
|
||||
handler: () => {
|
||||
console.log('Share clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
icon: caretForwardCircle,
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Favorite',
|
||||
icon: 'heart',
|
||||
icon: heart,
|
||||
handler: () => {
|
||||
console.log('Favorite clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Cancel',
|
||||
icon: 'close',
|
||||
icon: close,
|
||||
role: 'cancel',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked')
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return actionSheet.present();
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
Developers can also use this component directly in their template:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<ion-button @click="setOpen(true)">Show Action Sheet</ion-button>
|
||||
<ion-action-sheet
|
||||
:is-open="isOpenRef"
|
||||
header="Albums"
|
||||
css-class="my-custom-class"
|
||||
:buttons="buttons"
|
||||
@onDidDismiss="setOpen(false)"
|
||||
>
|
||||
</ion-action-sheet>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonActionSheet, IonButton } from '@ionic/vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { caretForwardCircle, close, heart, trash, share } from 'ionicons/icons';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonActionSheet, IonButton },
|
||||
setup() {
|
||||
const isOpenRef = ref(false);
|
||||
const setOpen = (state: boolean) => isOpenRef.value = state;
|
||||
const buttons = [
|
||||
{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: trash,
|
||||
handler: () => {
|
||||
console.log('Delete clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Share',
|
||||
icon: share,
|
||||
handler: () => {
|
||||
console.log('Share clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: caretForwardCircle,
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Favorite',
|
||||
icon: heart,
|
||||
handler: () => {
|
||||
console.log('Favorite clicked')
|
||||
},
|
||||
},
|
||||
{
|
||||
text: 'Cancel',
|
||||
icon: close,
|
||||
role: 'cancel',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked')
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return { buttons, isOpenRef, setOpen }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -36,6 +36,7 @@ export interface AlertInput {
|
||||
max?: string | number;
|
||||
cssClass?: string | string[];
|
||||
attributes?: AlertInputAttributes | AlertTextareaAttributes;
|
||||
tabindex?: number;
|
||||
}
|
||||
|
||||
export interface AlertTextareaAttributes extends JSXBase.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
@include position(0, 0, 0, 0);
|
||||
|
||||
display: flex;
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, Watch, forceUpdate, h } from '@stencil/core';
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Listen, Method, Prop, Watch, forceUpdate, h } from '@stencil/core';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { AlertButton, AlertInput, AlertInputAttributes, AlertTextareaAttributes, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
@@ -34,6 +34,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
private gesture?: Gesture;
|
||||
|
||||
presented = false;
|
||||
lastFocus?: HTMLElement;
|
||||
|
||||
@Element() el!: HTMLIonAlertElement;
|
||||
|
||||
@@ -129,6 +130,58 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
@Event({ eventName: 'ionAlertDidDismiss' }) didDismiss!: EventEmitter<OverlayEventDetail>;
|
||||
|
||||
@Listen('keydown', { target: 'document' })
|
||||
onKeydown(ev: any) {
|
||||
const inputTypes = new Set(this.processedInputs.map(i => i.type));
|
||||
|
||||
// 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 (
|
||||
!inputTypes.has('radio')
|
||||
|| (ev.target && !this.el.contains(ev.target))
|
||||
|| ev.target.classList.contains('alert-button')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all radios inside of the radio group and then
|
||||
// filter out disabled radios since we need to skip those
|
||||
const query = this.el.querySelectorAll('.alert-radio') as NodeListOf<HTMLButtonElement>;
|
||||
const radios = Array.from(query).filter(radio => !radio.disabled);
|
||||
|
||||
// The focused radio is the one that shares the same id as
|
||||
// the event target
|
||||
const index = radios.findIndex(radio => radio.id === ev.target.id);
|
||||
|
||||
// We need to know what the next radio element should
|
||||
// be in order to change the focus
|
||||
let nextEl: HTMLButtonElement | undefined;
|
||||
|
||||
// If hitting arrow down or arrow right, move to the next radio
|
||||
// If we're on the last radio, move to the first radio
|
||||
if (['ArrowDown', 'ArrowRight'].includes(ev.code)) {
|
||||
nextEl = (index === radios.length - 1)
|
||||
? radios[0]
|
||||
: radios[index + 1];
|
||||
}
|
||||
|
||||
// If hitting arrow up or arrow left, move to the previous radio
|
||||
// If we're on the first radio, move to the last radio
|
||||
if (['ArrowUp', 'ArrowLeft'].includes(ev.code)) {
|
||||
nextEl = (index === 0)
|
||||
? radios[radios.length - 1]
|
||||
: radios[index - 1];
|
||||
}
|
||||
|
||||
if (nextEl && radios.includes(nextEl)) {
|
||||
const nextProcessed = this.processedInputs.find(input => input.id === nextEl?.id);
|
||||
|
||||
if (nextProcessed) {
|
||||
this.rbClick(nextProcessed);
|
||||
nextEl.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Watch('buttons')
|
||||
buttonsChanged() {
|
||||
const buttons = this.buttons;
|
||||
@@ -143,12 +196,21 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
inputsChanged() {
|
||||
const inputs = this.inputs;
|
||||
|
||||
// Get the first input that is not disabled and the checked one
|
||||
// If an enabled checked input exists, set it to be the focusable input
|
||||
// otherwise we default to focus the first input
|
||||
// This will only be used when the input is type radio
|
||||
const first = inputs.find(input => !input.disabled);
|
||||
const checked = inputs.find(input => input.checked && !input.disabled);
|
||||
const focusable = checked || first;
|
||||
|
||||
// An alert can be created with several different inputs. Radios,
|
||||
// checkboxes and inputs are all accepted, but they cannot be mixed.
|
||||
const inputTypes = new Set(inputs.map(i => i.type));
|
||||
if (inputTypes.has('checkbox') && inputTypes.has('radio')) {
|
||||
console.warn(`Alert cannot mix input types: ${(Array.from(inputTypes.values()).join('/'))}. Please see alert docs for more info.`);
|
||||
}
|
||||
|
||||
this.inputType = inputTypes.values().next().value;
|
||||
this.processedInputs = inputs.map((i, index) => ({
|
||||
type: i.type || 'text',
|
||||
@@ -164,10 +226,11 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
max: i.max,
|
||||
cssClass: i.cssClass || '',
|
||||
attributes: i.attributes || {},
|
||||
tabindex: (i.type === 'radio' && i !== focusable) ? -1 : 0
|
||||
}) as AlertInput);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
connectedCallback() {
|
||||
prepareOverlay(this.el);
|
||||
}
|
||||
|
||||
@@ -176,7 +239,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
this.buttonsChanged();
|
||||
}
|
||||
|
||||
componentDidUnload() {
|
||||
disconnectedCallback() {
|
||||
if (this.gesture) {
|
||||
this.gesture.destroy();
|
||||
this.gesture = undefined;
|
||||
@@ -240,6 +303,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
private rbClick(selectedInput: AlertInput) {
|
||||
for (const input of this.processedInputs) {
|
||||
input.checked = input === selectedInput;
|
||||
input.tabindex = input === selectedInput ? 0 : -1;
|
||||
}
|
||||
this.activeId = selectedInput.id;
|
||||
safeCall(selectedInput.handler, selectedInput);
|
||||
@@ -309,22 +373,24 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
return values;
|
||||
}
|
||||
|
||||
private renderAlertInputs(labelledBy: string | undefined) {
|
||||
private renderAlertInputs() {
|
||||
switch (this.inputType) {
|
||||
case 'checkbox': return this.renderCheckbox(labelledBy);
|
||||
case 'radio': return this.renderRadio(labelledBy);
|
||||
default: return this.renderInput(labelledBy);
|
||||
case 'checkbox': return this.renderCheckbox();
|
||||
case 'radio': return this.renderRadio();
|
||||
default: return this.renderInput();
|
||||
}
|
||||
}
|
||||
|
||||
private renderCheckbox(labelledby: string | undefined) {
|
||||
private renderCheckbox() {
|
||||
const inputs = this.processedInputs;
|
||||
const mode = getIonMode(this);
|
||||
|
||||
if (inputs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="alert-checkbox-group" aria-labelledby={labelledby}>
|
||||
<div class="alert-checkbox-group">
|
||||
{ inputs.map(i => (
|
||||
<button
|
||||
type="button"
|
||||
@@ -332,7 +398,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
aria-checked={`${i.checked}`}
|
||||
id={i.id}
|
||||
disabled={i.disabled}
|
||||
tabIndex={0}
|
||||
tabIndex={i.tabindex}
|
||||
role="checkbox"
|
||||
class={{
|
||||
...getClassMap(i.cssClass),
|
||||
@@ -358,13 +424,15 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
);
|
||||
}
|
||||
|
||||
private renderRadio(labelledby: string | undefined) {
|
||||
private renderRadio() {
|
||||
const inputs = this.processedInputs;
|
||||
|
||||
if (inputs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="alert-radio-group" role="radiogroup" aria-labelledby={labelledby} aria-activedescendant={this.activeId}>
|
||||
<div class="alert-radio-group" role="radiogroup" aria-activedescendant={this.activeId}>
|
||||
{ inputs.map(i => (
|
||||
<button
|
||||
type="button"
|
||||
@@ -372,7 +440,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
aria-checked={`${i.checked}`}
|
||||
disabled={i.disabled}
|
||||
id={i.id}
|
||||
tabIndex={0}
|
||||
tabIndex={i.tabindex}
|
||||
class={{
|
||||
...getClassMap(i.cssClass),
|
||||
'alert-radio-button': true,
|
||||
@@ -395,13 +463,13 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
);
|
||||
}
|
||||
|
||||
private renderInput(labelledby: string | undefined) {
|
||||
private renderInput() {
|
||||
const inputs = this.processedInputs;
|
||||
if (inputs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div class="alert-input-group" aria-labelledby={labelledby}>
|
||||
<div class="alert-input-group">
|
||||
{ inputs.map(i => {
|
||||
if (i.type === 'textarea') {
|
||||
return (
|
||||
@@ -410,7 +478,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
placeholder={i.placeholder}
|
||||
value={i.value}
|
||||
id={i.id}
|
||||
tabIndex={0}
|
||||
tabIndex={i.tabindex}
|
||||
{...i.attributes as AlertTextareaAttributes}
|
||||
disabled={i.attributes?.disabled ?? i.disabled}
|
||||
class={inputClass(i)}
|
||||
@@ -431,7 +499,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
max={i.max}
|
||||
value={i.value}
|
||||
id={i.id}
|
||||
tabIndex={0}
|
||||
tabIndex={i.tabindex}
|
||||
{...i.attributes as AlertInputAttributes}
|
||||
disabled={i.attributes?.disabled ?? i.disabled}
|
||||
class={inputClass(i)}
|
||||
@@ -488,13 +556,6 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
const subHdrId = `alert-${overlayIndex}-sub-hdr`;
|
||||
const msgId = `alert-${overlayIndex}-msg`;
|
||||
|
||||
let labelledById: string | undefined;
|
||||
if (header !== undefined) {
|
||||
labelledById = hdrId;
|
||||
} else if (subHeader !== undefined) {
|
||||
labelledById = subHdrId;
|
||||
}
|
||||
|
||||
return (
|
||||
<Host
|
||||
role="dialog"
|
||||
@@ -514,7 +575,9 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
|
||||
<ion-backdrop tappable={this.backdropDismiss}/>
|
||||
|
||||
<div class="alert-wrapper ion-wrapper" ref={el => this.wrapperEl = el}>
|
||||
<div tabindex="0"></div>
|
||||
|
||||
<div class="alert-wrapper ion-overlay-wrapper" ref={el => this.wrapperEl = el}>
|
||||
|
||||
<div class="alert-head">
|
||||
{header && <h2 id={hdrId} class="alert-title">{header}</h2>}
|
||||
@@ -523,10 +586,12 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
|
||||
<div id={msgId} class="alert-message" innerHTML={sanitizeDOMString(this.message)}></div>
|
||||
|
||||
{this.renderAlertInputs(labelledById)}
|
||||
{this.renderAlertInputs()}
|
||||
{this.renderAlertButtons()}
|
||||
|
||||
</div>
|
||||
|
||||
<div tabindex="0"></div>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -588,6 +588,48 @@ function presentAlertCheckbox() {
|
||||
### React
|
||||
|
||||
```tsx
|
||||
/* Using with useIonAlert Hook */
|
||||
|
||||
import React from 'react';
|
||||
import { IonButton, IonContent, IonPage, useIonAlert } from '@ionic/react';
|
||||
|
||||
const AlertExample: React.FC = () => {
|
||||
const [present] = useIonAlert();
|
||||
return (
|
||||
<IonPage>
|
||||
<IonContent fullscreen>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() =>
|
||||
present({
|
||||
cssClass: 'my-css',
|
||||
header: 'Alert',
|
||||
message: 'alert from hook',
|
||||
buttons: [
|
||||
'Cancel',
|
||||
{ text: 'Ok', handler: (d) => console.log('ok pressed') },
|
||||
],
|
||||
onDidDismiss: (e) => console.log('did dismiss'),
|
||||
})
|
||||
}
|
||||
>
|
||||
Show Alert
|
||||
</IonButton>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() => present('hello with params', [{ text: 'Ok' }])}
|
||||
>
|
||||
Show Alert using params
|
||||
</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
/* Using with IonAlert Component */
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { IonAlert, IonButton, IonContent } from '@ionic/react';
|
||||
|
||||
@@ -1155,45 +1197,47 @@ export class AlertExample {
|
||||
|
||||
```html
|
||||
<template>
|
||||
<IonVuePage :title="'Alert'">
|
||||
<ion-button @click="presentAlert">Show Alert</ion-button>
|
||||
<ion-button @click="presentAlertMultipleButtons">Show Alert (multiple buttons)</ion-button>
|
||||
<ion-button @click="presentAlertConfirm">Show Alert (confirm)</ion-button>
|
||||
<ion-button @click="presentAlertPrompt">Show Alert (prompt)</ion-button>
|
||||
<ion-button @click="presentAlertRadio">Show Alert (radio)</ion-button>
|
||||
<ion-button @click="presentAlertCheckbox">Show Alert (checkbox)</ion-button>
|
||||
</IonVuePage>
|
||||
<ion-button @click="presentAlert">Show Alert</ion-button>
|
||||
<ion-button @click="presentAlertMultipleButtons">Show Alert (multiple buttons)</ion-button>
|
||||
<ion-button @click="presentAlertConfirm">Show Alert (confirm)</ion-button>
|
||||
<ion-button @click="presentAlertPrompt">Show Alert (prompt)</ion-button>
|
||||
<ion-button @click="presentAlertRadio">Show Alert (radio)</ion-button>
|
||||
<ion-button @click="presentAlertCheckbox">Show Alert (checkbox)</ion-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
import { IonButton, alertController } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonButton },
|
||||
methods: {
|
||||
presentAlert() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlert() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['OK'],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertMultipleButtons() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertMultipleButtons() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['Cancel', 'Open Modal', 'Delete'],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertConfirm() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertConfirm() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Confirm!',
|
||||
@@ -1214,12 +1258,12 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertPrompt() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertPrompt() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Prompt!',
|
||||
@@ -1288,12 +1332,12 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertRadio() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertRadio() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Radio',
|
||||
@@ -1346,12 +1390,12 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertCheckbox() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertCheckbox() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Checkbox',
|
||||
@@ -1409,11 +1453,45 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
Developers can also use this component directly in their template:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<ion-button @click="setOpen(true)">Show Alert</ion-button>
|
||||
<ion-alert
|
||||
:is-open="isOpenRef"
|
||||
header="Alert"
|
||||
sub-header="Subtitle"
|
||||
message="This is an alert message."
|
||||
css-class="my-custom-class"
|
||||
:buttons="buttons"
|
||||
@onDidDismiss="setOpen(false)"
|
||||
>
|
||||
</ion-alert>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonAlert, IonButton } from '@ionic/vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonAlert, IonButton },
|
||||
setup() {
|
||||
const isOpenRef = ref(false);
|
||||
const setOpen = (state: boolean) => isOpenRef.value = state;
|
||||
const buttons = ['Ok'];
|
||||
|
||||
return { buttons, isOpenRef, setOpen }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,40 @@
|
||||
import { testAlert } from '../test.utils';
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
const DIRECTORY = 'basic';
|
||||
const getActiveElementText = async (page) => {
|
||||
const activeElement = await page.evaluateHandle(() => document.activeElement);
|
||||
return await page.evaluate(el => el && el.textContent, activeElement);
|
||||
}
|
||||
|
||||
test('alert: focus trap', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/alert/test/basic?ionic:_testing=true' });
|
||||
|
||||
await page.click('#multipleButtons');
|
||||
await page.waitForSelector('#multipleButtons');
|
||||
|
||||
let alert = await page.find('ion-alert');
|
||||
|
||||
expect(alert).not.toBe(null);
|
||||
await alert.waitForVisible();
|
||||
|
||||
await page.keyboard.press('Tab');
|
||||
|
||||
const activeElementText = await getActiveElementText(page);
|
||||
expect(activeElementText).toEqual('Open Modal');
|
||||
|
||||
await page.keyboard.down('Shift');
|
||||
await page.keyboard.press('Tab');
|
||||
await page.keyboard.up('Shift');
|
||||
|
||||
const activeElementTextTwo = await getActiveElementText(page);
|
||||
expect(activeElementTextTwo).toEqual('Cancel');
|
||||
|
||||
await page.keyboard.press('Tab');
|
||||
|
||||
const activeElementTextThree = await getActiveElementText(page);
|
||||
expect(activeElementTextThree).toEqual('Open Modal');
|
||||
});
|
||||
|
||||
test(`alert: basic`, async () => {
|
||||
await testAlert(DIRECTORY, '#basic');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -206,7 +206,6 @@
|
||||
type: 'radio',
|
||||
label: 'Radio 1',
|
||||
value: 'value1',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
type: 'radio',
|
||||
@@ -216,7 +215,8 @@
|
||||
{
|
||||
type: 'radio',
|
||||
label: 'Radio 3',
|
||||
value: 'value3'
|
||||
value: 'value3',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
type: 'radio',
|
||||
@@ -241,12 +241,12 @@
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: () => {
|
||||
console.log('Confirm Cancel')
|
||||
console.log('Confirm Cancel');
|
||||
}
|
||||
}, {
|
||||
text: 'Ok',
|
||||
handler: () => {
|
||||
console.log('Confirm Ok')
|
||||
handler: (ev) => {
|
||||
console.log('Confirm Ok', ev);
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,4 +1,46 @@
|
||||
```tsx
|
||||
/* Using with useIonAlert Hook */
|
||||
|
||||
import React from 'react';
|
||||
import { IonButton, IonContent, IonPage, useIonAlert } from '@ionic/react';
|
||||
|
||||
const AlertExample: React.FC = () => {
|
||||
const [present] = useIonAlert();
|
||||
return (
|
||||
<IonPage>
|
||||
<IonContent fullscreen>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() =>
|
||||
present({
|
||||
cssClass: 'my-css',
|
||||
header: 'Alert',
|
||||
message: 'alert from hook',
|
||||
buttons: [
|
||||
'Cancel',
|
||||
{ text: 'Ok', handler: (d) => console.log('ok pressed') },
|
||||
],
|
||||
onDidDismiss: (e) => console.log('did dismiss'),
|
||||
})
|
||||
}
|
||||
>
|
||||
Show Alert
|
||||
</IonButton>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() => present('hello with params', [{ text: 'Ok' }])}
|
||||
>
|
||||
Show Alert using params
|
||||
</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
/* Using with IonAlert Component */
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { IonAlert, IonButton, IonContent } from '@ionic/react';
|
||||
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
```html
|
||||
<template>
|
||||
<IonVuePage :title="'Alert'">
|
||||
<ion-button @click="presentAlert">Show Alert</ion-button>
|
||||
<ion-button @click="presentAlertMultipleButtons">Show Alert (multiple buttons)</ion-button>
|
||||
<ion-button @click="presentAlertConfirm">Show Alert (confirm)</ion-button>
|
||||
<ion-button @click="presentAlertPrompt">Show Alert (prompt)</ion-button>
|
||||
<ion-button @click="presentAlertRadio">Show Alert (radio)</ion-button>
|
||||
<ion-button @click="presentAlertCheckbox">Show Alert (checkbox)</ion-button>
|
||||
</IonVuePage>
|
||||
<ion-button @click="presentAlert">Show Alert</ion-button>
|
||||
<ion-button @click="presentAlertMultipleButtons">Show Alert (multiple buttons)</ion-button>
|
||||
<ion-button @click="presentAlertConfirm">Show Alert (confirm)</ion-button>
|
||||
<ion-button @click="presentAlertPrompt">Show Alert (prompt)</ion-button>
|
||||
<ion-button @click="presentAlertRadio">Show Alert (radio)</ion-button>
|
||||
<ion-button @click="presentAlertCheckbox">Show Alert (checkbox)</ion-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
import { IonButton, alertController } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonButton },
|
||||
methods: {
|
||||
presentAlert() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlert() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['OK'],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertMultipleButtons() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertMultipleButtons() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['Cancel', 'Open Modal', 'Delete'],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertConfirm() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertConfirm() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Confirm!',
|
||||
@@ -59,12 +61,12 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertPrompt() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertPrompt() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Prompt!',
|
||||
@@ -133,12 +135,12 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertRadio() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertRadio() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Radio',
|
||||
@@ -191,12 +193,12 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
|
||||
presentAlertCheckbox() {
|
||||
return this.$ionic.alertController
|
||||
async presentAlertCheckbox() {
|
||||
const alert = await alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Checkbox',
|
||||
@@ -254,10 +256,44 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.then(a => a.present())
|
||||
});
|
||||
return alert.present();
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
Developers can also use this component directly in their template:
|
||||
|
||||
```html
|
||||
<template>
|
||||
<ion-button @click="setOpen(true)">Show Alert</ion-button>
|
||||
<ion-alert
|
||||
:is-open="isOpenRef"
|
||||
header="Alert"
|
||||
sub-header="Subtitle"
|
||||
message="This is an alert message."
|
||||
css-class="my-custom-class"
|
||||
:buttons="buttons"
|
||||
@onDidDismiss="setOpen(false)"
|
||||
>
|
||||
</ion-alert>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonAlert, IonButton } from '@ionic/vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonAlert, IonButton },
|
||||
setup() {
|
||||
const isOpenRef = ref(false);
|
||||
const setOpen = (state: boolean) => isOpenRef.value = state;
|
||||
const buttons = ['Ok'];
|
||||
|
||||
return { buttons, isOpenRef, setOpen }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -3,6 +3,16 @@ html.plt-mobile ion-app {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* This works around a WebKit issue
|
||||
* where user-select: none was causing
|
||||
* contenteditable to not be selectable,
|
||||
* even though inputs and textareas are selectable.
|
||||
*/
|
||||
html.plt-mobile ion-app [contenteditable] {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
ion-app.force-statusbar-padding {
|
||||
--ion-safe-area-top: 20px;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export class App implements ComponentInterface {
|
||||
|
||||
componentDidLoad() {
|
||||
if (Build.isBrowser) {
|
||||
rIC(() => {
|
||||
rIC(async () => {
|
||||
const isHybrid = isPlatform(window, 'hybrid');
|
||||
if (!config.getBoolean('_testing')) {
|
||||
import('../../utils/tap-click').then(module => module.startTapClick(config));
|
||||
@@ -24,8 +24,11 @@ export class App implements ComponentInterface {
|
||||
if (config.getBoolean('inputShims', needInputShims())) {
|
||||
import('../../utils/input-shims/input-shims').then(module => module.startInputShims(config));
|
||||
}
|
||||
const hardwareBackButtonModule = await import('../../utils/hardware-back-button');
|
||||
if (config.getBoolean('hardwareBackButton', isHybrid)) {
|
||||
import('../../utils/hardware-back-button').then(module => module.startHardwareBackButton());
|
||||
hardwareBackButtonModule.startHardwareBackButton();
|
||||
} else {
|
||||
hardwareBackButtonModule.blockHardwareBackButton();
|
||||
}
|
||||
if (typeof (window as any) !== 'undefined') {
|
||||
import('../../utils/keyboard/keyboard').then(module => module.startKeyboardAssist(window));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr" class="safe-area">
|
||||
<html lang="en" dir="ltr" class="safe-area">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -120,6 +120,15 @@ export class AvatarExample {
|
||||
<ion-label>Item Avatar</ion-label>
|
||||
</ion-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonAvatar, IonChip, IonItem, IonLabel } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonAvatar, IonChip, IonItem, IonLabel }
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -18,4 +18,13 @@
|
||||
<ion-label>Item Avatar</ion-label>
|
||||
</ion-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonAvatar, IonChip, IonItem, IonLabel } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonAvatar, IonChip, IonItem, IonLabel }
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -2,12 +2,16 @@ import { Component, ComponentInterface, Element, Host, Prop, h } from '@stencil/
|
||||
|
||||
import { config } from '../../global/config';
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { Color } from '../../interface';
|
||||
import { AnimationBuilder, Color } from '../../interface';
|
||||
import { ButtonInterface } from '../../utils/element-interface';
|
||||
import { createColorClasses, hostContext, openURL } from '../../utils/theme';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
*
|
||||
* @part native - The native HTML button element that wraps all child elements.
|
||||
* @part icon - The back button icon (uses ion-icon).
|
||||
* @part text - The back button text.
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-back-button',
|
||||
@@ -36,7 +40,7 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
/**
|
||||
* If `true`, the user cannot interact with the button.
|
||||
*/
|
||||
@Prop({ reflectToAttr: true }) disabled = false;
|
||||
@Prop({ reflect: true }) disabled = false;
|
||||
|
||||
/**
|
||||
* The icon name to use for the back button.
|
||||
@@ -53,6 +57,12 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
*/
|
||||
@Prop() type: 'submit' | 'reset' | 'button' = 'button';
|
||||
|
||||
/**
|
||||
* When using a router, it specifies the transition animation when navigating to
|
||||
* another page.
|
||||
*/
|
||||
@Prop() routerAnimation: AnimationBuilder | undefined;
|
||||
|
||||
componentWillLoad() {
|
||||
if (this.defaultHref === undefined) {
|
||||
this.defaultHref = config.get('backButtonDefaultHref');
|
||||
@@ -99,9 +109,9 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
ev.preventDefault();
|
||||
|
||||
if (nav && await nav.canGoBack()) {
|
||||
return nav.pop({ skipIfBusy: true });
|
||||
return nav.pop({ animationBuilder: this.routerAnimation, skipIfBusy: true });
|
||||
}
|
||||
return openURL(this.defaultHref, ev, 'back');
|
||||
return openURL(this.defaultHref, ev, 'back', this.routerAnimation);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -112,10 +122,8 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
return (
|
||||
<Host
|
||||
onClick={this.onClick}
|
||||
class={{
|
||||
...createColorClasses(color),
|
||||
class={createColorClasses(color, {
|
||||
[mode]: true,
|
||||
|
||||
'button': true, // ion-buttons target .button
|
||||
'back-button-disabled': disabled,
|
||||
'back-button-has-icon-only': hasIconOnly,
|
||||
@@ -124,12 +132,18 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
'ion-activatable': true,
|
||||
'ion-focusable': true,
|
||||
'show-back-button': showBackButton
|
||||
}}
|
||||
})}
|
||||
>
|
||||
<button type={type} disabled={disabled} class="button-native" aria-label={backButtonText || 'back'}>
|
||||
<button
|
||||
type={type}
|
||||
disabled={disabled}
|
||||
class="button-native"
|
||||
part="native"
|
||||
aria-label={backButtonText || 'back'}
|
||||
>
|
||||
<span class="button-inner">
|
||||
{backButtonIcon && <ion-icon icon={backButtonIcon} aria-hidden="true" lazy={false}></ion-icon>}
|
||||
{backButtonText && <span aria-hidden="true" class="button-text">{backButtonText}</span>}
|
||||
{backButtonIcon && <ion-icon part="icon" icon={backButtonIcon} aria-hidden="true" lazy={false}></ion-icon>}
|
||||
{backButtonText && <span part="text" aria-hidden="true" class="button-text">{backButtonText}</span>}
|
||||
</span>
|
||||
{mode === 'md' && <ion-ripple-effect type={this.rippleType}></ion-ripple-effect>}
|
||||
</button>
|
||||
|
||||
@@ -295,21 +295,40 @@ export class BackButtonExample {
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonButtons, IonHeader, IonMenuButton, IonToolbar } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonButtons, IonHeader, IonMenuButton, IonToolbar }
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ----------- |
|
||||
| `color` | `color` | The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). | `string \| undefined` | `undefined` |
|
||||
| `defaultHref` | `default-href` | The url to navigate back to by default when there is no history. | `string \| undefined` | `undefined` |
|
||||
| `disabled` | `disabled` | If `true`, the user cannot interact with the button. | `boolean` | `false` |
|
||||
| `icon` | `icon` | The icon name to use for the back button. | `null \| string \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `text` | `text` | The text to display in the back button. | `null \| string \| undefined` | `undefined` |
|
||||
| `type` | `type` | The type of the button. | `"button" \| "reset" \| "submit"` | `'button'` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ----------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ----------- |
|
||||
| `color` | `color` | The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). | `string \| undefined` | `undefined` |
|
||||
| `defaultHref` | `default-href` | The url to navigate back to by default when there is no history. | `string \| undefined` | `undefined` |
|
||||
| `disabled` | `disabled` | If `true`, the user cannot interact with the button. | `boolean` | `false` |
|
||||
| `icon` | `icon` | The icon name to use for the back button. | `null \| string \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `routerAnimation` | -- | When using a router, it specifies the transition animation when navigating to another page. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `text` | `text` | The text to display in the back button. | `null \| string \| undefined` | `undefined` |
|
||||
| `type` | `type` | The type of the button. | `"button" \| "reset" \| "submit"` | `'button'` |
|
||||
|
||||
|
||||
## Shadow Parts
|
||||
|
||||
| Part | Description |
|
||||
| ---------- | ------------------------------------------------------------- |
|
||||
| `"icon"` | The back button icon (uses ion-icon). |
|
||||
| `"native"` | The native HTML button element that wraps all child elements. |
|
||||
| `"text"` | The back button text. |
|
||||
|
||||
|
||||
## CSS Custom Properties
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -49,4 +49,13 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonButtons, IonHeader, IonMenuButton, IonToolbar } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonButtons, IonHeader, IonMenuButton, IonToolbar }
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -67,6 +67,7 @@ export class Backdrop implements ComponentInterface {
|
||||
return (
|
||||
<Host
|
||||
tabindex="-1"
|
||||
aria-hidden="true"
|
||||
class={{
|
||||
[mode]: true,
|
||||
'backdrop-hide': !this.visible,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user