Compare commits

...

273 Commits

Author SHA1 Message Date
Liam DeBeasi
ede6289bc6 remove package lock 2020-06-05 16:08:10 -04:00
Liam DeBeasi
f077f0aac7 sync with master 2020-06-05 16:06:40 -04:00
Liam DeBeasi
9c64308f0d add generic wrapper class 2020-06-05 16:05:43 -04:00
Liam DeBeasi
795783311a clean up animations: 2020-06-05 14:55:58 -04:00
Liam DeBeasi
f3e8d4c31d typo 2020-06-05 14:04:51 -04:00
Liam DeBeasi
7fb38d1e12 add support for backdrop to fade anim 2020-06-05 14:04:04 -04:00
Liam DeBeasi
9f9ba235ee add fade and fade through animations 2020-06-05 13:54:56 -04:00
Liam DeBeasi
187917c746 chore(): exempt bugs and feature requests from stale issues (#21435) 2020-06-05 09:45:27 -04:00
Liam DeBeasi
137c49d70b fix(scroll-assist): improve scroll detection accuracy (#21416) 2020-06-03 10:01:01 -04:00
Alexey Vinogradov
5bf83b80d7 feat(all): add optional generics typings for overlay component methods (#21393) 2020-06-03 09:08:27 -04:00
Niklas Merz
c7e94a1f23 docs(datetime): specify default value for dayShortNames (#21281) 2020-06-02 17:21:38 -04:00
Celilsemi Sam Erkiner
1ed81693f2 feat(alert): add support for custom input attributes (#21365) 2020-06-01 11:18:59 -04:00
Thomas Clark
5f2001c43c fix(reorder-group): revert item to original position when passing false to complete (#21396)
fixes #19128
2020-05-29 14:35:34 -04:00
Brandy Carney
882f8fef07 fix(item): inherit align-items from parent item (#19278)
inherits alignment in inner item, sets item alignment to center

fixes #18703
2020-05-29 11:30:19 -04:00
Adam Bradley
323e15003f chore: internal import updates to improve bundling (#21400)
* chore: internal import updates to improve bundling

- Rename keyboard.ts so it has a good filename after custom element bundling
- Import util fns directly instead of from top level index
- Do not export with *

* chore(angular): bump ng-packagr

Co-authored-by: Mike Hartington <mikehartington@gmail.com>
2020-05-29 10:04:12 -05:00
Haidar Zeineddine
53fc8e37c8 feat(angular): strongly type Ionic lifecycle hooks (#18044)
closes #18043
2020-05-27 16:42:34 -04:00
Alex Currie-Clark
29d208de88 fix(item): input-wrapper now inherits overflow (#21282) 2020-05-27 12:56:11 -04:00
Brandy Carney
5285824da5 feat(select-option): pass class from the option to the interface for individual styling (#21304)
Co-authored-by: Robb Wright <audaxion@gmail.com>
2020-05-27 12:12:01 -04:00
David
2dac12c577 fix(header): large title transition works on older versions of iOS (#21339) 2020-05-27 10:34:01 -04:00
Simon Hänisch
7703da28f8 fix(toast, action-sheet): allow button handler to return Promise<void> (#21259) 2020-05-26 15:27:14 -04:00
Brandy Carney
1ea5ce5839 chore(stencil): update to latest stencil version (#21378)
references ionic-team/ionic-docs#1343
2020-05-26 15:05:36 -04:00
Liam DeBeasi
33be1f061e fix(ios): add haptic drag gesture for action sheet and alert components (#21060) 2020-05-26 11:33:51 -04:00
Manu MA
e53f0241e2 feat(alert): add destructive role to alert buttons (#21269) 2020-05-22 15:32:12 -04:00
Liam DeBeasi
4af54a2fea feat(angular): expose getPlatforms and isPlatform (#21308) 2020-05-22 10:27:03 -04:00
Manu MA
4fd7c0cc5a feat(all): add all autocomplete values to input and searchbar (#21297) 2020-05-22 09:23:44 -04:00
Liam DeBeasi
32906048a4 fix(slides): update Swiper dependency to resolve error when doing SSR (#21350) 2020-05-20 15:54:02 -04:00
Liam DeBeasi
829a0d9be5 feat(angular): expose activatedView (#21302) 2020-05-20 15:24:30 -04:00
Liam DeBeasi
c680705162 chore(): update scripts to use colorette instead of turbocolor (#21349) 2020-05-20 13:33:53 -04:00
Liam DeBeasi
60be68ca6d docs(title): clarify background-color styling with collapsible large title (#21348) 2020-05-20 12:58:24 -04:00
Liam DeBeasi
28c5e14434 add multi axis anim 2020-05-20 11:25:30 -04:00
Liam DeBeasi
237748049c fix(textarea): native textarea inherits max/min width and heights (#21333)
Co-authored-by: Stefanos Anagnostou <anagstef@users.noreply.github.com>
2020-05-19 12:38:03 -04:00
Liam DeBeasi
a4be67aeb8 add axis support 2020-05-18 17:39:12 -04:00
Liam DeBeasi
ec4c0fe5bd chore(): revert changes until bot is updated (#21332)
This reverts commit cc780c80b2.
2020-05-18 13:48:39 -04:00
Liam DeBeasi
cc780c80b2 chore(): update bot template to properly close issues (#21330) 2020-05-18 13:40:37 -04:00
Liam DeBeasi
eaf4fb6b2a fix(menu-button): screen readers now properly announce menu button (#21324) 2020-05-18 12:43:02 -04:00
Liam DeBeasi
94c3d481e9 Add base motion package 2020-05-15 15:57:55 -04:00
Liam DeBeasi
3937101e5c fix(datetime): ensure year-only values are not affected by timezone when parsing (#21309) 2020-05-15 11:36:01 -04:00
Brandy Carney
16a03d58ec docs(headings): update readme headings to be correct level 2020-05-14 17:26:44 -04:00
Julian Baumann
448dfa0a69 fix(modal): card style modal no longer gets stuck when swiping quickly (#21224) 2020-05-14 11:50:31 -04:00
Liam DeBeasi
39bfaeaa79 merge release-5.1.1
5.1.1
2020-05-13 14:22:45 -04:00
Liam DeBeasi
f954d40453 5.1.1 2020-05-13 14:19:55 -04:00
Brandy Carney
dd4cb706ff fix(input): check for tabindex and pass it properly to native input (#21170)
* fix(input): check for tabindex and pass it properly to native input

references #17515

* style(input): fix lint error

* test(input): update test for more use cases (inside item)

* fix(item): adds delegatesFocus to shadow

* style(input): add comment block on what the code does
2020-05-13 12:18:03 -04:00
Liam DeBeasi
50678c03c9 fix(ios): transition shadow properly sized regardless of footer (#21095) 2020-05-13 12:17:45 -04:00
Brandy Carney
898401a7e0 docs(overlays): add documentation on customization in scoped overlays (#21283)
- improves the documentation on customizing scoped overlays using cssClass and/or CSS variables
- includes a section in the Angular usage with information on where the CSS needs to be styled (globally) in order to work for an overlay
2020-05-13 11:54:11 -04:00
Brandy Carney
687122127c docs(stencil): add stencil usage to components (#21261) 2020-05-12 20:35:48 -04:00
Brandy Carney
703ef5c992 fix(display): remove 1px gap between mutually exclusive breakpoints (#21276)
updates breakpoint max to reduce the max width by 0.02px

closes #20993 closes #20743
2020-05-12 12:02:07 -04:00
Liam DeBeasi
85cc35ee91 fix(segment-button): screen readers now announce selected state properly (#21273) 2020-05-12 11:37:56 -04:00
Liam DeBeasi
7166a290cc fix(all): improve scroll assist reliability for below the fold inputs (#21206) 2020-05-11 15:44:59 -04:00
Liam DeBeasi
1e6f92377a fix(refresher): refresher completes even after switching to a new tab (#21236) 2020-05-11 15:21:26 -04:00
Liam DeBeasi
8e11ecc136 fix(picker): haptics now work properly (#21268) 2020-05-11 15:10:19 -04:00
Liam DeBeasi
1fbdb2255e fix(toggle): screen readers now announce toggle properly (#21168) 2020-05-08 11:59:04 -04:00
Liam DeBeasi
0c13f25bbb fix(header): do not error on collapsable header on devices that do not support IntersectionObserve (#21222) 2020-05-08 11:57:50 -04:00
Liam DeBeasi
9d0dcbbd31 fix(overlays): respect keyboardClose property when opening overlays (#21240) 2020-05-08 11:56:40 -04:00
Liam DeBeasi
f23f1cb37e fix(refresher): correctly select shadow root on older browsers (#21237) 2020-05-08 11:54:57 -04:00
Liam DeBeasi
f334e83a43 fix(md): do not hide page when swipe gesture is cancelled (#21247) 2020-05-08 10:16:42 -04:00
Liam DeBeasi
bb62023a0c fix(all): overlay components no longer display outline when focused (#21226) 2020-05-07 16:33:51 -04:00
Liam DeBeasi
cae389bd12 chore(): remove undocumented back button parts (#21223) 2020-05-07 16:32:18 -04:00
Liam DeBeasi
9308f0329c merge release-5.1.0
5.1.0
2020-04-30 18:25:49 -04:00
Liam DeBeasi
042686c7a4 5.1.0 2020-04-30 17:34:30 -04:00
Ely Lucas
43f9d24824 feat(react): Add IonTabsContext to add some missing element methods, closes #19935 (#21171) 2020-04-30 15:08:23 -06:00
Liam DeBeasi
ae5f1ddff0 feat(app): keyboard open and close events (#18478) 2020-04-30 16:07:44 -04:00
Liam DeBeasi
dea9248763 fix(all): gestures should use a passive listener (#21038) 2020-04-30 16:03:54 -04:00
Liam DeBeasi
eab3373213 fix(router): account for query string when pushing page (#21071) 2020-04-30 16:02:21 -04:00
Liam DeBeasi
bcf0fa17a9 docs(select): direct old controller links to component pages (#21167) 2020-04-30 12:10:08 -04:00
Liam DeBeasi
a261cb1f67 chore(select): make note about interfaceOptions and alert input/buttons clearer (#21166) 2020-04-30 11:12:54 -04:00
Brandy Carney
6bc62e1da5 docs(select): update headings to display properly in the docs (#21159) 2020-04-30 11:10:33 -04:00
Brandy Carney
04ace4c983 feat(toggle): improve customization with css vars and auto-adjust handle width and height (#21050)
- Updates Material Design toggle background & box-shadow to match spec
- Adds the following variables: --handle-box-shadow, --handle-height, --handle-max-height, --handle-transition, --handle-width, --handle-spacing
- Improves customization of toggle by inheriting properties where possible and auto-adjusting the handle height and position based on the width and height of the toggle

Closes #19868, closes #20474
2020-04-29 18:31:34 -04:00
Liam DeBeasi
83dcc7168a fix(refresher): properly calculate content dimensions in native ion-refresher (#21157) 2020-04-29 13:53:01 -04:00
Liam DeBeasi
c53b136dbe fix(all): use proper undefined check when using Haptics plugin (#21156)
fixes #21148
2020-04-29 13:13:28 -04:00
Liam DeBeasi
fc2be8d08b fix(overlays): focus overlay when presented (#20997)
fixes #19882, fixes #17126
2020-04-28 16:43:00 -04:00
Brandy Carney
c54911f451 docs(refresher): update usage to correct ionicons 5 icon (#21141)
closes ionic-team/ionic-docs#1263
2020-04-28 15:34:01 -04:00
Liam DeBeasi
fa9ddc91bc feat(all): add ability to eject from Ionic sanitizer (#20457)
resolves #18277
2020-04-27 16:03:39 -04:00
Liam DeBeasi
578ab93d29 feat(content): add parts support for background, scroll (#20929) 2020-04-27 16:01:39 -04:00
Liam DeBeasi
64144960b0 feat(item): add parts support for detail-icon (#20979) 2020-04-27 15:33:54 -04:00
Liam DeBeasi
3821c0463a feat(): add ability to continue processing hardware back button events (#20613)
fixes #17824
2020-04-27 12:58:37 -04:00
Liam DeBeasi
429edb053b feat(gesture): add option to run inside NgZone for Angular apps (#20685)
fixes #20529
2020-04-27 12:50:44 -04:00
Liam DeBeasi
15203de08b fix(angular): do not navigate to same tab if already active (#21085)
fixes #21074, fixes #19943
2020-04-27 12:19:23 -04:00
Liam DeBeasi
671802f9a2 fix(overlays): prevent accidental clicks when dismissing overlays (#21093)
fixes #21092
2020-04-27 11:33:23 -04:00
Liam DeBeasi
14c226ce75 fix(back-button): screen readers correctly announce the back button text (#21053)
fixes #21043
2020-04-27 11:31:32 -04:00
Liam DeBeasi
66e8e6404d fix(select): account for MutationObserver when performing SSR (#21068)
fixes #21063
2020-04-27 11:29:44 -04:00
Liam DeBeasi
4bd9134473 fix(modal): swipeToClose property is now reactive (#21073)
fixes #21072
2020-04-27 11:27:18 -04:00
EinfachHans
1b11ff7fb9 feat(back-button): add 'backButtonDefaultHref' property to Ionic Config (#20491)
closes #19305

Co-authored-by: Brandy Carney <brandy@ionic.io>
2020-04-27 10:57:43 -04:00
Liam DeBeasi
32ecdd6753 feat(gesture): add support for blurring active inputs on gesture start (#20638)
fixes #20588
2020-04-27 10:52:14 -04:00
Alex Currie-Clark
32ee040e3f fix(textarea): height is set correctly when using autoGrow in modals (#20971)
fixes #18993
2020-04-24 13:54:51 -04:00
Liam DeBeasi
1622d9bb3c feat(textarea): add support for inputmode and enterkeyhint (#21106) 2020-04-24 11:56:10 -04:00
Antoine
a75e8f34d6 fix(datetime): locale inputs are now reactive (#20826)
fixes #20367
2020-04-24 11:29:22 -04:00
Liam DeBeasi
e585a22ac9 chore(): change contributing link text (#21121) 2020-04-23 15:57:18 -04:00
Liam DeBeasi
395d7ec5a3 chore(): add extra lines for ionitron message (#21120) 2020-04-23 15:53:02 -04:00
Liam DeBeasi
71c7284ed5 chore(): update contributing docs, update ionitron bot (#21117) 2020-04-23 15:44:21 -04:00
Liam DeBeasi
0a33a095f1 chore(button): remove unreleased parts support (#21111) 2020-04-23 12:23:48 -04:00
Liam DeBeasi
50bc212d0b feat(menu): add parts support for backdrop, container (#20978) 2020-04-23 12:22:19 -04:00
Liam DeBeasi
76ca475734 feat(datetime): add parts support for placeholder, text (#20930) 2020-04-23 12:20:25 -04:00
Liam DeBeasi
63c75edd21 feat(img): add parts support for image (#20943) 2020-04-23 12:19:52 -04:00
Liam DeBeasi
d4b9151396 feat(checkbox): add parts support for container, mark (#20950) 2020-04-23 12:19:24 -04:00
Liam DeBeasi
228ca2b093 feat(radio): add parts support for container, mark (#20952) 2020-04-23 12:18:58 -04:00
Liam DeBeasi
ba20209604 feat(reorder): add parts support for icon (#20960) 2020-04-23 12:18:32 -04:00
Liam DeBeasi
619f67a00b feat(range): add parts support for bar, bar-active, knob, pin, tick, tick-active (#20961) 2020-04-23 12:18:04 -04:00
Liam DeBeasi
d2b772f19f feat(toggle): add parts support for handle, track (#20962) 2020-04-23 12:17:17 -04:00
Liam DeBeasi
15a603b397 fix(searchbar): screen readers correctly announce the cancel button text (#21049)
fixes #21013
2020-04-23 12:15:54 -04:00
Liam DeBeasi
30a1c89688 feat(select): add parts support for placeholder, icon, text (#21108) 2020-04-23 12:14:21 -04:00
Liam DeBeasi
63d8f6239c fix(loading): screen readers no longer incorrectly announce spinner (#21116)
fixes #21107
2020-04-23 12:07:43 -04:00
Brandy Carney
ae0a98924f chore(api): update api generator to include parts in the public API (#21110) 2020-04-22 15:41:44 -04:00
Liam DeBeasi
e442324753 fix(action-sheet): show correct cancel button background on dark mode (#21084)
fixes #21082
2020-04-22 14:27:18 -04:00
Liam DeBeasi
57b2a6b0cc docs(input): provide info regarding pattern used with date type (#21067)
fixes #21020
2020-04-17 10:09:21 -04:00
Liam DeBeasi
497380743d fix(md): do not display blank screen when using MD page transition and swipe gesture (#21058)
fixes #21056
2020-04-16 13:15:02 -04:00
Liam DeBeasi
6a167172ff chore(): update to swiper 5.3.7 (#21055) 2020-04-16 09:55:12 -04:00
Brandy Carney
fe175380d2 chore(github): remove weekly digest 2020-04-15 16:15:47 -04:00
Liam DeBeasi
e90683a713 feat(searchbar): add support for enterkeyhint (#21036)
fixes #21034
2020-04-15 15:08:43 -04:00
Liam DeBeasi
3efaf43821 feat(input): add support for enterkeyhint (#21035)
fixes #21034
2020-04-15 15:08:12 -04:00
Masanori Onoue
102a842bd2 fix(react): IonTabBar properly extends IonicReactProps (#21009)
fixes #21006
2020-04-10 13:09:06 -04:00
Ramez Atassi
7a21708d24 fix(split-pane): properly show border in rtl mode (#20995)
closes #20994

Co-authored-by: Ramez Atassi <ramez@al-salamah.net>
2020-04-08 15:27:24 -04:00
Liam DeBeasi
8a02b28efe fix(ios): properly animate content when navigating from a tabbed page (#20918)
fixes #20912
2020-04-08 15:16:10 -04:00
Liam DeBeasi
6f13b8c792 perf(all): improve scroll assist responsiveness (#20987)
resolves #20922
2020-04-07 12:19:58 -04:00
EinfachHans
acaa1d9ef7 feat(searchbar): add border-radius css variable (#20662)
fixes #17426
fixes #18247
2020-04-03 13:01:07 -04:00
Liam DeBeasi
5b9840508f feat(animation): add option to clean up old animation stylesheets (#20940)
fixes #20610
2020-04-03 09:28:41 -04:00
Liam DeBeasi
4e28445ecb feat(slides): update to swiper 5 (#20917)
fixes #20033
2020-04-02 16:19:28 -04:00
Liam DeBeasi
e23dec5eb9 fix(ios): account for nested tabs with page transition (#20955)
fixes #20948
2020-04-02 15:03:08 -04:00
Liam DeBeasi
e0f3c09bab chore(): update @stencil/core (#20945)
- also updated @stencil/sass
2020-04-01 17:45:26 -04:00
Mike Hartington
6fac5ff7fc docs(modal): remove navParams usage 2020-04-01 10:13:43 -04:00
Liam DeBeasi
3123a318b6 fix(slides): slides no longer breaks when Angular Ivy enabled (#20899)
fixes #20356
2020-03-31 13:07:25 -04:00
Liam DeBeasi
e5e02d4f88 feat(toast): add white-space variable for toast message (#20729)
fixes #20727
2020-03-30 12:02:46 -04:00
Liam DeBeasi
bd64509bae fix(modal): properly inherit border radius for modals on Safari (#20887)
fixes #20878
2020-03-30 11:56:46 -04:00
Liam DeBeasi
9b534bd43f chore(): generate correct change log (#20888) 2020-03-30 11:53:37 -04:00
Liam DeBeasi
8a161f053f merge release-5.0.7
Release 5.0.7
2020-03-26 11:48:51 -04:00
Liam DeBeasi
af1a6d6d6d 5.0.7 2020-03-26 11:30:32 -04:00
Liam DeBeasi
5816cf52a7 fix(modal): properly target card modal for iPadOS styles (#20884) 2020-03-26 11:19:47 -04:00
Liam DeBeasi
7c5661fcfb fix(modal): properly target card modal for iPadOS styles (#20884) 2020-03-26 11:19:23 -04:00
Liam DeBeasi
2b854ec2cc merge release-5.0.6
Release 5.0.6
2020-03-25 15:26:55 -04:00
Liam DeBeasi
3a269e27b6 merge release-5.0.6
Release 5.0.6
2020-03-25 15:26:00 -04:00
Liam DeBeasi
576da29ac6 5.0.6 2020-03-25 14:57:31 -04:00
Jakob Engelbrecht
6ed1c51321 fix(): only cascade mode from parent Ionic components (#20828)
fixes #20055
2020-03-25 14:39:38 -04:00
Liam DeBeasi
75bae403e9 fix(modal): respect card-style modal spec for iPadOS (#20750)
fixes #20700
2020-03-25 14:39:38 -04:00
Liam DeBeasi
321140ff73 fix(title): large title now inherits global color styling during nav transition (#20862) 2020-03-25 14:39:38 -04:00
Liam DeBeasi
d3d7de121b fix(): scroll assists now recognizes inputs on inner pages and modals (#20864)
fixes #20843
2020-03-25 14:39:38 -04:00
Liam DeBeasi
43fbd9d2f2 chore(): properly export ionic page transition functions (#20860) 2020-03-25 14:39:38 -04:00
Liam DeBeasi
dff3816c04 fix(modal): properly apply border radius on card-style modal (#20852)
fixes #20851
2020-03-25 14:39:38 -04:00
Liam DeBeasi
3bd6b5def2 fix(title): improve reliability of large title ios nav transition (#20861) 2020-03-25 14:38:46 -04:00
Liam DeBeasi
2707289b36 fix(content): apply --offset-top and --offset-bottom values correctly (#20790)
fixes #20735
2020-03-25 14:38:46 -04:00
Brandy Carney
d91e22d820 fix(item-divider): update design to match native iOS (#20854) 2020-03-25 14:38:45 -04:00
Manu MA
5a20f84aa4 refactor(): minor updates for next stencil version (#20787) 2020-03-25 14:38:45 -04:00
Liam DeBeasi
71f118201b fix(modal): properly remove safe area padding on card-modal (#20853)
fixes #20799
2020-03-25 14:38:45 -04:00
Hayden Braxton
8bd5bace73 fix(textarea): properly adjust auto-grow textarea in scrolled content (#19776)
fixes #19193
2020-03-25 14:38:45 -04:00
Hayden Braxton
a3fc77be91 fix(content): set overscroll-behavior based on the scroll direction (#20011)
resolves #20010
2020-03-25 14:38:08 -04:00
Liam DeBeasi
14ac8ae24c chore(): add show-modal in component not in animation (#20833)
resolves #20827
2020-03-25 14:38:08 -04:00
Liam DeBeasi
b1a87c8892 fix(refresher): properly dismiss refresher when completed synchronously (#20815)
fixes #20803
2020-03-25 14:38:08 -04:00
Liam DeBeasi
cdfd50b554 fix(segment): automatically expand width for scrollable segment buttons (#20763)
fixes #20566
2020-03-25 14:37:56 -04:00
Brandy Carney
7bc51911f6 fix(list): show bottom border on last item in a list followed by a list (#20798) 2020-03-25 14:37:50 -04:00
Liam DeBeasi
253cd96164 fix(modal): backdrop and box shadows no longer stack when opening multiple modals (#20801)
fixes #20800
2020-03-25 14:37:44 -04:00
Liam DeBeasi
12932dd202 fix(modal): backdrop is no longer tappable on card-style modal on smaller screens (#20802)
fixes #20783
2020-03-25 14:37:34 -04:00
Liam DeBeasi
f23ac44c9a fix(item-sliding): account for swipe to go back gesture when opening item-options (#20777)
fixes #20773
2020-03-25 14:37:22 -04:00
Brandy Carney
2d5d2515be fix(slides): check that mutation observer is defined for ssr (#20791) 2020-03-25 14:37:16 -04:00
Liam DeBeasi
e24060ecd9 fix(): properly scroll to input with scroll assist (#20742)
fixes #19589
2020-03-25 14:37:10 -04:00
Liam DeBeasi
0514b421ec docs(segment): clarify usage of scrollable segments (#20765)
resolves #20692
2020-03-25 14:37:03 -04:00
Liam DeBeasi
0897c3f9c2 fix(react): expose correct type for CreateAnimation (#20775)
fixes #20771
2020-03-25 14:36:58 -04:00
Liam DeBeasi
f2dbe1ff3b fix(angular): respect animation property for ion-router-outlet (#20767)
fixes #20764
2020-03-25 14:36:47 -04:00
Liam DeBeasi
2ece194a08 fix(angular): export Animation and Gesture related types (#20766) 2020-03-25 14:36:47 -04:00
Simon Hänisch
ab146c96ec fix(segment): scrollable segments only show scrollbar if they overflow (#20760)
fixes #20758
2020-03-25 14:36:24 -04:00
Jakob Engelbrecht
364a0a63da fix(): only cascade mode from parent Ionic components (#20828)
fixes #20055
2020-03-25 14:33:13 -04:00
Liam DeBeasi
ae7fe543fe fix(modal): respect card-style modal spec for iPadOS (#20750)
fixes #20700
2020-03-25 13:36:54 -04:00
Liam DeBeasi
794c3d4e96 fix(title): large title now inherits global color styling during nav transition (#20862) 2020-03-25 12:14:26 -04:00
Liam DeBeasi
e2cba41e32 fix(): scroll assists now recognizes inputs on inner pages and modals (#20864)
fixes #20843
2020-03-25 11:45:56 -04:00
Liam DeBeasi
f340cb64c8 chore(): properly export ionic page transition functions (#20860) 2020-03-25 11:43:02 -04:00
Liam DeBeasi
645578c66b fix(modal): properly apply border radius on card-style modal (#20852)
fixes #20851
2020-03-25 11:10:57 -04:00
Liam DeBeasi
df27793702 fix(title): improve reliability of large title ios nav transition (#20861) 2020-03-24 18:06:17 -04:00
Liam DeBeasi
8680c2e83b fix(content): apply --offset-top and --offset-bottom values correctly (#20790)
fixes #20735
2020-03-24 15:44:56 -04:00
Brandy Carney
8660e61b96 fix(item-divider): update design to match native iOS (#20854) 2020-03-24 12:03:41 -04:00
Manu MA
976e68da5b refactor(): minor updates for next stencil version (#20787) 2020-03-24 11:59:07 -04:00
Liam DeBeasi
7a4ddde5ce fix(modal): properly remove safe area padding on card-modal (#20853)
fixes #20799
2020-03-24 11:53:29 -04:00
Hayden Braxton
2796e9453f fix(textarea): properly adjust auto-grow textarea in scrolled content (#19776)
fixes #19193
2020-03-24 11:48:57 -04:00
Hayden Braxton
c68160ecd3 fix(content): set overscroll-behavior based on the scroll direction (#20011)
resolves #20010
2020-03-23 15:07:08 -04:00
Liam DeBeasi
879b90c3c4 chore(): add show-modal in component not in animation (#20833)
resolves #20827
2020-03-20 12:23:09 -04:00
Liam DeBeasi
dae1ce8526 fix(refresher): properly dismiss refresher when completed synchronously (#20815)
fixes #20803
2020-03-19 09:52:49 -04:00
Liam DeBeasi
f86c82639f fix(segment): automatically expand width for scrollable segment buttons (#20763)
fixes #20566
2020-03-18 16:14:06 -04:00
Brandy Carney
de28bd3b79 fix(list): show bottom border on last item in a list followed by a list (#20798) 2020-03-18 15:43:36 -04:00
Liam DeBeasi
0b134dfebf fix(modal): backdrop and box shadows no longer stack when opening multiple modals (#20801)
fixes #20800
2020-03-18 13:44:11 -04:00
Liam DeBeasi
8b6536098a fix(modal): backdrop is no longer tappable on card-style modal on smaller screens (#20802)
fixes #20783
2020-03-18 13:20:14 -04:00
Walter S
39e6c8f55b feat(angular): support multi-app for ng-add schematic (#20768)
* chore(angular): Add missing argument type information.

* chore(angular): Add missing semicolon.

* fix(angular): Properly detect the Angular project name for multi-app repositories.

* fix(angular): Fix generated angular.json when using ng-add  in multi-app repositories.

* chore(angular): Improve reported warnings when using ng-add with invalid workspace configuration.
2020-03-18 12:46:14 -04:00
Liam DeBeasi
3514dd8362 fix(item-sliding): account for swipe to go back gesture when opening item-options (#20777)
fixes #20773
2020-03-17 11:00:38 -04:00
Brandy Carney
e2df046eff fix(slides): check that mutation observer is defined for ssr (#20791) 2020-03-16 17:36:58 -04:00
Liam DeBeasi
0e91c6c502 fix(): properly scroll to input with scroll assist (#20742)
fixes #19589
2020-03-16 15:38:11 -04:00
Liam DeBeasi
cfc6773cb9 docs(segment): clarify usage of scrollable segments (#20765)
resolves #20692
2020-03-16 09:51:13 -04:00
Liam DeBeasi
2982c95993 fix(react): expose correct type for CreateAnimation (#20775)
fixes #20771
2020-03-13 10:10:38 -04:00
Liam DeBeasi
bfb78abda0 fix(angular): respect animation property for ion-router-outlet (#20767)
fixes #20764
2020-03-12 15:26:24 -04:00
Liam DeBeasi
5049d19917 fix(angular): export Animation and Gesture related types (#20766) 2020-03-12 14:56:36 -04:00
Simon Hänisch
13e4e5b03d fix(segment): scrollable segments only show scrollbar if they overflow (#20760)
fixes #20758
2020-03-12 11:01:42 -04:00
Liam DeBeasi
ac229528eb merge release-5.0.5
Release 5.0.5
2020-03-11 14:30:12 -04:00
Liam DeBeasi
f9f3095eb4 merge release-5.0.5
5.0.5
2020-03-11 14:29:29 -04:00
Liam DeBeasi
572f7b6934 5.0.5 2020-03-11 13:07:09 -04:00
Simon Hänisch
4d34ce6a31 fix(label): text overflow for slotted headings (#20690)
fixes #17087
2020-03-11 12:42:46 -04:00
Brandy Carney
d53595eb16 fix(item): apply proper margin left for slotted icon in RTL (#20684)
fixes #20653
2020-03-11 11:52:01 -04:00
Adam Bradley
a1bf2f5b8f chore(ionicons): bump ionicons version (#20704) 2020-03-11 11:36:04 -04:00
Brandy Carney
7ecde36f9d fix(button): allow overflow to be overridden by the CSS variable (#20738)
fixes #20726
2020-03-11 11:35:26 -04:00
Liam DeBeasi
87a27216d0 fix(header): collapsible header now works when navigating quickly (#20728)
fixes #20725
2020-03-11 10:58:26 -04:00
Liam DeBeasi
f6c3ba7e5a fix(header): collapsable header should default to using content background (#20736)
fixes #20691
2020-03-11 10:52:33 -04:00
Liam DeBeasi
f796074f33 chore(): set @nguniversal/builders dependency to exact version (#20734) 2020-03-10 11:22:36 -04:00
Liam DeBeasi
7d260b96a7 fix(modal): swipeable modal now works in firefox (#20714)
fixes #20706
2020-03-06 13:19:48 -05:00
Liam DeBeasi
22d5256810 fix(modal): leave animation transitions modal completely out of viewport on ipad (#20702)
fixes #20697
2020-03-06 10:12:21 -05:00
Liam DeBeasi
b6c2a77deb fix(overlays): prevent accidental dismiss of overlays when tapping screen twice (#20683)
fixes #20608
2020-03-06 10:11:20 -05:00
Liam DeBeasi
ec4878ac08 fix(ios): large title animation now works properly in a modal (#20703)
fixes #20696
2020-03-06 10:09:39 -05:00
Liam DeBeasi
314dbb1a4d fix(segment): allow routerLink to work on segment buttons (#20682)
fixes #20678
2020-03-05 12:38:51 -05:00
Liam DeBeasi
44993b7987 fix(segment): iOS mode segment now works on older Android devices (#20673)
fixes #20648
2020-03-05 11:56:54 -05:00
Mike Hartington
f64b1420ae fix(): exclude components from ssr (#20674) 2020-03-02 14:46:03 -05:00
Ni Tianzhen
21774612d8 fix(datetime): max property now works when hour, minute, or second set to 0 (#20665)
fixes #20652
2020-03-02 11:23:43 -05:00
Brandy Carney
a360ea6d19 merge release-5.0.4 2020-02-27 18:05:03 -05:00
Brandy Carney
36f98eda1b merge release-5.0.4 2020-02-27 18:04:44 -05:00
Brandy Carney
b11ae5da67 5.0.4 2020-02-27 17:32:17 -05:00
Mike Hartington
dff1ffd124 chore(): bump stencil version 2020-02-27 17:09:55 -05:00
Brandy Carney
c1d7bf229d fix(buttons): use proper button colors based on CSS variables when inside of a toolbar (#20633) 2020-02-27 16:22:39 -05:00
Liam DeBeasi
0e0e401d86 fix(animation): reset all temporary flags when interrupting an animation (#20627)
fixes #20602
2020-02-27 11:17:43 -05:00
Beeno Tung
b84822e674 docs(readme): update npm version on CDN example to latest (#20599) 2020-02-26 19:56:29 -05:00
Liam DeBeasi
8e71317de4 merge release-5.0.3
5.0.3
2020-02-26 18:52:13 -05:00
Liam DeBeasi
5a87a728e1 5.0.3 2020-02-26 16:00:07 -05:00
Liam DeBeasi
fe8d74d08c fix(menu): allow ssr to work properly with hardware back button updates (#20629) 2020-02-26 15:54:50 -05:00
Liam DeBeasi
11d8c14d72 merge release-5.0.2
5.0.2
2020-02-26 13:39:08 -05:00
Liam DeBeasi
686325e0ec 5.0.2 2020-02-26 12:21:05 -05:00
Brandy Carney
926ac3fb47 fix(select): add icon-inner & placeholder part (#20605)
- adds custom test for styling the select parts
- set opacity on icon container
- align items center, this makes the select text align vertically with the icon when used standalone even when changing the font size of the text
2020-02-26 12:08:03 -05:00
Brandy Carney
20af652a1b fix(slides): set height to 100% for vertical slides (#20603)
fixes #17341
2020-02-26 12:06:37 -05:00
Elvis Graholskis
e3e5c69681 fix(refresher): ensure that translate is cleaned up to avoid stacking context (#20621)
fixes #17949
2020-02-26 11:56:10 -05:00
Liam DeBeasi
fcf97465f5 docs(segment-button): update usage for v5 (#20612) 2020-02-25 10:30:04 -05:00
Liam DeBeasi
b5310effe3 fix(modal): card style modal now adds appropriate contrast (#20604) 2020-02-24 15:30:56 -05:00
Liam DeBeasi
0224bed0c9 fix(segment): segment functions properly on android 5 (#20554)
fixes #20466
2020-02-24 13:41:49 -05:00
Brandy Carney
cefb08fe32 chore(release): update to latest octokit and usage (#20601)
- rename all references of `tag` to either `gitTag` or `npmTag` based on what they contain since this was confusing throughout
- add the code to publish to git as a prerelease if the npm tag is `next`
- log the version when asking if the npm tag is correct
2020-02-24 11:46:09 -05:00
Liam DeBeasi
71875417f2 fix(ios): large title transition works properly in tabbed applications (#20555)
fixes #20482
2020-02-24 11:38:50 -05:00
Liam DeBeasi
6b2a929cd7 fix(menu): hardware back button now dismisses side menu if open (#20558)
fixes #20559
2020-02-24 11:37:51 -05:00
Liam DeBeasi
8d3ce8d29c fix(modal): allow swipe to close animation to be overridden (#20585)
fixes #20577
2020-02-24 11:22:07 -05:00
Liam DeBeasi
3a2d82814b fix(modal): swipeable modal styles only apply to ios (#20571)
fixes #20569
2020-02-24 11:14:43 -05:00
Liam DeBeasi
ad6fac83cb fix(modal): swipeable modal background should be able to be overridden (#20584)
fixes #20572
2020-02-21 10:05:31 -05:00
Ely Lucas
714ecaae65 docs(react): updating icon usages 2020-02-20 16:08:23 -07:00
Ely Lucas
972e361bdc docs(react): updating react input usages with binding examples (#20557) 2020-02-19 17:49:53 -07:00
Liam DeBeasi
fa9b78e775 merge release-5.0.1
5.0.1
2020-02-19 13:55:15 -05:00
Liam DeBeasi
a826b6dff5 5.0.1 2020-02-19 13:19:39 -05:00
Brandy Carney
34f8576b95 fix(tab-bar): update ios icon and label design to match native (#20548) 2020-02-19 11:32:45 -05:00
Brandy Carney
59fa340650 fix(button): reduce font size of icon only button in toolbar on iOS (#20547) 2020-02-19 11:31:42 -05:00
Liam DeBeasi
06b828b4ff fix(segment): inner div no longer interferes with click events (#20522)
fixes #20381
2020-02-19 09:40:10 -05:00
Liam DeBeasi
3252c2f8dc fix(menu): swipe gesture should not open menu when a modal is displayed (#20546)
fixes #20467
2020-02-19 08:57:42 -05:00
Niklas Merz
800a9339bc docs(item-sliding): fix link to list (#20519) 2020-02-18 15:37:32 -05:00
Liam DeBeasi
dd32a5e278 fix(ios): clamp out of bounds values for swipe to go back (#20540)
fixes #20505
2020-02-18 15:14:30 -05:00
Brandy Carney
ce41d90715 docs(breaking): rename segment events heading to remove conflict with main events 2020-02-18 15:13:52 -05:00
Liam DeBeasi
4d50064764 fix(segment): only emit ionChange when user releases pointer from screen (#20495)
fixes #20500
fixes #20257
2020-02-18 15:11:28 -05:00
Liam DeBeasi
7a461c59c5 fix(segment): do not show ripple effect if disabled via config (#20542)
fixes #20533
2020-02-18 14:02:34 -05:00
Liam DeBeasi
9b5854d797 fix(segment): border radius applies to indicator on ios (#20541)
fixes #20539
2020-02-18 13:58:25 -05:00
Brandy Carney
e42c85d641 fix(fab): show close icon on hover, focused, activated (#20497)
also fixes the fab so users don't have to set color for each state
2020-02-18 13:55:31 -05:00
Ely Lucas
45d03baf98 fix(react): update paths of tab buttons when href changes in ion buttons, fixes #20321 (#20480) 2020-02-14 13:36:30 -07:00
Ely Lucas
82670fe4d0 fix(react): icons with MD set should work in browser (#20463) 2020-02-14 13:36:30 -07:00
Ely Lucas
c0aadd6007 fix(react): Do a better job matching up route to sync, fixes #20363 (#20446) 2020-02-14 13:36:30 -07:00
Ely Lucas
b6fbe98812 fix(react): dont remove pages when navigating between tabs, fixes #20398 (#20431) 2020-02-14 13:36:30 -07:00
Brandy Carney
27a219874c docs(grid): update usage from attributes to classes (#20492)
closes ionic-team/ionic-docs#1230
2020-02-14 12:45:46 -05:00
Liam DeBeasi
c4fb31403e fix(fab): add close icon to internal icons for react (#20490)
fixes #20489
2020-02-14 10:21:14 -05:00
Liam DeBeasi
89bf08b627 fix(input): do not clear input if "Enter" key pressed (#20462)
fixes #20442
2020-02-14 09:27:05 -05:00
Liam DeBeasi
abf594aa61 fix(modal): presenting multiple card-style modals now adds border radius properly (#20476)
fixes #20475
2020-02-13 15:57:30 -05:00
Liam DeBeasi
86ab77a6e2 fix(modal): prevent card style modal styles from being overridden (#20470)
fixes #20469
2020-02-13 10:12:28 -05:00
Brandy Carney
c16de96633 fix(card): inherit background in inner button (#20461)
fixes #20458
2020-02-12 16:25:27 -05:00
Liam DeBeasi
4d6e15ab18 fix(searchbar): properly align placeholder (#20460)
fixes #20456
2020-02-12 16:21:08 -05:00
Brandy Carney
f61b671844 docs(changelog): remove save-exact flag 2020-02-12 15:39:34 -05:00
Liam DeBeasi
99d6069ecb docs(): remove mention of controllers (#20444)
resolves #20453
2020-02-12 09:55:58 -05:00
Brandy Carney
e3364f283f merge release-5.0.0 2020-02-11 12:31:15 -05:00
Brandy Carney
054223b79c merge release-5.0.0 2020-02-11 12:30:24 -05:00
Brandy Carney
6bfdaeed86 5.0.0 2020-02-11 11:42:30 -05:00
Liam DeBeasi
0b182a9c66 merge release-5.0.0-rc.5
5.0.0-rc.5
2020-02-11 11:05:26 -05:00
Brandy Carney
d21b5df523 chore(scripts): include v4-lts as a choice tag for release 2020-02-11 10:53:19 -05:00
Liam DeBeasi
0daca31f38 5.0.0-rc.5 2020-02-11 09:26:30 -05:00
hiepxanh
fd9c7a9601 fix(schematic): correct path for angular project (#20436)
fixes #20435
2020-02-11 09:04:07 -05:00
Liam DeBeasi
61f0faccdb merge release-5.0.0-rc.4 2020-02-10 18:41:06 -05:00
Liam DeBeasi
f303acc99a 5.0.0-rc.4 2020-02-10 16:29:34 -05:00
Liam DeBeasi
3d6f287d87 fix(label): remove subpixel font-size to prevent visual glitches (#20415)
resolves #20407
2020-02-10 09:11:12 -05:00
Ely Lucas
3403574f31 chore(react): update to ionicons v5 final (#20414) 2020-02-07 12:16:23 -07:00
Liam DeBeasi
a6764c4724 fix(item): remove unneeded box-shadow CSS variable (#20412)
resolves #20392
2020-02-07 13:35:21 -05:00
Liam DeBeasi
aa663b76cc chore(datetime): run build (#20411) 2020-02-07 12:27:01 -05:00
Brandy Carney
e8886e98f1 fix(segment): add activated class directly to segment button (#20400)
this gets around a bug with Safari where the ::slotted css selector was not working properly
2020-02-07 12:13:09 -05:00
Liam DeBeasi
fd1b44a40b fix(content): only emit scroll events if enabled (#20401) 2020-02-07 11:53:11 -05:00
Brandy Carney
916f6670a0 chore(ionicons): update to official 5.0.0 release (#20399) 2020-02-06 16:38:29 -05:00
Liam DeBeasi
11d39457d5 fix(header): backdrop filter no longer distorts content with collapsible header (#20388)
fixes #20385
2020-02-06 09:41:25 -05:00
Liam DeBeasi
cfcdd97cc0 merge release-5.0.0-rc.3 (#20387) 2020-02-05 14:28:06 -05:00
516 changed files with 29753 additions and 12088 deletions

View File

@@ -4,6 +4,7 @@ Thanks for your interest in contributing to the Ionic Framework! :tada:
- [Contributing Etiquette](#contributing-etiquette)
- [Creating an Issue](#creating-an-issue)
* [Creating a Good Code Reproduction](#creating-a-good-code-reproduction)
- [Creating a Pull Request](#creating-a-pull-request)
* [Setup](#setup)
* [Core](#core)
@@ -40,13 +41,40 @@ Please see our [Contributor Code of Conduct](https://github.com/ionic-team/ionic
* The issue list of this repository is exclusively for bug reports and feature requests. Non-conforming issues will be closed immediately.
* Issues with no clear steps to reproduce will not be triaged. If an issue is labeled with "needs: reply" and receives no further replies from the author of the issue for more than 30 days, it will be closed.
* Issues with no clear steps to reproduce will not be triaged. If an issue is labeled with "needs: reply" and receives no further replies from the author of the issue for more than 14 days, it will be closed.
* If you think you have found a bug, or have a new feature idea, please start by making sure it hasn't already been [reported](https://github.com/ionic-team/ionic/issues?utf8=%E2%9C%93&q=is%3Aissue). You can search through existing issues to see if there is a similar one reported. Include closed issues as it may have been closed with a solution.
* Next, [create a new issue](https://github.com/ionic-team/ionic/issues/new/choose) that thoroughly explains the problem. Please fill out the populated issue form before submitting the issue.
## Creating a Good Code Reproduction
### What is a Code Reproduction?
A code reproduction is a small application that is built to demonstrate a particular issue. The code reproduction should contain the minimum amount of code needed to recreate the issue and should focus on a single issue.
### Why Should You Create a Reproduction?
A code reproduction of the issue you are experiencing helps us better isolate the cause of the problem. This is an important first step to getting any bug fixed!
Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed. In other words, creating a code reproduction of the issue helps us help you.
### How to Create a Reproduction
* Create a new Ionic application using one of our starter templates. The `blank` starter application is a great choice for this. You can create one using the following Ionic CLI command: `ionic start myApp blank`
* Add the minimum amount of code needed to recreate the issue you are experiencing. Do not include anything that is not required to reproduce the issue. This includes any 3rd party plugins you have installed.
* Publish the application on GitHub and include a link to it when [creating an issue](#creating-an-issue).
* Be sure to include steps to reproduce the issue. These steps should be clear and easy to follow.
### Benefits of Creating a Reproduction
* **Uses the latest version of Ionic:** By creating a new Ionic application, you are ensuring that you are testing against the latest version of the framework. Sometimes the issues you are experiencing have already been resolved in a newer version of the framework!
* **Minimal surface area:** By removing code that is not needed in order to reproduce the issue, it makes it easier to identify the cause of the issue.
* **No secret code needed:** Creating a minimal reproduction of the issue prevents you from having to publish any proprietary code used in your project.
* **Get help fixing the issue:** If we can reliably reproduce an issue, there is a good chance we will be able to address it.
## Creating a Pull Request
* We appreciate you taking the time to contribute! Before submitting a pull request, we ask that you please [create an issue](#creating-an-issue) that explains the bug or feature request and let us know that you plan on creating a pull request for it. If an issue already exists, please comment on that issue letting us know you would like to submit a pull request for it. This helps us to keep track of the pull request and make sure there isn't duplicated effort.

View File

@@ -21,6 +21,16 @@ comment:
Thank you!
- label: "ionitron: needs reproduction"
message: >
Thanks for the issue! This issue has been labeled as `needs reproduction`. This label
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.
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).
dryRun: false
closeAndLock:
@@ -65,8 +75,10 @@ stale:
days: 365
maxIssuesPerRun: 100
exemptLabels:
- good first issue
- triage
- "good first issue"
- "triage"
- "type: bug"
- "type: feature request"
exemptAssigned: true
exemptProjects: true
exemptMilestones: true
@@ -83,7 +95,7 @@ stale:
dryRun: false
noReply:
days: 30
days: 14
maxIssuesPerRun: 100
label: "needs: reply"
responseLabel: triage
@@ -95,6 +107,24 @@ noReply:
template is fully filled out.
Thank you for using Ionic!
close: true
lock: true
dryRun: false
noReproduction:
days: 14
maxIssuesPerRun: 100
label: "ionitron: needs reproduction"
responseLabel: triage
exemptProjects: true
exemptMilestones: true
message: >
Thanks for the issue! This issue is being closed due to the lack of a code reproduction. If this is still
an issue with the latest version of Ionic, please create a new issue and ensure the
template is fully filled out.
Thank you for using Ionic!
close: true
lock: true

View File

@@ -1,7 +0,0 @@
# Configuration for weekly-digest - https://github.com/apps/weekly-digest
publishDay: wed
canPublishIssues: true
canPublishPullRequests: true
canPublishContributors: true
canPublishStargazers: true
canPublishCommits: true

View File

@@ -4,7 +4,7 @@ const execa = require('execa');
const inquirer = require('inquirer');
const Listr = require('listr');
const semver = require('semver');
const tc = require('turbocolor');
const { bold, cyan, dim } = require('colorette');
const rootDir = path.join(__dirname, '../');
@@ -36,13 +36,13 @@ function projectPath(project) {
return path.join(rootDir, project);
}
async function askTag() {
async function askNpmTag(version) {
const prompts = [
{
type: 'list',
name: 'tag',
name: 'npmTag',
message: 'Select npm tag or specify a new tag',
choices: ['latest', 'next']
choices: ['latest', 'next', 'v4-lts']
.concat([
new inquirer.Separator(),
{
@@ -55,13 +55,13 @@ async function askTag() {
type: 'confirm',
name: 'confirm',
message: answers => {
return `Will publish to ${tc.cyan(answers.tag)}. Continue?`;
return `Will publish ${cyan(version)} to ${cyan(answers.npmTag)}. Continue?`;
}
}
];
const { tag, confirm } = await inquirer.prompt(prompts);
return { tag, confirm };
const { npmTag, confirm } = await inquirer.prompt(prompts);
return { npmTag, confirm };
}
function checkGit(tasks) {
@@ -192,7 +192,7 @@ function preparePackage(tasks, package, version, install) {
// Add project tasks
tasks.push({
title: `Prepare ${tc.bold(pkg.name)}`,
title: `Prepare ${bold(pkg.name)}`,
task: () => new Listr(projectTasks)
});
}
@@ -234,7 +234,7 @@ function prepareDevPackage(tasks, package, version) {
// Add project tasks
tasks.push({
title: `Prepare dev build: ${tc.bold(pkg.name)}`,
title: `Prepare dev build: ${bold(pkg.name)}`,
task: () => new Listr(projectTasks)
});
}
@@ -244,7 +244,7 @@ function updatePackageVersions(tasks, packages, version) {
updatePackageVersion(tasks, package, version);
tasks.push({
title: `${package} update @ionic/core dependency, if present ${tc.dim(`(${version})`)}`,
title: `${package} update @ionic/core dependency, if present ${dim(`(${version})`)}`,
task: async () => {
if (package !== 'core') {
const pkg = readPkg(package);
@@ -261,7 +261,7 @@ function updatePackageVersions(tasks, packages, version) {
updatePackageVersion(tasks, distPackage, version);
tasks.push({
title: `${package} update @ionic/core dependency, if present ${tc.dim(`(${version})`)}`,
title: `${package} update @ionic/core dependency, if present ${dim(`(${version})`)}`,
task: async () => {
const pkg = readPkg(distPackage);
updateDependency(pkg, '@ionic/core', version);
@@ -272,7 +272,7 @@ function updatePackageVersions(tasks, packages, version) {
if (package === 'packages/react-router') {
tasks.push({
title: `${package} update @ionic/react dependency, if present ${tc.dim(`(${version})`)}`,
title: `${package} update @ionic/react dependency, if present ${dim(`(${version})`)}`,
task: async () => {
const pkg = readPkg(package);
updateDependency(pkg, '@ionic/react', version);
@@ -287,7 +287,7 @@ function updatePackageVersion(tasks, package, version) {
const projectRoot = projectPath(package);
tasks.push({
title: `${package}: update package.json ${tc.dim(`(${version})`)}`,
title: `${package}: update package.json ${dim(`(${version})`)}`,
task: async () => {
await execa('npm', ['version', version], { cwd: projectRoot });
}
@@ -310,7 +310,7 @@ function copyPackageToDist(tasks, packages) {
});
}
function publishPackages(tasks, packages, version, tag = 'latest') {
function publishPackages(tasks, packages, version, npmTag = 'latest') {
// first verify version
packages.forEach(package => {
if (package === 'core') {
@@ -338,9 +338,9 @@ function publishPackages(tasks, packages, version, tag = 'latest') {
}
tasks.push({
title: `${package}: publish to ${tag} tag`,
title: `${package}: publish to ${npmTag} tag`,
task: async () => {
await execa('npm', ['publish', '--tag', tag], { cwd: projectRoot });
await execa('npm', ['publish', '--tag', npmTag], { cwd: projectRoot });
}
});
});
@@ -375,7 +375,7 @@ function copyCDNLoader(tasks, version) {
module.exports = {
checkTestDist,
checkGit,
askTag,
askNpmTag,
isValidVersion,
isVersionGreater,
copyCDNLoader,

View File

@@ -2,7 +2,7 @@
* Deploy script adopted from https://github.com/sindresorhus/np
* MIT License (c) Sindre Sorhus (sindresorhus.com)
*/
const tc = require('turbocolor');
const { cyan, dim, red, reset } = require('colorette');
const execa = require('execa');
const inquirer = require('inquirer');
const Listr = require('listr');
@@ -34,7 +34,7 @@ async function main() {
console.log(` npm run release\n`);
} catch(err) {
console.log('\n', tc.red(err), '\n');
console.log('\n', red(err), '\n');
process.exit(1);
}
}
@@ -84,7 +84,7 @@ async function askVersion() {
type: 'confirm',
name: 'confirm',
message: answers => {
return `Will bump from ${tc.cyan(oldVersion)} to ${tc.cyan(answers.version)}. Continue?`;
return `Will bump from ${cyan(oldVersion)} to ${cyan(answers.version)}. Continue?`;
}
}
];
@@ -131,7 +131,7 @@ async function preparePackages(packages, version, install) {
function validateGit(tasks, version) {
tasks.push(
{
title: `Validate git tag ${tc.dim(`(v${version})`)}`,
title: `Validate git tag ${dim(`(v${version})`)}`,
task: () => execa('git', ['fetch'])
.then(() => {
return execa.stdout('npm', ['config', 'get', 'tag-version-prefix']);
@@ -198,17 +198,17 @@ function prettyVersionDiff(oldVersion, inc) {
for (let i = 0; i < newVersion.length; i++) {
if ((newVersion[i] !== oldVersion[i] && !firstVersionChange)) {
output.push(`${tc.dim.cyan(newVersion[i])}`);
output.push(`${dim(cyan(newVersion[i]))}`);
firstVersionChange = true;
} else if (newVersion[i].indexOf('-') >= 1) {
let preVersion = [];
preVersion = newVersion[i].split('-');
output.push(`${tc.dim.cyan(`${preVersion[0]}-${preVersion[1]}`)}`);
output.push(`${dim(cyan(`${preVersion[0]}-${preVersion[1]}`))}`);
} else {
output.push(tc.reset.dim(newVersion[i]));
output.push(reset(dim(newVersion[i])));
}
}
return output.join(tc.reset.dim('.'));
return output.join(reset(dim('.')));
}
main();

View File

@@ -1,4 +1,4 @@
const tc = require('turbocolor');
const { cyan, red } = require('colorette');
const semver = require('semver');
const execa = require('execa');
const inquirer = require('inquirer');
@@ -47,7 +47,7 @@ async function main() {
console.log(`\nionic ${devVersion} published!! 🎉\n`);
} catch (err) {
console.log('\n', tc.red(err), '\n');
console.log('\n', red(err), '\n');
process.exit(1);
}
@@ -64,7 +64,7 @@ async function askDevVersion(devVersion) {
name: 'confirm',
value: true,
message: () => {
return `Publish the dev build ${tc.cyan(devVersion)}?`;
return `Publish the dev build ${cyan(devVersion)}?`;
}
}
];

View File

@@ -2,11 +2,11 @@
* Deploy script adopted from https://github.com/sindresorhus/np
* MIT License (c) Sindre Sorhus (sindresorhus.com)
*/
const tc = require('turbocolor');
const { cyan, dim, green, red, yellow } = require('colorette');
const execa = require('execa');
const Listr = require('listr');
const path = require('path');
const octokit = require('@octokit/rest')()
const { Octokit } = require('@octokit/rest');
const common = require('./common');
const fs = require('fs-extra');
@@ -28,7 +28,7 @@ async function main() {
// repo must be clean
common.checkGit(tasks);
const { tag, confirm } = await common.askTag();
const { npmTag, confirm } = await common.askNpmTag(version);
if (!confirm) {
return;
@@ -36,10 +36,10 @@ async function main() {
if(!dryRun) {
// publish each package in NPM
common.publishPackages(tasks, common.packages, version, tag);
common.publishPackages(tasks, common.packages, version, npmTag);
// push tag to git remote
publishGit(tasks, version, changelog);
publishGit(tasks, version, changelog, npmTag);
}
const listr = new Listr(tasks);
@@ -48,14 +48,14 @@ async function main() {
// Dry run doesn't publish to npm or git
if (dryRun) {
console.log(`
\n${tc.yellow('Did not publish. Remove the "--dry-run" flag to publish:')}\n${tc.green(version)} to ${tc.cyan(tag)}\n
\n${yellow('Did not publish. Remove the "--dry-run" flag to publish:')}\n${green(version)} to ${cyan(npmTag)}\n
`);
} else {
console.log(`\nionic ${version} published to ${tag}!! 🎉\n`);
console.log(`\nionic ${version} published to ${npmTag}!! 🎉\n`);
}
} catch (err) {
console.log('\n', tc.red(err), '\n');
console.log('\n', red(err), '\n');
process.exit(1);
}
}
@@ -70,13 +70,13 @@ function checkProductionRelease() {
}
}
function publishGit(tasks, version, changelog) {
const tag = `v${version}`;
function publishGit(tasks, version, changelog, npmTag) {
const gitTag = `v${version}`;
tasks.push(
{
title: `Tag latest commit ${tc.dim(`(${tag})`)}`,
task: () => execa('git', ['tag', `${tag}`], { cwd: common.rootDir })
title: `Tag latest commit ${dim(`(${gitTag})`)}`,
task: () => execa('git', ['tag', `${gitTag}`], { cwd: common.rootDir })
},
{
title: 'Push branches to remote',
@@ -88,7 +88,7 @@ function publishGit(tasks, version, changelog) {
},
{
title: 'Publish Github release',
task: () => publishGithub(version, tag, changelog)
task: () => publishGithub(version, gitTag, changelog, npmTag)
}
);
}
@@ -100,7 +100,7 @@ function findChangelog() {
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.startsWith('# [')) {
if (line.startsWith('## [') || line.startsWith('# [')) {
if (start === -1) {
start = i + 1;
} else {
@@ -116,10 +116,12 @@ function findChangelog() {
return lines.slice(start, end).join('\n').trim();
}
async function publishGithub(version, tag, changelog) {
octokit.authenticate({
type: 'oauth',
token: process.env.GH_TOKEN
async function publishGithub(version, gitTag, changelog, npmTag) {
// If the npm tag is next then publish as a prerelease
const prerelease = npmTag === 'next' ? true : false;
const octokit = new Octokit({
auth: process.env.GH_TOKEN
});
let branch = await execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']);
@@ -132,9 +134,10 @@ async function publishGithub(version, tag, changelog) {
owner: 'ionic-team',
repo: 'ionic',
target_commitish: branch,
tag_name: tag,
tag_name: gitTag,
name: version,
body: changelog,
prerelease: prerelease
});
}

View File

@@ -418,7 +418,7 @@ The `inputmode` property for `ion-searchbar` now defaults to `undefined`. To get
Segment was completely revamped to use the new iOS design including an all new gesture that applies for both Material Design and iOS. Due to these changes, some breaking changes were inevitably introduced in order to support the new design.
##### Events
##### Renamed Events
`ion-segment` no longer emits an `ionSelect` event. Developers should listen for an `ionChange` event to be emitted on `ion-segment` instead.

View File

@@ -1,3 +1,273 @@
## [5.1.1](https://github.com/ionic-team/ionic/compare/v5.1.0...v5.1.1) (2020-05-13)
### Bug Fixes
* **all:** improve scroll assist reliability for below the fold inputs ([#21206](https://github.com/ionic-team/ionic/issues/21206)) ([7166a29](https://github.com/ionic-team/ionic/commit/7166a290cc1dd728e5bab2f7e39b8d41954e3808))
* **all:** overlay components no longer display outline when focused ([#21226](https://github.com/ionic-team/ionic/issues/21226)) ([bb62023](https://github.com/ionic-team/ionic/commit/bb62023a0cdc5a64e956766c7d1704797fc8c9ae))
* **display:** remove 1px gap between mutually exclusive breakpoints ([#21276](https://github.com/ionic-team/ionic/issues/21276)) ([703ef5c](https://github.com/ionic-team/ionic/commit/703ef5c99284f1e2b8d63c3af411c945dc756e20)), closes [#20993](https://github.com/ionic-team/ionic/issues/20993) [#20743](https://github.com/ionic-team/ionic/issues/20743)
* **header:** do not error on collapsible header on devices that do not support IntersectionObserve ([#21222](https://github.com/ionic-team/ionic/issues/21222)) ([0c13f25](https://github.com/ionic-team/ionic/commit/0c13f25bbb4d4674e76cd19b098900f698e7146e))
* **input:** check for tabindex and pass it properly to native input ([#21170](https://github.com/ionic-team/ionic/issues/21170)) ([dd4cb70](https://github.com/ionic-team/ionic/commit/dd4cb706ffeebc2069645ea03f0e7a96d6b14d43)), closes [#17515](https://github.com/ionic-team/ionic/issues/17515)
* **ios:** position page transition shadow properly under footer ([#21095](https://github.com/ionic-team/ionic/issues/21095)) ([50678c0](https://github.com/ionic-team/ionic/commit/50678c03c9829a87408633dabd77b21da1650a84))
* **md:** do not hide page when swipe gesture is cancelled ([#21247](https://github.com/ionic-team/ionic/issues/21247)) ([f334e83](https://github.com/ionic-team/ionic/commit/f334e83a43f855ac1e36eaf73954df6ee27a03af))
* **overlays:** respect keyboardClose property when opening overlays ([#21240](https://github.com/ionic-team/ionic/issues/21240)) ([9d0dcbb](https://github.com/ionic-team/ionic/commit/9d0dcbbd31fc34ad8952eacb9864ad1b31636113))
* **picker:** haptics now work properly ([#21268](https://github.com/ionic-team/ionic/issues/21268)) ([8e11ecc](https://github.com/ionic-team/ionic/commit/8e11ecc136c61e925e76c0e48ab21611e09b5898))
* **refresher:** correctly select shadow root on older browsers ([#21237](https://github.com/ionic-team/ionic/issues/21237)) ([f23f1cb](https://github.com/ionic-team/ionic/commit/f23f1cb37eef02307c357fbb48c0db729974cdc4))
* **refresher:** refresher completes even after switching to a new tab ([#21236](https://github.com/ionic-team/ionic/issues/21236)) ([1e6f923](https://github.com/ionic-team/ionic/commit/1e6f92377aaf0804cfd0ddb9b06da7b4c9dc355f))
* **segment-button:** screen readers now announce selected state properly ([#21273](https://github.com/ionic-team/ionic/issues/21273)) ([85cc35e](https://github.com/ionic-team/ionic/commit/85cc35ee9163a38c48c6df466a3c036906437804))
* **toggle:** screen readers now announce toggle properly ([#21168](https://github.com/ionic-team/ionic/issues/21168)) ([1fbdb22](https://github.com/ionic-team/ionic/commit/1fbdb2255e4ff7fccf22d9ccc12b7f9bb4c3a064))
# [5.1.0 Aluminum](https://github.com/ionic-team/ionic/compare/v5.0.7...v5.1.0) (2020-04-30)
### Bug Fixes
* **action-sheet:** show correct cancel button background on dark mode ([#21084](https://github.com/ionic-team/ionic/issues/21084)) ([e442324](https://github.com/ionic-team/ionic/commit/e4423247537cbcda174305ab9fdde4a57c50a88e)), closes [#21082](https://github.com/ionic-team/ionic/issues/21082)
* **all:** correctly default gestures to use a passive listener ([#21038](https://github.com/ionic-team/ionic/issues/21038)) ([dea9248](https://github.com/ionic-team/ionic/commit/dea9248763737164e17678119c775cdfc0e53ccd))
* **angular:** do not navigate to the same tab if already active ([#21085](https://github.com/ionic-team/ionic/issues/21085)) ([15203de](https://github.com/ionic-team/ionic/commit/15203de08bf97f27e33f35994444c2c4843b3a44)), closes [#21074](https://github.com/ionic-team/ionic/issues/21074) [#19943](https://github.com/ionic-team/ionic/issues/19943)
* **back-button:** announce back button text correctly by screen readers ([#21053](https://github.com/ionic-team/ionic/issues/21053)) ([14c226c](https://github.com/ionic-team/ionic/commit/14c226ce75958da14b66821028d6f3a6852d695c)), closes [#21043](https://github.com/ionic-team/ionic/issues/21043)
* **datetime:** locale inputs are now reactive ([#20826](https://github.com/ionic-team/ionic/issues/20826)) ([a75e8f3](https://github.com/ionic-team/ionic/commit/a75e8f34d608c167f8d429ddbf39e94173204a61)), closes [#20367](https://github.com/ionic-team/ionic/issues/20367)
* **ios:** account for nested tabs with page transition ([#20955](https://github.com/ionic-team/ionic/issues/20955)) ([e23dec5](https://github.com/ionic-team/ionic/commit/e23dec5eb9fbb58eedffabefca8d7d643f49f7b9)), closes [#20948](https://github.com/ionic-team/ionic/issues/20948)
* **ios:** properly animate content when navigating from a tabbed page ([#20918](https://github.com/ionic-team/ionic/issues/20918)) ([8a02b28](https://github.com/ionic-team/ionic/commit/8a02b28efeca81c25176ff52508b4005441e8314)), closes [#20912](https://github.com/ionic-team/ionic/issues/20912)
* **loading:** correctly announce spinner by screen readers ([#21116](https://github.com/ionic-team/ionic/issues/21116)) ([63d8f62](https://github.com/ionic-team/ionic/commit/63d8f6239cc39e6a111108bd1a2557c297a256ae)), closes [#21107](https://github.com/ionic-team/ionic/issues/21107)
* **md:** do not display blank screen when using MD page transition and swipe gesture ([#21058](https://github.com/ionic-team/ionic/issues/21058)) ([4973807](https://github.com/ionic-team/ionic/commit/497380743df4461688455bc8b8440d2f3cc7c247)), closes [#21056](https://github.com/ionic-team/ionic/issues/220800)
* **modal:** properly inherit border radius for modals on Safari ([#20887](https://github.com/ionic-team/ionic/issues/20887)) ([bd64509](https://github.com/ionic-team/ionic/commit/bd64509bae9dd4c960134d986ce8150dc1a9d3b4)), closes [#20878](https://github.com/ionic-team/ionic/issues/20878)
* **modal:** swipeToClose property is now reactive ([#21073](https://github.com/ionic-team/ionic/issues/21073)) ([4bd9134](https://github.com/ionic-team/ionic/commit/4bd91344730bd26c66a8d838436d94045dc21f78)), closes [#21072](https://github.com/ionic-team/ionic/issues/21072)
* **overlays:** focus overlay when presented ([#20997](https://github.com/ionic-team/ionic/issues/20997)) ([fc2be8d](https://github.com/ionic-team/ionic/commit/fc2be8d08bbb495df911783f808d7ca511942172)), closes [#19882](https://github.com/ionic-team/ionic/issues/19882) [#17126](https://github.com/ionic-team/ionic/issues/17126)
* **overlays:** prevent accidental clicks when dismissing overlays ([#21093](https://github.com/ionic-team/ionic/issues/21093)) ([671802f](https://github.com/ionic-team/ionic/commit/671802f9a2050d9942e9dfb2db9f9c58bdc58620)), closes [#21092](https://github.com/ionic-team/ionic/issues/21092)
* **react:** IonTabBar properly extends IonicReactProps ([#21009](https://github.com/ionic-team/ionic/issues/21009)) ([102a842](https://github.com/ionic-team/ionic/commit/102a842bd2a967c04a3cf42ed4e0811929bd4d99)), closes [#21006](https://github.com/ionic-team/ionic/issues/21006)
* **refresher:** properly check for Haptics plugin on web ([#21156](https://github.com/ionic-team/ionic/issues/21156)) ([c53b136](https://github.com/ionic-team/ionic/commit/c53b136dbe7ed7fc0fc298593f8b677a66c77910)), closes [#21148](https://github.com/ionic-team/ionic/issues/21148)
* **refresher:** properly calculate content dimensions in native ion-refresher ([#21157](https://github.com/ionic-team/ionic/issues/21157)) ([83dcc71](https://github.com/ionic-team/ionic/commit/83dcc7168a48bc5b05583fb7c01b5eff9d1a67f8))
* **router:** account for query string when pushing page ([#21071](https://github.com/ionic-team/ionic/issues/21071)) ([eab3373](https://github.com/ionic-team/ionic/commit/eab33732133bd43ca6788bba6e93a9b545ee058a))
* **searchbar:** correctly announce the cancel button text by screen readers ([#21049](https://github.com/ionic-team/ionic/issues/21049)) ([15a603b](https://github.com/ionic-team/ionic/commit/15a603b39797dee6baf7e33d58907f98ced7e86d)), closes [#21013](https://github.com/ionic-team/ionic/issues/21013)
* **select:** account for MutationObserver when performing SSR ([#21068](https://github.com/ionic-team/ionic/issues/21068)) ([66e8e64](https://github.com/ionic-team/ionic/commit/66e8e6404d87a2767e71b13bed19706b29ad1b9c)), closes [#21063](https://github.com/ionic-team/ionic/issues/21063)
* **slides:** slides no longer break with Angular Ivy enabled ([#20899](https://github.com/ionic-team/ionic/issues/20899)) ([3123a31](https://github.com/ionic-team/ionic/commit/3123a318b6755dbf8fde8476f81c37e6ffa9b70e)), closes [#20356](https://github.com/ionic-team/ionic/issues/20356)
* **split-pane:** properly show border in rtl mode ([#20995](https://github.com/ionic-team/ionic/issues/20995)) ([7a21708](https://github.com/ionic-team/ionic/commit/7a21708d24bab6a388e1b55c88337e3d0f7922eb)), closes [#20994](https://github.com/ionic-team/ionic/issues/20994)
* **textarea:** height is set correctly when using autoGrow in modals ([#20971](https://github.com/ionic-team/ionic/issues/20971)) ([32ee040](https://github.com/ionic-team/ionic/commit/32ee040e3f0d7012790f190856097d0c6fa0eaa2)), closes [#18993](https://github.com/ionic-team/ionic/issues/18993)
### Features
* **all:** add ability to continue processing hardware back button events ([#20613](https://github.com/ionic-team/ionic/issues/20613)) ([3821c04](https://github.com/ionic-team/ionic/commit/3821c0463ae9a02e67c835a221c4ea01fab306d1)), closes [#17824](https://github.com/ionic-team/ionic/issues/17824)
* **all:** add ability to eject from Ionic sanitizer ([#20457](https://github.com/ionic-team/ionic/issues/20457)) ([fa9ddc9](https://github.com/ionic-team/ionic/commit/fa9ddc91bc9fefc2bb247cfe7511384f77335476)), closes [#18277](https://github.com/ionic-team/ionic/issues/18277)
* **angular:** support multi-app for ng-add schematic ([#20768](https://github.com/ionic-team/ionic/issues/20768)) ([39e6c8f](https://github.com/ionic-team/ionic/commit/39e6c8f55b514b0c7330dd3a790c859bb3410404))
* **animation:** add option to clean up old animation stylesheets ([#20940](https://github.com/ionic-team/ionic/issues/20940)) ([5b98405](https://github.com/ionic-team/ionic/commit/5b9840508faf6a2c985726be889c1f2fca0e0733)), closes [#20610](https://github.com/ionic-team/ionic/issues/20610)
* **app:** add keyboard open and close events (ionKeyboardDidShow and ionKeyboardDidHide) ([#18478](https://github.com/ionic-team/ionic/issues/18478)) ([ae5f1dd](https://github.com/ionic-team/ionic/commit/ae5f1ddff0c0799167a154abbb418b2ad3434d47))
* **back-button:** add backButtonDefaultHref property to Ionic Config ([#20491](https://github.com/ionic-team/ionic/issues/20491)) ([1b11ff7](https://github.com/ionic-team/ionic/commit/1b11ff7fb92b75f5c869c79d5e0d5dfd8889597f)), closes [#19305](https://github.com/ionic-team/ionic/issues/19305)
* **checkbox:** add parts support for container, mark ([#20950](https://github.com/ionic-team/ionic/issues/20950)) ([d4b9151](https://github.com/ionic-team/ionic/commit/d4b9151396aed6d7a29d8f40d6e607bf6258b4ef))
* **content:** add parts support for background, scroll ([#20929](https://github.com/ionic-team/ionic/issues/20929)) ([578ab93](https://github.com/ionic-team/ionic/commit/578ab93d297f101ac899b6b6b099445ac679c71f))
* **datetime:** add parts support for placeholder, text ([#20930](https://github.com/ionic-team/ionic/issues/20930)) ([76ca475](https://github.com/ionic-team/ionic/commit/76ca475734e13404886bdf70117c0c39bbd7ce70))
* **gesture:** add option to run inside NgZone for Angular apps ([#20685](https://github.com/ionic-team/ionic/issues/20685)) ([429edb0](https://github.com/ionic-team/ionic/commit/429edb053bf2a5e778665770c373e31fc7d3bfd2)), closes [#20529](https://github.com/ionic-team/ionic/issues/20529)
* **gesture:** add support for blurring active inputs on gesture start ([#20638](https://github.com/ionic-team/ionic/issues/20638)) ([32ecdd6](https://github.com/ionic-team/ionic/commit/32ecdd67536f07f9d95e331e44661afb2cf7b470)), closes [#20588](https://github.com/ionic-team/ionic/issues/20588)
* **img:** add parts support for image ([#20943](https://github.com/ionic-team/ionic/issues/20943)) ([63c75ed](https://github.com/ionic-team/ionic/commit/63c75edd21387f28387c8a8529ba638317a9d9b8))
* **input:** add support for enterkeyhint ([#21035](https://github.com/ionic-team/ionic/issues/21035)) ([3efaf43](https://github.com/ionic-team/ionic/commit/3efaf4382175d40902968cabb7edd672ffc7cc2b)), closes [#21034](https://github.com/ionic-team/ionic/issues/21034)
* **item:** add parts support for detail-icon ([#20979](https://github.com/ionic-team/ionic/issues/20979)) ([6414496](https://github.com/ionic-team/ionic/commit/64144960b06e056a99aa3d352486a495b6bb43ed))
* **menu:** add parts support for backdrop, container ([#20978](https://github.com/ionic-team/ionic/issues/20978)) ([50bc212](https://github.com/ionic-team/ionic/commit/50bc212d0b30919c136d6be60a9d458ec7d50dde))
* **radio:** add parts support for container, mark ([#20952](https://github.com/ionic-team/ionic/issues/20952)) ([228ca2b](https://github.com/ionic-team/ionic/commit/228ca2b093215aba91fe925b301049471ffaa169))
* **range:** add parts support for bar, bar-active, knob, pin, tick, tick-active ([#20961](https://github.com/ionic-team/ionic/issues/20961)) ([619f67a](https://github.com/ionic-team/ionic/commit/619f67a00baa387d0f2bf3f6219e21bc87c03313))
* **react:** expose selectTab method and activeTab, closes [#19935](https://github.com/ionic-team/ionic/issues/19935) ([#21171](https://github.com/ionic-team/ionic/issues/21171)) ([43f9d24](https://github.com/ionic-team/ionic/commit/43f9d24824e4c1b679b350b3db05a6830d98fc0a))
* **reorder:** add parts support for icon ([#20960](https://github.com/ionic-team/ionic/issues/20960)) ([ba20209](https://github.com/ionic-team/ionic/commit/ba20209604666048619ae5f4358be0e65ef36e4f))
* **searchbar:** add border-radius css variable ([#20662](https://github.com/ionic-team/ionic/issues/20662)) ([acaa1d9](https://github.com/ionic-team/ionic/commit/acaa1d9ef7e4037913159c0d32829183ddc1860b)), closes [#17426](https://github.com/ionic-team/ionic/issues/17426) [#18247](https://github.com/ionic-team/ionic/issues/18247)
* **searchbar:** add support for enterkeyhint ([#21036](https://github.com/ionic-team/ionic/issues/21036)) ([e90683a](https://github.com/ionic-team/ionic/commit/e90683a713cb45d1e1283dd41343ea6b672a9e3a)), closes [#21034](https://github.com/ionic-team/ionic/issues/21034)
* **select:** add parts support for placeholder, icon, text ([#21108](https://github.com/ionic-team/ionic/issues/21108)) ([30a1c89](https://github.com/ionic-team/ionic/commit/30a1c896883e971ab87ef7d5d8790e9a60632fc2))
* **slides:** update to swiper 5 ([#20917](https://github.com/ionic-team/ionic/issues/20917)) ([4e28445](https://github.com/ionic-team/ionic/commit/4e28445ecb029f8d225acf9313209e5f61114dc4)), closes [#20033](https://github.com/ionic-team/ionic/issues/20033)
* **textarea:** add support for inputmode and enterkeyhint ([#21106](https://github.com/ionic-team/ionic/issues/21106)) ([1622d9b](https://github.com/ionic-team/ionic/commit/1622d9bb3c7f2aeed7dc823620204737619a5b0d))
* **toast:** add white-space variable for toast message ([#20729](https://github.com/ionic-team/ionic/issues/20729)) ([e5e02d4](https://github.com/ionic-team/ionic/commit/e5e02d4f88abbcc7dbc626db6d5adf4292d8e776)), closes [#20727](https://github.com/ionic-team/ionic/issues/20727)
* **toggle:** add parts support for handle, track ([#20962](https://github.com/ionic-team/ionic/issues/20962)) ([d2b772f](https://github.com/ionic-team/ionic/commit/d2b772f19fde71bcec72300cb4cf8234321b35bc))
* **toggle:** improve customization with css vars and auto-adjust handle width and height ([#21050](https://github.com/ionic-team/ionic/issues/21050)) ([04ace4c](https://github.com/ionic-team/ionic/commit/04ace4c98346fde5bad343224657f049beb3e868)), closes [#19868](https://github.com/ionic-team/ionic/issues/19868) [#20474](https://github.com/ionic-team/ionic/issues/20474)
### Performance Improvements
* **all:** improve scroll assist responsiveness ([#20987](https://github.com/ionic-team/ionic/issues/20987)) ([6f13b8c](https://github.com/ionic-team/ionic/commit/6f13b8c7922f638cac4eb3b111ff9643e6995491)), closes [#20922](https://github.com/ionic-team/ionic/issues/20922)
## [5.0.7](https://github.com/ionic-team/ionic/compare/v5.0.6...v5.0.7) (2020-03-26)
### Bug Fixes
* **modal:** properly target card modal for iPadOS styles ([#20884](https://github.com/ionic-team/ionic/issues/20884)) ([5816cf5](https://github.com/ionic-team/ionic/commit/5816cf52a779acc4613c2d2da28b97c511360cc2))
## [5.0.6](https://github.com/ionic-team/ionic/compare/v5.0.5...v5.0.6) (2020-03-25)
### Bug Fixes
* **all** only warn invalid mode if used on an ionic component ([#20828](https://github.com/ionic-team/ionic/issues/20828)) ([6ed1c51](https://github.com/ionic-team/ionic/commit/6ed1c51321d781ff92efbf623790af91cb16a5af)), closes [#20055](https://github.com/ionic-team/ionic/issues/20055)
* **all** properly scroll to input with scroll assist ([#20742](https://github.com/ionic-team/ionic/issues/20742)) ([e24060e](https://github.com/ionic-team/ionic/commit/e24060ecd9d803ece4bbb9c6beae23e761d7fb5e)), closes [#19589](https://github.com/ionic-team/ionic/issues/19589)
* **angular:** export Animation and Gesture related types ([#20766](https://github.com/ionic-team/ionic/issues/20766)) ([2ece194](https://github.com/ionic-team/ionic/commit/2ece194a085742b919cc68f643b1b365f7d85594))
* **angular:** respect animation property for ion-router-outlet ([#20767](https://github.com/ionic-team/ionic/issues/20767)) ([f2dbe1f](https://github.com/ionic-team/ionic/commit/f2dbe1ff3be44e6697b791de392a9ef46dbf27e8)), closes [#20764](https://github.com/ionic-team/ionic/issues/20764)
* **content:** apply --offset-top and --offset-bottom values correctly ([#20790](https://github.com/ionic-team/ionic/issues/20790)) ([2707289](https://github.com/ionic-team/ionic/commit/2707289b36883ae495f86cfb2f2b6c84e090551b)), closes [#20735](https://github.com/ionic-team/ionic/issues/20735)
* **content:** set overscroll-behavior based on the scroll direction ([#20011](https://github.com/ionic-team/ionic/issues/20011)) ([a3fc77b](https://github.com/ionic-team/ionic/commit/a3fc77be91ead6edc3f07c6127879753a063bd18)), closes [#20010](https://github.com/ionic-team/ionic/issues/20010)
* **item-divider:** update design to match native iOS ([#20854](https://github.com/ionic-team/ionic/issues/20854)) ([d91e22d](https://github.com/ionic-team/ionic/commit/d91e22d820f170ecfdfad835ca56701ad70e6f3d))
* **item-sliding:** account for swipe to go back gesture when opening item-options ([#20777](https://github.com/ionic-team/ionic/issues/20777)) ([f23ac44](https://github.com/ionic-team/ionic/commit/f23ac44c9a6646129762bb861cae6145690ca5a1)), closes [#20773](https://github.com/ionic-team/ionic/issues/20773)
* **list:** show bottom border on last item in a list followed by a list ([#20798](https://github.com/ionic-team/ionic/issues/20798)) ([7bc5191](https://github.com/ionic-team/ionic/commit/7bc51911f6c538be8b91d1e569675b19832cb000))
* **modal:** backdrop and box shadows no longer stack when opening multiple modals ([#20801](https://github.com/ionic-team/ionic/issues/20801)) ([253cd96](https://github.com/ionic-team/ionic/commit/253cd96164914a803f6bb42ff95ca74880c940d0)), closes [#20800](https://github.com/ionic-team/ionic/issues/20800)
* **modal:** backdrop is no longer tappable on card-style modal on smaller screens ([#20802](https://github.com/ionic-team/ionic/issues/20802)) ([12932dd](https://github.com/ionic-team/ionic/commit/12932dd20212bec7d780650166c70819d125f75a)), closes [#20783](https://github.com/ionic-team/ionic/issues/20783)
* **modal:** properly apply border radius on card-style modal ([#20852](https://github.com/ionic-team/ionic/issues/20852)) ([dff3816](https://github.com/ionic-team/ionic/commit/dff3816c049a1c051f94d3176c8b903a69603912)), closes [#20851](https://github.com/ionic-team/ionic/issues/20851)
* **modal:** properly remove safe area padding on card-modal ([#20853](https://github.com/ionic-team/ionic/issues/20853)) ([71f1182](https://github.com/ionic-team/ionic/commit/71f118201b0918f60c1a078d55afd10b39f17e86)), closes [#20799](https://github.com/ionic-team/ionic/issues/20799)
* **modal:** respect card-style modal spec for iPadOS ([#20750](https://github.com/ionic-team/ionic/issues/20750)) ([75bae40](https://github.com/ionic-team/ionic/commit/75bae403e917b20645675343734440ee95d31634)), closes [#20700](https://github.com/ionic-team/ionic/issues/20700)
* **react:** expose correct type for CreateAnimation ([#20775](https://github.com/ionic-team/ionic/issues/20775)) ([0897c3f](https://github.com/ionic-team/ionic/commit/0897c3f9c2591442b3f80d28a25ec4471da3c9d7)), closes [#20771](https://github.com/ionic-team/ionic/issues/20771)
* **refresher:** properly dismiss refresher when completed synchronously ([#20815](https://github.com/ionic-team/ionic/issues/20815)) ([b1a87c8](https://github.com/ionic-team/ionic/commit/b1a87c88923201fd0b31bf55d81b97acc09ddf1c)), closes [#20803](https://github.com/ionic-team/ionic/issues/20803)
* **segment:** automatically expand width for scrollable segment buttons ([#20763](https://github.com/ionic-team/ionic/issues/20763)) ([cdfd50b](https://github.com/ionic-team/ionic/commit/cdfd50b554d1d8f89c3d9948c7613ce75ede1e52)), closes [#20566](https://github.com/ionic-team/ionic/issues/20566)
* **segment:** scrollable segments only show scrollbar if they overflow ([#20760](https://github.com/ionic-team/ionic/issues/20760)) ([ab146c9](https://github.com/ionic-team/ionic/commit/ab146c96ec5cbc962eed629c30b2c5c446f3098d)), closes [#20758](https://github.com/ionic-team/ionic/issues/20758)
* **slides:** check that mutation observer is defined for ssr ([#20791](https://github.com/ionic-team/ionic/issues/20791)) ([2d5d251](https://github.com/ionic-team/ionic/commit/2d5d2515be86496a280d93847185ab332e5d47a2))
* **textarea:** properly adjust auto-grow textarea in scrolled content ([#19776](https://github.com/ionic-team/ionic/issues/19776)) ([8bd5bac](https://github.com/ionic-team/ionic/commit/8bd5bace73670dfe351b3734b51cbf3aa87517dc)), closes [#19193](https://github.com/ionic-team/ionic/issues/19193)
* **title:** improve reliability of large title ios nav transition ([#20861](https://github.com/ionic-team/ionic/issues/20861)) ([3bd6b5d](https://github.com/ionic-team/ionic/commit/3bd6b5def2877f6a918c587de25a10ccc82f88f1))
* **title:** large title now inherits global color styling during nav transition ([#20862](https://github.com/ionic-team/ionic/issues/20862)) ([321140f](https://github.com/ionic-team/ionic/commit/321140ff736b46d2631a9e87a7b070009c5e1b2c))
## [5.0.5](https://github.com/ionic-team/ionic/compare/v5.0.4...v5.0.5) (2020-03-11)
### Bug Fixes
* **button:** allow overflow to be overridden by the CSS variable ([#20738](https://github.com/ionic-team/ionic/issues/20738)) ([7ecde36](https://github.com/ionic-team/ionic/commit/7ecde36f9d31327a45f7b5023ed533edbb9cc709)), closes [#20726](https://github.com/ionic-team/ionic/issues/20726)
* **datetime:** account for max property when hour, minute, or second is set to 0 ([#20665](https://github.com/ionic-team/ionic/issues/20665)) ([2177461](https://github.com/ionic-team/ionic/commit/21774612d8d70ab7eda3eab0e6e9ac039b5c87d8)), closes [#20652](https://github.com/ionic-team/ionic/issues/20652)
* **header:** collapsable header should default to using content background ([#20736](https://github.com/ionic-team/ionic/issues/20736)) ([f6c3ba7](https://github.com/ionic-team/ionic/commit/f6c3ba7e5af2af9e32f75306cde7704509e82263)), closes [#20691](https://github.com/ionic-team/ionic/issues/20691)
* **header:** resolve undefined error on collapsible header when navigating quickly ([#20728](https://github.com/ionic-team/ionic/issues/20728)) ([87a2721](https://github.com/ionic-team/ionic/commit/87a27216d011f1d02ac0fc0aeb3ae0400ecfbd8c)), closes [#20725](https://github.com/ionic-team/ionic/issues/20725)
* **ios:** large title animation now works properly in a modal ([#20703](https://github.com/ionic-team/ionic/issues/20703)) ([ec4878a](https://github.com/ionic-team/ionic/commit/ec4878ac085d8ff92cb8b2ea0852523f174ab01b)), closes [#20696](https://github.com/ionic-team/ionic/issues/20696)
* **item:** apply proper margin left for slotted icon in RTL ([#20684](https://github.com/ionic-team/ionic/issues/20684)) ([d53595e](https://github.com/ionic-team/ionic/commit/d53595eb1629e0d60f7e832414e84c544e184346)), closes [#20653](https://github.com/ionic-team/ionic/issues/20653)
* **label:** text overflow for slotted headings ([#20690](https://github.com/ionic-team/ionic/issues/20690)) ([4d34ce6](https://github.com/ionic-team/ionic/commit/4d34ce6a31eaa19859699646cc614f5be6239e10)), closes [#17087](https://github.com/ionic-team/ionic/issues/17087)
* **modal:** leave animation transitions modal completely out of viewport on ipad ([#20702](https://github.com/ionic-team/ionic/issues/20702)) ([22d5256](https://github.com/ionic-team/ionic/commit/22d52568100d8096ee36e3a61a19614f0d63d45f)), closes [#20697](https://github.com/ionic-team/ionic/issues/20697)
* **angular** exclude components from ssr ([#20674](https://github.com/ionic-team/ionic/issues/20674)) ([f64b142](https://github.com/ionic-team/ionic/commit/f64b1420aead39b9056dc25cfdbcf95bc4f6f621))
* **modal:** swipeable modal now works in firefox ([#20714](https://github.com/ionic-team/ionic/issues/20714)) ([7d260b9](https://github.com/ionic-team/ionic/commit/7d260b96a73958709fa93a4fe58f816a445471ee)), closes [#20706](https://github.com/ionic-team/ionic/issues/20706)
* **overlays:** prevent accidental dismiss of overlays when tapping screen twice ([#20683](https://github.com/ionic-team/ionic/issues/20683)) ([b6c2a77](https://github.com/ionic-team/ionic/commit/b6c2a77deb1c09eb1fd414f7737794e208ab5081)), closes [#20608](https://github.com/ionic-team/ionic/issues/20608)
* **segment:** allow routerLink to work on segment buttons ([#20682](https://github.com/ionic-team/ionic/issues/20682)) ([314dbb1](https://github.com/ionic-team/ionic/commit/314dbb1a4d970327fcbb2f3fbdec0627c626fe4d)), closes [#20678](https://github.com/ionic-team/ionic/issues/20678)
* **segment:** iOS mode segment now works on older Android devices ([#20673](https://github.com/ionic-team/ionic/issues/20673)) ([44993b7](https://github.com/ionic-team/ionic/commit/44993b7987031b6618409675fdbb1f15ec4ea343)), closes [#20648](https://github.com/ionic-team/ionic/issues/20648)
## [5.0.4](https://github.com/ionic-team/ionic/compare/v5.0.3...v5.0.4) (2020-02-27)
### Bug Fixes
* **animation:** reset all temporary flags when interrupting an animation ([#20627](https://github.com/ionic-team/ionic/issues/20627)) ([0e0e401](https://github.com/ionic-team/ionic/commit/0e0e401d86dabaa1dc804656e4d384154d6fdd05)), closes [#20602](https://github.com/ionic-team/ionic/issues/20602)
* **buttons:** use proper button colors based on CSS variables when inside of a toolbar ([#20633](https://github.com/ionic-team/ionic/issues/20633)) ([c1d7bf2](https://github.com/ionic-team/ionic/commit/c1d7bf229d10d0a12f90b6d2730d6d8ac78b48cd))
## [5.0.3](https://github.com/ionic-team/ionic/compare/v5.0.2...v5.0.3) (2020-02-26)
### Bug Fixes
* **menu:** allow ssr to work properly with hardware back button updates ([#20629](https://github.com/ionic-team/ionic/issues/20629)) ([fe8d74d](https://github.com/ionic-team/ionic/commit/fe8d74d08cb919ed1c685262f0aed4a544c3a7e1))
## [5.0.2](https://github.com/ionic-team/ionic/compare/v5.0.1...v5.0.2) (2020-02-26)
### Bug Fixes
* **ios:** large title transition works properly in tabbed applications ([#20555](https://github.com/ionic-team/ionic/issues/20555)) ([7187541](https://github.com/ionic-team/ionic/commit/71875417f207d26bd7115655f239251460a1e3d8)), closes [#20482](https://github.com/ionic-team/ionic/issues/20482)
* **menu:** hardware back button now dismisses side menu if open in Cordova/Capacitor app ([#20558](https://github.com/ionic-team/ionic/issues/20558)) ([6b2a929](https://github.com/ionic-team/ionic/commit/6b2a929cd7e70b16383cb3336b399a1aee2d6101)), closes [#20559](https://github.com/ionic-team/ionic/issues/20559)
* **modal:** allow swipe to close animation to be overridden ([#20585](https://github.com/ionic-team/ionic/issues/20585)) ([8d3ce8d](https://github.com/ionic-team/ionic/commit/8d3ce8d29c9abd89ce47c882e0d7b2ac0f861966)), closes [#20577](https://github.com/ionic-team/ionic/issues/20577)
* **modal:** card style modal now adds appropriate contrast ([#20604](https://github.com/ionic-team/ionic/issues/20604)) ([b5310ef](https://github.com/ionic-team/ionic/commit/b5310effe3f9b47459f22221da1853a55dbb0279))
* **modal:** allow swipeable modal background to be overridden ([#20584](https://github.com/ionic-team/ionic/issues/20584)) ([ad6fac8](https://github.com/ionic-team/ionic/commit/ad6fac83cb7c4acb377b4b1620ab1a3f852bc6d3)), closes [#20572](https://github.com/ionic-team/ionic/issues/20572)
* **modal:** swipeable modal styles only apply to ios ([#20571](https://github.com/ionic-team/ionic/issues/20571)) ([3a2d828](https://github.com/ionic-team/ionic/commit/3a2d82814b22a3987a5abfe4412d83a93a97b6b7)), closes [#20569](https://github.com/ionic-team/ionic/issues/20569)
* **refresher:** ensure that translate is cleaned up to avoid stacking context ([#20621](https://github.com/ionic-team/ionic/issues/20621)) ([e3e5c69](https://github.com/ionic-team/ionic/commit/e3e5c69681f376cbc4b1305f719fc6895b21a9b7)), closes [#17949](https://github.com/ionic-team/ionic/issues/17949)
* **segment:** segment functions properly on older versions of Android ([#20554](https://github.com/ionic-team/ionic/issues/20554)) ([0224bed](https://github.com/ionic-team/ionic/commit/0224bed0c9f91bcb54bb4b3064df56928cf5ed8a)), closes [#20466](https://github.com/ionic-team/ionic/issues/20466)
* **select:** properly align text, add icon-inner and placeholder part ([#20605](https://github.com/ionic-team/ionic/issues/20605)) ([926ac3f](https://github.com/ionic-team/ionic/commit/926ac3fb47228be19146ccdfab92a05cf6677ff4))
* **slides:** set height to 100% for vertical slides ([#20603](https://github.com/ionic-team/ionic/issues/20603)) ([20af652](https://github.com/ionic-team/ionic/commit/20af652a1be5e1aff2836422489642c8baed6939)), closes [#17341](https://github.com/ionic-team/ionic/issues/17341)
## [5.0.1](https://github.com/ionic-team/ionic/compare/v5.0.0...v5.0.1) (2020-02-19)
### Bug Fixes
* **button:** reduce font size of icon only button in toolbar on iOS ([#20547](https://github.com/ionic-team/ionic/issues/20547)) ([59fa340](https://github.com/ionic-team/ionic/commit/59fa340650840b2abf86bd643350da7064ee9ead))
* **card:** inherit background in inner button ([#20461](https://github.com/ionic-team/ionic/issues/20461)) ([c16de96](https://github.com/ionic-team/ionic/commit/c16de9663329993698c10e4251dbb0b75167701f)), closes [#20458](https://github.com/ionic-team/ionic/issues/20458)
* **fab:** add close icon to internal icons for react ([#20490](https://github.com/ionic-team/ionic/issues/20490)) ([c4fb314](https://github.com/ionic-team/ionic/commit/c4fb31403eb4704bcf04e6c32bfa46422f08bf4f)), closes [#20489](https://github.com/ionic-team/ionic/issues/20489)
* **fab:** show close icon on hover, focused, activated ([#20497](https://github.com/ionic-team/ionic/issues/20497)) ([e42c85d](https://github.com/ionic-team/ionic/commit/e42c85d64161b7fac7147325cb6c2ceff990042b))
* **input:** do not clear input if "Enter" key pressed ([#20462](https://github.com/ionic-team/ionic/issues/20462)) ([89bf08b](https://github.com/ionic-team/ionic/commit/89bf08b6276f2a25d66fc0e74ba3303f923af652)), closes [#20442](https://github.com/ionic-team/ionic/issues/20442)
* **ios:** clamp out of bounds values for swipe to go back ([#20540](https://github.com/ionic-team/ionic/issues/20540)) ([dd32a5e](https://github.com/ionic-team/ionic/commit/dd32a5e2788a11a5c2be0d1840f5775c7307c57f)), closes [#20505](https://github.com/ionic-team/ionic/issues/20505)
* **menu:** swipe gesture should not open menu when a modal is displayed ([#20546](https://github.com/ionic-team/ionic/issues/20546)) ([3252c2f](https://github.com/ionic-team/ionic/commit/3252c2f8dc46e0853a7f626baa6023a01ac21a25)), closes [#20467](https://github.com/ionic-team/ionic/issues/20467)
* **modal:** presenting multiple card-style modals now adds border radius properly ([#20476](https://github.com/ionic-team/ionic/issues/20476)) ([abf594a](https://github.com/ionic-team/ionic/commit/abf594aa611562a76e3baecfa38456d41a1410f3)), closes [#20475](https://github.com/ionic-team/ionic/issues/20475)
* **modal:** prevent card style modal styles from being overridden ([#20470](https://github.com/ionic-team/ionic/issues/20470)) ([86ab77a](https://github.com/ionic-team/ionic/commit/86ab77a6e2cb124510c244110fc78a4bc0654cd1)), closes [#20469](https://github.com/ionic-team/ionic/issues/20469)
* **react:** do a better job matching up route to sync ([#20446](https://github.com/ionic-team/ionic/issues/20446)) ([c0aadd6](https://github.com/ionic-team/ionic/commit/c0aadd60077e5ba379959d93006e3a9c1418263c)), closes [#20363](https://github.com/ionic-team/ionic/issues/20363)
* **react:** do not remove pages when navigating between tabs ([#20431](https://github.com/ionic-team/ionic/issues/20431)) ([b6fbe98](https://github.com/ionic-team/ionic/commit/b6fbe98812fbab5ef9e0723802605c0711581dd2)), closes [#20398](https://github.com/ionic-team/ionic/issues/20398)
* **react:** icons with MD set should work in browser ([#20463](https://github.com/ionic-team/ionic/issues/20463)) ([82670fe](https://github.com/ionic-team/ionic/commit/82670fe4d0592451cbc243b3008beb3f8f483c30))
* **react:** update paths of tab buttons when href changes in ion buttons ([#20480](https://github.com/ionic-team/ionic/issues/20480)) ([45d03ba](https://github.com/ionic-team/ionic/commit/45d03baf981d0e10eb1fe689908532adef2ba31d)), closes [#20321](https://github.com/ionic-team/ionic/issues/20321)
* **searchbar:** properly align placeholder ([#20460](https://github.com/ionic-team/ionic/issues/20460)) ([4d6e15a](https://github.com/ionic-team/ionic/commit/4d6e15ab18fc894c3826b89362163256adc227f4)), closes [#20456](https://github.com/ionic-team/ionic/issues/20456)
* **segment:** border radius applies to indicator on ios ([#20541](https://github.com/ionic-team/ionic/issues/20541)) ([9b5854d](https://github.com/ionic-team/ionic/commit/9b5854d79712356f8a3772442c0cc412db09d5e0)), closes [#20539](https://github.com/ionic-team/ionic/issues/20539)
* **segment:** do not show ripple effect if disabled via config ([#20542](https://github.com/ionic-team/ionic/issues/20542)) ([7a461c5](https://github.com/ionic-team/ionic/commit/7a461c59c5d9a23de0bcdd53397f452d17251fd6)), closes [#20533](https://github.com/ionic-team/ionic/issues/20533)
* **segment:** inner div no longer interferes with click events ([#20522](https://github.com/ionic-team/ionic/issues/20522)) ([06b828b](https://github.com/ionic-team/ionic/commit/06b828b4ffb12b076b0805274f53fa158ee65c5a)), closes [#20381](https://github.com/ionic-team/ionic/issues/20381)
* **segment:** only emit ionChange when user releases pointer from screen ([#20495](https://github.com/ionic-team/ionic/issues/20495)) ([4d50064](https://github.com/ionic-team/ionic/commit/4d5006476479bc376d3bb4edad6db0b3ce806ef7)), closes [#20500](https://github.com/ionic-team/ionic/issues/20500) [#20257](https://github.com/ionic-team/ionic/issues/20257)
* **tab-bar:** update ios icon and label design to match native ([#20548](https://github.com/ionic-team/ionic/issues/20548)) ([34f8576](https://github.com/ionic-team/ionic/commit/34f8576b959d41896502e4f7b0c4240156e001eb))
# [5.0.0 Magnesium](https://github.com/ionic-team/ionic/compare/v4.11.10...v5.0.0) (2020-02-11)
Enjoy! :fire:
> We recommend updating to version `4.11.10` before updating to this version in order to see deprecation warnings related to your app [in the developer console](https://javascript.info/devtools).
Run the following commands based on your project type:
```
# for an angular app
npm i @ionic/angular@latest --save
# for a react app
npm i @ionic/react@latest --save
npm i @ionic/react-router@latest --save
npm i ionicons@latest --save
# for a stencil / vanilla JS app
npm i @ionic/core@latest --save
```
Then take a look at the [Breaking Changes](./BREAKING.md) file for API changes.
# [5.0.0-rc.5](https://github.com/ionic-team/ionic/compare/v5.0.0-rc.4...v5.0.0-rc.5) (2020-02-11)
### Bug Fixes
* **angular:** correct path for angular projects ([#20436](https://github.com/ionic-team/ionic/issues/20436)) ([fd9c7a9](https://github.com/ionic-team/ionic/commit/fd9c7a9601e7f21b74c76be1f8bb305bf008915c)), closes [#20435](https://github.com/ionic-team/ionic/issues/20435)
# [5.0.0-rc.4](https://github.com/ionic-team/ionic/compare/v5.0.0-rc.3...v5.0.0-rc.4) (2020-02-10)
### Bug Fixes
* **content:** only emit scroll events if enabled ([#20401](https://github.com/ionic-team/ionic/issues/20401)) ([fd1b44a](https://github.com/ionic-team/ionic/commit/fd1b44a40b741088e099f6538dd14caa0dc5540c))
* **header:** backdrop filter no longer distorts content with collapsible header ([#20388](https://github.com/ionic-team/ionic/issues/20388)) ([11d3945](https://github.com/ionic-team/ionic/commit/11d39457d56c091e9c41c180391d27464ae748b5)), closes [#20385](https://github.com/ionic-team/ionic/issues/20385)
* **item:** remove unneeded box-shadow CSS variable ([#20412](https://github.com/ionic-team/ionic/issues/20412)) ([a6764c4](https://github.com/ionic-team/ionic/commit/a6764c4724e1e7eed19a1902b563aeb61bfde38e)), closes [#20392](https://github.com/ionic-team/ionic/issues/20392)
* **label:** remove subpixel font-size to prevent visual glitches ([#20415](https://github.com/ionic-team/ionic/issues/20415)) ([3d6f287](https://github.com/ionic-team/ionic/commit/3d6f287d87bfaa0d81a34182baf38192e08fb3c1)), closes [#20407](https://github.com/ionic-team/ionic/issues/20407)
* **segment:** add activated class directly to segment button ([#20400](https://github.com/ionic-team/ionic/issues/20400)) ([e8886e9](https://github.com/ionic-team/ionic/commit/e8886e98f188044227bf5757892341cb598fdd27))
# [5.0.0-rc.3](https://github.com/ionic-team/ionic/compare/v5.0.0-rc.2...v5.0.0-rc.3) (2020-02-05)
### Bug Fixes
* **refresher:** ensure gesture does not interfere with item-sliding ([#20380](https://github.com/ionic-team/ionic/issues/20380)) ([8983c70](https://github.com/ionic-team/ionic/commit/8983c7006e54743873cd45ae1acdfa974d74547a)), closes [#20379](https://github.com/ionic-team/ionic/issues/20379)
* **refresher:** translate background content when refreshing ([#20378](https://github.com/ionic-team/ionic/issues/20378)) ([cf70916](https://github.com/ionic-team/ionic/commit/cf7091625ecb46c3f9882ae9eff5c946523fab75)), closes [#20377](https://github.com/ionic-team/ionic/issues/20377)
* **segment:** allow background to be set on iOS segment in a toolbar ([#20350](https://github.com/ionic-team/ionic/issues/20350)) ([0f31624](https://github.com/ionic-team/ionic/commit/0f31624104d195367df197eda9b8d6c5bda4cf75))
* **toolbar:** properly apply safe area and border ([#20375](https://github.com/ionic-team/ionic/issues/20375)) ([4971499](https://github.com/ionic-team/ionic/commit/4971499026fcee70a32cc9480302bb14a1bebcb7)), closes [#20354](https://github.com/ionic-team/ionic/issues/20354)
# [5.0.0-rc.2](https://github.com/ionic-team/ionic/compare/v5.0.0-rc.1...v5.0.0-rc.2) (2020-01-30)

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "5.0.0-rc.2",
"version": "5.1.1",
"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.0.0-rc.2",
"@ionic/core": "5.1.1",
"tslib": "^1.9.3"
},
"peerDependencies": {
@@ -64,7 +64,7 @@
"@types/node": "12.12.5",
"fs-extra": "^7.0.0",
"glob": "^7.1.4",
"ng-packagr": "5.7.1",
"ng-packagr": "^9.1.5",
"rollup": "~1.17.0",
"rollup-plugin-node-resolve": "~5.2.0",
"rxjs": "^6.5.2",

View File

@@ -12,6 +12,13 @@ export class ValueAccessor implements ControlValueAccessor {
constructor(protected el: ElementRef) {}
writeValue(value: any) {
/**
* TODO for Ionic 6:
* Change `value == null ? '' : value;`
* to `value`. This was a fix for IE9, but IE9
* is no longer supported; however, this change
* is potentially a breaking change
*/
this.el.nativeElement.value = this.lastValue = value == null ? '' : value;
setIonicClasses(this.el);
}

View File

@@ -1,5 +1,6 @@
import { Directive, HostListener, Optional } from '@angular/core';
import { Config } from '../../providers/config';
import { NavController } from '../../providers/nav-controller';
import { IonRouterOutlet } from './ion-router-outlet';
@@ -14,7 +15,8 @@ export class IonBackButtonDelegate {
constructor(
@Optional() private routerOutlet: IonRouterOutlet,
private navCtrl: NavController
private navCtrl: NavController,
private config: Config
) {}
/**
@@ -22,11 +24,13 @@ export class IonBackButtonDelegate {
*/
@HostListener('click', ['$event'])
onClick(ev: Event) {
const defaultHref = this.defaultHref || this.config.get('backButtonDefaultHref');
if (this.routerOutlet && this.routerOutlet.canGoBack()) {
this.routerOutlet.pop();
ev.preventDefault();
} else if (this.defaultHref != null) {
this.navCtrl.navigateBack(this.defaultHref);
} else if (defaultHref != null) {
this.navCtrl.navigateBack(defaultHref);
ev.preventDefault();
}
}

View File

@@ -4,6 +4,7 @@ import { ActivatedRoute, ChildrenOutletContexts, OutletContext, PRIMARY_OUTLET,
import { BehaviorSubject, Observable } from 'rxjs';
import { distinctUntilChanged, filter, switchMap } from 'rxjs/operators';
import { AnimationBuilder } from '../../';
import { Config } from '../../providers/config';
import { NavController } from '../../providers/nav-controller';
@@ -13,13 +14,13 @@ import { RouteView, getUrl } from './stack-utils';
@Directive({
selector: 'ion-router-outlet',
exportAs: 'outlet',
inputs: ['animated', 'swipeGesture']
inputs: ['animated', 'animation', 'swipeGesture']
})
export class IonRouterOutlet implements OnDestroy, OnInit {
nativeEl: HTMLIonRouterOutletElement;
private activated: ComponentRef<any> | null = null;
private activatedView: RouteView | null = null;
activatedView: RouteView | null = null;
private _activatedRoute: ActivatedRoute | null = null;
private _swipeGesture?: boolean;
@@ -38,6 +39,10 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
@Output('activate') activateEvents = new EventEmitter<any>();
@Output('deactivate') deactivateEvents = new EventEmitter<any>();
set animation(animation: AnimationBuilder) {
this.nativeEl.animation = animation;
}
set animated(animated: boolean) {
this.nativeEl.animated = animated;
}

View File

@@ -91,6 +91,12 @@ export class IonTabs {
const alreadySelected = this.outlet.getActiveStackId() === tab;
const tabRootUrl = `${this.outlet.tabsPrefix}/${tab}`;
if (alreadySelected) {
const activeStackId = this.outlet.getActiveStackId();
const activeView = this.outlet.getLastRouteView(activeStackId);
// If on root tab, do not navigate to root tab again
if (activeView.url === tabRootUrl) { return; }
const rootView = this.outlet.getRootView(tab);
const navigationExtras = rootView && tabRootUrl === rootView.url && rootView.savedExtras;
return this.navCtrl.navigateRoot(tabRootUrl, {

View File

@@ -2,7 +2,7 @@
import * as d from './proxies';
export const DIRECTIVES = [
d.IonApp,
d.IonApp,
d.IonAvatar,
d.IonBackButton,
d.IonBackdrop,

View File

@@ -1,29 +1,30 @@
/* eslint-disable */
/* tslint:disable */
import { fromEvent } from 'rxjs';
export const proxyInputs = (Cmp: any, inputs: string[]) => {
const Prototype = Cmp.prototype;
inputs.forEach(item => {
Object.defineProperty(Prototype, item, {
get() {
return this.el[item];
},
set(val: any) {
this.z.runOutsideAngular(() => (this.el[item] = val));
}
});
Object.defineProperty(Prototype, item, {
get() {
return this.el[item];
},
set(val: any) {
this.z.runOutsideAngular(() => (this.el[item] = val));
}
});
});
};
export const proxyMethods = (Cmp: any, methods: string[]) => {
const Prototype = Cmp.prototype;
methods.forEach(methodName => {
Prototype[methodName] = function () {
const args = arguments;
return this.z.runOutsideAngular(() =>
this.el[methodName].apply(this.el, args)
);
};
Prototype[methodName] = function () {
const args = arguments;
return this.z.runOutsideAngular(() =>
this.el[methodName].apply(this.el, args)
);
};
});
};
@@ -31,16 +32,15 @@ export const proxyOutputs = (instance: any, el: any, events: string[]) => {
events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
}
// tslint:disable-next-line: only-arrow-functions
export function ProxyCmp(opts: { inputs?: any; methods?: any }) {
const decorator = function(cls: any){
if (opts.inputs) {
proxyInputs(cls, opts.inputs);
}
if (opts.methods) {
proxyMethods(cls, opts.methods);
}
return cls;
if (opts.inputs) {
proxyInputs(cls, opts.inputs);
}
if (opts.methods) {
proxyMethods(cls, opts.methods);
}
return cls;
};
return decorator;
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -36,5 +36,14 @@ export { GestureController } from './providers/gesture-controller';
// ROUTER STRATEGY
export { IonicRouteStrategy } from './util/ionic-router-reuse-strategy';
// TYPES
export * from './types/ionic-lifecycle-hooks';
// PACKAGE MODULE
export { IonicModule } from './ionic-module';
// UTILS
export { IonicSafeString, getPlatforms, isPlatform } from '@ionic/core';
// CORE TYPES
export { Animation, AnimationBuilder, AnimationCallbackOptions, AnimationDirection, AnimationFill, AnimationKeyFrames, AnimationLifecycle, Gesture, GestureConfig, GestureDetail, mdTransitionAnimation, iosTransitionAnimation } from '@ionic/core';

View File

@@ -1,14 +1,24 @@
import { Injectable } from '@angular/core';
import { Injectable, NgZone } from '@angular/core';
import { Gesture, GestureConfig, createGesture } from '@ionic/core';
@Injectable({
providedIn: 'root',
})
export class GestureController {
constructor(private zone: NgZone) {}
/**
* Create a new gesture
*/
create(opts: GestureConfig): Gesture {
create(opts: GestureConfig, runInsideAngularZone = false): Gesture {
if (runInsideAngularZone) {
Object.getOwnPropertyNames(opts).forEach(key => {
if (typeof opts[key] === 'function') {
const fn = opts[key];
opts[key] = (...props) => this.zone.run(() => fn(...props));
}
});
}
return createGesture(opts);
}
}

View File

@@ -45,7 +45,10 @@ export class NavController {
}
// Subscribe to backButton events
platform.backButton.subscribeWithPriority(0, () => this.pop());
platform.backButton.subscribeWithPriority(0, processNextHandler => {
this.pop();
processNextHandler();
});
}
/**

View File

@@ -1,10 +1,10 @@
import { DOCUMENT } from '@angular/common';
import { Inject, Injectable, NgZone } from '@angular/core';
import { BackButtonEventDetail, Platforms, getPlatforms, isPlatform } from '@ionic/core';
import { BackButtonEventDetail, KeyboardEventDetail, Platforms, getPlatforms, isPlatform } from '@ionic/core';
import { Subject, Subscription } from 'rxjs';
export interface BackButtonEmitter extends Subject<BackButtonEventDetail> {
subscribeWithPriority(priority: number, callback: () => Promise<any> | void): Subscription;
subscribeWithPriority(priority: number, callback: (processNextHandler: () => void) => Promise<any> | void): Subscription;
}
@Injectable({
@@ -20,6 +20,18 @@ export class Platform {
*/
backButton: BackButtonEmitter = new Subject<BackButtonEventDetail>() as any;
/**
* The keyboardDidShow event emits when the
* on-screen keyboard is presented.
*/
keyboardDidShow = new Subject<KeyboardEventDetail>() as any;
/**
* The keyboardDidHide event emits when the
* on-screen keyboard is hidden.
*/
keyboardDidHide = new Subject<void>();
/**
* The pause event emits when the native platform puts the application
* into the background, typically when the user switches to a different
@@ -46,15 +58,17 @@ export class Platform {
zone.run(() => {
this.win = doc.defaultView;
this.backButton.subscribeWithPriority = function(priority, callback) {
return this.subscribe(ev => (
ev.register(priority, () => zone.run(callback))
));
return this.subscribe(ev => {
return ev.register(priority, processNextHandler => zone.run(() => callback(processNextHandler)));
});
};
proxyEvent(this.pause, doc, 'pause');
proxyEvent(this.resume, doc, 'resume');
proxyEvent(this.backButton, doc, 'ionBackButton');
proxyEvent(this.resize, this.win, 'resize');
proxyEvent(this.keyboardDidShow, this.win, 'ionKeyboardDidShow');
proxyEvent(this.keyboardDidHide, this.win, 'ionKeyboardDidHide');
let readyResolve: (value: string) => void;
this._readyPromise = new Promise(res => { readyResolve = res; });

View File

@@ -2,7 +2,7 @@ import { join, Path } from '@angular-devkit/core';
import { apply, chain, mergeWith, move, Rule, SchematicContext, SchematicsException, template, Tree, url } from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
import { addModuleImportToRootModule } from './../utils/ast';
import { addArchitectBuilder, addStyle, getWorkspace, addAsset, WorkspaceProject, WorkspaceSchema } from './../utils/config';
import { addArchitectBuilder, addAsset, addStyle, getDefaultAngularAppName, getWorkspace, WorkspaceProject, WorkspaceSchema } from './../utils/config';
import { addPackageToPackageJson } from './../utils/package';
import { Schema as IonAddOptions } from './schema';
@@ -37,7 +37,7 @@ function addIonicAngularModuleToAppModule(projectSourceRoot: Path): Rule {
};
}
function addIonicStyles(projectSourceRoot: Path): Rule {
function addIonicStyles(projectName: string, projectSourceRoot: Path): Rule {
return (host: Tree) => {
const ionicStyles = [
'node_modules/@ionic/angular/css/normalize.css',
@@ -51,27 +51,27 @@ function addIonicStyles(projectSourceRoot: Path): Rule {
'node_modules/@ionic/angular/css/flex-utils.css',
`${projectSourceRoot}/theme/variables.css`
].forEach(entry => {
addStyle(host, entry);
addStyle(host, projectName, entry);
});
return host;
};
}
function addIonicons(): Rule {
function addIonicons(projectName: string): Rule {
return (host: Tree) => {
const ioniconsGlob = {
glob: '**/*.svg',
input: 'node_modules/ionicons/dist/ionicons/svg',
output: './svg'
};
addAsset(host, ioniconsGlob);
addAsset(host, projectName, ioniconsGlob);
return host;
};
}
function addIonicBuilder(projectName: string): Rule {
return (host: Tree) => {
addArchitectBuilder(host, 'ionic-cordova-serve', {
addArchitectBuilder(host, projectName, 'ionic-cordova-serve', {
builder: '@ionic/angular-toolkit:cordova-serve',
options: {
cordovaBuildTarget: `${projectName}:ionic-cordova-build`,
@@ -84,7 +84,7 @@ function addIonicBuilder(projectName: string): Rule {
}
}
});
addArchitectBuilder(host, 'ionic-cordova-build', {
addArchitectBuilder(host, projectName, 'ionic-cordova-build', {
builder: '@ionic/angular-toolkit:cordova-build',
options: {
browserTarget: `${projectName}:build`
@@ -109,7 +109,7 @@ export default function ngAdd(options: IonAddOptions): Rule {
return (host: Tree) => {
const workspace: WorkspaceSchema = getWorkspace(host);
if (!options.project) {
options.project = Object.keys(workspace.projects)[0];
options.project = getDefaultAngularAppName(workspace);
}
const project: WorkspaceProject = workspace.projects[options.project];
if (project.projectType !== 'application') {
@@ -117,7 +117,7 @@ export default function ngAdd(options: IonAddOptions): Rule {
`Ionic Add requires a project type of "application".`
);
}
const sourcePath: Path = join(project.root as Path, project.sourceRoot as Path);
const sourcePath: Path = join(project.sourceRoot as Path);
const rootTemplateSource = apply(url('./files/root'), [
template({ ...options }),
move(sourcePath)
@@ -128,8 +128,8 @@ export default function ngAdd(options: IonAddOptions): Rule {
addIonicAngularToolkitToPackageJson(),
addIonicAngularModuleToAppModule(sourcePath),
addIonicBuilder(options.project),
addIonicStyles(sourcePath),
addIonicons(),
addIonicStyles(options.project, sourcePath),
addIonicons(options.project),
mergeWith(rootTemplateSource),
// install freshly added dependencies
installNodeDeps()

View File

@@ -27,7 +27,7 @@ export function getSourceFile(host: Tree, path: string): ts.SourceFile {
*/
export function addModuleImportToRootModule(
host: Tree,
projectSourceRoot,
projectSourceRoot: string,
moduleName: string,
importSrc: string
) {

View File

@@ -21,7 +21,7 @@ function isAngularBrowserProject(projectConfig: any) {
return false;
}
export function getAngularAppName(config: any): string | null {
export function getDefaultAngularAppName(config: any): string {
const projects = config.projects;
const projectNames = Object.keys(projects);
@@ -32,60 +32,48 @@ export function getAngularAppName(config: any): string | null {
}
}
return null;
return projectNames[0];
}
export function getAngularAppConfig(config: any): any | null {
const projects = config.projects;
const projectNames = Object.keys(projects);
for (const projectName of projectNames) {
const projectConfig = projects[projectName];
if (isAngularBrowserProject(projectConfig)) {
return projectConfig;
}
export function getAngularAppConfig(config: any, projectName: string): any | never {
if (!config.projects.hasOwnProperty(projectName)) {
throw new SchematicsException(`Could not find project: ${projectName}`);
}
return null;
}
const projectConfig = config.projects[projectName];
if (isAngularBrowserProject(projectConfig)) {
return projectConfig;
}
export function addStyle(host: Tree, stylePath: string) {
const config = readConfig(host);
const appConfig = getAngularAppConfig(config);
if (appConfig) {
appConfig.architect.build.options.styles.push({
input: stylePath
});
writeConfig(host, config);
if (config.projectType !== 'application') {
throw new SchematicsException(`Invalid projectType for ${projectName}: ${config.projectType}`);
} else {
throw new SchematicsException(`Cannot find valid app`);
const buildConfig = projectConfig.architect.build;
throw new SchematicsException(`Invalid builder for ${projectName}: ${buildConfig.builder}`);
}
}
export function addAsset(host: Tree, asset: string | {glob: string; input: string; output: string}) {
export function addStyle(host: Tree, projectName: string, stylePath: string) {
const config = readConfig(host);
const appConfig = getAngularAppConfig(config);
if (appConfig) {
appConfig.architect.build.options.assets.push(asset);
writeConfig(host, config);
} else {
throw new SchematicsException(`Cannot find valid app`);
}
const appConfig = getAngularAppConfig(config, projectName);
appConfig.architect.build.options.styles.push({
input: stylePath
});
writeConfig(host, config);
}
export function addArchitectBuilder(host: Tree, builderName: string, builderOpts: any){
export function addAsset(host: Tree, projectName: string, asset: string | {glob: string; input: string; output: string}) {
const config = readConfig(host);
const appConfig = getAngularAppConfig(config);
const appConfig = getAngularAppConfig(config, projectName);
appConfig.architect.build.options.assets.push(asset);
writeConfig(host, config);
}
if (appConfig) {
appConfig.architect[builderName] = builderOpts
writeConfig(host, config);
} else {
throw new SchematicsException(`Cannot find valid app`);
}
export function addArchitectBuilder(host: Tree, projectName: string, builderName: string, builderOpts: any): void | never {
const config = readConfig(host);
const appConfig = getAngularAppConfig(config, projectName);
appConfig.architect[builderName] = builderOpts;
writeConfig(host, config);
}
export type WorkspaceSchema = experimental.workspace.WorkspaceSchema;

View File

@@ -0,0 +1,31 @@
/**
* https://ionicframework.com/docs/api/router-outlet#life-cycle-hooks
*/
export interface ViewWillEnter {
/**
* Fired when the component routing to is about to animate into view.
*/
ionViewWillEnter(): void;
}
export interface ViewDidEnter {
/**
* Fired when the component routing to has finished animating.
*/
ionViewDidEnter(): void;
}
export interface ViewWillLeave {
/**
* Fired when the component routing from is about to animate.
*/
ionViewWillLeave(): void;
}
export interface ViewDidLeave {
/**
* Fired when the component routing to has finished animating.
*/
ionViewDidLeave(): void;
}

View File

@@ -41,7 +41,7 @@
"@angular/cli": "^9.0.0-rc.2",
"@angular/compiler-cli": "^9.0.0-rc.2",
"@angular/language-service": "^9.0.0-rc.2",
"@nguniversal/builders": "^9.0.0-next.9",
"@nguniversal/builders": "9.0.0-next.9",
"@types/express": "^4.17.0",
"@types/jasmine": "3.4.1",
"@types/node": "^12.11.1",

View File

@@ -1,11 +1,11 @@
import { Component, Input, NgZone, OnInit, Optional } from '@angular/core';
import { ModalController, NavParams, IonNav } from '@ionic/angular';
import { ModalController, NavParams, IonNav, ViewWillLeave, ViewDidEnter, ViewDidLeave } from '@ionic/angular';
@Component({
selector: 'app-modal-example',
templateUrl: './modal-example.component.html',
})
export class ModalExampleComponent implements OnInit {
export class ModalExampleComponent implements OnInit, ViewWillLeave, ViewDidEnter, ViewWillLeave, ViewDidLeave {
@Input() value: string;

View File

@@ -1,11 +1,11 @@
import { Component, OnInit, NgZone } from '@angular/core';
import { IonRouterOutlet } from '@ionic/angular';
import { IonRouterOutlet, ViewDidEnter, ViewDidLeave, ViewWillLeave } from '@ionic/angular';
@Component({
selector: 'app-router-link-page',
templateUrl: './router-link-page.component.html',
})
export class RouterLinkPageComponent implements OnInit {
export class RouterLinkPageComponent implements OnInit, ViewWillLeave, ViewDidEnter, ViewWillLeave, ViewDidLeave {
onInit = 0;
willEnter = 0;

View File

@@ -1,12 +1,12 @@
import { Component, NgZone, OnInit } from '@angular/core';
import { NavController } from '@ionic/angular';
import { NavController, ViewDidEnter, ViewDidLeave, ViewWillEnter, ViewWillLeave } from '@ionic/angular';
import { Router } from '@angular/router';
@Component({
selector: 'app-router-link',
templateUrl: './router-link.component.html',
})
export class RouterLinkComponent implements OnInit {
export class RouterLinkComponent implements OnInit, ViewWillEnter, ViewDidEnter, ViewWillLeave, ViewDidLeave {
onInit = 0;
willEnter = 0;

View File

@@ -1,11 +1,12 @@
import { Component, NgZone, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ViewDidEnter, ViewDidLeave, ViewWillEnter, ViewWillLeave } from '@ionic/angular';
@Component({
selector: 'app-virtual-scroll-detail',
templateUrl: './virtual-scroll-detail.component.html',
})
export class VirtualScrollDetailComponent implements OnInit {
export class VirtualScrollDetailComponent implements OnInit, ViewWillEnter, ViewDidEnter, ViewWillLeave, ViewDidLeave {
onInit = 0;
willEnter = 0;

View File

@@ -23,9 +23,9 @@ The Ionic Core package contains the Web Components that make up the reusable UI
Easiest way to start using Ionic Core is by adding a script tag to the CDN:
```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@4.6.2/dist/ionic/ionic.esm.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core@4.6.2/dist/ionic/ionic.js"></script>
<link href="https://cdn.jsdelivr.net/npm/@ionic/core@4.6.2/css/ionic.bundle.css" rel="stylesheet">
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
<link href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" rel="stylesheet">
```
Any Ionic component added to the webpage will automatically load. This includes writing the component tag directly in HTML, or using JavaScript such as `document.createElement('ion-toggle')`.

View File

@@ -12,8 +12,8 @@ ion-action-sheet,prop,mode,"ios" | "md",undefined,false,false
ion-action-sheet,prop,subHeader,string | undefined,undefined,false,false
ion-action-sheet,prop,translucent,boolean,false,false,false
ion-action-sheet,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
ion-action-sheet,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
ion-action-sheet,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
ion-action-sheet,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-action-sheet,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-action-sheet,method,present,present() => Promise<void>
ion-action-sheet,event,ionActionSheetDidDismiss,OverlayEventDetail<any>,true
ion-action-sheet,event,ionActionSheetDidPresent,void,true
@@ -53,13 +53,13 @@ ion-alert,prop,header,string | 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
ion-alert,prop,message,string | undefined,undefined,false,false
ion-alert,prop,message,IonicSafeString | string | undefined,undefined,false,false
ion-alert,prop,mode,"ios" | "md",undefined,false,false
ion-alert,prop,subHeader,string | undefined,undefined,false,false
ion-alert,prop,translucent,boolean,false,false,false
ion-alert,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
ion-alert,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
ion-alert,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
ion-alert,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-alert,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-alert,method,present,present() => Promise<void>
ion-alert,event,ionAlertDidDismiss,OverlayEventDetail<any>,true
ion-alert,event,ionAlertDidPresent,void,true
@@ -235,6 +235,8 @@ ion-checkbox,css-prop,--checkmark-color
ion-checkbox,css-prop,--checkmark-width
ion-checkbox,css-prop,--size
ion-checkbox,css-prop,--transition
ion-checkbox,part,container
ion-checkbox,part,mark
ion-chip,shadow
ion-chip,prop,color,string | undefined,undefined,false,false
@@ -300,6 +302,8 @@ ion-content,css-prop,--padding-bottom
ion-content,css-prop,--padding-end
ion-content,css-prop,--padding-start
ion-content,css-prop,--padding-top
ion-content,part,background
ion-content,part,scroll
ion-datetime,shadow
ion-datetime,prop,cancelText,string,'Cancel',false,false
@@ -320,7 +324,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; 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?: "ios" | "md" | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
ion-datetime,prop,placeholder,null | string | undefined,undefined,false,false
ion-datetime,prop,readonly,boolean,false,false,false
ion-datetime,prop,value,null | string | undefined,undefined,false,false
@@ -335,6 +339,8 @@ ion-datetime,css-prop,--padding-end
ion-datetime,css-prop,--padding-start
ion-datetime,css-prop,--padding-top
ion-datetime,css-prop,--placeholder-color
ion-datetime,part,placeholder
ion-datetime,part,text
ion-fab,shadow
ion-fab,prop,activated,boolean,false,false,false
@@ -416,6 +422,7 @@ ion-img,prop,src,string | undefined,undefined,false,false
ion-img,event,ionError,void,true
ion-img,event,ionImgDidLoad,void,true
ion-img,event,ionImgWillLoad,void,true
ion-img,part,image
ion-infinite-scroll,none
ion-infinite-scroll,prop,disabled,boolean,false,false,false
@@ -426,12 +433,12 @@ ion-infinite-scroll,event,ionInfinite,void,true
ion-infinite-scroll-content,none
ion-infinite-scroll-content,prop,loadingSpinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false
ion-infinite-scroll-content,prop,loadingText,string | undefined,undefined,false,false
ion-infinite-scroll-content,prop,loadingText,IonicSafeString | string | undefined,undefined,false,false
ion-input,scoped
ion-input,prop,accept,string | undefined,undefined,false,false
ion-input,prop,autocapitalize,string,'off',false,false
ion-input,prop,autocomplete,"off" | "on",'off',false,false
ion-input,prop,autocomplete,"on" | "off" | "name" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "email" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "url" | "photo",'off',false,false
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
@@ -439,6 +446,7 @@ ion-input,prop,clearOnEdit,boolean | undefined,undefined,false,false
ion-input,prop,color,string | undefined,undefined,false,false
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
ion-input,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
ion-input,prop,max,string | undefined,undefined,false,false
ion-input,prop,maxlength,number | undefined,undefined,false,false
@@ -498,7 +506,6 @@ ion-item,css-prop,--border-color
ion-item,css-prop,--border-radius
ion-item,css-prop,--border-style
ion-item,css-prop,--border-width
ion-item,css-prop,--box-shadow
ion-item,css-prop,--color
ion-item,css-prop,--color-activated
ion-item,css-prop,--color-focused
@@ -523,6 +530,7 @@ ion-item,css-prop,--padding-start
ion-item,css-prop,--padding-top
ion-item,css-prop,--ripple-color
ion-item,css-prop,--transition
ion-item,part,detail-icon
ion-item-divider,shadow
ion-item-divider,prop,color,string | undefined,undefined,false,false
@@ -598,14 +606,14 @@ ion-loading,prop,duration,number,0,false,false
ion-loading,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | 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,string | undefined,undefined,false,false
ion-loading,prop,message,IonicSafeString | string | undefined,undefined,false,false
ion-loading,prop,mode,"ios" | "md",undefined,false,false
ion-loading,prop,showBackdrop,boolean,true,false,false
ion-loading,prop,spinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false
ion-loading,prop,translucent,boolean,false,false,false
ion-loading,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
ion-loading,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
ion-loading,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
ion-loading,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-loading,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-loading,method,present,present() => Promise<void>
ion-loading,event,ionLoadingDidDismiss,OverlayEventDetail<any>,true
ion-loading,event,ionLoadingDidPresent,void,true
@@ -646,6 +654,8 @@ ion-menu,css-prop,--max-width
ion-menu,css-prop,--min-height
ion-menu,css-prop,--min-width
ion-menu,css-prop,--width
ion-menu,part,backdrop
ion-menu,part,container
ion-menu-button,shadow
ion-menu-button,prop,autoHide,boolean,true,false,false
@@ -685,8 +695,8 @@ ion-modal,prop,presentingElement,HTMLElement | undefined,undefined,false,false
ion-modal,prop,showBackdrop,boolean,true,false,false
ion-modal,prop,swipeToClose,boolean,false,false,false
ion-modal,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
ion-modal,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
ion-modal,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
ion-modal,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-modal,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-modal,method,present,present() => Promise<void>
ion-modal,event,ionModalDidDismiss,OverlayEventDetail<any>,true
ion-modal,event,ionModalDidPresent,void,true
@@ -751,8 +761,8 @@ ion-picker,prop,mode,"ios" | "md",undefined,false,false
ion-picker,prop,showBackdrop,boolean,true,false,false
ion-picker,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
ion-picker,method,getColumn,getColumn(name: string) => Promise<PickerColumn | undefined>
ion-picker,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
ion-picker,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
ion-picker,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-picker,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-picker,method,present,present() => Promise<void>
ion-picker,event,ionPickerDidDismiss,OverlayEventDetail<any>,true
ion-picker,event,ionPickerDidPresent,void,true
@@ -786,8 +796,8 @@ ion-popover,prop,mode,"ios" | "md",undefined,false,false
ion-popover,prop,showBackdrop,boolean,true,false,false
ion-popover,prop,translucent,boolean,false,false,false
ion-popover,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
ion-popover,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
ion-popover,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
ion-popover,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-popover,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-popover,method,present,present() => Promise<void>
ion-popover,event,ionPopoverDidDismiss,OverlayEventDetail<any>,true
ion-popover,event,ionPopoverDidPresent,void,true
@@ -826,6 +836,8 @@ ion-radio,css-prop,--border-radius
ion-radio,css-prop,--color
ion-radio,css-prop,--color-checked
ion-radio,css-prop,--inner-border-radius
ion-radio,part,container
ion-radio,part,mark
ion-radio-group,none
ion-radio-group,prop,allowEmptySelection,boolean,false,false,false
@@ -861,6 +873,12 @@ ion-range,css-prop,--knob-box-shadow
ion-range,css-prop,--knob-size
ion-range,css-prop,--pin-background
ion-range,css-prop,--pin-color
ion-range,part,bar
ion-range,part,bar-active
ion-range,part,knob
ion-range,part,pin
ion-range,part,tick
ion-range,part,tick-active
ion-refresher,none
ion-refresher,prop,closeDuration,string,'280ms',false,false
@@ -878,11 +896,12 @@ ion-refresher,event,ionStart,void,true
ion-refresher-content,none
ion-refresher-content,prop,pullingIcon,null | string | undefined,undefined,false,false
ion-refresher-content,prop,pullingText,string | undefined,undefined,false,false
ion-refresher-content,prop,pullingText,IonicSafeString | string | undefined,undefined,false,false
ion-refresher-content,prop,refreshingSpinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false
ion-refresher-content,prop,refreshingText,string | undefined,undefined,false,false
ion-refresher-content,prop,refreshingText,IonicSafeString | string | undefined,undefined,false,false
ion-reorder,shadow
ion-reorder,part,icon
ion-reorder-group,none
ion-reorder-group,prop,disabled,boolean,true,false,false
@@ -930,7 +949,7 @@ ion-row,shadow
ion-searchbar,scoped
ion-searchbar,prop,animated,boolean,false,false,false
ion-searchbar,prop,autocomplete,"off" | "on",'off',false,false
ion-searchbar,prop,autocomplete,"on" | "off" | "name" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "email" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "url" | "photo",'off',false,false
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
@@ -938,6 +957,7 @@ ion-searchbar,prop,clearIcon,string | undefined,undefined,false,false
ion-searchbar,prop,color,string | undefined,undefined,false,false
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
ion-searchbar,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
ion-searchbar,prop,mode,"ios" | "md",undefined,false,false
ion-searchbar,prop,placeholder,string,'Search',false,false
@@ -955,6 +975,7 @@ ion-searchbar,event,ionClear,void,true
ion-searchbar,event,ionFocus,void,true
ion-searchbar,event,ionInput,KeyboardEvent,true
ion-searchbar,css-prop,--background
ion-searchbar,css-prop,--border-radius
ion-searchbar,css-prop,--box-shadow
ion-searchbar,css-prop,--cancel-button-color
ion-searchbar,css-prop,--clear-button-color
@@ -1033,6 +1054,9 @@ ion-select,css-prop,--padding-start
ion-select,css-prop,--padding-top
ion-select,css-prop,--placeholder-color
ion-select,css-prop,--placeholder-opacity
ion-select,part,icon
ion-select,part,placeholder
ion-select,part,text
ion-select-option,shadow
ion-select-option,prop,disabled,boolean,false,false,false
@@ -1163,6 +1187,8 @@ ion-textarea,prop,color,string | undefined,undefined,false,false
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
ion-textarea,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
ion-textarea,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
ion-textarea,prop,maxlength,number | undefined,undefined,false,false
ion-textarea,prop,minlength,number | undefined,undefined,false,false
ion-textarea,prop,mode,"ios" | "md",undefined,false,false
@@ -1211,13 +1237,13 @@ ion-toast,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefin
ion-toast,prop,header,string | 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,string | undefined,undefined,false,false
ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,false
ion-toast,prop,mode,"ios" | "md",undefined,false,false
ion-toast,prop,position,"bottom" | "middle" | "top",'bottom',false,false
ion-toast,prop,translucent,boolean,false,false,false
ion-toast,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
ion-toast,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
ion-toast,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
ion-toast,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-toast,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-toast,method,present,present() => Promise<void>
ion-toast,event,ionToastDidDismiss,OverlayEventDetail<any>,true
ion-toast,event,ionToastDidPresent,void,true
@@ -1238,6 +1264,7 @@ ion-toast,css-prop,--max-width
ion-toast,css-prop,--min-height
ion-toast,css-prop,--min-width
ion-toast,css-prop,--start
ion-toast,css-prop,--white-space
ion-toast,css-prop,--width
ion-toggle,shadow
@@ -1256,6 +1283,14 @@ ion-toggle,css-prop,--border-radius
ion-toggle,css-prop,--handle-background
ion-toggle,css-prop,--handle-background-checked
ion-toggle,css-prop,--handle-border-radius
ion-toggle,css-prop,--handle-box-shadow
ion-toggle,css-prop,--handle-height
ion-toggle,css-prop,--handle-max-height
ion-toggle,css-prop,--handle-spacing
ion-toggle,css-prop,--handle-transition
ion-toggle,css-prop,--handle-width
ion-toggle,part,handle
ion-toggle,part,track
ion-toolbar,shadow
ion-toolbar,prop,color,string | undefined,undefined,false,false

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "5.0.0-rc.2",
"version": "5.1.1",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -30,16 +30,16 @@
"loader/"
],
"dependencies": {
"ionicons": "5.0.0-17",
"ionicons": "^5.0.1",
"tslib": "^1.10.0"
},
"devDependencies": {
"@stencil/core": "1.8.3",
"@stencil/sass": "1.0.1",
"@types/jest": "24.0.21",
"@stencil/core": "1.13.0",
"@stencil/sass": "1.3.1",
"@types/jest": "24.9.1",
"@types/node": "12.12.3",
"@types/puppeteer": "1.19.1",
"@types/swiper": "4.4.4",
"@types/swiper": "5.3.1",
"aws-sdk": "^2.497.0",
"clean-css-cli": "^4.1.11",
"domino": "^2.1.3",
@@ -49,13 +49,13 @@
"np": "^5.0.3",
"pixelmatch": "4.0.2",
"puppeteer": "1.20.0",
"rollup": "1.19.4",
"rollup": "1.32.0",
"rollup-plugin-node-resolve": "5.2.0",
"rollup-plugin-virtual": "^1.0.1",
"sass": "^1.22.9",
"stylelint": "10.1.0",
"stylelint-order": "3.0.1",
"swiper": "4.5.1",
"swiper": "5.4.1",
"tslint": "^5.10.0",
"tslint-ionic-rules": "0.0.21",
"tslint-react": "^3.6.0"
@@ -65,6 +65,7 @@
"build.vendor": "rollup --config ./scripts/swiper.rollup.config.js",
"build.css": "npm run css.sass && npm run css.minify",
"build.debug": "npm run clean && stencil build --debug",
"build.docs": "stencil build --docs",
"build.docs.json": "stencil build --docs-json dist/docs.json",
"clean": "node scripts/clean.js",
"cdnloader": "node scripts/copy-cdn-loader.js",

View File

@@ -35,6 +35,9 @@ function generateComponent(component, content) {
component.styles.forEach(prop => {
content.push(`${component.tag},css-prop,${prop.name}`);
});
component.parts.forEach(part => {
content.push(`${component.tag},part,${part.name}`);
});
}
exports.apiSpecGenerator = apiSpecGenerator;

12002
core/src/components.d.ts vendored
View File

File diff suppressed because it is too large Load Diff

View File

@@ -21,5 +21,5 @@ export interface ActionSheetButton {
role?: 'cancel' | 'destructive' | 'selected' | string;
icon?: string;
cssClass?: string | string[];
handler?: () => boolean | void | Promise<boolean>;
handler?: () => boolean | void | Promise<boolean | void>;
}

View File

@@ -134,6 +134,8 @@
@include margin-horizontal(null, $action-sheet-ios-button-icon-padding-right);
font-size: $action-sheet-ios-button-icon-font-size;
pointer-events: none;
}
.action-sheet-button:last-child {

View File

@@ -121,7 +121,7 @@ $action-sheet-ios-button-background: linear-gradien
$action-sheet-ios-button-background-activated: $text-color !default;
/// @prop - Background color of the selected action sheet button
$action-sheet-ios-button-background-selected: $background-color !default;
$action-sheet-ios-button-background-selected: var(--ion-color-step-150, $background-color) !default;
/// @prop - Destructive text color of the action sheet button
$action-sheet-ios-button-destructive-text-color: ion-color(danger, base) !default;

View File

@@ -52,6 +52,8 @@
display: block;
position: fixed;
outline: none;
font-family: $font-family-base;
touch-action: none;
@@ -110,6 +112,7 @@
flex-shrink: 0;
align-items: center;
justify-content: center;
pointer-events: none;
width: 100%;
height: 100%;
@@ -210,4 +213,4 @@
opacity: var(--button-background-hover-opacity);
}
}
}
}

View File

@@ -1,7 +1,9 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h } from '@stencil/core';
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 { Gesture } from '../../utils/gesture';
import { createButtonActiveGesture } from '../../utils/gesture/button-active';
import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays';
import { getClassMap } from '../../utils/theme';
@@ -25,7 +27,9 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
presented = false;
animation?: any;
mode = getIonMode(this);
private wrapperEl?: HTMLElement;
private groupEl?: HTMLElement;
private gesture?: Gesture;
@Element() el!: HTMLIonActionSheetElement;
@@ -135,7 +139,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
* Returns a promise that resolves when the action sheet did dismiss.
*/
@Method()
onDidDismiss(): Promise<OverlayEventDetail> {
onDidDismiss<T = any>(): Promise<OverlayEventDetail<T>> {
return eventMethod(this.el, 'ionActionSheetDidDismiss');
}
@@ -144,7 +148,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
*
*/
@Method()
onWillDismiss(): Promise<OverlayEventDetail> {
onWillDismiss<T = any>(): Promise<OverlayEventDetail<T>> {
return eventMethod(this.el, 'ionActionSheetWillDismiss');
}
@@ -193,6 +197,35 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
}
}
componentDidUnload() {
if (this.gesture) {
this.gesture.destroy();
this.gesture = undefined;
}
}
componentDidLoad() {
/**
* Do not create gesture if:
* 1. A gesture already exists
* 2. App is running in MD mode
* 3. A wrapper ref does not exist
*/
const { groupEl, wrapperEl } = this;
if (this.gesture || getIonMode(this) === 'md' || !wrapperEl || !groupEl) { return; }
readTask(() => {
const isScrollable = groupEl.scrollHeight > groupEl.clientHeight;
if (!isScrollable) {
this.gesture = createButtonActiveGesture(
wrapperEl,
(refEl: HTMLElement) => refEl.classList.contains('action-sheet-button')
);
this.gesture.enable(true);
}
});
}
render() {
const mode = getIonMode(this);
const allButtons = this.getButtons();
@@ -203,6 +236,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
<Host
role="dialog"
aria-modal="true"
tabindex="-1"
style={{
zIndex: `${20000 + this.overlayIndex}`,
}}
@@ -216,9 +250,9 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
onIonBackdropTap={this.onBackdropTap}
>
<ion-backdrop tappable={this.backdropDismiss}/>
<div class="action-sheet-wrapper" role="dialog">
<div class="action-sheet-wrapper ion-wrapper" role="dialog" ref={el => this.wrapperEl = el}>
<div class="action-sheet-container">
<div class="action-sheet-group">
<div class="action-sheet-group" ref={el => this.groupEl = el}>
{this.header !== undefined &&
<div class="action-sheet-title">
{this.header}

View File

@@ -11,7 +11,11 @@ export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop')!)
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)');
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
.beforeStyles({
'pointer-events': 'none'
})
.afterClearStyles(['pointer-events']);
wrapperAnimation
.addElement(baseEl.querySelector('.action-sheet-wrapper')!)

View File

@@ -11,7 +11,11 @@ export const mdEnterAnimation = (baseEl: HTMLElement): Animation => {
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop')!)
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)');
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
.beforeStyles({
'pointer-events': 'none'
})
.afterClearStyles(['pointer-events']);
wrapperAnimation
.addElement(baseEl.querySelector('.action-sheet-wrapper')!)

View File

@@ -2,14 +2,38 @@
An Action Sheet is a dialog that displays a set of options. It appears on top of the app's content, and must be manually dismissed by the user before they can resume interaction with the app. Destructive options are made obvious in `ios` mode. There are multiple ways to dismiss the action sheet, including tapping the backdrop or hitting the escape key on desktop.
### Creating
An action sheet can be created by the [Action Sheet Controller](../action-sheet-controller) from an array of `buttons`, with each button including properties for its `text`, and optionally a `handler` and `role`. If a handler returns `false` then the action sheet will not be dismissed. An action sheet can also optionally have a `header` and a `subHeader`.
### Buttons
## Buttons
A button's `role` property can either be `destructive` or `cancel`. Buttons without a role property will have the default look for the platform. Buttons with the `cancel` role will always load as the bottom button, no matter where they are in the array. All other buttons will be displayed in the order they have been added to the `buttons` array. Note: We recommend that `destructive` buttons are always the first button in the array, making them the top button. Additionally, if the action sheet is dismissed by tapping the backdrop, then it will fire the handler from the button with the cancel role.
## Customization
Action Sheet uses scoped encapsulation, which means it will automatically scope its CSS by appending each of the styles with an additional class at runtime. Overriding scoped selectors in CSS requires a [higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) selector.
We recommend passing a custom class to `cssClass` in the `create` method and using that to add custom styles to the host and inner elements. This property can also accept multiple classes separated by spaces. View the [Usage](#usage) section for an example of how to pass a class using `cssClass`.
```css
/* DOES NOT WORK - not specific enough */
.action-sheet-group {
background: #e5e5e5;
}
/* Works - pass "my-custom-class" in cssClass to increase specificity */
.my-custom-class .action-sheet-group {
background: #e5e5e5;
}
```
Any of the defined [CSS Custom Properties](#css-custom-properties) can be used to style the Action Sheet without needing to target individual elements:
```css
.my-custom-class {
--background: #e5e5e5;
}
```
> 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.
<!-- Auto Generated Below -->
@@ -34,6 +58,7 @@ export class ActionSheetExample {
async presentActionSheet() {
const actionSheet = await this.actionSheetController.create({
header: 'Albums',
cssClass: 'my-custom-class',
buttons: [{
text: 'Delete',
role: 'destructive',
@@ -49,7 +74,7 @@ export class ActionSheetExample {
}
}, {
text: 'Play (open modal)',
icon: 'arrow-dropright-circle',
icon: 'caret-forward-circle',
handler: () => {
console.log('Play clicked');
}
@@ -75,14 +100,19 @@ export class ActionSheetExample {
```
### Style Placement
In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Action Sheet can be presented from within a page, the `ion-action-sheet` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config).
### Javascript
```javascript
async function presentActionSheet() {
const actionSheet = document.createElement('ion-action-sheet');
actionSheet.header = "Albums";
actionSheet.header = 'Albums';
actionSheet.cssClass = 'my-custom-class';
actionSheet.buttons = [{
text: 'Delete',
role: 'destructive',
@@ -98,7 +128,7 @@ async function presentActionSheet() {
}
}, {
text: 'Play (open modal)',
icon: 'arrow-dropright-circle',
icon: 'caret-forward-circle',
handler: () => {
console.log('Play clicked');
}
@@ -124,48 +154,51 @@ async function presentActionSheet() {
### React
```typescript
import React, { useState } from 'react'
```tsx
import React, { useState } from 'react';
import { IonActionSheet, IonContent, IonButton } from '@ionic/react';
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';
export const ActionSheetExample: React.FC = () => {
const [showActionSheet, setShowActionSheet] = useState(false);
return (
<IonContent>
<IonButton onClick={() => setShowActionSheet(true)} expand="block">Show Action Sheet</IonButton>
<IonButton onClick={() => setShowActionSheet(true)} expand="block">
Show Action Sheet
</IonButton>
<IonActionSheet
isOpen={showActionSheet}
onDidDismiss={() => setShowActionSheet(false)}
cssClass='my-custom-class'
buttons={[{
text: 'Delete',
role: 'destructive',
icon: 'trash',
icon: trash,
handler: () => {
console.log('Delete clicked');
}
}, {
text: 'Share',
icon: 'share',
icon: share,
handler: () => {
console.log('Share clicked');
}
}, {
text: 'Play (open modal)',
icon: 'arrow-dropright-circle',
icon: caretForwardCircle,
handler: () => {
console.log('Play clicked');
}
}, {
text: 'Favorite',
icon: 'heart',
icon: heart,
handler: () => {
console.log('Favorite clicked');
}
}, {
text: 'Cancel',
icon: 'close',
icon: close,
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
@@ -174,11 +207,72 @@ export const ActionSheetExample: React.FC = () => {
>
</IonActionSheet>
</IonContent>
);
}
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
import { actionSheetController } from '@ionic/core';
@Component({
tag: 'action-sheet-example',
styleUrl: 'action-sheet-example.css'
})
export class ActionSheetExample {
async presentActionSheet() {
const actionSheet = await actionSheetController.create({
header: 'Albums',
cssClass: 'my-custom-class',
buttons: [{
text: 'Delete',
role: 'destructive',
icon: 'trash',
handler: () => {
console.log('Delete clicked');
}
}, {
text: 'Share',
icon: 'share',
handler: () => {
console.log('Share clicked');
}
}, {
text: 'Play (open modal)',
icon: 'caret-forward-circle',
handler: () => {
console.log('Play clicked');
}
}, {
text: 'Favorite',
icon: 'heart',
handler: () => {
console.log('Favorite clicked');
}
}, {
text: 'Cancel',
icon: 'close',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}]
});
await actionSheet.present();
}
render() {
return [
<ion-content>
<ion-button onClick={() => this.presentActionSheet()}>Present Action Sheet</ion-button>
</ion-content>
];
}
}
```
@@ -198,6 +292,7 @@ export default {
return this.$ionic.actionSheetController
.create({
header: 'Albums',
cssClass: 'my-custom-class',
buttons: [
{
text: 'Delete',
@@ -216,7 +311,7 @@ export default {
},
{
text: 'Play (open modal)',
icon: 'arrow-dropright-circle',
icon: 'caret-forward-circle',
handler: () => {
console.log('Play clicked')
},
@@ -286,23 +381,23 @@ Type: `Promise<boolean>`
### `onDidDismiss() => Promise<OverlayEventDetail<any>>`
### `onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>`
Returns a promise that resolves when the action sheet did dismiss.
#### Returns
Type: `Promise<OverlayEventDetail<any>>`
Type: `Promise<OverlayEventDetail<T>>`
### `onWillDismiss() => Promise<OverlayEventDetail<any>>`
### `onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>`
Returns a promise that resolves when the action sheet will dismiss.
#### Returns
Type: `Promise<OverlayEventDetail<any>>`
Type: `Promise<OverlayEventDetail<T>>`

View File

@@ -14,6 +14,7 @@ export class ActionSheetExample {
async presentActionSheet() {
const actionSheet = await this.actionSheetController.create({
header: 'Albums',
cssClass: 'my-custom-class',
buttons: [{
text: 'Delete',
role: 'destructive',
@@ -29,7 +30,7 @@ export class ActionSheetExample {
}
}, {
text: 'Play (open modal)',
icon: 'arrow-dropright-circle',
icon: 'caret-forward-circle',
handler: () => {
console.log('Play clicked');
}
@@ -53,3 +54,8 @@ export class ActionSheetExample {
}
```
### Style Placement
In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Action Sheet can be presented from within a page, the `ion-action-sheet` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config).

View File

@@ -1,9 +1,9 @@
```javascript
async function presentActionSheet() {
const actionSheet = document.createElement('ion-action-sheet');
actionSheet.header = "Albums";
actionSheet.header = 'Albums';
actionSheet.cssClass = 'my-custom-class';
actionSheet.buttons = [{
text: 'Delete',
role: 'destructive',
@@ -19,7 +19,7 @@ async function presentActionSheet() {
}
}, {
text: 'Play (open modal)',
icon: 'arrow-dropright-circle',
icon: 'caret-forward-circle',
handler: () => {
console.log('Play clicked');
}

View File

@@ -1,45 +1,48 @@
```typescript
import React, { useState } from 'react'
```tsx
import React, { useState } from 'react';
import { IonActionSheet, IonContent, IonButton } from '@ionic/react';
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';
export const ActionSheetExample: React.FC = () => {
const [showActionSheet, setShowActionSheet] = useState(false);
return (
<IonContent>
<IonButton onClick={() => setShowActionSheet(true)} expand="block">Show Action Sheet</IonButton>
<IonButton onClick={() => setShowActionSheet(true)} expand="block">
Show Action Sheet
</IonButton>
<IonActionSheet
isOpen={showActionSheet}
onDidDismiss={() => setShowActionSheet(false)}
cssClass='my-custom-class'
buttons={[{
text: 'Delete',
role: 'destructive',
icon: 'trash',
icon: trash,
handler: () => {
console.log('Delete clicked');
}
}, {
text: 'Share',
icon: 'share',
icon: share,
handler: () => {
console.log('Share clicked');
}
}, {
text: 'Play (open modal)',
icon: 'arrow-dropright-circle',
icon: caretForwardCircle,
handler: () => {
console.log('Play clicked');
}
}, {
text: 'Favorite',
icon: 'heart',
icon: heart,
handler: () => {
console.log('Favorite clicked');
}
}, {
text: 'Cancel',
icon: 'close',
icon: close,
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
@@ -48,9 +51,6 @@ export const ActionSheetExample: React.FC = () => {
>
</IonActionSheet>
</IonContent>
);
}
```

View File

@@ -0,0 +1,60 @@
```tsx
import { Component, h } from '@stencil/core';
import { actionSheetController } from '@ionic/core';
@Component({
tag: 'action-sheet-example',
styleUrl: 'action-sheet-example.css'
})
export class ActionSheetExample {
async presentActionSheet() {
const actionSheet = await actionSheetController.create({
header: 'Albums',
cssClass: 'my-custom-class',
buttons: [{
text: 'Delete',
role: 'destructive',
icon: 'trash',
handler: () => {
console.log('Delete clicked');
}
}, {
text: 'Share',
icon: 'share',
handler: () => {
console.log('Share clicked');
}
}, {
text: 'Play (open modal)',
icon: 'caret-forward-circle',
handler: () => {
console.log('Play clicked');
}
}, {
text: 'Favorite',
icon: 'heart',
handler: () => {
console.log('Favorite clicked');
}
}, {
text: 'Cancel',
icon: 'close',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}]
});
await actionSheet.present();
}
render() {
return [
<ion-content>
<ion-button onClick={() => this.presentActionSheet()}>Present Action Sheet</ion-button>
</ion-content>
];
}
}
```

View File

@@ -12,6 +12,7 @@ export default {
return this.$ionic.actionSheetController
.create({
header: 'Albums',
cssClass: 'my-custom-class',
buttons: [
{
text: 'Delete',
@@ -30,7 +31,7 @@ export default {
},
{
text: 'Play (open modal)',
icon: 'arrow-dropright-circle',
icon: 'caret-forward-circle',
handler: () => {
console.log('Play clicked')
},

View File

@@ -1,9 +1,12 @@
import { JSXBase } from '@stencil/core/internal';
import { AnimationBuilder, Mode, TextFieldTypes } from '../../interface';
import { IonicSafeString } from '../../utils/sanitization';
export interface AlertOptions {
header?: string;
subHeader?: string;
message?: string;
message?: string | IonicSafeString;
cssClass?: string | string[];
inputs?: AlertInput[];
buttons?: (AlertButton | string)[];
@@ -31,8 +34,13 @@ export interface AlertInput {
handler?: (input: AlertInput) => void;
min?: string | number;
max?: string | number;
cssClass?: string | string[];
attributes?: AlertInputAttributes | AlertTextareaAttributes;
}
export interface AlertTextareaAttributes extends JSXBase.TextareaHTMLAttributes<HTMLTextAreaElement> {}
export interface AlertInputAttributes extends JSXBase.InputHTMLAttributes<HTMLInputElement> {}
export interface AlertButton {
text: string;
role?: string;

View File

@@ -19,6 +19,10 @@
overflow: hidden;
}
.alert-button .alert-button-inner {
pointer-events: none;
}
// iOS Translucent Alert
// -----------------------------------------
@@ -301,3 +305,12 @@
.alert-button.ion-activated {
background-color: $alert-ios-button-background-color-activated;
}
// iOS Action Sheet Button: Destructive
// ---------------------------------------------------
.alert-button-role-destructive,
.alert-button-role-destructive.ion-activated,
.alert-button-role-destructive.ion-focused {
color: $alert-ios-button-destructive-text-color;
}

View File

@@ -145,6 +145,9 @@ $alert-ios-button-font-size: 17px !default;
/// @prop - Color of the text in the alert button
$alert-ios-button-text-color: ion-color(primary, base) !default;
/// @prop - Destructive text color of the alert button
$alert-ios-button-destructive-text-color: ion-color(danger, base) !default;
/// @prop - Background color of the alert button
$alert-ios-button-background-color: transparent !default;

View File

@@ -32,6 +32,8 @@
align-items: center;
justify-content: center;
outline: none;
font-family: $font-family-base;
contain: strict;

View File

@@ -1,9 +1,11 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, Watch, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, Watch, forceUpdate, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { AlertButton, AlertInput, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
import { AlertButton, AlertInput, AlertInputAttributes, AlertTextareaAttributes, 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';
import { sanitizeDOMString } from '../../utils/sanitization';
import { IonicSafeString, sanitizeDOMString } from '../../utils/sanitization';
import { getClassMap } from '../../utils/theme';
import { iosEnterAnimation } from './animations/ios.enter';
@@ -28,9 +30,10 @@ export class Alert implements ComponentInterface, OverlayInterface {
private inputType?: string;
private processedInputs: AlertInput[] = [];
private processedButtons: AlertButton[] = [];
private wrapperEl?: HTMLElement;
private gesture?: Gesture;
presented = false;
mode = getIonMode(this);
@Element() el!: HTMLIonAlertElement;
@@ -77,7 +80,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
*
* For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
*/
@Prop() message?: string;
@Prop() message?: string | IonicSafeString;
/**
* Array of buttons to be added to the alert.
@@ -158,7 +161,9 @@ export class Alert implements ComponentInterface, OverlayInterface {
id: i.id || `alert-input-${this.overlayIndex}-${index}`,
handler: i.handler,
min: i.min,
max: i.max
max: i.max,
cssClass: i.cssClass || '',
attributes: i.attributes || {},
}) as AlertInput);
}
@@ -171,6 +176,29 @@ export class Alert implements ComponentInterface, OverlayInterface {
this.buttonsChanged();
}
componentDidUnload() {
if (this.gesture) {
this.gesture.destroy();
this.gesture = undefined;
}
}
componentDidLoad() {
/**
* Do not create gesture if:
* 1. A gesture already exists
* 2. App is running in MD mode
* 3. A wrapper ref does not exist
*/
if (this.gesture || getIonMode(this) === 'md' || !this.wrapperEl) { return; }
this.gesture = createButtonActiveGesture(
this.wrapperEl,
(refEl: HTMLElement) => refEl.classList.contains('alert-button')
);
this.gesture.enable(true);
}
/**
* Present the alert overlay after it has been created.
*/
@@ -197,7 +225,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
* Returns a promise that resolves when the alert did dismiss.
*/
@Method()
onDidDismiss(): Promise<OverlayEventDetail> {
onDidDismiss<T = any>(): Promise<OverlayEventDetail<T>> {
return eventMethod(this.el, 'ionAlertDidDismiss');
}
@@ -205,7 +233,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
* Returns a promise that resolves when the alert will dismiss.
*/
@Method()
onWillDismiss(): Promise<OverlayEventDetail> {
onWillDismiss<T = any>(): Promise<OverlayEventDetail<T>> {
return eventMethod(this.el, 'ionAlertWillDismiss');
}
@@ -215,13 +243,13 @@ export class Alert implements ComponentInterface, OverlayInterface {
}
this.activeId = selectedInput.id;
safeCall(selectedInput.handler, selectedInput);
this.el.forceUpdate();
forceUpdate(this);
}
private cbClick(selectedInput: AlertInput) {
selectedInput.checked = !selectedInput.checked;
safeCall(selectedInput.handler, selectedInput);
this.el.forceUpdate();
forceUpdate(this);
}
private buttonClick(button: AlertButton) {
@@ -307,6 +335,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
tabIndex={0}
role="checkbox"
class={{
...getClassMap(i.cssClass),
'alert-tappable': true,
'alert-checkbox': true,
'alert-checkbox-button': true,
@@ -345,6 +374,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
id={i.id}
tabIndex={0}
class={{
...getClassMap(i.cssClass),
'alert-radio-button': true,
'alert-tappable': true,
'alert-radio': true,
@@ -379,13 +409,14 @@ export class Alert implements ComponentInterface, OverlayInterface {
<textarea
placeholder={i.placeholder}
value={i.value}
onInput={e => i.value = (e.target as any).value}
id={i.id}
disabled={i.disabled}
tabIndex={0}
class={{
'alert-input': true,
'alert-input-disabled': i.disabled || false
{...i.attributes as AlertTextareaAttributes}
disabled={i.attributes?.disabled ?? i.disabled}
class={inputClass(i)}
onInput={e => {
i.value = (e.target as any).value;
if (i.attributes?.onInput) { i.attributes.onInput(e); }
}}
/>
</div>
@@ -395,17 +426,18 @@ export class Alert implements ComponentInterface, OverlayInterface {
<div class="alert-input-wrapper">
<input
placeholder={i.placeholder}
value={i.value}
type={i.type}
min={i.min}
max={i.max}
onInput={e => i.value = (e.target as any).value}
value={i.value}
id={i.id}
disabled={i.disabled}
tabIndex={0}
class={{
'alert-input': true,
'alert-input-disabled': i.disabled || false
{...i.attributes as AlertInputAttributes}
disabled={i.attributes?.disabled ?? i.disabled}
class={inputClass(i)}
onInput={e => {
i.value = (e.target as any).value;
if (i.attributes?.onInput) { i.attributes.onInput(e); }
}}
/>
</div>
@@ -467,6 +499,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
<Host
role="dialog"
aria-modal="true"
tabindex="-1"
style={{
zIndex: `${20000 + overlayIndex}`,
}}
@@ -481,7 +514,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
<ion-backdrop tappable={this.backdropDismiss}/>
<div class="alert-wrapper">
<div class="alert-wrapper ion-wrapper" ref={el => this.wrapperEl = el}>
<div class="alert-head">
{header && <h2 id={hdrId} class="alert-title">{header}</h2>}
@@ -499,11 +532,21 @@ export class Alert implements ComponentInterface, OverlayInterface {
}
}
const inputClass = (input: AlertInput): CssClassMap => {
return {
'alert-input': true,
'alert-input-disabled': (input.attributes?.disabled ?? input.disabled) || false,
...getClassMap(input.cssClass),
...getClassMap(input.attributes ? input.attributes.class?.toString() : ''),
};
};
const buttonClass = (button: AlertButton): CssClassMap => {
return {
'alert-button': true,
'ion-focusable': true,
'ion-activatable': true,
[`alert-button-role-${button.role}`]: button.role !== undefined,
...getClassMap(button.cssClass)
};
};

View File

@@ -11,7 +11,11 @@ export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop')!)
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)');
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
.beforeStyles({
'pointer-events': 'none'
})
.afterClearStyles(['pointer-events']);
wrapperAnimation
.addElement(baseEl.querySelector('.alert-wrapper')!)

View File

@@ -11,7 +11,11 @@ export const mdEnterAnimation = (baseEl: HTMLElement): Animation => {
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop')!)
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)');
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
.beforeStyles({
'pointer-events': 'none'
})
.afterClearStyles(['pointer-events']);
wrapperAnimation
.addElement(baseEl.querySelector('.alert-wrapper')!)

View File

@@ -2,23 +2,45 @@
An Alert is a dialog that presents users with information or collects information from the user using inputs. An alert appears on top of the app's content, and must be manually dismissed by the user before they can resume interaction with the app. It can also optionally have a `header`, `subHeader` and `message`.
### Creating
Alerts can be created using an [Alert Controller](../alert-controller). They can be customized by passing alert options in the alert controller's create method.
### Buttons
## Buttons
In the array of `buttons`, each button includes properties for its `text`, and optionally a `handler`. If a handler returns `false` then the alert will not automatically be dismissed when the button is clicked. All buttons will show up in the order they have been added to the `buttons` array from left to right. Note: The right most button (the last one in the array) is the main button.
Optionally, a `role` property can be added to a button, such as `cancel`. If a `cancel` role is on one of the buttons, then if the alert is dismissed by tapping the backdrop, then it will fire the handler from the button with a cancel role.
### Inputs
## Inputs
Alerts can also include several different inputs whose data can be passed back to the app. Inputs can be used as a simple way to prompt users for information. Radios, checkboxes and text inputs are all accepted, but they cannot be mixed. For example, an alert could have all radio button inputs, or all checkbox inputs, but the same alert cannot mix radio and checkbox inputs. Do note however, different types of "text" inputs can be mixed, such as `url`, `email`, `text`, `textarea` etc. If you require a complex form UI which doesn't fit within the guidelines of an alert then we recommend building the form within a modal instead.
## Customization
Alert uses scoped encapsulation, which means it will automatically scope its CSS by appending each of the styles with an additional class at runtime. Overriding scoped selectors in CSS requires a [higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) selector.
We recommend passing a custom class to `cssClass` in the `create` method and using that to add custom styles to the host and inner elements. This property can also accept multiple classes separated by spaces. View the [Usage](#usage) section for an example of how to pass a class using `cssClass`.
```css
/* DOES NOT WORK - not specific enough */
.alert-wrapper {
background: #e5e5e5;
}
/* Works - pass "my-custom-class" in cssClass to increase specificity */
.my-custom-class .alert-wrapper {
background: #e5e5e5;
}
```
Any of the defined [CSS Custom Properties](#css-custom-properties) can be used to style the Alert without needing to target individual elements:
```css
.my-custom-class {
--background: #e5e5e5;
}
```
> 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.
<!-- Auto Generated Below -->
@@ -42,6 +64,7 @@ export class AlertExample {
async presentAlert() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
@@ -53,6 +76,7 @@ export class AlertExample {
async presentAlertMultipleButtons() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
@@ -64,6 +88,7 @@ export class AlertExample {
async presentAlertConfirm() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
buttons: [
@@ -88,6 +113,7 @@ export class AlertExample {
async presentAlertPrompt() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Prompt!',
inputs: [
{
@@ -136,6 +162,16 @@ export class AlertExample {
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
],
buttons: [
@@ -160,6 +196,7 @@ export class AlertExample {
async presentAlertRadio() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Radio',
inputs: [
{
@@ -222,6 +259,7 @@ export class AlertExample {
async presentAlertCheckbox() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Checkbox',
inputs: [
{
@@ -286,16 +324,21 @@ export class AlertExample {
await alert.present();
}
}
```
### Style Placement
In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Alert can be presented from within a page, the `ion-alert` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config).
### Javascript
```javascript
function presentAlert() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Alert';
alert.subHeader = 'Subtitle';
alert.message = 'This is an alert message.';
@@ -307,6 +350,7 @@ function presentAlert() {
function presentAlertMultipleButtons() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Alert';
alert.subHeader = 'Subtitle';
alert.message = 'This is an alert message.';
@@ -318,6 +362,7 @@ function presentAlertMultipleButtons() {
function presentAlertConfirm() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Confirm!';
alert.message = 'Message <strong>text</strong>!!!';
alert.buttons = [
@@ -342,6 +387,7 @@ function presentAlertConfirm() {
function presentAlertPrompt() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Prompt!';
alert.inputs = [
{
@@ -387,6 +433,16 @@ function presentAlertPrompt() {
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
];
alert.buttons = [
@@ -411,6 +467,7 @@ function presentAlertPrompt() {
function presentAlertRadio() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Radio';
alert.inputs = [
{
@@ -466,6 +523,7 @@ function presentAlertRadio() {
function presentAlertCheckbox() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Checkbox';
alert.inputs = [
{
@@ -553,6 +611,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert1}
onDidDismiss={() => setShowAlert1(false)}
cssClass='my-custom-class'
header={'Alert'}
subHeader={'Subtitle'}
message={'This is an alert message.'}
@@ -562,6 +621,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert2}
onDidDismiss={() => setShowAlert2(false)}
cssClass='my-custom-class'
header={'Alert'}
subHeader={'Subtitle'}
message={'This is an alert message.'}
@@ -571,6 +631,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert3}
onDidDismiss={() => setShowAlert3(false)}
cssClass='my-custom-class'
header={'Confirm!'}
message={'Message <strong>text</strong>!!!'}
buttons={[
@@ -594,6 +655,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert4}
onDidDismiss={() => setShowAlert4(false)}
cssClass='my-custom-class'
header={'Prompt!'}
inputs={[
{
@@ -635,6 +697,16 @@ export const AlertExample: React.FC = () => {
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
]}
buttons={[
@@ -658,6 +730,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert5}
onDidDismiss={() => setShowAlert5(false)}
cssClass='my-custom-class'
header={'Radio'}
inputs={[
{
@@ -719,6 +792,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert6}
onDidDismiss={() => setShowAlert6(false)}
cssClass='my-custom-class'
header={'Checkbox'}
inputs={[
{
@@ -785,6 +859,298 @@ export default AlertExample;
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
import { alertController } from '@ionic/core';
@Component({
tag: 'alert-example',
styleUrl: 'alert-example.css'
})
export class AlertExample {
async presentAlert() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
buttons: ['OK']
});
await alert.present();
}
async presentAlertMultipleButtons() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
buttons: ['Cancel', 'Open Modal', 'Delete']
});
await alert.present();
}
async presentAlertConfirm() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: (blah) => {
console.log('Confirm Cancel: blah');
}
}, {
text: 'Okay',
handler: () => {
console.log('Confirm Okay');
}
}
]
});
await alert.present();
}
async presentAlertPrompt() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Prompt!',
inputs: [
{
name: 'name1',
type: 'text',
placeholder: 'Placeholder 1'
},
{
name: 'name2',
type: 'text',
id: 'name2-id',
value: 'hello',
placeholder: 'Placeholder 2'
},
// multiline input.
{
name: 'paragraph',
id: 'paragraph',
type: 'textarea',
placeholder: 'Placeholder 3'
},
{
name: 'name3',
value: 'http://ionicframework.com',
type: 'url',
placeholder: 'Favorite site ever'
},
// input date with min & max
{
name: 'name4',
type: 'date',
min: '2017-03-01',
max: '2018-01-12'
},
// input date without min nor max
{
name: 'name5',
type: 'date'
},
{
name: 'name6',
type: 'number',
min: -5,
max: 10
},
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: () => {
console.log('Confirm Cancel');
}
}, {
text: 'Ok',
handler: () => {
console.log('Confirm Ok');
}
}
]
});
await alert.present();
}
async presentAlertRadio() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Radio',
inputs: [
{
name: 'radio1',
type: 'radio',
label: 'Radio 1',
value: 'value1',
checked: true
},
{
name: 'radio2',
type: 'radio',
label: 'Radio 2',
value: 'value2'
},
{
name: 'radio3',
type: 'radio',
label: 'Radio 3',
value: 'value3'
},
{
name: 'radio4',
type: 'radio',
label: 'Radio 4',
value: 'value4'
},
{
name: 'radio5',
type: 'radio',
label: 'Radio 5',
value: 'value5'
},
{
name: 'radio6',
type: 'radio',
label: 'Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 ',
value: 'value6'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: () => {
console.log('Confirm Cancel');
}
}, {
text: 'Ok',
handler: () => {
console.log('Confirm Ok');
}
}
]
});
await alert.present();
}
async presentAlertCheckbox() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Checkbox',
inputs: [
{
name: 'checkbox1',
type: 'checkbox',
label: 'Checkbox 1',
value: 'value1',
checked: true
},
{
name: 'checkbox2',
type: 'checkbox',
label: 'Checkbox 2',
value: 'value2'
},
{
name: 'checkbox3',
type: 'checkbox',
label: 'Checkbox 3',
value: 'value3'
},
{
name: 'checkbox4',
type: 'checkbox',
label: 'Checkbox 4',
value: 'value4'
},
{
name: 'checkbox5',
type: 'checkbox',
label: 'Checkbox 5',
value: 'value5'
},
{
name: 'checkbox6',
type: 'checkbox',
label: 'Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6',
value: 'value6'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: () => {
console.log('Confirm Cancel');
}
}, {
text: 'Ok',
handler: () => {
console.log('Confirm Ok');
}
}
]
});
await alert.present();
}
render() {
return [
<ion-content>
<ion-button onClick={() => this.presentAlert()}>Present Alert</ion-button>
<ion-button onClick={() => this.presentAlertMultipleButtons()}>Present Alert: Multiple Buttons</ion-button>
<ion-button onClick={() => this.presentAlertConfirm()}>Present Alert: Confirm</ion-button>
<ion-button onClick={() => this.presentAlertPrompt()}>Present Alert: Prompt</ion-button>
<ion-button onClick={() => this.presentAlertRadio()}>Present Alert: Radio</ion-button>
<ion-button onClick={() => this.presentAlertCheckbox()}>Present Alert: Checkbox</ion-button>
</ion-content>
];
}
}
```
### Vue
```html
@@ -805,6 +1171,7 @@ export default {
presentAlert() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
@@ -816,6 +1183,7 @@ export default {
presentAlertMultipleButtons() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
@@ -827,6 +1195,7 @@ export default {
presentAlertConfirm() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
buttons: [
@@ -852,6 +1221,7 @@ export default {
presentAlertPrompt() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Prompt!',
inputs: [
{
@@ -891,6 +1261,16 @@ export default {
name: 'name7',
type: 'number',
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
],
buttons: [
{
@@ -915,6 +1295,7 @@ export default {
presentAlertRadio() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Radio',
inputs: [
{
@@ -972,6 +1353,7 @@ export default {
presentAlertCheckbox() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Checkbox',
inputs: [
{
@@ -1050,7 +1432,7 @@ export default {
| `inputs` | -- | Array of input to show in the alert. | `AlertInput[]` | `[]` |
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
| `leaveAnimation` | -- | Animation to use when the alert is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
| `message` | `message` | The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `&lt;Ionic&gt;` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` |
| `message` | `message` | The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `&lt;Ionic&gt;` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `IonicSafeString \| string \| undefined` | `undefined` |
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
| `subHeader` | `sub-header` | The subtitle in the heading of the alert. Displayed under the title. | `string \| undefined` | `undefined` |
| `translucent` | `translucent` | If `true`, the alert will be translucent. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility). | `boolean` | `false` |
@@ -1078,23 +1460,23 @@ Type: `Promise<boolean>`
### `onDidDismiss() => Promise<OverlayEventDetail<any>>`
### `onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>`
Returns a promise that resolves when the alert did dismiss.
#### Returns
Type: `Promise<OverlayEventDetail<any>>`
Type: `Promise<OverlayEventDetail<T>>`
### `onWillDismiss() => Promise<OverlayEventDetail<any>>`
### `onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>`
Returns a promise that resolves when the alert will dismiss.
#### Returns
Type: `Promise<OverlayEventDetail<any>>`
Type: `Promise<OverlayEventDetail<T>>`

View File

@@ -14,7 +14,7 @@
import { alertController } from '../../../../dist/ionic/index.esm.js';
window.alertController = alertController;
</script>
<body>
<ion-app>
@@ -75,7 +75,14 @@
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
buttons: ['Cancel', 'Open Modal', 'Delete']
buttons: [
'Open Modal',
{
text: 'Delete',
role: 'destructive',
},
'Cancel',
]
});
}
@@ -161,6 +168,16 @@
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'text',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
],
buttons: [

View File

@@ -13,6 +13,7 @@ export class AlertExample {
async presentAlert() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
@@ -24,6 +25,7 @@ export class AlertExample {
async presentAlertMultipleButtons() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
@@ -35,6 +37,7 @@ export class AlertExample {
async presentAlertConfirm() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
buttons: [
@@ -59,6 +62,7 @@ export class AlertExample {
async presentAlertPrompt() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Prompt!',
inputs: [
{
@@ -107,6 +111,16 @@ export class AlertExample {
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
],
buttons: [
@@ -131,6 +145,7 @@ export class AlertExample {
async presentAlertRadio() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Radio',
inputs: [
{
@@ -193,6 +208,7 @@ export class AlertExample {
async presentAlertCheckbox() {
const alert = await this.alertController.create({
cssClass: 'my-custom-class',
header: 'Checkbox',
inputs: [
{
@@ -257,6 +273,10 @@ export class AlertExample {
await alert.present();
}
}
```
### Style Placement
In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Alert can be presented from within a page, the `ion-alert` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config).

View File

@@ -1,6 +1,7 @@
```javascript
function presentAlert() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Alert';
alert.subHeader = 'Subtitle';
alert.message = 'This is an alert message.';
@@ -12,6 +13,7 @@ function presentAlert() {
function presentAlertMultipleButtons() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Alert';
alert.subHeader = 'Subtitle';
alert.message = 'This is an alert message.';
@@ -23,6 +25,7 @@ function presentAlertMultipleButtons() {
function presentAlertConfirm() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Confirm!';
alert.message = 'Message <strong>text</strong>!!!';
alert.buttons = [
@@ -47,6 +50,7 @@ function presentAlertConfirm() {
function presentAlertPrompt() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Prompt!';
alert.inputs = [
{
@@ -92,6 +96,16 @@ function presentAlertPrompt() {
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
];
alert.buttons = [
@@ -116,6 +130,7 @@ function presentAlertPrompt() {
function presentAlertRadio() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Radio';
alert.inputs = [
{
@@ -171,6 +186,7 @@ function presentAlertRadio() {
function presentAlertCheckbox() {
const alert = document.createElement('ion-alert');
alert.cssClass = 'my-custom-class';
alert.header = 'Checkbox';
alert.inputs = [
{

View File

@@ -22,6 +22,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert1}
onDidDismiss={() => setShowAlert1(false)}
cssClass='my-custom-class'
header={'Alert'}
subHeader={'Subtitle'}
message={'This is an alert message.'}
@@ -31,6 +32,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert2}
onDidDismiss={() => setShowAlert2(false)}
cssClass='my-custom-class'
header={'Alert'}
subHeader={'Subtitle'}
message={'This is an alert message.'}
@@ -40,6 +42,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert3}
onDidDismiss={() => setShowAlert3(false)}
cssClass='my-custom-class'
header={'Confirm!'}
message={'Message <strong>text</strong>!!!'}
buttons={[
@@ -63,6 +66,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert4}
onDidDismiss={() => setShowAlert4(false)}
cssClass='my-custom-class'
header={'Prompt!'}
inputs={[
{
@@ -104,6 +108,16 @@ export const AlertExample: React.FC = () => {
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
]}
buttons={[
@@ -127,6 +141,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert5}
onDidDismiss={() => setShowAlert5(false)}
cssClass='my-custom-class'
header={'Radio'}
inputs={[
{
@@ -188,6 +203,7 @@ export const AlertExample: React.FC = () => {
<IonAlert
isOpen={showAlert6}
onDidDismiss={() => setShowAlert6(false)}
cssClass='my-custom-class'
header={'Checkbox'}
inputs={[
{

View File

@@ -0,0 +1,288 @@
```tsx
import { Component, h } from '@stencil/core';
import { alertController } from '@ionic/core';
@Component({
tag: 'alert-example',
styleUrl: 'alert-example.css'
})
export class AlertExample {
async presentAlert() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
buttons: ['OK']
});
await alert.present();
}
async presentAlertMultipleButtons() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
buttons: ['Cancel', 'Open Modal', 'Delete']
});
await alert.present();
}
async presentAlertConfirm() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: (blah) => {
console.log('Confirm Cancel: blah');
}
}, {
text: 'Okay',
handler: () => {
console.log('Confirm Okay');
}
}
]
});
await alert.present();
}
async presentAlertPrompt() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Prompt!',
inputs: [
{
name: 'name1',
type: 'text',
placeholder: 'Placeholder 1'
},
{
name: 'name2',
type: 'text',
id: 'name2-id',
value: 'hello',
placeholder: 'Placeholder 2'
},
// multiline input.
{
name: 'paragraph',
id: 'paragraph',
type: 'textarea',
placeholder: 'Placeholder 3'
},
{
name: 'name3',
value: 'http://ionicframework.com',
type: 'url',
placeholder: 'Favorite site ever'
},
// input date with min & max
{
name: 'name4',
type: 'date',
min: '2017-03-01',
max: '2018-01-12'
},
// input date without min nor max
{
name: 'name5',
type: 'date'
},
{
name: 'name6',
type: 'number',
min: -5,
max: 10
},
{
name: 'name7',
type: 'number'
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: () => {
console.log('Confirm Cancel');
}
}, {
text: 'Ok',
handler: () => {
console.log('Confirm Ok');
}
}
]
});
await alert.present();
}
async presentAlertRadio() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Radio',
inputs: [
{
name: 'radio1',
type: 'radio',
label: 'Radio 1',
value: 'value1',
checked: true
},
{
name: 'radio2',
type: 'radio',
label: 'Radio 2',
value: 'value2'
},
{
name: 'radio3',
type: 'radio',
label: 'Radio 3',
value: 'value3'
},
{
name: 'radio4',
type: 'radio',
label: 'Radio 4',
value: 'value4'
},
{
name: 'radio5',
type: 'radio',
label: 'Radio 5',
value: 'value5'
},
{
name: 'radio6',
type: 'radio',
label: 'Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 ',
value: 'value6'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: () => {
console.log('Confirm Cancel');
}
}, {
text: 'Ok',
handler: () => {
console.log('Confirm Ok');
}
}
]
});
await alert.present();
}
async presentAlertCheckbox() {
const alert = await alertController.create({
cssClass: 'my-custom-class',
header: 'Checkbox',
inputs: [
{
name: 'checkbox1',
type: 'checkbox',
label: 'Checkbox 1',
value: 'value1',
checked: true
},
{
name: 'checkbox2',
type: 'checkbox',
label: 'Checkbox 2',
value: 'value2'
},
{
name: 'checkbox3',
type: 'checkbox',
label: 'Checkbox 3',
value: 'value3'
},
{
name: 'checkbox4',
type: 'checkbox',
label: 'Checkbox 4',
value: 'value4'
},
{
name: 'checkbox5',
type: 'checkbox',
label: 'Checkbox 5',
value: 'value5'
},
{
name: 'checkbox6',
type: 'checkbox',
label: 'Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6',
value: 'value6'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
handler: () => {
console.log('Confirm Cancel');
}
}, {
text: 'Ok',
handler: () => {
console.log('Confirm Ok');
}
}
]
});
await alert.present();
}
render() {
return [
<ion-content>
<ion-button onClick={() => this.presentAlert()}>Present Alert</ion-button>
<ion-button onClick={() => this.presentAlertMultipleButtons()}>Present Alert: Multiple Buttons</ion-button>
<ion-button onClick={() => this.presentAlertConfirm()}>Present Alert: Confirm</ion-button>
<ion-button onClick={() => this.presentAlertPrompt()}>Present Alert: Prompt</ion-button>
<ion-button onClick={() => this.presentAlertRadio()}>Present Alert: Radio</ion-button>
<ion-button onClick={() => this.presentAlertCheckbox()}>Present Alert: Checkbox</ion-button>
</ion-content>
];
}
}
```

View File

@@ -16,6 +16,7 @@ export default {
presentAlert() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
@@ -27,6 +28,7 @@ export default {
presentAlertMultipleButtons() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
@@ -38,6 +40,7 @@ export default {
presentAlertConfirm() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
buttons: [
@@ -63,6 +66,7 @@ export default {
presentAlertPrompt() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Prompt!',
inputs: [
{
@@ -102,6 +106,16 @@ export default {
name: 'name7',
type: 'number',
},
{
name: 'name8',
type: 'password',
placeholder: 'Advanced Attributes',
cssClass: 'specialClass',
attributes: {
maxlength: 4,
inputmode: 'decimal'
}
}
],
buttons: [
{
@@ -126,6 +140,7 @@ export default {
presentAlertRadio() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Radio',
inputs: [
{
@@ -183,6 +198,7 @@ export default {
presentAlertCheckbox() {
return this.$ionic.alertController
.create({
cssClass: 'my-custom-class',
header: 'Checkbox',
inputs: [
{

View File

@@ -6,10 +6,9 @@ import { isPlatform } from '../../utils/platform';
@Component({
tag: 'ion-app',
styleUrl: 'app.scss'
styleUrl: 'app.scss',
})
export class App implements ComponentInterface {
@Element() el!: HTMLElement;
componentDidLoad() {
@@ -28,6 +27,9 @@ export class App implements ComponentInterface {
if (config.getBoolean('hardwareBackButton', isHybrid)) {
import('../../utils/hardware-back-button').then(module => module.startHardwareBackButton());
}
if (typeof (window as any) !== 'undefined') {
import('../../utils/keyboard/keyboard').then(module => module.startKeyboardAssist(window));
}
import('../../utils/focus-visible').then(module => module.startFocusVisible());
});
}
@@ -40,7 +42,7 @@ export class App implements ComponentInterface {
class={{
[mode]: true,
'ion-page': true,
'force-statusbar-padding': config.getBoolean('_forceStatusbarPadding')
'force-statusbar-padding': config.getBoolean('_forceStatusbarPadding'),
}}
>
</Host>

View File

@@ -36,7 +36,7 @@ Avatars can be used by themselves or inside of any element. If placed inside of
### React
```tsx
import React from 'react'
import React from 'react';
import { IonAvatar, IonChip, IonItem, IonLabel, IonContent } from '@ionic/react';
export const AvatarExample: React.FC = () => (
@@ -63,6 +63,41 @@ export const AvatarExample: React.FC = () => (
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'avatar-example',
styleUrl: 'avatar-example.css'
})
export class AvatarExample {
render() {
return [
<ion-avatar>
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
</ion-avatar>,
<ion-chip>
<ion-avatar>
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
</ion-avatar>
<ion-label>Chip Avatar</ion-label>
</ion-chip>,
<ion-item>
<ion-avatar slot="start">
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
</ion-avatar>
<ion-label>Item Avatar</ion-label>
</ion-item>
];
}
}
```
### Vue
```html

View File

@@ -1,5 +1,5 @@
```tsx
import React from 'react'
import React from 'react';
import { IonAvatar, IonChip, IonItem, IonLabel, IonContent } from '@ionic/react';
export const AvatarExample: React.FC = () => (

View File

@@ -0,0 +1,31 @@
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'avatar-example',
styleUrl: 'avatar-example.css'
})
export class AvatarExample {
render() {
return [
<ion-avatar>
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
</ion-avatar>,
<ion-chip>
<ion-avatar>
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
</ion-avatar>
<ion-label>Chip Avatar</ion-label>
</ion-chip>,
<ion-item>
<ion-avatar slot="start">
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
</ion-avatar>
<ion-label>Item Avatar</ion-label>
</ion-item>
];
}
}
```

View File

@@ -239,6 +239,6 @@ ion-icon {
// Back Button in Toolbar: Global Theming
// --------------------------------------------------
:host(.in-toolbar) {
:host(.in-toolbar:not(.in-toolbar-color)) {
color: #{var(--ion-toolbar-color, var(--color))};
}

View File

@@ -19,7 +19,6 @@ import { createColorClasses, hostContext, openURL } from '../../utils/theme';
})
export class BackButton implements ComponentInterface, ButtonInterface {
mode = getIonMode(this);
@Element() el!: HTMLElement;
/**
@@ -32,7 +31,7 @@ export class BackButton implements ComponentInterface, ButtonInterface {
/**
* The url to navigate back to by default when there is no history.
*/
@Prop() defaultHref?: string;
@Prop({ mutable: true }) defaultHref?: string;
/**
* If `true`, the user cannot interact with the button.
@@ -54,6 +53,12 @@ export class BackButton implements ComponentInterface, ButtonInterface {
*/
@Prop() type: 'submit' | 'reset' | 'button' = 'button';
componentWillLoad() {
if (this.defaultHref === undefined) {
this.defaultHref = config.get('backButtonDefaultHref');
}
}
get backButtonIcon() {
const icon = this.icon;
if (icon != null) {
@@ -61,7 +66,7 @@ export class BackButton implements ComponentInterface, ButtonInterface {
return icon;
}
if (this.mode === 'ios') {
if (getIonMode(this) === 'ios') {
// default ios back button icon
return config.get('backButtonIcon', 'chevron-back');
}
@@ -71,7 +76,7 @@ export class BackButton implements ComponentInterface, ButtonInterface {
}
get backButtonText() {
const defaultBackButtonText = this.mode === 'ios' ? 'Back' : null;
const defaultBackButtonText = getIonMode(this) === 'ios' ? 'Back' : null;
return this.text != null ? this.text : config.get('backButtonText', defaultBackButtonText);
}
@@ -100,8 +105,9 @@ export class BackButton implements ComponentInterface, ButtonInterface {
}
render() {
const { color, defaultHref, disabled, type, mode, hasIconOnly, backButtonIcon, backButtonText } = this;
const { color, defaultHref, disabled, type, hasIconOnly, backButtonIcon, backButtonText } = this;
const showBackButton = defaultHref !== undefined;
const mode = getIonMode(this);
return (
<Host
@@ -114,15 +120,16 @@ export class BackButton implements ComponentInterface, ButtonInterface {
'back-button-disabled': disabled,
'back-button-has-icon-only': hasIconOnly,
'in-toolbar': hostContext('ion-toolbar', this.el),
'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
'ion-activatable': true,
'ion-focusable': true,
'show-back-button': showBackButton
}}
>
<button type={type} disabled={disabled} class="button-native" part="button">
<button type={type} disabled={disabled} class="button-native" aria-label={backButtonText || 'back'}>
<span class="button-inner">
{backButtonIcon && <ion-icon icon={backButtonIcon} lazy={false} part="icon"></ion-icon>}
{backButtonText && <span class="button-text" part="text">{backButtonText}</span>}
{backButtonIcon && <ion-icon icon={backButtonIcon} aria-hidden="true" lazy={false}></ion-icon>}
{backButtonText && <span aria-hidden="true" class="button-text">{backButtonText}</span>}
</span>
{mode === 'md' && <ion-ripple-effect type={this.rippleType}></ion-ripple-effect>}
</button>

View File

@@ -173,6 +173,75 @@ export const BackButtonExample: React.FC = () => (
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'back-button-example',
styleUrl: 'back-button-example.css'
})
export class BackButtonExample {
render() {
const buttonText = "Custom";
const buttonIcon = "add";
return [
// Default back button
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>,
// Back button with a default href
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button defaultHref="home"></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>,
// Back button with custom text and icon
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button
text={buttonText}
icon={buttonIcon}>
</ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>,
// Back button with no text and custom icon
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button text="" icon="add"></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>,
// Danger back button next to a menu button
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
<ion-back-button color="danger"></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
];
}
}
```
### Vue
```html

View File

@@ -1,18 +1,28 @@
import { newSpecPage } from '@stencil/core/testing';
import { BackButton } from "../back-button";
import { config } from "../../../global/config";
import { setMode } from '@stencil/core';
describe('back button', () => {
let bb: BackButton;
beforeEach(() => {
config.reset({});
bb = new BackButton();
});
const newBackButton = async (mode: string = 'md'): Promise<BackButton> => {
setMode(() => mode);
const { rootInstance } = await newSpecPage({
components: [BackButton],
html: `<ion-back-button></ion-back-button>`
})
return rootInstance;
};
describe('backButtonIcon', () => {
it('set custom icon on the instance, override config', () => {
it('set custom icon on the instance, override config', async () => {
const bb = await newBackButton();
bb.icon = 'custom-icon-instance';
config.reset({
backButtonIcon: 'custom-icon-config'
@@ -20,24 +30,27 @@ describe('back button', () => {
expect(bb.backButtonIcon).toBe('custom-icon-instance');
});
it('set custom icon in the config', () => {
it('set custom icon in the config', async () => {
const bb = await newBackButton();
config.reset({
backButtonIcon: 'custom-icon-config'
});
expect(bb.backButtonIcon).toBe('custom-icon-config');
});
it('set custom icon on the instance', () => {
it('set custom icon on the instance', async () => {
const bb = await newBackButton();
bb.icon = 'custom-icon-instance';
expect(bb.backButtonIcon).toBe('custom-icon-instance');
});
it('default icon for ios mode', () => {
bb.mode = 'ios';
it('default icon for ios mode', async () => {
const bb = await newBackButton('ios');
expect(bb.backButtonIcon).toBe('chevron-back');
});
it('default icon', () => {
it('default icon', async () => {
const bb = await newBackButton();
expect(bb.backButtonIcon).toBe('arrow-back-sharp');
});
@@ -45,15 +58,49 @@ describe('back button', () => {
describe('backButtonText', () => {
it('default text for ios mode', () => {
bb.mode = 'ios';
it('default text for ios mode', async () => {
const bb = await newBackButton('ios');
expect(bb.backButtonText).toBe('Back');
});
it('default text', () => {
it('default text', async () => {
const bb = await newBackButton();
expect(bb.backButtonText).toBe(null);
});
});
describe('backButtonDefaultHref', () => {
it('set custom defaultHref in the config', async () => {
config.reset({
backButtonDefaultHref: 'custom-default-href-config'
});
const bb = await newBackButton();
expect(bb.defaultHref).toBe('custom-default-href-config');
});
it('set custom defaultHref on the instance', async () => {
const bb = await newBackButton();
bb.defaultHref = 'custom-default-href';
expect(bb.defaultHref).toBe('custom-default-href');
});
it('set custom defaultHref on the instance, override config', async () => {
const bb = await newBackButton();
bb.defaultHref = 'custom-default-href';
config.reset({
backButtonDefaultHref: 'custom-default-href-config'
});
expect(bb.defaultHref).toBe('custom-default-href');
const bb2 = await newBackButton();
bb2.defaultHref = 'custom-default-href-second';
expect(bb2.defaultHref).toBe('custom-default-href-second');
});
});
});

View File

@@ -0,0 +1,65 @@
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'back-button-example',
styleUrl: 'back-button-example.css'
})
export class BackButtonExample {
render() {
const buttonText = "Custom";
const buttonIcon = "add";
return [
// Default back button
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>,
// Back button with a default href
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button defaultHref="home"></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>,
// Back button with custom text and icon
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button
text={buttonText}
icon={buttonIcon}>
</ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>,
// Back button with no text and custom icon
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button text="" icon="add"></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>,
// Danger back button next to a menu button
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
<ion-back-button color="danger"></ion-back-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
];
}
}
```

View File

@@ -2,7 +2,6 @@ import { Component, ComponentInterface, Event, EventEmitter, Host, Listen, Prop,
import { getIonMode } from '../../global/ionic-global';
import { GESTURE_CONTROLLER } from '../../utils/gesture';
import { now } from '../../utils/helpers';
@Component({
tag: 'ion-backdrop',
@@ -14,7 +13,6 @@ import { now } from '../../utils/helpers';
})
export class Backdrop implements ComponentInterface {
private lastClick = -10000;
private blocker = GESTURE_CONTROLLER.createBlocker({
disableScroll: true
});
@@ -49,18 +47,9 @@ export class Backdrop implements ComponentInterface {
this.blocker.unblock();
}
@Listen('touchstart', { passive: false, capture: true })
protected onTouchStart(ev: TouchEvent) {
this.lastClick = now(ev);
this.emitTap(ev);
}
@Listen('click', { passive: false, capture: true })
@Listen('mousedown', { passive: false, capture: true })
protected onMouseDown(ev: TouchEvent) {
if (this.lastClick < now(ev) - 2500) {
this.emitTap(ev);
}
this.emitTap(ev);
}
private emitTap(ev: Event) {

View File

@@ -40,7 +40,7 @@ import { Component } from '@angular/core';
styleUrls: ['./backdrop-example.css'],
})
export class BackdropExample {
backdropDismiss = false;
enableBackdropDismiss = false;
showBackdrop = false;
shouldPropagate = false;
}
@@ -100,6 +100,46 @@ export const BackdropExample: React.FC = () => (
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'backdrop-example',
styleUrl: 'backdrop-example.css'
})
export class BackdropExample {
render() {
const enableBackdropDismiss = false;
const showBackdrop = false;
const shouldPropagate = false;
return [
// Default backdrop
<ion-backdrop></ion-backdrop>,
// Backdrop that is not tappable
<ion-backdrop tappable={false}></ion-backdrop>,
// Backdrop that is not visible
<ion-backdrop visible={false}></ion-backdrop>,
// Backdrop with propagation
<ion-backdrop stopPropagation={false}></ion-backdrop>,
// Backdrop that sets dynamic properties
<ion-backdrop
tappable={enableBackdropDismiss}
visible={showBackdrop}
stopPropagation={shouldPropagate}>
</ion-backdrop>
];
}
}
```
### Vue
```html
@@ -129,7 +169,7 @@ export const BackdropExample: React.FC = () => (
@Component()
export default class Example extends Vue {
backdropDismiss = false;
enableBackdropDismiss = false;
showBackdrop = false;
shouldPropagate = false;
}

View File

@@ -28,7 +28,7 @@ import { Component } from '@angular/core';
styleUrls: ['./backdrop-example.css'],
})
export class BackdropExample {
backdropDismiss = false;
enableBackdropDismiss = false;
showBackdrop = false;
shouldPropagate = false;
}

View File

@@ -0,0 +1,36 @@
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'backdrop-example',
styleUrl: 'backdrop-example.css'
})
export class BackdropExample {
render() {
const enableBackdropDismiss = false;
const showBackdrop = false;
const shouldPropagate = false;
return [
// Default backdrop
<ion-backdrop></ion-backdrop>,
// Backdrop that is not tappable
<ion-backdrop tappable={false}></ion-backdrop>,
// Backdrop that is not visible
<ion-backdrop visible={false}></ion-backdrop>,
// Backdrop with propagation
<ion-backdrop stopPropagation={false}></ion-backdrop>,
// Backdrop that sets dynamic properties
<ion-backdrop
tappable={enableBackdropDismiss}
visible={showBackdrop}
stopPropagation={shouldPropagate}>
</ion-backdrop>
];
}
}
```

View File

@@ -25,7 +25,7 @@
@Component()
export default class Example extends Vue {
backdropDismiss = false;
enableBackdropDismiss = false;
showBackdrop = false;
shouldPropagate = false;
}

View File

@@ -67,6 +67,44 @@ export const BadgeExample: React.FC = () => (
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'badge-example',
styleUrl: 'badge-example.css'
})
export class BadgeExample {
render() {
return [
// Default
<ion-badge>99</ion-badge>,
// Colors
<ion-badge color="primary">11</ion-badge>,
<ion-badge color="secondary">22</ion-badge>,
<ion-badge color="tertiary">33</ion-badge>,
<ion-badge color="success">44</ion-badge>,
<ion-badge color="warning">55</ion-badge>,
<ion-badge color="danger">66</ion-badge>,
<ion-badge color="light">77</ion-badge>,
<ion-badge color="medium">88</ion-badge>,
<ion-badge color="dark">99</ion-badge>,
// Item with badge on left and right
<ion-item>
<ion-badge slot="start">11</ion-badge>
<ion-label>My Item</ion-label>
<ion-badge slot="end">22</ion-badge>
</ion-item>
];
}
}
```
### Vue
```html

View File

@@ -0,0 +1,34 @@
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'badge-example',
styleUrl: 'badge-example.css'
})
export class BadgeExample {
render() {
return [
// Default
<ion-badge>99</ion-badge>,
// Colors
<ion-badge color="primary">11</ion-badge>,
<ion-badge color="secondary">22</ion-badge>,
<ion-badge color="tertiary">33</ion-badge>,
<ion-badge color="success">44</ion-badge>,
<ion-badge color="warning">55</ion-badge>,
<ion-badge color="danger">66</ion-badge>,
<ion-badge color="light">77</ion-badge>,
<ion-badge color="medium">88</ion-badge>,
<ion-badge color="dark">99</ion-badge>,
// Item with badge on left and right
<ion-item>
<ion-badge slot="start">11</ion-badge>
<ion-label>My Item</ion-label>
<ion-badge slot="end">22</ion-badge>
</ion-item>
];
}
}
```

View File

@@ -175,4 +175,12 @@
:host(.button-solid.ion-color:hover) .button-native::after {
background: #{current-color(tint)};
}
// Solid buttons inside of a toolbar should use a tint of the current
// background so use white to tint it
:host(:hover.button-solid.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native::after {
background: #fff;
opacity: 0.10;
}
}

View File

@@ -179,13 +179,13 @@
line-height: 1;
box-shadow: var(--box-shadow);
contain: layout style;
cursor: pointer;
opacity: var(--opacity);
overflow: var(--overflow);
overflow: hidden;
z-index: 0;
box-sizing: border-box;
appearance: none;
@@ -305,3 +305,19 @@ ion-ripple-effect {
background: transparent;
color: current-color(base);
}
// Button in Toolbar
// --------------------------------------------------
:host(.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
color: #{var(--ion-toolbar-color, var(--color))};
}
:host(.button-outline.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
border-color: #{var(--ion-toolbar-color, var(--color, var(--border-color)))};
}
:host(.button-solid.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
background: #{var(--ion-toolbar-color, var(--background))};
color: #{var(--ion-toolbar-background, var(--color))};
}

View File

@@ -4,7 +4,7 @@ import { getIonMode } from '../../global/ionic-global';
import { Color, RouterDirection } from '../../interface';
import { AnchorInterface, ButtonInterface } from '../../utils/element-interface';
import { hasShadowDom } from '../../utils/helpers';
import { createColorClasses, openURL } from '../../utils/theme';
import { createColorClasses, hostContext, openURL } from '../../utils/theme';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
@@ -13,9 +13,6 @@ import { createColorClasses, openURL } from '../../utils/theme';
* @slot icon-only - Should be used on an icon in a button that has no text.
* @slot start - Content is placed to the left of the button text in LTR, and to the right in RTL.
* @slot end - Content is placed to the right of the button text in LTR, and to the left in RTL.
*
* @part button - The native button or anchor tag that is rendered.
* @part button-inner - The span inside of the native button or anchor.
*/
@Component({
tag: 'ion-button',
@@ -208,7 +205,8 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
[`${buttonType}-${shape}`]: shape !== undefined,
[`${buttonType}-${fill}`]: true,
[`${buttonType}-strong`]: strong,
'in-toolbar': hostContext('ion-toolbar', this.el),
'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
'button-has-icon-only': hasIconOnly,
'button-disabled': disabled,
'ion-activatable': true,
@@ -221,9 +219,8 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
disabled={disabled}
onFocus={this.onFocus}
onBlur={this.onBlur}
part="button"
>
<span class="button-inner" part="button-inner">
<span class="button-inner">
<slot name="icon-only"></slot>
<slot name="start"></slot>
<slot></slot>

View File

@@ -97,6 +97,7 @@ This attribute specifies the size of the button. Setting this attribute will cha
import React from 'react';
import { IonButton, IonIcon, IonContent } from '@ionic/react';
import { star } from 'ionicons/icons';
export const ButtonExample: React.FC = () => (
<IonContent>
@@ -131,17 +132,17 @@ export const ButtonExample: React.FC = () => (
{/*-- Icons --*/}
<IonButton>
<IonIcon slot="start" name="star" />
<IonIcon slot="start" icon={star} />
Left Icon
</IonButton>
<IonButton>
Right Icon
<IonIcon slot="end" name="star" />
<IonIcon slot="end" icon={star} />
</IonButton>
<IonButton>
<IonIcon slot="icon-only" name="star" />
<IonIcon slot="icon-only" icon={star} />
</IonButton>
{/*-- Sizes --*/}
@@ -154,6 +155,72 @@ export const ButtonExample: React.FC = () => (
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'button-example',
styleUrl: 'button-example.css'
})
export class ButtonExample {
render() {
return [
// Default
<ion-button>Default</ion-button>,
// Anchor
<ion-button href="#">Anchor</ion-button>,
// Colors
<ion-button color="primary">Primary</ion-button>,
<ion-button color="secondary">Secondary</ion-button>,
<ion-button color="tertiary">Tertiary</ion-button>,
<ion-button color="success">Success</ion-button>,
<ion-button color="warning">Warning</ion-button>,
<ion-button color="danger">Danger</ion-button>,
<ion-button color="light">Light</ion-button>,
<ion-button color="medium">Medium</ion-button>,
<ion-button color="dark">Dark</ion-button>,
// Expand
<ion-button expand="full">Full Button</ion-button>,
<ion-button expand="block">Block Button</ion-button>,
// Round
<ion-button shape="round">Round Button</ion-button>,
// Fill
<ion-button expand="full" fill="outline">Outline + Full</ion-button>,
<ion-button expand="block" fill="outline">Outline + Block</ion-button>,
<ion-button shape="round" fill="outline">Outline + Round</ion-button>,
// Icons
<ion-button>
<ion-icon slot="start" name="star"></ion-icon>
Left Icon
</ion-button>,
<ion-button>
Right Icon
<ion-icon slot="end" name="star"></ion-icon>
</ion-button>,
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>,
// Sizes
<ion-button size="large">Large</ion-button>,
<ion-button>Default</ion-button>,
<ion-button size="small">Small</ion-button>
];
}
}
```
### Vue
```html

View File

@@ -23,7 +23,7 @@
<ion-button fill="clear">Clear</ion-button>
<ion-button color="secondary">Default</ion-button>
<ion-button color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
<ion-button color="danger" shape="round">Round</ion-button>
<ion-button color="danger" shape="round" fill="outline">Round</ion-button>
<ion-button color="warning" fill="outline">Outline</ion-button>
<ion-button color="dark" fill="clear">Clear</ion-button>
</p>
@@ -37,7 +37,7 @@
<ion-button class="ion-focused" fill="clear">Clear</ion-button>
<ion-button class="ion-focused" color="secondary">Default</ion-button>
<ion-button class="ion-focused" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
<ion-button class="ion-focused" color="danger" shape="round">Round</ion-button>
<ion-button class="ion-focused" color="danger" shape="round" fill="outline">Round</ion-button>
<ion-button class="ion-focused" color="warning" fill="outline">Outline</ion-button>
<ion-button class="ion-focused" color="dark" fill="clear">Clear</ion-button>
</p>
@@ -51,7 +51,7 @@
<ion-button class="ion-activated" fill="clear">Clear</ion-button>
<ion-button class="ion-activated" color="secondary">Default</ion-button>
<ion-button class="ion-activated" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
<ion-button class="ion-activated" color="danger" shape="round">Round</ion-button>
<ion-button class="ion-activated" color="danger" shape="round" fill="outline">Round</ion-button>
<ion-button class="ion-activated" color="warning" fill="outline">Outline</ion-button>
<ion-button class="ion-activated" color="dark" fill="clear">Clear</ion-button>
</p>
@@ -65,7 +65,7 @@
<ion-button class="custom" fill="clear">Clear</ion-button>
<ion-button class="custom" color="secondary">Default</ion-button>
<ion-button class="custom" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
<ion-button class="custom" color="danger" shape="round">Round</ion-button>
<ion-button class="custom" color="danger" shape="round" fill="outline">Round</ion-button>
<ion-button class="custom" color="warning" fill="outline">Outline</ion-button>
<ion-button class="custom" color="dark" fill="clear">Clear</ion-button>
<ion-button class="custom ion-focused">Default</ion-button>
@@ -75,7 +75,7 @@
<ion-button class="custom ion-focused" fill="clear">Clear</ion-button>
<ion-button class="custom ion-focused" color="secondary">Default</ion-button>
<ion-button class="custom ion-focused" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
<ion-button class="custom ion-focused" color="danger" shape="round">Round</ion-button>
<ion-button class="custom ion-focused" color="danger" shape="round" fill="outline">Round</ion-button>
<ion-button class="custom ion-focused" color="warning" fill="outline">Outline</ion-button>
<ion-button class="custom ion-focused" color="dark" fill="clear">Clear</ion-button>
<ion-button class="custom ion-activated">Default</ion-button>
@@ -85,7 +85,7 @@
<ion-button class="custom ion-activated" fill="clear">Clear</ion-button>
<ion-button class="custom ion-activated" color="secondary">Default</ion-button>
<ion-button class="custom ion-activated" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
<ion-button class="custom ion-activated" color="danger" shape="round">Round</ion-button>
<ion-button class="custom ion-activated" color="danger" shape="round" fill="outline">Round</ion-button>
<ion-button class="custom ion-activated" color="warning" fill="outline">Outline</ion-button>
<ion-button class="custom ion-activated" color="dark" fill="clear">Clear</ion-button>
</p>

View File

@@ -2,6 +2,7 @@
import React from 'react';
import { IonButton, IonIcon, IonContent } from '@ionic/react';
import { star } from 'ionicons/icons';
export const ButtonExample: React.FC = () => (
<IonContent>
@@ -36,17 +37,17 @@ export const ButtonExample: React.FC = () => (
{/*-- Icons --*/}
<IonButton>
<IonIcon slot="start" name="star" />
<IonIcon slot="start" icon={star} />
Left Icon
</IonButton>
<IonButton>
Right Icon
<IonIcon slot="end" name="star" />
<IonIcon slot="end" icon={star} />
</IonButton>
<IonButton>
<IonIcon slot="icon-only" name="star" />
<IonIcon slot="icon-only" icon={star} />
</IonButton>
{/*-- Sizes --*/}

View File

@@ -0,0 +1,62 @@
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'button-example',
styleUrl: 'button-example.css'
})
export class ButtonExample {
render() {
return [
// Default
<ion-button>Default</ion-button>,
// Anchor
<ion-button href="#">Anchor</ion-button>,
// Colors
<ion-button color="primary">Primary</ion-button>,
<ion-button color="secondary">Secondary</ion-button>,
<ion-button color="tertiary">Tertiary</ion-button>,
<ion-button color="success">Success</ion-button>,
<ion-button color="warning">Warning</ion-button>,
<ion-button color="danger">Danger</ion-button>,
<ion-button color="light">Light</ion-button>,
<ion-button color="medium">Medium</ion-button>,
<ion-button color="dark">Dark</ion-button>,
// Expand
<ion-button expand="full">Full Button</ion-button>,
<ion-button expand="block">Block Button</ion-button>,
// Round
<ion-button shape="round">Round Button</ion-button>,
// Fill
<ion-button expand="full" fill="outline">Outline + Full</ion-button>,
<ion-button expand="block" fill="outline">Outline + Block</ion-button>,
<ion-button shape="round" fill="outline">Outline + Round</ion-button>,
// Icons
<ion-button>
<ion-icon slot="start" name="star"></ion-icon>
Left Icon
</ion-button>,
<ion-button>
Right Icon
<ion-icon slot="end" name="star"></ion-icon>
</ion-button>,
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>,
// Sizes
<ion-button size="large">Large</ion-button>,
<ion-button>Default</ion-button>,
<ion-button size="small">Small</ion-button>
];
}
}
```

View File

@@ -17,12 +17,11 @@
font-weight: 400;
}
::slotted(*) ion-button:not(.button-round) {
--border-radius: #{$toolbar-ios-button-border-radius};
}
// iOS Toolbar with Color: Default Buttons
// --------------------------------------------------
@@ -38,6 +37,8 @@
--background-focused-opacity: .12;
--background-activated: #000;
--background-activated-opacity: .12;
--background-hover: #{current-color(base)};
--background-hover-opacity: 0.45;
--color: #{current-color(base)};
--color-focused: #{current-color(base)};
}
@@ -53,38 +54,21 @@
}
// iOS Toolbar Button Clear
// iOS Toolbar Button Clear / Outline
// --------------------------------------------------
:host-context(ion-toolbar:not(.ion-color))::slotted(*) .button-clear:not(.ion-color) {
--color: #{var(--ion-toolbar-color, ion-color(primary, base))};
--color-focused: #{var(--ion-toolbar-color, ion-color(primary, base))};
--background-focused: #{var(--ion-toolbar-color, ion-color(primary, base))};
}
// iOS Toolbar Button Outline
// --------------------------------------------------
:host-context(ion-toolbar:not(.ion-color))::slotted(*) .button-outline:not(.ion-color) {
--color: #{var(--ion-toolbar-color, ion-color(primary, base))};
--color-activated: #{var(--ion-toolbar-background, ion-color(primary, contrast))};
--color-focused: #{var(--ion-toolbar-color, ion-color(primary, base))};
--border-color: #{var(--ion-toolbar-color, ion-color(primary, base))};
--background-focused: #{var(--ion-toolbar-color, ion-color(primary, base))};
::slotted(*) .button-clear,
::slotted(*) .button-outline {
--background-activated: transparent;
--background-focused: currentColor;
--background-hover: transparent;
}
// iOS Toolbar Button Solid
// --------------------------------------------------
:host-context(ion-toolbar:not(.ion-color))::slotted(*) .button-solid:not(.ion-color) {
--color: #{$toolbar-ios-background};
--color-activated: #{$toolbar-ios-background};
--color-focused: #{$toolbar-ios-background};
--background: #{var(--ion-toolbar-color, ion-color(primary, base))};
--background-hover: #{var(--ion-toolbar-background, ion-color(primary, contrast))};
--background-hover-opacity: 0.1;
::slotted(*) .button-solid:not(.ion-color) {
--background-focused: #000;
--background-focused-opacity: .12;
--background-activated: #000;
@@ -117,29 +101,7 @@
@include padding(0);
@include margin(0);
font-size: 31px;
font-size: 28px;
line-height: .67;
}
// iOS Toolbar Menu Toggle
// --------------------------------------------------
// .button-menutoggle-ios {
// order: map-get($toolbar-order-ios, menu-toggle-start);
// min-width: 36px;
// --padding-top: 0;
// --padding-bottom: 0;
// --padding-start: 0;
// --padding-end: 0;
// ion-icon {
// @include padding(0, 6px);
// font-size: 28px;
// }
// }

View File

@@ -77,7 +77,6 @@
::slotted(*) .button-solid {
--color: #{$toolbar-md-background};
--color-activated: #{$toolbar-md-background};
--background: #{$toolbar-md-color};
--background-activated: transparent;
--background-focused: currentColor;
@@ -89,13 +88,11 @@
::slotted(*) .button-outline {
--color: initial;
--color-activated: currentColor;
--color-focused: #{$toolbar-md-color};
--background: transparent;
--background-activated: transparent;
--background-focused: currentColor;
--background-hover: currentColor;
--border-color: #{$toolbar-md-color};
--border-color: currentColor;
}
@@ -104,8 +101,6 @@
::slotted(*) .button-clear {
--color: initial;
--color-focused: #{$toolbar-md-color};
--color-activated: currentColor;
--background: transparent;
--background-activated: transparent;
--background-focused: currentColor;

View File

@@ -125,16 +125,8 @@ The `<ion-buttons>` element can be positioned inside of the toolbar using a name
```tsx
import React from 'react';
import {
IonButtons,
IonToolbar,
IonBackButton,
IonTitle,
IonButton,
IonIcon,
IonMenuButton,
IonContent
} from '@ionic/react';
import { IonButtons, IonToolbar, IonBackButton, IonTitle, IonButton, IonIcon, IonMenuButton, IonContent } from '@ionic/react';
import { personCircle, search, star, ellipsisHorizontal, ellipsisVertical } from 'ionicons/icons';
export const ButtonsExample: React.FC = () => (
<IonContent>
@@ -148,16 +140,16 @@ export const ButtonsExample: React.FC = () => (
<IonToolbar>
<IonButtons slot="secondary">
<IonButton>
<IonIcon slot="icon-only" name="person-circle" />
<IonIcon slot="icon-only" icon={personCircle} />
</IonButton>
<IonButton>
<IonIcon slot="icon-only" name="search" />
<IonIcon slot="icon-only" icon={search} />
</IonButton>
</IonButtons>
<IonTitle>Default Buttons</IonTitle>
<IonButtons slot="primary">
<IonButton color="secondary">
<IonIcon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical" />
<IonIcon slot="icon-only" ios={ellipsisHorizontal} md={ellipsisVertical} />
</IonButton>
</IonButtons>
</IonToolbar>
@@ -165,7 +157,7 @@ export const ButtonsExample: React.FC = () => (
<IonToolbar>
<IonButtons slot="primary">
<IonButton onClick={() => {}}>
<IonIcon slot="icon-only" name="star" />
<IonIcon slot="icon-only" icon={star} />
</IonButton>
</IonButtons>
<IonTitle>Right side menu toggle</IonTitle>
@@ -177,7 +169,7 @@ export const ButtonsExample: React.FC = () => (
<IonToolbar>
<IonButtons collapse="true">
<IonButton>
<IonIcon slot="icon-only" name="star" />
<IonIcon slot="icon-only" icon={star} />
</IonButton>
</IonButtons>
<IonTitle>Collapsible Buttons</IonTitle>
@@ -187,6 +179,73 @@ export const ButtonsExample: React.FC = () => (
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'buttons-example',
styleUrl: 'buttons-example.css'
})
export class ButtonsExample {
clickedStar() {
console.log("Clicked star button");
}
render() {
return [
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Back Button</ion-title>
</ion-toolbar>,
<ion-toolbar>
<ion-buttons slot="secondary">
<ion-button>
<ion-icon slot="icon-only" name="person-circle"></ion-icon>
</ion-button>
<ion-button>
<ion-icon slot="icon-only" name="search"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Default Buttons</ion-title>
<ion-buttons slot="primary">
<ion-button color="secondary">
<ion-icon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>,
<ion-toolbar>
<ion-buttons slot="primary">
<ion-button onClick={() => this.clickedStar()}>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Right side menu toggle</ion-title>
<ion-buttons slot="end">
<ion-menu-button autoHide={false}></ion-menu-button>
</ion-buttons>
</ion-toolbar>,
<ion-toolbar>
<ion-buttons collapse={true}>
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Collapsible Buttons</ion-title>
</ion-toolbar>
];
}
}
```
### Vue
```html

View File

@@ -1,15 +1,7 @@
```tsx
import React from 'react';
import {
IonButtons,
IonToolbar,
IonBackButton,
IonTitle,
IonButton,
IonIcon,
IonMenuButton,
IonContent
} from '@ionic/react';
import { IonButtons, IonToolbar, IonBackButton, IonTitle, IonButton, IonIcon, IonMenuButton, IonContent } from '@ionic/react';
import { personCircle, search, star, ellipsisHorizontal, ellipsisVertical } from 'ionicons/icons';
export const ButtonsExample: React.FC = () => (
<IonContent>
@@ -23,16 +15,16 @@ export const ButtonsExample: React.FC = () => (
<IonToolbar>
<IonButtons slot="secondary">
<IonButton>
<IonIcon slot="icon-only" name="person-circle" />
<IonIcon slot="icon-only" icon={personCircle} />
</IonButton>
<IonButton>
<IonIcon slot="icon-only" name="search" />
<IonIcon slot="icon-only" icon={search} />
</IonButton>
</IonButtons>
<IonTitle>Default Buttons</IonTitle>
<IonButtons slot="primary">
<IonButton color="secondary">
<IonIcon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical" />
<IonIcon slot="icon-only" ios={ellipsisHorizontal} md={ellipsisVertical} />
</IonButton>
</IonButtons>
</IonToolbar>
@@ -40,7 +32,7 @@ export const ButtonsExample: React.FC = () => (
<IonToolbar>
<IonButtons slot="primary">
<IonButton onClick={() => {}}>
<IonIcon slot="icon-only" name="star" />
<IonIcon slot="icon-only" icon={star} />
</IonButton>
</IonButtons>
<IonTitle>Right side menu toggle</IonTitle>
@@ -52,7 +44,7 @@ export const ButtonsExample: React.FC = () => (
<IonToolbar>
<IonButtons collapse="true">
<IonButton>
<IonIcon slot="icon-only" name="star" />
<IonIcon slot="icon-only" icon={star} />
</IonButton>
</IonButtons>
<IonTitle>Collapsible Buttons</IonTitle>

View File

@@ -0,0 +1,63 @@
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'buttons-example',
styleUrl: 'buttons-example.css'
})
export class ButtonsExample {
clickedStar() {
console.log("Clicked star button");
}
render() {
return [
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Back Button</ion-title>
</ion-toolbar>,
<ion-toolbar>
<ion-buttons slot="secondary">
<ion-button>
<ion-icon slot="icon-only" name="person-circle"></ion-icon>
</ion-button>
<ion-button>
<ion-icon slot="icon-only" name="search"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Default Buttons</ion-title>
<ion-buttons slot="primary">
<ion-button color="secondary">
<ion-icon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>,
<ion-toolbar>
<ion-buttons slot="primary">
<ion-button onClick={() => this.clickedStar()}>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Right side menu toggle</ion-title>
<ion-buttons slot="end">
<ion-menu-button autoHide={false}></ion-menu-button>
</ion-buttons>
</ion-toolbar>,
<ion-toolbar>
<ion-buttons collapse={true}>
<ion-button>
<ion-icon slot="icon-only" name="star"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Collapsible Buttons</ion-title>
</ion-toolbar>
];
}
}
```

View File

@@ -65,7 +65,7 @@
outline: none;
background: var(--background);
background: inherit;
}
.card-native::-moz-focus-inner {

View File

@@ -67,58 +67,133 @@ sub-components to reflect this. Please see `ion-card-content`,
```tsx
import React from 'react';
import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonContent, IonIcon, IonItem, IonLabel } from '@ionic/react';
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCard, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCardContent, IonItem, IonIcon, IonLabel, IonButton } from '@ionic/react';
import { pin, wifi, wine, warning, walk } from 'ionicons/icons';
export const CardExample: React.FC = () => (
<IonContent>
<IonCard>
<IonCardHeader>
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
<IonCardTitle>Card Title</IonCardTitle>
</IonCardHeader>
export const CardExamples: React.FC = () => {
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>CardExamples</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonCard>
<IonCardHeader>
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
<IonCardTitle>Card Title</IonCardTitle>
</IonCardHeader>
<IonCardContent>
Keep close to Nature's heart... and break clear away, once in awhile,
and climb a mountain or spend a week in the woods. Wash your spirit clean.
<IonCardContent>
Keep close to Nature's heart... and break clear away, once in awhile,
and climb a mountain or spend a week in the woods. Wash your spirit clean.
</IonCardContent>
</IonCard>
</IonCard>
<IonCard>
<IonItem>
<IonIcon name="pin" slot="start" />
<IonLabel>ion-item in a card, icon left, button right</IonLabel>
<IonButton fill="outline" slot="end">View</IonButton>
</IonItem>
<IonCard>
<IonItem>
<IonIcon icon={pin} slot="start" />
<IonLabel>ion-item in a card, icon left, button right</IonLabel>
<IonButton fill="outline" slot="end">View</IonButton>
</IonItem>
<IonCardContent>
This is content, without any paragraph or header tags,
within an ion-cardContent element.
<IonCardContent>
This is content, without any paragraph or header tags,
within an ion-cardContent element.
</IonCardContent>
</IonCard>
</IonCard>
<IonCard>
<IonItem href="#" className="ion-activated">
<IonIcon name="wifi" slot="start" />
<IonLabel>Card Link Item 1 activated</IonLabel>
</IonItem>
<IonCard>
<IonItem href="#" className="ion-activated">
<IonIcon icon={wifi} slot="start" />
<IonLabel>Card Link Item 1 activated</IonLabel>
</IonItem>
<IonItem href="#">
<IonIcon name="wine" slot="start" />
<IonLabel>Card Link Item 2</IonLabel>
</IonItem>
<IonItem href="#">
<IonIcon icon={wine} slot="start" />
<IonLabel>Card Link Item 2</IonLabel>
</IonItem>
<IonItem className="ion-activated">
<IonIcon name="warning" slot="start" />
<IonLabel>Card Button Item 1 activated</IonLabel>
</IonItem>
<IonItem className="ion-activated">
<IonIcon icon={warning} slot="start" />
<IonLabel>Card Button Item 1 activated</IonLabel>
</IonItem>
<IonItem>
<IonIcon name="walk" slot="start" />
<IonLabel>Card Button Item 2</IonLabel>
</IonItem>
</IonCard>
</IonContent>
);
<IonItem>
<IonIcon icon={walk} slot="start" />
<IonLabel>Card Button Item 2</IonLabel>
</IonItem>
</IonCard>
</IonContent>
</IonPage>
);
};
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'card-example',
styleUrl: 'card-example.css'
})
export class CardExample {
render() {
return [
<ion-card>
<ion-card-header>
<ion-card-subtitle>Card Subtitle</ion-card-subtitle>
<ion-card-title>Card Title</ion-card-title>
</ion-card-header>
<ion-card-content>
Keep close to Nature's heart... and break clear away, once in awhile,
and climb a mountain or spend a week in the woods. Wash your spirit clean.
</ion-card-content>
</ion-card>,
<ion-card>
<ion-item>
<ion-icon name="pin" slot="start"></ion-icon>
<ion-label>ion-item in a card, icon left, button right</ion-label>
<ion-button fill="outline" slot="end">View</ion-button>
</ion-item>
<ion-card-content>
This is content, without any paragraph or header tags,
within an ion-card-content element.
</ion-card-content>
</ion-card>,
<ion-card>
<ion-item href="#" class="ion-activated">
<ion-icon name="wifi" slot="start"></ion-icon>
<ion-label>Card Link Item 1 activated</ion-label>
</ion-item>
<ion-item href="#">
<ion-icon name="wine" slot="start"></ion-icon>
<ion-label>Card Link Item 2</ion-label>
</ion-item>
<ion-item class="ion-activated">
<ion-icon name="warning" slot="start"></ion-icon>
<ion-label>Card Button Item 1 activated</ion-label>
</ion-item>
<ion-item>
<ion-icon name="walk" slot="start"></ion-icon>
<ion-label>Card Button Item 2</ion-label>
</ion-item>
</ion-card>
];
}
}
```

View File

@@ -50,6 +50,33 @@
</ion-card-content>
</ion-card>
<ion-card button color="tertiary">
<ion-card-header>
<ion-card-subtitle>
Subtitle
</ion-card-subtitle>
<ion-card-title>
Button Card
</ion-card-title>
</ion-card-header>
<ion-card-content>
This is content, inside of a card with a button attribute.
</ion-card-content>
</ion-card>
<ion-card href="#" color="warning">
<ion-card-header>
<ion-card-title>
Anchor Card
</ion-card-title>
</ion-card-header>
<ion-card-content>
This is content, inside of a card with a href attribute.
</ion-card-content>
</ion-card>
<ion-card button>
<div style="position: absolute; top: 0; left:0; right:0; bottom:0;">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHwAAAB8AQAAAACDZekTAAABMElEQVR4AWLABZjQBdjRBfgb0ATkD6AJ2D9AE6j/gCbw/weAyzk2IwAKwBgIixvNKPaA+P7yXplUZ1/7OO79DkYdjHrIqKeMeskoISXkWkLuBWSMkhGQMYCMAWQMISVkDCBjDCKjZAAZA8gYQMYAUkLGaBAZg8goGYPIGATGIDAGgTEIjEFgDCKjZAwiYxAYg8AYBMYgMAaBMYiMkjGIjEHGSMgYQErIGEDGAAKjZAwyhpAxgIwB5F9nvVsBCAUgDC3Zf2MGuCe1+r6QyBuMwSysg5WyF3bLeXBinCmnzr1wc9wtt08+SBAZI4XklCSTddpAX2gUnaOV9JZm033oAD8gDAyCUnAM0sFCaAlPIS5MhtpwHfLjBuyBXzAQjsJieE4T6kptqm81ss7W6ss/gwMyz60frEbR8QAAAABJRU5ErkJggg==">

View File

@@ -1,55 +1,66 @@
```tsx
import React from 'react';
import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonContent, IonIcon, IonItem, IonLabel } from '@ionic/react';
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCard, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCardContent, IonItem, IonIcon, IonLabel, IonButton } from '@ionic/react';
import { pin, wifi, wine, warning, walk } from 'ionicons/icons';
export const CardExample: React.FC = () => (
<IonContent>
<IonCard>
<IonCardHeader>
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
<IonCardTitle>Card Title</IonCardTitle>
</IonCardHeader>
export const CardExamples: React.FC = () => {
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>CardExamples</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonCard>
<IonCardHeader>
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
<IonCardTitle>Card Title</IonCardTitle>
</IonCardHeader>
<IonCardContent>
Keep close to Nature's heart... and break clear away, once in awhile,
and climb a mountain or spend a week in the woods. Wash your spirit clean.
<IonCardContent>
Keep close to Nature's heart... and break clear away, once in awhile,
and climb a mountain or spend a week in the woods. Wash your spirit clean.
</IonCardContent>
</IonCard>
</IonCard>
<IonCard>
<IonItem>
<IonIcon name="pin" slot="start" />
<IonLabel>ion-item in a card, icon left, button right</IonLabel>
<IonButton fill="outline" slot="end">View</IonButton>
</IonItem>
<IonCard>
<IonItem>
<IonIcon icon={pin} slot="start" />
<IonLabel>ion-item in a card, icon left, button right</IonLabel>
<IonButton fill="outline" slot="end">View</IonButton>
</IonItem>
<IonCardContent>
This is content, without any paragraph or header tags,
within an ion-cardContent element.
<IonCardContent>
This is content, without any paragraph or header tags,
within an ion-cardContent element.
</IonCardContent>
</IonCard>
</IonCard>
<IonCard>
<IonItem href="#" className="ion-activated">
<IonIcon name="wifi" slot="start" />
<IonLabel>Card Link Item 1 activated</IonLabel>
</IonItem>
<IonCard>
<IonItem href="#" className="ion-activated">
<IonIcon icon={wifi} slot="start" />
<IonLabel>Card Link Item 1 activated</IonLabel>
</IonItem>
<IonItem href="#">
<IonIcon name="wine" slot="start" />
<IonLabel>Card Link Item 2</IonLabel>
</IonItem>
<IonItem href="#">
<IonIcon icon={wine} slot="start" />
<IonLabel>Card Link Item 2</IonLabel>
</IonItem>
<IonItem className="ion-activated">
<IonIcon name="warning" slot="start" />
<IonLabel>Card Button Item 1 activated</IonLabel>
</IonItem>
<IonItem className="ion-activated">
<IonIcon icon={warning} slot="start" />
<IonLabel>Card Button Item 1 activated</IonLabel>
</IonItem>
<IonItem>
<IonIcon icon={walk} slot="start" />
<IonLabel>Card Button Item 2</IonLabel>
</IonItem>
</IonCard>
</IonContent>
</IonPage>
);
};
<IonItem>
<IonIcon name="walk" slot="start" />
<IonLabel>Card Button Item 2</IonLabel>
</IonItem>
</IonCard>
</IonContent>
);
```

View File

@@ -0,0 +1,60 @@
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'card-example',
styleUrl: 'card-example.css'
})
export class CardExample {
render() {
return [
<ion-card>
<ion-card-header>
<ion-card-subtitle>Card Subtitle</ion-card-subtitle>
<ion-card-title>Card Title</ion-card-title>
</ion-card-header>
<ion-card-content>
Keep close to Nature's heart... and break clear away, once in awhile,
and climb a mountain or spend a week in the woods. Wash your spirit clean.
</ion-card-content>
</ion-card>,
<ion-card>
<ion-item>
<ion-icon name="pin" slot="start"></ion-icon>
<ion-label>ion-item in a card, icon left, button right</ion-label>
<ion-button fill="outline" slot="end">View</ion-button>
</ion-item>
<ion-card-content>
This is content, without any paragraph or header tags,
within an ion-card-content element.
</ion-card-content>
</ion-card>,
<ion-card>
<ion-item href="#" class="ion-activated">
<ion-icon name="wifi" slot="start"></ion-icon>
<ion-label>Card Link Item 1 activated</ion-label>
</ion-item>
<ion-item href="#">
<ion-icon name="wine" slot="start"></ion-icon>
<ion-label>Card Link Item 2</ion-label>
</ion-item>
<ion-item class="ion-activated">
<ion-icon name="warning" slot="start"></ion-icon>
<ion-label>Card Button Item 1 activated</ion-label>
</ion-item>
<ion-item>
<ion-icon name="walk" slot="start"></ion-icon>
<ion-label>Card Button Item 2</ion-label>
</ion-item>
</ion-card>
];
}
}
```

View File

@@ -7,6 +7,9 @@ import { createColorClasses, hostContext } from '../../utils/theme';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
*
* @part container - The container for the checkbox mark.
* @part mark - The checkmark used to indicate the checked state.
*/
@Component({
tag: 'ion-checkbox',
@@ -136,13 +139,13 @@ export class Checkbox implements ComponentInterface {
renderHiddenInput(true, el, this.name, (checked ? value : ''), disabled);
let path = indeterminate
? <path d="M6 12L18 12"/>
: <path d="M5.9,12.5l3.8,3.8l8.8-8.8" />;
? <path d="M6 12L18 12" part="mark" />
: <path d="M5.9,12.5l3.8,3.8l8.8-8.8" part="mark" />;
if (mode === 'md') {
path = indeterminate
? <path d="M2 12H22"/>
: <path d="M1.73,12.91 8.1,19.28 22.79,4.59"/>;
? <path d="M2 12H22" part="mark" />
: <path d="M1.73,12.91 8.1,19.28 22.79,4.59" part="mark" />;
}
return (
@@ -162,7 +165,7 @@ export class Checkbox implements ComponentInterface {
'interactive': true
}}
>
<svg class="checkbox-icon" viewBox="0 0 24 24">
<svg class="checkbox-icon" viewBox="0 0 24 24" part="container">
{path}
</svg>
<button

View File

@@ -98,44 +98,107 @@ export class HomePage {
### React
```tsx
import React from 'react';
import { IonCheckbox, IonList, IonItem, IonLabel, IonContent } from '@ionic/react';
import React, { useState } from 'react';
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCheckbox, IonList, IonItem, IonLabel, IonItemDivider } from '@ionic/react';
const form = [
const checkboxList = [
{ val: 'Pepperoni', isChecked: true },
{ val: 'Sausage', isChecked: false },
{ val: 'Mushroom', isChecked: false }
];
export const CheckboxExample: React.FC = () => (
<IonContent>
{/*-- Default Checkbox --*/}
<IonCheckbox />
export const CheckboxExamples: React.FC = () => {
{/*-- Disabled Checkbox --*/}
<IonCheckbox disabled={true} />
const [checked, setChecked] = useState(false);
{/*-- Checked Checkbox --*/}
<IonCheckbox checked={true} />
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>CheckboxExamples</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonList>
<IonItemDivider>Default Checkbox</IonItemDivider>
<IonItem>
<IonLabel>Checked: {JSON.stringify(checked)}</IonLabel>
<IonCheckbox checked={checked} onIonChange={e => setChecked(e.detail.checked)} />
</IonItem>
{/*-- Checkbox Colors --*/}
<IonCheckbox color="primary" />
<IonCheckbox color="secondary" />
<IonCheckbox color="danger" />
<IonCheckbox color="light" />
<IonCheckbox color="dark" />
<IonItemDivider>Disabled Checkbox</IonItemDivider>
<IonItem><IonCheckbox slot="end" disabled={true} /></IonItem>
{/*-- Checkboxes in a List --*/}
<IonList>
{ form.map(({val, isChecked}) => (
<IonItem key={val}>
<IonLabel>{val}</IonLabel>
<IonCheckbox slot="end" value={val} checked={isChecked} />
</IonItem>
)) }
</IonList>
</IonContent>
);
<IonItemDivider>Checkbox Colors</IonItemDivider>
<IonItem>
<IonCheckbox slot="end" color="primary" />
<IonCheckbox slot="end" color="secondary" />
<IonCheckbox slot="end" color="danger" />
<IonCheckbox slot="end" color="light" />
<IonCheckbox slot="end" color="dark" />
</IonItem>
<IonItemDivider>Checkboxes in a List</IonItemDivider>
{checkboxList.map(({ val, isChecked }, i) => (
<IonItem key={i}>
<IonLabel>{val}</IonLabel>
<IonCheckbox slot="end" value={val} checked={isChecked} />
</IonItem>
))}
</IonList>
</IonContent>
</IonPage>
);
};
```
### Stencil
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'checkbox-example',
styleUrl: 'checkbox-example.css'
})
export class CheckboxExample {
private form = [
{ val: 'Pepperoni', isChecked: true },
{ val: 'Sausage', isChecked: false },
{ val: 'Mushroom', isChecked: false }
];
render() {
return [
// Default Checkbox
<ion-checkbox></ion-checkbox>,
// Disabled Checkbox
<ion-checkbox disabled={true}></ion-checkbox>,
// Checked Checkbox
<ion-checkbox checked={true}></ion-checkbox>,
// Checkbox Colors
<ion-checkbox color="primary"></ion-checkbox>,
<ion-checkbox color="secondary"></ion-checkbox>,
<ion-checkbox color="danger"></ion-checkbox>,
<ion-checkbox color="light"></ion-checkbox>,
<ion-checkbox color="dark"></ion-checkbox>,
// Checkboxes in a List
<ion-list>
{this.form.map(entry =>
<ion-item>
<ion-label>{entry.val}</ion-label>
<ion-checkbox slot="end" checked={entry.isChecked}></ion-checkbox>
</ion-item>
)}
</ion-list>
];
}
}
```
@@ -210,6 +273,14 @@ export const CheckboxExample: React.FC = () => (
| `ionFocus` | Emitted when the toggle has focus. | `CustomEvent<void>` |
## Shadow Parts
| Part | Description |
| ------------- | ------------------------------------------------- |
| `"container"` | The container for the checkbox mark. |
| `"mark"` | The checkmark used to indicate the checked state. |
## CSS Custom Properties
| Name | Description |

View File

@@ -10,7 +10,12 @@
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script></head>
<style>
ion-checkbox.checkbox-part::part(mark) {
transform: scale(.5);
transform-origin: center;
}
</style>
<body>
<ion-app>
@@ -81,6 +86,11 @@
<ion-checkbox checked color="dark" slot="start" style="--checkmark-width: 7;"></ion-checkbox>
</ion-item>
<ion-item>
<ion-label>Checkmark ::part</ion-label>
<ion-checkbox checked color="dark" slot="start" class="checkbox-part"></ion-checkbox>
</ion-item>
<ion-item>
<ion-label>Unchecked by Default</ion-label>
<ion-checkbox></ion-checkbox>

View File

@@ -1,40 +1,54 @@
```tsx
import React from 'react';
import { IonCheckbox, IonList, IonItem, IonLabel, IonContent } from '@ionic/react';
import React, { useState } from 'react';
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCheckbox, IonList, IonItem, IonLabel, IonItemDivider } from '@ionic/react';
const form = [
const checkboxList = [
{ val: 'Pepperoni', isChecked: true },
{ val: 'Sausage', isChecked: false },
{ val: 'Mushroom', isChecked: false }
];
export const CheckboxExample: React.FC = () => (
<IonContent>
{/*-- Default Checkbox --*/}
<IonCheckbox />
export const CheckboxExamples: React.FC = () => {
{/*-- Disabled Checkbox --*/}
<IonCheckbox disabled={true} />
const [checked, setChecked] = useState(false);
{/*-- Checked Checkbox --*/}
<IonCheckbox checked={true} />
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>CheckboxExamples</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonList>
<IonItemDivider>Default Checkbox</IonItemDivider>
<IonItem>
<IonLabel>Checked: {JSON.stringify(checked)}</IonLabel>
<IonCheckbox checked={checked} onIonChange={e => setChecked(e.detail.checked)} />
</IonItem>
{/*-- Checkbox Colors --*/}
<IonCheckbox color="primary" />
<IonCheckbox color="secondary" />
<IonCheckbox color="danger" />
<IonCheckbox color="light" />
<IonCheckbox color="dark" />
<IonItemDivider>Disabled Checkbox</IonItemDivider>
<IonItem><IonCheckbox slot="end" disabled={true} /></IonItem>
{/*-- Checkboxes in a List --*/}
<IonList>
{ form.map(({val, isChecked}) => (
<IonItem key={val}>
<IonLabel>{val}</IonLabel>
<IonCheckbox slot="end" value={val} checked={isChecked} />
</IonItem>
)) }
</IonList>
</IonContent>
);
<IonItemDivider>Checkbox Colors</IonItemDivider>
<IonItem>
<IonCheckbox slot="end" color="primary" />
<IonCheckbox slot="end" color="secondary" />
<IonCheckbox slot="end" color="danger" />
<IonCheckbox slot="end" color="light" />
<IonCheckbox slot="end" color="dark" />
</IonItem>
<IonItemDivider>Checkboxes in a List</IonItemDivider>
{checkboxList.map(({ val, isChecked }, i) => (
<IonItem key={i}>
<IonLabel>{val}</IonLabel>
<IonCheckbox slot="end" value={val} checked={isChecked} />
</IonItem>
))}
</IonList>
</IonContent>
</IonPage>
);
};
```

View File

@@ -0,0 +1,45 @@
```tsx
import { Component, h } from '@stencil/core';
@Component({
tag: 'checkbox-example',
styleUrl: 'checkbox-example.css'
})
export class CheckboxExample {
private form = [
{ val: 'Pepperoni', isChecked: true },
{ val: 'Sausage', isChecked: false },
{ val: 'Mushroom', isChecked: false }
];
render() {
return [
// Default Checkbox
<ion-checkbox></ion-checkbox>,
// Disabled Checkbox
<ion-checkbox disabled={true}></ion-checkbox>,
// Checked Checkbox
<ion-checkbox checked={true}></ion-checkbox>,
// Checkbox Colors
<ion-checkbox color="primary"></ion-checkbox>,
<ion-checkbox color="secondary"></ion-checkbox>,
<ion-checkbox color="danger"></ion-checkbox>,
<ion-checkbox color="light"></ion-checkbox>,
<ion-checkbox color="dark"></ion-checkbox>,
// Checkboxes in a List
<ion-list>
{this.form.map(entry =>
<ion-item>
<ion-label>{entry.val}</ion-label>
<ion-checkbox slot="end" checked={entry.isChecked}></ion-checkbox>
</ion-item>
)}
</ion-list>
];
}
}
```

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