Compare commits

..

322 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Liam DeBeasi
cb2c9b63e8 5.5.4 2021-02-04 11:13:52 -05:00
Liam DeBeasi
ff0f1da9f1 fix(vue): ionChange events now propagate correctly (#22872)
resolves #22870
2021-02-04 11:00:46 -05:00
Mike Hartington
487349f02a fix(schematics): update ngAdd schematic (#22858)
* fix(schematics): update ngAdd schematic
Closes https://github.com/ionic-team/angular-toolkit/issues/415
Closes https://github.com/ionic-team/angular-toolkit/issues/419

* Update angular/src/schematics/utils/config.ts

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

* Update angular/src/schematics/add/index.ts

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

Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
2021-02-02 16:44:33 -05:00
Liam DeBeasi
b6b2d34fd4 fix(app): keyboard no longer hides when using contenteditable (#22857)
resolves #22856
2021-02-02 13:19:19 -05:00
Liam DeBeasi
1a5accc5f7 fix(select): class on component now indicates when select is open (#22846)
resolves #22801
2021-02-01 13:02:04 -05:00
Liam DeBeasi
f7d4c21b64 fix(): scroll assist no longer prevents first click event from firing (#22845)
resolves #21871
2021-02-01 13:00:33 -05:00
Adam Bradley
fa515eb79b refactor(react): look up tabs also by property key (#22823)
When IonTabBar is wrapped by a functional component or fragment, then IonTabs is unable to find it. This is a rare case, but adding the ability for a function component to manually state that is is an IonTabBar. Same for IonTabButtons.
2021-02-01 11:31:33 -06:00
Liam DeBeasi
697bcf3420 merge release-5.5.3
5.5.3
2021-01-28 12:38:23 -05:00
Liam DeBeasi
bc17e24a03 5.5.3 2021-01-28 12:17:55 -05:00
Liam DeBeasi
ab1fc8f231 fix(react): add improved method for not unmounting component until overlay is dismissed (#22813)
resolves #22761
2021-01-22 12:48:47 -05:00
Liam DeBeasi
2a3ce9a74e fix(vue): improve path matching with tabs (#22807)
resolves #22519
2021-01-22 10:19:38 -05:00
Liam DeBeasi
e2d8e5c4dc fix(refresher): correctly detect spinner when using native refresher (#22800)
resolves #22706
2021-01-20 17:18:36 -05:00
Simon
7ecae2e4cb fix(vue): output commonjs format for node environments (#22766) 2021-01-20 16:20:44 -05:00
Liam DeBeasi
14e8441706 fix(react): do not unmount overlay inner component until overlay is dismissed (#22763)
resolves #22761
2021-01-14 10:53:39 -05:00
Liam DeBeasi
e1d6627bf0 fix(vue): ensure v-model value is properly synced before ionChange event (#22749)
resolves #22610
2021-01-13 11:22:27 -05:00
Liam DeBeasi
348c50b7ea fix(title): only add large title transition when using collapsible header (#22762)
resolves #22760
2021-01-13 10:12:04 -05:00
Liam DeBeasi
9e9a372497 fix(react, vue): do not show back button when replacing to root page (#22750)
resolves #22528
2021-01-13 10:10:44 -05:00
Liam DeBeasi
64719f49f9 fix(vue): improve v-model binding sync between vue wrappers and web components (#22745)
resolves #22731
2021-01-08 12:06:45 -05:00
Liam DeBeasi
3d6ac1382e fix(vue): all ionic vue components can now use router link (#22743) 2021-01-07 15:52:06 -05:00
Liam DeBeasi
9a02ec8402 chore(): end holiday triage mode (#22741) 2021-01-07 12:20:08 -05:00
Liam DeBeasi
fbb777ab5a test(datetime): improve reliability of focus trap test (#22742) 2021-01-07 11:37:19 -05:00
Liam DeBeasi
67b0853b28 chore(): start holiday triage mode (#22700) 2020-12-18 17:32:02 -05:00
Liam DeBeasi
e3a05bfeb5 fix(vue): correctly determine leaving view when transitioning to a new instance of a previous page (#22655)
resolves #22654 resolves #22658
2020-12-16 16:45:28 -05:00
Liam DeBeasi
5c27dd8032 fix(vue): tab bar is now correctly hidden when keyboard is open (#22687) 2020-12-16 16:43:38 -05:00
Amith Mihiranga
b768181307 docs(input): add available autocapitalize property options (#21886)
Co-authored-by: Brandy Carney <brandy@ionic.io>
2020-12-16 09:53:00 -05:00
Ely Lucas
f891f66708 fix(react): improve view matching logic (#22569) 2020-12-15 11:03:08 -05:00
Ely Lucas
a01bdb8c8d fix(react): adding dynamic class to ion-page no longer hides component (#22666)
resolves #22631
2020-12-15 11:02:06 -05:00
Ken Sodemann
09a5ed6a0d docs(tab-button): use an href in vue sample (#22674) 2020-12-14 16:14:42 -05:00
Liam DeBeasi
39bbb99f75 chore(vue): import animation types from @ionic/vue instead of @ionic/core (#22677) 2020-12-14 14:39:41 -05:00
Óscar Carretero
11a59133d9 test(item): fix disabled test script path (#22660) 2020-12-10 17:00:32 -05:00
Liam DeBeasi
1ef112ef12 merge release-5.5.2
5.5.2
2020-12-09 16:03:47 -05:00
Liam DeBeasi
78740d0dfc 5.5.2 2020-12-09 15:38:27 -05:00
Liam DeBeasi
94518c9387 chore(react): relax peer dependency requirements (#22645)
resolves #22644
2020-12-08 16:17:16 -05:00
Ely Lucas
31f45cdcc9 fix(react): setting a ref should allow other props to be passed in, closes #22609 2020-12-08 13:45:24 -07:00
Liam DeBeasi
61cf0c534e fix(vue): adding non tab button elements inside ion-tab-bar no longer causes errors (#22643)
resolves #22642
2020-12-08 12:49:13 -05:00
Liam DeBeasi
8d5ed47a28 fix(refresher): clean up old css if calling refresh method before native refresher is setup (#22640)
resolves #22636
2020-12-08 10:16:29 -05:00
Liam DeBeasi
a94e2a87fb fix(vue): query strings are now correctly handled when navigating back (#22615)
resolves #22517
2020-12-07 15:17:31 -05:00
Liam DeBeasi
818e387fe8 fix(button): allow aria-label to be inherited to inner button (#22632)
resolves #22629
2020-12-07 12:31:05 -05:00
Augusto Amaral
ff39d40255 docs(vue): fix menu usage example (#22624) 2020-12-07 11:42:18 -05:00
Ely Lucas
91aaaab71a chore(react): adding prettier and formating files 2020-12-07 09:31:33 -07:00
Liam DeBeasi
01afdc42e5 fix(vue): pass in correct route to props function (#22605)
resolves #22602
2020-12-07 10:33:22 -05:00
Ely Lucas
36939e10ae fix(react): android hardware button should invoke browser back 2020-12-07 08:33:00 -07:00
Liam DeBeasi
5ed73cdf4d fix(refresher): refresher correctly detects native refresher when shown asynchronously (#22623)
resolves #22616
2020-12-03 14:58:12 -05:00
Augusto Amaral
0be79fe82b docs(vue): fix skeleton-text usage example (#22596) 2020-12-03 12:52:13 -05:00
Liam DeBeasi
216f51b12a fix(vue): correctly handle navigation failures (#22621)
resolves #22591
2020-12-03 12:44:16 -05:00
Liam DeBeasi
dc9faa6a0f fix(android): setting hardwareBackButton: false in config now disabled default webview behavior (#22555)
resolves #18237
2020-12-02 15:44:34 -05:00
Liam DeBeasi
4f4f31b65e fix(vue): correctly remove old view when replacing route (#22566)
resolves #22492
2020-11-30 11:00:14 -05:00
Liam DeBeasi
9d04c127e8 fix(vue): swipe back gesture is properly disabled when swipeBackEnabled config is false (#22568)
resolves #22567
2020-11-30 10:59:00 -05:00
Liam DeBeasi
181fc59ab7 chore(): add note on 5.5.1 upgrading (#22578) 2020-11-25 18:47:52 -05:00
Liam DeBeasi
53ec9cff5e merge release-5.5.1
5.5.1
2020-11-25 18:25:50 -05:00
Liam DeBeasi
d61456c46d 5.5.1 2020-11-25 17:17:52 -05:00
Brandy Carney
07868354aa fix(a11y): only preventDefault for the onClick event (#22573) 2020-11-25 16:56:51 -05:00
Ely Lucas
5275332e43 fix(react): eliminate use of deprecated findDOMNode, resolves #20972 2020-11-25 14:21:12 -07:00
Brandy Carney
ea52db66f0 fix(select): improvements for announcing placeholder and value on screenreaders (#22556)
- Hides select text from screen readers so it isn't announced twice (Android talkback needs this)
- Adds the placeholder text to be announced if there is no value
- Don't add a comma if there is no value/placeholder (NVDA speech viewer)
- Don't announce alert label twice
2020-11-25 15:47:14 -05:00
Liam DeBeasi
c45c8d5564 fix(checkbox): click events on ion-item now fire properly (#22561)
resolves #22557
2020-11-24 14:31:24 -05:00
Brandy Carney
afcc46e1cc fix(radio): properly announce radios on screen readers and resolve axe errors (#22507) 2020-11-24 11:43:59 -05:00
Liam DeBeasi
4e23aad3d9 fix(vue): testing a routerLink-capable component no longer warns of missing router dependency (#22532)
resolves #22506
2020-11-23 14:17:52 -05:00
Liam DeBeasi
a664ccbde9 chore(): fix @types/react to avoid 16.14.1 release (#22554) 2020-11-23 13:37:22 -05:00
Liam DeBeasi
8002114e72 fix(vue): onBeforeRouteLeave and onBeforeRouteUpdate hooks now fire properly (#22542)
resolves #22540
2020-11-23 10:22:03 -05:00
Brandy Carney
04b874e32a fix(select): fix a11y issues with axe and screen readers (#22494)
fixes #21552 fixes #21548
2020-11-20 17:18:51 -05:00
Yohann CINTRE
c727419350 docs(select): fix broken link to select-option (#22539) 2020-11-20 12:20:07 -05:00
Liam DeBeasi
e1e23bc1a2 docs(modal): include note on using ion-page when wrapping modal component (#22534) 2020-11-19 15:31:01 -05:00
Liam DeBeasi
cdc2fb652f fix(vue): tabs correctly fire lifecycle events (#22479)
resolves #22466
2020-11-19 15:30:32 -05:00
Liam DeBeasi
bb519b8724 chore(): update "needs reproduction" wording for clarity (#22520) 2020-11-19 09:46:58 -05:00
Liam DeBeasi
1956f98968 fix(router): navigation guards now fire when navigating to a page with params (#22521)
resolves #22516
2020-11-18 14:36:49 -05:00
Liam DeBeasi
3ed44993e1 merge release-5.5.0
5.5.0
2020-11-18 14:33:55 -05:00
Liam DeBeasi
f4ecc32c14 5.5.0 2020-11-18 13:02:47 -05:00
Liam DeBeasi
d5eb3a44e6 test(angular): fix e2e tests (#22522) 2020-11-18 12:25:30 -05:00
Liam DeBeasi
33768e1d0c docs(tabs): add correct vue examples (#22510) 2020-11-17 11:02:28 -05:00
Liam DeBeasi
ce4a381d4f chore(): re-add es5 check (#22504)
This reverts commit 0eb643d563.
2020-11-16 12:54:59 -05:00
Liam DeBeasi
2d878fc4f6 fix(backdrop): nvda no longer incorrectly announces backdrop (#22481)
resolves #22102
2020-11-16 12:15:33 -05:00
Takuma Kira
65bc99577c feat(segment): add swipeGesture property to allow for disabling of the swipe gesture (#22087)
resolves #22048
2020-11-13 12:38:23 -05:00
Liam DeBeasi
abad12fbdb fix(input): title attribute is automatically inherited (#22493)
resolves #22055
2020-11-13 12:15:33 -05:00
Liam DeBeasi
d77a9d57ec perf(ios): move content to stacking context while preserving position: fixed behavior (#22489)
resolves #22473
2020-11-12 16:02:12 -05:00
Brandy Carney
813611a61b fix(toggle): use a native input to fix a11y issues with axe and screen readers (#22477)
fixes #22011
references #21552
2020-11-12 15:29:05 -05:00
Liam DeBeasi
96d6012071 merge release-5.4.4
Release 5.4.4
2020-11-12 13:23:18 -05:00
Brandy Carney
7214a8401b fix(checkbox): use a native input to fix a11y issues with axe and screen readers (#22402)
fixes #21644
fixes #20517
fixes #17796
2020-11-12 11:25:33 -05:00
Liam DeBeasi
bf3f3bb3dc test(): disable treeshake test 2020-11-12 10:39:10 -05:00
Liam DeBeasi
3a6fcc7d8b 5.4.4 2020-11-12 09:51:48 -05:00
Liam DeBeasi
62dd16a5ee fix(build): add missing es5 output 2020-11-12 09:49:49 -05:00
Liam DeBeasi
0956f8bc55 fix(vue): correctly pass route props to components (#22476)
resolves #22472
2020-11-11 12:12:12 -05:00
Liam DeBeasi
a4a64530ff fix(refresher): ios native refresher now works in side menu (#22449) 2020-11-10 12:07:38 -05:00
Liam DeBeasi
e17c822bfb fix(vue): tab bar now works with slot="top" (#22461)
resolves #22456
2020-11-10 10:07:31 -05:00
Michael Tintiuc
f5b0299729 feat(vue): composition api lifecycle methods (#22241) 2020-11-10 09:14:24 -05:00
Daniele
1267945480 docs(checkbox): update example for vue 3 syntax (#22457) 2020-11-09 11:01:34 -05:00
Stian Øvrevåge
907cc7b159 docs(vue): fix label typo (#22451) 2020-11-09 09:57:38 -05:00
Liam DeBeasi
e76f79d054 feat(vue): vetur support (#22403) 2020-11-06 14:25:23 -05:00
Liam DeBeasi
f130fb2b17 merge release-5.4.3
Release 5.4.3
2020-11-06 12:53:17 -05:00
Liam DeBeasi
6b817f26b0 fix(refresher): refresher gesture now works in side menu (#22446)
resolves #20832
2020-11-06 12:16:45 -05:00
Liam DeBeasi
c356526520 5.4.3 2020-11-06 12:13:28 -05:00
Liam DeBeasi
caa3afa613 fix(): add missing vendor prefixes to css 2020-11-06 12:13:14 -05:00
Hans Krywalsky
0a0cbd8f2a feat(chip): add disabled property (#20658)
resolves #19510
2020-11-05 14:18:24 -05:00
Piotr Tomiak
639314ab21 feat(vue): web-types support (#22428)
resolves #19522
2020-11-05 13:54:31 -05:00
Liam DeBeasi
7512c90241 merge release-5.4.2
Release 5.4.2
2020-11-05 13:51:25 -05:00
682 changed files with 107495 additions and 44995 deletions

View File

@@ -1,30 +1,32 @@
version: 2.1
orbs:
cypress: cypress-io/cypress@1.27.0
aliases:
- &restore-cache
keys:
- dependency-cache-{{ checksum "package.json" }}-3
- dependency-cache-{{ checksum "package.json" }}-7
- &save-cache
key: dependency-cache-{{ checksum "package.json" }}-3
key: dependency-cache-{{ checksum "package.json" }}-7
paths:
- node_modules
- &restore-cache-core
keys:
- dependency-cache-{{ checksum "core/package.json" }}-3
- dependency-cache-{{ checksum "core/package.json" }}-7
- &save-cache-core
key: dependency-cache-{{ checksum "core/package.json" }}-3
key: dependency-cache-{{ checksum "core/package.json" }}-7
paths:
- core/node_modules
- &restore-cache-core-stencil
keys:
- stencil-cache-2
- stencil-cache-6
- &save-cache-core-stencil
key: stencil-cache-2
key: stencil-cache-6
paths:
- core/.stencil
- core/screenshot/images
@@ -64,7 +66,7 @@ jobs:
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
- node_modules
build-core:
<<: *defaults
@@ -85,7 +87,12 @@ jobs:
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
- core/node_modules
- core/dist
- core/components
- core/css
- core/hydrate
- core/loader
build-angular:
<<: *defaults
@@ -108,7 +115,8 @@ jobs:
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
- angular/node_modules
- angular/dist
build-angular-server:
<<: *defaults
@@ -125,7 +133,7 @@ jobs:
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
- packages/angular-server/dist
build-react:
<<: *defaults
@@ -148,7 +156,10 @@ jobs:
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
- packages/react/node_modules
- packages/react/dist
- packages/react/css
build-react-router:
<<: *defaults
steps:
@@ -176,7 +187,8 @@ jobs:
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
- packages/react-router/node_modules
- packages/react-router/dist
build-vue:
<<: *defaults
@@ -185,7 +197,7 @@ jobs:
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install --legacy-peer-deps
command: npm install
working_directory: /tmp/workspace/packages/vue
- run:
command: sudo npm link
@@ -199,7 +211,9 @@ jobs:
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
- packages/vue/node_modules
- packages/vue/dist
- packages/vue/css
build-vue-router:
<<: *defaults
@@ -208,13 +222,7 @@ jobs:
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install --legacy-peer-deps
working_directory: /tmp/workspace/packages/vue-router
- run:
command: sudo npm link
working_directory: /tmp/workspace/core
- run:
command: sudo npm link @ionic/core
command: npm install
working_directory: /tmp/workspace/packages/vue-router
- run:
command: sudo npm link
@@ -228,7 +236,7 @@ jobs:
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
- packages/vue-router/dist
test-core-clean-build:
<<: *defaults
@@ -258,7 +266,7 @@ jobs:
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run test.e2e --ci
command: npm run test.e2e -- --ci --no-build
working_directory: /tmp/workspace/core
test-core-spec:
@@ -268,7 +276,7 @@ jobs:
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run test.spec --ci
command: npm run test.spec -- --ci
working_directory: /tmp/workspace/core
test-core-treeshake:
@@ -278,7 +286,7 @@ jobs:
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run test.treeshake --ci
command: npm run test.treeshake -- --ci
working_directory: /tmp/workspace/core
test-core-screenshot:
@@ -289,7 +297,7 @@ jobs:
at: /tmp/workspace
- run:
name: Run Screenshot
command: npx stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci || true
command: npx stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci --no-build || true
working_directory: /tmp/workspace/core
test-core-screenshot-master:
@@ -300,7 +308,7 @@ jobs:
at: /tmp/workspace
- run:
name: Run Screenshot
command: npx stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci --update-screenshot || true
command: npx stencil test --e2e --screenshot --screenshot-connector=scripts/screenshot/ci.js --ci --update-screenshot --no-build || true
working_directory: /tmp/workspace/core
test-angular-lint:
@@ -391,6 +399,33 @@ jobs:
command: npm run test.spec
working_directory: /tmp/workspace/packages/react-router
install-react-test-app:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: CYPRESS_CACHE_FOLDER=/tmp/workspace/packages/react-router/test-app npm install
working_directory: /tmp/workspace/packages/react-router/test-app
- persist_to_workspace:
root: /tmp/workspace
paths:
- packages/react-router/test-app
test-react-e2e:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run sync
working_directory: /tmp/workspace/packages/react-router/test-app
- run:
command: CYPRESS_CACHE_FOLDER=/tmp/workspace/packages/react-router/test-app npm run e2e
working_directory: /tmp/workspace/packages/react-router/test-app
test-vue-router-spec:
<<: *defaults
steps:
@@ -423,9 +458,39 @@ jobs:
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
command: npm run test
working_directory: /tmp/workspace/angular/test/test-app
install-vue-test-app:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: CYPRESS_CACHE_FOLDER=/tmp/workspace/packages/vue/test-app npm install
working_directory: /tmp/workspace/packages/vue/test-app
- persist_to_workspace:
root: /tmp/workspace
paths:
- packages/vue/test-app
test-vue-spec-and-e2e:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm run sync
working_directory: /tmp/workspace/packages/vue/test-app
- run:
command: npm run test:unit
working_directory: /tmp/workspace/packages/vue/test-app
- run:
command: CYPRESS_CACHE_FOLDER=/tmp/workspace/packages/vue/test-app npm run test:e2e
working_directory: /tmp/workspace/packages/vue/test-app
workflows:
version: 2
build:
@@ -442,8 +507,11 @@ workflows:
requires: [puppeteer-dependencies, build-core]
- test-core-spec:
requires: [build-core]
- test-core-treeshake:
requires: [build-core]
# Adam requested we skip this test for now
# since it is failing on ES5 code which
# will be removed in Ionic Framework v6
#- test-core-treeshake:
# requires: [build-core]
- test-core-screenshot:
requires: [build-core]
filters:
@@ -471,16 +539,24 @@ workflows:
requires: [build-react]
- test-react-router-spec:
requires: [build-react-router]
- install-react-test-app:
requires: [build-core]
- test-react-e2e:
requires: [install-react-test-app, build-react, build-react-router]
- build-vue:
requires: [build-core]
- build-vue-router:
requires: [build-core, build-vue]
requires: [build-vue]
- test-vue-lint:
requires: [build-vue]
- test-vue-router-lint:
requires: [build-vue-router]
- test-vue-router-spec:
requires: [build-vue-router]
- install-vue-test-app:
requires: [build-core]
- test-vue-spec-and-e2e:
requires: [install-vue-test-app, build-vue, build-vue-router]
- test-angular-lint:
requires: [build-angular]
- test-angular-e2e:

View File

@@ -9,10 +9,14 @@
* [Ripple Effect](#ripple-effect)
* [Example Components](#example-components)
* [References](#references)
- [Accessibility](#accessibility)
* [Checkbox](#checkbox)
* [Switch](#switch)
- [Rendering Anchor or Button](#rendering-anchor-or-button)
* [Example Components](#example-components-1)
* [Component Structure](#component-structure-1)
- [Converting Scoped to Shadow](#converting-scoped-to-shadow)
- [RTL](#rtl)
## Button States
@@ -362,6 +366,265 @@ ion-ripple-effect {
- [iOS Buttons](https://developer.apple.com/design/human-interface-guidelines/ios/controls/buttons/)
## Accessibility
### Checkbox
#### Example Components
- [ion-checkbox](https://github.com/ionic-team/ionic/tree/master/core/src/components/checkbox)
#### VoiceOver
In order for VoiceOver to work properly with a checkbox component there must be a native `input` with `type="checkbox"`, and `aria-checked` and `role="checkbox"` **must** be on the host element. The `aria-hidden` attribute needs to be added if the checkbox is disabled, preventing iOS users from selecting it:
```tsx
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
<input
type="checkbox"
/>
...
</Host>
);
}
```
#### NVDA
It is required to have `aria-checked` on the native input for checked to read properly and `disabled` to prevent tabbing to the input:
```tsx
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
<input
type="checkbox"
aria-checked={`${checked}`}
disabled={disabled}
/>
...
</Host>
);
}
```
#### Labels
A helper function has been created to get the proper `aria-label` for the checkbox. This can be imported as `getAriaLabel` like the following:
```tsx
const { label, labelId, labelText } = getAriaLabel(el, inputId);
```
where `el` and `inputId` are the following:
```tsx
export class Checkbox implements ComponentInterface {
private inputId = `ion-cb-${checkboxIds++}`;
@Element() el!: HTMLElement;
...
}
```
This can then be added to the `Host` like the following:
```tsx
<Host
aria-labelledby={label ? labelId : null}
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
```
In addition to that, the checkbox input should have a label added:
```tsx
<Host
aria-labelledby={label ? labelId : null}
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
<label htmlFor={inputId}>
{labelText}
</label>
<input
type="checkbox"
aria-checked={`${checked}`}
disabled={disabled}
id={inputId}
/>
```
#### Hidden Input
A helper function to render a hidden input has been added, it can be added in the `render`:
```tsx
renderHiddenInput(true, el, name, (checked ? value : ''), disabled);
```
> This is required for the checkbox to work with forms.
#### Known Issues
When using VoiceOver on macOS, Chrome will announce the following when you are focused on a checkbox:
```
currently on a checkbox inside of a checkbox
```
This is a compromise we have to make in order for it to work with the other screen readers & Safari.
### Switch
#### Example Components
- [ion-toggle](https://github.com/ionic-team/ionic/tree/master/core/src/components/toggle)
#### Voiceover
In order for VoiceOver to work properly with a switch component there must be a native `input` with `type="checkbox"` and `role="switch"`, and `aria-checked` and `role="switch"` **must** be on the host element. The `aria-hidden` attribute needs to be added if the switch is disabled, preventing iOS users from selecting it:
```tsx
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
<input
type="checkbox"
role="switch"
/>
...
</Host>
);
}
```
#### NVDA
It is required to have `aria-checked` on the native input for checked to read properly and `disabled` to prevent tabbing to the input:
```tsx
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
<input
type="checkbox"
role="switch"
aria-checked={`${checked}`}
disabled={disabled}
/>
...
</Host>
);
}
```
#### Labels
A helper function has been created to get the proper `aria-label` for the switch. This can be imported as `getAriaLabel` like the following:
```tsx
const { label, labelId, labelText } = getAriaLabel(el, inputId);
```
where `el` and `inputId` are the following:
```tsx
export class Toggle implements ComponentInterface {
private inputId = `ion-tg-${toggleIds++}`;
@Element() el!: HTMLElement;
...
}
```
This can then be added to the `Host` like the following:
```tsx
<Host
aria-labelledby={label ? labelId : null}
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
```
In addition to that, the checkbox input should have a label added:
```tsx
<Host
aria-labelledby={label ? labelId : null}
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
<label htmlFor={inputId}>
{labelText}
</label>
<input
type="checkbox"
role="switch"
aria-checked={`${checked}`}
disabled={disabled}
id={inputId}
/>
```
#### Hidden Input
A helper function to render a hidden input has been added, it can be added in the `render`:
```tsx
renderHiddenInput(true, el, name, (checked ? value : ''), disabled);
```
> This is required for the switch to work with forms.
#### Known Issues
When using VoiceOver on macOS or iOS, Chrome will announce the switch as a checked or unchecked `checkbox`:
```
You are currently on a switch. To select or deselect this checkbox, press Control-Option-Space.
```
There is a WebKit bug open for this: https://bugs.webkit.org/show_bug.cgi?id=196354
## Rendering Anchor or Button
Certain components can render an `<a>` or a `<button>` depending on the presence of an `href` attribute.
@@ -441,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

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

14
.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
@@ -142,7 +150,7 @@ See the [steps for releasing](#releasing) below for detailed information on how
### 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 `master` 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.

View File

@@ -27,7 +27,10 @@ comment:
is added to issues that need a code reproduction.
Please provide a reproduction with the minimum amount of code required to reproduce the issue. Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.
Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.
If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.
For a guide on how to create a good reproduction, see our [Contributing Guide](https://ionicframework.com/docs/contributing/how-to-contribute#creating-a-good-code-reproduction).

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

@@ -63,8 +63,9 @@ async function main() {
function checkProductionRelease() {
const corePath = common.projectPath('core');
const hasEsm = fs.existsSync(path.join(corePath, 'dist', 'esm'));
const hasEsmEs5 = fs.existsSync(path.join(corePath, 'dist', 'esm-es5'));
const hasCjs = fs.existsSync(path.join(corePath, 'dist', 'cjs'));
if (!hasEsm || !hasCjs) {
if (!hasEsm || !hasEsmEs5 || !hasCjs) {
throw new Error('core build is not a production build');
}
}

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,432 @@
## [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)
### Bug Fixes
* **vue:** account for event name changes in vue 3.0.6+ ([#22980](https://github.com/ionic-team/ionic/issues/22980)) ([7dd2e6d](https://github.com/ionic-team/ionic/commit/7dd2e6d287b47cca758e1d4a71928dd3dc9ac24d)), closes [#22977](https://github.com/ionic-team/ionic/issues/22977)
## [5.5.4](https://github.com/ionic-team/ionic/compare/v5.5.3...v5.5.4) (2021-02-04)
### Bug Fixes
* **angular:** update ngAdd schematic ([#22858](https://github.com/ionic-team/ionic/issues/22858)) ([487349f](https://github.com/ionic-team/ionic/commit/487349f02a41344db2478735d27bf79f2a1c99b3))
* **app:** keyboard no longer hides when using contenteditable ([#22857](https://github.com/ionic-team/ionic/issues/22857)) ([b6b2d34](https://github.com/ionic-team/ionic/commit/b6b2d34fd446feb06cf0143946a014d19231a78e)), closes [#22856](https://github.com/ionic-team/ionic/issues/22856)
* **ios**: scroll assist no longer prevents first click event from firing ([#22845](https://github.com/ionic-team/ionic/issues/22845)) ([f7d4c21](https://github.com/ionic-team/ionic/commit/f7d4c21b64e27f9b655bc1ab2522d6357dc6010f)), closes [#21871](https://github.com/ionic-team/ionic/issues/21871)
* **select:** class on component now indicates when select is open ([#22846](https://github.com/ionic-team/ionic/issues/22846)) ([1a5accc](https://github.com/ionic-team/ionic/commit/1a5accc5f707f84063469c0bd3e5e153489f1e5d)), closes [#22801](https://github.com/ionic-team/ionic/issues/22801)
* **vue:** ionChange events now propagate correctly ([#22872](https://github.com/ionic-team/ionic/issues/22872)) ([ff0f1da](https://github.com/ionic-team/ionic/commit/ff0f1da9f11915b48c4258af7c48c4513785f3fc)), closes [#22870](https://github.com/ionic-team/ionic/issues/22870)
## [5.5.3](https://github.com/ionic-team/ionic/compare/v5.5.2...v5.5.3) (2021-01-28)
### Bug Fixes
* **react:** do not unmount overlay inner component until overlay is dismissed ([#22813](https://github.com/ionic-team/ionic/issues/22813)) ([ab1fc8f](https://github.com/ionic-team/ionic/commit/ab1fc8f2311fd252146942c7a947ebc96efd054f)), closes [#22761](https://github.com/ionic-team/ionic/issues/22761)
* **react:** adding dynamic class to ion-page no longer hides component ([#22666](https://github.com/ionic-team/ionic/issues/22666)) ([a01bdb8](https://github.com/ionic-team/ionic/commit/a01bdb8c8dfee760721eeb35a8b556954f3b5b13)), closes [#22631](https://github.com/ionic-team/ionic/issues/22631)
* **react:** improve view matching logic ([#22569](https://github.com/ionic-team/ionic/issues/22569)) ([f891f66](https://github.com/ionic-team/ionic/commit/f891f667082d2deb5f1b5f0f27af46e46ed1ca0f))
* **react, vue:** do not show back button when replacing to root page ([#22750](https://github.com/ionic-team/ionic/issues/22750)) ([9e9a372](https://github.com/ionic-team/ionic/commit/9e9a3724979e95f3df1a340be21d16d8664a013c)), closes [#22528](https://github.com/ionic-team/ionic/issues/22528)
* **refresher:** correctly detect spinner when using native refresher ([#22800](https://github.com/ionic-team/ionic/issues/22800)) ([e2d8e5c](https://github.com/ionic-team/ionic/commit/e2d8e5c4dcf893ddd8aaa556c1dd8fcaf52411c9)), closes [#22706](https://github.com/ionic-team/ionic/issues/22706)
* **title:** only add large title transition when using collapsible header ([#22762](https://github.com/ionic-team/ionic/issues/22762)) ([348c50b](https://github.com/ionic-team/ionic/commit/348c50b7ea5d4c74498c5d26e40c1c4fe923ee55)), closes [#22760](https://github.com/ionic-team/ionic/issues/22760)
* **vue:** all ionic vue components can now use router link ([#22743](https://github.com/ionic-team/ionic/issues/22743)) ([3d6ac13](https://github.com/ionic-team/ionic/commit/3d6ac1382e23663a3d010fd253d3c6017d3923e4))
* **vue:** correctly determine leaving view when transitioning to a new instance of a previous page ([#22655](https://github.com/ionic-team/ionic/issues/22655)) ([e3a05bf](https://github.com/ionic-team/ionic/commit/e3a05bfeb55d8eaa38aa08a37859aa4df6ffa2d4)), closes [#22654](https://github.com/ionic-team/ionic/issues/22654) [#22658](https://github.com/ionic-team/ionic/issues/22658)
* **vue:** ensure v-model value is properly synced before ionChange event ([#22749](https://github.com/ionic-team/ionic/issues/22749)) ([e1d6627](https://github.com/ionic-team/ionic/commit/e1d6627bf0ef1f47f980db1573c6b2a3d16d7677)), closes [#22610](https://github.com/ionic-team/ionic/issues/22610)
* **vue:** improve path matching with tabs, deprecated adding additional pages as children of tabs without a router outlet ([#22807](https://github.com/ionic-team/ionic/issues/22807)) ([2a3ce9a](https://github.com/ionic-team/ionic/commit/2a3ce9a74e85111a2f1f470b9d8bfe2cda793ca5)), closes [#22519](https://github.com/ionic-team/ionic/issues/22519)
* **vue:** improve v-model binding sync between vue wrappers and web components ([#22745](https://github.com/ionic-team/ionic/issues/22745)) ([64719f4](https://github.com/ionic-team/ionic/commit/64719f49f979c0296a01827d3c02599a48ba93a6)), closes [#22731](https://github.com/ionic-team/ionic/issues/22731)
* **vue:** output commonjs format for node environments ([#22766](https://github.com/ionic-team/ionic/issues/22766)) ([7ecae2e](https://github.com/ionic-team/ionic/commit/7ecae2e4cb5d0eebc6041a8a7a5acc156132c2e1))
* **vue:** tab bar is now correctly hidden when keyboard is open ([#22687](https://github.com/ionic-team/ionic/issues/22687)) ([5c27dd8](https://github.com/ionic-team/ionic/commit/5c27dd8032d32ebb57c31e1f6c112dc513344b93))
## [5.5.2](https://github.com/ionic-team/ionic/compare/v5.5.1...v5.5.2) (2020-12-09)
### Bug Fixes
* **android:** setting hardwareBackButton: false in config now disables default webview behavior ([#22555](https://github.com/ionic-team/ionic/issues/22555)) ([dc9faa6](https://github.com/ionic-team/ionic/commit/dc9faa6a0fbebb64c83c107c79cfd486cc0c096a)), closes [#18237](https://github.com/ionic-team/ionic/issues/18237)
* **button:** allow aria-label to be inherited on inner button ([#22632](https://github.com/ionic-team/ionic/issues/22632)) ([818e387](https://github.com/ionic-team/ionic/commit/818e387fe81ac7026fb374d8865116dadd433c87)), closes [#22629](https://github.com/ionic-team/ionic/issues/22629)
* **react:** hardware back button now navigates correctly ([36939e1](https://github.com/ionic-team/ionic/commit/36939e10ae0b8ac9a9275ee06d8e0d345de7c64f))
* **react:** setting a ref now allows other props to be passed in ([31f45cd](https://github.com/ionic-team/ionic/commit/31f45cdcc953b08749d9db08321fa5ec6cbe2532)), closes [#22609](https://github.com/ionic-team/ionic/issues/22609)
* **refresher:** clean up old css if calling refresh method before native refresher is setup ([#22640](https://github.com/ionic-team/ionic/issues/22640)) ([8d5ed47](https://github.com/ionic-team/ionic/commit/8d5ed47a282f92a60a2c4126a673cc2a5733067e)), closes [#22636](https://github.com/ionic-team/ionic/issues/22636)
* **refresher:** refresher correctly detects native refresher when shown asynchronously ([#22623](https://github.com/ionic-team/ionic/issues/22623)) ([5ed73cd](https://github.com/ionic-team/ionic/commit/5ed73cdf4d63eeee25ef28d9676fcaa4f8e07b47)), closes [#22616](https://github.com/ionic-team/ionic/issues/22616)
* **vue:** adding non tab button elements inside ion-tab-bar no longer causes errors ([#22643](https://github.com/ionic-team/ionic/issues/22643)) ([61cf0c5](https://github.com/ionic-team/ionic/commit/61cf0c534e45ce09410be6bfb50bdc27b657d1bc)), closes [#22642](https://github.com/ionic-team/ionic/issues/22642)
* **vue:** correctly handle navigation failures ([#22621](https://github.com/ionic-team/ionic/issues/22621)) ([216f51b](https://github.com/ionic-team/ionic/commit/216f51b12a8c4ae7b410f47ce3d350ea513b68a1)), closes [#22591](https://github.com/ionic-team/ionic/issues/22591)
* **vue:** correctly remove old view when replacing route ([#22566](https://github.com/ionic-team/ionic/issues/22566)) ([4f4f31b](https://github.com/ionic-team/ionic/commit/4f4f31b65e48294c3130ff24ae00b1a2aa1f9d31)), closes [#22492](https://github.com/ionic-team/ionic/issues/22492)
* **vue:** pass in correct route to props function ([#22605](https://github.com/ionic-team/ionic/issues/22605)) ([01afdc4](https://github.com/ionic-team/ionic/commit/01afdc42e5b1598d4d15cb51761bbb3eb5d13893)), closes [#22602](https://github.com/ionic-team/ionic/issues/22602)
* **vue:** query strings are now correctly handled when navigating back ([#22615](https://github.com/ionic-team/ionic/issues/22615)) ([a94e2a8](https://github.com/ionic-team/ionic/commit/a94e2a87fb759e7b7daed2d0304c1199dbc7afd1)), closes [#22517](https://github.com/ionic-team/ionic/issues/22517)
* **vue:** swipe back gesture is properly disabled when swipeBackEnabled config is false ([#22568](https://github.com/ionic-team/ionic/issues/22568)) ([9d04c12](https://github.com/ionic-team/ionic/commit/9d04c127e817676983940b034a4c7efc92fdfbc6)), closes [#22567](https://github.com/ionic-team/ionic/issues/22567)
### For Ionic Vue Developers
Vue Router 4 has been released! Be sure to update from the release candidate to the latest stable version of Vue Router.
For more information on the changes in Vue Router 4, see https://github.com/vuejs/vue-router-next/releases/tag/v4.0.0.
```
npm install vue-router@4
```
## [5.5.1](https://github.com/ionic-team/ionic/compare/v5.5.0...v5.5.1) (2020-11-25)
### Bug Fixes
* **checkbox:** click handler now fires properly ([#22573](https://github.com/ionic-team/ionic/issues/22573)) ([0786835](https://github.com/ionic-team/ionic/commit/07868354aaf88deebf7472a5bf0f34d7c823de17)), closes [#22557](https://github.com/ionic-team/ionic/issues/22557)
* **radio:** properly announce radios on screen readers and resolve axe errors ([#22507](https://github.com/ionic-team/ionic/issues/22507)) ([afcc46e](https://github.com/ionic-team/ionic/commit/afcc46e1cc4d7f6e9d1a50f8b367da4b1d0c3143))
* **react:** eliminate use of deprecated `findDOMNode`, resolves [#20972](https://github.com/ionic-team/ionic/issues/20972) ([5275332](https://github.com/ionic-team/ionic/commit/5275332e43694f3ee8738a1726c0d202b16c3052))
* **router:** navigation guards now fire when navigating to a page with params ([#22521](https://github.com/ionic-team/ionic/issues/22521)) ([1956f98](https://github.com/ionic-team/ionic/commit/1956f9896883dc4687488e5418e50ce0f6cbe6c9)), closes [#22516](https://github.com/ionic-team/ionic/issues/22516)
* **select:** fix a11y issues with axe and screen readers ([#22494](https://github.com/ionic-team/ionic/issues/22494)) ([04b874e](https://github.com/ionic-team/ionic/commit/04b874e32a65588ca79eda9399ab7e9d86a3cb77)), closes [#21552](https://github.com/ionic-team/ionic/issues/21552) [#21548](https://github.com/ionic-team/ionic/issues/21548)
* **select:** improvements for announcing placeholder and value on screenreaders ([#22556](https://github.com/ionic-team/ionic/issues/22556)) ([ea52db6](https://github.com/ionic-team/ionic/commit/ea52db66f05a185fed6b2e849734a7ffa1c6c6ea))
* **vue:** onBeforeRouteLeave and onBeforeRouteUpdate hooks now fire properly ([#22542](https://github.com/ionic-team/ionic/issues/22542)) ([8002114](https://github.com/ionic-team/ionic/commit/8002114e720361e60d7a7fe2d15ab88b49a72e1b)), closes [#22540](https://github.com/ionic-team/ionic/issues/22540)
* **vue:** tabs now correctly fire lifecycle events ([#22479](https://github.com/ionic-team/ionic/issues/22479)) ([cdc2fb6](https://github.com/ionic-team/ionic/commit/cdc2fb652fe5aa149eaa751a77fb506ac1f64195)), closes [#22466](https://github.com/ionic-team/ionic/issues/22466)
* **vue:** unit testing a routerLink-capable component no longer warns of missing router dependency ([#22532](https://github.com/ionic-team/ionic/issues/22532)) ([4e23aad](https://github.com/ionic-team/ionic/commit/4e23aad3d911188e4a2706545463a81332c00ce9)), closes [#22506](https://github.com/ionic-team/ionic/issues/22506)
### For Ionic Vue Developers
When updating to Ionic Vue v5.5.1 make sure you are on the latest version of `vue-router@next` to take advantage of the bug fixes in this release:
```
npm install vue-router@next
```
# [5.5.0 Chlorine](https://github.com/ionic-team/ionic/compare/v5.4.4...v5.5.0) (2020-11-18)
### Bug Fixes
* **backdrop:** nvda no longer incorrectly announces backdrop ([#22481](https://github.com/ionic-team/ionic/issues/22481)) ([2d878fc](https://github.com/ionic-team/ionic/commit/2d878fc4f6c7a710dbfb722e188e3e402e1672f9)), closes [#22102](https://github.com/ionic-team/ionic/issues/22102)
* **checkbox:** use a native input to fix a11y issues with axe and screen readers ([#22402](https://github.com/ionic-team/ionic/issues/22402)) ([7214a84](https://github.com/ionic-team/ionic/commit/7214a8401b709e1353155304cf6e9f97b2b4d294)), closes [#21644](https://github.com/ionic-team/ionic/issues/21644) [#20517](https://github.com/ionic-team/ionic/issues/20517) [#17796](https://github.com/ionic-team/ionic/issues/17796)
* **input:** title attribute is now automatically inherited ([#22493](https://github.com/ionic-team/ionic/issues/22493)) ([abad12f](https://github.com/ionic-team/ionic/commit/abad12fbdb1378066282fe8e9b7761747951b685)), closes [#22055](https://github.com/ionic-team/ionic/issues/22055)
* **refresher:** ios native refresher now works in side menu ([#22449](https://github.com/ionic-team/ionic/issues/22449)) ([a4a6453](https://github.com/ionic-team/ionic/commit/a4a64530ff083b83187b293dfdacb0fa45ad9f51))
* **refresher:** md native refresher now works in side menu ([#22446](https://github.com/ionic-team/ionic/issues/22446)) ([6b817f2](https://github.com/ionic-team/ionic/commit/6b817f26b08d01d8367d16308db775b6192e7628)), closes [#20832](https://github.com/ionic-team/ionic/issues/20832)
* **toggle:** use a native input to fix a11y issues with axe and screen readers ([#22477](https://github.com/ionic-team/ionic/issues/22477)) ([813611a](https://github.com/ionic-team/ionic/commit/813611a61b664c9827760ccaa889d0e2fcae7d94)), closes [#22011](https://github.com/ionic-team/ionic/issues/22011) [#21552](https://github.com/ionic-team/ionic/issues/21552)
* **vue:** correctly pass route props to components ([#22476](https://github.com/ionic-team/ionic/issues/22476)) ([0956f8b](https://github.com/ionic-team/ionic/commit/0956f8bc5588836996c8c74f98166c347414a312)), closes [#22472](https://github.com/ionic-team/ionic/issues/22472)
* **vue:** tab bar now works with slot="top" ([#22461](https://github.com/ionic-team/ionic/issues/22461)) ([e17c822](https://github.com/ionic-team/ionic/commit/e17c822bfbc2a876226738b77a4c95c02e0b5953)), closes [#22456](https://github.com/ionic-team/ionic/issues/22456)
### Features
* **chip:** add disabled property ([#20658](https://github.com/ionic-team/ionic/issues/20658)) ([0a0cbd8](https://github.com/ionic-team/ionic/commit/0a0cbd8f2a505ad2b3d8afb60cb1e940ced52e0d)), closes [#19510](https://github.com/ionic-team/ionic/issues/19510)
* **segment:** add swipeGesture property to allow for disabling of the swipe gesture ([#22087](https://github.com/ionic-team/ionic/issues/22087)) ([65bc995](https://github.com/ionic-team/ionic/commit/65bc99577c44cce653dafd9937c4d8f9c45fff61)), closes [#22048](https://github.com/ionic-team/ionic/issues/22048)
* **vue:** composition api lifecycle methods ([#22241](https://github.com/ionic-team/ionic/issues/22241)) ([f5b0299](https://github.com/ionic-team/ionic/commit/f5b0299729c2c639e432612e62fb7eaa189ca969))
* **vue:** vetur support ([#22403](https://github.com/ionic-team/ionic/issues/22403)) ([e76f79d](https://github.com/ionic-team/ionic/commit/e76f79d0548c97edd193808f5e0a19889cffae5b))
* **vue:** web-types support ([#22428](https://github.com/ionic-team/ionic/issues/22428)) ([639314a](https://github.com/ionic-team/ionic/commit/639314ab218b65a9a2de6040417b0e1b363e47ef)), closes [#19522](https://github.com/ionic-team/ionic/issues/19522)
### Performance Improvements
* **ios:** move content to stacking context while preserving position: fixed behavior ([#22489](https://github.com/ionic-team/ionic/issues/22489)) ([d77a9d5](https://github.com/ionic-team/ionic/commit/d77a9d57ec02c69df43ec2a286eea674a85cae36)), closes [#22473](https://github.com/ionic-team/ionic/issues/22473)
## [5.4.4](https://github.com/ionic-team/ionic/compare/v5.4.3...v5.4.4) (2020-11-12)
### Bug Fixes
* **build:** add missing es5 output ([228d349](https://github.com/ionic-team/ionic/commit/228d349c6e29b62cbfee5d5502883682cfa5032f))
## [5.4.3](https://github.com/ionic-team/ionic/compare/v5.4.2...v5.4.3) (2020-11-06)
### Bug Fixes
* **all** add missing vendor prefixes to css ([0989ea5](https://github.com/ionic-team/ionic/commit/0989ea5ac897f528e8fce5434861ca080b9b4a56))
## [5.4.2](https://github.com/ionic-team/ionic/compare/v5.4.1...v5.4.2) (2020-11-05)
@@ -3619,4 +4048,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

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/angular",
"version": "5.4.2",
"version": "5.8.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular",
"version": "5.4.2",
"version": "5.8.3",
"license": "MIT",
"dependencies": {
"@ionic/core": "file:../core",
"@ionic/core": "5.8.2",
"tslib": "^1.9.3"
},
"devDependencies": {
@@ -42,43 +42,6 @@
"zone.js": ">=0.8.26"
}
},
"../core": {
"version": "5.4.1",
"license": "MIT",
"dependencies": {
"ionicons": "^5.1.2",
"tslib": "^1.10.0"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/core": "2.1.2",
"@stencil/sass": "1.3.2",
"@stencil/vue-output-target": "0.1.8",
"@types/jest": "^26.0.10",
"@types/node": "^14.6.0",
"@types/puppeteer": "3.0.1",
"@types/swiper": "5.4.0",
"aws-sdk": "^2.738.0",
"clean-css-cli": "^4.1.11",
"domino": "^2.1.6",
"fs-extra": "^9.0.1",
"jest": "^26.4.1",
"jest-cli": "^26.4.1",
"np": "^6.4.0",
"pixelmatch": "4.0.2",
"puppeteer": "^5.2.1",
"rollup": "^2.26.4",
"sass": "^1.26.10",
"stylelint": "^13.6.1",
"stylelint-order": "^4.1.0",
"swiper": "5.4.1",
"tslint": "^6.1.3",
"tslint-ionic-rules": "0.0.21",
"tslint-react": "^5.0.0",
"typescript": "^4.0.5"
}
},
"node_modules/@angular-devkit/core": {
"version": "8.3.17",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.17.tgz",
@@ -241,8 +204,19 @@
}
},
"node_modules/@ionic/core": {
"resolved": "../core",
"link": true
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.8.2.tgz",
"integrity": "sha512-BWIh6hyhq+tzVvebPMfRa+IhTV5/yXh4wO3a0U3Qo4PL4KDzWyBJfoiPi6bOEc+BAlFnCtOooTTXTumgXXOojg==",
"dependencies": {
"@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",
@@ -322,6 +296,18 @@
"node": ">=6"
}
},
"node_modules/@stencil/core": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.6.0.tgz",
"integrity": "sha512-QsxWayZyusnqSZrlCl81R71rA3KqFjVVQSH4E0rGN15F1GdQaFonKlHLyCOLKLig1zzC+DQkLLiUuocexuvdeQ==",
"bin": {
"stencil": "bin/stencil"
},
"engines": {
"node": ">=12.10.0",
"npm": ">=6.0.0"
}
},
"node_modules/@szmarczak/http-timer": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
@@ -945,7 +931,6 @@
"anymatch": "^2.0.0",
"async-each": "^1.0.1",
"braces": "^2.3.2",
"fsevents": "^1.2.7",
"glob-parent": "^3.1.0",
"inherits": "^2.0.3",
"is-binary-path": "^1.0.0",
@@ -2047,6 +2032,14 @@
"node": ">=4"
}
},
"node_modules/ionicons": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
"dependencies": {
"@stencil/core": "^2.5.0"
}
},
"node_modules/is-accessor-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
@@ -2429,13 +2422,7 @@
"integrity": "sha512-+1V2PCMFkL+OIj2/HrtrvZw0BC0sYLMICJfbQjuj/K8CEnlrFX6R5cKKgzzttsZDHyxQNL1jqMREjKN3ja/E3Q==",
"dev": true,
"dependencies": {
"errno": "^0.1.1",
"graceful-fs": "^4.1.2",
"image-size": "~0.5.0",
"make-dir": "^2.1.0",
"mime": "^1.4.1",
"native-request": "^1.0.5",
"source-map": "~0.6.0",
"tslib": "^1.10.0"
},
"bin": {
@@ -2818,7 +2805,6 @@
"dependencies": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
@@ -2959,9 +2945,6 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.7.5.tgz",
"integrity": "sha512-xQSM8uzhgtF6tTnTVEvOQThrcG3LPUP3T/4l4EukzDp0kbTY1QRDuXjiwtYzs9odKj9Bj/PccRG6viFfS7DmCQ==",
"dev": true,
"dependencies": {
"fsevents": "~2.1.2"
},
"bin": {
"rollup": "dist/bin/rollup"
},
@@ -5173,37 +5156,20 @@
}
},
"@ionic/core": {
"version": "file:../core",
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.8.2.tgz",
"integrity": "sha512-BWIh6hyhq+tzVvebPMfRa+IhTV5/yXh4wO3a0U3Qo4PL4KDzWyBJfoiPi6bOEc+BAlFnCtOooTTXTumgXXOojg==",
"requires": {
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/core": "2.1.2",
"@stencil/sass": "1.3.2",
"@stencil/vue-output-target": "0.1.8",
"@types/jest": "^26.0.10",
"@types/node": "^14.6.0",
"@types/puppeteer": "3.0.1",
"@types/swiper": "5.4.0",
"aws-sdk": "^2.738.0",
"clean-css-cli": "^4.1.11",
"domino": "^2.1.6",
"fs-extra": "^9.0.1",
"ionicons": "^5.1.2",
"jest": "^26.4.1",
"jest-cli": "^26.4.1",
"np": "^6.4.0",
"pixelmatch": "4.0.2",
"puppeteer": "^5.2.1",
"rollup": "^2.26.4",
"sass": "^1.26.10",
"stylelint": "^13.6.1",
"stylelint-order": "^4.1.0",
"swiper": "5.4.1",
"tslib": "^1.10.0",
"tslint": "^6.1.3",
"tslint-ionic-rules": "0.0.21",
"tslint-react": "^5.0.0",
"typescript": "^4.0.5"
"@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": {
@@ -5276,6 +5242,11 @@
"integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
"dev": true
},
"@stencil/core": {
"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",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
@@ -6690,6 +6661,14 @@
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
"dev": true
},
"ionicons": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
"requires": {
"@stencil/core": "^2.5.0"
}
},
"is-accessor-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "5.4.2",
"version": "5.8.3",
"description": "Angular specific wrappers for @ionic/core",
"keywords": [
"ionic",
@@ -42,7 +42,7 @@
"validate": "npm i && npm run lint && npm run test && npm run build"
},
"dependencies": {
"@ionic/core": "5.4.2",
"@ionic/core": "5.8.3",
"tslib": "^1.9.3"
},
"peerDependencies": {

View File

@@ -1,26 +1,20 @@
import { NgZone } from '@angular/core';
import { initialize } 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 = {
initialize({
...config,
_zoneGate: (h: any) => zone.run(h)
};
});
const aelFn = '__zone_symbol__addEventListener' in (doc.body as any)
? '__zone_symbol__addEventListener'

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,6 +298,7 @@ export class StackController {
this.runningTask = undefined;
}
const promise = this.runningTask = task();
promise.finally(() => this.runningTask = undefined);
return promise;
}
}

View File

@@ -156,8 +156,8 @@ export class IonCheckbox {
}
export declare interface IonChip extends Components.IonChip {
}
@ProxyCmp({ inputs: ["color", "mode", "outline"] })
@Component({ selector: "ion-chip", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["color", "mode", "outline"] })
@ProxyCmp({ inputs: ["color", "disabled", "mode", "outline"] })
@Component({ selector: "ion-chip", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["color", "disabled", "mode", "outline"] })
export class IonChip {
protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
@@ -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>;
@@ -661,8 +661,8 @@ export class IonSearchbar {
}
export declare interface IonSegment extends Components.IonSegment {
}
@ProxyCmp({ inputs: ["color", "disabled", "mode", "scrollable", "value"] })
@Component({ selector: "ion-segment", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["color", "disabled", "mode", "scrollable", "value"] })
@ProxyCmp({ inputs: ["color", "disabled", "mode", "scrollable", "swipeGesture", "value"] })
@Component({ selector: "ion-segment", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["color", "disabled", "mode", "scrollable", "swipeGesture", "value"] })
export class IonSegment {
ionChange!: EventEmitter<CustomEvent>;
protected el: HTMLElement;

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 } 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

@@ -40,20 +40,23 @@ function addIonicAngularModuleToAppModule(projectSourceRoot: Path): Rule {
function addIonicStyles(projectName: string, projectSourceRoot: Path): Rule {
return (host: Tree) => {
const ionicStyles = [
'node_modules/@ionic/angular/css/core.css',
'node_modules/@ionic/angular/css/normalize.css',
'node_modules/@ionic/angular/css/structure.css',
'node_modules/@ionic/angular/css/typography.css',
'node_modules/@ionic/angular/css/core.css',
'node_modules/@ionic/angular/css/display.css',
'node_modules/@ionic/angular/css/padding.css',
'node_modules/@ionic/angular/css/float-elements.css',
'node_modules/@ionic/angular/css/text-alignment.css',
'node_modules/@ionic/angular/css/text-transformation.css',
'node_modules/@ionic/angular/css/flex-utils.css',
`${projectSourceRoot}/theme/variables.css`
].forEach(entry => {
]
ionicStyles.forEach(entry => {
addStyle(host, projectName, entry);
});
return host;
return host;
};
}
@@ -64,7 +67,8 @@ function addIonicons(projectName: string): Rule {
input: 'node_modules/ionicons/dist/ionicons/svg',
output: './svg'
};
addAsset(host, projectName, ioniconsGlob);
addAsset(host, projectName, 'build', ioniconsGlob);
addAsset(host, projectName, 'test', ioniconsGlob);
return host;
};
}

View File

@@ -62,10 +62,10 @@ export function addStyle(host: Tree, projectName: string, stylePath: string) {
writeConfig(host, config);
}
export function addAsset(host: Tree, projectName: string, asset: string | {glob: string; input: string; output: string}) {
export function addAsset(host: Tree, projectName: string, architect: string, asset: string | {glob: string; input: string; output: string}) {
const config = readConfig(host);
const appConfig = getAngularAppConfig(config, projectName);
appConfig.architect.build.options.assets.push(asset);
appConfig.architect[architect].options.assets.push(asset);
writeConfig(host, config);
}

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,6 +12,10 @@
// 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

@@ -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 85.0.4183.87",
"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

View File

@@ -40,9 +40,27 @@ The `@ionic/core` package can by used in simple HTML, or by vanilla JavaScript w
* [@ionic/angular](https://www.npmjs.com/package/@ionic/angular)
## Custom Elements Build (Experimental)
In addition to the default, self lazy-loading components built by Stencil, this package also comes with each component exported as a stand-alone custom element within `@ionic/core/components`. Each component extends `HTMLElement`, and does not lazy-load itself. Instead, this package is useful for projects already using a bundler such as Webpack or Rollup. While all components are available to be imported, the custom elements build also ensures bundlers only import what's used, and tree-shakes any unused components.
Below is an example of importing `ion-toggle`, and initializing Ionic so it's able to correctly load the "mode", such as Material Design or iOS. Additionally, the `initialize({...})` function can receive the Ionic config.
```typescript
import { IonBadge } from "@ionic/core/components/ion-badge";
import { initialize } from "@ionic/core/components";
initialize();
customElements.define("ion-badge", IonBadge);
```
Notice how `IonBadge` is imported from `@ionic/core/components/ion-badge` rather than just `@ionic/core/components`. Additionally, the `initialize` function is imported from `@ionic/core/components` rather than `@ionic/core`. All of this helps to ensure bundlers do not pull in more code than is needed.
## How to contribute
[Check out the CONTRIBUTE guide](CONTRIBUTING.md)
[Check out the CONTRIBUTE guide](/.github/CONTRIBUTING.md)
## Related

View File

@@ -6,6 +6,7 @@ ion-action-sheet,prop,buttons,(string | ActionSheetButton)[],[],false,false
ion-action-sheet,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-action-sheet,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-action-sheet,prop,header,string | undefined,undefined,false,false
ion-action-sheet,prop,htmlAttributes,ActionSheetAttributes | undefined,undefined,false,false
ion-action-sheet,prop,keyboardClose,boolean,true,false,false
ion-action-sheet,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-action-sheet,prop,mode,"ios" | "md",undefined,false,false
@@ -50,6 +51,7 @@ ion-alert,prop,buttons,(string | AlertButton)[],[],false,false
ion-alert,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-alert,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-alert,prop,header,string | undefined,undefined,false,false
ion-alert,prop,htmlAttributes,AlertAttributes | undefined,undefined,false,false
ion-alert,prop,inputs,AlertInput[],[],false,false
ion-alert,prop,keyboardClose,boolean,true,false,false
ion-alert,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
@@ -80,7 +82,7 @@ ion-avatar,shadow
ion-avatar,css-prop,--border-radius
ion-back-button,shadow
ion-back-button,prop,color,string | undefined,undefined,false,false
ion-back-button,prop,color,string | undefined,undefined,false,true
ion-back-button,prop,defaultHref,string | undefined,undefined,false,false
ion-back-button,prop,disabled,boolean,false,false,true
ion-back-button,prop,icon,null | string | undefined,undefined,false,false
@@ -131,7 +133,7 @@ ion-backdrop,prop,visible,boolean,true,false,false
ion-backdrop,event,ionBackdropTap,void,true
ion-badge,shadow
ion-badge,prop,color,string | undefined,undefined,false,false
ion-badge,prop,color,string | undefined,undefined,false,true
ion-badge,prop,mode,"ios" | "md",undefined,false,false
ion-badge,css-prop,--background
ion-badge,css-prop,--color
@@ -142,7 +144,7 @@ ion-badge,css-prop,--padding-top
ion-button,shadow
ion-button,prop,buttonType,string,'button',false,false
ion-button,prop,color,string | undefined,undefined,false,false
ion-button,prop,color,string | undefined,undefined,false,true
ion-button,prop,disabled,boolean,false,false,true
ion-button,prop,download,string | undefined,undefined,false,false
ion-button,prop,expand,"block" | "full" | undefined,undefined,false,true
@@ -189,7 +191,7 @@ ion-buttons,prop,collapse,boolean,false,false,false
ion-card,shadow
ion-card,prop,button,boolean,false,false,false
ion-card,prop,color,string | undefined,undefined,false,false
ion-card,prop,color,string | undefined,undefined,false,true
ion-card,prop,disabled,boolean,false,false,false
ion-card,prop,download,string | undefined,undefined,false,false
ion-card,prop,href,string | undefined,undefined,false,false
@@ -207,30 +209,30 @@ ion-card-content,none
ion-card-content,prop,mode,"ios" | "md",undefined,false,false
ion-card-header,shadow
ion-card-header,prop,color,string | undefined,undefined,false,false
ion-card-header,prop,color,string | undefined,undefined,false,true
ion-card-header,prop,mode,"ios" | "md",undefined,false,false
ion-card-header,prop,translucent,boolean,false,false,false
ion-card-subtitle,shadow
ion-card-subtitle,prop,color,string | undefined,undefined,false,false
ion-card-subtitle,prop,color,string | undefined,undefined,false,true
ion-card-subtitle,prop,mode,"ios" | "md",undefined,false,false
ion-card-subtitle,css-prop,--color
ion-card-title,shadow
ion-card-title,prop,color,string | undefined,undefined,false,false
ion-card-title,prop,color,string | undefined,undefined,false,true
ion-card-title,prop,mode,"ios" | "md",undefined,false,false
ion-card-title,css-prop,--color
ion-checkbox,shadow
ion-checkbox,prop,checked,boolean,false,false,false
ion-checkbox,prop,color,string | undefined,undefined,false,false
ion-checkbox,prop,color,string | undefined,undefined,false,true
ion-checkbox,prop,disabled,boolean,false,false,false
ion-checkbox,prop,indeterminate,boolean,false,false,false
ion-checkbox,prop,mode,"ios" | "md",undefined,false,false
ion-checkbox,prop,name,string,this.inputId,false,false
ion-checkbox,prop,value,string,'on',false,false
ion-checkbox,event,ionBlur,void,true
ion-checkbox,event,ionChange,CheckboxChangeEventDetail,true
ion-checkbox,event,ionChange,CheckboxChangeEventDetail<any>,true
ion-checkbox,event,ionFocus,void,true
ion-checkbox,css-prop,--background
ion-checkbox,css-prop,--background-checked
@@ -247,7 +249,8 @@ ion-checkbox,part,container
ion-checkbox,part,mark
ion-chip,shadow
ion-chip,prop,color,string | undefined,undefined,false,false
ion-chip,prop,color,string | undefined,undefined,false,true
ion-chip,prop,disabled,boolean,false,false,false
ion-chip,prop,mode,"ios" | "md",undefined,false,false
ion-chip,prop,outline,boolean,false,false,false
ion-chip,css-prop,--background
@@ -287,7 +290,7 @@ ion-col,css-prop,--ion-grid-column-padding-xs
ion-col,css-prop,--ion-grid-columns
ion-content,shadow
ion-content,prop,color,string | undefined,undefined,false,false
ion-content,prop,color,string | undefined,undefined,false,true
ion-content,prop,forceOverscroll,boolean | undefined,undefined,false,false
ion-content,prop,fullscreen,boolean,false,false,false
ion-content,prop,scrollEvents,boolean,false,false,false
@@ -332,7 +335,7 @@ ion-datetime,prop,monthShortNames,string | string[] | undefined,undefined,false,
ion-datetime,prop,monthValues,number | number[] | string | undefined,undefined,false,false
ion-datetime,prop,name,string,this.inputId,false,false
ion-datetime,prop,pickerFormat,string | undefined,undefined,false,false
ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: "ios" | "md" | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: Mode | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; htmlAttributes?: PickerAttributes | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
ion-datetime,prop,placeholder,null | string | undefined,undefined,false,false
ion-datetime,prop,readonly,boolean,false,false,false
ion-datetime,prop,value,null | string | undefined,undefined,false,false
@@ -360,7 +363,7 @@ ion-fab,method,close,close() => Promise<void>
ion-fab-button,shadow
ion-fab-button,prop,activated,boolean,false,false,false
ion-fab-button,prop,closeIcon,string,'close',false,false
ion-fab-button,prop,color,string | undefined,undefined,false,false
ion-fab-button,prop,color,string | undefined,undefined,false,true
ion-fab-button,prop,disabled,boolean,false,false,false
ion-fab-button,prop,download,string | undefined,undefined,false,false
ion-fab-button,prop,href,string | undefined,undefined,false,false
@@ -456,7 +459,7 @@ ion-input,prop,autocorrect,"off" | "on",'off',false,false
ion-input,prop,autofocus,boolean,false,false,false
ion-input,prop,clearInput,boolean,false,false,false
ion-input,prop,clearOnEdit,boolean | undefined,undefined,false,false
ion-input,prop,color,string | undefined,undefined,false,false
ion-input,prop,color,string | undefined,undefined,false,true
ion-input,prop,debounce,number,0,false,false
ion-input,prop,disabled,boolean,false,false,false
ion-input,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
@@ -496,7 +499,7 @@ ion-input,css-prop,--placeholder-opacity
ion-item,shadow
ion-item,prop,button,boolean,false,false,false
ion-item,prop,color,string | undefined,undefined,false,false
ion-item,prop,color,string | undefined,undefined,false,true
ion-item,prop,detail,boolean | undefined,undefined,false,false
ion-item,prop,detailIcon,string,'chevron-forward',false,false
ion-item,prop,disabled,boolean,false,false,false
@@ -548,7 +551,7 @@ ion-item,part,detail-icon
ion-item,part,native
ion-item-divider,shadow
ion-item-divider,prop,color,string | undefined,undefined,false,false
ion-item-divider,prop,color,string | undefined,undefined,false,true
ion-item-divider,prop,mode,"ios" | "md",undefined,false,false
ion-item-divider,prop,sticky,boolean,false,false,false
ion-item-divider,css-prop,--background
@@ -565,7 +568,7 @@ ion-item-divider,css-prop,--padding-top
ion-item-group,none
ion-item-option,shadow
ion-item-option,prop,color,string | undefined,undefined,false,false
ion-item-option,prop,color,string | undefined,undefined,false,true
ion-item-option,prop,disabled,boolean,false,false,false
ion-item-option,prop,download,string | undefined,undefined,false,false
ion-item-option,prop,expandable,boolean,false,false,false
@@ -592,7 +595,7 @@ ion-item-sliding,method,open,open(side: Side | undefined) => Promise<void>
ion-item-sliding,event,ionDrag,any,true
ion-label,scoped
ion-label,prop,color,string | undefined,undefined,false,false
ion-label,prop,color,string | undefined,undefined,false,true
ion-label,prop,mode,"ios" | "md",undefined,false,false
ion-label,prop,position,"fixed" | "floating" | "stacked" | undefined,undefined,false,false
ion-label,css-prop,--color
@@ -604,7 +607,7 @@ ion-list,prop,mode,"ios" | "md",undefined,false,false
ion-list,method,closeSlidingItems,closeSlidingItems() => Promise<boolean>
ion-list-header,shadow
ion-list-header,prop,color,string | undefined,undefined,false,false
ion-list-header,prop,color,string | undefined,undefined,false,true
ion-list-header,prop,lines,"full" | "inset" | "none" | undefined,undefined,false,false
ion-list-header,prop,mode,"ios" | "md",undefined,false,false
ion-list-header,css-prop,--background
@@ -620,6 +623,7 @@ ion-loading,prop,backdropDismiss,boolean,false,false,false
ion-loading,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-loading,prop,duration,number,0,false,false
ion-loading,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-loading,prop,htmlAttributes,LoadingAttributes | undefined,undefined,false,false
ion-loading,prop,keyboardClose,boolean,true,false,false
ion-loading,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-loading,prop,message,IonicSafeString | string | undefined,undefined,false,false
@@ -675,7 +679,7 @@ ion-menu,part,container
ion-menu-button,shadow
ion-menu-button,prop,autoHide,boolean,true,false,false
ion-menu-button,prop,color,string | undefined,undefined,false,false
ion-menu-button,prop,color,string | undefined,undefined,false,true
ion-menu-button,prop,disabled,boolean,false,false,false
ion-menu-button,prop,menu,string | undefined,undefined,false,false
ion-menu-button,prop,mode,"ios" | "md",undefined,false,false
@@ -707,6 +711,7 @@ ion-modal,prop,component,Function | HTMLElement | null | string,undefined,true,f
ion-modal,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
ion-modal,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-modal,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-modal,prop,htmlAttributes,ModalAttributes | undefined,undefined,false,false
ion-modal,prop,keyboardClose,boolean,true,false,false
ion-modal,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-modal,prop,mode,"ios" | "md",undefined,false,false
@@ -763,7 +768,7 @@ ion-nav-link,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | und
ion-nav-link,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
ion-note,shadow
ion-note,prop,color,string | undefined,undefined,false,false
ion-note,prop,color,string | undefined,undefined,false,true
ion-note,prop,mode,"ios" | "md",undefined,false,false
ion-note,css-prop,--color
@@ -775,6 +780,7 @@ ion-picker,prop,columns,PickerColumn[],[],false,false
ion-picker,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-picker,prop,duration,number,0,false,false
ion-picker,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-picker,prop,htmlAttributes,PickerAttributes | undefined,undefined,false,false
ion-picker,prop,keyboardClose,boolean,true,false,false
ion-picker,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-picker,prop,mode,"ios" | "md",undefined,false,false
@@ -810,6 +816,7 @@ ion-popover,prop,componentProps,undefined | { [key: string]: any; },undefined,fa
ion-popover,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-popover,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-popover,prop,event,any,undefined,false,false
ion-popover,prop,htmlAttributes,PopoverAttributes | undefined,undefined,false,false
ion-popover,prop,keyboardClose,boolean,true,false,false
ion-popover,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-popover,prop,mode,"ios" | "md",undefined,false,false
@@ -835,7 +842,7 @@ ion-popover,css-prop,--width
ion-progress-bar,shadow
ion-progress-bar,prop,buffer,number,1,false,false
ion-progress-bar,prop,color,string | undefined,undefined,false,false
ion-progress-bar,prop,color,string | undefined,undefined,false,true
ion-progress-bar,prop,mode,"ios" | "md",undefined,false,false
ion-progress-bar,prop,reversed,boolean,false,false,false
ion-progress-bar,prop,type,"determinate" | "indeterminate",'determinate',false,false
@@ -843,9 +850,12 @@ ion-progress-bar,prop,value,number,0,false,false
ion-progress-bar,css-prop,--background
ion-progress-bar,css-prop,--buffer-background
ion-progress-bar,css-prop,--progress-background
ion-progress-bar,part,progress
ion-progress-bar,part,stream
ion-progress-bar,part,track
ion-radio,shadow
ion-radio,prop,color,string | undefined,undefined,false,false
ion-radio,prop,color,string | undefined,undefined,false,true
ion-radio,prop,disabled,boolean,false,false,false
ion-radio,prop,mode,"ios" | "md",undefined,false,false
ion-radio,prop,name,string,this.inputId,false,false
@@ -863,10 +873,10 @@ ion-radio-group,none
ion-radio-group,prop,allowEmptySelection,boolean,false,false,false
ion-radio-group,prop,name,string,this.inputId,false,false
ion-radio-group,prop,value,any,undefined,false,false
ion-radio-group,event,ionChange,RadioGroupChangeEventDetail,true
ion-radio-group,event,ionChange,RadioGroupChangeEventDetail<any>,true
ion-range,shadow
ion-range,prop,color,string | undefined,undefined,false,false
ion-range,prop,color,string | undefined,undefined,false,true
ion-range,prop,debounce,number,0,false,false
ion-range,prop,disabled,boolean,false,false,false
ion-range,prop,dualKnobs,boolean,false,false,false
@@ -933,8 +943,8 @@ ion-ripple-effect,prop,type,"bounded" | "unbounded",'bounded',false,false
ion-ripple-effect,method,addRipple,addRipple(x: number, y: number) => Promise<() => void>
ion-route,none
ion-route,prop,beforeEnter,(() => boolean | NavigationHookOptions | Promise<NavigationHookResult>) | undefined,undefined,false,false
ion-route,prop,beforeLeave,(() => boolean | NavigationHookOptions | Promise<NavigationHookResult>) | undefined,undefined,false,false
ion-route,prop,beforeEnter,(() => NavigationHookResult | Promise<NavigationHookResult>) | undefined,undefined,false,false
ion-route,prop,beforeLeave,(() => NavigationHookResult | Promise<NavigationHookResult>) | undefined,undefined,false,false
ion-route,prop,component,string,undefined,true,false
ion-route,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
ion-route,prop,url,string,'',false,false
@@ -954,7 +964,7 @@ ion-router,event,ionRouteDidChange,RouterEventDetail,true
ion-router,event,ionRouteWillChange,RouterEventDetail,true
ion-router-link,shadow
ion-router-link,prop,color,string | undefined,undefined,false,false
ion-router-link,prop,color,string | undefined,undefined,false,true
ion-router-link,prop,href,string | undefined,undefined,false,false
ion-router-link,prop,rel,string | undefined,undefined,false,false
ion-router-link,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
@@ -977,7 +987,7 @@ ion-searchbar,prop,autocorrect,"off" | "on",'off',false,false
ion-searchbar,prop,cancelButtonIcon,string,config.get('backButtonIcon', 'arrow-back-sharp') as string,false,false
ion-searchbar,prop,cancelButtonText,string,'Cancel',false,false
ion-searchbar,prop,clearIcon,string | undefined,undefined,false,false
ion-searchbar,prop,color,string | undefined,undefined,false,false
ion-searchbar,prop,color,string | undefined,undefined,false,true
ion-searchbar,prop,debounce,number,250,false,false
ion-searchbar,prop,disabled,boolean,false,false,false
ion-searchbar,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
@@ -986,6 +996,7 @@ ion-searchbar,prop,mode,"ios" | "md",undefined,false,false
ion-searchbar,prop,placeholder,string,'Search',false,false
ion-searchbar,prop,searchIcon,string | undefined,undefined,false,false
ion-searchbar,prop,showCancelButton,"always" | "focus" | "never",'never',false,false
ion-searchbar,prop,showClearButton,"always" | "focus" | "never",'focus',false,false
ion-searchbar,prop,spellcheck,boolean,false,false,false
ion-searchbar,prop,type,"email" | "number" | "password" | "search" | "tel" | "text" | "url",'search',false,false
ion-searchbar,prop,value,null | string | undefined,'',false,false
@@ -1010,10 +1021,11 @@ ion-searchbar,css-prop,--placeholder-font-weight
ion-searchbar,css-prop,--placeholder-opacity
ion-segment,shadow
ion-segment,prop,color,string | undefined,undefined,false,false
ion-segment,prop,color,string | undefined,undefined,false,true
ion-segment,prop,disabled,boolean,false,false,false
ion-segment,prop,mode,"ios" | "md",undefined,false,false
ion-segment,prop,scrollable,boolean,false,false,false
ion-segment,prop,swipeGesture,boolean,true,false,false
ion-segment,prop,value,null | string | undefined,undefined,false,false
ion-segment,event,ionChange,SegmentChangeEventDetail,true
ion-segment,css-prop,--background
@@ -1141,7 +1153,7 @@ ion-slides,css-prop,--scroll-bar-background
ion-slides,css-prop,--scroll-bar-background-active
ion-spinner,shadow
ion-spinner,prop,color,string | undefined,undefined,false,false
ion-spinner,prop,color,string | undefined,undefined,false,true
ion-spinner,prop,duration,number | undefined,undefined,false,false
ion-spinner,prop,name,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | undefined,undefined,false,false
ion-spinner,prop,paused,boolean,false,false,false
@@ -1163,7 +1175,7 @@ ion-tab,prop,tab,string,undefined,true,false
ion-tab,method,setActive,setActive() => Promise<void>
ion-tab-bar,shadow
ion-tab-bar,prop,color,string | undefined,undefined,false,false
ion-tab-bar,prop,color,string | undefined,undefined,false,true
ion-tab-bar,prop,mode,"ios" | "md",undefined,false,false
ion-tab-bar,prop,selectedTab,string | undefined,undefined,false,false
ion-tab-bar,prop,translucent,boolean,false,false,false
@@ -1202,7 +1214,7 @@ ion-tabs,event,ionTabsDidChange,{ tab: string; },false
ion-tabs,event,ionTabsWillChange,{ tab: string; },false
ion-text,shadow
ion-text,prop,color,string | undefined,undefined,false,false
ion-text,prop,color,string | undefined,undefined,false,true
ion-text,prop,mode,"ios" | "md",undefined,false,false
ion-textarea,scoped
@@ -1210,7 +1222,7 @@ ion-textarea,prop,autoGrow,boolean,false,false,false
ion-textarea,prop,autocapitalize,string,'none',false,false
ion-textarea,prop,autofocus,boolean,false,false,false
ion-textarea,prop,clearOnEdit,boolean,false,false,false
ion-textarea,prop,color,string | undefined,undefined,false,false
ion-textarea,prop,color,string | undefined,undefined,false,true
ion-textarea,prop,cols,number | undefined,undefined,false,false
ion-textarea,prop,debounce,number,0,false,false
ion-textarea,prop,disabled,boolean,false,false,false
@@ -1250,18 +1262,19 @@ ion-thumbnail,css-prop,--border-radius
ion-thumbnail,css-prop,--size
ion-title,shadow
ion-title,prop,color,string | undefined,undefined,false,false
ion-title,prop,color,string | undefined,undefined,false,true
ion-title,prop,size,"large" | "small" | undefined,undefined,false,false
ion-title,css-prop,--color
ion-toast,shadow
ion-toast,prop,animated,boolean,true,false,false
ion-toast,prop,buttons,(string | ToastButton)[] | undefined,undefined,false,false
ion-toast,prop,color,string | undefined,undefined,false,false
ion-toast,prop,color,string | undefined,undefined,false,true
ion-toast,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-toast,prop,duration,number,0,false,false
ion-toast,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-toast,prop,header,string | undefined,undefined,false,false
ion-toast,prop,htmlAttributes,ToastAttributes | undefined,undefined,false,false
ion-toast,prop,keyboardClose,boolean,false,false,false
ion-toast,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,false
@@ -1300,7 +1313,7 @@ ion-toast,part,message
ion-toggle,shadow
ion-toggle,prop,checked,boolean,false,false,false
ion-toggle,prop,color,string | undefined,undefined,false,false
ion-toggle,prop,color,string | undefined,undefined,false,true
ion-toggle,prop,disabled,boolean,false,false,false
ion-toggle,prop,mode,"ios" | "md",undefined,false,false
ion-toggle,prop,name,string,this.inputId,false,false
@@ -1324,7 +1337,7 @@ ion-toggle,part,handle
ion-toggle,part,track
ion-toolbar,shadow
ion-toolbar,prop,color,string | undefined,undefined,false,false
ion-toolbar,prop,color,string | undefined,undefined,false,true
ion-toolbar,prop,mode,"ios" | "md",undefined,false,false
ion-toolbar,css-prop,--background
ion-toolbar,css-prop,--border-color

12927
core/package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "5.4.2",
"version": "5.8.3",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -24,34 +24,38 @@
"collection": "dist/collection/collection-manifest.json",
"types": "dist/types/interface.d.ts",
"files": [
"dist/",
"components/",
"css/",
"dist/",
"hydrate/",
"loader/"
],
"dependencies": {
"ionicons": "^5.1.2",
"tslib": "^1.10.0"
"@stencil/core": "^2.4.0",
"ionicons": "^5.5.3",
"tslib": "^2.1.0"
},
"devDependencies": {
"@axe-core/puppeteer": "^4.1.1",
"@jest/core": "^26.6.3",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/core": "2.1.2",
"@stencil/sass": "1.3.2",
"@stencil/vue-output-target": "0.1.8",
"@types/jest": "^26.0.10",
"@stencil/vue-output-target": "^0.4.3",
"@types/jest": "^26.0.20",
"@types/node": "^14.6.0",
"@types/puppeteer": "3.0.1",
"@types/puppeteer": "5.4.3",
"@types/swiper": "5.4.0",
"aws-sdk": "^2.738.0",
"clean-css-cli": "^4.1.11",
"domino": "^2.1.6",
"execa": "^5.0.0",
"fs-extra": "^9.0.1",
"jest": "^26.4.1",
"jest-cli": "^26.4.1",
"np": "^6.4.0",
"pixelmatch": "4.0.2",
"puppeteer": "^5.2.1",
"puppeteer": "^7.0.1",
"rollup": "^2.26.4",
"sass": "^1.26.10",
"stylelint": "^13.6.1",
@@ -63,8 +67,7 @@
"typescript": "^4.0.5"
},
"scripts": {
"build": "npm run clean && npm run build.css && npm run build.vendor && stencil build --docs --es5 --docs-json dist/docs.json && npm run cdnloader",
"build.vendor": "rollup --config ./scripts/swiper.rollup.config.js",
"build": "npm run clean && npm run build.css && stencil build --docs --es5 --docs-json dist/docs.json && npm run cdnloader",
"build.css": "npm run css.sass && npm run css.minify",
"build.debug": "npm run clean && stencil build --debug",
"build.docs": "stencil build --docs",
@@ -75,7 +78,7 @@
"css.sass": "sass src/css:./css",
"lint": "npm run lint.ts && npm run lint.sass",
"lint.fix": "npm run lint.ts.fix && npm run lint.sass.fix",
"lint.sass": "stylelint 'src/**/*.scss'",
"lint.sass": "stylelint \"src/**/*.scss\"",
"lint.sass.fix": "npm run lint.sass -- --fix",
"lint.ts": "tslint --project .",
"lint.ts.fix": "tslint --project . --fix",

View File

@@ -0,0 +1,2 @@
export * from './index';
export * from '../dist/types/interface';

View File

@@ -0,0 +1,9 @@
{
"name": "@ionic/core/components",
"version": "0.0.0",
"description": "Ionic Components exported as custom elements, extending HTMLElement.",
"main": "./index.js",
"types": "./custom-elements.d.ts",
"private": true,
"sideEffects": false
}

View File

@@ -13,7 +13,7 @@ const s3 = new S3({ apiVersion: '2006-03-01' });
class CIScreenshotConnector extends IonicConnector {
async initBuild(opts) {
const result = await execa.stdout('git', ['log', '-1', '--format=%H%n%an <%ae>%n%ct%n%s']);
const { stdout: result } = await execa('git', ['log', '-1', '--format=%H%n%an <%ae>%n%ct%n%s']);
const [ sha1, author, timestamp, msg ] = result.split('\n');
const sha1short = sha1.slice(0, 7);
@@ -125,8 +125,6 @@ class CIScreenshotConnector extends IonicConnector {
uploadPaths.push(path.join(appRoot, 'scripts', 'testing', 'styles.css'));
const distDir = path.join(appRoot, 'dist');
uploadPaths.push(path.join(distDir, 'ionic.js'));
const distIonicDir = path.join(distDir, 'ionic');
fs.readdirSync(distIonicDir).forEach(distIonicFile => {
uploadPaths.push(path.join(distIonicDir, distIonicFile));

View File

@@ -1,12 +0,0 @@
import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/components/slides/swiper/swiper.js',
output: {
file: 'src/components/slides/swiper/swiper.bundle.js',
format: 'es'
},
plugins: [
resolve()
]
};

View File

@@ -4,15 +4,15 @@ const virtual = require('@rollup/plugin-virtual');
const fs = require('fs');
async function main() {
const input = process.argv[2] || getInput();
const result = await check(input);
const relative = path.relative(process.cwd(), input);
const input = process.argv[2] || getMainEntry();
const result = await check(input);
const relative = path.relative(process.cwd(), input);
if (result.shaken) {
console.error(`Success! ${relative} is fully tree-shakeable`);
} else {
error(`Failed to tree-shake ${relative}`);
}
if (result.shaken) {
console.error(`Success! ${relative} is fully tree-shakeable`);
} else {
error(`Failed to tree-shake ${relative}`);
};
}
function error(msg) {
@@ -20,10 +20,10 @@ function error(msg) {
process.exit(1);
}
function getInput() {
if (!fs.existsSync('package.json')) {
error(`Could not find package.json`);
}
function getMainEntry() {
if (!fs.existsSync('package.json')) {
error(`Could not find package.json`);
}
const pkg = JSON.parse(fs.readFileSync('package.json'), 'utf-8');
@@ -38,20 +38,20 @@ function getInput() {
}
function resolve(file) {
if (isDirectory(file)) {
return ifExists(`${file}/index.js`) || ifExists(`${file}/index.cjs.js`);
}
if (isDirectory(file)) {
return ifExists(`${file}/index.cjs.js`) || ifExists(`${file}/index.js`);
}
return ifExists(file) || ifExists(`${file}.js`) || ifExists(`${file}.cjs.js`);
return ifExists(file) || ifExists(`${file}.cjs.js`) || ifExists(`${file}.js`);
}
function isDirectory(file) {
try {
const stats = fs.statSync(file);
return stats.isDirectory();
} catch (err) {
return false;
}
try {
const stats = fs.statSync(file);
return stats.isDirectory();
} catch (err) {
return false;
}
}
function ifExists(file) {
@@ -67,7 +67,7 @@ async function check(input) {
virtual({
__agadoo__: `import ${JSON.stringify(resolved)}`,
tslib: `
const noop = () => {};
const noop = () => {};
export const __awaiter = noop;
export const __extends = noop;
export const __generator = noop;

View File

@@ -5,10 +5,12 @@
* It contains typing information for all components that exist in this project.
*/
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimeOptions, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, MenuChangeEventDetail, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerButton, PickerColumn, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, ViewController } from "./interface";
import { ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimeOptions, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, ViewController } from "./interface";
import { IonicSafeString } from "./utils/sanitization";
import { AlertAttributes } from "./components/alert/alert-interface";
import { NavigationHookCallback } from "./components/route/route-interface";
import { SelectCompareFn } from "./components/select/select-interface";
import { ToastAttributes } from "./components/toast/toast-interface";
export namespace Components {
interface IonActionSheet {
/**
@@ -41,6 +43,10 @@ export namespace Components {
* Title for the action sheet.
*/
"header"?: string;
/**
* Additional attributes to pass to the action sheet.
*/
"htmlAttributes"?: ActionSheetAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -106,6 +112,10 @@ export namespace Components {
* The main title in the heading of the alert.
*/
"header"?: string;
/**
* Additional attributes to pass to the alert.
*/
"htmlAttributes"?: AlertAttributes;
/**
* Array of input to show in the alert.
*/
@@ -394,7 +404,7 @@ export namespace Components {
*/
"name": string;
/**
* The value of the toggle does not mean if it's checked or not, use the `checked` property for that. The value of a toggle is analogous to the value of a `<input type="checkbox">`, it's only used when the toggle participates in a native `<form>`.
* The value of the checkbox does not mean if it's checked or not, use the `checked` property for that. The value of a checkbox is analogous to the value of an `<input type="checkbox">`, it's only used when the checkbox participates in a native `<form>`.
*/
"value": string;
}
@@ -403,6 +413,10 @@ export namespace Components {
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, the user cannot interact with the chip.
*/
"disabled": boolean;
/**
* The mode determines which platform styles to use.
*/
@@ -830,7 +844,7 @@ export namespace Components {
*/
"accept"?: string;
/**
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user. Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
*/
"autocapitalize": string;
/**
@@ -1173,6 +1187,10 @@ export namespace Components {
* Animation to use when the loading indicator is presented.
*/
"enterAnimation"?: AnimationBuilder;
/**
* Additional attributes to pass to the loader.
*/
"htmlAttributes"?: LoadingAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -1221,7 +1239,7 @@ export namespace Components {
*/
"close": (animated?: boolean) => Promise<boolean>;
/**
* The content's id the menu should use.
* The `id` of the main content. When using a router this is typically `ion-router-outlet`. When not using a router, this is typically your main view's `ion-content`. This is not the id of the `ion-content` inside of your `ion-menu`.
*/
"contentId"?: string;
/**
@@ -1337,6 +1355,10 @@ export namespace Components {
* Animation to use when the modal is presented.
*/
"enterAnimation"?: AnimationBuilder;
/**
* Additional attributes to pass to the modal.
*/
"htmlAttributes"?: ModalAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -1554,6 +1576,10 @@ export namespace Components {
* @param name The name of the column.
*/
"getColumn": (name: string) => Promise<PickerColumn | undefined>;
/**
* Additional attributes to pass to the picker.
*/
"htmlAttributes"?: PickerAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -1626,6 +1652,10 @@ export namespace Components {
* The event to pass to the popover animation.
*/
"event": any;
/**
* Additional attributes to pass to the popover.
*/
"htmlAttributes"?: PopoverAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -1704,7 +1734,7 @@ export namespace Components {
*/
"name": string;
"setButtonTabindex": (value: number) => Promise<void>;
"setFocus": () => Promise<void>;
"setFocus": (ev: any) => Promise<void>;
/**
* the value of the radio.
*/
@@ -1812,7 +1842,7 @@ export namespace Components {
*/
"pullMin": number;
/**
* Time it takes the refresher to to snap back to the `refreshing` state. Does not apply when the refresher content uses a spinner, enabling the native refresher.
* Time it takes the refresher to snap back to the `refreshing` state. Does not apply when the refresher content uses a spinner, enabling the native refresher.
*/
"snapbackDuration": string;
}
@@ -1906,11 +1936,11 @@ export namespace Components {
*/
"push": (url: string, direction?: RouterDirection, animation?: AnimationBuilder | undefined) => Promise<boolean>;
/**
* By default `ion-router` will match the routes at the root path ("/"). That can be changed when
* The root path to use when matching URLs. By default, this is set to "/", but you can specify an alternate prefix for all URL paths.
*/
"root": string;
/**
* The router can work in two "modes": - With hash: `/index.html#/path/to/page` - Without hash: `/path/to/page` Using one or another might depend in the requirements of your app and/or where it's deployed. Usually "hash-less" navigation works better for SEO and it's more user friendly too, but it might requires additional server-side configuration in order to properly work. On the otherside hash-navigation is much easier to deploy, it even works over the file protocol. By default, this property is `true`, change to `false` to allow hash-less URLs.
* The router can work in two "modes": - With hash: `/index.html#/path/to/page` - Without hash: `/path/to/page` Using one or another might depend in the requirements of your app and/or where it's deployed. Usually "hash-less" navigation works better for SEO and it's more user friendly too, but it might requires additional server-side configuration in order to properly work. On the other side hash-navigation is much easier to deploy, it even works over the file protocol. By default, this property is `true`, change to `false` to allow hash-less URLs.
*/
"useHash": boolean;
}
@@ -2030,6 +2060,10 @@ export namespace Components {
* Sets the behavior for the cancel button. Defaults to `"never"`. Setting to `"focus"` shows the cancel button on focus. Setting to `"never"` hides the cancel button. Setting to `"always"` shows the cancel button regardless of focus state.
*/
"showCancelButton": 'never' | 'focus' | 'always';
/**
* Sets the behavior for the clear button. Defaults to `"focus"`. Setting to `"focus"` shows the clear button on focus if the input is not empty. Setting to `"never"` hides the clear button. Setting to `"always"` shows the clear button regardless of focus state, but only if the input is not empty.
*/
"showClearButton": 'never' | 'focus' | 'always';
/**
* If `true`, enable spellcheck on the input.
*/
@@ -2060,6 +2094,10 @@ export namespace Components {
* If `true`, the segment buttons will overflow and the user can swipe to see them. In addition, this will disable the gesture to drag the indicator between the buttons in order to swipe to see hidden buttons.
*/
"scrollable": boolean;
/**
* If `true`, users will be able to swipe between segment buttons to activate them.
*/
"swipeGesture": boolean;
/**
* the value of the segment.
*/
@@ -2291,7 +2329,7 @@ export namespace Components {
}
interface IonSplitPane {
/**
* The content `id` of the split-pane's main content.
* The `id` of the main content. When using a router this is typically `ion-router-outlet`. When not using a router, this is typically your main view's `ion-content`. This is not the id of the `ion-content` inside of your `ion-menu`.
*/
"contentId"?: string;
/**
@@ -2553,6 +2591,10 @@ export namespace Components {
* Header to be shown in the toast.
*/
"header"?: string;
/**
* Additional attributes to pass to the toast.
*/
"htmlAttributes"?: ToastAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -3334,6 +3376,10 @@ declare namespace LocalJSX {
* Title for the action sheet.
*/
"header"?: string;
/**
* Additional attributes to pass to the action sheet.
*/
"htmlAttributes"?: ActionSheetAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -3397,6 +3443,10 @@ declare namespace LocalJSX {
* The main title in the heading of the alert.
*/
"header"?: string;
/**
* Additional attributes to pass to the alert.
*/
"htmlAttributes"?: AlertAttributes;
/**
* Array of input to show in the alert.
*/
@@ -3701,7 +3751,7 @@ declare namespace LocalJSX {
*/
"name"?: string;
/**
* Emitted when the toggle loses focus.
* Emitted when the checkbox loses focus.
*/
"onIonBlur"?: (event: CustomEvent<void>) => void;
/**
@@ -3709,7 +3759,7 @@ declare namespace LocalJSX {
*/
"onIonChange"?: (event: CustomEvent<CheckboxChangeEventDetail>) => void;
/**
* Emitted when the toggle has focus.
* Emitted when the checkbox has focus.
*/
"onIonFocus"?: (event: CustomEvent<void>) => void;
/**
@@ -3717,7 +3767,7 @@ declare namespace LocalJSX {
*/
"onIonStyle"?: (event: CustomEvent<StyleEventDetail>) => void;
/**
* The value of the toggle does not mean if it's checked or not, use the `checked` property for that. The value of a toggle is analogous to the value of a `<input type="checkbox">`, it's only used when the toggle participates in a native `<form>`.
* The value of the checkbox does not mean if it's checked or not, use the `checked` property for that. The value of a checkbox is analogous to the value of an `<input type="checkbox">`, it's only used when the checkbox participates in a native `<form>`.
*/
"value"?: string;
}
@@ -3726,6 +3776,10 @@ declare namespace LocalJSX {
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
*/
"color"?: Color;
/**
* If `true`, the user cannot interact with the chip.
*/
"disabled"?: boolean;
/**
* The mode determines which platform styles to use.
*/
@@ -4169,7 +4223,7 @@ declare namespace LocalJSX {
*/
"accept"?: string;
/**
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user.
* Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user. Available options: `"off"`, `"none"`, `"on"`, `"sentences"`, `"words"`, `"characters"`.
*/
"autocapitalize"?: string;
/**
@@ -4504,6 +4558,10 @@ declare namespace LocalJSX {
* Animation to use when the loading indicator is presented.
*/
"enterAnimation"?: AnimationBuilder;
/**
* Additional attributes to pass to the loader.
*/
"htmlAttributes"?: LoadingAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -4552,7 +4610,7 @@ declare namespace LocalJSX {
}
interface IonMenu {
/**
* The content's id the menu should use.
* The `id` of the main content. When using a router this is typically `ion-router-outlet`. When not using a router, this is typically your main view's `ion-content`. This is not the id of the `ion-content` inside of your `ion-menu`.
*/
"contentId"?: string;
/**
@@ -4662,6 +4720,10 @@ declare namespace LocalJSX {
* Animation to use when the modal is presented.
*/
"enterAnimation"?: AnimationBuilder;
/**
* Additional attributes to pass to the modal.
*/
"htmlAttributes"?: ModalAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -4796,6 +4858,10 @@ declare namespace LocalJSX {
* Animation to use when the picker is presented.
*/
"enterAnimation"?: AnimationBuilder;
/**
* Additional attributes to pass to the picker.
*/
"htmlAttributes"?: PickerAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -4870,6 +4936,10 @@ declare namespace LocalJSX {
* The event to pass to the popover animation.
*/
"event"?: any;
/**
* Additional attributes to pass to the popover.
*/
"htmlAttributes"?: PopoverAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@@ -5090,7 +5160,7 @@ declare namespace LocalJSX {
*/
"pullMin"?: number;
/**
* Time it takes the refresher to to snap back to the `refreshing` state. Does not apply when the refresher content uses a spinner, enabling the native refresher.
* Time it takes the refresher to snap back to the `refreshing` state. Does not apply when the refresher content uses a spinner, enabling the native refresher.
*/
"snapbackDuration"?: string;
}
@@ -5180,11 +5250,11 @@ declare namespace LocalJSX {
*/
"onIonRouteWillChange"?: (event: CustomEvent<RouterEventDetail>) => void;
/**
* By default `ion-router` will match the routes at the root path ("/"). That can be changed when
* The root path to use when matching URLs. By default, this is set to "/", but you can specify an alternate prefix for all URL paths.
*/
"root"?: string;
/**
* The router can work in two "modes": - With hash: `/index.html#/path/to/page` - Without hash: `/path/to/page` Using one or another might depend in the requirements of your app and/or where it's deployed. Usually "hash-less" navigation works better for SEO and it's more user friendly too, but it might requires additional server-side configuration in order to properly work. On the otherside hash-navigation is much easier to deploy, it even works over the file protocol. By default, this property is `true`, change to `false` to allow hash-less URLs.
* The router can work in two "modes": - With hash: `/index.html#/path/to/page` - Without hash: `/path/to/page` Using one or another might depend in the requirements of your app and/or where it's deployed. Usually "hash-less" navigation works better for SEO and it's more user friendly too, but it might requires additional server-side configuration in order to properly work. On the other side hash-navigation is much easier to deploy, it even works over the file protocol. By default, this property is `true`, change to `false` to allow hash-less URLs.
*/
"useHash"?: boolean;
}
@@ -5324,6 +5394,10 @@ declare namespace LocalJSX {
* Sets the behavior for the cancel button. Defaults to `"never"`. Setting to `"focus"` shows the cancel button on focus. Setting to `"never"` hides the cancel button. Setting to `"always"` shows the cancel button regardless of focus state.
*/
"showCancelButton"?: 'never' | 'focus' | 'always';
/**
* Sets the behavior for the clear button. Defaults to `"focus"`. Setting to `"focus"` shows the clear button on focus if the input is not empty. Setting to `"never"` hides the clear button. Setting to `"always"` shows the clear button regardless of focus state, but only if the input is not empty.
*/
"showClearButton"?: 'never' | 'focus' | 'always';
/**
* If `true`, enable spellcheck on the input.
*/
@@ -5366,6 +5440,10 @@ declare namespace LocalJSX {
* If `true`, the segment buttons will overflow and the user can swipe to see them. In addition, this will disable the gesture to drag the indicator between the buttons in order to swipe to see hidden buttons.
*/
"scrollable"?: boolean;
/**
* If `true`, users will be able to swipe between segment buttons to activate them.
*/
"swipeGesture"?: boolean;
/**
* the value of the segment.
*/
@@ -5601,7 +5679,7 @@ declare namespace LocalJSX {
}
interface IonSplitPane {
/**
* The content `id` of the split-pane's main content.
* The `id` of the main content. When using a router this is typically `ion-router-outlet`. When not using a router, this is typically your main view's `ion-content`. This is not the id of the `ion-content` inside of your `ion-menu`.
*/
"contentId"?: string;
/**
@@ -5870,6 +5948,10 @@ declare namespace LocalJSX {
* Header to be shown in the toast.
*/
"header"?: string;
/**
* Additional attributes to pass to the toast.
*/
"htmlAttributes"?: ToastAttributes;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/

View File

@@ -1,3 +1,5 @@
import { JSXBase } from '@stencil/core/internal';
import { AnimationBuilder, Mode } from '../../interface';
export interface ActionSheetOptions {
@@ -11,11 +13,14 @@ export interface ActionSheetOptions {
mode?: Mode;
keyboardClose?: boolean;
id?: string;
htmlAttributes?: ActionSheetAttributes;
enterAnimation?: AnimationBuilder;
leaveAnimation?: AnimationBuilder;
}
export interface ActionSheetAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
export interface ActionSheetButton {
text?: string;
role?: 'cancel' | 'destructive' | 'selected' | string;

View File

@@ -110,10 +110,16 @@
text-align: $action-sheet-ios-text-align;
}
.action-sheet-title.action-sheet-has-sub-title {
font-weight: $action-sheet-ios-title-with-sub-title-font-weight;
}
.action-sheet-sub-title {
@include padding($action-sheet-ios-sub-title-padding-top, $action-sheet-ios-sub-title-padding-end, $action-sheet-ios-sub-title-padding-bottom, $action-sheet-ios-sub-title-padding-start);
font-size: $action-sheet-ios-sub-title-font-size;
font-weight: $action-sheet-ios-title-font-weight;
}

View File

@@ -55,6 +55,9 @@ $action-sheet-ios-title-font-size: 13px !default;
/// @prop - Font weight of the action sheet title
$action-sheet-ios-title-font-weight: 400 !default;
/// @prop - Font weight of the action sheet title when it has a sub title
$action-sheet-ios-title-with-sub-title-font-weight: 600 !default;
/// @prop - Border width of the action sheet title
$action-sheet-ios-title-border-width: $hairlines-width !default;
@@ -72,10 +75,10 @@ $action-sheet-ios-title-border-color: rgba($text-col
// --------------------------------------------------
/// @prop - Font size of the action sheet sub title
$action-sheet-ios-sub-title-font-size: 12px !default;
$action-sheet-ios-sub-title-font-size: 13px !default;
/// @prop - Padding top of the action sheet sub title
$action-sheet-ios-sub-title-padding-top: 15px !default;
$action-sheet-ios-sub-title-padding-top: 6px !default;
/// @prop - Padding end of the action sheet sub title
$action-sheet-ios-sub-title-padding-end: 0 !default;
@@ -103,7 +106,7 @@ $action-sheet-ios-button-text-color: ion-color(prim
$action-sheet-ios-button-icon-font-size: 28px !default;
/// @prop - Padding right of the action sheet button icon
$action-sheet-ios-button-icon-padding-right: .1em !default;
$action-sheet-ios-button-icon-padding-right: .3em !default;
/// @prop - Font size of the action sheet button
$action-sheet-ios-button-font-size: 20px !default;

View File

@@ -23,7 +23,7 @@
.action-sheet-title {
@include padding($action-sheet-md-title-padding-top, $action-sheet-md-title-padding-end, $action-sheet-md-title-padding-bottom, $action-sheet-md-title-padding-start);
height: $action-sheet-md-title-height;
min-height: $action-sheet-md-title-height;
color: var(--color, $action-sheet-md-title-color);

View File

@@ -1,7 +1,7 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h, readTask } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
import { ActionSheetAttributes, ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
import { Gesture } from '../../utils/gesture';
import { createButtonActiveGesture } from '../../utils/gesture/button-active';
import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays';
@@ -90,6 +90,11 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
*/
@Prop() animated = true;
/**
* Additional attributes to pass to the action sheet.
*/
@Prop() htmlAttributes?: ActionSheetAttributes;
/**
* Emitted after the alert has presented.
*/
@@ -228,6 +233,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
}
render() {
const { htmlAttributes } = this;
const mode = getIonMode(this);
const allButtons = this.getButtons();
const cancelButton = allButtons.find(b => b.role === 'cancel');
@@ -238,6 +244,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
role="dialog"
aria-modal="true"
tabindex="-1"
{...htmlAttributes as any}
style={{
zIndex: `${20000 + this.overlayIndex}`,
}}
@@ -258,7 +265,10 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
<div class="action-sheet-container">
<div class="action-sheet-group" ref={el => this.groupEl = el}>
{this.header !== undefined &&
<div class="action-sheet-title">
<div class={{
'action-sheet-title': true,
'action-sheet-has-sub-title': this.subHeader !== undefined
}}>
{this.header}
{this.subHeader && <div class="action-sheet-sub-title">{this.subHeader}</div>}
</div>

View File

@@ -34,6 +34,46 @@ Any of the defined [CSS Custom Properties](#css-custom-properties) can be used t
> If you are building an Ionic Angular app, the styles need to be added to a global stylesheet file. Read [Style Placement](#style-placement) in the Angular section below for more information.
## Interfaces
### ActionSheetButton
```typescript
interface ActionSheetButton {
text?: string;
role?: 'cancel' | 'destructive' | 'selected' | string;
icon?: string;
cssClass?: string | string[];
handler?: () => boolean | void | Promise<boolean | void>;
}
```
### ActionSheetOptions
```typescript
interface ActionSheetOptions {
header?: string;
subHeader?: string;
cssClass?: string | string[];
buttons: (ActionSheetButton | string)[];
backdropDismiss?: boolean;
translucent?: boolean;
animated?: boolean;
mode?: Mode;
keyboardClose?: boolean;
id?: string;
htmlAttributes?: ActionSheetAttributes;
enterAnimation?: AnimationBuilder;
leaveAnimation?: AnimationBuilder;
}
```
### ActionSheetAttributes
```typescript
interface ActionSheetAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
```
<!-- Auto Generated Below -->
@@ -94,6 +134,9 @@ export class ActionSheetExample {
}]
});
await actionSheet.present();
const { role } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
}
@@ -147,7 +190,10 @@ async function presentActionSheet() {
}
}];
document.body.appendChild(actionSheet);
return actionSheet.present();
await actionSheet.present();
const { role } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
```
@@ -155,6 +201,59 @@ async function presentActionSheet() {
### React
```tsx
/* Using with useIonActionSheet Hook */
import React from 'react';
import {
IonButton,
IonContent,
IonPage,
useIonActionSheet,
} from '@ionic/react';
const ActionSheetExample: React.FC = () => {
const [present, dismiss] = useIonActionSheet();
return (
<IonPage>
<IonContent>
<IonButton
expand="block"
onClick={() =>
present({
buttons: [{ text: 'Ok' }, { text: 'Cancel' }],
header: 'Action Sheet'
})
}
>
Show ActionSheet
</IonButton>
<IonButton
expand="block"
onClick={() =>
present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet')
}
>
Show ActionSheet using params
</IonButton>
<IonButton
expand="block"
onClick={() => {
present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet');
setTimeout(dismiss, 3000);
}}
>
Show ActionSheet, hide after 3 seconds
</IonButton>
</IonContent>
</IonPage>
);
};
```
```tsx
/* Using with IonActionSheet Component */
import React, { useState } from 'react';
import { IonActionSheet, IonContent, IonButton } from '@ionic/react';
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';
@@ -263,6 +362,9 @@ export class ActionSheetExample {
}]
});
await actionSheet.present();
const { role } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
render() {
@@ -336,7 +438,10 @@ export default defineComponent({
},
],
});
return actionSheet.present();
await actionSheet.present();
const { role } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
},
},
});
@@ -353,7 +458,7 @@ Developers can also use this component directly in their template:
header="Albums"
css-class="my-custom-class"
:buttons="buttons"
@onDidDismiss="setOpen(false)"
@didDismiss="setOpen(false)"
>
</ion-action-sheet>
</template>
@@ -426,6 +531,7 @@ export default defineComponent({
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
| `enterAnimation` | -- | Animation to use when the action sheet is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
| `header` | `header` | Title for the action sheet. | `string \| undefined` | `undefined` |
| `htmlAttributes` | -- | Additional attributes to pass to the action sheet. | `ActionSheetAttributes \| undefined` | `undefined` |
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
| `leaveAnimation` | -- | Animation to use when the action sheet is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |

View File

@@ -111,3 +111,21 @@ test('action-sheet:rtl: basic, scroll without cancel', async () => {
test('action-sheet:rtl: basic, custom backdrop', async () => {
await testActionSheet(DIRECTORY, '#customBackdrop', true);
});
// Attributes
test('action-sheet: htmlAttributes', async () => {
const page = await newE2EPage({ url: '/src/components/action-sheet/test/basic?ionic:_testing=true' });
await page.click('#basic');
await page.waitForSelector('#basic');
let toast = await page.find('ion-action-sheet');
expect(toast).not.toBe(null);
await toast.waitForVisible();
const attribute = await page.evaluate((el) => document.querySelector('ion-action-sheet').getAttribute('data-testid'));
expect(attribute).toEqual('basic-action-sheet');
});

View File

@@ -70,6 +70,10 @@
const mode = Ionic.mode;
await openActionSheet({
header: "Albums",
subHeader: 'This is a sub header inside of an action sheet',
htmlAttributes: {
'data-testid': 'basic-action-sheet'
},
buttons: [{
text: 'Delete',
role: 'destructive',

View File

@@ -71,7 +71,7 @@ export const testActionSheetAlert = async (
const alert = await page.find('ion-alert');
await alert.waitForVisible();
await page.waitFor(250);
await page.waitForTimeout(250);
screenshotCompares.push(await page.compareScreenshot(`alert open`));

View File

@@ -50,6 +50,9 @@ export class ActionSheetExample {
}]
});
await actionSheet.present();
const { role } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
}

View File

@@ -38,6 +38,9 @@ async function presentActionSheet() {
}
}];
document.body.appendChild(actionSheet);
return actionSheet.present();
await actionSheet.present();
const { role } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
```

View File

@@ -1,4 +1,57 @@
```tsx
/* Using with useIonActionSheet Hook */
import React from 'react';
import {
IonButton,
IonContent,
IonPage,
useIonActionSheet,
} from '@ionic/react';
const ActionSheetExample: React.FC = () => {
const [present, dismiss] = useIonActionSheet();
return (
<IonPage>
<IonContent>
<IonButton
expand="block"
onClick={() =>
present({
buttons: [{ text: 'Ok' }, { text: 'Cancel' }],
header: 'Action Sheet'
})
}
>
Show ActionSheet
</IonButton>
<IonButton
expand="block"
onClick={() =>
present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet')
}
>
Show ActionSheet using params
</IonButton>
<IonButton
expand="block"
onClick={() => {
present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet');
setTimeout(dismiss, 3000);
}}
>
Show ActionSheet, hide after 3 seconds
</IonButton>
</IonContent>
</IonPage>
);
};
```
```tsx
/* Using with IonActionSheet Component */
import React, { useState } from 'react';
import { IonActionSheet, IonContent, IonButton } from '@ionic/react';
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';

View File

@@ -47,6 +47,9 @@ export class ActionSheetExample {
}]
});
await actionSheet.present();
const { role } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
render() {

View File

@@ -56,7 +56,10 @@ export default defineComponent({
},
],
});
return actionSheet.present();
await actionSheet.present();
const { role } = await actionSheet.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
},
},
});
@@ -73,7 +76,7 @@ Developers can also use this component directly in their template:
header="Albums"
css-class="my-custom-class"
:buttons="buttons"
@onDidDismiss="setOpen(false)"
@didDismiss="setOpen(false)"
>
</ion-action-sheet>
</template>

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