Compare commits

..

308 Commits

Author SHA1 Message Date
Liam DeBeasi
f3fb09ab44 merge release-5.9.4
5.9.4
2022-04-27 11:54:50 -04:00
Liam DeBeasi
7947a26ba4 5.9.4 2022-04-27 11:40:57 -04:00
Sean Perkins
ffb056d50e fix(core): inherit aria attributes on host elements (#25156) (#25169) 2022-04-27 10:59:58 -04:00
Liam DeBeasi
2d9724947d merge release-5.9.3
Release 5.9.3
2021-12-15 10:29:24 -05:00
Liam DeBeasi
02ef5ae179 5.9.3 2021-12-15 10:10:07 -05:00
Sean Perkins
4aab72b061 fix(vue): tabs no longer get unmounted when navigating back to a tabs context (#24337)
resolves #24332

Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
2021-12-15 09:55:29 -05:00
Liam DeBeasi
9c9e28ccc9 perf(content): remove global click listener to improve interaction performance (#24360)
resolves #24359
2021-12-15 09:55:22 -05:00
Liam DeBeasi
1c2875044a fix(vue): improve query params handling in tabs (#24355)
resolves #24353
2021-12-15 09:55:05 -05:00
Liam DeBeasi
d665ace5c4 chore(): create 5.9.x history
chore(): create 5.9.x history
2021-12-08 09:06:27 -05:00
Liam DeBeasi
672ab80807 merge release-5.9.2
5.9.2
2021-12-07 09:43:26 -05:00
Liam DeBeasi
da3b93b4a2 5.9.2 2021-12-07 09:21:00 -05:00
Sean Perkins
5e5054d369 fix(router): popping route now accounts for route params (#24315) 2021-12-06 17:25:40 -05:00
Anant Sharma
8f188eaae7 fix(react): properly check for custom elements to avoid errors in unit tests (#24156)
resolves #24149
2021-12-06 17:06:17 -05:00
Amanda Smith
f6a00ea954 fix(popover): handle scrolling in content so header can be sticky (#24294) 2021-12-06 10:45:37 -06:00
Djakson
b083ae4e58 docs(): fix typo in popover docs (#24318) 2021-12-06 10:26:03 -05:00
Sean Perkins
f7bd4c02c3 docs(back-button): update icon prop to include src and name approach (#24307) 2021-12-03 12:52:42 -05:00
Liam DeBeasi
047d3c7772 fix(vue): switching between tabs preserves query string (#24297)
resolves #23699
2021-12-02 10:04:26 -05:00
Sean Perkins
4b26feaa47 fix(react): present and dismiss hooks return promises (#24299) 2021-12-01 15:16:55 -05:00
Amanda Smith
e41b0e0cf2 fix(content): ensure fixed slot renders on top of content in iOS (#24300) 2021-12-01 13:47:39 -06:00
Will Martin
7f61b06895 build(commitizen): do not run on main, next, or release branches (#24258) 2021-11-25 09:17:23 -05:00
Sean Perkins
89e4bc56a1 fix(slides): update swiper instance after initialization (#24257) 2021-11-24 11:52:48 -05:00
Yuhongjie
fb96ab5a26 fix(vue): ionic lifecycle hooks now run when using vue 3.2 setup syntax (#24253)
resolves #23824

Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
2021-11-23 17:04:24 -05:00
Liam DeBeasi
6f01c3b73d chore(): update vue test app (#24262) 2021-11-23 16:35:54 -05:00
Ryan Waskiewicz
07d83ccd24 chore(ci): fix typo for test-vue-e2e step (#24256) 2021-11-23 14:28:58 -05:00
Sean Perkins
816096f897 fix(angular): strict type usage (#24221) 2021-11-22 15:59:12 -05:00
Liam DeBeasi
615dcc0461 merge release-5.9.1
5.9.1
2021-11-17 12:01:48 -05:00
Liam DeBeasi
c2603e9cff 5.9.1 2021-11-17 11:48:52 -05:00
Liam DeBeasi
1d983fa4b3 fix(angular): build is now in correct directory (#24236)
* fix(): revert ded build changes

* fix(); revert stuff

* chore(): revert dev build

* chore(): fix merge
2021-11-17 11:40:56 -05:00
Liam DeBeasi
23b4fc5385 merge release-5.9.0
5.9.0
2021-11-17 10:29:56 -05:00
Liam DeBeasi
11425fbb35 build(): ensure react router gets latest version of core 2021-11-17 15:16:22 +00:00
Liam DeBeasi
2d70427608 build(): publish to prod but not dev builds (#24232) 2021-11-17 09:47:24 -05:00
Liam DeBeasi
bd8c3e881f 5.9.0 2021-11-17 09:27:51 -05:00
Sean Perkins
0566ec0da3 fix(input): date type in ion-input now aligns correctly on iOS 15 (#24217) 2021-11-12 15:13:37 -05:00
Sean Perkins
b2f2a4b71b docs(): docs reference main instead of master (#24216) 2021-11-12 14:31:18 -05:00
Liam DeBeasi
64dd070d67 build(dev-build): correctly pass secrets to publish task (#24194) 2021-11-10 12:52:00 -05:00
Liam DeBeasi
928dfa52ca build(dev-build): add GitHub actions for dev builds (#24193) 2021-11-09 13:25:22 -05:00
Liam DeBeasi
d0b61307c6 feat(slides): add support for Swiper 7 (#24190) 2021-11-09 12:50:56 -05:00
Amanda Smith
579d11824d chore(ionitron): remove reference to old Slack channel (#24189) 2021-11-09 09:18:20 -06:00
Liam DeBeasi
7c43589b0a fix(vue): canGoBack method now works correctly (#24188)
resolves #24109
2021-11-09 09:45:12 -05:00
Liam DeBeasi
642255e514 fix(action-sheet): safe area is now accounted for in MD mode (#24176)
resolves #24175
2021-11-08 08:58:20 -05:00
Matt Netkow
2485b303da docs(virtual-scroll): fix url reference paths (#24172) 2021-11-05 12:28:21 -04:00
Liam DeBeasi
9e2373e15e docs(github-actions): do not run screenshot test on forks (#24164) 2021-11-04 16:08:21 -04:00
Liam DeBeasi
e8fe117c34 docs(): update table of contents for contributing guide (#24148) 2021-11-01 17:54:25 -04:00
Liam DeBeasi
811a34493d docs(react): fix infinite scroll example to remove extra imports (#24147) 2021-11-01 17:47:07 -04:00
Liam DeBeasi
5bcb39f82b docs(): update contributing guide for angular, react, and vue (#24141)
resolves #24137
2021-11-01 17:37:48 -04:00
Liam DeBeasi
22be16f3f0 test(): allow core to use cached node modules (#24146) 2021-11-01 17:31:26 -04:00
Liam DeBeasi
fd59acd691 test(): add way of manually busting node module cache (#24145) 2021-11-01 17:00:25 -04:00
Liam DeBeasi
b5dbb3984c test(): migrate tests to GitHub Actions (#24029) 2021-11-01 15:41:00 -04:00
Liam DeBeasi
794bfbbc57 docs(react): add examples for infinite scroll (#24130) 2021-10-28 16:23:26 -04:00
Liam DeBeasi
351c30ce42 merge release-5.8.5
Release 5.8.5
2021-10-27 09:15:12 -04:00
Liam DeBeasi
8605c467d1 merge release-5.8.5
5.8.5
2021-10-27 09:14:49 -04:00
Liam DeBeasi
1b0669eebe 5.8.5 2021-10-27 09:01:14 -04:00
Amanda Smith
bdb268aa12 fix(menu): added focus trapping, improved compatibility with screen readers (#24076)
* fix(menu): add basic accessibility features

* fix(menu): add focus trapping

* test(menu): add test for focus trapping

* style(menu): lint fixes

* fix(menu): focus first element inside instead of whole menu

* test(menu): fix focus trap test to account for new behavior

* refactor(menu): pull focus handler into its own prop

* test(menu): add a11y testing

* fix(menu): prevent nested aria landmark from header inside menu

* fix(menu): revert switch to nav element

* fix(menu): remove unnecessary import from test

* fix(menu): allow for custom aria-label

* fix(menu): move nested ARIA role logic to header for flexibility

* fix(item): only add focusable class if it actually is focusable

* fix(menu): allow focusing of menu itself, for a11y on menus with no focusable children

* fix(item): move isFocusable logic to state for better reactivity

* perf(item): only grab one focusable child

* fix(menu): hide page content from screen readers when menu is open

* fix(menu): fallback to focusing host element

* docs(menu): add comments

Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
2021-10-27 08:51:46 -04:00
Dmitriy Fishman
2916810a2b docs(): fix a typo in the readme (#24087) 2021-10-19 10:08:22 -04:00
Liam DeBeasi
24659a527a fix(vue): mount correct views when navigating (#24056)
resolves #23914
2021-10-14 11:28:36 -04:00
Liam DeBeasi
a09d7d4ab6 fix(vue): back button now selects correct route when navigating from view multiple times (#24060)
resolves #23987
2021-10-13 09:07:53 -04:00
Ely Lucas
ea34e50430 test(react): add react e2e app 2021-10-12 15:10:03 -06:00
Liam DeBeasi
4075ea6941 merge release-5.8.4
5.8.4
2021-10-11 12:09:01 -04:00
Liam DeBeasi
2a2829c17e 5.8.4 2021-10-11 11:31:16 -04:00
Liam DeBeasi
e001f24f2c fix(angular): setup config properly (#24054)
resolves #24051 #24052
2021-10-11 11:22:08 -04:00
Amanda Smith
68a7e43345 fix(back-button): pass aria-label to native element (#24027) 2021-10-08 12:08:32 -05:00
Liam DeBeasi
e92fecb08c merge release-5.8.3
Release 5.8.3
2021-10-08 13:03:04 -04:00
Liam DeBeasi
a63474a621 5.8.3 2021-10-07 16:50:46 -04:00
Liam DeBeasi
f98151c5d1 5.8.3 2021-10-07 20:50:28 +00:00
Ely Lucas
655631ddf0 fix(react): fix to regression in overlay hooks dimiss method (#24038)
resolves #24030
2021-10-07 15:18:10 -04:00
Liam DeBeasi
3b9b9082b8 merge release-5.8.2
Release 5.8.2
2021-10-06 10:24:24 -04:00
Liam DeBeasi
11332e446c merge release-5.8.2
5.8.2
2021-10-06 10:24:14 -04:00
Liam DeBeasi
fe9bec29d5 5.8.2 2021-10-06 14:05:57 +00:00
Liam DeBeasi
b1ffdadbc3 chore(): fix typo in feature request template (#24017) 2021-10-05 09:05:49 -04:00
Liam DeBeasi
077b915ad5 chore(): fix typo in bug template (#24016) 2021-10-05 09:04:38 -04:00
Ely Lucas
2c97712601 fix(react): overlay hooks memorised properly to prevent re-renders (#24010)
resolves #23741

Co-authored-by: Fabrice <fabrice@weinberg.me>
2021-10-05 08:44:40 -04:00
Robert Rhoades
f112ad4490 fix(angular): use initialize function when setting up ionic angular to avoid config errors (#24004)
resolves #22853

Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
2021-10-04 10:21:48 -04:00
Liam DeBeasi
25eb8cdf98 fix(status-bar): tapping status bar correctly scrolls content to top (#24001)
resolves #20423

Co-authored-by: Hans Krywalsky <EinfachHans@users.noreply.github.com>
2021-09-30 18:37:47 -04:00
Mads Buchmann Frederiksen
7010fe97a7 docs(readme): fix broken link to CONTRIBUTE guide (#23982) 2021-09-27 10:35:28 -04:00
Amanda Smith
a26275378f fix(alert): made it easier to tell if alert is scrollable in MD mode (#23976) 2021-09-24 14:23:41 -05:00
Liam DeBeasi
3ca04197a4 fix(item-sliding): closing an item can no longer be interrupted (#23973)
resolves #23969
2021-09-23 16:08:33 -04:00
Liam DeBeasi
aa4ba890e9 fix(select-popover): non-scrollable popovers no longer have forced overscroll (#23972)
resolves #23971
2021-09-23 10:05:32 -04:00
Liam DeBeasi
0774cca2cd merge release-5.8.1
Release 5.8.1
2021-09-22 10:48:57 -04:00
Liam DeBeasi
bb126a02e8 merge release-5.8.1
5.8.1
2021-09-22 10:48:51 -04:00
Liam DeBeasi
598aaed4bf 5.8.1 2021-09-22 09:14:14 -04:00
Liam DeBeasi
3c1be89112 fix(angular): select method now has correct types (#23953)
resolves #23952
2021-09-22 08:51:33 -04:00
Amanda Smith
00269941ca docs(router): make root prop docs more descriptive (#23961) 2021-09-21 13:08:55 -05:00
Amanda Smith
e483034f3a docs(refresher): fix 'to to' in snapbackDuration (#23960) 2021-09-21 10:28:52 -05:00
amandaesmith3
53d64c1eb8 docs(title): fix typo in usage CSS example (#23957) 2021-09-21 08:18:31 -05:00
Liam DeBeasi
ae1325cee6 fix(label): only inherit color if color property is set on ion-item (#23944)
resolves #20125
2021-09-16 15:27:43 -04:00
Liam DeBeasi
8108edd876 fix(item-sliding): item-sliding accounts for multiple ion-item elements (#23943)
resolves #19312
2021-09-16 12:29:12 -04:00
Liam DeBeasi
874e791377 merge release-5.8.0
5.8.0
2021-09-15 11:37:22 -04:00
Liam DeBeasi
6c366aaf87 merge release-5.8.0
Release 5.8.0
2021-09-15 11:37:12 -04:00
Liam DeBeasi
b104690192 chore(): add version name 2021-09-15 11:19:25 -04:00
Liam DeBeasi
57bc299dea 5.8.0 2021-09-15 15:16:21 +00:00
Liam DeBeasi
5f95f45e58 chore(overlays): run build for vue (#23931) 2021-09-15 11:05:29 -04:00
amandaesmith3
6f85e010c8 docs(process): remove old Slack channel reference (#23932) 2021-09-15 09:57:54 -05:00
Liam DeBeasi
bd96a81ff8 feat(action-sheet, loading, modal, picker, popover): pass HTML attributes to host element (#23929) 2021-09-15 10:02:19 -04:00
William Martin
73a1daf0aa feat(alert, toast): pass arbitrary HTML attributes to host element (#23891)
resolves #23825
2021-09-14 22:44:57 -04:00
Michael Chen
1e13429731 fix(react): modal now mounts child component independently of other modals (#23903)
resolves #23904
2021-09-13 15:29:14 -04:00
Liam DeBeasi
1ed9f07060 fix(angular): nested tabs now go to correct page (#23902)
resolves #23897
2021-09-09 14:06:43 -04:00
Liam DeBeasi
47829690b5 fix(tab-bar): safe area padding now added when slot="top" (#23895)
resolves #23893
2021-09-08 13:33:16 -04:00
Liam DeBeasi
8888e2bafd fix(header): role attribute can now be customized (#23888)
resolves #21327
2021-09-08 10:48:18 -04:00
Liam DeBeasi
6876fd089f merge release-5.7.0
Release 5.7.0
2021-09-01 10:07:42 -04:00
Liam DeBeasi
e512fc1ecd merge release-5.7.0
5.7.0
2021-09-01 10:07:36 -04:00
Liam DeBeasi
a12d146c3e 5.7.0 2021-09-01 09:43:23 -04:00
Liam DeBeasi
a0229bc7b2 refactor(virtual-scroll): deprecate virtual scroll in favor of JS framework solutions (#23854) 2021-08-31 18:20:29 -04:00
William Martin
11fda41420 feat(slides): add IonicSlides module for Swiper migration, deprecate ion-slides (#23844)
backports #23447
2021-08-31 17:52:47 -04:00
Ikko Ashimine
33f0bcd437 chore(slides): fix typo in image slides example (#23838) 2021-08-30 10:15:12 -04:00
Liam DeBeasi
3c442228ff fix(vue): router guards are now fired correctly when written in a component (#23821)
resolves #23820
2021-08-26 10:40:48 -04:00
Liam DeBeasi
50b88b24c2 chore(): run build to update picker readme (#23822) 2021-08-25 18:57:26 -04:00
Sarah Drasner
9317f6eb41 docs(picker): add a simple picker example for Vue (#23818)
There was previously no example for a vue picker, this adds one.

closes #2053
2021-08-25 17:50:33 -04:00
Liam DeBeasi
9932e26a2e fix(label): label now only takes up as much space as needed when slotted (#23807)
resolves #23806
2021-08-24 10:25:12 -04:00
Toby Smith
02409f2abf fix(reorder-group): dragging reorder item to bottom no longer gives out of bounds index (#23797)
resolves #23796
2021-08-23 09:38:27 -04:00
Liam DeBeasi
864212b0f2 fix(alert): AlertButton role now has correct types (#23791) 2021-08-18 13:43:12 -04:00
Liam DeBeasi
34b150e5e7 merge release-5.6.14
5.6.14
2021-08-18 09:33:41 -04:00
Liam DeBeasi
22a8842ac2 merge release-5.6.14
Release 5.6.14
2021-08-18 09:33:30 -04:00
Liam DeBeasi
e4c0023df2 5.6.14 2021-08-18 09:17:36 -04:00
Mark Chris Levy
f9415ef8a6 fix(nav): custom animation is now used correctly (#23779)
resolves #23777
2021-08-18 08:34:34 -04:00
William Martin
e0c4ad30be fix(item-sliding): prevent scrolling during slide gesture (#23774)
resolves #19564
2021-08-17 23:53:16 -04:00
Liam DeBeasi
621f4faa1a fix(vue): using router.go now shows correct view (#23773)
resolves #22563
2021-08-17 08:53:55 -04:00
Liam DeBeasi
6b18a89ac2 fix(back-button): MD ripple now accounts for --ripple-color (#23749)
resolves #23748
2021-08-09 16:21:38 -04:00
Jacob McKay
067e621bbc fix(img): correctly determine when to load image when scrolling quickly on slower devices (#23704)
resolves #23703
2021-08-09 16:18:53 -04:00
William Martin
f83768cafe build(commit): add husky and commitizen (#23714) 2021-08-06 10:00:11 -04:00
Liam DeBeasi
2d6e45e8d1 merge release-5.6.13
5.6.13
2021-08-04 10:25:48 -04:00
Liam DeBeasi
2d5faa75db merge release-5.6.13
Release 5.6.13
2021-08-04 10:25:37 -04:00
Liam DeBeasi
22b7413f51 5.6.13 2021-08-04 10:05:10 -04:00
Liam DeBeasi
4a64e97a3e fix(vue): tabs warning about user-provided router outlet change is now correctly logged (#23724)
resolves #23719
2021-08-04 09:55:05 -04:00
Evgeniy
8a941fd24c fix(checkbox, radio): change event interfaces correctly use TypeScript generics for value (#23044)
Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
2021-08-03 16:29:53 -04:00
Liam DeBeasi
fbe648406b chore(): bump ionicons version (#23717) 2021-08-03 09:41:40 -04:00
Liam DeBeasi
4edb5e2fed fix(gesture): onEnd now correctly fires even if the event target was removed from the DOM (#23713)
resolves #22819 

Co-authored-by: Falingorn <falingorn@users.noreply.github.com>
2021-08-02 13:47:27 -04:00
Denis
792864f8ab fix(item-sliding): opening item while other items are open no longer requires multiple swipes (#23683)
resolves #21579
2021-08-02 12:56:27 -04:00
William Martin
f2a05bed1e fix(react): add SSR check to IonTabs (#23696)
resolves #23651
2021-08-02 10:28:51 -04:00
Moritz Eck
caf0917623 docs(platform): add capacitor to method docs (#23688)
resolves #23687
2021-07-26 08:49:24 -04:00
Liam DeBeasi
fb260a9e09 fix(vue): improve accuracy of ion-page dev warning (#23677)
resolves #23675
2021-07-23 09:42:06 -04:00
Liam DeBeasi
cab2a5103f merge release-5.6.12
Release 5.6.12
2021-07-21 09:37:04 -04:00
Liam DeBeasi
80edb603c2 merge release-5.6.12
5.6.12
2021-07-21 09:36:29 -04:00
Liam DeBeasi
f70ed79f47 5.6.12 2021-07-21 09:21:15 -04:00
Ikko Ashimine
ae0a1a3deb chore(nav): fix typo in test comment (#23658) 2021-07-20 11:21:39 -04:00
Liam DeBeasi
d8a2db73e2 chore(): add emojis to issue template titles (#23648)
resolves #23647
2021-07-15 13:55:16 -04:00
Liam DeBeasi
86ece8f8b5 chore(): fix typo in config (#23645) 2021-07-15 11:36:25 -04:00
Liam DeBeasi
3016b79717 chore(): remove cli, docs, and support templates in favor of directing visitors to correct place url (#23644) 2021-07-15 10:00:21 -04:00
Liam DeBeasi
773bbcb211 fix(overlays): overlay interfaces are now exported from framework packages and documented (#23619)
resolves #22790
2021-07-15 08:50:50 -04:00
Liam DeBeasi
3134e0afcd chore(): fix form template typos (#23635) 2021-07-14 19:31:04 -04:00
Liam DeBeasi
6d94a27fb9 chore(): convert remaining issue templates to forms (#23634) 2021-07-14 18:54:18 -04:00
Liam DeBeasi
d2ca304c12 chore(): use supported form keys (#23633) 2021-07-14 16:26:48 -04:00
Liam DeBeasi
e35386a52d chore(): fix yaml errors (#23632) 2021-07-14 15:50:34 -04:00
Liam DeBeasi
d10d9f9f74 chore(): fix bug issue name (#23630) 2021-07-14 15:18:49 -04:00
Liam DeBeasi
c940bd18d2 chore(): use new github form template for bug reports (#23629) 2021-07-14 14:49:30 -04:00
Liam DeBeasi
174b7de741 docs(vue): add card style modal example (#23628) 2021-07-14 10:18:17 -04:00
Liam DeBeasi
3cebcb0883 chore(): warn if developer forgot to use ionpage component in view (#23625) 2021-07-14 08:59:31 -04:00
Liam DeBeasi
7315e0157b chore(): switch to using disallow terminology (#23618) 2021-07-13 14:03:58 -04:00
jcesarmobile
4b56744d7f docs(react): install @ionic/cli instead of ionic (#23610) 2021-07-12 14:39:18 -04:00
Liam DeBeasi
c08345df2e fix(menu-button): custom aria-label can now be set (#23608)
resolves #23604
2021-07-12 08:52:03 -04:00
Liam DeBeasi
fa069424b2 fix(router-outlet): improve reliability of swipe back gesture when quickly swiping back (#23527)
resolves #22895
2021-07-09 09:29:16 -04:00
Liam DeBeasi
3b803ebe02 fix(button): buttons are now disabled during page transitions (#23589)
resolves #23588
2021-07-09 09:27:11 -04:00
William Martin
9021e7cc4b fix(item): mirror disabled prop to aria attribute (#23544)
resolves #23513
2021-07-09 09:19:48 -04:00
Liam DeBeasi
39315bc857 fix(action-sheet): header, subheader, and icon alignment better matches native ios (#23322)
resolves #23317
2021-07-08 09:38:00 -04:00
omar2205
a15cace139 docs(loading): show how to use dismiss method returns from useIonLoading for react (#23537) 2021-07-07 09:04:10 -04:00
Liam DeBeasi
635ac195d9 docs(router-outlet): add react note to docs (#23580) 2021-07-06 10:19:54 -04:00
Liam DeBeasi
34aad178d0 merge release-5.6.11
5.6.11
2021-07-01 12:03:53 -04:00
Liam DeBeasi
d36050918a merge release-5.6.11
Release 5.6.11
2021-07-01 12:03:38 -04:00
Liam DeBeasi
cffeb4d9bd 5.6.11 2021-07-01 11:16:21 -04:00
Liam DeBeasi
69be51dc54 fix(ios, md): double tapping back button no longer causes app to go back 2 pages (#23526)
resolves #18455
2021-07-01 10:44:19 -04:00
Liam DeBeasi
f3d6abbc1b fix(animation): typescript interface has correct return value for progress methods (#23536) 2021-06-29 16:36:51 -04:00
Liam DeBeasi
0b5c470b98 docs(card): fix usage example for vue (#23535) 2021-06-29 15:03:01 -04:00
Liam DeBeasi
d5980354fa chore(): add link to v6 beta onboarding guide (#23495) 2021-06-23 09:31:15 -04:00
Liam DeBeasi
508f1a46fb chore(): add 6.x to bug report template (#23493) 2021-06-23 09:27:21 -04:00
Liam DeBeasi
3130dd3fd8 chore(): add 6.x to feature request template (#23494) 2021-06-23 09:26:25 -04:00
Liam DeBeasi
57156526ff merge release-5.6.10
5.6.10
2021-06-22 10:02:05 -04:00
Liam DeBeasi
64f128be07 merge release-5.6.10
Release 5.6.10
2021-06-22 10:01:58 -04:00
Liam DeBeasi
40fadcd9bf 5.6.10 2021-06-22 09:30:43 -04:00
Liam DeBeasi
494a4a08fe chore(): add missing dependency (#23482) 2021-06-22 09:20:45 -04:00
Liam DeBeasi
b3847ff723 chore(): remove old test app, bump dependencies (#23481) 2021-06-22 08:43:57 -04:00
Liam DeBeasi
a2a4cff3d0 fix(vue): IonTabs can now accept IonRouterOutlet (#23477)
resolves #23321
2021-06-21 16:52:50 -04:00
Liam DeBeasi
68c0e7136d fix(button): buttons using fill and color properties now account for hover and focused opacity variables (#23442)
resolves #23441
2021-06-21 13:00:50 -04:00
Liam DeBeasi
87999e3c7a merge release-5.6.9
Release 5.6.9
2021-06-08 09:38:37 -04:00
Liam DeBeasi
87b4a42c96 merge release-5.6.9
5.6.9
2021-06-08 09:38:34 -04:00
Liam DeBeasi
e27b5b6ae3 fix(item): using multiple items with inputs no longer results in console warnings (#23429)
resolves #23427
2021-06-08 09:16:29 -04:00
Liam DeBeasi
10be62a71d 5.6.9 2021-06-08 08:58:49 -04:00
Liam DeBeasi
60bedb5599 fix(vue): prevent error from being thrown when testing on certain jest runners (#23421)
resolves #23397
2021-06-07 10:49:19 -04:00
Liam DeBeasi
f008628851 fix(vue): improve v-model integration for Vue 3.1.0+ (#23420) 2021-06-04 19:25:02 -04:00
Brandy Carney
82cfa55653 fix(title): inherit padding for iOS title in a toolbar (#23343)
resolves #23072
2021-06-03 11:28:57 -04:00
Hans Krywalsky
ae96563fb3 fix(modal): swipe to close modal is no longer swipeable on footer (#23401)
resolves #23398
2021-06-02 08:59:25 -04:00
Liam DeBeasi
d527414e10 chore(radio-group): clean up code to reuse helper function (#23396)
Co-authored-by: Daniel Simão <danielsimao@users.noreply.github.com>
2021-06-01 10:44:45 -04:00
Liam DeBeasi
6cc6f4c44b chore(): revert incorrect co-author credit (#23395)
This reverts commit 62ed9712e1.
2021-06-01 09:54:04 -04:00
Liam DeBeasi
62ed9712e1 chore(radio-group): use existing helper function for getting all radios (#23394)
Co-authored-by: Daniel Simão < danielsimao @users.noreply.github.com>
2021-06-01 09:22:12 -04:00
Liam DeBeasi
e3aaa9513e docs(popover): resolve variable naming conflict (#23393) 2021-06-01 09:08:14 -04:00
dejian-lc
e4bbaf8a7f chore(angular): fix typo in platform provider (#23385) 2021-06-01 08:52:36 -04:00
Victor Berchet
857550a0c4 chore(router): clean up code and add comments (#23355) 2021-05-28 08:57:52 -04:00
Liam DeBeasi
fee4e82f0e merge release-5.6.8
5.6.8
2021-05-27 16:01:52 -04:00
Liam DeBeasi
bb4554211d merge release-5.6.8
Release 5.6.8
2021-05-27 16:01:36 -04:00
Liam DeBeasi
565361b023 5.6.8 2021-05-27 15:41:40 -04:00
Liam DeBeasi
3d474ec67f fix(title): large title scale animation is now correct in rtl mode (#23372)
resolves #23371
2021-05-26 13:40:44 -04:00
Ikko Ashimine
2933531c44 docs(): fix typo in process doc (#23360) 2021-05-25 10:04:13 -04:00
Liam DeBeasi
bc2f1b8944 docs(fab): document correct ion-icon usage for vue (#23352) 2021-05-24 11:04:31 -04:00
Liam DeBeasi
36bfa33503 fix(react): remove @ionic/core dependency in @ionic/react-router to resolve yarn install warning (#23351)
resolves #23346
2021-05-24 10:32:33 -04:00
Daniel Ehrhardt
1a36922f41 fix(skeleton-text): animation no longer jumps on large skeleton text elements (#22697)
resolves #22694
2021-05-24 08:52:39 -04:00
Liam DeBeasi
dc430af906 fix(all): reflect color property as an attribute for vue (#23345)
resolves #23323
2021-05-21 19:26:53 -04:00
Victor Berchet
08a9f3ac94 fix(router): redirects now account for query string (#23337)
resolves #23136
2021-05-21 15:34:06 -04:00
Liam DeBeasi
881dcff40b fix(range): knob can now have an accessible name (#23338)
resolves #23295
2021-05-21 14:38:18 -04:00
Liam DeBeasi
a708c41262 fix(slides): resolve prototype pollution in swiper v5 (#23344)
resolves #23342
2021-05-21 14:16:53 -04:00
Liam DeBeasi
d473a53851 fix(action-sheet): subheader no longer overlaps action sheet buttons (#23318)
resolves #23316
2021-05-21 11:28:34 -04:00
Victor Berchet
56f6f56c66 fix(router): guards are now triggered on initial navigation (#23123)
resolves #22936
2021-05-20 10:05:49 -04:00
Liam DeBeasi
6bfe1ceee7 chore(): screenshot diff runs correctly (#23319) 2021-05-17 16:32:16 -04:00
Liam DeBeasi
faa93ad975 chore(): do not rebuild core when doing e2e tests, run vue spec and e2e tests together (#23320) 2021-05-17 16:31:09 -04:00
Liam DeBeasi
4da5216b4f fix(react): support history@5 in preparation for react router 6 (#23297)
resolves #23294
2021-05-14 09:03:15 -04:00
Liam DeBeasi
f71109b088 merge release-5.6.7
Release 5.6.7
2021-05-13 10:00:26 -04:00
Liam DeBeasi
eb10a2ab0c merge release-5.6.7
5.6.7
2021-05-13 10:00:18 -04:00
Liam DeBeasi
d802a17047 5.6.7 2021-05-13 09:04:18 -04:00
Liam DeBeasi
a9b12a5aa4 fix(overlays): screen readers no longer read content behind overlays (#23284)
resolves #22714
2021-05-11 09:51:37 -04:00
Liam DeBeasi
9cb6c80b3d fix(angular): warnings are no longer generated when running tests with ng test (#23292)
resolves #19926

Co-authored-by: Sean Wu <seanwu1105@users.noreply.github.com>
2021-05-11 09:49:25 -04:00
Liam DeBeasi
1e1596f471 fix(refresher): refresher now only activates when pulling down on MD (#23283)
resolves #23245
2021-05-10 09:38:14 -04:00
Matthias Max
f36eabccb8 docs(modal): document stacked modal behavior (#23279) 2021-05-07 11:56:26 -04:00
William Martin
03d5fcb6c8 chore(): revert #23181
Reverts #23181
2021-05-03 16:29:58 -04:00
Mohammd Alamgir Siddiqui
2e00dab95d fix(vue): use correct history mode when doing ssr to avoid errors (#23255)
resolves #23254
2021-05-03 15:32:20 -04:00
William Martin
d94739f39b fix(modal): add additional padding to toolbars in iOS modal (#23181)
resolves #22778
2021-05-03 10:44:41 -04:00
Liam DeBeasi
44e18bd795 merge release-5.6.6
Release 5.6.6
2021-04-29 10:31:45 -04:00
Liam DeBeasi
ccf0f14b81 merge release-5.6.6
5.6.6
2021-04-29 10:31:34 -04:00
Liam DeBeasi
c32bed6794 5.6.6 2021-04-29 10:06:48 -04:00
William Martin
c501da73be fix(react): remove hardware back button event listener when NavManager is unmounted (#23224)
resolves #23170
2021-04-28 17:47:33 -04:00
Liam DeBeasi
f2f41e2af4 fix(vue): components inside of ion-nav are now unmounted properly (#23240)
resolves #23233
2021-04-26 12:58:34 -04:00
Liam DeBeasi
e436439e10 fix(angular): back button goes back to proper tab on angular 11.2.10 (#23238)
resolves #23230
2021-04-26 12:55:48 -04:00
Liam DeBeasi
2ccaabb5b4 fix(slides): undefined error is no longer thrown after destroying and quickly re-creating ion-slides (#23239)
resolves #22289
2021-04-26 12:25:23 -04:00
Liam DeBeasi
dab927d290 fix(vue): overlay events can now be listened for without the "on" prefix, deprecated "on" prefix event listeners (#23227) 2021-04-23 11:38:45 -04:00
Liam DeBeasi
f4d265eb60 merge release-5.6.5
Release 5.6.5
2021-04-22 13:37:44 -04:00
Liam DeBeasi
0ac8ec1f05 merge release-5.6.5
5.6.5
2021-04-22 13:37:30 -04:00
Liam DeBeasi
287205480a 5.6.5 2021-04-22 10:13:17 -04:00
Tucker Whitehouse
0dd189e2c0 fix(react): callback refs now work correctly with ionic components (#23152)
resolves #23153
2021-04-22 09:56:04 -04:00
Liam DeBeasi
004885bfd4 fix(vue): dynamic tabs are now correct recognized (#23212)
resolves #22847
2021-04-21 15:14:30 -04:00
William Martin
7139b3f39e fix(radio-group): pressing spacebar correctly unselects radio with allow-empty-selection (#23194)
resolves #22734
2021-04-21 14:34:27 -04:00
William Martin
a31fb55bac fix(datetime, input, textarea): remove aria-labelledby when there is no adjacent ion-label (#23211)
* fix(datetime, input, textarea): remove aria-labelledby when there is no adjacent ion-label

* Update core/src/components/input/test/a11y/input.spec.ts

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>

* Update core/src/components/textarea/test/a11y/textarea.spec.ts

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>

* Update core/src/components/datetime/test/a11y/datetime.spec.ts

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>

* remove hard-coded label, fix whitespace

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
2021-04-20 12:34:32 -04:00
Liam DeBeasi
35c8802c22 fix(vue): update props when navigating to new parameterized route (#23189) 2021-04-15 12:37:50 -04:00
Brandy Carney
15abc181aa test(cypress): migrate Angular tests to Cypress (#23083) 2021-04-15 11:59:27 -04:00
Liam DeBeasi
ff7922a1a5 chore(vue): fix typo in comments (#23192) 2021-04-15 09:44:27 -04:00
William Martin
2d07d8216a fix(content): change main child element to div when parent is menu (#23160)
* fix(content): change main child element to div when parent is menu

* fix(content): change main child element to div when parent is menu, popover, or modal

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>

* fix(content): make closest element detector unreactive

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
2021-04-12 09:22:24 -04:00
William Martin
91ac340ae7 fix(segment, segment-button): use correct tablist and tab roles for screen readers (#23145)
* fix(segment, segment-button): change aria attributes for segment and segment-button

* add axe test

* Add tests, screen reader doc

* add updated screen reader

* fix(segment-button): move aria tags to host

* verify nvda and talkback behavior

* fix(segment-button): remove outline on focus

* Update core/src/components/segment/test/basic/index.html

Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
2021-04-12 09:20:59 -04:00
Liam DeBeasi
669d24c551 tests(vue): improve reliability of e2e tests (#23168) 2021-04-08 14:00:07 -04:00
Liam DeBeasi
d7b1acce14 merge release-5.6.4
5.6.4
2021-04-08 13:14:37 -04:00
Liam DeBeasi
1e8dfb7d85 merge release-5.6.4
Release 5.6.4
2021-04-08 13:14:26 -04:00
Liam DeBeasi
0e1cb1bb0c 5.6.4 2021-04-08 12:49:11 -04:00
William Martin
61f094d306 fix(input): inherit aria-label to input (#23159) 2021-04-07 14:44:03 -04:00
Ikko Ashimine
8739c9b16d test(slides): fix typo in test (#23158) 2021-04-07 09:42:17 -04:00
Liam DeBeasi
7203190234 fix(react, vue): correct view now chosen when going back inside tabs (#23154)
resolves #23087
resolves #23101
2021-04-06 10:16:23 -04:00
William Martin
42e6c90c46 fix(toggle): prevent click event from firing twice (#23146)
resolves #23041
2021-04-06 09:54:29 -04:00
Liam DeBeasi
dee6eb30df fix(react): overlays now correctly unmount any child components after dismissing (#23149)
resolves #23140
2021-04-06 09:53:26 -04:00
Liam DeBeasi
6df1215ee2 tests(react): run e2e tests on CI (#23147) 2021-04-05 12:37:28 -04:00
William Martin
b0d53ca736 docs(action-sheet, alert, popover, toast): update usage to show onDidDismiss (#23133) 2021-04-02 13:00:36 -04:00
William Martin
ef1a82f64a docs(alert): add input handler to usage examples (#23131) 2021-04-02 12:58:59 -04:00
William Martin
f4eb4b34d6 docs(reorder-group): fix vue usage of reorder-group (#23130)
resolves https://github.com/ionic-team/ionic-docs/issues/1804
2021-04-01 16:19:02 -04:00
capc0
28c52fd4e3 fix(angular): swiping back quickly no longer causes app to get stuck (#23125)
resolves #15154
2021-04-01 09:57:04 -04:00
William Martin
b7b97ce4cc docs(modal): update angular usage for consistent modalController (#23127) 2021-03-31 20:25:28 -04:00
Liam DeBeasi
27318cf585 fix(vue): account for event name changes in vue 3.0.6+ for overlay components (#23100) 2021-03-29 15:30:31 -04:00
Liam DeBeasi
ba51daf17c fix(vue): components now integrate properly with vee-validate (#23114)
resolves #22886
2021-03-29 14:34:52 -04:00
Liam DeBeasi
eacd8f6d27 test(vue): run vue e2e and unit tests on ci (#23113) 2021-03-29 13:37:37 -04:00
Liam DeBeasi
4bbbf89f43 chore(): update process guide for needs reproduction label (#23098) 2021-03-24 09:54:12 -04:00
Liam DeBeasi
9f023c92c4 merge release-5.6.3
Release 5.6.3
2021-03-23 11:21:16 -04:00
Liam DeBeasi
8e0e5da740 merge release-5.6.3
5.6.3
2021-03-23 11:21:04 -04:00
Liam DeBeasi
ddbdc6b1b3 chore(): add missing fix to changelog 2021-03-23 10:45:09 -04:00
Liam DeBeasi
f0cfe5a283 5.6.3 2021-03-23 10:41:42 -04:00
Liam DeBeasi
0cdd326a4a chore(): update tslib dependency to latest (#23092) 2021-03-23 10:30:09 -04:00
Liam DeBeasi
694d47b794 merge release-5.6.2
Release 5.6.2
2021-03-22 17:07:08 -04:00
Liam DeBeasi
7b140b1e12 merge release-5.6.2
5.6.2
2021-03-22 17:06:56 -04:00
Liam DeBeasi
1c93b75e39 fix(react): correctly show ion-back-button when going back (#23069)
resolves #22692
2021-03-22 16:11:45 -04:00
Liam DeBeasi
5fef3e7b21 5.6.2 2021-03-22 16:07:34 -04:00
Liam DeBeasi
b04fb6e849 fix(item): detail icon now respects rtl mode (#23081)
resolves #23078
2021-03-22 15:49:33 -04:00
Liam DeBeasi
b87c555a6e merge release-5.6.1
Release 5.6.1
2021-03-18 09:36:55 -04:00
Liam DeBeasi
8ac4d12f40 merge release-5.6.1
5.6.1
2021-03-18 09:36:47 -04:00
Liam DeBeasi
a0ff24b5d6 5.6.1 2021-03-17 12:59:08 -04:00
Brandy Carney
c8a3999da1 fix(label): properly float labels for non-input items (#23060) 2021-03-17 12:32:50 -04:00
Liam DeBeasi
67617fbc0f fix(refresher): progressEnd no longer errors when pulling quickly in MD native refresher (#23056) 2021-03-16 11:28:10 -04:00
Liam DeBeasi
c877061a32 fix(item): detail icon is no longer announced by screen readers (#23055)
resolves #23054
2021-03-16 09:59:30 -04:00
Liam DeBeasi
2f54bc1469 fix(vue): passing params as props are correctly updated when switching pages (#23049)
resolves #23043
2021-03-16 09:31:45 -04:00
Liam DeBeasi
2a253a1d33 fix(virtual-scroll): allow null in items prop (#23047)
Co-authored-by: Robert Rhoades <studioromeo@users.noreply.github.com>
2021-03-15 12:16:55 -04:00
Victor Berchet
4ce62b26a8 fix(router): simplify param merging (#22999) 2021-03-15 11:45:56 -04:00
Liam DeBeasi
e4bf052794 fix(): overlays now present correctly when using custom elements build (#23039)
resolves #23029
2021-03-15 09:13:23 -04:00
Evgeniy
630848ae5c chore(): remove duplicate --color definition in ion-item (#23030) 2021-03-10 09:56:03 -05:00
Liam DeBeasi
f94e618a7b fix(react): only pass tab event props from IonTabs to IonTabBar if defined (#23024)
resolves #23023
2021-03-05 16:03:14 -05:00
Liam DeBeasi
de58238333 merge release-5.6.0
5.6.0
2021-03-04 14:14:24 -05:00
Liam DeBeasi
1a2fd2fb6e 5.6.0 2021-03-04 13:54:38 -05:00
Liam DeBeasi
a1f95264e7 chore(): remove core/components from separate package release (#23018) 2021-03-04 13:38:09 -05:00
Brandy Carney
e256d3f09f feat(progress): add parts for more design customization (#22938)
resolves #20062 fixes #21820
2021-03-04 12:48:52 -05:00
Brandy Carney
e828a9a693 docs(github): update component guide to include switch (#22994)
adds a notice of webkit bug with VoiceOver
2021-03-03 14:10:05 -05:00
Liam DeBeasi
dcf5317310 docs(modal): remove incorrect ion-page note for react (#23009) 2021-03-03 10:46:29 -05:00
Liam DeBeasi
f022464cf8 docs(menu, split-pane): update contentId docs to be more clear (#23008) 2021-03-03 10:40:39 -05:00
Liam DeBeasi
38eb378d66 chore(): update web driver (#23010) 2021-03-03 10:06:28 -05:00
Liam DeBeasi
a2763afe8e fix(vue): correctly remove active state from tab button when navigating away from tab (#23000)
resolves #22597
2021-03-03 09:26:46 -05:00
Liam DeBeasi
943e3f6ae3 fix(react, vue): tab buttons no longer throw an error if href is undefined (#22998)
resolves #22997
2021-03-02 10:05:59 -05:00
Brandy Carney
9282aa6871 fix(label): only show placeholder with floating label when focused (#22958)
fixes #17571
2021-03-01 15:36:29 -05:00
Ely Lucas
b83e00934e feat(react): add react hooks to control overlay components (#22484) 2021-03-01 11:34:13 -05:00
Liam DeBeasi
dd1c8dbf3b feat(vue): add composition API ionic lifecycle hooks (#22970)
resolves #22769
2021-03-01 10:35:25 -05:00
Liam DeBeasi
9486e51f6d merge release-5.5.5
Release 5.5.5
2021-02-26 14:51:05 -05:00
Liam DeBeasi
fb631742af chore(): run build 2021-02-26 14:26:06 -05:00
Liam DeBeasi
0101a5fce2 5.5.5 2021-02-26 14:10:48 -05:00
Liam DeBeasi
06d4c8e6f1 fix(vue): account for event name changes in vue 3.0.6+ 2021-02-26 14:10:42 -05:00
Liam DeBeasi
cd8ffd82a0 fix(react, vue): navigating using ion-back-button now selects correct page (#22974)
resolves #22830
2021-02-25 13:18:20 -05:00
Dominik Geng
b6b2714d70 fix(progress-bar): use correct theme colors in dark mode (#22965)
resolves #20098

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
2021-02-24 16:40:40 -05:00
Liam DeBeasi
8c1646a105 fix(progress-bar): add width transition (#22964) 2021-02-24 11:27:18 -05:00
Liam DeBeasi
68a9b80053 fix(vue): prevent race conditions when opening overlays (#22883)
resolves #22880
2021-02-23 14:42:38 -05:00
Liam DeBeasi
26285bbc91 fix(progress-bar): use correct theme colors in dark mode (#22957)
resolves #20098

Co-authored-by: Dominik Geng <domske@users.noreply.github.com>
2021-02-23 13:13:38 -05:00
Hans Krywalsky
215eb5d4ef feat(searchbar): add showClearIcon property (#22759)
resolves #22738

Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
2021-02-23 12:34:42 -05:00
Liam DeBeasi
677d55ebe4 test(): update theming test with latest dark mode values (#22956) 2021-02-23 12:34:04 -05:00
Liam DeBeasi
a4c38aca88 chore(): update package-lock to account for npm 7.5.3 bug fix (#22963) 2021-02-23 11:41:51 -05:00
Liam DeBeasi
5300dcc693 fix(header): collapsed toolbar is no longer incorrectly shown when using ion-refresher (#22937)
resolves #22829
2021-02-18 08:53:49 -05:00
Ely Lucas
b064fdebef fix(react): onIonTabsWillChange and onIonTabsDidChange event handlers are now properly bound to IonTabs (#22233)
Co-authored-by: Hansu Kim <khsily@users.noreply.github.com>
2021-02-11 14:50:07 -05:00
Yohann CINTRE
c05476b88e fix(refresher): add correct dark mode styles (#22639)
resolves #22637
2021-02-11 12:31:41 -05:00
Adam Bradley
0de75afbef feat(custom-elements): add experimental custom elements build (#22863)
Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
2021-02-11 12:08:00 -05:00
Liam DeBeasi
19d63f6243 fix(a11y): improve support for ids with special characters when getting label element (#22680)
resolves #22678
2021-02-11 11:34:03 -05:00
aleemosman
343f855147 chore(): update code of conduct (#22619)
Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
2021-02-11 09:35:02 -05:00
Liam DeBeasi
da1b7a0e7a fix(react): IonRouterOutlet now respects animated={false} prop (#22905)
resolves #22903
2021-02-10 15:05:04 -05:00
Liam DeBeasi
3a0465e7d6 fix(radio-group): pressing space no longer jumps screen to bottom of page (#22892)
resolves #22716
2021-02-09 12:56:58 -05:00
Liam DeBeasi
8cb2ea6804 test(): update modal dark theme, fix styles test (#22884) 2021-02-05 12:55:57 -05:00
Liam DeBeasi
d46e074fb1 merge release-5.5.4
5.5.4
2021-02-04 11:50:39 -05:00
598 changed files with 151666 additions and 48055 deletions

View File

@@ -1,486 +0,0 @@
version: 2.1
aliases:
- &restore-cache
keys:
- dependency-cache-{{ checksum "package.json" }}-3
- &save-cache
key: dependency-cache-{{ checksum "package.json" }}-3
paths:
- node_modules
- &restore-cache-core
keys:
- dependency-cache-{{ checksum "core/package.json" }}-3
- &save-cache-core
key: dependency-cache-{{ checksum "core/package.json" }}-3
paths:
- core/node_modules
- &restore-cache-core-stencil
keys:
- stencil-cache-2
- &save-cache-core-stencil
key: stencil-cache-2
paths:
- core/.stencil
- core/screenshot/images
defaults: &defaults
docker:
- 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 --legacy-peer-deps
- save_cache: *save-cache
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
build-core:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- restore_cache: *restore-cache-core
- restore_cache: *restore-cache-core-stencil
- run:
command: npm install --legacy-peer-deps
working_directory: /tmp/workspace/core
- save_cache: *save-cache-core
- run:
command: npm run build -- --ci
working_directory: /tmp/workspace/core
- save_cache: *save-cache-core-stencil
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
build-angular:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install --legacy-peer-deps
working_directory: /tmp/workspace/angular
- run:
command: sudo npm link
working_directory: /tmp/workspace/core
- run:
command: sudo npm link @ionic/core
working_directory: /tmp/workspace/angular
- run:
command: npm run build
working_directory: /tmp/workspace/angular
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
build-angular-server:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install --legacy-peer-deps
working_directory: /tmp/workspace/packages/angular-server
- run:
command: npm run build.prod
working_directory: /tmp/workspace/packages/angular-server
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
build-react:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install --legacy-peer-deps
working_directory: /tmp/workspace/packages/react
- run:
command: sudo npm link
working_directory: /tmp/workspace/core
- run:
command: sudo npm link @ionic/core
working_directory: /tmp/workspace/packages/react
- run:
command: npm run build
working_directory: /tmp/workspace/packages/react
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
build-react-router:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install --legacy-peer-deps
working_directory: /tmp/workspace/packages/react-router
- run:
command: sudo npm link
working_directory: /tmp/workspace/core
- run:
command: sudo npm link @ionic/core
working_directory: /tmp/workspace/packages/react-router
- run:
command: sudo npm link
working_directory: /tmp/workspace/packages/react
- run:
command: sudo npm link @ionic/react
working_directory: /tmp/workspace/packages/react-router
- run:
command: npm run build
working_directory: /tmp/workspace/packages/react-router
- persist_to_workspace:
root: /tmp/workspace
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:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
name: Checking clean build
command: git diff --exit-code
working_directory: /tmp/workspace/core
test-core-lint:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run lint
working_directory: /tmp/workspace/core
test-core-e2e:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run test.e2e --ci
working_directory: /tmp/workspace/core
test-core-spec:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run test.spec --ci
working_directory: /tmp/workspace/core
test-core-treeshake:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run test.treeshake --ci
working_directory: /tmp/workspace/core
test-core-screenshot:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
name: Run Screenshot
command: npx stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci || true
working_directory: /tmp/workspace/core
test-core-screenshot-master:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
name: Run Screenshot
command: npx stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci --update-screenshot || true
working_directory: /tmp/workspace/core
test-angular-lint:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run lint
working_directory: /tmp/workspace/angular
test-react-lint:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run lint
working_directory: /tmp/workspace/packages/react
test-react-router-lint:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
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:
- 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/react
- run:
command: npm run test.spec
working_directory: /tmp/workspace/packages/react
test-react-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/react
- run:
command: sudo npm link
working_directory: /tmp/workspace/packages/react
- run:
command: sudo npm link @ionic/react
working_directory: /tmp/workspace/packages/react-router
- run:
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:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install --legacy-peer-deps
working_directory: /tmp/workspace/angular/test/test-app
- run:
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]
- test-core-clean-build:
requires: [build-core]
- test-core-lint:
requires: [build-core]
- test-core-e2e:
requires: [puppeteer-dependencies, build-core]
- test-core-spec:
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:
branches:
ignore: master
- test-core-screenshot-master:
requires: [build-core]
filters:
branches:
only: master
- build-angular:
requires: [build-core]
- build-angular-server:
requires: [build-angular]
- build-react:
requires: [build-core]
- build-react-router:
requires: [build-core, build-react]
- test-react-lint:
requires: [build-react]
- test-react-router-lint:
requires: [build-react-router]
- test-react-spec:
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:
requires:
- build-angular
- build-angular-server

View File

@@ -11,10 +11,12 @@
* [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)
- [Converting Scoped to Shadow](#converting-scoped-to-shadow)
- [RTL](#rtl)
## Button States
@@ -354,9 +356,9 @@ ion-ripple-effect {
### Example Components
- [ion-button](https://github.com/ionic-team/ionic/tree/master/core/src/components/button)
- [ion-back-button](https://github.com/ionic-team/ionic/tree/master/core/src/components/back-button)
- [ion-menu-button](https://github.com/ionic-team/ionic/tree/master/core/src/components/menu-button)
- [ion-button](https://github.com/ionic-team/ionic/tree/main/core/src/components/button)
- [ion-back-button](https://github.com/ionic-team/ionic/tree/main/core/src/components/back-button)
- [ion-menu-button](https://github.com/ionic-team/ionic/tree/main/core/src/components/menu-button)
### References
@@ -370,8 +372,7 @@ ion-ripple-effect {
#### Example Components
- [ion-checkbox](https://github.com/ionic-team/ionic/tree/master/core/src/components/checkbox)
- [ion-toggle](https://github.com/ionic-team/ionic/tree/master/core/src/components/toggle)
- [ion-checkbox](https://github.com/ionic-team/ionic/tree/main/core/src/components/checkbox)
#### VoiceOver
@@ -432,9 +433,13 @@ const { label, labelId, labelText } = getAriaLabel(el, inputId);
where `el` and `inputId` are the following:
```tsx
private inputId = `ion-cb-${checkboxIds++}`;
export class Checkbox implements ComponentInterface {
private inputId = `ion-cb-${checkboxIds++}`;
@Element() el!: HTMLElement;
@Element() el!: HTMLElement;
...
}
```
This can then be added to the `Host` like the following:
@@ -448,7 +453,7 @@ This can then be added to the `Host` like the following:
>
```
In addition to that, the checkbox should have a label added:
In addition to that, the checkbox input should have a label added:
```tsx
<Host
@@ -489,17 +494,148 @@ 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/main/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.
### Example Components
- [ion-button](https://github.com/ionic-team/ionic/tree/master/core/src/components/button)
- [ion-card](https://github.com/ionic-team/ionic/tree/master/core/src/components/card)
- [ion-fab-button](https://github.com/ionic-team/ionic/tree/master/core/src/components/fab-button)
- [ion-item-option](https://github.com/ionic-team/ionic/tree/master/core/src/components/item-option)
- [ion-item](https://github.com/ionic-team/ionic/tree/master/core/src/components/item)
- [ion-button](https://github.com/ionic-team/ionic/tree/main/core/src/components/button)
- [ion-card](https://github.com/ionic-team/ionic/tree/main/core/src/components/card)
- [ion-fab-button](https://github.com/ionic-team/ionic/tree/main/core/src/components/fab-button)
- [ion-item-option](https://github.com/ionic-team/ionic/tree/main/core/src/components/item-option)
- [ion-item](https://github.com/ionic-team/ionic/tree/main/core/src/components/item)
### Component Structure
@@ -568,3 +704,39 @@ There will be some CSS issues when converting to shadow. Below are some of the d
/* IN SHADOW*/
:host-context(ion-toolbar:not(.ion-color)):host(:not(.ion-color)) ::slotted(ion-segment-button) {
```
## RTL
When you need to support both LTR and RTL modes, try to avoid using values such as `left` and `right`. For certain CSS properties, you can use the appropriate mixin to have this handled for you automatically.
For example, if you wanted `transform-origin` to be RTL-aware, you would use the `transform-origin` mixin:
```css
@include transform-origin(start, center);
```
This would output `transform-origin: left center` in LTR mode and `transform-origin: right center` in RTL mode.
These mixins depend on the `:host-context` pseudo-class when used inside of shadow components, which is not supported in WebKit. As a result, these mixins will not work in Safari for macOS and iOS when applied to shadow components.
To work around this, you should set an RTL class on the host of your component and set your RTL styles by targeting that class:
```tsx
<Host
class={{
'my-cmp-rtl': document.dir === 'rtl'
})
>
...
</Host>
```
```css
:host {
transform-origin: left center;
}
:host(.my-cmp-rtl) {
transform-origin: right center;
}
```

View File

@@ -15,6 +15,12 @@ Thanks for your interest in contributing to the Ionic Framework! :tada:
+ [Modifying Tests](#modifying-tests)
- [Screenshot Tests](#screenshot-tests)
+ [Building Changes](#building-changes)
* [Angular, React, and Vue](#angular-react-and-vue)
+ [Modifying Files](#modifying-files)
+ [Preview Changes](#preview-changes-1)
+ [Lint Changes](#lint-changes-1)
+ [Modifying Tests](#modifying-tests-1)
+ [Building Changes](#building-changes-1)
* [Submit Pull Request](#submit-pull-request)
- [Commit Message Guidelines](#commit-message-guidelines)
* [Commit Message Format](#commit-message-format)
@@ -30,7 +36,7 @@ Thanks for your interest in contributing to the Ionic Framework! :tada:
## Contributing Etiquette
Please see our [Contributor Code of Conduct](https://github.com/ionic-team/ionic/blob/master/CODE_OF_CONDUCT.md) for information on our rules of conduct.
Please see our [Contributor Code of Conduct](https://github.com/ionic-team/ionic/blob/main/CODE_OF_CONDUCT.md) for information on our rules of conduct.
## Creating an Issue
@@ -87,7 +93,7 @@ Without a reliable code reproduction, it is unlikely we will be able to resolve
1. [Download the installer](https://nodejs.org/) for the LTS version of Node.js. This is the best way to also [install npm](https://blog.npmjs.org/post/85484771375/how-to-install-npm#_=_).
2. Fork this repository.
3. Clone your fork.
4. Create a new branch from master for your change.
4. Create a new branch from main for your change.
5. Navigate into the directory of the package you wish to modify (core, angular, etc.).
6. Run `npm install` to install dependencies for this package.
7. Follow the steps for the specific package below.
@@ -160,17 +166,67 @@ Without a reliable code reproduction, it is unlikely we will be able to resolve
3. Make sure the build has finished before committing. If you made changes to the documentation, properties, methods, or anything else that requires an update to a generate file, this needs to be committed.
4. After the changes have been pushed, publish the branch and [create a pull request](#creating-a-pull-request).
### Angular, React, and Vue
#### Modifying Files
1. Locate the files inside the relevant root directory:
- Angular: `/angular/src`
- React: `/packages/react/src`
- Vue: `/packages/vue/src`
2. Make your changes to the files. If the change is overly complex or out of the ordinary, add comments so we can understand the changes.
3. Run lint on the directory and make sure there are no errors.
4. Build the project.
5. After the build is finished, commit the changes. Please follow the [commit message format](#commit-message-format) for every commit.
6. [Submit a Pull Request](#submit-pull-request) of your changes.
#### Preview Changes
1. Run `npm run start` inside of the relevant test app directory. This will sync your previously built changes into a test Ionic app:
- Angular: `/angular/test-app`
- React: `/packages/react/test-app`
- Vue: `/packages/vue/test-app`
2. In a browser, navigate to the page you wish to test.
3. Alternatively, create a new page if you need to test something that is not already there.
#### Lint Changes
1. Run `npm run lint` to lint the TypeScript in the relevant directory:
- Angular: `/angular/src`
- React: `/packages/react/src`
- Vue: `/packages/vue/src`
2. If there are lint errors, run `npm run lint.fix` to automatically fix any errors. Repeat step 1 to ensure the errors have been fixed, and manually fix them if not.
#### Modifying Tests
1. Locate the test to modify inside the relevant test app directory:
- Angular: `/angular/test-app/e2e/src`
- React: `/packages/react/test-app/cypress/integration`
- Vue: `/packages/vue/test-app/tests/e2e`
2. If a test exists, modify the test by adding an example to reproduce the problem fixed or feature added.
3. If a new test is needed, copy an existing test, rename it, and edit the content in the test file.
4. Run `npm run test` to run your tests.
#### Building Changes
1. Once all changes have been made, run `npm run build` inside of the root directory. This will add your changes to any auto-generated files, if necessary.
2. Review the changes and, if everything looks correct, [commit](#commit-message-format) the changes.
3. Make sure the build has finished before committing. If you made changes to the documentation, properties, methods, or anything else that requires an update to a generate file, this needs to be committed.
4. After the changes have been pushed, publish the branch and [create a pull request](#creating-a-pull-request).
### Submit Pull Request
1. [Create a new pull request](https://github.com/ionic-team/ionic/compare) with the `master` branch as the `base`. You may need to click on `compare across forks` to find your changes.
1. [Create a new pull request](https://github.com/ionic-team/ionic/compare) with the `main` branch as the `base`. You may need to click on `compare across forks` to find your changes.
2. See the [Creating a pull request from a fork](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) GitHub help article for more information.
3. Please fill out the provided Pull Request template to the best of your ability and include any issues that are related.
## Commit Message Guidelines
We have very precise rules over how our git commit messages should be formatted. This leads to readable messages that are easy to follow when looking through the project history. We also use the git commit messages to generate our [changelog](https://github.com/ionic-team/ionic/blob/master/CHANGELOG.md). Our format closely resembles Angular's [commit message guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit).
We have very precise rules over how our git commit messages should be formatted. This leads to readable messages that are easy to follow when looking through the project history. We also use the git commit messages to generate our [changelog](https://github.com/ionic-team/ionic/blob/main/CHANGELOG.md). Our format closely resembles Angular's [commit message guidelines](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit).
### Commit Message Format

View File

@@ -1,59 +0,0 @@
---
name: Bug Report
about: Create a report to help us improve
title: 'bug: '
labels: ''
assignees: ''
---
<!-- Before submitting an issue, please consult our docs (https://ionicframework.com/docs/). -->
<!-- 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 the Ionic Forum: https://forum.ionicframework.com/ -->
<!-- ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. -->
# Bug Report
**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) -->
[ ] **4.x**
[x] **5.x**
**Current behavior:**
<!-- Describe how the bug manifests. -->
**Expected behavior:**
<!-- Describe what the behavior would be without the bug. -->
**Steps to reproduce:**
<!-- Please explain the steps required to duplicate the issue, especially if you are able to provide a sample application. -->
**Related code:**
<!-- If you are able to illustrate the bug or feature request with an example, please provide a sample application via one of the following means:
A sample application via GitHub
StackBlitz (https://stackblitz.com)
Ionic Angular StackBlitz: https://stackblitz.com/edit/ionic-v4-angular-tabs
Plunker (http://plnkr.co/edit/cpeRJs?p=preview)
-->
```
insert short code snippets here
```
**Other information:**
<!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. -->
**Ionic info:**
<!-- (run `ionic info` from a terminal/cmd prompt and paste output below): -->
```
insert the output from ionic info here
```

56
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,56 @@
name: 🐛 Bug Report
description: Create a report to help us improve Ionic Framework
title: 'bug: '
body:
- type: checkboxes
attributes:
label: Prerequisites
description: Please ensure you have completed all of the following.
options:
- label: I have read the [Contributing Guidelines](https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#creating-an-issue).
required: true
- label: I agree to follow the [Code of Conduct](https://ionicframework.com/code-of-conduct).
required: true
- label: I have searched for [existing issues](https://github.com/ionic-team/ionic-framework/issues) that already report this problem, without success.
required: true
- type: checkboxes
attributes:
label: Ionic Framework Version
description: Please select which versions of Ionic Framework this issue impacts. For Ionic Framework 1.x issues, please use https://github.com/ionic-team/ionic-v1. For Ionic Framework 2.x and 3.x issues, please use https://github.com/ionic-team/ionic-v3.
options:
- label: v4.x
- label: v5.x
- label: v6.x
- type: textarea
attributes:
label: Current Behavior
description: A clear description of what the bug is and how it manifests.
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A clear description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Steps to Reproduce
description: Please explain the steps required to duplicate this issue.
validations:
required: true
- type: input
attributes:
label: Code Reproduction URL
description: Please reproduce this issue in a blank Ionic Framework starter application and provide a link to the repo. Try out our [Getting Started Wizard](https://ionicframework.com/start#basics) to quickly spin up an Ionic Framework starter app. This is the best way to ensure this issue is triaged quickly. Issues without a code reproduction may be closed if the Ionic Team cannot reproduce the issue you are reporting.
placeholder: https://github.com/...
- type: textarea
attributes:
label: Ionic Info
description: Please run `ionic info` from within your Ionic Framework project directory and paste the output below.
validations:
requred: true
- type: textarea
attributes:
label: Additional Information
description: List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc.

View File

@@ -1,11 +0,0 @@
---
name: CLI
about: Suggest an improvement for the CLI
title: ''
labels: 'ionitron: cli'
assignees: ''
---
# CLI
Please do not submit bug reports or feature requests related to the Ionic CLI. Instead, please submit an issue to the [Ionic CLI Repository](https://github.com/ionic-team/ionic-cli/issues/new/choose).

10
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
contact_links:
- name: 📚 Documentation
url: https://github.com/ionic-team/ionic-docs/issues/new/choose
about: This issue tracker is not for documentation issues. Please file documentation issues on the Ionic Docs repo.
- name: 💻 CLI
url: https://github.com/ionic-team/ionic-cli/issues/new/choose
about: This issue tracker is not for CLI issues. Please file CLI issues on the Ionic CLI repo.
- name: 🤔 Support Question
url: https://forum.ionicframework.com/
about: This issue tracker is not for support questions. Please post your question on the Ionic Forums.

View File

@@ -1,11 +0,0 @@
---
name: Documentation
about: Suggest an improvement for the documentation of this project
title: ''
labels: 'ionitron: docs'
assignees: ''
---
# Documentation
Please do not submit issues on how to improve or fix the documentation. Instead, please submit an issue to the [Ionic Docs Repository](https://github.com/ionic-team/ionic-docs/issues/new/choose).

View File

@@ -1,37 +0,0 @@
---
name: Feature Request
about: Suggest an idea for this project
title: 'feat: '
labels: ''
assignees: ''
---
<!-- Before submitting an issue, please consult our docs (https://ionicframework.com/docs/). -->
<!-- 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/ -->
<!-- ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. -->
# Feature Request
**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**
**Describe the Feature Request**
<!-- A clear and concise description of what the feature request is. Please include if your feature request is related to a problem. -->
**Describe Preferred Solution**
<!-- A clear and concise description of what you want to happen. -->
**Describe Alternatives**
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
**Related Code**
<!-- If you are able to illustrate the feature request with an example, please provide a sample application via an online code collaborator such as [StackBlitz](https://stackblitz.com), or [GitHub](https://github.com). -->
**Additional Context**
<!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to add, use case, Stack Overflow links, forum links, screenshots, OS if applicable, etc. -->

View File

@@ -0,0 +1,43 @@
name: 💡 Feature Request
description: Suggest an idea for Ionic Framework
title: 'feat: '
body:
- type: checkboxes
attributes:
label: Prerequisites
description: Please ensure you have completed all of the following.
options:
- label: I have read the [Contributing Guidelines](https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#creating-an-issue).
required: true
- label: I agree to follow the [Code of Conduct](https://ionicframework.com/code-of-conduct).
required: true
- label: I have searched for [existing issues](https://github.com/ionic-team/ionic-framework/issues) that already include this feature request, without success.
required: true
- type: textarea
attributes:
label: Describe the Feature Request
description: A clear and concise description of what the feature does.
validations:
required: true
- type: textarea
attributes:
label: Describe the Use Case
description: A clear and concise use case for what problem this feature would solve.
validations:
required: true
- type: textarea
attributes:
label: Describe Preferred Solution
description: A clear and concise description of what you how you want this feature to be added to Ionic Framework.
- type: textarea
attributes:
label: Describe Alternatives
description: A clear and concise description of any alternative solutions or features you have considered.
- type: textarea
attributes:
label: Related Code
description: If you are able to illustrate the feature request with an example, please provide a sample Ionic Framework application. Try out our [Getting Started Wizard](https://ionicframework.com/start#basics) to quickly spin up an Ionic Framework starter app.
- type: textarea
attributes:
label: Additional Information
description: List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to implement, Stack Overflow links, forum links, etc.

View File

@@ -1,11 +0,0 @@
---
name: Support Question
about: Question on how to use this project
title: 'support: '
labels: 'ionitron: support'
assignees: ''
---
# Support Question
Please do not submit support requests or "How to" questions here. Instead, please use the Ionic Forum: https://forum.ionicframework.com/

74
.github/PROCESS.md vendored
View File

@@ -60,7 +60,7 @@ If the issue is associated with Ionic Appflow the submitter should be told to us
### Support Questions
If the issue is a support question, the submitter should be redirected to our [forum](https://forum.ionicframework.com) or [slack channel](https://ionicworldwide.herokuapp.com/). The issue should be closed and locked. Use the `ionitron: support` label to accomplish this.
If the issue is a support question, the submitter should be redirected to our [forum](https://forum.ionicframework.com). The issue should be closed and locked. Use the `ionitron: support` label to accomplish this.
### Incomplete Template
@@ -77,7 +77,15 @@ NOTE: be sure to perform those actions in the order stated. If you add the comme
If there is a response to the question, the bot will remove the `needs: reply` and apply the `triage` label. The issue will then go through the triage handling again.
If there is no response within 30 days, the issue will be closed and locked.
If there is no response within 14 days, the issue will be closed and locked.
### Missing Code Reproduction
If the information the submitter has supplied is not enough for you to reproduce the issue, add the `ionitron: needs reproduction` label. An automated comment will be added to the thread asking the submitter to provide a code reproduction of the issue.
This label can also be added when the submitter has supplied some code, but not enough for you to reproduce the issue (i.e. code snippets).
Issues with this label are not automatically closed and locked, so we manually close and lock them if there is no response within 14 days.
## Workflow
@@ -87,81 +95,81 @@ If there is no response within 30 days, the issue will be closed and locked.
We have two long-living branches:
- `master`: completed features, bug fixes, refactors, chores
- `main`: completed features, bug fixes, refactors, chores
- `stable`: the latest release
The overall flow:
1. Feature, refactor, and bug fix branches are created from `master`
1. When a feature, refactor, or fix is complete it is merged into `master`
1. A release branch is created from `master`
1. When the release branch is done it is merged into `master` and `stable`
1. Feature, refactor, and bug fix branches are created from `main`
1. When a feature, refactor, or fix is complete it is merged into `main`
1. A release branch is created from `main`
1. When the release branch is done it is merged into `main` and `stable`
1. If an issue in `stable` is detected a hotfix branch is created from `stable`
1. Once the hotfix is complete it is merged to both `master` and `stable`
1. All branches should follow the syntax of `{type}-{details}` where `{type}` is the type of branch (`hotfix`, `release`, or one of the [commit types](https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format)) and `{details}` is a few hyphen separated words explaining the branch
1. Once the hotfix is complete it is merged to both `main` and `stable`
1. All branches should follow the syntax of `{type}-{details}` where `{type}` is the type of branch (`hotfix`, `release`, or one of the [commit types](https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md#commit-message-format)) and `{details}` is a few hyphen separated words explaining the branch
### Stable and Master Branches
### Stable and Main Branches
#### Stable Branch
Branches created from `stable`:
The following branch should be merged back to **both** `master` and `stable`:
The following branch should be merged back to **both** `main` and `stable`:
- A `hotfix` branch (e.g. `hotfix-missing-export`): a bug fix that is fixing a regression or issue with a published release
A `hotfix` branch should be the **only** branch that is created from stable.
#### Master Branch
#### Main Branch
Branches created from `master`:
Branches created from `main`:
The following branches should be merged back to `master` via a pull request:
The following branches should be merged back to `main` via a pull request:
1. A feature branch (e.g. `feat-desktop-support`): an addition to the API that is not a bug fix or regression fix
1. A bug fix branch (e.g. `fix-tab-color`): a bug fix that is not fixing a regression or issue with a published release
1. All other types listed in the [commit message types](https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format): `docs`, `style`, `refactor`, `perf`, `test`, `chore`
1. All other types listed in the [commit message types](https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md#commit-message-format): `docs`, `style`, `refactor`, `perf`, `test`, `chore`
The following branch should be merged back to **both** `master` and `stable`:
The following branch should be merged back to **both** `main` and `stable`:
1. A `release` branch (e.g. `release-4.1.x`): contains all fixes and (optionally) features that are tested and should go into the release
### Feature Branches
Each new feature should reside in its own branch, based on the `master` branch. When a feature is complete, it should go into a pull request that gets merged back into `master`. A pull request adding a feature should be approved by two team members. Features should never interact directly with `stable`.
Each new feature should reside in its own branch, based on the `main` branch. When a feature is complete, it should go into a pull request that gets merged back into `main`. A pull request adding a feature should be approved by two team members. Features should never interact directly with `stable`.
### Release Branches
Once `master` has acquired enough features for a release (or a predetermined release date is approaching), fork a release branch off of `master`. Creating this branch starts the next release cycle, so no new features can be added after this point - only bug fixes, documentation generation, and other release-oriented tasks should go in this branch.
Once `main` has acquired enough features for a release (or a predetermined release date is approaching), fork a release branch off of `main`. Creating this branch starts the next release cycle, so no new features can be added after this point - only bug fixes, documentation generation, and other release-oriented tasks should go in this branch.
Once the release is ready to ship, it will get merged into `stable` and `master`, then the release branch will be deleted. Its important to merge back into `master` because critical updates may have been added to the release branch and they need to be accessible to new features. This should be done in a pull request after review.
Once the release is ready to ship, it will get merged into `stable` and `main`, then the release branch will be deleted. Its important to merge back into `main` because critical updates may have been added to the release branch and they need to be accessible to new features. This should be done in a pull request after review.
See the [steps for releasing](#releasing) below for detailed information on how to publish a release.
### Version Branches
Once a release has shipped and the release branch has been merged into `stable` and `master` it should also be merged into its corrsponding version branch. These version branches allow us to ship updates for specific versions of the framework (i.e. Lets us ship a bug fix that only affects 4.2.x).
Once a release has shipped and the release branch has been merged into `stable` and `main` it should also be merged into its corresponding version branch. These version branches allow us to ship updates for specific versions of the framework (i.e. Lets us ship a bug fix that only affects 4.2.x).
Patch releases should be merged into their corresponding version branches. For example, a `release-4.1.1` branch should be merged into the `4.1.x` version branch and a `release-5.0.1` branch should be merged into the `5.0.x` version branch.
When releasing a major version such as `5.0.0 ` or a minor version such as `4.1.0` , the version branch will not exist. The version branch should be created once the release branch has been merged into `stable` and `master`. For example, when releasing `4.1.0`, the `release-4.1.0` release branch should be merged into `stable` and `master` and then the `4.1.x` version branch should be created off the latest `stable`.
When releasing a major version such as `5.0.0 ` or a minor version such as `4.1.0` , the version branch will not exist. The version branch should be created once the release branch has been merged into `stable` and `main`. For example, when releasing `4.1.0`, the `release-4.1.0` release branch should be merged into `stable` and `main` and then the `4.1.x` version branch should be created off the latest `stable`.
### Hotfix Branches
Maintenance or “hotfix” branches are used to quickly patch production releases. This is the only branch that should fork directly off of `stable`. As soon as the fix is complete, it should be merged into both `stable` and `master` (or the current release branch).
Maintenance or “hotfix” branches are used to quickly patch production releases. This is the only branch that should fork directly off of `stable`. As soon as the fix is complete, it should be merged into both `stable` and `main` (or the current release branch).
### Examples
#### Making a Change
1. Create a branch from `master`.
1. Create a branch from `main`.
1. Make changes. Limit your changes to a "unit of work", meaning don't include irrelevant changes that may confuse and delay the change.
1. Push changes.
1. Create a PR with the base of `master`.
1. Create a PR with the base of `main`.
1. Have someone approve your change (optional right now--at your discretion).
<img width="236" alt="image" src="https://user-images.githubusercontent.com/236501/47031893-913e0480-d136-11e8-9d9a-4b6297a4d7ba.png">
@@ -174,13 +182,13 @@ Maintenance or “hotfix” branches are used to quickly patch production releas
<img width="192" alt="Squash and merge button" src="https://user-images.githubusercontent.com/236501/47031620-da418900-d135-11e8-91ff-e84f2478b2b3.png">
1. During confirmation, rewrite the commit message using our [Commit Message Format guidelines](https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format). Keep the `(#1234)` at the end; it will create a link to the PR in the commit history and `CHANGELOG.md`. This is where commits on `master` become permanent.
1. During confirmation, rewrite the commit message using our [Commit Message Format guidelines](https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md#commit-message-format). Keep the `(#1234)` at the end; it will create a link to the PR in the commit history and `CHANGELOG.md`. This is where commits on `main` become permanent.
<img width="672" alt="Squash and merge confirmation" src="https://user-images.githubusercontent.com/236501/47031753-31dff480-d136-11e8-9116-03934961bdc2.png">
1. Confirm squash and merge into `master`.
1. Confirm squash and merge into `main`.
#### Updating from `master`
#### Updating from `main`
1. Pull the latest changes locally.
1. Merge the changes, fixing any conflicts.
@@ -196,7 +204,7 @@ OR
#### Hotfixes
Hotfixes bypass `master` and should only be used for urgent fixes that can't wait for the next release to be ready.
Hotfixes bypass `main` and should only be used for urgent fixes that can't wait for the next release to be ready.
1. Create a branch from `stable`.
1. Make changes.
@@ -207,13 +215,13 @@ Hotfixes bypass `master` and should only be used for urgent fixes that can't wai
<img width="192" alt="Squash and merge button" src="https://user-images.githubusercontent.com/236501/47031620-da418900-d135-11e8-91ff-e84f2478b2b3.png">
1. During confirmation, rewrite the commit message using our [Commit Message Format guidelines](https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format). Keep the `(#1234)` at the end; it will create a link to the PR in the commit history and `CHANGELOG.md`. This is where commits on `master` become permanent.
1. During confirmation, rewrite the commit message using our [Commit Message Format guidelines](https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md#commit-message-format). Keep the `(#1234)` at the end; it will create a link to the PR in the commit history and `CHANGELOG.md`. This is where commits on `main` become permanent.
<img width="672" alt="Squash and merge confirmation" src="https://user-images.githubusercontent.com/236501/47031753-31dff480-d136-11e8-9116-03934961bdc2.png">
1. Confirm squash and merge into `stable`.
1. CI builds `stable`, performing the release.
1. Create a PR to merge `stable` into `master`.
1. Create a PR to merge `stable` into `main`.
1. Click **Merge pull request**. Use the dropdown to select this option if necessary.
<img width="191" alt="Merge pull request button" src="https://user-images.githubusercontent.com/236501/47032669-8be1b980-d138-11e8-9a90-d1518c223184.png">
@@ -221,7 +229,7 @@ Hotfixes bypass `master` and should only be used for urgent fixes that can't wai
## Releasing
1. Create the release branch from `master`, for example: `release-4.5.0`.
1. Create the release branch from `main`, for example: `release-4.5.0`.
1. For major or minor releases, create a version branch based off the latest version branch. For example, if releasing 4.5.0, create a branch called `4.5.x` based off `4.4.x`.
@@ -236,7 +244,7 @@ Hotfixes bypass `master` and should only be used for urgent fixes that can't wai
1. Run `npm run release.prepare`
- Select the version based on the type of commits and the [Ionic Versioning](https://ionicframework.com/docs/intro/versioning)
- After the process completes, verify the version number in all packages (`core`, `docs`, `angular`)
- Verify the changelog commits are accurate and follow the [proper format]((https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format))
- Verify the changelog commits are accurate and follow the [proper format]((https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md#commit-message-format))
- For major or minor releases, ensure that the version number has an associated title (for example: `4.5.0 Boron`)
- Commit these changes with the version number as the message, e.g. `git commit -m "4.5.0"`
@@ -250,4 +258,4 @@ Hotfixes bypass `master` and should only be used for urgent fixes that can't wai
1. Rewrite the commit message to `merge release-[VERSION]` with the proper release branch. For example, if this release is for `4.5.0`, the message would be `merge release-4.5.0`.
1. Submit a pull request from the release branch into `master`. Merge this pull request using the same commit format in the last step, to ensure any changes made on the release branch get added to future releases.
1. Submit a pull request from the release branch into `main`. Merge this pull request using the same commit format in the last step, to ensure any changes made on the release branch get added to future releases.

View File

@@ -41,8 +41,7 @@ closeAndLock:
- label: "ionitron: support"
message: >
Thanks for the issue! This issue appears to be a support request. We use this issue tracker exclusively for
bug reports and feature requests. Please use our [forum](https://forum.ionicframework.com) or our
[slack channel](https://ionicworldwide.herokuapp.com/) for questions about the framework.
bug reports and feature requests. Please use our [forum](https://forum.ionicframework.com) for questions about the framework.
Thank you for using Ionic!

View File

@@ -0,0 +1,22 @@
name: 'Build Ionic Angular Server'
description: 'Build Ionic Angular Server'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Install Angular Server Dependencies
run: npm install --legacy-peer-deps
shell: bash
working-directory: ./packages/angular-server
- name: Build
run: npm run build.prod
shell: bash
working-directory: ./packages/angular-server
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-angular-server
output: packages/angular-server/AngularServerBuild.zip
paths: packages/angular-server/dist

View File

@@ -0,0 +1,53 @@
name: 'Build Ionic Angular'
description: 'Build Ionic Angular'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json')}}-v1
- name: Cache Angular Node Modules
uses: actions/cache@v2
env:
cache-name: angular-node-modules
with:
path: ./angular/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./angular/package-lock.json')}}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install Angular Dependencies
run: npm install
shell: bash
working-directory: ./angular
- name: Link @ionic/core
run: npm link
shell: bash
working-directory: ./core
- name: Link @ionic/core in @ionic/angular
run: npm link @ionic/core
shell: bash
working-directory: ./angular
- name: Lint
run: npm run lint
shell: bash
working-directory: ./angular
- name: Build
run: npm run build
shell: bash
working-directory: ./angular
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-angular
output: ./angular/AngularBuild.zip
paths: ./angular/dist

View File

@@ -0,0 +1,30 @@
name: 'Build Ionic Core'
description: 'Build Ionic Core'
runs:
using: 'composite'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- name: Install Dependencies
run: npm install
working-directory: ./core
shell: bash
- name: Build Core
run: npm run build -- --ci
working-directory: ./core
shell: bash
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-core
output: core/CoreBuild.zip
paths: core/dist core/components core/css core/hydrate core/loader

View File

@@ -0,0 +1,51 @@
name: 'Build Ionic React Router'
description: 'Build Ionic React Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-react
path: ./packages/react
filename: ReactBuild.zip
- name: Install Dependencies
run: npm install --legacy-peer-deps
shell: bash
working-directory: ./packages/react-router
- name: Sync
run: npm run sync
shell: bash
working-directory: ./packages/react-router
- name: Lint
run: npm run lint
shell: bash
working-directory: ./packages/react-router
- name: Build
run: npm run build
shell: bash
working-directory: ./packages/react-router
- name: Test Spec
run: npm run test.spec
shell: bash
working-directory: ./packages/react-router
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-react-router
output: packages/react-router/ReactRouterBuild.zip
paths: packages/react-router/dist

View File

@@ -0,0 +1,46 @@
name: 'Build Ionic React'
description: 'Build Ionic React'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install React Dependencies
run: npm install --legacy-peer-deps
shell: bash
working-directory: ./packages/react
- name: Sync
run: npm run sync
shell: bash
working-directory: ./packages/react
- name: Lint
run: npm run lint
shell: bash
working-directory: ./packages/react
- name: Build
run: npm run build
shell: bash
working-directory: ./packages/react
- name: Test Spec
run: npm run test.spec
shell: bash
working-directory: ./packages/react
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-react
output: packages/react/ReactBuild.zip
paths: packages/react/dist packages/react/css

View File

@@ -0,0 +1,51 @@
name: 'Build Ionic Vue Router'
description: 'Builds Ionic Vue Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-vue
path: ./packages/vue
filename: VueBuild.zip
- name: Install Vue Router Dependencies
run: npm install
shell: bash
working-directory: ./packages/vue-router
- name: Sync
run: npm run sync
shell: bash
working-directory: ./packages/vue-router
- name: Lint
run: npm run lint
shell: bash
working-directory: ./packages/vue-router
- name: Build
run: npm run build
shell: bash
working-directory: ./packages/vue-router
- name: Test Spec
run: npm run test.spec
shell: bash
working-directory: ./packages/vue-router
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-vue-router
output: ./packages/vue-router/VueRouterBuild.zip
paths: packages/vue-router/dist

View File

@@ -0,0 +1,42 @@
name: 'Build Ionic Vue'
description: 'Build Ionic Vue'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install Vue Dependencies
run: npm install
shell: bash
working-directory: ./packages/vue
- name: Sync
run: npm run sync
shell: bash
working-directory: ./packages/vue
- name: Lint
run: npm run lint
shell: bash
working-directory: ./packages/vue
- name: Build
run: npm run build
shell: bash
working-directory: ./packages/vue
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-vue
output: packages/vue/VueBuild.zip
paths: packages/vue/dist packages/vue/css

View File

@@ -0,0 +1,19 @@
name: 'Ionic Framework Archive Download'
description: 'Downloads and decompresses an archive from a previous job'
inputs:
path:
description: 'Input archive name'
filename:
description: 'Input file name'
name:
description: 'Archive name'
runs:
using: 'composite'
steps:
- uses: actions/download-artifact@v2
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}
- name: Exract Archive
run: unzip -q -o ${{ inputs.path }}/${{ inputs.filename }}
shell: bash

View File

@@ -0,0 +1,39 @@
name: 'Test Angular E2E'
description: 'Test Angular E2E'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-angular
path: ./angular
filename: AngularBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-angular-server
path: ./packages/angular-server
filename: AngularServerBuild.zip
- name: Install Dependencies
run: npm install --legacy-peer-deps
shell: bash
working-directory: ./angular/test/test-app
- name: Run Tests
run: npm run test
shell: bash
working-directory: ./angular/test/test-app

View File

@@ -0,0 +1,18 @@
name: 'Test Core Clean Build'
description: 'Test Core Clean Build'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Check Diff
run: git diff --exit-code
shell: bash
working-directory: ./core

View File

@@ -0,0 +1,25 @@
name: 'Test Core E2E'
description: 'Test Core E2E'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Test
run: npm run test.e2e -- --ci --no-build
shell: bash
working-directory: ./core

View File

@@ -0,0 +1,20 @@
name: 'Test Core Lint'
description: 'Test Core Lint'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- name: Lint
run: npm run lint
shell: bash
working-directory: ./core

View File

@@ -0,0 +1,33 @@
name: 'Test Core Screenshot Main'
description: 'Test Core Screenshot Main'
inputs:
access-key-id:
description: 'AWS_ACCESS_KEY_ID'
secret-access-key:
description: 'AWS_SECRET_ACCESS_KEY'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Test
run: npx stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci --update-screenshot --no-build || true
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ inputs.access-key-id }}
AWS_SECRET_ACCESS_KEY: ${{ inputs.secret-access-key }}
working-directory: ./core

View File

@@ -0,0 +1,33 @@
name: 'Test Core Screenshot'
description: 'Test Core Screenshot'
inputs:
access-key-id:
description: 'AWS_ACCESS_KEY_ID'
secret-access-key:
description: 'AWS_SECRET_ACCESS_KEY'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Test
run: npx stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci --no-build || true
shell: bash
env:
AWS_ACCESS_KEY_ID: ${{ inputs.access-key-id }}
AWS_SECRET_ACCESS_KEY: ${{ inputs.secret-access-key }}
working-directory: ./core

View File

@@ -0,0 +1,25 @@
name: 'Test Core Spec'
description: 'Test Core Spec'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Test
run: npm run test.spec -- --ci
shell: bash
working-directory: ./core

View File

@@ -0,0 +1,37 @@
name: 'Test React E2E'
description: 'Test React E2E'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-react
path: ./packages/react
filename: ReactBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-react-router
path: ./packages/react-router
filename: ReactRouterBuild.zip
- uses: cypress-io/github-action@v2
with:
browser: chrome
headless: true
start: npm run start.ci
working-directory: ./packages/react/test-app

View File

@@ -0,0 +1,37 @@
name: 'Test React Router E2E'
description: 'Test React Router '
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-react
path: ./packages/react
filename: ReactBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-react-router
path: ./packages/react-router
filename: ReactRouterBuild.zip
- uses: cypress-io/github-action@v2
with:
browser: chrome
headless: true
start: npm run start.ci
working-directory: ./packages/react-router/test-app

View File

@@ -0,0 +1,47 @@
name: 'Test Vue E2E'
description: 'Test Vue E2E'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Cache Core Node Modules
uses: actions/cache@v2
env:
cache-name: core-node-modules
with:
path: ./core/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-vue
path: ./packages/vue
filename: VueBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-vue-router
path: ./packages/vue-router
filename: VueRouterBuild.zip
- name: Install Dependencies
run: npm install
shell: bash
working-directory: ./packages/vue/test-app
- name: Sync
run: npm run sync
shell: bash
working-directory: ./packages/vue/test-app
- name: Run Spec Tests
run: npm run test:unit
shell: bash
working-directory: ./packages/vue/test-app
- name: Run E2E Tests
run: npm run test:e2e
shell: bash
working-directory: ./packages/vue/test-app

View File

@@ -0,0 +1,19 @@
name: 'Ionic Framework Archive Upload'
description: 'Compresses and uploads an archive to be reused across jobs'
inputs:
paths:
description: 'Paths to files or directories to archive'
output:
description: 'Output file name'
name:
description: 'Archive name'
runs:
using: 'composite'
steps:
- name: Create Archive
run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }}
shell: bash
- uses: actions/upload-artifact@v2
with:
name: ${{ inputs.name }}
path: ${{ inputs.output }}

132
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,132 @@
name: 'Ionic Framework Build'
on:
pull_request:
branches: [ '**' ]
jobs:
build-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/build-core
test-core-clean-build:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-core-clean-build
test-core-lint:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-core-lint
test-core-spec:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-core-spec
test-core-e2e:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-core-e2e
test-core-screenshot:
needs: [build-core]
runs-on: ubuntu-latest
if: github.ref != 'refs/heads/main' && !github.event.pull_request.head.repo.fork
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-core-screenshot
with:
access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
test-core-screenshot-main:
needs: [build-core]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-core-screenshot-main
with:
access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
build-vue:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/build-vue-router
test-vue-e2e:
needs: [build-vue, build-vue-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-vue-e2e
build-angular:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/build-angular
build-angular-server:
needs: [build-angular]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/build-angular-server
test-angular-e2e:
needs: [build-angular, build-angular-server]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-angular-e2e
build-react:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/build-react-router
test-react-router-e2e:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-react-router-e2e
test-react-e2e:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ./.github/workflows/actions/test-react-e2e

18
.github/workflows/dev-build.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: 'Ionic Dev Build'
on:
workflow_dispatch:
jobs:
dev-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 15.x
- name: Create Dev Build
run: npm run release.dev -- --skip-prompt
shell: bash
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

2
.gitignore vendored
View File

@@ -59,10 +59,10 @@ prerender-static.html
angular/css/
packages/react/css/
packages/vue/css/
core/components/
core/css/
core/hydrate/
core/loader/
core/www/
.stencil/
angular/build/
core/components/

View File

@@ -44,7 +44,7 @@ async function askNpmTag(version) {
type: 'list',
name: 'npmTag',
message: 'Select npm tag or specify a new tag',
choices: ['latest', 'next', 'v4-lts']
choices: ['latest', 'next', 'v4-lts', 'v5-lts']
.concat([
new inquirer.Separator(),
{

View File

@@ -127,7 +127,7 @@ async function publishGithub(version, gitTag, changelog, npmTag) {
let branch = await execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']);
if (!branch) {
branch = 'master';
branch = 'main';
}
await octokit.repos.createRelease({

View File

@@ -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
{

View File

@@ -1,3 +1,372 @@
## [5.9.4](https://github.com/ionic-team/ionic/compare/v5.9.3...v5.9.4) (2022-04-27)
### Bug Fixes
* **core:** inherit aria attributes on host elements ([#25156](https://github.com/ionic-team/ionic/issues/25156)) ([#25169](https://github.com/ionic-team/ionic/issues/25169)) ([ffb056d](https://github.com/ionic-team/ionic/commit/ffb056d50e126a1b89f5133de1e7516d0c29a61a))
## [5.9.3](https://github.com/ionic-team/ionic/compare/v5.9.2...v5.9.3) (2021-12-15)
### Bug Fixes
* **vue:** improve query params handling in tabs ([#24355](https://github.com/ionic-team/ionic/issues/24355)) ([1c28750](https://github.com/ionic-team/ionic/commit/1c2875044ad4d93fdca866017159a89f4dc8872d)), closes [#24353](https://github.com/ionic-team/ionic/issues/24353)
* **vue:** tabs no longer get unmounted when navigating back to a tabs context ([#24337](https://github.com/ionic-team/ionic/issues/24337)) ([4aab72b](https://github.com/ionic-team/ionic/commit/4aab72b06159729d2dcd18b2ef0b76f693e5a74e)), closes [#24332](https://github.com/ionic-team/ionic/issues/24332)
### Performance Improvements
* **content:** remove global click listener to improve interaction performance ([#24360](https://github.com/ionic-team/ionic/issues/24360)) ([9c9e28c](https://github.com/ionic-team/ionic/commit/9c9e28ccc9f899c403c757d911ac02d9099415af)), closes [#24359](https://github.com/ionic-team/ionic/issues/24359)
## [5.9.2](https://github.com/ionic-team/ionic/compare/v5.9.1...v5.9.2) (2021-12-07)
### Bug Fixes
* **angular:** improve typing when compiling with legacy View Engine ([#24221](https://github.com/ionic-team/ionic/issues/24221)) ([816096f](https://github.com/ionic-team/ionic/commit/816096f89747e943a4a273175d384189f25e4628))
* **content:** ensure fixed slot renders on top of content in iOS ([#24300](https://github.com/ionic-team/ionic/issues/24300)) ([e41b0e0](https://github.com/ionic-team/ionic/commit/e41b0e0cf2a794972d7f4d8943a0bec3d1e08016)), closes [#24286](https://github.com/ionic-team/ionic-framework/issues/24286)
* **popover:** improve scrolling in popover when using header and footer ([#24294](https://github.com/ionic-team/ionic/issues/24294)) ([f6a00ea](https://github.com/ionic-team/ionic/commit/f6a00ea9544aa70620b5f8f65a7702fa3bedd974))
* **react:** present and dismiss hooks return promises ([#24299](https://github.com/ionic-team/ionic/issues/24299)) ([4b26fea](https://github.com/ionic-team/ionic/commit/4b26feaa47efed4806aba565a52554db232b99e2)), closes [#24293](https://github.com/ionic-team/ionic-framework/issues/24293)
* **react:** properly check for custom elements to avoid errors in unit tests ([#24156](https://github.com/ionic-team/ionic/issues/24156)) ([8f188ea](https://github.com/ionic-team/ionic/commit/8f188eaae7422c9e81053868b9dd93b4ac738e98)), closes [#24149](https://github.com/ionic-team/ionic/issues/24149)
* **router:** popping route now accounts for route params ([#24315](https://github.com/ionic-team/ionic/issues/24315)) ([5e5054d](https://github.com/ionic-team/ionic/commit/5e5054d369ad68c9ac43e12439d71fb42d6ca26b)), closes [#24223](https://github.com/ionic-team/ionic-framework/issues/24223)
* **slides:** update swiper instance after initialization ([#24257](https://github.com/ionic-team/ionic/issues/24257)) ([89e4bc5](https://github.com/ionic-team/ionic/commit/89e4bc56a1c3cd4fb26fc5514f38c6a01f047297)), closes [#19638](https://github.com/ionic-team/ionic-framework/issues/19638)
* **vue:** ionic lifecycle hooks now run when using vue 3.2 setup syntax ([#24253](https://github.com/ionic-team/ionic/issues/24253)) ([fb96ab5](https://github.com/ionic-team/ionic/commit/fb96ab5a26d87818a8b64ee82df0020355054183)), closes [#23824](https://github.com/ionic-team/ionic/issues/23824)
* **vue:** switching between tabs preserves query string ([#24297](https://github.com/ionic-team/ionic/issues/24297)) ([047d3c7](https://github.com/ionic-team/ionic/commit/047d3c77729db08e4fd84f426f6c5c2af0eacc52)), closes [#23699](https://github.com/ionic-team/ionic/issues/23699)
## [5.9.1](https://github.com/ionic-team/ionic/compare/v5.9.0...v5.9.1) (2021-11-17)
### Bug Fixes
* **angular:** build is now in correct directory ([#24236](https://github.com/ionic-team/ionic/issues/24236)) ([1d983fa](https://github.com/ionic-team/ionic/commit/1d983fa4b3ef0457dc192f376e380c77b611d058))
# [5.9.0](https://github.com/ionic-team/ionic/compare/v5.8.5...v5.9.0) (2021-11-17)
### Bug Fixes
* **action-sheet:** safe area is now accounted for in MD mode ([#24176](https://github.com/ionic-team/ionic/issues/24176)) ([642255e](https://github.com/ionic-team/ionic/commit/642255e514fd67238d9bd8ea90781111687c6d03)), closes [#24175](https://github.com/ionic-team/ionic/issues/24175)
* **input:** date type in ion-input now aligns correctly on iOS 15 ([#24217](https://github.com/ionic-team/ionic/issues/24217)) ([0566ec0](https://github.com/ionic-team/ionic/commit/0566ec0da3b8a66a1a1ebb1b235e7297ec483c79))
* **vue:** canGoBack method now works correctly ([#24188](https://github.com/ionic-team/ionic/issues/24188)) ([7c43589](https://github.com/ionic-team/ionic/commit/7c43589b0a486f71ee2ae5a4cdcd73071fcd31b9)), closes [#24109](https://github.com/ionic-team/ionic/issues/24109)
### Features
* **slides:** add support for Swiper 7 ([#24190](https://github.com/ionic-team/ionic/issues/24190)) ([d0b6130](https://github.com/ionic-team/ionic/commit/d0b61307c6b7ff1589646c43f989260b59db1473))
## [5.8.5](https://github.com/ionic-team/ionic/compare/v5.8.4...v5.8.5) (2021-10-27)
### Bug Fixes
* **menu:** added focus trapping, improved compatibility with screen readers ([#24076](https://github.com/ionic-team/ionic/issues/24076)) ([bdb268a](https://github.com/ionic-team/ionic/commit/bdb268aa12c5bf411c96529672486d35e018cefa))
* **vue:** back button now selects correct route when navigating from view multiple times ([#24060](https://github.com/ionic-team/ionic/issues/24060)) ([a09d7d4](https://github.com/ionic-team/ionic/commit/a09d7d4ab6dd0d90204015eaaf232ed190753c56)), closes [#23987](https://github.com/ionic-team/ionic/issues/23987)
* **vue:** mount correct views when navigating ([#24056](https://github.com/ionic-team/ionic/issues/24056)) ([24659a5](https://github.com/ionic-team/ionic/commit/24659a527abe0c70df7e8ae6da3dcb4017bf500c)), closes [#23914](https://github.com/ionic-team/ionic/issues/23914)
## [5.8.4](https://github.com/ionic-team/ionic/compare/v5.8.3...v5.8.4) (2021-10-11)
### Bug Fixes
* **angular:** setup config properly ([#24054](https://github.com/ionic-team/ionic/issues/24054)) ([e001f24](https://github.com/ionic-team/ionic/commit/e001f24f2ca99abbc98b923dd1a132cc83b3b23f)), closes [#24051](https://github.com/ionic-team/ionic/issues/24051) [#24052](https://github.com/ionic-team/ionic/issues/24052)
* **back-button:** pass aria-label to native element ([#24027](https://github.com/ionic-team/ionic/issues/24027)) ([68a7e43](https://github.com/ionic-team/ionic/commit/68a7e43345a0261fdeed6054198c5a22fbbcb584))
## [5.8.3](https://github.com/ionic-team/ionic/compare/v5.8.2...v5.8.3) (2021-10-07)
### Bug Fixes
* **react:** overlay hooks dismiss method now works ([#24038](https://github.com/ionic-team/ionic/issues/24038)) ([655631d](https://github.com/ionic-team/ionic/commit/655631ddf059ce58066d5384d0ae186d7abc09a9)), closes [#24030](https://github.com/ionic-team/ionic/issues/24030)
## [5.8.2](https://github.com/ionic-team/ionic/compare/v5.8.1...v5.8.2) (2021-10-06)
### Bug Fixes
* **alert:** made it easier to tell if alert is scrollable in MD mode ([#23976](https://github.com/ionic-team/ionic/issues/23976)) ([a262753](https://github.com/ionic-team/ionic/commit/a26275378f10835343ad8a6cdea50303e6c10a14))
* **angular:** use initialize function when setting up ionic angular to avoid config errors ([#24004](https://github.com/ionic-team/ionic/issues/24004)) ([f112ad4](https://github.com/ionic-team/ionic/commit/f112ad4490dc4a179dc3feab495530e14e655e5a)), closes [#22853](https://github.com/ionic-team/ionic/issues/22853)
* **item-sliding:** closing an item can no longer be interrupted ([#23973](https://github.com/ionic-team/ionic/issues/23973)) ([3ca0419](https://github.com/ionic-team/ionic/commit/3ca04197a4186c85d04cdf04fa9cb2689ca1bbfb)), closes [#23969](https://github.com/ionic-team/ionic/issues/23969)
* **react:** overlay hooks memorised properly to prevent re-renders ([#24010](https://github.com/ionic-team/ionic/issues/24010)) ([2c97712](https://github.com/ionic-team/ionic/commit/2c977126012ae0231d4e4fa63cc76a528bde699b)), closes [#23741](https://github.com/ionic-team/ionic/issues/23741)
* **select-popover:** non-scrollable popovers no longer have forced overscroll ([#23972](https://github.com/ionic-team/ionic/issues/23972)) ([aa4ba89](https://github.com/ionic-team/ionic/commit/aa4ba890e9c18e8a911c5188b3e2e85433658be9)), closes [#23971](https://github.com/ionic-team/ionic/issues/23971)
* **status-bar:** tapping status bar correctly scrolls content to top ([#24001](https://github.com/ionic-team/ionic/issues/24001)) ([25eb8cd](https://github.com/ionic-team/ionic/commit/25eb8cdf98fe455433ca6185e89d9e1223a6d3ae)), closes [#20423](https://github.com/ionic-team/ionic/issues/20423)
## [5.8.1](https://github.com/ionic-team/ionic/compare/v5.8.0...v5.8.1) (2021-09-22)
### Bug Fixes
* **angular:** select method now has correct types ([#23953](https://github.com/ionic-team/ionic/issues/23953)) ([3c1be89](https://github.com/ionic-team/ionic/commit/3c1be89112d464e77d65c875223138aaedf350cd)), closes [#23952](https://github.com/ionic-team/ionic/issues/23952)
* **item-sliding:** item-sliding accounts for multiple ion-item elements ([#23943](https://github.com/ionic-team/ionic/issues/23943)) ([8108edd](https://github.com/ionic-team/ionic/commit/8108edd876b10834015016385dc3cd5b8f31fbfa)), closes [#19312](https://github.com/ionic-team/ionic/issues/19312)
* **label:** only inherit color if color property is set on ion-item ([#23944](https://github.com/ionic-team/ionic/issues/23944)) ([ae1325c](https://github.com/ionic-team/ionic/commit/ae1325cee698066a71aae4e7deb953c4185c0926)), closes [#20125](https://github.com/ionic-team/ionic/issues/20125)
# [5.8.0 Calcium](https://github.com/ionic-team/ionic/compare/v5.7.0...v5.8.0) (2021-09-15)
### Bug Fixes
* **angular:** nested tabs now go to correct page ([#23902](https://github.com/ionic-team/ionic/issues/23902)) ([1ed9f07](https://github.com/ionic-team/ionic/commit/1ed9f07060736d0c951910427fb12b250d7dd9af)), closes [#23897](https://github.com/ionic-team/ionic/issues/23897)
* **header:** role attribute can now be customized ([#23888](https://github.com/ionic-team/ionic/issues/23888)) ([8888e2b](https://github.com/ionic-team/ionic/commit/8888e2bafd76b59f32b932b5d4a6a961b52894d9)), closes [#21327](https://github.com/ionic-team/ionic/issues/21327)
* **react:** modal now mounts child component independently of other modals ([#23903](https://github.com/ionic-team/ionic/issues/23903)) ([1e13429](https://github.com/ionic-team/ionic/commit/1e13429731c1d4b5200af7f5ca20aff1f3078bfe)), closes [#23904](https://github.com/ionic-team/ionic/issues/23904)
* **tab-bar:** safe area padding now added when slot="top" ([#23895](https://github.com/ionic-team/ionic/issues/23895)) ([4782969](https://github.com/ionic-team/ionic/commit/47829690b538903b70ad4fe77657404013270263)), closes [#23893](https://github.com/ionic-team/ionic/issues/23893)
### Features
* **action-sheet, loading, modal, picker, popover:** pass HTML attributes to host element ([#23929](https://github.com/ionic-team/ionic/issues/23929)) ([bd96a81](https://github.com/ionic-team/ionic/commit/bd96a81ff80ffe32914804ba9b6234c0286a33db))
* **alert, toast:** pass arbitrary HTML attributes to host element ([#23891](https://github.com/ionic-team/ionic/issues/23891)) ([73a1daf](https://github.com/ionic-team/ionic/commit/73a1daf0aaf6ffe8c7871619f2aec5f6fca1321a)), closes [#23825](https://github.com/ionic-team/ionic/issues/23825)
# [5.7.0 Potassium](https://github.com/ionic-team/ionic/compare/v5.6.14...v5.7.0) (2021-09-01)
### Bug Fixes
* **alert:** AlertButton role now has correct types ([#23791](https://github.com/ionic-team/ionic/issues/23791)) ([864212b](https://github.com/ionic-team/ionic/commit/864212b0f28d33daede5f4767aa03efa37c219ae))
* **label:** label now only takes up as much space as needed when slotted ([#23807](https://github.com/ionic-team/ionic/issues/23807)) ([9932e26](https://github.com/ionic-team/ionic/commit/9932e26a2ef28317bc85761e71a8fc4d881b8ae8)), closes [#23806](https://github.com/ionic-team/ionic/issues/23806)
* **reorder-group:** dragging reorder item to bottom no longer gives out of bounds index ([#23797](https://github.com/ionic-team/ionic/issues/23797)) ([02409f2](https://github.com/ionic-team/ionic/commit/02409f2abfa8acbab05d0f1217b9d1c13721746e)), closes [#23796](https://github.com/ionic-team/ionic/issues/23796)
* **vue:** router guards are now fire correctly when written in a component ([#23821](https://github.com/ionic-team/ionic/issues/23821)) ([3c44222](https://github.com/ionic-team/ionic/commit/3c442228ff746165fd823687a2661a24edd08820)), closes [#23820](https://github.com/ionic-team/ionic/issues/23820)
### Features
* **slides:** add IonicSlides module for Swiper migration, deprecate ion-slides ([#23844](https://github.com/ionic-team/ionic/issues/23844)) ([11fda41](https://github.com/ionic-team/ionic/commit/11fda41420343886dabd97096690be38f1c40524)), closes [#23447](https://github.com/ionic-team/ionic/issues/23447)
### Code Refactoring
* **virtual-scroll:** deprecated virtual scroll in favor of solutions provided by JS frameworks ([#23854](https://github.com/ionic-team/ionic-framework/pull/23854)) ([a0229bc](https://github.com/ionic-team/ionic-framework/commit/a0229bc7b2edb061510de0f2042e7910d04accc0))
## [5.6.14](https://github.com/ionic-team/ionic/compare/v5.6.13...v5.6.14) (2021-08-18)
### Bug Fixes
* **back-button:** MD ripple now accounts for --ripple-color ([#23749](https://github.com/ionic-team/ionic/issues/23749)) ([6b18a89](https://github.com/ionic-team/ionic/commit/6b18a89ac2c446082ce7faebe329157eedb13a0e)), closes [#23748](https://github.com/ionic-team/ionic/issues/23748)
* **img:** correctly determine when to load image when scrolling quickly on slower devices ([#23704](https://github.com/ionic-team/ionic/issues/23704)) ([067e621](https://github.com/ionic-team/ionic/commit/067e621bbc3865184ae114b8c91122188c13c860)), closes [#23703](https://github.com/ionic-team/ionic/issues/23703)
* **item-sliding:** prevent scrolling during slide gesture ([#23774](https://github.com/ionic-team/ionic/issues/23774)) ([e0c4ad3](https://github.com/ionic-team/ionic/commit/e0c4ad30bec3f2bd325d65b210ffb0437149810f)), closes [#19564](https://github.com/ionic-team/ionic/issues/19564)
* **nav:** custom animation is now used correctly ([#23779](https://github.com/ionic-team/ionic/issues/23779)) ([f9415ef](https://github.com/ionic-team/ionic/commit/f9415ef8a689e26078bdd01623348c79f9f818ad)), closes [#23777](https://github.com/ionic-team/ionic/issues/23777)
* **vue:** using router.go now shows correct view ([#23773](https://github.com/ionic-team/ionic/issues/23773)) ([621f4fa](https://github.com/ionic-team/ionic/commit/621f4faa1ab03137158127a56c7fe0aa1f7ae489)), closes [#22563](https://github.com/ionic-team/ionic/issues/22563)
## [5.6.13](https://github.com/ionic-team/ionic/compare/v5.6.12...v5.6.13) (2021-08-04)
### Bug Fixes
* **checkbox, radio:** change event interfaces correctly use TypeScript generics for value ([#23044](https://github.com/ionic-team/ionic/issues/23044)) ([8a941fd](https://github.com/ionic-team/ionic/commit/8a941fd24cd138817a2e91c42898878a919538e4))
* **gesture:** onEnd now correctly fires even if the event target was removed from the DOM ([#23713](https://github.com/ionic-team/ionic/issues/23713)) ([4edb5e2](https://github.com/ionic-team/ionic/commit/4edb5e2fed55c8ea21eae50821d16d351bf3aebf)), closes [#22819](https://github.com/ionic-team/ionic/issues/22819)
* **item-sliding:** opening item while other items are open no longer requires multiple swipes ([#23683](https://github.com/ionic-team/ionic/issues/23683)) ([792864f](https://github.com/ionic-team/ionic/commit/792864f8ab21dc178c1836a8a0d4fe2d305cc142)), closes [#21579](https://github.com/ionic-team/ionic/issues/21579)
* **react:** IonTabs no longer causes SSR to fail ([#23696](https://github.com/ionic-team/ionic/issues/23696)) ([f2a05be](https://github.com/ionic-team/ionic/commit/f2a05bed1e2a1150e8f1823bfed2d12a219d6ad0)), closes [#23651](https://github.com/ionic-team/ionic/issues/23651)
* **vue:** improve accuracy of ion-page dev warning ([#23677](https://github.com/ionic-team/ionic/issues/23677)) ([fb260a9](https://github.com/ionic-team/ionic/commit/fb260a9e09e6f3912b30ef2ebf581d3216483fea)), closes [#23675](https://github.com/ionic-team/ionic/issues/23675)
* **vue:** tabs warning about user-provided router outlet change is now correctly logged ([#23724](https://github.com/ionic-team/ionic/issues/23724)) ([4a64e97](https://github.com/ionic-team/ionic/commit/4a64e97a3e390e365101bbb477acad0ddc4671ff)), closes [#23719](https://github.com/ionic-team/ionic/issues/23719)
## [5.6.12](https://github.com/ionic-team/ionic/compare/v5.6.11...v5.6.12) (2021-07-21)
### Bug Fixes
* **action-sheet:** header, subheader, and icon alignment better matches native ios ([#23322](https://github.com/ionic-team/ionic/issues/23322)) ([39315bc](https://github.com/ionic-team/ionic/commit/39315bc857b850347dca386776665e21c9742cad)), closes [#23317](https://github.com/ionic-team/ionic/issues/23317)
* **button:** buttons are now disabled during page transitions ([#23589](https://github.com/ionic-team/ionic/issues/23589)) ([3b803eb](https://github.com/ionic-team/ionic/commit/3b803ebe024be3dbcf814a30a18df51ce23c8880)), closes [#23588](https://github.com/ionic-team/ionic/issues/23588)
* **item:** mirror disabled prop to aria attribute ([#23544](https://github.com/ionic-team/ionic/issues/23544)) ([9021e7c](https://github.com/ionic-team/ionic/commit/9021e7cc4b48a69ccc94faa7d2ddcb10a2afa340)), closes [#23513](https://github.com/ionic-team/ionic/issues/23513)
* **menu-button:** custom aria-label can now be set ([#23608](https://github.com/ionic-team/ionic/issues/23608)) ([c08345d](https://github.com/ionic-team/ionic/commit/c08345df2ee3175f3f0d11ff877c7b6f1a102321)), closes [#23604](https://github.com/ionic-team/ionic/issues/23604)
* **overlays:** overlay interfaces are now exported from framework packages and documented ([#23619](https://github.com/ionic-team/ionic/issues/23619)) ([773bbcb](https://github.com/ionic-team/ionic/commit/773bbcb211d3cf0caf38c25b44e666d98ddfafe5)), closes [#22790](https://github.com/ionic-team/ionic/issues/22790)
* **router-outlet:** improve reliability of swipe back gesture when quickly swiping back ([#23527](https://github.com/ionic-team/ionic/issues/23527)) ([fa06942](https://github.com/ionic-team/ionic/commit/fa069424b265891852a07869b6d086a1cb041e93)), closes [#22895](https://github.com/ionic-team/ionic/issues/22895)
## [5.6.11](https://github.com/ionic-team/ionic/compare/v5.6.10...v5.6.11) (2021-07-01)
### Bug Fixes
* **animation:** typescript interface has correct return value for progress methods ([#23536](https://github.com/ionic-team/ionic/issues/23536)) ([f3d6abb](https://github.com/ionic-team/ionic/commit/f3d6abbc1beeafe3b5e7f473d70d0b8ef4c79bc8))
* **ios, md:** double tapping back button no longer causes app to go back 2 pages ([#23526](https://github.com/ionic-team/ionic/issues/23526)) ([69be51d](https://github.com/ionic-team/ionic/commit/69be51dc54e670b2f75cbfac28a4a09517dbf355)), closes [#18455](https://github.com/ionic-team/ionic/issues/18455)
## [5.6.10](https://github.com/ionic-team/ionic/compare/v5.6.9...v5.6.10) (2021-06-22)
### Bug Fixes
* **button:** buttons using fill and color properties now account for hover and focused opacity variables ([#23442](https://github.com/ionic-team/ionic/issues/23442)) ([68c0e71](https://github.com/ionic-team/ionic/commit/68c0e7136d3f8aad8a195a0371104f7dd5fa7060)), closes [#23441](https://github.com/ionic-team/ionic/issues/23441)
* **item:** using multiple items with inputs no longer results in console warnings ([#23429](https://github.com/ionic-team/ionic/issues/23429)) ([e27b5b6](https://github.com/ionic-team/ionic/commit/e27b5b6ae360c44d8521ac7191817cbbe0367c05)), closes [#23427](https://github.com/ionic-team/ionic/issues/23427)
* **vue:** IonTabs can now accept IonRouterOutlet, deprecated default router outlet in tabs ([#23477](https://github.com/ionic-team/ionic/issues/23477)) ([a2a4cff](https://github.com/ionic-team/ionic/commit/a2a4cff3d0d67868f384e1e9eec7cc738e260a27)), closes [#23321](https://github.com/ionic-team/ionic/issues/23321)
## [5.6.9](https://github.com/ionic-team/ionic/compare/v5.6.8...v5.6.9) (2021-06-08)
### Bug Fixes
* **modal:** swipe to close modal is no longer swipeable on footer ([#23401](https://github.com/ionic-team/ionic/issues/23401)) ([ae96563](https://github.com/ionic-team/ionic/commit/ae96563fb3c4612cb8585292b389ee746f5759f7)), closes [#23398](https://github.com/ionic-team/ionic/issues/23398)
* **title:** inherit padding for iOS title in a toolbar ([#23343](https://github.com/ionic-team/ionic/issues/23343)) ([82cfa55](https://github.com/ionic-team/ionic/commit/82cfa5565347704b0e9f7dac792ed2aa6dd30505)), closes [#23072](https://github.com/ionic-team/ionic/issues/23072)
* **vue:** improve v-model integration for Vue 3.1.0+ ([#23420](https://github.com/ionic-team/ionic/issues/23420)) ([f008628](https://github.com/ionic-team/ionic/commit/f0086288512bd7f7d1929d79bfd8bf702efc732e))
* **vue:** prevent error from being thrown when testing on certain jest runners ([#23421](https://github.com/ionic-team/ionic/issues/23421)) ([60bedb5](https://github.com/ionic-team/ionic/commit/60bedb5599b286bffccfc54c4861a269d9b8df73)), closes [#23397](https://github.com/ionic-team/ionic/issues/23397)
## [5.6.8](https://github.com/ionic-team/ionic/compare/v5.6.7...v5.6.8) (2021-05-27)
### Bug Fixes
* **action-sheet:** subheader no longer overlaps action sheet buttons ([#23318](https://github.com/ionic-team/ionic/issues/23318)) ([d473a53](https://github.com/ionic-team/ionic/commit/d473a5385108ef5f39d7c9a2b2924e89fec631de)), closes [#23316](https://github.com/ionic-team/ionic/issues/23316)
* **all:** reflect color property as an attribute for vue ([#23345](https://github.com/ionic-team/ionic/issues/23345)) ([dc430af](https://github.com/ionic-team/ionic/commit/dc430af906c608f948c8d404ad73ae0e0ac36076)), closes [#23323](https://github.com/ionic-team/ionic/issues/23323)
* **range:** knob can now have an accessible name ([#23338](https://github.com/ionic-team/ionic/issues/23338)) ([881dcff](https://github.com/ionic-team/ionic/commit/881dcff40b8bdcb07b27d4ee812ce4ee64b6ea9a)), closes [#23295](https://github.com/ionic-team/ionic/issues/23295)
* **react:** remove @ionic/core dependency in @ionic/react-router to resolve yarn install warning ([#23351](https://github.com/ionic-team/ionic/issues/23351)) ([36bfa33](https://github.com/ionic-team/ionic/commit/36bfa3350354e09be6c62f4e4bee0c553c5981a3)), closes [#23346](https://github.com/ionic-team/ionic/issues/23346)
* **react:** support history@5 in preparation for react router 6 ([#23297](https://github.com/ionic-team/ionic/issues/23297)) ([4da5216](https://github.com/ionic-team/ionic/commit/4da5216b4f65f3d893cc81ebee77261835218f7f)), closes [#23294](https://github.com/ionic-team/ionic/issues/23294)
* **router:** guards are now triggered on initial navigation ([#23123](https://github.com/ionic-team/ionic/issues/23123)) ([56f6f56](https://github.com/ionic-team/ionic/commit/56f6f56c6665f40ea6bf41be463cd416883359f7)), closes [#22936](https://github.com/ionic-team/ionic/issues/22936)
* **router:** redirects now account for query string ([#23337](https://github.com/ionic-team/ionic/issues/23337)) ([08a9f3a](https://github.com/ionic-team/ionic/commit/08a9f3ac94685c5782dd2fa6b56bf3448729a768)), closes [#23136](https://github.com/ionic-team/ionic/issues/23136)
* **skeleton-text:** animation no longer jumps on large skeleton text elements ([#22697](https://github.com/ionic-team/ionic/issues/22697)) ([1a36922](https://github.com/ionic-team/ionic/commit/1a36922f41f2890c778feedbad9c5b74a72a3907)), closes [#22694](https://github.com/ionic-team/ionic/issues/22694)
* **slides:** resolve prototype pollution in swiper v5 ([#23344](https://github.com/ionic-team/ionic/issues/23344)) ([a708c41](https://github.com/ionic-team/ionic/commit/a708c412625cba475ec7863468dcc2146b8feb7a)), closes [#23342](https://github.com/ionic-team/ionic/issues/23342)
* **title:** large title scale animation is now correct in rtl mode ([#23372](https://github.com/ionic-team/ionic/issues/23372)) ([3d474ec](https://github.com/ionic-team/ionic/commit/3d474ec67ff4192fa3d08e370e20fecbee99a6aa)), closes [#23371](https://github.com/ionic-team/ionic/issues/23371)
## [5.6.7](https://github.com/ionic-team/ionic/compare/v5.6.6...v5.6.7) (2021-05-13)
### Bug Fixes
* **angular:** warnings are no longer generated when running tests with ng test ([#23292](https://github.com/ionic-team/ionic/issues/23292)) ([9cb6c80](https://github.com/ionic-team/ionic/commit/9cb6c80b3db4273e9c003a62a3065427995cb353)), closes [#19926](https://github.com/ionic-team/ionic/issues/19926)
* **overlays:** screen readers no longer read content behind overlays ([#23284](https://github.com/ionic-team/ionic/issues/23284)) ([a9b12a5](https://github.com/ionic-team/ionic/commit/a9b12a5aa4c150a1f8a80a826dda0df350bc0092)), closes [#22714](https://github.com/ionic-team/ionic/issues/22714)
* **refresher:** refresher now only activates when pulling down on MD ([#23283](https://github.com/ionic-team/ionic/issues/23283)) ([1e1596f](https://github.com/ionic-team/ionic/commit/1e1596f471e440085bf2d90e473f0cb0c0dcf6e2)), closes [#23245](https://github.com/ionic-team/ionic/issues/23245)
* **vue:** use correct history mode when doing ssr to avoid errors ([#23255](https://github.com/ionic-team/ionic/issues/23255)) ([2e00dab](https://github.com/ionic-team/ionic/commit/2e00dab95d3fefeab92c19cedb046ae2bb10879c)), closes [#23254](https://github.com/ionic-team/ionic/issues/23254)
## [5.6.6](https://github.com/ionic-team/ionic/compare/v5.6.5...v5.6.6) (2021-04-29)
### Bug Fixes
* **angular:** back button goes back to proper tab on angular 11.2.10 ([#23238](https://github.com/ionic-team/ionic/issues/23238)) ([e436439](https://github.com/ionic-team/ionic/commit/e436439e10c895b203ca4dc889cf307ffb9524b4)), closes [#23230](https://github.com/ionic-team/ionic/issues/23230)
* **react:** remove hardware back button event listener when NavManager is unmounted ([#23224](https://github.com/ionic-team/ionic/issues/23224)) ([c501da7](https://github.com/ionic-team/ionic/commit/c501da73be879db0fea818c507bae4386a47d42e)), closes [#23170](https://github.com/ionic-team/ionic/issues/23170)
* **slides:** undefined error is no longer thrown after destroying and quickly re-creating ion-slides ([#23239](https://github.com/ionic-team/ionic/issues/23239)) ([2ccaabb](https://github.com/ionic-team/ionic/commit/2ccaabb5b4d67ec4b1318e3ccb3edc1bd853ab3e)), closes [#22289](https://github.com/ionic-team/ionic/issues/22289)
* **vue:** components inside of ion-nav are now unmounted properly ([#23240](https://github.com/ionic-team/ionic/issues/23240)) ([f2f41e2](https://github.com/ionic-team/ionic/commit/f2f41e2af45ba9a36064d33e0b5c1b59da6b74ab)), closes [#23233](https://github.com/ionic-team/ionic/issues/23233)
* **vue:** overlay events can now be listened for without the "on" prefix, deprecated "on" prefix event listeners ([#23227](https://github.com/ionic-team/ionic/issues/23227)) ([dab927d](https://github.com/ionic-team/ionic/commit/dab927d2901658f4040c1d1aa6c777497d8714c8))
## [5.6.5](https://github.com/ionic-team/ionic/compare/v5.6.4...v5.6.5) (2021-04-22)
### Bug Fixes
* **content:** only render a main element when content is being used in primary view ([#23160](https://github.com/ionic-team/ionic/issues/23160)) ([2d07d82](https://github.com/ionic-team/ionic/commit/2d07d8216af908b181c5e7e438e79a049bb6d8c2))
* **datetime, input, textarea:** only add aria-labelledby if there is an adjacent label ([#23211](https://github.com/ionic-team/ionic/issues/23211)) ([a31fb55](https://github.com/ionic-team/ionic/commit/a31fb55bac1ef03e014f3d7f6c22c24eff20feb5))
* **radio-group:** pressing spacebar correctly unselects radio with allow-empty-selection ([#23194](https://github.com/ionic-team/ionic/issues/23194)) ([7139b3f](https://github.com/ionic-team/ionic/commit/7139b3f39e8eeef07ff7c595940fc5dafe062956)), closes [#22734](https://github.com/ionic-team/ionic/issues/22734)
* **react:** callback refs now work correctly with ionic components ([#23152](https://github.com/ionic-team/ionic/issues/23152)) ([0dd189e](https://github.com/ionic-team/ionic/commit/0dd189e2c05012659894a4c15cd3a9d407fe0a63)), closes [#23153](https://github.com/ionic-team/ionic/issues/23153)
* **segment, segment-button:** use tablist and tab roles ([#23145](https://github.com/ionic-team/ionic/issues/23145)) ([91ac340](https://github.com/ionic-team/ionic/commit/91ac340ae7e8928f7b0972a093dd9dd7fa727671))
* **vue:** dynamic tabs are now correctly recognized ([#23212](https://github.com/ionic-team/ionic/issues/23212)) ([004885b](https://github.com/ionic-team/ionic/commit/004885bfd4446487e6386876c868532a2795347f)), closes [#22847](https://github.com/ionic-team/ionic/issues/22847)
* **vue:** update props when navigating to new parameterized route ([#23189](https://github.com/ionic-team/ionic/issues/23189)) ([35c8802](https://github.com/ionic-team/ionic/commit/35c8802c22c1f4bf213a01e1c28398ad62d1b7ac))
## [5.6.4](https://github.com/ionic-team/ionic/compare/v5.6.3...v5.6.4) (2021-04-08)
### Bug Fixes
* **angular:** swiping back quickly no longer causes app to get stuck ([#23125](https://github.com/ionic-team/ionic/issues/23125)) ([28c52fd](https://github.com/ionic-team/ionic/commit/28c52fd4e3df3d96b4ec83075a322e110e938a1a)), closes [#15154](https://github.com/ionic-team/ionic/issues/15154)
* **input:** inherit aria-label to input ([#23159](https://github.com/ionic-team/ionic/issues/23159)) ([61f094d](https://github.com/ionic-team/ionic/commit/61f094d30665c9afec428028883a5d9a085892d8))
* **react:** overlays now correctly unmount any child components after dismissing ([#23149](https://github.com/ionic-team/ionic/issues/23149)) ([dee6eb3](https://github.com/ionic-team/ionic/commit/dee6eb30df370047bbc872b00ab6d801dd11fa81)), closes [#23140](https://github.com/ionic-team/ionic/issues/23140)
* **react, vue:** correct view now chosen when going back inside tabs ([#23154](https://github.com/ionic-team/ionic/issues/23154)) ([7203190](https://github.com/ionic-team/ionic/commit/72031902347dc279045e2e099f69852a23dd8436)), closes [#23087](https://github.com/ionic-team/ionic/issues/23087) [#23101](https://github.com/ionic-team/ionic/issues/23101)
* **toggle:** prevent click event from firing twice ([#23146](https://github.com/ionic-team/ionic/issues/23146)) ([42e6c90](https://github.com/ionic-team/ionic/commit/42e6c90c4632423386b165dddc4b94a55c075e2e)), closes [#23041](https://github.com/ionic-team/ionic/issues/23041)
* **vue:** account for event name changes in vue 3.0.6+ for overlay components ([#23100](https://github.com/ionic-team/ionic/issues/23100)) ([27318cf](https://github.com/ionic-team/ionic/commit/27318cf58563c4b38d0b7045fb61451f45954a8f))
* **vue:** components now integrate properly with vee-validate ([#23114](https://github.com/ionic-team/ionic/issues/23114)) ([ba51daf](https://github.com/ionic-team/ionic/commit/ba51daf17c4438aea6826882f82a04ebf8d6a5d8)), closes [#22886](https://github.com/ionic-team/ionic/issues/22886)
## [5.6.3](https://github.com/ionic-team/ionic/compare/v5.6.2...v5.6.3) (2021-03-23)
### Bug Fixes
* **all:** update tslib to resolve export errors ([#23092](https://github.com/ionic-team/ionic-framework/pull/23092)) ([0cdd326](https://github.com/ionic-team/ionic-framework/commit/0cdd326a4a02729a306bccfcadca7370475eae32)), closes [#23090](https://github.com/ionic-team/ionic-framework/issues/23090)
* **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)
@@ -3766,4 +4135,4 @@ The following dependencies need to be updated to resolve build errors
<a name="0.1.0"></a>
## [0.1.0](https://github.com/ionic-team/ionic/commit/43a8c4c7a719169336a84964fc1c737562d764a6) (2018-03-01)
## [0.1.0](https://github.com/ionic-team/ionic/commit/43a8c4c7a719169336a84964fc1c737562d764a6) (2018-03-01)

View File

@@ -16,14 +16,14 @@ diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
community include the ability to:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
* 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:

View File

@@ -5,6 +5,9 @@ build top quality native and progressive web apps with web technologies.
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.
## Looking for the Ionic Framework v6 beta?
[Click here to get started!](https://github.com/ionic-team/ionic-framework/blob/next/BETA.md)
### Packages
@@ -27,11 +30,11 @@ an [issue](https://github.com/ionic-team/ionic/issues/new) on this repository.
### Contributing
Thanks for your interest in contributing! Read up on our guidelines for
[contributing](https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md)
[contributing](https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md)
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.
Please note that this project is released with a [Contributor Code of Conduct](https://github.com/ionic-team/ionic/blob/main/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
### Examples

View File

@@ -137,7 +137,7 @@ The back button is no longer added by default to a navigation bar. It should be
</ion-toolbar>
```
See the [back button documentation](https://github.com/ionic-team/ionic/blob/master/core/src/components/back-button) for more usage examples.
See the [back button documentation](https://github.com/ionic-team/ionic/blob/main/core/src/components/back-button) for more usage examples.
## Button
@@ -507,7 +507,7 @@ _In the following examples, `{breakpoint}` refers to the optional screen breakpo
- `push-{breakpoint}-{value}` attributes have been renamed to `push-{breakpoint}=“{value}”`
- `pull-{breakpoint}-{value}` attributes have been renamed to `pull-{breakpoint}=“{value}”`
Customizing the padding and width of a grid should now be done with CSS variables. For more information, see [Grid Layout](https://github.com/ionic-team/ionic-docs/blob/master/src/pages/layout/grid.md).
Customizing the padding and width of a grid should now be done with CSS variables. For more information, see [Grid Layout](https://github.com/ionic-team/ionic-docs/blob/main/src/pages/layout/grid.md).
## Icon
@@ -1689,7 +1689,7 @@ The tab attribute defines the route to be shown upon clicking on this tab.
</ion-tabs>
```
See more usage examples in the [Tabs](https://github.com/ionic-team/ionic/blob/master/core/src/components/tabs) documentation.
See more usage examples in the [Tabs](https://github.com/ionic-team/ionic/blob/main/core/src/components/tabs) documentation.
## Text / Typography

View File

@@ -16,11 +16,11 @@ Ionic Angular specific building blocks on top of [@ionic/core](https://www.npmjs
## License
* [MIT](https://raw.githubusercontent.com/ionic-team/ionic/master/LICENSE)
* [MIT](https://raw.githubusercontent.com/ionic-team/ionic/main/LICENSE)
## Testing ng-add in ionic
1. Pull the latest from master
1. Pull the latest from `main`
2. Build ionic/angular: `npm run build`
3. Run `npm link` from `ionic/angular/dist` directory
4. Create a blank angular project

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/angular",
"version": "5.5.5",
"version": "5.9.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular",
"version": "5.5.5",
"version": "5.9.4",
"license": "MIT",
"dependencies": {
"@ionic/core": "5.5.4",
"@ionic/core": "5.9.3",
"tslib": "^1.9.3"
},
"devDependencies": {
@@ -204,14 +204,20 @@
}
},
"node_modules/@ionic/core": {
"version": "5.5.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.5.4.tgz",
"integrity": "sha512-IjbGN8vh3XuJ2ulo3BMlMflcWlUhvEGEexr29JKFvb+O4bWKP5sC2fkqSrswrIstOmv7axm7CeIi2MNRkwYwVA==",
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.9.3.tgz",
"integrity": "sha512-WM50vVxAAw+MQYqWXKUK4usBgkr7iQ9UWSb6t59mG4ZSy/fPAb7ZIdAjxY0U5i1ykk6A7Ur4B9ZJMpC/a7nnug==",
"dependencies": {
"ionicons": "^5.1.2",
"tslib": "^1.10.0"
"@stencil/core": "^2.4.0",
"ionicons": "^5.5.3",
"tslib": "^2.1.0"
}
},
"node_modules/@ionic/core/node_modules/tslib": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
"integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
},
"node_modules/@rollup/plugin-commonjs": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-11.1.0.tgz",
@@ -291,9 +297,9 @@
}
},
"node_modules/@stencil/core": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.4.0.tgz",
"integrity": "sha512-gU6+Yyd6O0KrCSS/O6j8KKqmRo+/Dcs2fI0+APCpbAWK+nqhwDISpdnSEfGDCLMoAC08XOZCycBRk2K1VGnEcg==",
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.6.0.tgz",
"integrity": "sha512-QsxWayZyusnqSZrlCl81R71rA3KqFjVVQSH4E0rGN15F1GdQaFonKlHLyCOLKLig1zzC+DQkLLiUuocexuvdeQ==",
"bin": {
"stencil": "bin/stencil"
},
@@ -2027,11 +2033,11 @@
}
},
"node_modules/ionicons": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.0.tgz",
"integrity": "sha512-0DUHTeoIrGSY+KNyNDaQW7v5+mDstjSkjx8dzT925kXKYBDrN3sGs8kUcSSQbTK132U4CbgDEZkn7FDUa9x8Qw==",
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
"dependencies": {
"@stencil/core": "^2.4.0"
"@stencil/core": "^2.5.0"
}
},
"node_modules/is-accessor-descriptor": {
@@ -5150,12 +5156,20 @@
}
},
"@ionic/core": {
"version": "5.5.4",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.5.4.tgz",
"integrity": "sha512-IjbGN8vh3XuJ2ulo3BMlMflcWlUhvEGEexr29JKFvb+O4bWKP5sC2fkqSrswrIstOmv7axm7CeIi2MNRkwYwVA==",
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.9.3.tgz",
"integrity": "sha512-WM50vVxAAw+MQYqWXKUK4usBgkr7iQ9UWSb6t59mG4ZSy/fPAb7ZIdAjxY0U5i1ykk6A7Ur4B9ZJMpC/a7nnug==",
"requires": {
"ionicons": "^5.1.2",
"tslib": "^1.10.0"
"@stencil/core": "^2.4.0",
"ionicons": "^5.5.3",
"tslib": "^2.1.0"
},
"dependencies": {
"tslib": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
"integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="
}
}
},
"@rollup/plugin-commonjs": {
@@ -5229,9 +5243,9 @@
"dev": true
},
"@stencil/core": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.4.0.tgz",
"integrity": "sha512-gU6+Yyd6O0KrCSS/O6j8KKqmRo+/Dcs2fI0+APCpbAWK+nqhwDISpdnSEfGDCLMoAC08XOZCycBRk2K1VGnEcg=="
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.6.0.tgz",
"integrity": "sha512-QsxWayZyusnqSZrlCl81R71rA3KqFjVVQSH4E0rGN15F1GdQaFonKlHLyCOLKLig1zzC+DQkLLiUuocexuvdeQ=="
},
"@szmarczak/http-timer": {
"version": "1.1.2",
@@ -6648,11 +6662,11 @@
"dev": true
},
"ionicons": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.0.tgz",
"integrity": "sha512-0DUHTeoIrGSY+KNyNDaQW7v5+mDstjSkjx8dzT925kXKYBDrN3sGs8kUcSSQbTK132U4CbgDEZkn7FDUa9x8Qw==",
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
"requires": {
"@stencil/core": "^2.4.0"
"@stencil/core": "^2.5.0"
}
},
"is-accessor-descriptor": {

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "5.5.5",
"version": "5.9.4",
"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.5.5",
"@ionic/core": "5.9.4",
"tslib": "^1.9.3"
},
"peerDependencies": {

View File

@@ -1,26 +1,20 @@
import { NgZone } from '@angular/core';
import { setupConfig } from '@ionic/core';
import { applyPolyfills, defineCustomElements } from '@ionic/core/loader';
import { Config } from './providers/config';
import { IonicWindow } from './types/interfaces';
import { raf } from './util/util';
let didInitialize = false;
export const appInitialize = (config: Config, doc: Document, zone: NgZone) => {
return (): any => {
const win: IonicWindow | undefined = doc.defaultView as any;
if (win && typeof (window as any) !== 'undefined') {
if (didInitialize) {
console.warn('Ionic Angular was already initialized. Make sure IonicModule.forRoot() is just called once.');
}
didInitialize = true;
const Ionic = win.Ionic = win.Ionic || {};
Ionic.config = {
setupConfig({
...config,
_zoneGate: (h: any) => zone.run(h)
};
});
const aelFn = '__zone_symbol__addEventListener' in (doc.body as any)
? '__zone_symbol__addEventListener'

View File

@@ -86,11 +86,11 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
*/
const formControl = ngControl.control;
if (formControl) {
const methodsToPatch = ['markAsTouched', 'markAllAsTouched', 'markAsUntouched', 'markAsDirty', 'markAsPristine'];
const methodsToPatch = ['markAsTouched', 'markAllAsTouched', 'markAsUntouched', 'markAsDirty', 'markAsPristine'] as const;
methodsToPatch.forEach(method => {
if (formControl[method]) {
const oldFn = formControl[method].bind(formControl);
formControl[method] = (...params) => {
formControl[method] = (...params: any[]) => {
oldFn(...params);
setIonicClasses(this.el);
};

View File

@@ -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';
@@ -51,7 +52,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
this._swipeGesture = swipe;
this.nativeEl.swipeHandler = swipe ? {
canStart: () => this.stackCtrl.canGoBack(1),
canStart: () => this.stackCtrl.canGoBack(1) && !this.stackCtrl.hasRunningTask(),
onStart: () => this.stackCtrl.startBackTransition(),
onEnd: shouldContinue => this.stackCtrl.endBackTransition(shouldContinue)
} : undefined;
@@ -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 {
@@ -147,15 +147,27 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
deactivate(): void {
if (this.activated) {
if (this.activatedView) {
this.activatedView.savedData = new Map(this.getContext()!.children['contexts']);
const context = this.getContext()!;
this.activatedView.savedData = new Map(context.children['contexts']);
/**
* Angular v11.2.10 introduced a change
* where this route context is cleared out when
* a router-outlet is deactivated, However,
* we need this route information in order to
* return a user back to the correct tab when
* leaving and then going back to the tab context.
*/
const primaryOutlet = this.activatedView.savedData.get('primary');
if (primaryOutlet && context.route) {
primaryOutlet.route = { ...context.route };
}
/**
* Ensure we are saving the NavigationExtras
* data otherwise it will be lost
*/
this.activatedView.savedExtras = {};
const context = this.getContext()!;
if (context.route) {
const contextSnapshot = context.route.snapshot;

View File

@@ -86,10 +86,23 @@ export class IonTabs {
* b. If the last route view doesn't exist, then navigate
* to the default tabRootUrl
*/
@HostListener('ionTabButtonClick', ['$event.detail.tab'])
select(tab: string) {
@HostListener('ionTabButtonClick', ['$event'])
select(tabOrEvent: string | CustomEvent) {
const isTabString = typeof tabOrEvent === 'string';
const tab = (isTabString) ? tabOrEvent : (tabOrEvent as CustomEvent).detail.tab;
const alreadySelected = this.outlet.getActiveStackId() === tab;
const tabRootUrl = `${this.outlet.tabsPrefix}/${tab}`;
/**
* If this is a nested tab, prevent the event
* from bubbling otherwise the outer tabs
* will respond to this event too, causing
* the app to get directed to the wrong place.
*/
if (!isTabString) {
(tabOrEvent as CustomEvent).stopPropagation();
}
if (alreadySelected) {
const activeStackId = this.outlet.getActiveStackId();
const activeView = this.outlet.getLastRouteView(activeStackId);

View File

@@ -232,6 +232,10 @@ export class StackController {
return this.activeView ? this.activeView.stackId : undefined;
}
hasRunningTask(): boolean {
return this.runningTask !== undefined;
}
destroy() {
this.containerEl = undefined!;
this.views.forEach(destroyView);
@@ -294,13 +298,14 @@ export class StackController {
this.runningTask = undefined;
}
const promise = this.runningTask = task();
promise.finally(() => this.runningTask = undefined);
return promise;
}
}
const cleanupAsync = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
if (typeof (requestAnimationFrame as any) === 'function') {
return new Promise<any>(resolve => {
return new Promise<void>(resolve => {
requestAnimationFrame(() => {
cleanup(activeRoute, views, viewsSnapshot, location);
resolve();

View File

@@ -278,8 +278,8 @@ export class IonHeader {
}
export declare interface IonIcon extends Components.IonIcon {
}
@ProxyCmp({ inputs: ["ariaLabel", "color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "size", "src"] })
@Component({ selector: "ion-icon", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["ariaLabel", "color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "size", "src"] })
@ProxyCmp({ inputs: ["ariaHidden", "ariaLabel", "color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] })
@Component({ selector: "ion-icon", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["ariaHidden", "ariaLabel", "color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] })
export class IonIcon {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
@@ -643,8 +643,8 @@ export class IonRow {
}
export declare interface IonSearchbar extends Components.IonSearchbar {
}
@ProxyCmp({ inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "spellcheck", "type", "value"], "methods": ["setFocus", "getInputElement"] })
@Component({ selector: "ion-searchbar", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "spellcheck", "type", "value"] })
@ProxyCmp({ inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"], "methods": ["setFocus", "getInputElement"] })
@Component({ selector: "ion-searchbar", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] })
export class IonSearchbar {
ionInput!: EventEmitter<CustomEvent>;
ionChange!: EventEmitter<CustomEvent>;

View File

@@ -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.

View File

@@ -43,7 +43,47 @@ export * from './types/ionic-lifecycle-hooks';
export { IonicModule } from './ionic-module';
// UTILS
export { IonicSafeString, getPlatforms, isPlatform, createAnimation } from '@ionic/core';
export { IonicSafeString, getPlatforms, isPlatform, createAnimation, IonicSwiper, IonicSlides } from '@ionic/core';
// CORE TYPES
export { Animation, AnimationBuilder, AnimationCallbackOptions, AnimationDirection, AnimationFill, AnimationKeyFrames, AnimationLifecycle, Gesture, GestureConfig, GestureDetail, mdTransitionAnimation, iosTransitionAnimation, NavComponentWithProps } from '@ionic/core';
export {
Animation,
AnimationBuilder,
AnimationCallbackOptions,
AnimationDirection,
AnimationFill,
AnimationKeyFrames,
AnimationLifecycle,
Gesture,
GestureConfig,
GestureDetail,
mdTransitionAnimation,
iosTransitionAnimation,
NavComponentWithProps,
SpinnerTypes,
ActionSheetOptions,
ActionSheetButton,
AlertOptions,
AlertInput,
AlertTextareaAttributes,
AlertInputAttributes,
AlertButton,
LoadingOptions,
ModalOptions,
PickerOptions,
PickerButton,
PickerColumn,
PickerColumnOption,
PopoverOptions,
ToastOptions,
ToastButton
} from '@ionic/core';

View File

@@ -110,6 +110,7 @@ export class Platform {
* | Platform Name | Description |
* |-----------------|------------------------------------|
* | android | on a device running Android. |
* | capacitor | on a device running Capacitor. |
* | cordova | on a device running Cordova. |
* | ios | on a device running iOS. |
* | ipad | on an iPad device. |
@@ -209,7 +210,7 @@ export class Platform {
}
/**
* Returns `true` if the app is in portait mode.
* Returns `true` if the app is in portrait mode.
*/
isPortrait(): boolean {
return this.win.matchMedia && this.win.matchMedia('(orientation: portrait)').matches;

View File

@@ -10,6 +10,6 @@ export interface IonicWindow extends Window {
}
export interface HTMLStencilElement extends HTMLElement {
componentOnReady(): Promise<this>;
forceUpdate(): void;
componentOnReady?(): Promise<this>;
forceUpdate?(): void;
}

View File

@@ -85,33 +85,6 @@
"browserTarget": "test-app:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"styles": ["src/styles.css"],
"scripts": [],
"assets": ["src/favicon.ico", "src/assets"]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "test-app:serve"
},
"configurations": {
"production": {
"devServerTarget": "test-app:serve:production"
},
"ci": {
"devServerTarget": "test-app:serve:ci"
}
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {

View File

@@ -0,0 +1,8 @@
{
"integrationFolder": "./e2e",
"testFiles": "**/*.spec.ts",
"baseUrl": "http://localhost:4200/",
"ignoreTestFiles": "**/examples/*",
"video": false,
"screenshotOnRunFailure": false
}

View File

@@ -1,3 +1,4 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
@@ -11,7 +12,11 @@
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
};
}

View File

@@ -0,0 +1,79 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
Cypress.Commands.add('ionSwipeToGoBack', (complete = false, selector = 'ion-router-outlet') => {
const increment = (complete) ? 60 : 25;
cy.get(selector)
.first()
.trigger('mousedown', 0, 275, { which: 1, force: true })
.trigger('mousemove', increment * 1, 275, { which: 1, force: true })
.wait(50)
.trigger('mousemove', increment * 2, 275, { which: 1, force: true })
.wait(50)
.trigger('mousemove', increment * 3, 275, { which: 1, force: true })
.wait(50)
.trigger('mousemove', increment * 4, 275, { which: 1, force: true })
.wait(50)
.trigger('mouseup', increment * 4, 275, { which: 1, force: true })
cy.wait(150);
})
Cypress.Commands.add('testStack', (selector, expected) => {
cy.document().then((doc) => {
const children = Array.from(
doc.querySelector(selector).children
).map(el => el.tagName.toLowerCase());
expect(children).to.deep.equal(expected);
})
})
Cypress.Commands.add('testLifeCycle', (selector, expected) => {
cy.get(`${selector} #ngOnInit`).invoke('text').should('equal', '1');
cy.get(`${selector} #ionViewWillEnter`).invoke('text').should('equal', expected.ionViewWillEnter.toString());
cy.get(`${selector} #ionViewDidEnter`).invoke('text').should('equal', expected.ionViewDidEnter.toString());
cy.get(`${selector} #ionViewWillLeave`).invoke('text').should('equal', expected.ionViewWillLeave.toString());
cy.get(`${selector} #ionViewDidLeave`).invoke('text').should('equal', expected.ionViewDidLeave.toString());
})
Cypress.Commands.add('ionPageVisible', (selector) => {
cy.get(selector)
.should('have.class', 'ion-page')
.should('not.have.class', 'ion-page-hidden')
.should('not.have.class', 'ion-page-invisible')
.should('have.length', 1)
})
Cypress.Commands.add('ionPageHidden', (selector) => {
cy.get(selector)
.should('have.class', 'ion-page')
.should('have.class', 'ion-page-hidden')
.should('have.length', 1)
})
Cypress.Commands.add('ionPageDoesNotExist', (selector) => {
cy.get(selector)
.should('not.exist')
});

View File

@@ -0,0 +1,69 @@
/// <reference types="cypress" />
declare namespace Cypress {
interface Chainable<Subject> {
/**
* Swipe to go back on the current selector or router outlet
* @example
* ```
* cy.ionSwipeToGoBack();
* cy.ionSwipeToGoBack(true);
* ```
*/
ionSwipeToGoBack(complete: boolean, selector: string): Chainable<any>
/**
* Test that the proper pages are in the navigation stack
* @example
* ```
* cy.testStack('ion-router-outlet', ['app-navigation-page2', 'app-navigation-page1']);
* cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
* ```
*/
testStack(selector: string, expected: string[]): Chainable<any>
/**
* Test whether or not the lifecycle events fired
* @example
* ```
* cy.testLifeCycle('app-router-link-page', {
* ionViewWillEnter: 1,
* ionViewDidEnter: 1,
* ionViewWillLeave: 0,
* ionViewDidLeave: 0,
* });
* ```
*/
testLifeCycle(selector: string, expected: any): Chainable<any>
/**
* Test whether or not an .ion-page element is visible.
* Use this to test a page after navigating to it.
* @example
* ```
* cy.ionPageVisible('app-my-page');
* ```
*/
ionPageVisible(selector: string): Chainable<any>
/**
* Test whether or not an .ion-page element is hidden
* Use this to test a page after navigating away from it.
* @example
* ```
* cy.ionPageHidden('app-my-page');
* ```
*/
ionPageHidden(selector: string): Chainable<any>
/**
* Test whether or not an .ion-page element exists.
* Use this to test a page after popping it off the stack.
* @example
* ```
* cy.ionPageDoesNotExist('app-my-page');
* ```
*/
ionPageDoesNotExist(selector: string): Chainable<any>
}
}

View File

@@ -14,7 +14,7 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@@ -1,14 +0,0 @@
// 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;

View File

@@ -1,35 +0,0 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
chromeOptions: {
args: [ "--headless", "--disable-gpu", "--window-size=400,1000", "--start-maximized" ]
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 100000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

View File

@@ -1,133 +0,0 @@
import { browser, element, by } from 'protractor';
import { handleErrorMessages, getProperty, setProperty, getText, waitTime } from './utils';
describe('form', () => {
afterEach(() => {
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');
await waitTime(30);
});
it('should have default values', async () => {
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
});
});
it('should become valid', async () => {
await setProperty('ion-input.required', 'value', 'Some value');
await testStatus('INVALID');
await setProperty('ion-select', 'value', 'nes');
await testStatus('INVALID');
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
});
});
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
});
});
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
});
});
it('should submit', async () => {
await element(by.css('#set-values')).click();
await waitTime(100);
await element(by.css('#submit-button')).click();
expect(await getText('#submit')).toEqual('true');
});
});
describe('blur', () => {
beforeEach(async () => {
await browser.get('/form#blur');
await waitTime(30);
});
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
});
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
});
});
});
});
async function testStatus(status: string) {
expect(await element(by.css('#status')).getText()).toEqual(status);
}
async function testData(data: any) {
expect(JSON.parse(await element(by.css('#data')).getText())).toEqual(data);
}

View File

@@ -0,0 +1,118 @@
describe('Form', () => {
beforeEach(() => {
cy.visit('/form');
})
describe('status updates', () => {
it('should update Ionic form classes when calling form methods programmatically', async () => {
cy.get('#input-touched').click();
cy.get('#touched-input-test').should('have.class', 'ion-touched');
});
});
describe('change', () => {
it('should have default values', () => {
testStatus('INVALID');
cy.get('#submit').should('have.text', 'false');
testData({
datetime: '2010-08-20',
select: null,
toggle: false,
input: '',
input2: 'Default Value',
checkbox: false,
range: 5
});
});
it('should become valid', () => {
cy.get('ion-input.required').invoke('prop', 'value', 'Some value');
testStatus('INVALID');
cy.get('ion-select').invoke('prop', 'value', 'nes');
testStatus('INVALID');
cy.get('ion-range').invoke('prop', 'value', 40);
testStatus('VALID');
testData({
datetime: '2010-08-20',
select: 'nes',
toggle: false,
input: 'Some value',
input2: 'Default Value',
checkbox: false,
range: 40
});
});
it('ion-toggle should change', () => {
cy.get('form ion-toggle').click();
testData({
datetime: '2010-08-20',
select: null,
toggle: true,
input: '',
input2: 'Default Value',
checkbox: false,
range: 5
});
});
it('ion-checkbox should change', () => {
cy.get('ion-checkbox').click();
testData({
datetime: '2010-08-20',
select: null,
toggle: false,
input: '',
input2: 'Default Value',
checkbox: true,
range: 5
});
});
it('should submit', () => {
cy.get('#set-values').click();
cy.get('#submit-button').click();
cy.get('#submit').should('have.text', 'true');
});
});
describe('blur', () => {
it('ion-toggle should change only after blur', () => {
cy.get('form ion-toggle').click();
testData({
datetime: '2010-08-20',
select: null,
toggle: true,
input: '',
input2: 'Default Value',
checkbox: false,
range: 5
});
cy.get('ion-checkbox').click();
testData({
datetime: '2010-08-20',
select: null,
toggle: true,
input: '',
input2: 'Default Value',
checkbox: true,
range: 5
});
});
});
});
function testStatus(status) {
cy.get('#status').should('have.text', status);
}
function testData(data) {
cy.get('#data').invoke('text').then(text => {
const value = JSON.parse(text);
console.log(value, data);
expect(value).to.deep.equal(data);
})
}

View File

@@ -1,69 +0,0 @@
import { browser, element, by } from 'protractor';
import { getProperty, setProperty, handleErrorMessages, waitTime } from './utils';
describe('inputs', () => {
beforeEach(async () => {
await browser.get('/inputs');
await waitTime(30);
});
afterEach(() => {
return handleErrorMessages();
});
it('should have default value', async () => {
expect(await getProperty('ion-checkbox', 'checked')).toEqual(true);
expect(await getProperty('ion-toggle', 'checked')).toEqual(true);
expect(await getProperty('ion-input', 'value')).toEqual('some text');
expect(await getProperty('ion-datetime', 'value')).toEqual('1994-03-15');
expect(await getProperty('ion-select', 'value')).toEqual('nes');
expect(await getProperty('ion-range', 'value')).toEqual(10);
});
it('should have reset value', async () => {
await element(by.css('#reset-button')).click();
expect(await getProperty('ion-checkbox', 'checked')).toEqual(false);
expect(await getProperty('ion-toggle', 'checked')).toEqual(false);
expect(await getProperty('ion-input', 'value')).toEqual('');
expect(await getProperty('ion-datetime', 'value')).toEqual('');
expect(await getProperty('ion-select', 'value')).toEqual('');
expect(await getProperty('ion-range', 'value')).toEqual(null);
});
it('should get some value', async () => {
await element(by.css('#reset-button')).click();
await element(by.css('#set-button')).click();
expect(await getProperty('ion-checkbox', 'checked')).toEqual(true);
expect(await getProperty('ion-toggle', 'checked')).toEqual(true);
expect(await getProperty('ion-input', 'value')).toEqual('some text');
expect(await getProperty('ion-datetime', 'value')).toEqual('1994-03-15');
expect(await getProperty('ion-select', 'value')).toEqual('nes');
expect(await getProperty('ion-range', 'value')).toEqual(10);
});
it('change values should update angular', async () => {
await element(by.css('#reset-button')).click();
await setProperty('ion-checkbox', 'checked', true);
await setProperty('ion-toggle', 'checked', true);
await setProperty('ion-input', 'value', 'hola');
await setProperty('ion-datetime', 'value', '1996-03-15');
await setProperty('ion-select', 'value', 'playstation');
await setProperty('ion-range', 'value', 20);
expect(await element(by.css('#checkbox-note')).getText()).toEqual('true');
expect(await element(by.css('#toggle-note')).getText()).toEqual('true');
expect(await element(by.css('#input-note')).getText()).toEqual('hola');
expect(await element(by.css('#datetime-note')).getText()).toEqual('1996-03-15');
expect(await element(by.css('#select-note')).getText()).toEqual('playstation');
expect(await element(by.css('#range-note')).getText()).toEqual('20');
});
it('nested components should not interfere with NgModel', async () => {
expect(await element(by.css('#range-note')).getText()).toEqual('10');
await element(by.css('#nested-toggle')).click();
expect(await element(by.css('#range-note')).getText()).toEqual('10');
});
});

View File

@@ -0,0 +1,61 @@
describe('Inputs', () => {
beforeEach(() => {
cy.visit('/inputs');
})
it('should have default value', () => {
cy.get('ion-checkbox').should('have.prop', 'checked').and('equal', true);
cy.get('ion-toggle').should('have.prop', 'checked').and('equal', true);
cy.get('ion-input').should('have.prop', 'value').and('equal', 'some text');
cy.get('ion-datetime').should('have.prop', 'value').and('equal', '1994-03-15');
cy.get('ion-select').should('have.prop', 'value').and('equal', 'nes');
cy.get('ion-range').should('have.prop', 'value').and('equal', 10);
});
it('should have reset value', () => {
cy.get('#reset-button').click();
cy.get('ion-checkbox').should('have.prop', 'checked').and('equal', false);
cy.get('ion-toggle').should('have.prop', 'checked').and('equal', false);
cy.get('ion-input').should('have.prop', 'value').and('equal', '');
cy.get('ion-datetime').should('have.prop', 'value').and('equal', '');
cy.get('ion-select').should('have.prop', 'value').and('equal', '');
cy.get('ion-range').should('have.prop', 'value').and('be.NaN');
});
it('should get some value', () => {
cy.get('#reset-button').click();
cy.get('#set-button').click();
cy.get('ion-checkbox').should('have.prop', 'checked').and('equal', true);
cy.get('ion-toggle').should('have.prop', 'checked').and('equal', true);
cy.get('ion-input').should('have.prop', 'value').and('equal', 'some text');
cy.get('ion-datetime').should('have.prop', 'value').and('equal', '1994-03-15');
cy.get('ion-select').should('have.prop', 'value').and('equal', 'nes');
cy.get('ion-range').should('have.prop', 'value').and('equal', 10);
});
it('change values should update angular', () => {
cy.get('#reset-button').click();
cy.get('ion-checkbox').invoke('prop', 'checked', true);
cy.get('ion-toggle').invoke('prop', 'checked', true);
cy.get('ion-input').invoke('prop', 'value', 'hola');
cy.get('ion-datetime').invoke('prop', 'value', '1996-03-15');
cy.get('ion-select').invoke('prop', 'value', 'playstation');
cy.get('ion-range').invoke('prop', 'value', 20);
cy.get('#checkbox-note').should('have.text', 'true');
cy.get('#toggle-note').should('have.text', 'true');
cy.get('#input-note').should('have.text', 'hola');
cy.get('#datetime-note').should('have.text', '1996-03-15');
cy.get('#select-note').should('have.text', 'playstation');
cy.get('#range-note').should('have.text', '20');
});
it('nested components should not interfere with NgModel', () => {
cy.get('#range-note').should('have.text', '10');
cy.get('#nested-toggle').click();
cy.get('#range-note').should('have.text', '10');
});
})

View File

@@ -1,55 +0,0 @@
import { browser, element, by } from 'protractor';
import { waitTime, getText, handleErrorMessages } from './utils';
describe('modals', () => {
beforeEach(async () => {
await browser.get('/modals');
await waitTime(30);
});
afterEach(() => {
return handleErrorMessages();
});
it('should open standalone modal and close', async () => {
await element(by.css('#action-button')).click();
await waitTime(800);
const modal = element(by.css('app-modal-example'));
expect(await modal.$('h2').getText()).toEqual('123');
expect(await modal.$('h3').getText()).toEqual('321');
expect(await getText('#onWillDismiss')).toEqual('false');
expect(await getText('#onDidDismiss')).toEqual('false');
await modal.$('#close-modal').click();
await waitTime(800);
expect(await getText('#onWillDismiss')).toEqual('true');
expect(await getText('#onDidDismiss')).toEqual('true');
});
it('should open nav modal and close', async () => {
await element(by.css('#action-button-2')).click();
await waitTime(800);
let page = element(by.css('ion-nav > *:last-child'));
expect(await page.$('h2').getText()).toEqual('123');
expect(await page.$('h3').getText()).toEqual('321');
await page.$('.push-page').click();
await waitTime(800);
page = element(by.css('ion-nav > *:last-child'));
expect(await page.$('h2').getText()).toEqual('pushed!');
expect(await page.$('h3').getText()).toEqual('');
await page.$('.pop-page').click();
await waitTime(800);
page = element(by.css('ion-nav > *:last-child'));
expect(await page.$('h2').getText()).toEqual('123');
});
});

View File

@@ -0,0 +1,43 @@
describe('Modals', () => {
beforeEach(() => {
cy.visit('/modals');
})
it('should open standalone modal and close', () => {
cy.get('#action-button').click();
cy.get('ion-modal').should('exist').should('be.visible');
cy.get('app-modal-example h2').should('have.text', '123');
cy.get('app-modal-example h3').should('have.text', '321');
cy.get('#onWillDismiss').should('have.text', 'false');
cy.get('#onDidDismiss').should('have.text', 'false');
cy.get('#close-modal').click();
cy.get('ion-modal').should('not.exist');
cy.get('#onWillDismiss').should('have.text', 'true');
cy.get('#onDidDismiss').should('have.text', 'true');
});
it('should open nav modal and close', () => {
cy.get('#action-button-2').click();
cy.get('ion-modal').should('exist').should('be.visible');
cy.get('ion-nav > *:last-child h2').should('have.text', '123');
cy.get('ion-nav > *:last-child h3').should('have.text', '321');
cy.get('ion-nav > *:last-child .push-page').click();
cy.get('ion-nav > *:last-child h2').should('have.text', 'pushed!');
cy.get('ion-nav > *:last-child h3').should('have.text', '');
cy.get('ion-nav > *:last-child .pop-page').click();
cy.get('ion-nav > *:last-child h2').should('have.text', '123');
});
});

View File

@@ -1,73 +0,0 @@
import { browser, element, by } from 'protractor';
import { handleErrorMessages, waitTime, testStack } from './utils';
describe('navigation', () => {
afterEach(() => {
return handleErrorMessages();
});
// TODO: Fix flaky tests
xit ('should swipe and abort', async () => {
await browser.get('/router-link?ionic:mode=ios');
await waitTime(500);
await element(by.css('#routerLink')).click();
await waitTime(500);
await swipeLeft(5);
await waitTime(500);
const pageHidden = element(by.css('app-router-link'));
expect(await pageHidden.getAttribute('aria-hidden')).toEqual('true');
expect(await pageHidden.getAttribute('class')).toEqual('ion-page ion-page-hidden');
const pageVisible = element(by.css('app-router-link-page'));
expect(await pageVisible.getAttribute('aria-hidden')).toEqual(null);
expect(await pageVisible.getAttribute('class')).toEqual('ion-page can-go-back');
});
xit ('should swipe and go back', async () => {
await browser.get('/router-link?ionic:mode=ios');
await waitTime(500);
await element(by.css('#routerLink')).click();
await waitTime(500);
await testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
await swipeLeft(300);
await waitTime(1000);
await testStack('ion-router-outlet', ['app-router-link']);
const page = element(by.css('app-router-link'));
expect(await page.getAttribute('aria-hidden')).toEqual(null);
expect(await page.getAttribute('class')).toEqual('ion-page');
})
it('should navigate correctly', async () => {
await browser.get('/navigation/page1');
await waitTime(2000);
await testStack('ion-router-outlet', ['app-navigation-page2', 'app-navigation-page1']);
const pageHidden = element(by.css('app-navigation-page2'));
expect(await pageHidden.getAttribute('aria-hidden')).toEqual('true');
expect(await pageHidden.getAttribute('class')).toEqual('ion-page ion-page-hidden');
const pageVisible = element(by.css('app-navigation-page1'));
expect(await pageVisible.getAttribute('aria-hidden')).toEqual(null);
expect(await pageVisible.getAttribute('class')).toEqual('ion-page can-go-back');
});
});
function swipeLeft(end: number) {
return browser.driver.touchActions()
.tapAndHold({x: 5, y: 1})
.move({x: 6, y: 1})
.move({x: 7, y: 1})
.move({x: 8, y: 1})
.move({x: 30, y: 1})
.move({x: 300, y: 1})
.move({x: end, y: 1})
.move({x: end, y: 1})
.release({x: end, y: 1})
.perform();
}

View File

@@ -0,0 +1,18 @@
describe('Navigation', () => {
beforeEach(() => {
cy.visit('/navigation');
})
it('should navigate correctly', () => {
cy.visit('/navigation/page1');
cy.wait(2000);
cy.testStack('ion-router-outlet', ['app-navigation-page2', 'app-navigation-page1']);
cy.get('app-navigation-page2').should('have.attr', 'aria-hidden').and('equal', 'true');
cy.get('app-navigation-page2').should('have.attr', 'class').and('equal', 'ion-page ion-page-hidden');
cy.get('app-navigation-page1').should('not.have.attr', 'aria-hidden');
cy.get('app-navigation-page1').should('have.attr', 'class').and('equal', 'ion-page can-go-back');
});
})

View File

@@ -1,23 +0,0 @@
import { browser, element, by } from 'protractor';
import { waitTime, handleErrorMessages, goBack } from './utils';
describe('nested-outlet', () => {
afterEach(() => {
return handleErrorMessages();
});
it('should navigate correctly', async () => {
await browser.get('/nested-outlet/page');
expect(await element(by.css('ion-router-outlet ion-router-outlet app-nested-outlet-page h1')).getText()).toEqual('Nested page 1');
await element(by.css('#goto-tabs')).click();
await waitTime(500);
await element(by.css('#goto-nested-page1')).click();
await waitTime(500);
await element(by.css('#goto-nested-page2')).click();
await waitTime(500);
expect(await element(by.css('ion-router-outlet ion-router-outlet app-nested-outlet-page2 h1')).getText()).toEqual('Nested page 2');
});
});

View File

@@ -0,0 +1,25 @@
describe('Nested Outlet', () => {
beforeEach(() => {
cy.visit('/nested-outlet/page');
})
it('should navigate correctly', () => {
cy.get('ion-router-outlet ion-router-outlet app-nested-outlet-page h1').should('have.text', 'Nested page 1');
cy.get('#goto-tabs').click();
cy.ionPageVisible('app-tabs');
cy.ionPageVisible('app-tabs-tab1');
cy.get('#goto-nested-page1').click();
cy.ionPageVisible('app-nested-outlet-page');
cy.ionPageDoesNotExist('app-tabs');
cy.get('#goto-nested-page2').click();
cy.ionPageVisible('app-nested-outlet-page2');
cy.get('ion-router-outlet ion-router-outlet app-nested-outlet-page2 h1').should('have.text', 'Nested page 2');
});
});

View File

@@ -1,29 +0,0 @@
import { browser, element, by } from 'protractor';
import { handleErrorMessages, waitTime } from './utils';
describe('providers', () => {
afterEach(() => {
return handleErrorMessages();
});
it('should load all providers', async () => {
await browser.get('/providers');
expect(await element(by.css('#is-loaded')).getText()).toEqual('true');
expect(await element(by.css('#is-ready')).getText()).toEqual('true');
expect(await element(by.css('#is-paused')).getText()).toEqual('true');
expect(await element(by.css('#is-resumed')).getText()).toEqual('true');
expect(await element(by.css('#is-resized')).getText()).toEqual('true');
expect(await element(by.css('#is-testing')).getText()).toEqual('false');
expect(await element(by.css('#is-desktop')).getText()).toEqual('true');
expect(await element(by.css('#is-mobile')).getText()).toEqual('false');
expect(await element(by.css('#keyboard-height')).getText()).toEqual('12345');
});
it('should detect testing mode', async () => {
await browser.get('/providers?ionic:_testing=true');
expect(await element(by.css('#is-testing')).getText()).toEqual('true');
});
});

View File

@@ -0,0 +1,24 @@
describe('Providers', () => {
beforeEach(() => {
cy.visit('/providers');
})
it('should load all providers', () => {
cy.get('#is-loaded').should('have.text', 'true');
cy.get('#is-ready').should('have.text', 'true');
cy.get('#is-paused').should('have.text', 'true');
cy.get('#is-resumed').should('have.text', 'true');
cy.get('#is-resized').should('have.text', 'true');
cy.get('#is-testing').should('have.text', 'false');
cy.get('#is-desktop').should('have.text', 'true');
cy.get('#is-mobile').should('have.text', 'false');
cy.get('#keyboard-height').should('have.text', '12345');
});
it('should detect testing mode', () => {
cy.visit('/providers?ionic:_testing=true');
cy.get('#is-testing').should('have.text', 'true');
});
});

View File

@@ -1,194 +0,0 @@
import { browser, element, by, protractor } from 'protractor';
import { waitTime, testStack, testLifeCycle, handleErrorMessages, getText } from './utils';
const EC = protractor.ExpectedConditions;
describe('router-link params and fragments', () => {
const queryParam = 'A&=#Y';
const fragment = 'myDiv1';
const id = 'MyPageID==';
afterEach(() => {
return handleErrorMessages();
});
it('should go to a page with properly encoded values', async () => {
await browser.get('/router-link?ionic:_testing=true');
await element(by.css('#queryParamsFragment')).click();
const expectedRoute = `${encodeURIComponent(id)}?token=${encodeURIComponent(queryParam)}#${encodeURIComponent(fragment)}`;
browser.wait(EC.urlContains(expectedRoute), 5000);
});
it('should return to a page with preserved query param and fragment', async () => {
await browser.get('/router-link?ionic:_testing=true');
await waitTime(30);
await element(by.css('#queryParamsFragment')).click();
await waitTime(400);
await element(by.css('#goToPage3')).click();
browser.wait(EC.urlContains('router-link-page3'), 5000);
await waitTime(400);
await element(by.css('#goBackFromPage3')).click();
const expectedRoute = `${encodeURIComponent(id)}?token=${encodeURIComponent(queryParam)}#${encodeURIComponent(fragment)}`;
browser.wait(EC.urlContains(expectedRoute), 5000);
});
it('should preserve query param and fragment with defaultHref string', async () => {
await browser.get('/router-link-page3?ionic:_testing=true');
await waitTime(30);
await element(by.css('#goBackFromPage3')).click();
const expectedRoute = '?token=ABC#fragment';
browser.wait(EC.urlContains(expectedRoute), 5000);
});
});
describe('router-link', () => {
beforeEach(async () => {
await browser.get('/router-link');
await waitTime(30);
});
afterEach(() => {
return handleErrorMessages();
});
it('should have correct lifecycle counts', async () => {
await testLifeCycle('app-router-link', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
});
describe('forward', () => {
it('should go forward with ion-button[routerLink]', async () => {
await element(by.css('#routerLink')).click();
await testForward();
});
it('should go forward with a[routerLink]', async () => {
await element(by.css('#a')).click();
await testForward();
});
it('should go forward with button + navigateByUrl()', async () => {
await element(by.css('#button')).click();
await testForward();
});
it('should go forward with button + navigateForward()', async () => {
await element(by.css('#button-forward')).click();
await testForward();
});
});
describe('root', () => {
it('should go root with ion-button[routerLink][routerDirection=root]', async () => {
await element(by.css('#routerLink-root')).click();
await testRoot();
});
it('should go root with a[routerLink][routerDirection=root]', async () => {
await element(by.css('#a-root')).click();
await testRoot();
});
it('should go root with button + navigateRoot', async () => {
await element(by.css('#button-root')).click();
await testRoot();
});
});
describe('back', () => {
it('should go back with ion-button[routerLink][routerDirection=back]', async () => {
await element(by.css('#routerLink-back')).click();
});
it('should go back with a[routerLink][routerDirection=back]', async () => {
await element(by.css('#a-back')).click();
await testBack();
});
it('should go back with button + navigateBack', async () => {
await element(by.css('#button-back')).click();
await testBack();
});
});
});
async function testForward() {
await waitTime(2500);
await testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
await testLifeCycle('app-router-link-page', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('true');
await browser.navigate().back();
await waitTime(100);
await testStack('ion-router-outlet', ['app-router-link']);
await testLifeCycle('app-router-link', {
ionViewWillEnter: 2,
ionViewDidEnter: 2,
ionViewWillLeave: 1,
ionViewDidLeave: 1,
});
}
async function testRoot() {
await waitTime(200);
await testStack('ion-router-outlet', ['app-router-link-page']);
await testLifeCycle('app-router-link-page', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('false');
await browser.navigate().back();
await waitTime(100);
await testStack('ion-router-outlet', ['app-router-link']);
await testLifeCycle('app-router-link', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
}
async function testBack() {
await waitTime(500);
await testStack('ion-router-outlet', ['app-router-link-page']);
await testLifeCycle('app-router-link-page', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('false');
await browser.navigate().back();
await waitTime(100);
await testStack('ion-router-outlet', ['app-router-link']);
await testLifeCycle('app-router-link', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
}

View File

@@ -0,0 +1,192 @@
describe('Router Link', () => {
beforeEach(() => {
cy.visit('/router-link');
});
describe('router-link params and fragments', () => {
const queryParam = 'A&=#Y';
const fragment = 'myDiv1';
const id = 'MyPageID==';
it('should go to a page with properly encoded values', () => {
cy.visit('/router-link?ionic:_testing=true');
cy.get('#queryParamsFragment').click();
const expectedPath = `${encodeURIComponent(id)}`;
const expectedSearch = `?token=${encodeURIComponent(queryParam)}`;
const expectedHash = `#${encodeURIComponent(fragment)}`;
cy.location().should((location) => {
expect(location.pathname).to.contain(expectedPath);
expect(location.search).to.eq(expectedSearch);
expect(location.hash).to.eq(expectedHash);
});
});
it('should return to a page with preserved query param and fragment', () => {
cy.visit('/router-link?ionic:_testing=true');
cy.get('#queryParamsFragment').click();
cy.get('#goToPage3').click();
cy.location().should((location) => {
expect(location.pathname).to.contain('router-link-page3');
});
cy.get('#goBackFromPage3').click();
const expectedPath = `${encodeURIComponent(id)}`;
const expectedSearch = `?token=${encodeURIComponent(queryParam)}`;
const expectedHash = `#${encodeURIComponent(fragment)}`;
cy.location().should((location) => {
expect(location.pathname).to.contain(expectedPath);
expect(location.search).to.eq(expectedSearch);
expect(location.hash).to.eq(expectedHash);
});
});
it('should preserve query param and fragment with defaultHref string', () => {
cy.visit('/router-link-page3?ionic:_testing=true');
cy.get('#goBackFromPage3').click();
const expectedSearch = '?token=ABC';
const expectedHash = '#fragment';
cy.location().should((location) => {
expect(location.search).to.eq(expectedSearch);
expect(location.hash).to.eq(expectedHash);
});
});
});
describe('router-link', () => {
it('should have correct lifecycle counts', () => {
cy.testLifeCycle('app-router-link', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
});
});
describe('forward', () => {
it('should go forward with ion-button[routerLink]', () => {
cy.get('#routerLink').click();
testForward();
});
it('should go forward with a[routerLink]', () => {
cy.get('#a').click();
testForward();
});
it('should go forward with button + navigateByUrl()', () => {
cy.get('#button').click();
testForward();
});
it('should go forward with button + navigateForward()', () => {
cy.get('#button-forward').click();
testForward();
});
});
describe('root', () => {
it('should go root with ion-button[routerLink][routerDirection=root]', () => {
cy.get('#routerLink-root').click();
testRoot();
});
it('should go root with a[routerLink][routerDirection=root]', () => {
cy.get('#a-root').click();
testRoot();
});
it('should go root with button + navigateRoot', () => {
cy.get('#button-root').click();
testRoot();
});
});
describe('back', () => {
it('should go back with ion-button[routerLink][routerDirection=back]', () => {
cy.get('#routerLink-back').click();
});
it('should go back with a[routerLink][routerDirection=back]', () => {
cy.get('#a-back').click();
testBack();
});
it('should go back with button + navigateBack', () => {
cy.get('#button-back').click();
testBack();
});
});
});
function testForward() {
cy.testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
cy.testLifeCycle('app-router-link-page', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
cy.get('app-router-link-page #canGoBack').should('have.text', 'true');
cy.go('back');
cy.testStack('ion-router-outlet', ['app-router-link']);
cy.testLifeCycle('app-router-link', {
ionViewWillEnter: 2,
ionViewDidEnter: 2,
ionViewWillLeave: 1,
ionViewDidLeave: 1,
});
}
function testRoot() {
cy.wait(200);
cy.testStack('ion-router-outlet', ['app-router-link-page']);
cy.testLifeCycle('app-router-link-page', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
cy.get('app-router-link-page #canGoBack').should('have.text', 'false');
cy.go('back');
cy.wait(100);
cy.testStack('ion-router-outlet', ['app-router-link']);
cy.testLifeCycle('app-router-link', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
}
function testBack() {
cy.wait(500);
cy.testStack('ion-router-outlet', ['app-router-link-page']);
cy.testLifeCycle('app-router-link-page', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
cy.get('app-router-link-page #canGoBack').should('have.text', 'false');
cy.go('back');
cy.wait(100);
cy.testStack('ion-router-outlet', ['app-router-link']);
cy.testLifeCycle('app-router-link', {
ionViewWillEnter: 1,
ionViewDidEnter: 1,
ionViewWillLeave: 0,
ionViewDidLeave: 0,
});
}

View File

@@ -0,0 +1,36 @@
describe('Routing', () => {
beforeEach(() => {
cy.visit('/router-link?ionic:mode=ios');
})
it('should swipe and abort', () => {
cy.get('#routerLink').click();
cy.ionSwipeToGoBack();
cy.get('app-router-link').should('have.attr', 'aria-hidden').and('equal', 'true');
cy.get('app-router-link').should('have.attr', 'class').and('equal', 'ion-page ion-page-hidden');
cy.get('app-router-link-page').should('not.have.attr', 'aria-hidden');
cy.get('app-router-link-page').should('have.attr', 'class').and('equal', 'ion-page can-go-back');
});
it('should swipe and go back', () => {
cy.get('#routerLink').click();
cy.ionPageHidden('app-router-link');
cy.ionPageVisible('app-router-link-page');
cy.testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
cy.ionSwipeToGoBack(true);
cy.ionPageVisible('app-router-link');
cy.ionPageDoesNotExist('app-router-link-page');
cy.testStack('ion-router-outlet', ['app-router-link']);
cy.get('app-router-link').should('not.have.attr', 'aria-hidden');
cy.get('app-router-link').should('have.attr', 'class').and('equal', 'ion-page');
});
})

View File

@@ -1,51 +0,0 @@
import { browser, element, by } from 'protractor';
import { handleErrorMessages, waitTime } from './utils';
describe('slides', () => {
beforeEach(async () => {
await browser.get('/slides');
await waitTime(30);
});
afterEach(() => {
return handleErrorMessages();
});
it('should change index on slide change', async () => {
expect(await element.all(by.css('ion-slide')).count()).toEqual(0);
await addSlides();
expect(await element.all(by.css('ion-slide')).count()).toEqual(3);
await checkIndex('0');
await nextSlide();
await checkIndex('1');
await nextSlide();
await checkIndex('2');
await prevSlide();
await checkIndex('1');
});
});
async function checkIndex(index: string) {
expect(await element(by.css('#slide-index')).getText()).toEqual(index);
expect(await element(by.css('#slide-index-2')).getText()).toEqual(index);
}
async function addSlides() {
await element(by.css('#add-slides')).click();
await waitTime(800);
}
async function nextSlide() {
await element(by.css('#btn-next')).click();
await waitTime(800);
}
async function prevSlide() {
await element(by.css('#btn-prev')).click();
await waitTime(800);
}

View File

@@ -0,0 +1,44 @@
describe('Slides', () => {
beforeEach(() => {
cy.visit('/slides');
cy.wait(30);
})
it('should change index on slide change', () => {
cy.get('ion-slide').should('have.length', 0);
cy.get('#add-slides').click();
cy.get('ion-slide').should('have.length', 3);
// Should be on the first slide
checkIndex('0');
// Swipe to the second slide
nextSlide();
checkIndex('1');
// Swipe to the third slide
nextSlide();
checkIndex('2');
// Go back to the second slide
prevSlide();
checkIndex('1');
});
});
function checkIndex(index) {
cy.get('#slide-index').should('have.text', index);
cy.get('#slide-index-2').should('have.text', index);
}
function nextSlide() {
cy.get('#btn-next').click();
cy.wait(800);
}
function prevSlide() {
cy.get('#btn-prev').click();
cy.wait(800);
}

View File

@@ -1,334 +0,0 @@
import { browser, by, element, ElementFinder, ExpectedConditions } from 'protractor';
import { handleErrorMessages, testStack, waitTime } from './utils';
describe('tabs', () => {
afterEach(() => {
return handleErrorMessages();
});
describe('entry url - /tabs', () => {
beforeEach(async () => {
await browser.get('/tabs');
await waitTime(30);
});
it('should redirect and load tab-account', async () => {
await testTabTitle('Tab 1 - Page 1');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1']);
await testState(1, 'account');
});
it('should navigate between tabs and ionChange events should be dispatched ', async () => {
let tab = await testTabTitle('Tab 1 - Page 1');
expect(await tab.$('.segment-changed').getText()).toEqual('false');
await element(by.css('#tab-button-contact')).click();
tab = await testTabTitle('Tab 2 - Page 1');
expect(await tab.$('.segment-changed').getText()).toEqual('false');
});
it('should simulate stack + double tab click', async () => {
let tab = await getSelectedTab() as ElementFinder;
await tab.$('#goto-tab1-page2').click();
await testTabTitle('Tab 1 - Page 2 (1)');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested']);
await testState(1, 'account');
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
await element(by.css('#tab-button-contact')).click();
await testTabTitle('Tab 2 - Page 1');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
await testState(2, 'contact');
await element(by.css('#tab-button-account')).click();
tab = await testTabTitle('Tab 1 - Page 2 (1)');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
await testState(3, 'account');
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 1');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
await testState(3, 'account');
});
it('should simulate stack + back button click', async () => {
const tab = await getSelectedTab();
await tab.$('#goto-tab1-page2').click();
await testTabTitle('Tab 1 - Page 2 (1)');
await testState(1, 'account');
await element(by.css('#tab-button-contact')).click();
await testTabTitle('Tab 2 - Page 1');
await testState(2, 'contact');
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 2 (1)');
await testState(3, 'account');
await element(by.css('ion-back-button')).click();
await testTabTitle('Tab 1 - Page 1');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
await testState(3, 'account');
});
it('should navigate deep then go home', async () => {
let tab = await getSelectedTab();
await tab.$('#goto-tab1-page2').click();
tab = await testTabTitle('Tab 1 - Page 2 (1)');
await tab.$('#goto-next').click();
tab = await testTabTitle('Tab 1 - Page 2 (2)');
await element(by.css('#tab-button-contact')).click();
tab = await testTabTitle('Tab 2 - Page 1');
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 2 (2)');
await testStack('ion-tabs ion-router-outlet', [
'app-tabs-tab1',
'app-tabs-tab1-nested',
'app-tabs-tab1-nested',
'app-tabs-tab2'
]);
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 1');
await testStack('ion-tabs ion-router-outlet', [
'app-tabs-tab1',
'app-tabs-tab2'
]);
});
it('should switch tabs and go back', async () => {
await element(by.css('#tab-button-contact')).click();
const tab = await testTabTitle('Tab 2 - Page 1');
await tab.$('#goto-tab1-page1').click();
await testTabTitle('Tab 1 - Page 1');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
});
it('should switch tabs and go to nested', async () => {
await element(by.css('#tab-button-contact')).click();
const tab = await testTabTitle('Tab 2 - Page 1');
await tab.$('#goto-tab1-page2').click();
await testTabTitle('Tab 1 - Page 2 (1)');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab2', 'app-tabs-tab1-nested']);
});
it('should load lazy loaded tab', async () => {
await element(by.css('#tab-button-lazy')).click();
await testTabTitle('Tab 3 - Page 1');
});
it('should use ion-back-button defaultHref', async () => {
let tab = await getSelectedTab() as ElementFinder;
await tab.$('#goto-tab3-page2').click();
tab = await testTabTitle('Tab 3 - Page 2');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab3-nested']);
await tab.$('ion-back-button').click();
await testTabTitle('Tab 3 - Page 1');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab3']);
});
it('should preserve navigation extras when switching tabs', async () => {
const expectUrlToContain = 'search=hello#fragment';
let tab = await getSelectedTab() as ElementFinder;
await tab.$('#goto-nested-page1-with-query-params').click();
await testTabTitle('Tab 1 - Page 2 (1)');
await testUrlContains(expectUrlToContain);
await element(by.css('#tab-button-contact')).click();
await testTabTitle('Tab 2 - Page 1');
await element(by.css('#tab-button-account')).click();
tab = await testTabTitle('Tab 1 - Page 2 (1)');
await testUrlContains(expectUrlToContain);
});
it('should set root when clicking on an active tab to navigate to the root', async () => {
const expectNestedTabUrlToContain = 'search=hello#fragment';
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)');
await testUrlContains(expectNestedTabUrlToContain);
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 1');
await testUrlEquals(initialUrl);
});
});
describe('entry tab contains navigation extras', () => {
const expectNestedTabUrlToContain = 'search=hello#fragment';
const rootUrlParams = 'test=123#rootFragment';
const rootUrl = `/tabs/account?${rootUrlParams}`;
beforeEach(async () => {
await browser.get(rootUrl);
await waitTime(30);
});
it('should preserve root url navigation extras when clicking on an active tab to navigate to the root', async () => {
await browser.get(rootUrl);
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);
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 1');
await testUrlContains(rootUrl);
});
it('should preserve root url navigation extras when changing tabs', async () => {
await browser.get(rootUrl);
let tab = await getSelectedTab() as ElementFinder;
await element(by.css('#tab-button-contact')).click();
tab = await testTabTitle('Tab 2 - Page 1');
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 1');
await testUrlContains(rootUrl);
});
it('should navigate deep then go home and preserve navigation extras', async () => {
let tab = await getSelectedTab();
await tab.$('#goto-tab1-page2').click();
tab = await testTabTitle('Tab 1 - Page 2 (1)');
await tab.$('#goto-next').click();
tab = await testTabTitle('Tab 1 - Page 2 (2)');
await element(by.css('#tab-button-contact')).click();
tab = await testTabTitle('Tab 2 - Page 1');
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 2 (2)');
await element(by.css('#tab-button-account')).click();
await testTabTitle('Tab 1 - Page 1');
await testUrlContains(rootUrl);
});
});
describe('entry url - /tabs/account/nested/1', () => {
beforeEach(async () => {
await browser.get('/tabs/account/nested/1');
await waitTime(30);
});
it('should only display the back-button when there is a page in the stack', async () => {
let tab = await testTabTitle('Tab 1 - Page 2 (1)') as ElementFinder;
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
await element(by.css('#tab-button-account')).click();
tab = await testTabTitle('Tab 1 - Page 1');
await tab.$('#goto-tab1-page2').click();
tab = await testTabTitle('Tab 1 - Page 2 (1)');
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
});
it('should not reuse the same page', async () => {
let tab = await testTabTitle('Tab 1 - Page 2 (1)') as ElementFinder;
await tab.$('#goto-next').click();
tab = await testTabTitle('Tab 1 - Page 2 (2)');
await tab.$('#goto-next').click();
tab = await testTabTitle('Tab 1 - Page 2 (3)');
await testStack('ion-tabs ion-router-outlet', [
'app-tabs-tab1-nested',
'app-tabs-tab1-nested',
'app-tabs-tab1-nested'
]);
await tab.$('ion-back-button').click();
tab = await testTabTitle('Tab 1 - Page 2 (2)');
await tab.$('ion-back-button').click();
tab = await testTabTitle('Tab 1 - Page 2 (1)');
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
});
});
describe('entry url - /tabs/lazy', () => {
beforeEach(async () => {
await browser.get('/tabs/lazy');
await waitTime(30);
});
it('should not display the back-button if coming from a different stack', async () => {
let tab = await testTabTitle('Tab 3 - Page 1') as ElementFinder;
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3']);
await tab.$('#goto-tab1-page2').click();
tab = await testTabTitle('Tab 1 - Page 2 (1)');
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3', 'app-tabs-tab1-nested']);
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
});
});
describe('enter url - /tabs/contact/one', () => {
beforeEach(async () => {
await browser.get('/tabs/contact/one');
await waitTime(30);
});
it('should return to correct tab after going to page in different outlet', async () => {
const tab = await getSelectedTab();
await tab.$('#goto-nested-page1').click();
await waitTime(600);
await testStack('app-nested-outlet ion-router-outlet', ['app-nested-outlet-page']);
const nestedOutlet = await element(by.css('app-nested-outlet'));
const backButton = await nestedOutlet.$('ion-back-button');
await backButton.click();
await testTabTitle('Tab 2 - Page 1');
});
})
});
async function testState(count: number, tab: string) {
expect(await element(by.css('#tabs-state')).getText()).toEqual(`${count}.${tab}`);
}
async function testTabTitle(title: string) {
await waitTime(1000);
const tab = await getSelectedTab();
expect(await tab.$('ion-title').getText()).toEqual(title);
return tab;
}
async function testUrlContains(urlFragment: string) {
await browser.wait(ExpectedConditions.urlContains(urlFragment),
5000,
`expected ${browser.getCurrentUrl()} to contain ${urlFragment}`);
}
async function testUrlEquals(url: string) {
await browser.wait(ExpectedConditions.urlIs(url),
5000,
`expected ${browser.getCurrentUrl()} to equal ${url}`);
}
async function getSelectedTab(): Promise<ElementFinder> {
const tabs = element.all(by.css('ion-tabs ion-router-outlet > *:not(.ion-page-hidden)'));
expect(await tabs.count()).toEqual(1);
const tab = tabs.first();
return tab;
}

View File

@@ -0,0 +1,329 @@
describe('Tabs', () => {
beforeEach(() => {
cy.visit('/tabs');
})
describe('entry url - /tabs', () => {
it('should redirect and load tab-account', () => {
testTabTitle('Tab 1 - Page 1');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1']);
testState(1, 'account');
});
it('should navigate between tabs and ionChange events should be dispatched', () => {
let tab = testTabTitle('Tab 1 - Page 1');
tab.find('.segment-changed').should('have.text', 'false');
cy.get('#tab-button-contact').click();
tab = testTabTitle('Tab 2 - Page 1');
tab.find('.segment-changed').should('have.text', 'false');
});
it('should simulate stack + double tab click', () => {
let tab = getSelectedTab();
tab.find('#goto-tab1-page2').click();
testTabTitle('Tab 1 - Page 2 (1)');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested']);
testState(1, 'account');
// When you call find on tab above it changes the value of tab
// so we need to redefine it
tab = getSelectedTab();
tab.find('ion-back-button').should('be.visible');
cy.get('#tab-button-contact').click();
testTabTitle('Tab 2 - Page 1');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
testState(2, 'contact');
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 2 (1)');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
testState(3, 'account');
tab = getSelectedTab();
tab.find('ion-back-button').should('be.visible');
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 1');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
testState(3, 'account');
});
it('should simulate stack + back button click', () => {
const tab = getSelectedTab();
tab.find('#goto-tab1-page2').click();
testTabTitle('Tab 1 - Page 2 (1)');
testState(1, 'account');
cy.get('#tab-button-contact').click();
testTabTitle('Tab 2 - Page 1');
testState(2, 'contact');
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 2 (1)');
testState(3, 'account');
cy.get('ion-back-button').click();
testTabTitle('Tab 1 - Page 1');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
testState(3, 'account');
});
it('should navigate deep then go home', () => {
const tab = getSelectedTab();
tab.find('#goto-tab1-page2').click();
testTabTitle('Tab 1 - Page 2 (1)');
cy.get('#goto-next').click();
testTabTitle('Tab 1 - Page 2 (2)');
cy.get('#tab-button-contact').click();
testTabTitle('Tab 2 - Page 1');
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 2 (2)');
cy.testStack('ion-tabs ion-router-outlet', [
'app-tabs-tab1',
'app-tabs-tab1-nested',
'app-tabs-tab1-nested',
'app-tabs-tab2'
]);
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 1');
cy.testStack('ion-tabs ion-router-outlet', [
'app-tabs-tab1',
'app-tabs-tab2'
]);
});
it('should switch tabs and go back', () => {
cy.get('#tab-button-contact').click();
const tab = testTabTitle('Tab 2 - Page 1');
tab.find('#goto-tab1-page1').click();
testTabTitle('Tab 1 - Page 1');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
});
it('should switch tabs and go to nested', () => {
cy.get('#tab-button-contact').click();
const tab = testTabTitle('Tab 2 - Page 1');
tab.find('#goto-tab1-page2').click();
testTabTitle('Tab 1 - Page 2 (1)');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab2', 'app-tabs-tab1-nested']);
});
it('should load lazy loaded tab', () => {
cy.get('#tab-button-lazy').click();
cy.ionPageVisible('app-tabs-tab3');
testTabTitle('Tab 3 - Page 1');
});
it('should use ion-back-button defaultHref', () => {
let tab = getSelectedTab();
tab.find('#goto-tab3-page2').click();
testTabTitle('Tab 3 - Page 2');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab3-nested']);
tab = getSelectedTab();
tab.find('ion-back-button').click();
testTabTitle('Tab 3 - Page 1');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab3']);
});
it('should preserve navigation extras when switching tabs', () => {
const expectUrlToContain = 'search=hello#fragment';
let tab = getSelectedTab();
tab.find('#goto-nested-page1-with-query-params').click();
testTabTitle('Tab 1 - Page 2 (1)');
testUrlContains(expectUrlToContain);
cy.get('#tab-button-contact').click();
testTabTitle('Tab 2 - Page 1');
cy.get('#tab-button-account').click();
tab = testTabTitle('Tab 1 - Page 2 (1)');
testUrlContains(expectUrlToContain);
});
it('should set root when clicking on an active tab to navigate to the root', () => {
const expectNestedTabUrlToContain = 'search=hello#fragment';
cy.url().then(url => {
const tab = getSelectedTab();
tab.find('#goto-nested-page1-with-query-params').click();
testTabTitle('Tab 1 - Page 2 (1)');
testUrlContains(expectNestedTabUrlToContain);
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 1');
testUrlEquals(url);
})
});
})
describe('entry tab contains navigation extras', () => {
const expectNestedTabUrlToContain = 'search=hello#fragment';
const rootUrlParams = 'test=123#rootFragment';
const rootUrl = `/tabs/account?${rootUrlParams}`;
beforeEach(() => {
cy.visit(rootUrl);
})
it('should preserve root url navigation extras when clicking on an active tab to navigate to the root', () => {
const tab = getSelectedTab();
tab.find('#goto-nested-page1-with-query-params').click();
testTabTitle('Tab 1 - Page 2 (1)');
testUrlContains(expectNestedTabUrlToContain);
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 1');
testUrlContains(rootUrl);
});
it('should preserve root url navigation extras when changing tabs', () => {
getSelectedTab();
cy.get('#tab-button-contact').click();
testTabTitle('Tab 2 - Page 1');
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 1');
testUrlContains(rootUrl);
});
it('should navigate deep then go home and preserve navigation extras', () => {
let tab = getSelectedTab();
tab.find('#goto-tab1-page2').click();
tab = testTabTitle('Tab 1 - Page 2 (1)');
tab.find('#goto-next').click();
testTabTitle('Tab 1 - Page 2 (2)');
cy.get('#tab-button-contact').click();
testTabTitle('Tab 2 - Page 1');
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 2 (2)');
cy.get('#tab-button-account').click();
testTabTitle('Tab 1 - Page 1');
testUrlContains(rootUrl);
});
})
describe('entry url - /tabs/account/nested/1', () => {
beforeEach(() => {
cy.visit('/tabs/account/nested/1');
})
it('should only display the back-button when there is a page in the stack', () => {
let tab = getSelectedTab();
tab.find('ion-back-button').should('not.be.visible');
testTabTitle('Tab 1 - Page 2 (1)');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
cy.get('#tab-button-account').click();
tab = testTabTitle('Tab 1 - Page 1');
tab.find('#goto-tab1-page2').click();
tab = testTabTitle('Tab 1 - Page 2 (1)');
tab.find('ion-back-button').should('be.visible');
});
it('should not reuse the same page', () => {
let tab = testTabTitle('Tab 1 - Page 2 (1)');
tab.find('#goto-next').click();
tab = testTabTitle('Tab 1 - Page 2 (2)');
tab.find('#goto-next').click();
tab = testTabTitle('Tab 1 - Page 2 (3)');
cy.testStack('ion-tabs ion-router-outlet', [
'app-tabs-tab1-nested',
'app-tabs-tab1-nested',
'app-tabs-tab1-nested'
]);
tab = getSelectedTab();
tab.find('ion-back-button').click();
tab = testTabTitle('Tab 1 - Page 2 (2)');
tab.find('ion-back-button').click();
tab = testTabTitle('Tab 1 - Page 2 (1)');
tab.find('ion-back-button').should('not.be.visible');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
});
})
describe('entry url - /tabs/lazy', () => {
beforeEach(() => {
cy.visit('/tabs/lazy');
});
it('should not display the back-button if coming from a different stack', () => {
let tab = testTabTitle('Tab 3 - Page 1');
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3']);
tab = getSelectedTab();
tab.find('#goto-tab1-page2').click();
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3', 'app-tabs-tab1-nested']);
tab = testTabTitle('Tab 1 - Page 2 (1)');
tab.find('ion-back-button').should('not.be.visible');
});
})
describe('enter url - /tabs/contact/one', () => {
beforeEach(() => {
cy.visit('/tabs/contact/one');
});
it('should return to correct tab after going to page in different outlet', () => {
const tab = getSelectedTab();
tab.find('#goto-nested-page1').click();
cy.testStack('app-nested-outlet ion-router-outlet', ['app-nested-outlet-page']);
const nestedOutlet = cy.get('app-nested-outlet');
nestedOutlet.find('ion-back-button').click();
testTabTitle('Tab 2 - Page 1');
});
})
})
function testTabTitle(title) {
const tab = getSelectedTab();
// Find is used to get a direct descendant instead of get
tab.find('ion-title').should('have.text', title);
return getSelectedTab();
}
function getSelectedTab() {
cy.get('ion-tabs ion-router-outlet > *:not(.ion-page-hidden)').should('have.length', 1);
return cy.get('ion-tabs ion-router-outlet > *:not(.ion-page-hidden)').first();
}
function testState(count, tab) {
cy.get('#tabs-state').should('have.text', `${count}.${tab}`);
}
function testUrlContains(urlFragment) {
cy.location().should((location) => {
expect(location.href).to.contain(urlFragment);
});
}
function testUrlEquals(url) {
cy.url().should('eq', url);
}

View File

@@ -1,73 +0,0 @@
import { browser } from 'protractor';
export function goBack() {
return browser.executeScript(`return window.history.back()`);
}
export function getProperty(selector: string, property: string) {
return browser.executeScript(`
return document.querySelector('${selector}')['${property}'];
`);
}
export function getText(selector: string) {
return browser.executeScript(`
return document.querySelector('${selector}').textContent;
`);
}
export function setProperty(selector: string, property: string, value: any) {
const text = JSON.stringify(value);
return browser.executeScript(`
document.querySelector('${selector}')['${property}'] = ${text};
`);
}
export function waitTime(time: number) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
export interface LifeCycleCount {
ionViewWillEnter: number;
ionViewDidEnter: number;
ionViewWillLeave: number;
ionViewDidLeave: number;
}
export function handleErrorMessages() {
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);
}
}
});
}
export async function testLifeCycle(selector: string, expected: LifeCycleCount) {
await waitTime(50);
const results = await Promise.all([
getText(`${selector} #ngOnInit`),
getText(`${selector} #ionViewWillEnter`),
getText(`${selector} #ionViewDidEnter`),
getText(`${selector} #ionViewWillLeave`),
getText(`${selector} #ionViewDidLeave`),
]);
expect(results[0]).toEqual('1');
expect(results[1]).toEqual(expected.ionViewWillEnter.toString());
expect(results[2]).toEqual(expected.ionViewDidEnter.toString());
expect(results[3]).toEqual(expected.ionViewWillLeave.toString());
expect(results[4]).toEqual(expected.ionViewDidLeave.toString());
}
export async function testStack(selector: string, expected: string[]) {
const children = await browser.executeScript(`
return Array.from(
document.querySelector('${selector}').children
).map(el => el.tagName.toLowerCase());
`);
expect(children).toEqual(expected);
}

View File

@@ -1,22 +0,0 @@
import { browser, element, by } from 'protractor';
import { handleErrorMessages, waitTime } from './utils';
describe('view-child', () => {
beforeEach(async () => {
await browser.get('/view-child');
await waitTime(30);
});
afterEach(() => {
return handleErrorMessages();
});
it('should get a reference to all children', async () => {
// button should be red
expect(await element(by.css('#color-button.ion-color-danger')).isPresent()).toBeTruthy();
// tabs should be found
expect(await element(by.css('#tabs-result')).getText()).toEqual('all found');
});
});

View File

@@ -0,0 +1,14 @@
describe('View Child', () => {
beforeEach(() => {
cy.visit('/view-child');
})
it('should get a reference to all children', () => {
// button should be red
cy.get('#color-button').should('have.class', 'ion-color-danger');
// tabs should be found
cy.get('#tabs-result').should('have.text', 'all found');
});
});

View File

@@ -1,18 +0,0 @@
import { browser, element, by } from 'protractor';
import { waitTime, handleErrorMessages } from './utils';
describe('virtual-scroll', () => {
afterEach(() => {
return handleErrorMessages();
});
beforeEach(async () => {
await browser.get('/virtual-scroll');
await waitTime(30);
});
it('should open virtual-scroll', () => {
const virtualElements = element.all(by.css('ion-virtual-scroll > *'));
expect(virtualElements.count()).toBeGreaterThan(0);
});
});

View File

@@ -0,0 +1,14 @@
describe('Virtual Scroll', () => {
beforeEach(() => {
cy.visit('/virtual-scroll');
cy.wait(30);
})
it('should open virtual-scroll', () => {
cy.document().then((doc) => {
const virtualElements = doc.querySelectorAll('ion-virtual-scroll > *');
expect(virtualElements.length).to.be.greaterThan(0);
});
});
});

View File

@@ -4,14 +4,17 @@
"strictMetadataEmit" : true
},
"extends": "../tsconfig.json",
"include": [
"src/**spec.ts",
"../cypress/support/index.d.ts"
],
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"cypress",
"node"
]
}
}
}

View File

@@ -1,38 +0,0 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../coverage'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
customLaunchers: {
ChromeHeadlessCI: {
base: 'ChromeHeadless',
flags: ['--no-sandbox']
}
},
singleRun: false,
restartOnFileChange: true
});
};

View File

File diff suppressed because it is too large Load Diff

View File

@@ -8,60 +8,53 @@
"sync:build": "sh scripts/build-ionic.sh",
"sync": "sh scripts/sync.sh",
"build": "npm run sync && ng build --prod --no-progress",
"pretest": "webdriver-manager update --versions.chrome 87.0.4280.20",
"test": "ng e2e --prod --webdriver-update=false",
"test.dev": "npm run sync && ng e2e",
"lint": "ng lint",
"postinstall": "npm run sync && ngcc",
"serve:ssr": "node dist/test-app/server/main.js",
"build:ssr": "ng build --prod && ng run test-app:server:production",
"dev:ssr": "ng run test-app:serve-ssr",
"prerender": "ng run test-app:prerender"
"prerender": "ng run test-app:prerender",
"cy.open": "cypress open",
"cy.run": "cypress run",
"test": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy.run\" --kill-others --success first",
"test.watch": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy.open\" --kill-others --success first"
},
"dependencies": {
"@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",
"@angular/animations": "^11.2.11",
"@angular/common": "^11.2.11",
"@angular/compiler": "^11.2.11",
"@angular/core": "^11.2.11",
"@angular/forms": "^11.2.11",
"@angular/platform-browser": "^11.2.11",
"@angular/platform-browser-dynamic": "^11.2.11",
"@angular/platform-server": "^11.2.11",
"@angular/router": "^11.2.11",
"@ionic/angular": "^5.3.1",
"@ionic/angular-server": "^5.3.1",
"@nguniversal/express-engine": "9.0.0-next.9",
"@nguniversal/express-engine": "^11.2.1",
"angular-in-memory-web-api": "^0.11.0",
"core-js": "^2.6.11",
"express": "^4.15.2",
"jasmine-marbles": "^0.6.0",
"rxjs": "^6.5.5",
"tslib": "^1.13.0",
"tslib": "^2.0.0",
"zone.js": "^0.10.3"
},
"devDependencies": {
"@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",
"@angular-devkit/build-angular": "^0.1102.10",
"@angular/cli": "^11.2.10",
"@angular/compiler-cli": "^11.2.11",
"@angular/language-service": "^11.2.11",
"@nguniversal/builders": "^11.2.1",
"@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",
"codelyzer": "^6.0.1",
"concurrently": "^6.0.0",
"cypress": "^6.7.1",
"ts-loader": "^6.2.2",
"ts-node": "^8.3.0",
"tslint": "^6.1.3",
"typescript": "^3.8.3",
"tslint": "~6.1.0",
"typescript": "^4.0.7",
"wait-on": "^5.2.1",
"webpack-cli": "^3.3.12"
}
}

View File

@@ -27,6 +27,7 @@ export class ModalComponent {
async open(TheModalComponent: any) {
const modal = await this.modalCtrl.create({
component: TheModalComponent,
animated: false,
componentProps: {
value: '123',
prop: '321'
@@ -40,7 +41,7 @@ export class ModalComponent {
modal.onDidDismiss().then(() => {
NgZone.assertInAngularZone();
if (!this.onWillDismiss) {
throw new Error('onWillDismiss should be emited first');
throw new Error('onWillDismiss should be emitted first');
}
this.onDidDismiss = true;
});

View File

@@ -1,20 +0,0 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

View File

@@ -6,7 +6,7 @@
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"module": "esnext",
"module": "es2020",
"target": "es2015",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,

View File

@@ -2,7 +2,7 @@
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "./out-tsc/app-server",
"module": "commonjs",
"target": "es2016",
"types": [
"node"
]

View File

@@ -3,7 +3,6 @@
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine",
"node"
]
},

View File

@@ -2,16 +2,37 @@
"extends": "tslint:recommended",
"rulesDirectory": ["codelyzer"],
"rules": {
"align": {
"options": [
"parameters",
"statements"
]
},
"array-type": false,
"arrow-parens": false,
"arrow-return-shorthand": true,
"deprecation": {
"severity": "warn"
},
"import-blacklist": [true, "rxjs/Rx"],
"import-blacklist": [
true,
"rxjs/Rx"
],
"curly": true,
"interface-name": false,
"max-classes-per-file": false,
"max-line-length": [true, 140],
"max-line-length": [
true,
140
],
"eofline": true,
"member-access": false,
"import-spacing": true,
"indent": {
"options": [
"spaces"
]
},
"member-ordering": [
true,
{
@@ -30,7 +51,6 @@
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-use-before-declare": true,
"no-var-requires": false,
"object-literal-key-quotes": [true, "as-needed"],
"object-literal-sort-keys": false,
@@ -46,9 +66,68 @@
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true,
"one-variable-per-declaration": false,
"component-class-suffix": [true, "Page", "Component"],
"component-class-suffix": [
true,
"Page",
"Component"
],
"semicolon": {
"options": [
"always"
]
},
"space-before-function-paren": {
"options": {
"anonymous": "never",
"asyncArrow": "always",
"constructor": "never",
"method": "never",
"named": "never"
}
},
"directive-class-suffix": true,
"typedef-whitespace": {
"options": [
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
},
{
"call-signature": "onespace",
"index-signature": "onespace",
"parameter": "onespace",
"property-declaration": "onespace",
"variable-declaration": "onespace"
}
]
},
"directive-selector": [true, "attribute", "app", "camelCase"],
"component-selector": [true, "element", "app", "page", "kebab-case"]
"component-selector": [
true,
"element",
"app",
"page",
"kebab-case"
],
"variable-name": {
"options": [
"ban-keywords",
"check-format",
"allow-pascal-case"
]
},
"whitespace": {
"options": [
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type",
"check-typecast"
]
}
}
}

3
commitlint.config.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional']
}

View File

@@ -254,7 +254,7 @@ rules:
- visibility
- z-index
property-blacklist:
property-disallowed-list:
- background-position
- right
- left

Some files were not shown because too many files have changed in this diff Show More