From ffcf3d6c54ed991b7ac24d66f004479fb62645bd Mon Sep 17 00:00:00 2001 From: Matt Goo Date: Tue, 30 Apr 2019 16:16:04 -0700 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 14b22bcad0bf559e45c8fc341a858665a4bd442c Author: Matt Goo Date: Tue Apr 30 12:06:32 2019 -0700 feat(select): enhanced select (#823) commit b40001383776199629093eaae46b8e9902be72ae Author: Matt Goo Date: Mon Apr 29 14:49:32 2019 -0700 chore: reduce unused deps in package.json (#819) commit beedb23330e30bd6013be199c040b6b6a538a7e5 Author: Matt Goo Date: Mon Apr 29 13:43:20 2019 -0700 feat(select): add icon (#825) commit e22ac2a310f0cdc3ac3de08a66caaacb7c9a7100 Author: Matt Goo Date: Mon Apr 29 13:35:45 2019 -0700 feat(select): add helper text (#824) commit abaa146f7dc6711c98b5687cda248893a2b17ae2 Author: Matt Goo Date: Mon Apr 29 13:35:16 2019 -0700 feat(select): add option component (#826) commit 7adc12a1c09712ddcd7826cc7d7c27e452274f09 Author: Matt Goo Date: Mon Apr 29 13:11:16 2019 -0700 fix(drawer): add missing foundation import in drawer (#821) commit 7e0f8772232923b4e176e9ec4153214582c24e20 Author: Matt Goo Date: Fri Apr 26 14:33:40 2019 -0700 feat(menu): add component (#786) commit 509e93e92431f82989ad05f64aa68cf642d53b80 Author: Matt Goo Date: Fri Apr 26 09:46:26 2019 -0700 chore(infrastructure): add esmoduleinterop to tsconfig (#818) commit 4dbc8b8b3675dc6b8fa205e78c6a34b2c1f22905 Author: Matt Goo Date: Tue Apr 16 15:56:25 2019 -0700 feat(notched-outline): update to v1.1.1 (#806) commit ea15a2a37db27f7ca8934849c7aee18c3ced4a1f Author: 태ėžŽė˜ Date: Sat Apr 13 06:50:37 2019 +0900 fix(chips): Fix incorrect ripple effect (#804) commit 7b413dfbf487295a9884c364bfc53ed7bf82b473 Author: Matt Goo Date: Mon Apr 8 13:27:36 2019 -0700 feat(button): update mdc web deps to v1.1.0 (#791) commit 034158cb08d6fdc767fe8560c2864aa3f66f9fa1 Author: Matt Goo Date: Tue Apr 2 17:36:46 2019 -0700 fix: remove .only (#794) commit 74379afb8ff1efc38215aab4ff0c0a25d63b0d86 Author: Matt Goo Date: Tue Apr 2 16:24:45 2019 -0700 fix(list): maintain classes with state.listItemClassNames (#776) BREAKING CHANGE: Removes props.tabbableOnListItemFocus from all the auxiliary components, as it seemed confusing to have this and tabIndex dictate what tabIndex would ultimately be. commit e5b953fe9a93be634391ed656f3930ec15fd5d53 Author: Ben McKernan Date: Tue Apr 2 20:18:03 2019 +0200 fix(icon-button): upgrade to mdc-web v1.1 (#792) commit 9c7bfa7aafdceecededadf28ecdb270fa0ba0cc1 Author: Andrii Kostenko Date: Mon Apr 1 23:08:27 2019 +0300 fix(card): upgrade to mdc-web v1.1 (#788) commit bb9e7e429c7eabc97ba288b1ee1ae3f741dbca53 Author: Andrii Kostenko Date: Mon Apr 1 20:44:28 2019 +0300 fix(top-app-bar): mdc-web v1 upgrade (#780) commit 37c72691ba753b192771bed3b281cc20c3f657fa Author: Andrii Kostenko Date: Mon Apr 1 20:00:39 2019 +0300 fix(linear-progress): upgrade mdc-web to v1 (#787) commit b6403e616486fc972fcae67440952408e4d3ed30 Author: Andrii Kostenko Date: Mon Apr 1 19:38:31 2019 +0300 fix(fab): upgrade to mdc-web v1.1 (#790) commit bcda1115b82dd48bcd5d5ba0be34bc804a2e8d0f Author: Andrii Kostenko Date: Fri Mar 29 21:11:19 2019 +0300 fix(dialog): mdc-web v1 upgrade (#779) commit 8ff8695e02ad85ef3475e0d61b5d87e94c37caf9 Author: Andrii Kostenko Date: Thu Mar 28 22:32:55 2019 +0300 fix(typography): upgrade to mdc-web v1 (#778) commit 4d6bbc01c00e498b97b2b92a8e22fe5269558e45 Author: Andrii Kostenko Date: Thu Mar 28 22:15:22 2019 +0300 feat(radio): upgrade to typescript v1 (#777) commit 4f523e3305d5ac9f4a0a9092051c8efe77a03acc Author: Andrii Kostenko Date: Thu Mar 28 22:13:29 2019 +0300 fix(checkbox): upgrade mdc-web to v1 (#769) commit 1a04f3df86d1538ca1bcd4200593ff1f4a8e8497 Author: Matt Goo Date: Wed Mar 27 12:39:00 2019 -0700 feat(menu-surface): upgrade to mdc web v1 (#774) commit 44cca84297733a78059da95127b1056365963662 Author: Andrii Kostenko Date: Wed Mar 27 01:14:18 2019 +0200 feat(switch): upgrade to mdc-web v1 (#757) commit 580c850e43efcd9b34fecfe73297e9219212c39c Author: Andrii Kostenko Date: Wed Mar 27 01:13:37 2019 +0200 fix(tab-bar): upgrade mdc-web to v1 (#770) commit 45fef89af0c5956afd7658c3aa425c238c213881 Author: Matt Goo Date: Mon Mar 25 15:27:29 2019 -0700 fix(card): add react-ripple to package json (#773) commit 4e99b4c54de50ab2178e37fe3c73211e5c333243 Author: Matt Goo Date: Tue Mar 19 14:10:37 2019 -0700 feat(list): update to MDC Web 1.0.0 (#740) commit 38e9886a4f7696d0d3f79e384cdc10c305e2c4e1 Author: Matt Goo Date: Tue Mar 19 12:36:06 2019 -0700 feat(floating-label): update mdc web to v1.0.0 (#741) commit dd95b604bcba492437e79641a525bdab4d406b3a Author: Andrii Kostenko Date: Mon Mar 18 23:38:34 2019 +0200 feat(snackbar): MDC Web v1.0.0 (#755) commit 9b86474e7c3cab633c33801099ebfbd056ba2d52 Author: Andrii Kostenko Date: Mon Mar 18 23:27:39 2019 +0200 fix(tab): mdc-web v1.0.0 upgrade (#748) commit a8c64b5ee5e52f63bccceac8f5ecd946eea456f4 Author: Lucas Cordeiro Date: Mon Mar 18 17:46:29 2019 -0300 feat(drawer): add innerRef prop (#749) commit 5f5598391b715c5d8554f9d52876bf36ce3053a9 Author: Andrii Kostenko Date: Fri Mar 15 19:05:44 2019 +0200 fix(chips): upgrade mdc-web to v1.0.0 (#750) commit 09cb8a5b0b1fe08639f925534953ab8bd35ba211 Author: Matt Goo Date: Fri Mar 15 10:05:03 2019 -0700 fix: classnames@2.2.5 --> classnames@2.2.6 & update imports (#709) commit ae9b421bab3fe42fbac263f29c08becaafdf7096 Author: Andrii Kostenko Date: Thu Mar 14 20:53:28 2019 +0300 fix(tab-scroller): upgrade mdc-web to 1.0.0 (#743) commit 1b29dd9cd14b052e280df5ea9646077d6596f40a Author: Andrii Kostenko Date: Thu Mar 14 20:32:18 2019 +0300 fix(tab-indicator): upgrade mdc-web to 1.0.0 (#742) commit f96671486ab1a6c13cf6861725f3134c66041e93 Author: Andrii Kostenko Date: Thu Mar 14 19:45:11 2019 +0300 feat(ripple) mdc-web typescript conversion (#711) commit 0b674f5baca3d960c060c129a024ba3d4fbfe59e Author: Andrii Kostenko Date: Fri Mar 8 23:54:24 2019 +0300 feat(line-ripple): mdc-web typescript support (#716) --- docs/best-practices.md | 5 - package-lock.json | 3042 +++++++++++++---- package.json | 60 +- packages/button/index.tsx | 8 +- packages/button/package.json | 2 +- packages/card/ActionButtons.tsx | 2 +- packages/card/ActionIcons.tsx | 2 +- packages/card/Actions.tsx | 2 +- packages/card/Media.tsx | 2 +- packages/card/PrimaryContent.tsx | 8 +- packages/card/index.tsx | 2 +- packages/card/package.json | 2 +- packages/checkbox/NativeControl.tsx | 2 +- packages/checkbox/index.tsx | 43 +- packages/checkbox/package.json | 2 +- packages/chips/Chip.tsx | 44 +- packages/chips/ChipCheckmark.tsx | 2 +- packages/chips/ChipSet.tsx | 19 +- packages/chips/package.json | 2 +- packages/dialog/DialogButton.tsx | 2 +- packages/dialog/DialogContent.tsx | 2 +- packages/dialog/DialogFooter.tsx | 2 +- packages/dialog/DialogTitle.tsx | 2 +- packages/dialog/index.tsx | 32 +- packages/dialog/package.json | 4 +- packages/drawer/AppContent.tsx | 2 +- packages/drawer/Content.tsx | 2 +- packages/drawer/Header.tsx | 2 +- packages/drawer/Subtitle.tsx | 2 +- packages/drawer/Title.tsx | 2 +- packages/drawer/index.tsx | 23 +- packages/drawer/package.json | 4 +- packages/fab/index.tsx | 8 +- packages/fab/package.json | 2 +- packages/floating-label/index.tsx | 40 +- packages/floating-label/package.json | 2 +- packages/icon-button/IconToggle.tsx | 2 +- packages/icon-button/index.tsx | 23 +- packages/icon-button/package.json | 2 +- packages/layout-grid/Cell.tsx | 2 +- packages/layout-grid/Grid.tsx | 2 +- packages/layout-grid/Row.tsx | 2 +- packages/line-ripple/index.tsx | 16 +- packages/line-ripple/package.json | 2 +- packages/linear-progress/index.tsx | 20 +- packages/linear-progress/package.json | 2 +- packages/list/ListDivider.tsx | 2 +- packages/list/ListGroup.tsx | 2 +- packages/list/ListGroupSubheader.tsx | 2 +- packages/list/ListItem.tsx | 211 +- packages/list/ListItemGraphic.tsx | 6 +- packages/list/ListItemMeta.tsx | 8 +- packages/list/ListItemText.tsx | 8 +- packages/list/README.md | 203 +- packages/list/index.tsx | 416 ++- packages/list/package.json | 9 +- packages/material-icon/index.tsx | 8 +- packages/menu-surface/index.tsx | 163 +- packages/menu-surface/package.json | 2 +- packages/menu/MenuList.tsx | 104 + .../types.tsx => menu/MenuListItem.tsx} | 46 +- packages/menu/README.md | 213 ++ packages/menu/index.scss | 23 + packages/menu/index.tsx | 195 ++ packages/menu/package.json | 28 + packages/notched-outline/README.md | 21 +- packages/notched-outline/index.tsx | 171 +- packages/notched-outline/package.json | 2 +- packages/radio/NativeControl.tsx | 2 +- packages/radio/index.tsx | 14 +- packages/radio/package.json | 3 +- packages/ripple/index.tsx | 69 +- packages/ripple/package.json | 4 +- packages/select/BaseSelect.tsx | 158 + packages/select/EnhancedSelect.tsx | 208 ++ packages/select/NativeControl.tsx | 133 - packages/select/NativeSelect.tsx | 92 + packages/select/Option.tsx | 67 + packages/select/README.md | 83 +- packages/select/helper-text/README.md | 23 + packages/select/helper-text/index.tsx | 130 + packages/select/icon/README.md | 23 + packages/select/icon/index.tsx | 120 + packages/select/index.tsx | 344 +- packages/select/package.json | 4 +- packages/snackbar/index.tsx | 13 +- packages/snackbar/package.json | 2 +- packages/switch/NativeControl.tsx | 2 +- packages/switch/ThumbUnderlay.tsx | 8 +- packages/switch/index.tsx | 20 +- packages/switch/package.json | 2 +- packages/tab-bar/index.tsx | 39 +- packages/tab-bar/package.json | 2 +- packages/tab-indicator/index.tsx | 24 +- packages/tab-indicator/package.json | 2 +- packages/tab-scroller/index.tsx | 53 +- packages/tab-scroller/package.json | 4 +- packages/tab/README.md | 1 + packages/tab/TabRipple.tsx | 10 +- packages/tab/index.tsx | 36 +- packages/tab/package.json | 2 +- packages/text-field/Input.tsx | 2 +- packages/text-field/helper-text/index.tsx | 2 +- packages/text-field/icon/index.tsx | 2 +- packages/text-field/index.tsx | 15 +- packages/top-app-bar/FixedAdjust.tsx | 2 +- packages/top-app-bar/Icon.tsx | 2 +- packages/top-app-bar/Row.tsx | 2 +- packages/top-app-bar/Section.tsx | 2 +- packages/top-app-bar/Title.tsx | 2 +- packages/top-app-bar/index.tsx | 37 +- packages/top-app-bar/package.json | 2 +- packages/typography/package.json | 2 +- packages/typography/typography.tsx | 2 +- test/screenshot/App.tsx | 2 +- test/screenshot/button/index.tsx | 2 +- test/screenshot/card/index.tsx | 2 +- test/screenshot/checkbox/index.tsx | 2 +- test/screenshot/chips/index.tsx | 6 +- test/screenshot/dialog/alert.tsx | 2 +- test/screenshot/dialog/confirmation.tsx | 2 +- test/screenshot/dialog/index.tsx | 2 +- test/screenshot/dialog/scrollable.tsx | 2 +- test/screenshot/dialog/simple.tsx | 2 +- .../drawer/DrawerAboveTopAppBar.tsx | 2 +- .../drawer/DrawerBelowTopAppBar.tsx | 2 +- test/screenshot/drawer/DrawerTest.tsx | 2 +- test/screenshot/drawer/dismissible.tsx | 2 +- .../drawer/dismissibleBelowTopAppBar.tsx | 2 +- test/screenshot/drawer/index.tsx | 2 +- test/screenshot/drawer/modal.tsx | 2 +- test/screenshot/drawer/permanent.tsx | 2 +- .../drawer/permanentBelowTopAppBar.tsx | 2 +- test/screenshot/drawer/permanentToModal.tsx | 2 +- test/screenshot/fab/index.tsx | 2 +- test/screenshot/floating-label/index.tsx | 3 +- test/screenshot/golden.json | 27 +- test/screenshot/icon-button/index.tsx | 2 +- test/screenshot/index.tsx | 30 +- test/screenshot/layout-grid/index.tsx | 2 +- test/screenshot/line-ripple/index.tsx | 2 +- test/screenshot/linear-progress/index.tsx | 2 +- test/screenshot/list/index.tsx | 154 +- test/screenshot/material-icon/index.tsx | 2 +- test/screenshot/menu-surface/index.tsx | 2 +- test/screenshot/menu/index.tsx | 65 + test/screenshot/notched-outline/index.scss | 3 +- test/screenshot/notched-outline/index.tsx | 16 +- test/screenshot/radio/index.tsx | 2 +- test/screenshot/ripple/index.tsx | 2 +- test/screenshot/screenshot-test-urls.tsx | 7 +- test/screenshot/screenshot.tsx | 12 +- test/screenshot/select/enhanced.tsx | 8 + test/screenshot/select/index.tsx | 100 +- test/screenshot/select/nativeSelect.tsx | 8 + test/screenshot/select/variants.tsx | 4 + test/screenshot/snackbar/index.tsx | 2 +- test/screenshot/switch/index.tsx | 2 +- test/screenshot/tab-bar/index.tsx | 2 +- test/screenshot/tab-indicator/index.tsx | 2 +- test/screenshot/tab-scroller/index.tsx | 2 +- test/screenshot/tab/index.tsx | 2 +- test/screenshot/text-field/TestTextField.tsx | 2 +- .../text-field/TextFieldPermutations.tsx | 2 +- test/screenshot/text-field/attributesMap.tsx | 2 +- test/screenshot/text-field/fullWidth.tsx | 2 +- .../text-field/helper-text/index.tsx | 2 +- test/screenshot/text-field/icon/index.tsx | 2 +- test/screenshot/text-field/index.tsx | 6 +- test/screenshot/text-field/outlined.tsx | 2 +- test/screenshot/text-field/refTest.tsx | 2 +- test/screenshot/text-field/standard.tsx | 2 +- test/screenshot/text-field/textArea.tsx | 2 +- test/screenshot/text-field/variants.tsx | 1 - test/screenshot/top-app-bar/dense.tsx | 2 +- test/screenshot/top-app-bar/fixed.tsx | 2 +- test/screenshot/top-app-bar/index.tsx | 2 +- test/screenshot/top-app-bar/mainContent.tsx | 2 +- test/screenshot/top-app-bar/prominent.tsx | 2 +- .../screenshot/top-app-bar/prominentDense.tsx | 2 +- .../top-app-bar/prominentToShortCollapsed.tsx | 2 +- test/screenshot/top-app-bar/short.tsx | 2 +- .../screenshot/top-app-bar/shortCollapsed.tsx | 2 +- test/screenshot/top-app-bar/standard.tsx | 2 +- .../top-app-bar/standardNoActionItems.tsx | 2 +- .../standardWithNavigationIconElement.tsx | 2 +- test/screenshot/top-app-bar/twoRows.tsx | 2 +- test/screenshot/typography/index.tsx | 2 +- test/unit/button/index.test.tsx | 4 +- test/unit/card/ActionButton.test.tsx | 2 +- test/unit/card/ActionIcons.test.tsx | 2 +- test/unit/card/Actions.test.tsx | 2 +- test/unit/card/Content.test.tsx | 2 +- test/unit/card/Media.test.tsx | 2 +- test/unit/card/index.test.tsx | 2 +- test/unit/checkbox/NativeControl.test.tsx | 2 +- test/unit/checkbox/index.test.tsx | 61 +- test/unit/chips/Chip.test.tsx | 91 +- test/unit/chips/ChipCheckmark.test.tsx | 2 +- test/unit/chips/ChipSet.test.tsx | 22 +- test/unit/dialog/DialogButton.test.tsx | 2 +- test/unit/dialog/DialogContent.test.tsx | 2 +- test/unit/dialog/DialogFooter.test.tsx | 2 +- test/unit/dialog/DialogTitle.test.tsx | 2 +- test/unit/dialog/index.test.tsx | 69 +- test/unit/drawer/index.test.tsx | 101 +- test/unit/fab/index.test.tsx | 2 +- test/unit/floating-label/index.test.tsx | 26 +- test/unit/icon-button/IconToggle.test.tsx | 2 +- test/unit/icon-button/index.test.tsx | 22 +- test/unit/index.tsx | 4 +- test/unit/layout-grid/Cell.test.tsx | 2 +- test/unit/layout-grid/Grid.test.tsx | 2 +- test/unit/layout-grid/Row.test.tsx | 2 +- test/unit/line-ripple/index.test.tsx | 42 +- test/unit/linear-progress/index.test.tsx | 30 +- test/unit/list/ListDivider.test.tsx | 2 +- test/unit/list/ListGroup.test.tsx | 2 +- test/unit/list/ListGroupSubheader.test.tsx | 2 +- test/unit/list/ListItem.test.tsx | 146 +- test/unit/list/ListItemGraphic.test.tsx | 16 +- test/unit/list/ListItemMeta.test.tsx | 16 +- test/unit/list/ListItemText.test.tsx | 16 +- test/unit/list/index.test.tsx | 445 +-- test/unit/material-icon/index.test.tsx | 2 +- test/unit/menu-surface/index.test.tsx | 128 +- test/unit/menu/MenuList.test.tsx | 68 + test/unit/menu/MenuListItem.test.tsx | 22 + test/unit/menu/index.test.tsx | 232 ++ test/unit/notched-outline/index.test.tsx | 252 +- test/unit/radio/NativeControl.test.tsx | 2 +- test/unit/radio/index.test.tsx | 15 +- test/unit/ripple/index.test.tsx | 150 +- test/unit/select/BaseSelect.test.tsx | 249 ++ test/unit/select/EnhancedSelect.test.tsx | 234 ++ test/unit/select/NativeControl.test.tsx | 151 - test/unit/select/NativeSelect.test.tsx | 25 + test/unit/select/Option.test.tsx | 28 + test/unit/select/helper-text/index.test.tsx | 97 + test/unit/select/icon/index.test.tsx | 78 + test/unit/select/index.test.tsx | 393 ++- test/unit/snackbar/index.test.tsx | 18 +- test/unit/switch/NativeControl.test.tsx | 2 +- test/unit/switch/ThumbUnderlay.test.tsx | 2 +- test/unit/switch/index.test.tsx | 37 +- test/unit/tab-bar/index.test.tsx | 50 +- test/unit/tab-indicator/index.test.tsx | 10 +- test/unit/tab-scroller/index.test.tsx | 69 +- test/unit/tab/TabRipple.test.tsx | 2 +- test/unit/tab/index.test.tsx | 22 +- test/unit/text-field/Input.test.tsx | 4 +- .../text-field/helper-text/index.test.tsx | 4 +- test/unit/text-field/icon/index.test.tsx | 4 +- test/unit/text-field/index.test.tsx | 6 +- test/unit/top-app-bar/FixedAdjust.test.tsx | 2 +- test/unit/top-app-bar/Icon.test.tsx | 2 +- test/unit/top-app-bar/Row.test.tsx | 2 +- test/unit/top-app-bar/Section.test.tsx | 2 +- test/unit/top-app-bar/Title.test.tsx | 2 +- test/unit/top-app-bar/index.test.tsx | 33 +- test/unit/typography/Body1.test.tsx | 2 +- test/unit/typography/Body2.test.tsx | 2 +- test/unit/typography/Button.test.tsx | 2 +- test/unit/typography/Caption.test.tsx | 2 +- test/unit/typography/Headline1.test.tsx | 2 +- test/unit/typography/Headline2.test.tsx | 2 +- test/unit/typography/Headline3.test.tsx | 2 +- test/unit/typography/Headline4.test.tsx | 2 +- test/unit/typography/Headline5.test.tsx | 2 +- test/unit/typography/Headline6.test.tsx | 2 +- test/unit/typography/Overline.test.tsx | 2 +- test/unit/typography/Subtitle1.test.tsx | 2 +- test/unit/typography/Subtitle2.test.tsx | 2 +- tsconfig.json | 1 + 274 files changed, 8197 insertions(+), 3017 deletions(-) create mode 100644 packages/menu/MenuList.tsx rename packages/{snackbar/types.tsx => menu/MenuListItem.tsx} (58%) create mode 100644 packages/menu/README.md create mode 100644 packages/menu/index.scss create mode 100644 packages/menu/index.tsx create mode 100644 packages/menu/package.json create mode 100644 packages/select/BaseSelect.tsx create mode 100644 packages/select/EnhancedSelect.tsx delete mode 100644 packages/select/NativeControl.tsx create mode 100644 packages/select/NativeSelect.tsx create mode 100644 packages/select/Option.tsx create mode 100644 packages/select/helper-text/README.md create mode 100644 packages/select/helper-text/index.tsx create mode 100644 packages/select/icon/README.md create mode 100644 packages/select/icon/index.tsx create mode 100644 test/screenshot/menu/index.tsx create mode 100644 test/screenshot/select/enhanced.tsx create mode 100644 test/screenshot/select/nativeSelect.tsx create mode 100644 test/screenshot/select/variants.tsx create mode 100644 test/unit/menu/MenuList.test.tsx create mode 100644 test/unit/menu/MenuListItem.test.tsx create mode 100644 test/unit/menu/index.test.tsx create mode 100644 test/unit/select/BaseSelect.test.tsx create mode 100644 test/unit/select/EnhancedSelect.test.tsx delete mode 100644 test/unit/select/NativeControl.test.tsx create mode 100644 test/unit/select/NativeSelect.test.tsx create mode 100644 test/unit/select/Option.test.tsx create mode 100644 test/unit/select/helper-text/index.test.tsx create mode 100644 test/unit/select/icon/index.test.tsx diff --git a/docs/best-practices.md b/docs/best-practices.md index 93316de65..86c1bf0cd 100644 --- a/docs/best-practices.md +++ b/docs/best-practices.md @@ -27,9 +27,4 @@ Since `classnames@2.2.6` is exporting `default`, we should be importing as such: ```ts // referenced in https://github.com/basarat/typescript-book/blob/master/docs/project/external-modules.md#default-exportsimports import classnames from 'classnames'; -``` - -In other cases where we import modules that do not use `default`, we should import like: -```ts -import * as classnames from 'classnames'; ``` \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1a3d2146f..bd131a968 100644 --- a/package-lock.json +++ b/package-lock.json @@ -279,44 +279,59 @@ "dev": true }, "@material/base": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/base/-/base-0.41.0.tgz", - "integrity": "sha512-tEyzwBRu3d1H120SfKsDVYZHcqT5lKohh/7cWKR93aAaPDkSvjpKJIjyu2yuSkjpDduVZGzVocYbOvhUKhhzXQ==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/base/-/base-1.0.0.tgz", + "integrity": "sha512-5dxFp46x5FA+Epg6YHLzN+5zRt9S2wR84UdvVAEJ1egea94m9UHUg7y9tAnNSN16aexRSywmzyLwPr+i8PGEYA==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } }, "@material/button": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/button/-/button-0.43.0.tgz", - "integrity": "sha512-BQbU1se1RH2TcLxhvxEKCJVR0jtQVCmk1gjOJ1SmrVsRshTT5gSQE4WRSFiV/3YmXYU994/KVYMCs2aovLFE/A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/button/-/button-1.1.0.tgz", + "integrity": "sha512-P1oZyyC1ELRe26vdnmax+fO3BWNmftDqHDDlQbJ+gfYMDQsNQtZNJU16ZbnVHsnzEXOpFj729imbmuLfnz8Nbg==", "dev": true, "requires": { - "@material/elevation": "^0.43.0", - "@material/ripple": "^0.43.0", + "@material/elevation": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.1.0", "@material/rtl": "^0.42.0", - "@material/shape": "^0.43.0", - "@material/theme": "^0.43.0", - "@material/typography": "^0.43.0" + "@material/shape": "^1.0.0", + "@material/theme": "^1.1.0", + "@material/typography": "^1.0.0" }, "dependencies": { - "@material/elevation": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-0.43.0.tgz", - "integrity": "sha512-/OM+7HVS26hCa+AU0dfD/cdEkj2ssYNYIWwmqUVVJUIhB4v/xRsfnCf0Z1KXGtXU+V3AhHp8T9q5LHDzrkOvnA==", + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/theme": "^0.43.0" + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" } }, "@material/ripple": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.43.0.tgz", - "integrity": "sha512-5X5xJtE1tM5QYrsvIe5coZNk7nt++vi40CDBVxS2abO+83ky91I5mH/djcm0vcSFmkHM/QOymEQBR3XDjA3XXQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/theme": "^0.43.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" } }, "@material/rtl": { @@ -326,105 +341,334 @@ "dev": true }, "@material/shape": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/shape/-/shape-0.43.0.tgz", - "integrity": "sha512-KGnoQV4G2OQbMe5Lr5Xbk8XNlO93Qi/juxXtd2wrAfiaPmktD8ug0CwdVDOPBOmj9a0gX3Ofi9XWcoU+tLEVjg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } }, "@material/theme": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.43.0.tgz", - "integrity": "sha512-/zndZL6EihI18v2mYd4O8xvOBAAXmLeHyHVK28LozSAaJ9okQgD25wq5Ktk95oMTmPIC+rH66KcK6371ivNk8g==", - "dev": true - }, - "@material/typography": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/typography/-/typography-0.43.0.tgz", - "integrity": "sha512-WSg8vDoC2rnmOWbhNdDmSoT1jV0QQSw7CFps1DFbnIe57UaUxgWuGdhc+9XlEPctXUFto4FU4DfnRcdW4ydAig==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } } } }, "@material/card": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/card/-/card-0.41.0.tgz", - "integrity": "sha512-6/NIHuUZkftHoNS/l3JpROrpvI0TqYv4Xq9O1iRnxPmw2hwqvQ70LucE4+bJ+YzVomqYarV2KrtUUPrwSa90Lw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/card/-/card-1.1.1.tgz", + "integrity": "sha512-gLG5TmeHszM700NcFcSvXQ4EGzLTVIclhCW8Sw4sKMGaklv3S498O8MpSRGZDkRrbisXNWQpsmCAxOcTXfwlAw==", "dev": true, "requires": { - "@material/elevation": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/shape": "^0.41.0", - "@material/theme": "^0.41.0" + "@material/elevation": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.1.0", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.1.1", + "@material/theme": "^1.1.0" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.1.1.tgz", + "integrity": "sha512-Jge/h1XBLjdLlam4QMSzVgM99e/N8+elQROPkltqVP7eyLc17BwM3aP5cLVfZDgrJgvsjUxbgAP1H1j8sqmUyg==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } } }, "@material/checkbox": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-0.41.0.tgz", - "integrity": "sha512-Zz6e5WRpziO7Z+4rbEs8GHNNBf1UuttniLp6/RvwPSQRaD8G04sdg4HcP/aDCY1KGMwivkuDPc2Bsgs6j+rD7Q==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-1.0.1.tgz", + "integrity": "sha512-/FMQEM5aT3S63Rp2gWgq0/WnMl9tNpSBs222r/3YT9Aqesbdp56mcDG9rk9rq2Ph74sWxlI5+9MVwL4CZ3nCyg==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/selection-control": "^0.41.0", - "@material/theme": "^0.41.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } } }, "@material/chips": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/chips/-/chips-0.41.0.tgz", - "integrity": "sha512-Z2q01n4JdRR2f2fdYNCftmgu0M8wu8PZUeQTK3e3zVkQyRdmXcbqMbLHRawVWuXORC8/mIA6tuTtOEqle/Qj9w==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/checkbox": "^0.41.0", - "@material/elevation": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/shape": "^0.41.0", - "@material/theme": "^0.41.0", - "@material/typography": "^0.41.0" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/chips/-/chips-1.0.1.tgz", + "integrity": "sha512-UcCEkuFEE8c3zdzAnv7kdU7hG6QNOJpVgmrphWBgoPG92+yFFb8b5Wo+3MWT+SIF/wKNSNAo8a+BER9DsCOOjw==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/checkbox": "^1.0.1", + "@material/elevation": "^1.0.0", + "@material/ripple": "^1.0.1", + "@material/shape": "^1.0.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/checkbox": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-1.0.1.tgz", + "integrity": "sha512-/FMQEM5aT3S63Rp2gWgq0/WnMl9tNpSBs222r/3YT9Aqesbdp56mcDG9rk9rq2Ph74sWxlI5+9MVwL4CZ3nCyg==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.0.0.tgz", + "integrity": "sha512-TqmvEXmZDYLm2X5lEnjKCsZMDkCXpxFFxL22AfCAQB5L4d0gAS7vqDEE797y4Rp+BBKEcOP71mum1l56RI3NBQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0" + } + }, + "@material/ripple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } } }, "@material/dialog": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/dialog/-/dialog-0.43.0.tgz", - "integrity": "sha512-1WDYfzs7393Zj2BZyyix1NScUMHC+Je5gjXDTjNgmTJ54fC7izkbTeKtllczehnIOqRLPzwiWEtu4JWd+1SWgQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dialog/-/dialog-1.1.0.tgz", + "integrity": "sha512-XbFTTdzzRhjClLMDFxz8SR/mwwCBpQL6N7Z7UzX7SgD51UJmd19SsXPItFquRKk3mkNuoFBBcR4KJ6julAW+Fg==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/dom": "^0.41.0", - "@material/elevation": "^0.43.0", - "@material/ripple": "^0.43.0", + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/elevation": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.1.0", "@material/rtl": "^0.42.0", - "@material/shape": "^0.43.0", - "@material/theme": "^0.43.0", - "@material/typography": "^0.43.0", - "focus-trap": "^4.0.2" + "@material/shape": "^1.0.0", + "@material/theme": "^1.1.0", + "@material/typography": "^1.0.0", + "focus-trap": "^4.0.2", + "tslib": "^1.9.3" }, "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, "@material/elevation": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-0.43.0.tgz", - "integrity": "sha512-/OM+7HVS26hCa+AU0dfD/cdEkj2ssYNYIWwmqUVVJUIhB4v/xRsfnCf0Z1KXGtXU+V3AhHp8T9q5LHDzrkOvnA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.1.0.tgz", + "integrity": "sha512-m4eATJvDhWK1BT+yA1iHz5mhAk8cV9olC4mjVzm4PTAqhDH2yya4WzjN1HPVHE/a65ObyZ7V4qopxu9MRocm3A==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/theme": "^0.43.0" + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0" } }, "@material/ripple": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.43.0.tgz", - "integrity": "sha512-5X5xJtE1tM5QYrsvIe5coZNk7nt++vi40CDBVxS2abO+83ky91I5mH/djcm0vcSFmkHM/QOymEQBR3XDjA3XXQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/theme": "^0.43.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" } }, "@material/rtl": { @@ -434,38 +678,31 @@ "dev": true }, "@material/shape": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/shape/-/shape-0.43.0.tgz", - "integrity": "sha512-KGnoQV4G2OQbMe5Lr5Xbk8XNlO93Qi/juxXtd2wrAfiaPmktD8ug0CwdVDOPBOmj9a0gX3Ofi9XWcoU+tLEVjg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } }, "@material/theme": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.43.0.tgz", - "integrity": "sha512-/zndZL6EihI18v2mYd4O8xvOBAAXmLeHyHVK28LozSAaJ9okQgD25wq5Ktk95oMTmPIC+rH66KcK6371ivNk8g==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } }, "@material/typography": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/typography/-/typography-0.43.0.tgz", - "integrity": "sha512-WSg8vDoC2rnmOWbhNdDmSoT1jV0QQSw7CFps1DFbnIe57UaUxgWuGdhc+9XlEPctXUFto4FU4DfnRcdW4ydAig==", - "dev": true - }, - "focus-trap": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-4.0.2.tgz", - "integrity": "sha512-HtLjfAK7Hp2qbBtLS6wEznID1mPT+48ZnP2nkHzgjpL4kroYHg0CdqJ5cTXk+UO5znAxF5fRUkhdyfgrhh8Lzw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", "dev": true, "requires": { - "tabbable": "^3.1.2", - "xtend": "^4.0.1" + "@material/feature-targeting": "^0.44.1" } - }, - "tabbable": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-3.1.2.tgz", - "integrity": "sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ==", - "dev": true } } }, @@ -476,70 +713,353 @@ "dev": true }, "@material/drawer": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/drawer/-/drawer-0.41.0.tgz", - "integrity": "sha512-XMKrr9Ci7z69xwYsT1P/JH/BRccwB+HL9UiYzym8SAfZG/4XtP0b5qw+vYMrIZ/NeF0nOEaE8pNHq2XrUz0csA==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/elevation": "^0.41.0", - "@material/list": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/shape": "^0.41.0", - "@material/theme": "^0.41.0", - "@material/typography": "^0.41.0", - "focus-trap": "^3.0.0" - } - }, - "@material/elevation": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-0.41.0.tgz", - "integrity": "sha512-ZtZS8z5ie9c7Cx5PVudgSorGYa0C3lu3dA+Nn6qJdhGUokl01msh54NfNuwk+EZsk65bNRRqw1Td/63TCbKIzg==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/theme": "^0.41.0" - } - }, - "@material/fab": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/fab/-/fab-0.41.0.tgz", - "integrity": "sha512-SY/XhkFqlbT8byz0wVJF6vPoGQQRwcTpA7toK1WexW87tSme8KE17yAGJxsZYzIOOFZqW1xF+aDajWdaWyDZdQ==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/elevation": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/shape": "^0.41.0", - "@material/theme": "^0.41.0", - "@material/typography": "^0.41.0" - } - }, - "@material/floating-label": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-0.41.0.tgz", - "integrity": "sha512-qI6f1nZU3crXxWAI9fw3U5fHw2qOzEor49EvskbcaV5KSRW5qO+jtfUQ3ib/Vhki7lqhgwNHB/0n7KYhvhjRHQ==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/theme": "^0.41.0", - "@material/typography": "^0.41.0" - } - }, - "@material/icon-button": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-0.41.0.tgz", - "integrity": "sha512-RzGSH97aUcTW4he+uU8ahT75DEn6+29L0hH4PBKe03/R/qHFfOrWfjfd03PPiCkaT5SNkPkt1YnfEPqKolnH1Q==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/drawer/-/drawer-1.0.1.tgz", + "integrity": "sha512-xgpWg2MZVFWU0MX+H4MmWA0XQO0cxF1XFA0KdyV+7W0bdzpI1x8itM8Xh0suyzqyqDc+GMHG/OxP8KYUv40jeg==", "dev": true, "requires": { - "@material/base": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/theme": "^0.41.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/elevation": "^1.0.0", + "@material/list": "^1.0.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.0.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0", + "focus-trap": "^4.0.2", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.0.0.tgz", + "integrity": "sha512-TqmvEXmZDYLm2X5lEnjKCsZMDkCXpxFFxL22AfCAQB5L4d0gAS7vqDEE797y4Rp+BBKEcOP71mum1l56RI3NBQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0" + } + }, + "@material/list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/list/-/list-1.0.1.tgz", + "integrity": "sha512-u9Bx+mghPy2qCHcSH2b0+0jbjTtkXNdiWjb8JDQcYmOUTfFoeQ16GqvjTybRPwoKA0UC9Hc/4U8gYvnK+bReRw==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.0.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/elevation": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.1.0.tgz", + "integrity": "sha512-m4eATJvDhWK1BT+yA1iHz5mhAk8cV9olC4mjVzm4PTAqhDH2yya4WzjN1HPVHE/a65ObyZ7V4qopxu9MRocm3A==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/fab": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/fab/-/fab-1.1.0.tgz", + "integrity": "sha512-oCvo/4TFri+agTkGvEd5lREuwowInYw6OBbwNmGxpWQs4QGlMGHRS9/h8sfMYNZxs2TrwNUCwf/DK0WZEvniLQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/elevation": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.1.0", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.0.0", + "@material/theme": "^1.1.0", + "@material/typography": "^1.0.0" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.1.0.tgz", + "integrity": "sha512-m4eATJvDhWK1BT+yA1iHz5mhAk8cV9olC4mjVzm4PTAqhDH2yya4WzjN1HPVHE/a65ObyZ7V4qopxu9MRocm3A==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0" + } + }, + "@material/ripple": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/feature-targeting": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@material/feature-targeting/-/feature-targeting-0.44.1.tgz", + "integrity": "sha512-90cc7njn4aHbH9UxY8qgZth1W5JgOgcEdWdubH1t7sFkwqFxS5g3zgxSBt46TygFBVIXNZNq35Xmg80wgqO7Pg==", + "dev": true + }, + "@material/floating-label": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-1.0.0.tgz", + "integrity": "sha512-yESFi8HEUO0PmPWvaU3VW4X8+xaoFHhj2xGxLPu2hGye4ZBjTpmjOX6y1vwYqZLD5KWXj91k695UAT6J2wtWFQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/rtl": "^0.42.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/icon-button": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-1.1.0.tgz", + "integrity": "sha512-3HYOfFhlgpY32HyNt1thQJfTycjy0Cfd4B4IZmt2irfaETdj6JuP0wKs9kdEx1VHTbfWFkJHENArz0lPW+6r2A==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.1.0", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } } }, "@material/layout-grid": { @@ -549,250 +1069,1207 @@ "dev": true }, "@material/line-ripple": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-0.41.0.tgz", - "integrity": "sha512-5DDIoC3d78fCLhNgle7DRFojT3D2SF+XVpUd3g6yLZmybHB7832p4bgl/qGpbIXwk1wAQA1dkUgKH5foxorjNQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-1.0.0.tgz", + "integrity": "sha512-sFFpoFXVnqkknkac5bCrMhKGacay26AWVFfc3acaEGjQgkvF8VBV/bS41+CioACyubpc4JL69PU9Um/t7xAQVw==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/theme": "^0.41.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/base/-/base-1.0.0.tgz", + "integrity": "sha512-5dxFp46x5FA+Epg6YHLzN+5zRt9S2wR84UdvVAEJ1egea94m9UHUg7y9tAnNSN16aexRSywmzyLwPr+i8PGEYA==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } } }, "@material/linear-progress": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-0.41.0.tgz", - "integrity": "sha512-yWnJK58QfovYNJXANGfKWcyC5k9IqBFvygYa2EYQSH/MZbIvd84+MIn0fJO9xsRza79BA8Xh2tFIdTFy4+2Ctg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-1.1.0.tgz", + "integrity": "sha512-MIK0cD/o1rTLREtAfTK3v60h7A0/wAu8/3v9dPTMlAPe+Y5gOarAizYWM3r/bp88sGO4gU8nPK0X9/daD28pNw==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/theme": "^0.41.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/list/-/list-1.0.1.tgz", + "integrity": "sha512-u9Bx+mghPy2qCHcSH2b0+0jbjTtkXNdiWjb8JDQcYmOUTfFoeQ16GqvjTybRPwoKA0UC9Hc/4U8gYvnK+bReRw==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.0.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/menu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/menu/-/menu-1.1.1.tgz", + "integrity": "sha512-bfsZ4Uexm02ey665SukjMK+3HtQVu7Bbc/q5chvPmLoMbSQ4PYE19C/p8cXKeNxkhd3S0h/gJDPw/cTbB9mrhg==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/list": "^1.1.1", + "@material/menu-surface": "^1.1.1", + "@material/ripple": "^1.1.0", + "@material/rtl": "^0.42.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/list": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/list/-/list-1.1.1.tgz", + "integrity": "sha512-YqX2A5qagoBolla6WHzP2BIUid/ufot5rVP2yrTz3DFvmswJMXU3HV2XU9NbiVOiefCjkra9ljtimiTlHUrAEg==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.1.0", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.1.1", + "@material/theme": "^1.1.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/menu-surface": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-1.1.1.tgz", + "integrity": "sha512-bOY3LsVamovl/yb4hMBDi3gh8UFEYyP3GHNpTt+X5KBPDehoFhXG9s21aNvGbHZbwURhhWiRzy/OUC3MLE/hKA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/elevation": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.1.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.1.1.tgz", + "integrity": "sha512-Jge/h1XBLjdLlam4QMSzVgM99e/N8+elQROPkltqVP7eyLc17BwM3aP5cLVfZDgrJgvsjUxbgAP1H1j8sqmUyg==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/menu-surface": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-1.0.1.tgz", + "integrity": "sha512-JFUa3kQ+NtpuK/mgWIcyhC1AClKmt9EQdW4SG2KQhPAGg0juWiZwyMySDIjf+V0buSUZXZ7N26bi32+Y1LvZ3w==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/elevation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.0.0", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.0.0.tgz", + "integrity": "sha512-TqmvEXmZDYLm2X5lEnjKCsZMDkCXpxFFxL22AfCAQB5L4d0gAS7vqDEE797y4Rp+BBKEcOP71mum1l56RI3NBQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/notched-outline": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-1.1.1.tgz", + "integrity": "sha512-HekxMWgIEGlmmdiCATfEJPjAWz2jlyXnfGUiBOkAzI25/OyOgcCd3rLzcMT5DUqItbKoNk1M/9kOmzTSNSt/CA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/floating-label": "^1.1.0", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.1.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/floating-label": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-1.1.0.tgz", + "integrity": "sha512-7q7V+9o9XesgMnK11up9z+BcRFwtLIAIqVTCL3liKRARNHuzw9FGrGMKhTJUKvLZ3z0bM1+FmmVlA3q9FJWehQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/rtl": "^0.42.0", + "@material/theme": "^1.1.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.1.1.tgz", + "integrity": "sha512-Jge/h1XBLjdLlam4QMSzVgM99e/N8+elQROPkltqVP7eyLc17BwM3aP5cLVfZDgrJgvsjUxbgAP1H1j8sqmUyg==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/radio": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/radio/-/radio-1.1.0.tgz", + "integrity": "sha512-ySocik+l1fInopaA8hDfByJahv1UywUNtUcG7+hLLOhxQx4XVpUJUIjU/dlvVDYJB0QZQatm2asKi2cYVPlIsQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.1.0", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/ripple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.0.tgz", + "integrity": "sha512-WUjc6LU2D9mRjfHJPQgj8ljG0NuppwOAM6bIt5wyJ3aiUyYQqW05cvB7YCbYE7WHgfxFtL6UOrGuUG4Z+izJDw==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.0.tgz", + "integrity": "sha512-P2WDLk/9iZxg4RCvwqCtrObm0Qm0EF5G6X/rw21FKTg6uhwmPR75tCj2Zr1yyvVS9rjLxXZf0bQRsgvKxVE6Zw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/rtl": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.40.1.tgz", + "integrity": "sha512-Pk6Iw1/KrhWZoZtkDsPMDUW0bm7Z1zeXb3MTQRCFmjf1wU5cRxgOTtuoZLcJqlcKGppLAzJL/TJV3E7KEiuL0A==", + "dev": true + }, + "@material/select": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/select/-/select-1.1.1.tgz", + "integrity": "sha512-si/RGmqRcLflBmA4EXeiR4gVuOIM0YAqIwVN7WOwrx+AhfBDuvI9sPMDz2UXZ2VoFpll73TTRMdah2MPTpmCxQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/floating-label": "^1.1.0", + "@material/line-ripple": "^1.1.0", + "@material/menu": "^1.1.1", + "@material/menu-surface": "^1.1.1", + "@material/notched-outline": "^1.1.1", + "@material/ripple": "^1.1.0", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.1.1", + "@material/theme": "^1.1.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/floating-label": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-1.1.0.tgz", + "integrity": "sha512-7q7V+9o9XesgMnK11up9z+BcRFwtLIAIqVTCL3liKRARNHuzw9FGrGMKhTJUKvLZ3z0bM1+FmmVlA3q9FJWehQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/rtl": "^0.42.0", + "@material/theme": "^1.1.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/line-ripple": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-1.1.0.tgz", + "integrity": "sha512-XqCxDNfgkh9zq0IVlTEFVjmQV8hx8m4vxLFM5qwHDDqcKPlX/Lfc8M43fmm9uE1CaJBC6whMGPvOt/dIla+RUg==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/menu-surface": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-1.1.1.tgz", + "integrity": "sha512-bOY3LsVamovl/yb4hMBDi3gh8UFEYyP3GHNpTt+X5KBPDehoFhXG9s21aNvGbHZbwURhhWiRzy/OUC3MLE/hKA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/elevation": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.1.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.1.1.tgz", + "integrity": "sha512-Jge/h1XBLjdLlam4QMSzVgM99e/N8+elQROPkltqVP7eyLc17BwM3aP5cLVfZDgrJgvsjUxbgAP1H1j8sqmUyg==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/shape": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-0.41.0.tgz", + "integrity": "sha512-k1K3CjOVxclfb/0r28cOa2oJpP7QMA2fP0SOS3Vh8ale5Q2jkaHTL60KX8VkHvV6rMqShpXW+60gPjoz5XRbDQ==", + "dev": true + }, + "@material/snackbar": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/snackbar/-/snackbar-1.0.1.tgz", + "integrity": "sha512-Gts1N3DA7uEac7JZ1kNwTN+ljgrMDzVGgLAwgcPFSssndW08GSkmZSAko8Lk0Zb4hDY90WtI4jPwuzekixIrWw==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/button": "^1.0.1", + "@material/dom": "^1.0.1", + "@material/icon-button": "^1.0.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.0.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/button": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/button/-/button-1.0.1.tgz", + "integrity": "sha512-gMGuAlG9ETKH14Up4RAH87Z+51NkU725C4H7J0AnICzG75Rto8PtpMqNu5+w/c1cQM1Hudc8JfsflneMEZ10oA==", + "dev": true, + "requires": { + "@material/elevation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/shape": "^1.0.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.0.0.tgz", + "integrity": "sha512-TqmvEXmZDYLm2X5lEnjKCsZMDkCXpxFFxL22AfCAQB5L4d0gAS7vqDEE797y4Rp+BBKEcOP71mum1l56RI3NBQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0" + } + }, + "@material/icon-button": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-1.0.1.tgz", + "integrity": "sha512-a2jnwYMTDwPVsOIc4+osZIbXwQM7ujy1grQtjvvS0CVogsOdLXYzqUYrI8V9aHxdAdndos3ssm3JAziQhbsuEQ==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/ripple": "^1.0.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/shape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/switch": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/switch/-/switch-1.0.1.tgz", + "integrity": "sha512-McSLQA+VQdNV+wT6pRLpvlXv7V2BLsUkyIuCog8+Cs0Gsi4Lgs17I6iqdzQi4tySAX+G7nl6vqdUem/udUJZmw==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/elevation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.0.0.tgz", + "integrity": "sha512-TqmvEXmZDYLm2X5lEnjKCsZMDkCXpxFFxL22AfCAQB5L4d0gAS7vqDEE797y4Rp+BBKEcOP71mum1l56RI3NBQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0" + } + }, + "@material/ripple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/tab": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/tab/-/tab-1.0.1.tgz", + "integrity": "sha512-//JXHaL1ebTpR6Z1mZpd6Ltry/kD840HSI/NQRMCdjxKjdap3cVtNfjRZ5ST4snGEqihLQ7gsqfDg/XZ5k0j3g==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/tab-indicator": "^1.0.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/tab-bar": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/tab-bar/-/tab-bar-1.0.1.tgz", + "integrity": "sha512-zou4iUmTPW96uEepD3whGbkPeo4SvuaQCuR0FsRiBQA2fCdnGX2Eyn03GY5Kv41lDw9RpoEoMflkKU/njHK8gw==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/elevation": "^1.0.0", + "@material/tab": "^1.0.1", + "@material/tab-scroller": "^1.0.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.0.0.tgz", + "integrity": "sha512-TqmvEXmZDYLm2X5lEnjKCsZMDkCXpxFFxL22AfCAQB5L4d0gAS7vqDEE797y4Rp+BBKEcOP71mum1l56RI3NBQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/tab-indicator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/tab-indicator/-/tab-indicator-1.0.0.tgz", + "integrity": "sha512-4wT+dAc6YOe7ASPt68soHSqKlr/VVl5JcS883M8I2kAtJe92BglsHYW2ALa9IdqwWcvhFaw0sXZKWohLRwibMw==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } + } + }, + "@material/tab-scroller": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/tab-scroller/-/tab-scroller-1.0.1.tgz", + "integrity": "sha512-WpOw710NbLlx3W/ZqAmeoBCon+6u6/PpoSusrh/Qvxats9hajc5bQUSfjm/grzEhZcqfyXN/bCoci3lBIbfWvw==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/tab": "^1.0.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/ripple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/tab": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/tab/-/tab-1.0.1.tgz", + "integrity": "sha512-//JXHaL1ebTpR6Z1mZpd6Ltry/kD840HSI/NQRMCdjxKjdap3cVtNfjRZ5ST4snGEqihLQ7gsqfDg/XZ5k0j3g==", + "dev": true, + "requires": { + "@material/base": "^1.0.0", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/tab-indicator": "^1.0.0", + "@material/theme": "^1.0.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + }, + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } + } } }, - "@material/list": { + "@material/textfield": { "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/list/-/list-0.41.0.tgz", - "integrity": "sha512-HhYN0I02CTT8j91c1eeeI+L2KXVKdfzj0Zuapp2SdeCmQZLJO2tu2NYj0W6REBDTVBWBccr12Sn8o71CodEScQ==", + "resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-0.41.0.tgz", + "integrity": "sha512-kJ52W2gxOS2xfpreVhvHQ1u3UkiDl58duw9HkhEkK5Oi1bSDOtbnlWy0pGTOiAma5ZQgetPNgoa+T0zMBptfnw==", "dev": true, "requires": { + "@material/animation": "^0.41.0", "@material/base": "^0.41.0", - "@material/dom": "^0.41.0", + "@material/floating-label": "^0.41.0", + "@material/line-ripple": "^0.41.0", + "@material/notched-outline": "^0.41.0", "@material/ripple": "^0.41.0", "@material/rtl": "^0.40.1", "@material/shape": "^0.41.0", "@material/theme": "^0.41.0", "@material/typography": "^0.41.0" - } - }, - "@material/menu-surface": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-0.41.0.tgz", - "integrity": "sha512-HiGFrEIF8DCfEtS8mRtc6MCcK2CJNCh0U6KWWeSIXv+9nW2oiN09piuULXM7aU46wETvfweVcgvHNJvBAXnXjQ==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/elevation": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/shape": "^0.41.0", - "@material/theme": "^0.41.0" - } - }, - "@material/notched-outline": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-0.41.0.tgz", - "integrity": "sha512-nQBkOXvkd5G9FeJ9UuecZh88WRgTsnGVvfj7UFJZEkvkzZwLBGUiJS6fF9FYraih3ZFgmphdbJxXEd9af3cqyQ==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/shape": "^0.41.0", - "@material/theme": "^0.41.0" - } - }, - "@material/radio": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/radio/-/radio-0.41.0.tgz", - "integrity": "sha512-nJvVVu2x2lAttUNnJczpZzKWK+3lEw/BOYsSLVSYp1qUlIQsOfQ6aItI7URokbLkQDqDqlsNmvGP5JJv/Cpksw==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/selection-control": "^0.41.0", - "@material/theme": "^0.41.0" - } - }, - "@material/ripple": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.41.0.tgz", - "integrity": "sha512-rxEUVWM4AByDlTCH0kkthZQmUuY6eeN0X6cOHBoioFN2vUDk0D0Nfzz/N9FF2AlAf8C2lDDLrTuqnJPVIn+NHA==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/theme": "^0.41.0" - } - }, - "@material/rtl": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.40.1.tgz", - "integrity": "sha512-Pk6Iw1/KrhWZoZtkDsPMDUW0bm7Z1zeXb3MTQRCFmjf1wU5cRxgOTtuoZLcJqlcKGppLAzJL/TJV3E7KEiuL0A==", - "dev": true - }, - "@material/select": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/select/-/select-0.40.1.tgz", - "integrity": "sha512-aOMoOEzJRyQbTYiXRifqaLEvX0Oj5w/WWa9+UStemeIURVSnOlaVPlnNY+dcvr6vvFeGfBX6q/G1O+CGk0FIbA==", - "dev": true, - "requires": { - "@material/animation": "^0.40.1", - "@material/base": "^0.40.1", - "@material/floating-label": "^0.40.1", - "@material/line-ripple": "^0.40.1", - "@material/notched-outline": "^0.40.1", - "@material/ripple": "^0.40.1", - "@material/rtl": "^0.40.1", - "@material/shape": "^0.40.1", - "@material/theme": "^0.40.1", - "@material/typography": "^0.40.1" }, "dependencies": { - "@material/animation": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/animation/-/animation-0.40.1.tgz", - "integrity": "sha512-HtxFUw04EHg4S6pXfTA3Z0wKxnNDNcDhe1Np2Y2geo+lAk2Hb7m8yCL/GaL9o2I/eRYsgUXC0U7+Mk74GCz3zw==", - "dev": true - }, "@material/base": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/base/-/base-0.40.1.tgz", - "integrity": "sha512-vrbOK8hONVCYgURQ9h7nkXvMdYnZVVNmAfFFijF8fbWQdwnoPcNTdqV6RoQlhBEqHYHQqLNfdUDlznAPKLclGQ==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@material/base/-/base-0.41.0.tgz", + "integrity": "sha512-tEyzwBRu3d1H120SfKsDVYZHcqT5lKohh/7cWKR93aAaPDkSvjpKJIjyu2yuSkjpDduVZGzVocYbOvhUKhhzXQ==", "dev": true }, "@material/floating-label": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-0.40.1.tgz", - "integrity": "sha512-b8/Wj4qfqOSJRSoQ1X7EC2lQc2hF0IGPXIbGpanZYe0c3wnhRXdSYd4kUnDw6rHgKn2IfnOEZkzOetODkftWDw==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-0.41.0.tgz", + "integrity": "sha512-qI6f1nZU3crXxWAI9fw3U5fHw2qOzEor49EvskbcaV5KSRW5qO+jtfUQ3ib/Vhki7lqhgwNHB/0n7KYhvhjRHQ==", "dev": true, "requires": { - "@material/animation": "^0.40.1", - "@material/base": "^0.40.1", + "@material/animation": "^0.41.0", + "@material/base": "^0.41.0", "@material/rtl": "^0.40.1", - "@material/theme": "^0.40.1", - "@material/typography": "^0.40.1" + "@material/theme": "^0.41.0", + "@material/typography": "^0.41.0" } }, "@material/line-ripple": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-0.40.1.tgz", - "integrity": "sha512-S4Iq9qtxAF0ViwGfl+Dkb/dDd9EdJx/MpzA0/Lq51XvxWoJJvLfEEvX9j+V41ZhPd9FzqocTtUCCAw7Cov5mEw==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-0.41.0.tgz", + "integrity": "sha512-5DDIoC3d78fCLhNgle7DRFojT3D2SF+XVpUd3g6yLZmybHB7832p4bgl/qGpbIXwk1wAQA1dkUgKH5foxorjNQ==", "dev": true, "requires": { - "@material/animation": "^0.40.1", - "@material/base": "^0.40.1", - "@material/theme": "^0.40.1" + "@material/animation": "^0.41.0", + "@material/base": "^0.41.0", + "@material/theme": "^0.41.0" } }, "@material/notched-outline": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-0.40.1.tgz", - "integrity": "sha512-b3V6/G7TW1P21Frw3JxB6Hc6k7MbrmPSynGuVUPLmuX+eSUm6GhxOy0rK4UzlBZumDnyyJDw+2HvJd1BYoOgeg==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-0.41.0.tgz", + "integrity": "sha512-nQBkOXvkd5G9FeJ9UuecZh88WRgTsnGVvfj7UFJZEkvkzZwLBGUiJS6fF9FYraih3ZFgmphdbJxXEd9af3cqyQ==", "dev": true, "requires": { - "@material/animation": "^0.40.1", - "@material/base": "^0.40.1", + "@material/animation": "^0.41.0", + "@material/base": "^0.41.0", "@material/rtl": "^0.40.1", - "@material/shape": "^0.40.1", - "@material/theme": "^0.40.1" + "@material/shape": "^0.41.0", + "@material/theme": "^0.41.0" } }, "@material/ripple": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.40.1.tgz", - "integrity": "sha512-sndeTS4VHa0v1UGj7MNcxMCuO9LJ1DjoL1EjE6BH3Lm3M1MnXJHdsBo2CgPbU/FI84tt6+eyHGOYPdPrEDJhCA==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.41.0.tgz", + "integrity": "sha512-rxEUVWM4AByDlTCH0kkthZQmUuY6eeN0X6cOHBoioFN2vUDk0D0Nfzz/N9FF2AlAf8C2lDDLrTuqnJPVIn+NHA==", "dev": true, "requires": { - "@material/animation": "^0.40.1", - "@material/base": "^0.40.1", - "@material/theme": "^0.40.1" + "@material/animation": "^0.41.0", + "@material/base": "^0.41.0", + "@material/theme": "^0.41.0" } }, - "@material/shape": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/shape/-/shape-0.40.1.tgz", - "integrity": "sha512-o1pw5+s/jWqsKbUAkCCaEcB8XLqJ4FlZhYfSvxZ88WRw9zoWOt9iQMMP82wLWhUX1DSzpNRI8BAD7aNLK6yRlA==", - "dev": true - }, - "@material/theme": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.40.1.tgz", - "integrity": "sha512-cH1CsGIDisEQ2oroZhLTypV0Ir00x3WIwFXnPo7qv3832tuIDkZY623U3rUax6KNPz4Hh1j0tNpTwgrNZwvwWA==", - "dev": true - }, "@material/typography": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@material/typography/-/typography-0.40.1.tgz", - "integrity": "sha512-LkW2tAsId8zGKxGA5VIFXV/D1h4vCHQIuALRMaDpHbNGffgr2ubtJNvCh2EQkm19MTv4igVLEjn1Svh0dXcTpA==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-0.41.0.tgz", + "integrity": "sha512-15dlqSU+9uGcWdg4KXXcmDzTKJPb7/5Z9kmooONb2Laot1uiuntDXQS0yL+U2FYLW5Ros+WVMosDBKFruWx68A==", "dev": true } } }, - "@material/selection-control": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/selection-control/-/selection-control-0.41.0.tgz", - "integrity": "sha512-rRHGiZVPoP4nxAAoeqsgTsxz9GwInGs7HIlEhPfMFygmSZVUHHsuOJXSTpOKYi8GCoKHpB0RKZsAtxM0BYAelw==", - "dev": true, - "requires": { - "@material/ripple": "^0.41.0" - } - }, - "@material/shape": { + "@material/theme": { "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/shape/-/shape-0.41.0.tgz", - "integrity": "sha512-k1K3CjOVxclfb/0r28cOa2oJpP7QMA2fP0SOS3Vh8ale5Q2jkaHTL60KX8VkHvV6rMqShpXW+60gPjoz5XRbDQ==", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.41.0.tgz", + "integrity": "sha512-ohW2JxObKOWvP34EkIIcrEVtL3g0Gs/T3/MdOsM36euyshY8Jwl1f6fjVUQvVjSpixUtSb30/+ulblF8fTOwBg==", "dev": true }, - "@material/snackbar": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/snackbar/-/snackbar-0.43.0.tgz", - "integrity": "sha512-jmyQSDRLHeZWitrQJM26gySxBeY47zuAyouVsdm0HioYiElQWsn2LJLvl74kLwYByHtK+sFNkcJkKUh+Xm36OQ==", + "@material/top-app-bar": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/top-app-bar/-/top-app-bar-1.1.0.tgz", + "integrity": "sha512-fxVKFolNzPG4+LqH8GUxDKfjRZtQNDYX8sGD6c2pKbk1tigyiAGBO/Py31RQQkbAdCKPdmnanGJK2gewaUdw4g==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/button": "^0.43.0", - "@material/dom": "^0.41.0", - "@material/icon-button": "^0.43.0", - "@material/ripple": "^0.43.0", + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/elevation": "^1.1.0", + "@material/ripple": "^1.1.0", "@material/rtl": "^0.42.0", - "@material/shape": "^0.43.0", - "@material/theme": "^0.43.0", - "@material/typography": "^0.43.0" + "@material/shape": "^1.0.0", + "@material/theme": "^1.1.0", + "@material/typography": "^1.0.0", + "tslib": "^1.9.3" }, "dependencies": { - "@material/icon-button": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-0.43.0.tgz", - "integrity": "sha512-muldr6pmX2peY9ECYxcZfnmDWLqinT+HRVuND2ltCKUqgLBGi4DETQQE0PEOzsChePJothbyqeQorXgcBP8EgQ==", + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", "dev": true, "requires": { - "@material/base": "^0.41.0", - "@material/ripple": "^0.43.0", - "@material/theme": "^0.43.0" + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.1.0.tgz", + "integrity": "sha512-+HWW38ZaM2UBPu4+7QCusLDSf4tFT31rsEXHkTkxYSg/QpDivfPx6YDz4OmYtafmhPR1d1YjqB3MYysUHdodyw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.1.0.tgz", + "integrity": "sha512-m4eATJvDhWK1BT+yA1iHz5mhAk8cV9olC4mjVzm4PTAqhDH2yya4WzjN1HPVHE/a65ObyZ7V4qopxu9MRocm3A==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0" } }, "@material/ripple": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.43.0.tgz", - "integrity": "sha512-5X5xJtE1tM5QYrsvIe5coZNk7nt++vi40CDBVxS2abO+83ky91I5mH/djcm0vcSFmkHM/QOymEQBR3XDjA3XXQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.1.0.tgz", + "integrity": "sha512-mkfDBZAmxjpRG7V9TrfOmLxt1g/wvGHCXtYPgvH7W8ozjf53edqxLOFENEdvHbie27y9nyixzXn0gzU0HnxSeA==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/theme": "^0.43.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.1.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.1.0", + "tslib": "^1.9.3" } }, "@material/rtl": { @@ -802,134 +2279,43 @@ "dev": true }, "@material/shape": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/shape/-/shape-0.43.0.tgz", - "integrity": "sha512-KGnoQV4G2OQbMe5Lr5Xbk8XNlO93Qi/juxXtd2wrAfiaPmktD8ug0CwdVDOPBOmj9a0gX3Ofi9XWcoU+tLEVjg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-1.0.0.tgz", + "integrity": "sha512-zfXEacPQZmH+ujVtaFyfAsYiF46j1QCcFzJeZVouG4pznrbA7XD6614Ywg0wbyWX5iB6hD52ld/IN+R/6oxKqA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } }, "@material/theme": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.43.0.tgz", - "integrity": "sha512-/zndZL6EihI18v2mYd4O8xvOBAAXmLeHyHVK28LozSAaJ9okQgD25wq5Ktk95oMTmPIC+rH66KcK6371ivNk8g==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.1.0.tgz", + "integrity": "sha512-YYUV9Rhbx4r/EMb/zoOYJUWjhXChNaLlH1rqt3vpNVyxRcxGqoVMGp5u1XALBCFiD9dACPKLIkKyRYa928nmPQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } }, "@material/typography": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@material/typography/-/typography-0.43.0.tgz", - "integrity": "sha512-WSg8vDoC2rnmOWbhNdDmSoT1jV0QQSw7CFps1DFbnIe57UaUxgWuGdhc+9XlEPctXUFto4FU4DfnRcdW4ydAig==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" + } } } }, - "@material/switch": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/switch/-/switch-0.41.0.tgz", - "integrity": "sha512-8YTrn1oisUhp6DlB1XAPeFWVr5nD88jlq9FoTVQOtGaUxaEybQD0nrsYI7OwaVm4HvSnepd2zmMvbjXKbQX4XQ==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/elevation": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/selection-control": "^0.41.0", - "@material/theme": "^0.41.0" - } - }, - "@material/tab": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/tab/-/tab-0.41.0.tgz", - "integrity": "sha512-yM6eYD8Kgrk2cHa+zN3GYIK4Mt6EsSxDIpaArE6JopqRpalULjiOk83hWVPR1V95xphnzYAWM1YF6I6JexE9kw==", - "dev": true, - "requires": { - "@material/base": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/tab-indicator": "^0.41.0", - "@material/theme": "^0.41.0", - "@material/typography": "^0.41.0" - } - }, - "@material/tab-bar": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/tab-bar/-/tab-bar-0.41.0.tgz", - "integrity": "sha512-RL+0CA4ZeZAmhz3vlyFsm8h9sLim8JHTLkosfZSYRnx2o9iQHQHpV58jz76ZSWG+0iuDoHFnwZ2oNKNmImn0KQ==", - "dev": true, - "requires": { - "@material/base": "^0.41.0", - "@material/elevation": "^0.41.0", - "@material/tab": "^0.41.0", - "@material/tab-scroller": "^0.41.0" - } - }, - "@material/tab-indicator": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/tab-indicator/-/tab-indicator-0.41.0.tgz", - "integrity": "sha512-IBJEO+O8OnFVgRAn4CCGccpyNPF1bvTp5+1foD46S2u7XZLD7ejfxTQhqE5HYWtVLQ3zk1aYo3+N9+oSUkpM2w==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/theme": "^0.41.0" - } - }, - "@material/tab-scroller": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/tab-scroller/-/tab-scroller-0.41.0.tgz", - "integrity": "sha512-dyxaxLLSiDigIUVJ0BwqnKBtBseALrOhmPgvk6BQVDbynnRQ2bOvaNZ7cbpe3A0i8zOQGOoTZF4i9D38/iubcg==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/tab": "^0.41.0" - } - }, - "@material/textfield": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-0.41.0.tgz", - "integrity": "sha512-kJ52W2gxOS2xfpreVhvHQ1u3UkiDl58duw9HkhEkK5Oi1bSDOtbnlWy0pGTOiAma5ZQgetPNgoa+T0zMBptfnw==", - "dev": true, - "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/floating-label": "^0.41.0", - "@material/line-ripple": "^0.41.0", - "@material/notched-outline": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/shape": "^0.41.0", - "@material/theme": "^0.41.0", - "@material/typography": "^0.41.0" - } - }, - "@material/theme": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.41.0.tgz", - "integrity": "sha512-ohW2JxObKOWvP34EkIIcrEVtL3g0Gs/T3/MdOsM36euyshY8Jwl1f6fjVUQvVjSpixUtSb30/+ulblF8fTOwBg==", - "dev": true - }, - "@material/top-app-bar": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/top-app-bar/-/top-app-bar-0.41.0.tgz", - "integrity": "sha512-U3MK6pdzyfXC3zttsrEYihzR7aRqnKM3w2MWRwI0iub/lFygVOSa4qQfaJhwjz9TTyxB8tdtZOXBpEVDsH+xmA==", + "@material/typography": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-1.0.0.tgz", + "integrity": "sha512-Oeqbjci1cC7jTE8/n3dwnkqKe9ZeWiaE+rgMtRYtRFw1HvAw14SpGA5EEAS/Li2Hu2KZ50FYCe3HYqShfxtChA==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/elevation": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/shape": "^0.41.0", - "@material/theme": "^0.41.0", - "@material/typography": "^0.41.0" + "@material/feature-targeting": "^0.44.1" } }, - "@material/typography": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/typography/-/typography-0.41.0.tgz", - "integrity": "sha512-15dlqSU+9uGcWdg4KXXcmDzTKJPb7/5Z9kmooONb2Laot1uiuntDXQS0yL+U2FYLW5Ros+WVMosDBKFruWx68A==", - "dev": true - }, "@types/caseless": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz", @@ -1191,6 +2577,55 @@ "es6-promisify": "^5.0.0" } }, + "airbnb-prop-types": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz", + "integrity": "sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ==", + "dev": true, + "requires": { + "array.prototype.find": "^2.0.4", + "function.prototype.name": "^1.1.0", + "has": "^1.0.3", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0", + "prop-types": "^15.7.2", + "prop-types-exact": "^1.2.0", + "react-is": "^16.8.6" + }, + "dependencies": { + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", @@ -1678,6 +3113,12 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1733,6 +3174,27 @@ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, + "array.prototype.find": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", + "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, + "array.prototype.flat": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz", + "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.10.0", + "function-bind": "^1.1.1" + } + }, "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", @@ -3550,13 +5012,13 @@ "dev": true }, "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", "dev": true, "requires": { "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", + "dom-serializer": "~0.1.1", "entities": "~1.1.1", "htmlparser2": "^3.9.1", "lodash": "^4.15.0", @@ -5698,9 +7160,9 @@ } }, "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", "dev": true }, "cssesc": { @@ -6118,21 +7580,13 @@ } }, "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", "dev": true, "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } + "domelementtype": "^1.3.0", + "entities": "^1.1.1" } }, "domain-browser": { @@ -6142,15 +7596,15 @@ "dev": true }, "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, "domhandler": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", - "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "dev": true, "requires": { "domelementtype": "1" @@ -6401,53 +7855,134 @@ "dev": true }, "enzyme": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.3.0.tgz", - "integrity": "sha512-l8csyPyLmtxskTz6pX9W8eDOyH1ckEtDttXk/vlFWCjv00SkjTjtoUrogqp4yEvMyneU9dUJoOLnqFoiHb8IHA==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.9.0.tgz", + "integrity": "sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg==", "dev": true, "requires": { + "array.prototype.flat": "^1.2.1", "cheerio": "^1.0.0-rc.2", - "function.prototype.name": "^1.0.3", - "has": "^1.0.1", + "function.prototype.name": "^1.1.0", + "has": "^1.0.3", + "html-element-map": "^1.0.0", "is-boolean-object": "^1.0.0", - "is-callable": "^1.1.3", + "is-callable": "^1.1.4", "is-number-object": "^1.0.3", + "is-regex": "^1.0.4", "is-string": "^1.0.4", "is-subset": "^0.1.1", - "lodash": "^4.17.4", - "object-inspect": "^1.5.0", + "lodash.escape": "^4.0.1", + "lodash.isequal": "^4.5.0", + "object-inspect": "^1.6.0", "object-is": "^1.0.1", "object.assign": "^4.1.0", "object.entries": "^1.0.4", "object.values": "^1.0.4", "raf": "^3.4.0", - "rst-selector-parser": "^2.2.3" + "rst-selector-parser": "^2.2.3", + "string.prototype.trim": "^1.1.2" + }, + "dependencies": { + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + } } }, "enzyme-adapter-react-16": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.1.1.tgz", - "integrity": "sha512-kC8pAtU2Jk3OJ0EG8Y2813dg9Ol0TXi7UNxHzHiWs30Jo/hj7alc//G1YpKUsPP1oKl9X+Lkx+WlGJpPYA+nvw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.12.1.tgz", + "integrity": "sha512-GB61gvY97XvrA6qljExGY+lgI6BBwz+ASLaRKct9VQ3ozu0EraqcNn3CcrUckSGIqFGa1+CxO5gj5is5t3lwrw==", "dev": true, "requires": { - "enzyme-adapter-utils": "^1.3.0", - "lodash": "^4.17.4", - "object.assign": "^4.0.4", - "object.values": "^1.0.4", - "prop-types": "^15.6.0", - "react-reconciler": "^0.7.0", - "react-test-renderer": "^16.0.0-0" + "enzyme-adapter-utils": "^1.11.0", + "object.assign": "^4.1.0", + "object.values": "^1.1.0", + "prop-types": "^15.7.2", + "react-is": "^16.8.6", + "react-test-renderer": "^16.0.0-0", + "semver": "^5.6.0" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } } }, "enzyme-adapter-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.3.0.tgz", - "integrity": "sha512-vVXSt6uDv230DIv+ebCG66T1Pm36Kv+m74L1TrF4kaE7e1V7Q/LcxO0QRkajk5cA6R3uu9wJf5h13wOTezTbjA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.11.0.tgz", + "integrity": "sha512-0VZeoE9MNx+QjTfsjmO1Mo+lMfunucYB4wt5ficU85WB/LoetTJrbuujmHP3PJx6pSoaAuLA+Mq877x4LoxdNg==", "dev": true, "requires": { - "lodash": "^4.17.4", - "object.assign": "^4.0.4", - "prop-types": "^15.6.0" + "airbnb-prop-types": "^2.12.0", + "function.prototype.name": "^1.1.0", + "object.assign": "^4.1.0", + "object.fromentries": "^2.0.0", + "prop-types": "^15.7.2", + "semver": "^5.6.0" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } } }, "errno": { @@ -7428,12 +8963,12 @@ "dev": true }, "focus-trap": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-3.0.0.tgz", - "integrity": "sha512-jTFblf0tLWbleGjj2JZsAKbgtZTdL1uC48L8FcmSDl4c2vDoU4NycN1kgV5vJhuq1mxNFkw7uWZ1JAGlINWvyw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-4.0.2.tgz", + "integrity": "sha512-HtLjfAK7Hp2qbBtLS6wEznID1mPT+48ZnP2nkHzgjpL4kroYHg0CdqJ5cTXk+UO5znAxF5fRUkhdyfgrhh8Lzw==", "dev": true, "requires": { - "tabbable": "^3.1.0", + "tabbable": "^3.1.2", "xtend": "^4.0.1" } }, @@ -8852,6 +10387,15 @@ "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", "dev": true }, + "html-element-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.0.1.tgz", + "integrity": "sha512-BZSfdEm6n706/lBfXKWa4frZRZcT5k1cOusw95ijZsHlI+GdgY0v95h6IzO3iIDf2ROwq570YTwqNPqHcNMozw==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, "html-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", @@ -8859,17 +10403,39 @@ "dev": true }, "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", "dev": true, "requires": { - "domelementtype": "^1.3.0", + "domelementtype": "^1.3.1", "domhandler": "^2.3.0", "domutils": "^1.5.1", "entities": "^1.1.1", "inherits": "^2.0.1", - "readable-stream": "^2.0.2" + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", + "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "http-deceiver": { @@ -11096,12 +12662,24 @@ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, + "lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", + "dev": true + }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", @@ -11894,6 +13472,12 @@ "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=", "dev": true }, + "moo": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz", + "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -11976,15 +13560,24 @@ "dev": true }, "nearley": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.13.0.tgz", - "integrity": "sha512-ioYYogSaZhFlCpRizQgY3UT3G1qFXmHGY/5ozoFE3dMfiCRAeJfh+IPE3/eh9gCZvqLhPCWb4bLt7Bqzo+1mLQ==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.16.0.tgz", + "integrity": "sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg==", "dev": true, "requires": { - "nomnom": "~1.6.2", + "commander": "^2.19.0", + "moo": "^0.4.3", "railroad-diagrams": "^1.0.0", "randexp": "0.4.6", "semver": "^5.4.1" + }, + "dependencies": { + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + } } }, "needle": { @@ -12477,30 +14070,6 @@ "dev": true, "optional": true }, - "nomnom": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", - "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", - "dev": true, - "requires": { - "colors": "0.5.x", - "underscore": "~1.4.4" - }, - "dependencies": { - "colors": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", - "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", - "dev": true - }, - "underscore": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", - "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", - "dev": true - } - } - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -12584,9 +14153,9 @@ } }, "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dev": true, "requires": { "boolbase": "~1.0.0" @@ -12688,9 +14257,9 @@ } }, "object-inspect": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.5.0.tgz", - "integrity": "sha512-UmOFbHbwvv+XHj7BerrhVq+knjceBdkvU5AriwLMvhv2qi+e7DJzxfBeFpILEjVzCp+xA+W/pIf06RGPWlZNfw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", "dev": true }, "object-is": { @@ -12735,15 +14304,152 @@ } }, "object.entries": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", - "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "object.fromentries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", + "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==", "dev": true, "requires": { "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", + "es-abstract": "^1.11.0", + "function-bind": "^1.1.1", "has": "^1.0.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + }, + "dependencies": { + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + } + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } } }, "object.omit": { @@ -12774,15 +14480,81 @@ } }, "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } } }, "obuf": { @@ -14116,6 +15888,28 @@ "object-assign": "^4.1.1" } }, + "prop-types-exact": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", + "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", + "dev": true, + "requires": { + "has": "^1.0.3", + "object.assign": "^4.1.0", + "reflect.ownkeys": "^0.2.0" + }, + "dependencies": { + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + } + } + }, "proxy-addr": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", @@ -14330,9 +16124,9 @@ "dev": true }, "raf": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.0.tgz", - "integrity": "sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "dev": true, "requires": { "performance-now": "^2.1.0" @@ -14460,17 +16254,11 @@ "prop-types": "^15.6.0" } }, - "react-reconciler": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.7.0.tgz", - "integrity": "sha512-50JwZ3yNyMS8fchN+jjWEJOH3Oze7UmhxeoJLn2j6f3NjpfCRbcmih83XTWmzqtar/ivd5f7tvQhvvhism2fgg==", - "dev": true, - "requires": { - "fbjs": "^0.8.16", - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.0" - } + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true }, "react-router": { "version": "4.3.1", @@ -14519,14 +16307,37 @@ } }, "react-test-renderer": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.2.0.tgz", - "integrity": "sha512-Kd4gJFtpNziR9ElOE/C23LeflKLZPRpNQYWP3nQBY43SJ5a+xyEGSeMrm2zxNKXcnCbBS/q1UpD9gqd5Dv+rew==", + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.8.6.tgz", + "integrity": "sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==", "dev": true, "requires": { - "fbjs": "^0.8.16", "object-assign": "^4.1.1", - "prop-types": "^15.6.0" + "prop-types": "^15.6.2", + "react-is": "^16.8.6", + "scheduler": "^0.13.6" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } } }, "read-cmd-shim": { @@ -14690,6 +16501,12 @@ } } }, + "reflect.ownkeys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", + "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=", + "dev": true + }, "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", @@ -15223,6 +17040,16 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, "schema-utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", @@ -16141,6 +17968,17 @@ "strip-ansi": "^3.0.0" } }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", @@ -16248,9 +18086,9 @@ } }, "tabbable": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-3.1.1.tgz", - "integrity": "sha512-583MHIOwictf7+zbxqO/L5fBqMN6Li4SJ1XTKQA9WzHRA7c2BB+D+Ny7Y6kGqU2u+rHK59+oRzrBvMU53aZz+A==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-3.1.2.tgz", + "integrity": "sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ==", "dev": true }, "table": { diff --git a/package.json b/package.json index c6846a8f4..81bad640d 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "pretest": "npm stop", "test": "npm run lint && npm run test:unit && npm run test:screenshots", "posttest": "npm stop && istanbul report --root coverage text-summary && istanbul check-coverage --lines 95 --statements 95 --branches 95 --functions 95", - "postinstall": "lerna bootstrap", + "postinstall": "lerna bootstrap && rm node_modules/**/.babelrc -f && rm packages/**/node_modules/.babelrc -f", "test:watch": "karma start karma.local.js --auto-watch", "test:unit": "npm run clean && cross-env NODE_ENV=test karma start karma.local.js --single-run", "test:unit-ci": "karma start karma.ci.js --single-run", @@ -41,9 +41,11 @@ "linear-progress", "list", "menu-surface", + "notched-outline", "radio", "ripple", "select", + "snackbar", "top-app-bar", "switch", "tab", @@ -60,34 +62,27 @@ }, "devDependencies": { "@google-cloud/storage": "^1.6.0", - "@material/button": "^0.43.0", - "@material/card": "^0.41.0", - "@material/checkbox": "^0.41.0", - "@material/chips": "^0.41.0", - "@material/dialog": "^0.43.0", - "@material/dom": "^0.41.0", - "@material/drawer": "^0.41.0", - "@material/fab": "^0.41.0", - "@material/floating-label": "^0.41.0", - "@material/icon-button": "^0.41.0", - "@material/layout-grid": "^0.41.0", - "@material/line-ripple": "^0.41.0", - "@material/linear-progress": "^0.41.0", - "@material/list": "^0.41.0", - "@material/menu-surface": "^0.41.0", - "@material/notched-outline": "^0.41.0", - "@material/radio": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/select": "^0.40.1", - "@material/snackbar": "^0.43.0", - "@material/switch": "^0.41.0", - "@material/tab": "^0.41.0", - "@material/tab-bar": "^0.41.0", - "@material/tab-indicator": "^0.41.0", - "@material/tab-scroller": "^0.41.0", + "@material/base": "^1.0.0", + "@material/button": "^1.1.0", + "@material/card": "^1.1.0", + "@material/checkbox": "^1.0.0", + "@material/chips": "^1.1.1", + "@material/dialog": "^1.1.0", + "@material/drawer": "^1.0.1", + "@material/floating-label": "^1.1.0", + "@material/icon-button": "^1.1.0", + "@material/line-ripple": "^1.0.0", + "@material/list": "1.0.0", + "@material/menu-surface": "^1.0.1", + "@material/notched-outline": "^1.1.1", + "@material/radio": "^1.1.0", + "@material/ripple": "^1.0.0", + "@material/select": "^1.1.1", + "@material/snackbar": "^1.0.0", + "@material/tab": "^1.0.0", + "@material/tab-bar": "^1.0.0", "@material/textfield": "^0.41.0", - "@material/top-app-bar": "^0.41.0", - "@material/typography": "^0.41.0", + "@material/typography": "^1.0.0", "@types/chai": "^4.1.7", "@types/classnames": "^2.2.6", "@types/enzyme": "^3.1.15", @@ -119,8 +114,9 @@ "cp-file": "^6.0.0", "cross-env": "^5.2.0", "css-loader": "^0.28.10", - "enzyme": "^3.3.0", - "enzyme-adapter-react-16": "^1.1.1", + "enzyme": "^3.9.0", + "enzyme-adapter-react-16": "^1.11.2", + "enzyme-adapter-utils": "^1.10.1", "eslint": "^5.9.0", "eslint-config-google": "^0.9.1", "eslint-plugin-react": "^7.7.0", @@ -146,13 +142,13 @@ "react-dom": "^16.4.2", "react-router-dom": "^4.3.1", "remap-istanbul": "^0.12.0", - "rimraf": "^2.6.3", "resemblejs": "^3.0.1", + "rimraf": "^2.6.3", "sass-loader": "^6.0.7", "testdouble": "^3.6.0", "ts-loader": "^3.5.0", "ts-node": "^7.0.1", - "typescript": "^3.2.2", + "typescript": "^3.3.3", "typescript-eslint-parser": "^21.0.1", "utility-types": "^2.1.0", "uuid": "^3.3.2", diff --git a/packages/button/index.tsx b/packages/button/index.tsx index bade96ce9..48d650e82 100644 --- a/packages/button/index.tsx +++ b/packages/button/index.tsx @@ -20,16 +20,16 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; -import * as Ripple from '@material/react-ripple'; +import {withRipple, InjectedProps} from '@material/react-ripple'; const BUTTON_CLASS_NAME = 'mdc-button__icon'; type ButtonTypes = HTMLAnchorElement | HTMLButtonElement; export interface ButtonProps - extends Ripple.InjectedProps, React.AnchorHTMLAttributes, React.ButtonHTMLAttributes { + extends InjectedProps, React.AnchorHTMLAttributes, React.ButtonHTMLAttributes { raised?: boolean; unelevated?: boolean; outlined?: boolean; @@ -109,5 +109,5 @@ Button.defaultProps = { initRipple: () => {}, }; -export default Ripple.withRipple, ButtonTypes>(Button); +export default withRipple, ButtonTypes>(Button); diff --git a/packages/button/package.json b/packages/button/package.json index 83439e77c..985981a74 100644 --- a/packages/button/package.json +++ b/packages/button/package.json @@ -17,7 +17,7 @@ "url": "https://github.com/material-components/material-components-web-react.git" }, "dependencies": { - "@material/button": "^0.43.0", + "@material/button": "^1.1.0", "@material/react-ripple": "^0.11.0", "classnames": "^2.2.6", "react": "^16.4.2" diff --git a/packages/card/ActionButtons.tsx b/packages/card/ActionButtons.tsx index f658639c3..b459c5bb8 100644 --- a/packages/card/ActionButtons.tsx +++ b/packages/card/ActionButtons.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; type ChildType = React.ReactElement>; diff --git a/packages/card/ActionIcons.tsx b/packages/card/ActionIcons.tsx index fe6dddc57..eb32a6eff 100644 --- a/packages/card/ActionIcons.tsx +++ b/packages/card/ActionIcons.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; type ChildType = React.ReactElement>; diff --git a/packages/card/Actions.tsx b/packages/card/Actions.tsx index e0678524a..211206ac9 100644 --- a/packages/card/Actions.tsx +++ b/packages/card/Actions.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; export interface ActionsProps extends React.HTMLProps { diff --git a/packages/card/Media.tsx b/packages/card/Media.tsx index 23280e687..b3b7fb302 100644 --- a/packages/card/Media.tsx +++ b/packages/card/Media.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; export interface MediaProps extends React.HTMLProps { diff --git a/packages/card/PrimaryContent.tsx b/packages/card/PrimaryContent.tsx index e7b46c0ee..3d2c137cd 100644 --- a/packages/card/PrimaryContent.tsx +++ b/packages/card/PrimaryContent.tsx @@ -20,11 +20,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; -import * as Ripple from '@material/react-ripple'; +import {withRipple, InjectedProps} from '@material/react-ripple'; -export interface PrimaryContentBaseProps extends React.HTMLProps, Ripple.InjectedProps{ +export interface PrimaryContentBaseProps extends React.HTMLProps, InjectedProps{ className: string; unbounded?: boolean; }; @@ -47,4 +47,4 @@ export const PrimaryContentBase: React.FunctionComponent(PrimaryContentBase); +export default withRipple(PrimaryContentBase); diff --git a/packages/card/index.tsx b/packages/card/index.tsx index 6bb9d4235..df7e5e67c 100644 --- a/packages/card/index.tsx +++ b/packages/card/index.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; import ActionButtons from './ActionButtons'; import ActionIcons from './ActionIcons'; diff --git a/packages/card/package.json b/packages/card/package.json index c6e23dd11..07a77f7d6 100644 --- a/packages/card/package.json +++ b/packages/card/package.json @@ -17,7 +17,7 @@ "url": "https://github.com/material-components/material-components-web-react.git" }, "dependencies": { - "@material/card": "^0.41.0", + "@material/card": "^1.1.0", "@material/react-ripple": "^0.11.0", "classnames": "^2.2.6", "react": "^16.4.2" diff --git a/packages/checkbox/NativeControl.tsx b/packages/checkbox/NativeControl.tsx index eb14b7ef5..9a22351a6 100644 --- a/packages/checkbox/NativeControl.tsx +++ b/packages/checkbox/NativeControl.tsx @@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; export interface NativeControlProps extends React.HTMLProps{ checked: boolean; diff --git a/packages/checkbox/index.tsx b/packages/checkbox/index.tsx index cb17f3acf..c6da27f8b 100644 --- a/packages/checkbox/index.tsx +++ b/packages/checkbox/index.tsx @@ -20,15 +20,16 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; -// @ts-ignore no mdc .d.ts file -import {MDCCheckboxFoundation, MDCCheckboxAdapter} from '@material/checkbox/dist/mdc.checkbox'; -import * as Ripple from '@material/react-ripple'; +import {MDCCheckboxFoundation} from '@material/checkbox/foundation'; +import {MDCCheckboxAdapter} from '@material/checkbox/adapter'; +import {cssClasses} from '@material/checkbox/constants'; +import {withRipple, InjectedProps} from '@material/react-ripple'; import NativeControl from './NativeControl'; -export interface CheckboxProps extends Ripple.InjectedProps { +export interface CheckboxProps extends InjectedProps { checked?: boolean; className?: string; disabled?: boolean; @@ -45,12 +46,13 @@ interface CheckboxState { checked?: boolean; indeterminate?: boolean; classList: Set; - 'aria-checked': boolean; + 'aria-checked': string; + disabled: boolean; }; export class Checkbox extends React.Component { inputElement: React.RefObject = React.createRef(); - foundation = MDCCheckboxFoundation; + foundation!: MDCCheckboxFoundation; constructor(props: CheckboxProps) { super(props); @@ -58,7 +60,8 @@ export class Checkbox extends React.Component { 'checked': props.checked, 'indeterminate': props.indeterminate, 'classList': new Set(), - 'aria-checked': false, + 'aria-checked': 'false', + 'disabled': props.disabled!, }; } @@ -74,7 +77,7 @@ export class Checkbox extends React.Component { componentDidMount() { this.foundation = new MDCCheckboxFoundation(this.adapter); this.foundation.init(); - this.foundation.setDisabled(this.props.disabled); + this.foundation.setDisabled(this.props.disabled!); // indeterminate property on checkboxes is not supported: // https://github.com/facebook/react/issues/1798#issuecomment-333414857 if (this.inputElement.current) { @@ -91,7 +94,7 @@ export class Checkbox extends React.Component { this.handleChange(checked!, indeterminate!); } if (disabled !== prevProps.disabled) { - this.foundation.setDisabled(disabled); + this.foundation.setDisabled(disabled!); } } @@ -118,7 +121,9 @@ export class Checkbox extends React.Component { get classes(): string { const {classList} = this.state; const {className} = this.props; - return classnames('mdc-checkbox', Array.from(classList), className); + return classnames( + 'mdc-checkbox', Array.from(classList), + this.state.disabled ? cssClasses.DISABLED : null, className); } updateState = (key: keyof CheckboxState, value: string | boolean) => { @@ -146,10 +151,14 @@ export class Checkbox extends React.Component { // isAttachedToDOM will likely be removed // https://github.com/material-components/material-components-web/issues/3691 isAttachedToDOM: () => true, - isChecked: () => this.state.checked, - isIndeterminate: () => this.state.indeterminate, + isChecked: () => this.state.checked!, + isIndeterminate: () => this.state.indeterminate!, setNativeControlAttr: this.updateState, + setNativeControlDisabled: (disabled) => { + this.updateState('disabled', disabled); + }, removeNativeControlAttr: this.removeState, + forceLayout: () => null, }; } @@ -169,8 +178,8 @@ export class Checkbox extends React.Component { initRipple, onChange, unbounded, - /* eslint-enable no-unused-vars */ disabled, + /* eslint-enable no-unused-vars */ nativeControlId, name, ...otherProps @@ -186,8 +195,8 @@ export class Checkbox extends React.Component { { } } -export default Ripple.withRipple(Checkbox); +export default withRipple(Checkbox); diff --git a/packages/checkbox/package.json b/packages/checkbox/package.json index 7fa29357e..4dd5e50f2 100644 --- a/packages/checkbox/package.json +++ b/packages/checkbox/package.json @@ -16,7 +16,7 @@ "url": "https://github.com/material-components/material-components-web-react.git" }, "dependencies": { - "@material/checkbox": "^0.41.0", + "@material/checkbox": "^1.1.0", "@material/react-ripple": "^0.11.0", "classnames": "^2.2.6", "react": "^16.3.2" diff --git a/packages/chips/Chip.tsx b/packages/chips/Chip.tsx index 73ab59485..1d6bf4378 100644 --- a/packages/chips/Chip.tsx +++ b/packages/chips/Chip.tsx @@ -19,13 +19,13 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; -import * as Ripple from '@material/react-ripple'; -// @ts-ignore no mdc .d.ts file -import {MDCChipFoundation} from '@material/chips/dist/mdc.chips'; +import {withRipple, InjectedProps} from '@material/react-ripple'; +import {MDCChipFoundation} from '@material/chips/chip/foundation'; +import {MDCChipAdapter} from '@material/chips/chip/adapter'; -export interface ChipProps extends Ripple.InjectedProps { +export interface ChipProps extends InjectedProps { id?: string; label?: string; className?: string; @@ -51,7 +51,7 @@ type ChipState = { export class Chip extends React.Component { chipElement: HTMLDivElement | null = null; - foundation?: MDCChipFoundation; + foundation!: MDCChipFoundation; static defaultProps: Partial = { id: '', @@ -78,9 +78,9 @@ export class Chip extends React.Component { const {selected, shouldRemoveOnTrailingIconClick} = this.props; this.foundation = new MDCChipFoundation(this.adapter); this.foundation.init(); - this.foundation.setSelected(selected); + this.foundation.setSelected(selected!); if (shouldRemoveOnTrailingIconClick !== this.foundation.getShouldRemoveOnTrailingIconClick()) { - this.foundation.setShouldRemoveOnTrailingIconClick(shouldRemoveOnTrailingIconClick); + this.foundation.setShouldRemoveOnTrailingIconClick(shouldRemoveOnTrailingIconClick!); } } @@ -88,11 +88,11 @@ export class Chip extends React.Component { const {selected, shouldRemoveOnTrailingIconClick} = this.props; if (selected !== prevProps.selected) { - this.foundation.setSelected(selected); + this.foundation.setSelected(selected!); } if (shouldRemoveOnTrailingIconClick !== prevProps.shouldRemoveOnTrailingIconClick) { - this.foundation.setShouldRemoveOnTrailingIconClick(shouldRemoveOnTrailingIconClick); + this.foundation.setShouldRemoveOnTrailingIconClick(shouldRemoveOnTrailingIconClick!); } } @@ -111,7 +111,7 @@ export class Chip extends React.Component { return classnames('mdc-chip', Array.from(classList), className); } - get adapter() { + get adapter(): MDCChipAdapter { return { addClass: (className: string) => { const classList = new Set(this.state.classList); @@ -124,14 +124,24 @@ export class Chip extends React.Component { this.setState({classList}); }, hasClass: (className: string) => this.classes.split(' ').includes(className), + hasLeadingIcon: () => Boolean(this.props.leadingIcon), eventTargetHasClass: (target: HTMLElement, className: string) => target.classList.contains(className), getComputedStyleValue: (propertyName: string) => { - if (!this.chipElement) return; + if (!this.chipElement) return ''; return window .getComputedStyle(this.chipElement) .getPropertyValue(propertyName); }, + getRootBoundingClientRect: () => { + if (!this.chipElement) return new ClientRect(); + return this.chipElement.getBoundingClientRect(); + }, + getCheckmarkBoundingClientRect: () => { + const {chipCheckmark} = this.props; + if (!chipCheckmark) return new ClientRect(); + return chipCheckmark.props.getBoundingClientRect(); + }, setStyleProperty: (propertyName: keyof React.CSSProperties, value: string | null) => { if (!this.chipElement) return; this.chipElement.style.setProperty(propertyName, value); @@ -156,19 +166,19 @@ export class Chip extends React.Component { onClick = (e: React.MouseEvent) => { this.props.onClick!(e); - this.foundation.handleInteraction(e); + this.foundation.handleInteraction(e.nativeEvent); }; onKeyDown = (e: React.KeyboardEvent) => { this.props.onKeyDown!(e); - this.foundation.handleInteraction(e); + this.foundation.handleInteraction(e.nativeEvent); }; - handleTrailingIconClick = (e: React.MouseEvent) => this.foundation.handleTrailingIconInteraction(e); + handleTrailingIconClick = (e: React.MouseEvent) => this.foundation.handleTrailingIconInteraction(e.nativeEvent); handleTransitionEnd = (e: React.TransitionEvent) => { this.props.onTransitionEnd!(e); - this.foundation.handleTransitionEnd(e); + this.foundation.handleTransitionEnd(e.nativeEvent); }; renderLeadingIcon = (leadingIcon: React.ReactElement) => { @@ -246,4 +256,4 @@ export class Chip extends React.Component { } } -export default Ripple.withRipple(Chip); +export default withRipple(Chip); diff --git a/packages/chips/ChipCheckmark.tsx b/packages/chips/ChipCheckmark.tsx index 0a4e4bc17..ecceb6f96 100644 --- a/packages/chips/ChipCheckmark.tsx +++ b/packages/chips/ChipCheckmark.tsx @@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; export default class ChipCheckmark extends React.Component<{}, {}> { width: number = 0; diff --git a/packages/chips/ChipSet.tsx b/packages/chips/ChipSet.tsx index 826093d90..d15fdd883 100644 --- a/packages/chips/ChipSet.tsx +++ b/packages/chips/ChipSet.tsx @@ -19,10 +19,9 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; -// @ts-ignore no mdc .d.ts file -import {MDCChipSetFoundation} from '@material/chips/dist/mdc.chips'; +import {MDCChipSetFoundation} from '@material/chips/chip-set/foundation'; import ChipCheckmark from './ChipCheckmark'; import {ChipProps} from './Chip'; // eslint-disable-line no-unused-vars @@ -40,7 +39,7 @@ export interface ChipSetProps { }; interface ChipSetState { - foundation: MDCChipSetFoundation; + foundation: MDCChipSetFoundation | null; selectedChipIds: string[]; hasInitialized: boolean; }; @@ -83,7 +82,7 @@ export default class ChipSet extends React.Component } componentWillUnmount() { - this.state.foundation.destroy(); + this.state.foundation!.destroy(); } get classes() { @@ -99,7 +98,7 @@ export default class ChipSet extends React.Component return { hasClass: (className: string) => this.classes.split(' ').includes(className), setSelected: () => { - const selectedChipIds = this.state.foundation.getSelectedChipIds().slice(); + const selectedChipIds = this.state.foundation!.getSelectedChipIds().slice(); this.setState({selectedChipIds}, () => { this.props.handleSelect!(selectedChipIds); }); @@ -113,22 +112,22 @@ export default class ChipSet extends React.Component const {id} = (child as ChipType).props; const selected = this.state.selectedChipIds.indexOf(id!) > -1; if (selected) { - this.state.foundation.select(id); + this.state.foundation!.select(id!); } }); this.setState({hasInitialized: true}); } handleInteraction = (chipId: string) => { - this.state.foundation.handleChipInteraction(chipId); + this.state.foundation!.handleChipInteraction(chipId); }; handleSelect = (chipId: string, selected: boolean) => { - this.state.foundation.handleChipSelection(chipId, selected); + this.state.foundation!.handleChipSelection(chipId, selected); }; handleRemove = (chipId: string) => { - this.state.foundation.handleChipRemoval(chipId); + this.state.foundation!.handleChipRemoval(chipId); }; removeChip = (chipId: string) => { diff --git a/packages/chips/package.json b/packages/chips/package.json index f47cfe540..8e292482f 100644 --- a/packages/chips/package.json +++ b/packages/chips/package.json @@ -19,7 +19,7 @@ "url": "https://github.com/material-components/material-components-web-react.git" }, "dependencies": { - "@material/chips": "^0.41.0", + "@material/chips": "^1.1.1", "@material/react-ripple": "^0.11.0", "classnames": "^2.2.6", "react": "^16.4.2" diff --git a/packages/dialog/DialogButton.tsx b/packages/dialog/DialogButton.tsx index 85c1346ec..65e930aeb 100644 --- a/packages/dialog/DialogButton.tsx +++ b/packages/dialog/DialogButton.tsx @@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; import {cssClasses} from './constants'; import Button, {ButtonProps} from '@material/react-button'; diff --git a/packages/dialog/DialogContent.tsx b/packages/dialog/DialogContent.tsx index f417bb79e..b229c9d32 100644 --- a/packages/dialog/DialogContent.tsx +++ b/packages/dialog/DialogContent.tsx @@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; import {cssClasses} from './constants'; diff --git a/packages/dialog/DialogFooter.tsx b/packages/dialog/DialogFooter.tsx index 6ce9af8fc..9561e7244 100644 --- a/packages/dialog/DialogFooter.tsx +++ b/packages/dialog/DialogFooter.tsx @@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; import {cssClasses} from './constants'; diff --git a/packages/dialog/DialogTitle.tsx b/packages/dialog/DialogTitle.tsx index d78d2cd77..507fffae5 100644 --- a/packages/dialog/DialogTitle.tsx +++ b/packages/dialog/DialogTitle.tsx @@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; import {cssClasses} from './constants'; diff --git a/packages/dialog/index.tsx b/packages/dialog/index.tsx index e219eb894..5be86db2e 100644 --- a/packages/dialog/index.tsx +++ b/packages/dialog/index.tsx @@ -20,13 +20,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; -// @ts-ignore no .d.ts file -import {MDCDialogFoundation, MDCDialogAdapter, util} from '@material/dialog/dist/mdc.dialog'; -// @ts-ignore no .d.ts file -import {ponyfill} from '@material/dom/dist/mdc.dom'; +import {MDCDialogFoundation} from '@material/dialog/foundation'; +import {MDCDialogAdapter} from '@material/dialog/adapter'; +import {createFocusTrapInstance, isScrollable, areTopsMisaligned} from '@material/dialog/util'; +import {strings} from '@material/dialog/constants'; +import {ponyfill} from '@material/dom'; /* eslint-disable no-unused-vars */ import DialogContent, {DialogContentProps} from './DialogContent'; import DialogFooter, {DialogFooterProps} from './DialogFooter'; @@ -89,7 +90,7 @@ class Dialog extends React.Component< DialogState > { focusTrap?: FocusTrap; - foundation: MDCDialogFoundation; + foundation!: MDCDialogFoundation; dialogElement: React.RefObject = React.createRef(); labelledBy?: string; describedBy?: string; @@ -103,6 +104,8 @@ class Dialog extends React.Component< id: 'mdc-dialog', open: false, role: 'alertdialog', + escapeKeyAction: strings.CLOSE_ACTION, + scrimClickAction: strings.CLOSE_ACTION, }; state: DialogState = {classList: new Set()}; @@ -116,7 +119,7 @@ class Dialog extends React.Component< this.open(); } if (!autoStackButtons) { - this.foundation.setAutoStackButtons(autoStackButtons); + this.foundation.setAutoStackButtons(autoStackButtons!); } if (typeof escapeKeyAction === 'string') { // set even if empty string @@ -136,15 +139,15 @@ class Dialog extends React.Component< const {open, autoStackButtons, escapeKeyAction, scrimClickAction} = this.props; if (prevProps.autoStackButtons !== autoStackButtons) { - this.foundation.setAutoStackButtons(autoStackButtons); + this.foundation.setAutoStackButtons(autoStackButtons!); } if (prevProps.escapeKeyAction !== escapeKeyAction) { - this.foundation.setEscapeKeyAction(escapeKeyAction); + this.foundation.setEscapeKeyAction(escapeKeyAction!); } if (prevProps.scrimClickAction !== scrimClickAction) { - this.foundation.setScrimClickAction(scrimClickAction); + this.foundation.setScrimClickAction(scrimClickAction!); } if (prevProps.open !== open) { @@ -181,13 +184,12 @@ class Dialog extends React.Component< }; private initializeFocusTrap = (): void => { - this.focusTrap = this.props.children && util.createFocusTrapInstance(this.dialogElement.current); + this.focusTrap = this.props.children && createFocusTrapInstance(this.dialogElement.current!); }; - get adapter(): Partial { + get adapter(): MDCDialogAdapter { const strings = MDCDialogFoundation.strings; const {closest, matches} = ponyfill; - const {isScrollable, areTopsMisaligned} = util; return { addClass: (className: string) => { const {classList} = this.state; @@ -258,8 +260,8 @@ class Dialog extends React.Component< }; handleInteraction = (e: React.MouseEvent | React.KeyboardEvent): void => - this.foundation.handleInteraction(e); - handleDocumentKeyDown = (e: Event): void => + this.foundation.handleInteraction(e.nativeEvent); + handleDocumentKeyDown = (e: KeyboardEvent): void => this.foundation.handleDocumentKeydown(e); handleLayout = (): void => this.foundation.layout(); diff --git a/packages/dialog/package.json b/packages/dialog/package.json index ca64ea370..0dd016295 100644 --- a/packages/dialog/package.json +++ b/packages/dialog/package.json @@ -15,8 +15,8 @@ "url": "https://github.com/material-components/material-components-web-react.git" }, "dependencies": { - "@material/dialog": "0.43.0", - "@material/dom": "^0.41.0", + "@material/dialog": "1.1.0", + "@material/dom": "^1.0.0", "@material/react-button": "^0.11.0", "classnames": "^2.2.6", "focus-trap": "^4.0.2", diff --git a/packages/drawer/AppContent.tsx b/packages/drawer/AppContent.tsx index f3a83294f..a404a712e 100644 --- a/packages/drawer/AppContent.tsx +++ b/packages/drawer/AppContent.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; export interface DrawerAppContentProps { diff --git a/packages/drawer/Content.tsx b/packages/drawer/Content.tsx index 3a044de3d..4f0550c82 100644 --- a/packages/drawer/Content.tsx +++ b/packages/drawer/Content.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; export interface DrawerContentProps { diff --git a/packages/drawer/Header.tsx b/packages/drawer/Header.tsx index 4d4f6fe5f..371579433 100644 --- a/packages/drawer/Header.tsx +++ b/packages/drawer/Header.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; export interface DrawerHeaderProps { diff --git a/packages/drawer/Subtitle.tsx b/packages/drawer/Subtitle.tsx index 6cc9eca1a..4847bb3e2 100644 --- a/packages/drawer/Subtitle.tsx +++ b/packages/drawer/Subtitle.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; export interface DrawerSubTitleProps { diff --git a/packages/drawer/Title.tsx b/packages/drawer/Title.tsx index 256c12d2b..01235962c 100644 --- a/packages/drawer/Title.tsx +++ b/packages/drawer/Title.tsx @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; export interface DrawerTitleProps { diff --git a/packages/drawer/index.tsx b/packages/drawer/index.tsx index 3741ca423..876349153 100644 --- a/packages/drawer/index.tsx +++ b/packages/drawer/index.tsx @@ -20,16 +20,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; import { MDCDismissibleDrawerFoundation, MDCModalDrawerFoundation, util, -// @ts-ignore no .d.ts file -} from '@material/drawer/dist/mdc.drawer'; -// @ts-ignore no .d.ts file -import {MDCListFoundation} from '@material/list/dist/mdc.list'; +} from '@material/drawer'; +import {MDCListFoundation} from '@material/list/foundation'; import DrawerHeader from './Header'; import DrawerContent from './Content'; import DrawerSubtitle from './Subtitle'; @@ -62,7 +60,7 @@ const isRefObject = function(ref: DrawerProps['innerRef']): ref is React.RefObje class Drawer extends React.Component { previousFocus: HTMLElement | null = null; - foundation: MDCDismissibleDrawerFoundation | MDCModalDrawerFoundation; + foundation?: MDCDismissibleDrawerFoundation | MDCModalDrawerFoundation; focusTrap?: FocusTrap; drawerElement: React.RefObject = React.createRef(); @@ -113,7 +111,7 @@ class Drawer extends React.Component { if (changedToModal || changedToDismissible) { this.initFoundation(); } - if (open !== prevProps.open) { + if (open !== prevProps.open && this.foundation) { open ? this.foundation.open() : this.foundation.close(); } } @@ -124,7 +122,7 @@ class Drawer extends React.Component { } private initializeFocusTrap = () => { - this.focusTrap = util.createFocusTrapInstance(this.drawerElement.current); + this.focusTrap = util.createFocusTrapInstance(this.drawerElement.current!); }; get classes() { @@ -191,13 +189,13 @@ class Drawer extends React.Component { handleKeyDown = (evt: React.KeyboardEvent) => { this.props.onKeyDown!(evt); if (!this.foundation) return; - this.foundation.handleKeydown(evt); + this.foundation.handleKeydown(evt.nativeEvent); }; handleTransitionEnd = (evt: React.TransitionEvent) => { this.props.onTransitionEnd!(evt); if (!this.foundation) return; - this.foundation.handleTransitionEnd(evt); + this.foundation.handleTransitionEnd(evt.nativeEvent); }; attachRef = (node: HTMLElement) => { @@ -230,9 +228,9 @@ class Drawer extends React.Component { children, className, innerRef, + modal, /* eslint-enable no-unused-vars */ tag: Tag, - modal, ...otherProps } = this.props; @@ -253,11 +251,12 @@ class Drawer extends React.Component { ); } + renderScrim() { return (
this.foundation.handleScrimClick()} + onClick={() => (this.foundation as MDCModalDrawerFoundation).handleScrimClick()} /> ); } diff --git a/packages/drawer/package.json b/packages/drawer/package.json index ff0f760ff..5cb98a714 100644 --- a/packages/drawer/package.json +++ b/packages/drawer/package.json @@ -17,8 +17,8 @@ "url": "https://github.com/material-components/material-components-web-react.git" }, "dependencies": { - "@material/drawer": "^0.41.0", - "@material/list": "^0.41.0", + "@material/drawer": "^1.0.1", + "@material/list": "^1.0.0", "classnames": "^2.2.6", "focus-trap": "^4.0.2", "react": "^16.4.2" diff --git a/packages/fab/index.tsx b/packages/fab/index.tsx index 42ecd5551..03fc57a16 100644 --- a/packages/fab/index.tsx +++ b/packages/fab/index.tsx @@ -20,11 +20,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; -import * as Ripple from '@material/react-ripple'; +import {withRipple, InjectedProps} from '@material/react-ripple'; -export interface FabProps extends Ripple.InjectedProps, +export interface FabProps extends InjectedProps, React.ButtonHTMLAttributes { exited?: boolean; mini?: boolean; @@ -81,4 +81,4 @@ export const Fab: React.FunctionComponent(Fab); +export default withRipple(Fab); diff --git a/packages/fab/package.json b/packages/fab/package.json index be455b297..c7bdfc5b8 100644 --- a/packages/fab/package.json +++ b/packages/fab/package.json @@ -17,7 +17,7 @@ "url": "https://github.com/material-components/material-components-web-react.git" }, "dependencies": { - "@material/fab": "^0.41.0", + "@material/fab": "^1.1.0", "@material/react-ripple": "^0.11.0", "classnames": "^2.2.6", "react": "^16.4.2" diff --git a/packages/floating-label/index.tsx b/packages/floating-label/index.tsx index 645abacc0..0b2e5103c 100644 --- a/packages/floating-label/index.tsx +++ b/packages/floating-label/index.tsx @@ -20,10 +20,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import * as React from 'react'; +import React from 'react'; import classnames from 'classnames'; -// @ts-ignore no mdc .d.ts -import {MDCFloatingLabelFoundation} from '@material/floating-label/dist/mdc.floatingLabel'; +import {MDCFloatingLabelFoundation} from '@material/floating-label/foundation'; +import {MDCFloatingLabelAdapter} from '@material/floating-label/adapter'; export interface FloatingLabelProps extends React.LabelHTMLAttributes { className?: string; @@ -39,8 +39,8 @@ export default class FloatingLabel extends React.Component< FloatingLabelProps, FloatingLabelState > { - foundation_?: MDCFloatingLabelFoundation; - labelElement_: React.RefObject = React.createRef(); + foundation!: MDCFloatingLabelFoundation; + labelElement: React.RefObject = React.createRef(); static defaultProps: Partial = { className: '', @@ -55,12 +55,12 @@ export default class FloatingLabel extends React.Component< this.initializeFoundation(); this.handleWidthChange(); if (this.props.float) { - this.foundation_.float(true); + this.foundation.float(true); } } componentWillUnmount() { - this.foundation_.destroy(); + this.foundation.destroy(); } componentDidUpdate(prevProps: FloatingLabelProps) { @@ -68,13 +68,13 @@ export default class FloatingLabel extends React.Component< this.handleWidthChange(); } if (this.props.float !== prevProps.float) { - this.foundation_.float(this.props.float); + this.foundation.float(this.props.float!); } } initializeFoundation = () => { - this.foundation_ = new MDCFloatingLabelFoundation(this.adapter); - this.foundation_.init(); + this.foundation = new MDCFloatingLabelFoundation(this.adapter); + this.foundation.init(); }; get classes() { @@ -83,17 +83,26 @@ export default class FloatingLabel extends React.Component< return classnames('mdc-floating-label', Array.from(classList), className); } - get adapter() { + get adapter(): MDCFloatingLabelAdapter { return { addClass: (className: string) => this.setState({classList: this.state.classList.add(className)}), removeClass: this.removeClassFromClassList, + // the adapter methods below are effectively useless since React + // handles events and width differently + registerInteractionHandler: () => undefined, + deregisterInteractionHandler: () => undefined, + // Always returns 0 beacuse MDC Web component does + // only proxies to foundation.getWidth. + // MDC React instead passes it from the text-field + // component to floating-label component. + getWidth: () => 0, }; } // must be called via ref shake = () => { - this.foundation_.shake(true); + this.foundation.shake(true); }; removeClassFromClassList = (className: string) => { @@ -103,9 +112,8 @@ export default class FloatingLabel extends React.Component< }; handleWidthChange = () => { - const {handleWidthChange} = this.props; - if (handleWidthChange && this.labelElement_.current) { - handleWidthChange(this.labelElement_.current.offsetWidth); + if (this.props.handleWidthChange && this.labelElement.current) { + this.props.handleWidthChange(this.labelElement.current.offsetWidth); } }; @@ -126,7 +134,7 @@ export default class FloatingLabel extends React.Component< return (
); diff --git a/test/screenshot/radio/index.tsx b/test/screenshot/radio/index.tsx index d096e007d..b28e81acd 100644 --- a/test/screenshot/radio/index.tsx +++ b/test/screenshot/radio/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import './index.scss'; import '../../../packages/list/index.scss'; import Radio, {NativeRadioControl} from '../../../packages/radio/index'; diff --git a/test/screenshot/ripple/index.tsx b/test/screenshot/ripple/index.tsx index 0354b0ca3..c3a98ac15 100644 --- a/test/screenshot/ripple/index.tsx +++ b/test/screenshot/ripple/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {withRipple, InjectedProps} from '../../../packages/ripple'; import './index.scss'; diff --git a/test/screenshot/screenshot-test-urls.tsx b/test/screenshot/screenshot-test-urls.tsx index 672044b87..532b2e5d1 100644 --- a/test/screenshot/screenshot-test-urls.tsx +++ b/test/screenshot/screenshot-test-urls.tsx @@ -1,6 +1,7 @@ import topAppBarVariants from './top-app-bar/variants'; import dialogVariants from './dialog/variants'; import drawerVariants from './drawer/variants'; +import selectVariants from './select/variants'; import textFieldVariants from './text-field/variants'; const urls = [ 'button', @@ -15,10 +16,10 @@ const urls = [ 'icon-button', 'layout-grid', 'material-icon', + 'menu', 'menu-surface', 'notched-outline', 'radio', - 'select', 'snackbar', 'tab', 'tab-bar', @@ -41,6 +42,10 @@ drawerVariants.forEach((variant: string) => { urls.push(`drawer/${variant}`); }); +selectVariants.forEach((variant: string) => { + urls.push(`select/${variant}`); +}); + textFieldVariants.forEach((variant: string) => { urls.push(`text-field/${variant}`); }); diff --git a/test/screenshot/screenshot.tsx b/test/screenshot/screenshot.tsx index 9c6d98eb0..bc455df22 100644 --- a/test/screenshot/screenshot.tsx +++ b/test/screenshot/screenshot.tsx @@ -2,16 +2,16 @@ import {Readable} from 'stream'; import {createHash} from 'crypto'; import {readFile, writeFile} from 'fs'; import {promisify} from 'util'; -import * as puppeteer from 'puppeteer'; -// @ts-ignore -import * as compareImages from 'resemblejs/compareImages'; +import puppeteer from 'puppeteer'; +// @ts-ignore no typings +import compareImages from 'resemblejs/compareImages'; import {test} from 'mocha'; import {assert} from 'chai'; -import * as Storage from '@google-cloud/storage'; +import Storage from '@google-cloud/storage'; import comparisonOptions from './screenshot-comparison-options'; import axios from 'axios'; -import * as path from 'path'; -import * as mkdirp from 'mkdirp'; +import path from 'path'; +import mkdirp from 'mkdirp'; const readFilePromise = promisify(readFile); const writeFilePromise = promisify(writeFile); diff --git a/test/screenshot/select/enhanced.tsx b/test/screenshot/select/enhanced.tsx new file mode 100644 index 000000000..3d9984bdb --- /dev/null +++ b/test/screenshot/select/enhanced.tsx @@ -0,0 +1,8 @@ +import * as React from 'react'; +import {getSelects} from './index'; + +const EnhancedSelectScreenshotTest = () => { + return
{getSelects(true)}
; +}; + +export default EnhancedSelectScreenshotTest; diff --git a/test/screenshot/select/index.tsx b/test/screenshot/select/index.tsx index 25101e985..322ffa8e6 100644 --- a/test/screenshot/select/index.tsx +++ b/test/screenshot/select/index.tsx @@ -1,89 +1,123 @@ -import * as React from 'react'; -import Select, {SelectProps} from '../../../packages/select/index'; +import React from 'react'; +import {Link} from 'react-router-dom'; +import selectVariants from './variants'; +import Select, {SelectIcon, SelectProps, Option, SelectHelperText} from '../../../packages/select/index'; import '../../../packages/select/index.scss'; import './index.scss'; +const SelectScreenshotTest = () => { + return ( +
+ {selectVariants.map((variant, index) => ( +
+ {variant} +
+ ))} +
+ ); +}; + +interface SelectTestProps extends SelectProps { + enhanced: boolean; +} + interface SelectTestState { - value: any + value: string; } -class SelectTest extends React.Component { - constructor(props: SelectProps) { +class SelectTest extends React.Component { + constructor(props: SelectTestProps) { super(props); this.state = {value: props.value || ''}; // eslint-disable-line react/prop-types } static defaultProps: Partial = { - box: false, className: '', disabled: false, floatingLabelClassName: '', - isRtl: false, lineRippleClassName: '', - nativeControlClassName: '', + selectClassName: '', notchedOutlineClassName: '', outlined: false, options: [], onChange: () => {}, + enhanced: false, } onChange = (evt: React.ChangeEvent) => ( this.setState({value: evt.target.value}) ); + onEnhancedChange = (_index: number, item: Element) => ( + this.setState({value: item.getAttribute('data-value') as string}) + ); + render() { const { disabled, id, - isRtl, + enhanced, ref, // eslint-disable-line no-unused-vars ...otherProps // eslint-disable-line react/prop-types } = this.props; return ( -
+
); } } -const variants = [{}, {box: true}, {outlined: true}]; -const rtlMap = [{}, {isRtl: true}]; +const variants = [{}, {outlined: true}]; +const leadingIconMap = [{}, { + leadingIcon: favorite, + key: 'favorite', +}]; const disabledMap = [{}, {disabled: true}]; +const requiredMap = [{}, {required: true}]; const valueMap = [{}, {value: 'pomsky'}]; +const helperTextMap = [ + {key: 'nohelpertext'}, + {helperText: Help me, key: 'persistent'}, +]; -const selects = variants.map((variant) => { - return rtlMap.map((isRtl) => { - return disabledMap.map((disabled) => { - return valueMap.map((value) => { - const props = Object.assign({}, variant, disabled, isRtl, value); - const valueKey = Object.keys(value)[0] || ''; - const variantKey = Object.keys(variant)[0] || ''; - const rtlKey = Object.keys(isRtl)[0] || ''; - const disabledKey = Object.keys(disabled)[0] || ''; - const key = `${variantKey}-${disabledKey}-${valueKey}--${rtlKey}`; - return ; +export const getSelects = (enhanced: boolean = false) => variants.map((variant) => { + return disabledMap.map((disabled) => { + return valueMap.map((value) => { + return requiredMap.map((required) => { + return helperTextMap.map((helperText) => { + return leadingIconMap.map((icon) => { + const props = Object.assign({}, variant, disabled, value, required, helperText, icon, {enhanced}); + const valueKey = Object.keys(value)[0] || ''; + const variantKey = Object.keys(variant)[0] || ''; + const disabledKey = Object.keys(disabled)[0] || ''; + const requiredKey = Object.keys(required)[0] || ''; + const key + = `${variantKey}-${disabledKey}-${valueKey}-${requiredKey} + -${helperText.key}-${icon.key}-${enhanced}`; + return ; + }); + }); }); }); }); }); -const SelectScreenshotTest = () => { - return
{selects}
; -}; export default SelectScreenshotTest; diff --git a/test/screenshot/select/nativeSelect.tsx b/test/screenshot/select/nativeSelect.tsx new file mode 100644 index 000000000..8ab821621 --- /dev/null +++ b/test/screenshot/select/nativeSelect.tsx @@ -0,0 +1,8 @@ +import * as React from 'react'; +import {getSelects} from './index'; + +const NativeSelectScreenshotTest = () => { + return
{getSelects()}
; +}; + +export default NativeSelectScreenshotTest; diff --git a/test/screenshot/select/variants.tsx b/test/screenshot/select/variants.tsx new file mode 100644 index 000000000..282edc3a5 --- /dev/null +++ b/test/screenshot/select/variants.tsx @@ -0,0 +1,4 @@ +export default [ + 'nativeSelect', + 'enhanced', +]; diff --git a/test/screenshot/snackbar/index.tsx b/test/screenshot/snackbar/index.tsx index 13fcb892b..bc4c25c64 100644 --- a/test/screenshot/snackbar/index.tsx +++ b/test/screenshot/snackbar/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import '../../../packages/snackbar/index.scss'; import './index.scss'; import {Snackbar} from '../../../packages/snackbar/index'; diff --git a/test/screenshot/switch/index.tsx b/test/screenshot/switch/index.tsx index d3062a52e..6eba01124 100644 --- a/test/screenshot/switch/index.tsx +++ b/test/screenshot/switch/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import './index.scss'; import Switch from '../../../packages/switch'; diff --git a/test/screenshot/tab-bar/index.tsx b/test/screenshot/tab-bar/index.tsx index 2847de664..1a30c9752 100644 --- a/test/screenshot/tab-bar/index.tsx +++ b/test/screenshot/tab-bar/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import Tab, {TabProps} from '../../../packages/tab/index'; // eslint-disable-line no-unused-vars import TabBar from '../../../packages/tab-bar/index'; import './index.scss'; diff --git a/test/screenshot/tab-indicator/index.tsx b/test/screenshot/tab-indicator/index.tsx index a6ddb3c22..a159bff0a 100644 --- a/test/screenshot/tab-indicator/index.tsx +++ b/test/screenshot/tab-indicator/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TabIndicator from '../../../packages/tab-indicator/index'; import MaterialIcon from '../../../packages/material-icon'; import '../../../packages/tab-indicator/index.scss'; diff --git a/test/screenshot/tab-scroller/index.tsx b/test/screenshot/tab-scroller/index.tsx index 77f2084fd..12193bc28 100644 --- a/test/screenshot/tab-scroller/index.tsx +++ b/test/screenshot/tab-scroller/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TabScroller from '../../../packages/tab-scroller'; import '../../../packages/tab-scroller/index.scss'; import './index.scss'; diff --git a/test/screenshot/tab/index.tsx b/test/screenshot/tab/index.tsx index f2025ca00..6578951e5 100644 --- a/test/screenshot/tab/index.tsx +++ b/test/screenshot/tab/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import Tab, {TabProps} from '../../../packages/tab'; import MaterialIcon from '../../../packages/material-icon/index'; import '../../../packages/tab-indicator/index.scss'; diff --git a/test/screenshot/text-field/TestTextField.tsx b/test/screenshot/text-field/TestTextField.tsx index c368b0647..34839b1e0 100644 --- a/test/screenshot/text-field/TestTextField.tsx +++ b/test/screenshot/text-field/TestTextField.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TextField, {Input} from '../../../packages/text-field'; type TestFieldProps = { disabled?: boolean, diff --git a/test/screenshot/text-field/TextFieldPermutations.tsx b/test/screenshot/text-field/TextFieldPermutations.tsx index c0f4c1720..1735cca43 100644 --- a/test/screenshot/text-field/TextFieldPermutations.tsx +++ b/test/screenshot/text-field/TextFieldPermutations.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import { iconsMap, denseMap, diff --git a/test/screenshot/text-field/attributesMap.tsx b/test/screenshot/text-field/attributesMap.tsx index d5a4de844..c542196f0 100644 --- a/test/screenshot/text-field/attributesMap.tsx +++ b/test/screenshot/text-field/attributesMap.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {HelperText} from '../../../packages/text-field'; import MaterialIcon from '../../../packages/material-icon/index'; diff --git a/test/screenshot/text-field/fullWidth.tsx b/test/screenshot/text-field/fullWidth.tsx index 3f8f757cb..413449927 100644 --- a/test/screenshot/text-field/fullWidth.tsx +++ b/test/screenshot/text-field/fullWidth.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TextFieldPermutations from './TextFieldPermutations'; const FullWidthTextField = () => { diff --git a/test/screenshot/text-field/helper-text/index.tsx b/test/screenshot/text-field/helper-text/index.tsx index 1e640608f..a4e96c92a 100644 --- a/test/screenshot/text-field/helper-text/index.tsx +++ b/test/screenshot/text-field/helper-text/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import HelperText from '../../../../packages/text-field/helper-text/index'; import '../../../../packages/text-field/helper-text/index.scss'; diff --git a/test/screenshot/text-field/icon/index.tsx b/test/screenshot/text-field/icon/index.tsx index b48859192..227188676 100644 --- a/test/screenshot/text-field/icon/index.tsx +++ b/test/screenshot/text-field/icon/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import Icon from '../../../../packages/text-field/icon/index'; import MaterialIcon from '../../../../packages/material-icon/index'; import '../../../../packages/text-field/icon/index.scss'; diff --git a/test/screenshot/text-field/index.tsx b/test/screenshot/text-field/index.tsx index 05b4fd1f6..f44fb1448 100644 --- a/test/screenshot/text-field/index.tsx +++ b/test/screenshot/text-field/index.tsx @@ -1,10 +1,6 @@ -import * as React from 'react'; +import React from 'react'; import {Link} from 'react-router-dom'; import textFieldVariants from './variants'; -import '../../../packages/floating-label/index.scss'; -import '../../../packages/line-ripple/index.scss'; -import '../../../packages/notched-outline/index.scss'; -import '../../../packages/text-field/index.scss'; const TextFieldHomePage = () => { return ( diff --git a/test/screenshot/text-field/outlined.tsx b/test/screenshot/text-field/outlined.tsx index c85de9ee0..9f303ea4f 100644 --- a/test/screenshot/text-field/outlined.tsx +++ b/test/screenshot/text-field/outlined.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TextFieldPermutations from './TextFieldPermutations'; const OutlinedTextField = () => { diff --git a/test/screenshot/text-field/refTest.tsx b/test/screenshot/text-field/refTest.tsx index d263476be..3a14ae3f4 100644 --- a/test/screenshot/text-field/refTest.tsx +++ b/test/screenshot/text-field/refTest.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TextField, {Input} from '../../../packages/text-field'; import Button from '../../../packages/button/index'; diff --git a/test/screenshot/text-field/standard.tsx b/test/screenshot/text-field/standard.tsx index 699bb4b6d..415d0ed25 100644 --- a/test/screenshot/text-field/standard.tsx +++ b/test/screenshot/text-field/standard.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TextFieldPermutations from './TextFieldPermutations'; const StandardTextField = () => { diff --git a/test/screenshot/text-field/textArea.tsx b/test/screenshot/text-field/textArea.tsx index a6a5d8168..a74b3677b 100644 --- a/test/screenshot/text-field/textArea.tsx +++ b/test/screenshot/text-field/textArea.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import { denseMap, requiredMap, diff --git a/test/screenshot/text-field/variants.tsx b/test/screenshot/text-field/variants.tsx index dbf0457ac..aaabf4033 100644 --- a/test/screenshot/text-field/variants.tsx +++ b/test/screenshot/text-field/variants.tsx @@ -1,7 +1,6 @@ export default [ 'standard', 'fullWidth', - 'outlined', 'textArea', 'refTest', ]; diff --git a/test/screenshot/top-app-bar/dense.tsx b/test/screenshot/top-app-bar/dense.tsx index 7f39935d0..2cef6f624 100644 --- a/test/screenshot/top-app-bar/dense.tsx +++ b/test/screenshot/top-app-bar/dense.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/fixed.tsx b/test/screenshot/top-app-bar/fixed.tsx index 2d0f87b98..4d07e7cd8 100644 --- a/test/screenshot/top-app-bar/fixed.tsx +++ b/test/screenshot/top-app-bar/fixed.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/index.tsx b/test/screenshot/top-app-bar/index.tsx index a15e3d35f..a99989c2a 100644 --- a/test/screenshot/top-app-bar/index.tsx +++ b/test/screenshot/top-app-bar/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {Link} from 'react-router-dom'; import topAppBarVariants from './variants'; import {TopAppBarIcon} from '../../../packages/top-app-bar'; diff --git a/test/screenshot/top-app-bar/mainContent.tsx b/test/screenshot/top-app-bar/mainContent.tsx index 47bec24e2..1e0d636d8 100644 --- a/test/screenshot/top-app-bar/mainContent.tsx +++ b/test/screenshot/top-app-bar/mainContent.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import { TopAppBarFixedAdjust, TopAppbarFixedAdjustProps, // eslint-disable-line no-unused-vars diff --git a/test/screenshot/top-app-bar/prominent.tsx b/test/screenshot/top-app-bar/prominent.tsx index fd171caad..c2cd752e2 100644 --- a/test/screenshot/top-app-bar/prominent.tsx +++ b/test/screenshot/top-app-bar/prominent.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/prominentDense.tsx b/test/screenshot/top-app-bar/prominentDense.tsx index 80f2e244a..8fd047054 100644 --- a/test/screenshot/top-app-bar/prominentDense.tsx +++ b/test/screenshot/top-app-bar/prominentDense.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/prominentToShortCollapsed.tsx b/test/screenshot/top-app-bar/prominentToShortCollapsed.tsx index 3865cf3b9..82289eb4f 100644 --- a/test/screenshot/top-app-bar/prominentToShortCollapsed.tsx +++ b/test/screenshot/top-app-bar/prominentToShortCollapsed.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/short.tsx b/test/screenshot/top-app-bar/short.tsx index 670a8ac75..6804e7834 100644 --- a/test/screenshot/top-app-bar/short.tsx +++ b/test/screenshot/top-app-bar/short.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/shortCollapsed.tsx b/test/screenshot/top-app-bar/shortCollapsed.tsx index 43192c5fe..d27ba2d46 100644 --- a/test/screenshot/top-app-bar/shortCollapsed.tsx +++ b/test/screenshot/top-app-bar/shortCollapsed.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/standard.tsx b/test/screenshot/top-app-bar/standard.tsx index 83869fb1e..96c7e7361 100644 --- a/test/screenshot/top-app-bar/standard.tsx +++ b/test/screenshot/top-app-bar/standard.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/standardNoActionItems.tsx b/test/screenshot/top-app-bar/standardNoActionItems.tsx index 0396aa172..31f13c4ac 100644 --- a/test/screenshot/top-app-bar/standardNoActionItems.tsx +++ b/test/screenshot/top-app-bar/standardNoActionItems.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/standardWithNavigationIconElement.tsx b/test/screenshot/top-app-bar/standardWithNavigationIconElement.tsx index 55c01d33f..541364976 100644 --- a/test/screenshot/top-app-bar/standardWithNavigationIconElement.tsx +++ b/test/screenshot/top-app-bar/standardWithNavigationIconElement.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/top-app-bar/twoRows.tsx b/test/screenshot/top-app-bar/twoRows.tsx index e63355410..c5e13eec9 100644 --- a/test/screenshot/top-app-bar/twoRows.tsx +++ b/test/screenshot/top-app-bar/twoRows.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import TopAppBar, { TopAppBarIcon, TopAppBarRow, diff --git a/test/screenshot/typography/index.tsx b/test/screenshot/typography/index.tsx index 0ba302797..34891bc07 100644 --- a/test/screenshot/typography/index.tsx +++ b/test/screenshot/typography/index.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import { Body1, Body2, diff --git a/test/unit/button/index.test.tsx b/test/unit/button/index.test.tsx index 3471bb8e7..6195adcea 100644 --- a/test/unit/button/index.test.tsx +++ b/test/unit/button/index.test.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {mount, shallow} from 'enzyme'; import {Button} from '../../../packages/button/index'; import {coerceForTesting} from '../helpers/types'; diff --git a/test/unit/card/ActionButton.test.tsx b/test/unit/card/ActionButton.test.tsx index 887721b48..e6a463a21 100644 --- a/test/unit/card/ActionButton.test.tsx +++ b/test/unit/card/ActionButton.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {CardActionButtons} from '../../../packages/card/index'; diff --git a/test/unit/card/ActionIcons.test.tsx b/test/unit/card/ActionIcons.test.tsx index e19df903c..7bb7330fa 100644 --- a/test/unit/card/ActionIcons.test.tsx +++ b/test/unit/card/ActionIcons.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {CardActionIcons} from '../../../packages/card/index'; diff --git a/test/unit/card/Actions.test.tsx b/test/unit/card/Actions.test.tsx index 72f438c45..b6587b130 100644 --- a/test/unit/card/Actions.test.tsx +++ b/test/unit/card/Actions.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {CardActions} from '../../../packages/card/index'; diff --git a/test/unit/card/Content.test.tsx b/test/unit/card/Content.test.tsx index baee38227..740c6f4e2 100644 --- a/test/unit/card/Content.test.tsx +++ b/test/unit/card/Content.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {mount} from 'enzyme'; import {CardPrimaryContent} from '../../../packages/card/index'; diff --git a/test/unit/card/Media.test.tsx b/test/unit/card/Media.test.tsx index 652a7025a..b19e16abf 100644 --- a/test/unit/card/Media.test.tsx +++ b/test/unit/card/Media.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {CardMedia} from '../../../packages/card/index'; diff --git a/test/unit/card/index.test.tsx b/test/unit/card/index.test.tsx index 0169ef708..1917a4cb0 100644 --- a/test/unit/card/index.test.tsx +++ b/test/unit/card/index.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import Card from '../../../packages/card/index'; diff --git a/test/unit/checkbox/NativeControl.test.tsx b/test/unit/checkbox/NativeControl.test.tsx index b5887707b..7ccf2b892 100644 --- a/test/unit/checkbox/NativeControl.test.tsx +++ b/test/unit/checkbox/NativeControl.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import NativeControl from '../../../packages/checkbox/NativeControl'; diff --git a/test/unit/checkbox/index.test.tsx b/test/unit/checkbox/index.test.tsx index c08c0d362..68cf8df0d 100644 --- a/test/unit/checkbox/index.test.tsx +++ b/test/unit/checkbox/index.test.tsx @@ -1,12 +1,18 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {Checkbox} from '../../../packages/checkbox/index'; +import {MDCCheckboxAdapter} from '@material/checkbox/adapter'; import {coerceForTesting} from '../helpers/types'; suite('Checkbox'); +const getAdapter = (instance: Checkbox): MDCCheckboxAdapter => { + // @ts-ignore adapter_ is a protected property, we need to override it + return instance.foundation.adapter_; +}; + test('creates foundation', () => { const wrapper = shallow(); assert.exists(wrapper.instance().foundation); @@ -34,12 +40,29 @@ test('has disabled class when props.disabled is true', () => { ); }); +test('has disabled class when foundation calls setDisabled is true', () => { + const wrapper = shallow(); + getAdapter(wrapper.instance()).setNativeControlDisabled(true); + wrapper.update(); + assert.isTrue( + wrapper.find('.mdc-checkbox').hasClass('mdc-checkbox--disabled') + ); +}); + test('native control props.disabled is true when props.disabled is true', () => { const wrapper = shallow(); const nativeControl = wrapper.childAt(0); assert.isTrue(nativeControl.props().disabled); }); +test('native control props.disabled when foundation calls setDisabled is true', () => { + const wrapper = shallow(); + getAdapter(wrapper.instance()).setNativeControlDisabled(true); + wrapper.update(); + const nativeControl = wrapper.childAt(0); + assert.isTrue(nativeControl.props().disabled); +}); + test('native control props.checked is true when props.checked is true', () => { const wrapper = shallow(); const nativeControl = wrapper.childAt(0); @@ -48,21 +71,21 @@ test('native control props.checked is true when props.checked is true', () => { test('#foundation.handleChange gets called when prop.checked updates', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleChange = td.func(); + wrapper.instance().foundation.handleChange = td.func<() => null>(); wrapper.setProps({checked: true}); td.verify(wrapper.instance().foundation.handleChange(), {times: 1}); }); test('#foundation.handleChange gets called when prop.indeterminate updates', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleChange = td.func(); + wrapper.instance().foundation.handleChange = td.func<() => null>(); wrapper.setProps({indeterminate: true}); td.verify(wrapper.instance().foundation.handleChange(), {times: 1}); }); test('#foundation.setDisabled gets called when prop.disabled updates', () => { const wrapper = shallow(); - wrapper.instance().foundation.setDisabled = td.func(); + wrapper.instance().foundation.setDisabled = td.func<(disabled: boolean) => null>(); wrapper.setProps({disabled: true}); td.verify(wrapper.instance().foundation.setDisabled(true), {times: 1}); }); @@ -70,62 +93,58 @@ test('#foundation.setDisabled gets called when prop.disabled updates', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy(), {times: 1}); }); test('#adapter.addClass adds class to state.classList', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.addClass('test-class-name'); + getAdapter(wrapper.instance()).addClass('test-class-name'); assert.isTrue(wrapper.state().classList.has('test-class-name')); }); test('#adapter.removeClass removes class from state.classList', () => { const wrapper = shallow(); wrapper.setState({classList: new Set(['test-class-name'])}); - wrapper.instance().foundation.adapter_.removeClass('test-class-name'); + getAdapter(wrapper.instance()).removeClass('test-class-name'); assert.isFalse(wrapper.state().classList.has('test-class-name')); }); test('#adapter.isChecked returns state.checked if true', () => { const wrapper = shallow(); wrapper.setState({checked: true}); - assert.isTrue(wrapper.instance().foundation.adapter_.isChecked()); + assert.isTrue(getAdapter(wrapper.instance()).isChecked()); }); test('#adapter.isChecked returns state.checked if false', () => { const wrapper = shallow(); wrapper.setState({checked: false}); - assert.isFalse(wrapper.instance().foundation.adapter_.isChecked()); + assert.isFalse(getAdapter(wrapper.instance()).isChecked()); }); test('#adapter.isIndeterminate returns state.indeterminate if true', () => { const wrapper = shallow(); wrapper.setState({indeterminate: true}); - assert.isTrue(wrapper.instance().foundation.adapter_.isIndeterminate()); + assert.isTrue(getAdapter(wrapper.instance()).isIndeterminate()); }); test('#adapter.isIndeterminate returns state.indeterminate if false', () => { const wrapper = shallow(); wrapper.setState({indeterminate: false}); - assert.isFalse(wrapper.instance().foundation.adapter_.isIndeterminate()); + assert.isFalse(getAdapter(wrapper.instance()).isIndeterminate()); }); test('#adapter.setNativeControlAttr sets aria-checked state', () => { const wrapper = shallow(); - wrapper - .instance() - .foundation.adapter_.setNativeControlAttr('aria-checked', true); - assert.isTrue(wrapper.state()['aria-checked']); + getAdapter(wrapper.instance()).setNativeControlAttr('aria-checked', 'true'); + assert.equal(wrapper.state()['aria-checked'], 'true'); }); test('#adapter.removeNativeControlAttr sets aria-checked state as false', () => { const wrapper = shallow(); - wrapper.setState({'aria-checked': true}); - wrapper - .instance() - .foundation.adapter_.removeNativeControlAttr('aria-checked'); + wrapper.setState({'aria-checked': 'true'}); + getAdapter(wrapper.instance()).removeNativeControlAttr('aria-checked'); assert.isFalse(wrapper.state()['aria-checked']); }); @@ -148,7 +167,7 @@ test('calls foundation.handleChange in native control props.onChange', () => { indeterminate: false, }, }; - wrapper.instance().foundation.handleChange = td.func(); + wrapper.instance().foundation.handleChange = td.func<() => void>(); nativeControl.simulate('change', mockEvt); td.verify(wrapper.instance().foundation.handleChange(), {times: 1}); }); diff --git a/test/unit/chips/Chip.test.tsx b/test/unit/chips/Chip.test.tsx index 45f976796..541868328 100644 --- a/test/unit/chips/Chip.test.tsx +++ b/test/unit/chips/Chip.test.tsx @@ -1,13 +1,20 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {mount, shallow} from 'enzyme'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {Chip} from '../../../packages/chips/Chip'; import ChipCheckmark from '../../../packages/chips/ChipCheckmark'; import {coerceForTesting} from '../helpers/types'; +import {MDCChipAdapter} from '@material/chips/chip/adapter'; + suite('Chip'); +function getAdapter(instance: Chip): MDCChipAdapter { + // @ts-ignore adapter_ is protected property, we need to override it + return instance.foundation.adapter_; +} + test('creates foundation', () => { const wrapper = mount(); assert.exists(wrapper.instance().foundation); @@ -16,7 +23,7 @@ test('creates foundation', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy(), {times: 1}); }); @@ -45,7 +52,8 @@ test('when props.shouldRemoveOnTrailingIconClick updates to false, ' + ' #foundation.setShouldRemoveOnTrailingIconClick is called ', () => { const wrapper = shallow(); assert.isTrue(wrapper.instance().foundation.getShouldRemoveOnTrailingIconClick()); - wrapper.instance().foundation.setShouldRemoveOnTrailingIconClick = td.func(); + wrapper.instance().foundation.setShouldRemoveOnTrailingIconClick = + td.func<(shouldRemove: boolean) => void>(); wrapper.setProps({shouldRemoveOnTrailingIconClick: false}); td.verify(wrapper.instance().foundation.setShouldRemoveOnTrailingIconClick(false), {times: 1}); }); @@ -55,7 +63,8 @@ test('when props.shouldRemoveOnTrailingIconClick updates to true, ' + ' #foundation.setShouldRemoveOnTrailingIconClick is called ', () => { const wrapper = shallow(); assert.isFalse(wrapper.instance().foundation.getShouldRemoveOnTrailingIconClick()); - wrapper.instance().foundation.setShouldRemoveOnTrailingIconClick = td.func(); + wrapper.instance().foundation.setShouldRemoveOnTrailingIconClick = + td.func<(shouldRemove: boolean) => void>(); wrapper.setProps({shouldRemoveOnTrailingIconClick: true}); td.verify(wrapper.instance().foundation.setShouldRemoveOnTrailingIconClick(true), {times: 1}); }); @@ -126,9 +135,7 @@ test('#adapter.setStyleProperty should add styles to chip', () => { test('#adapter.addClassToLeadingIcon adds to state.leadingIconClassList', () => { const wrapper = shallow(); - wrapper - .instance() - .foundation.adapter_.addClassToLeadingIcon('test-leading-icon-class'); + getAdapter(wrapper.instance()).addClassToLeadingIcon('test-leading-icon-class'); assert.isTrue( wrapper.state().leadingIconClassList.has('test-leading-icon-class') ); @@ -139,9 +146,7 @@ test('#adapter.removeClassFromLeadingIcon removes from state.leadingIconClassLis wrapper.setState({ leadingIconClassList: new Set('test-leading-icon-class'), }); - wrapper - .instance() - .foundation.adapter_.removeClassFromLeadingIcon('test-leading-icon-class'); + getAdapter(wrapper.instance()).removeClassFromLeadingIcon('test-leading-icon-class'); assert.isFalse( wrapper.state().leadingIconClassList.has('test-leading-icon-class') ); @@ -152,52 +157,56 @@ test('#adapter.notifyInteraction calls #props.handleInteraction w/ chipId', () = const wrapper = shallow( ); - wrapper.instance().foundation.adapter_.notifyInteraction(); + getAdapter(wrapper.instance()).notifyInteraction(); td.verify(handleInteraction('123'), {times: 1}); }); test('#adapter.notifyRemoval calls #props.handleRemove w/ chipId', () => { const handleRemove = coerceForTesting<(id: string) => void>(td.func()); const wrapper = shallow(); - wrapper.instance().foundation.adapter_.notifyRemoval(); + getAdapter(wrapper.instance()).notifyRemoval(); td.verify(handleRemove('123'), {times: 1}); }); test('#adapter.notifySelection calls #props.handleSelect w/ chipId and selected false', () => { const handleSelect = coerceForTesting<(id: string, selected: boolean) => void>(td.func()); const wrapper = shallow(); - wrapper.instance().foundation.adapter_.notifySelection(false); + getAdapter(wrapper.instance()).notifySelection(false); td.verify(handleSelect('123', false), {times: 2}); }); test('#adapter.notifySelection calls #props.handleSelect w/ chipId and selected true', () => { const handleSelect = coerceForTesting<(id: string, selected: boolean) => void>(td.func()); const wrapper = shallow(); - wrapper.instance().foundation.adapter_.notifySelection(true); + getAdapter(wrapper.instance()).notifySelection(true); td.verify(handleSelect('123', true), {times: 1}); }); test('#adapter.notifyTrailingIconInteraction calls #props.handleTrailingIconInteraction w/ chipId', () => { const handleTrailingIconInteraction = coerceForTesting<(id: string) => void>(td.func()); const wrapper = shallow(); - wrapper.instance().foundation.adapter_.notifyTrailingIconInteraction(); + getAdapter(wrapper.instance()).notifyTrailingIconInteraction(); td.verify(handleTrailingIconInteraction('123'), {times: 1}); }); test('on click calls #props.onClick', () => { const onClick = coerceForTesting<(event: React.MouseEvent) => void>(td.func()); const wrapper = shallow(); - const evt = coerceForTesting({}); + const evt = coerceForTesting({ + nativeEvent: {}, + }); wrapper.simulate('click', evt); td.verify(onClick(evt), {times: 1}); }); test('on click calls #foudation.handleInteraction', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleInteraction = td.func(); - const evt = {}; + wrapper.instance().foundation.handleInteraction = td.func<(evt: MouseEvent | KeyboardEvent) => null>(); + const evt = coerceForTesting({ + nativeEvent: {}, + }); wrapper.simulate('click', evt); - td.verify(wrapper.instance().foundation.handleInteraction(evt), { + td.verify(wrapper.instance().foundation.handleInteraction(evt.nativeEvent), { times: 1, }); }); @@ -205,17 +214,21 @@ test('on click calls #foudation.handleInteraction', () => { test('on keydown calls #props.onKeyDown', () => { const onKeyDown = coerceForTesting<(event: React.KeyboardEvent) => void>(td.func()); const wrapper = shallow(); - const evt = coerceForTesting({}); + const evt = coerceForTesting({ + nativeEvent: {}, + }); wrapper.simulate('keydown', evt); td.verify(onKeyDown(evt), {times: 1}); }); test('on keydown calls #foudation.handleInteraction', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleInteraction = td.func(); - const evt = {}; + wrapper.instance().foundation.handleInteraction = td.func<(evt: MouseEvent | KeyboardEvent) => null>(); + const evt = coerceForTesting({ + nativeEvent: {}, + }); wrapper.simulate('keydown', evt); - td.verify(wrapper.instance().foundation.handleInteraction(evt), { + td.verify(wrapper.instance().foundation.handleInteraction(evt.nativeEvent), { times: 1, }); }); @@ -317,13 +330,16 @@ test('renders trailing icon with base class names', () => { test('trailing icon click calls #foundation.handleTrailingIconInteraction', () => { const trailingIcon = ; const wrapper = shallow(); - wrapper.instance().foundation.handleTrailingIconInteraction = td.func(); - const evt = {}; + wrapper.instance().foundation.handleTrailingIconInteraction = + td.func<(evt: MouseEvent | KeyboardEvent) => null>(); + const evt = coerceForTesting({ + nativeEvent: {}, + }); wrapper .children() .last() .simulate('click', evt); - td.verify(wrapper.instance().foundation.handleTrailingIconInteraction(evt), { + td.verify(wrapper.instance().foundation.handleTrailingIconInteraction(evt.nativeEvent), { times: 1, }); }); @@ -331,13 +347,16 @@ test('trailing icon click calls #foundation.handleTrailingIconInteraction', () = test('trailing icon keydown calls #foundation.handleTrailingIconInteraction', () => { const trailingIcon = ; const wrapper = shallow(); - wrapper.instance().foundation.handleTrailingIconInteraction = td.func(); - const evt = {}; + wrapper.instance().foundation.handleTrailingIconInteraction = + td.func<(evt: MouseEvent | KeyboardEvent) => null>(); + const evt = coerceForTesting({ + nativeEvent: {}, + }); wrapper .children() .last() .simulate('keydown', evt); - td.verify(wrapper.instance().foundation.handleTrailingIconInteraction(evt), { + td.verify(wrapper.instance().foundation.handleTrailingIconInteraction(evt.nativeEvent), { times: 1, }); }); @@ -345,10 +364,12 @@ test('trailing icon keydown calls #foundation.handleTrailingIconInteraction', () test('calls #foundation.handleTransitionEnd on transitionend event', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleTransitionEnd = td.func(); - const evt = {target: {}}; + wrapper.instance().foundation.handleTransitionEnd = td.func<(evt: TransitionEvent) => null>(); + const evt = coerceForTesting({ + nativeEvent: { + target: {}}}); wrapper.simulate('transitionend', evt); - td.verify(wrapper.instance().foundation.handleTransitionEnd(evt), { + td.verify(wrapper.instance().foundation.handleTransitionEnd(evt.nativeEvent), { times: 1, }); }); @@ -358,7 +379,7 @@ test('calls #props.onTransitionEnd on transitionend event', () => { const wrapper = shallow(); // need to remove foundation, since React.TransitionEvent does not have classList on EventTarget // see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/12239 - wrapper.instance().foundation = {handleTransitionEnd: () => {}}; + wrapper.instance().foundation = coerceForTesting({handleTransitionEnd: () => {}}); const evt = coerceForTesting({}); wrapper.simulate('transitionend', evt); td.verify(onTransitionEnd(evt), {times: 1}); @@ -394,7 +415,7 @@ test('renders label text', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy()); }); diff --git a/test/unit/chips/ChipCheckmark.test.tsx b/test/unit/chips/ChipCheckmark.test.tsx index 9521dce38..4c212fc02 100644 --- a/test/unit/chips/ChipCheckmark.test.tsx +++ b/test/unit/chips/ChipCheckmark.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {mount} from 'enzyme'; import ChipCheckmark from '../../../packages/chips/ChipCheckmark'; diff --git a/test/unit/chips/ChipSet.test.tsx b/test/unit/chips/ChipSet.test.tsx index 2f69ef4b5..0ae12234f 100644 --- a/test/unit/chips/ChipSet.test.tsx +++ b/test/unit/chips/ChipSet.test.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {shallow, mount} from 'enzyme'; import ChipSet from '../../../packages/chips/ChipSet'; import {Chip, ChipProps} from '../../../packages/chips/index'; // eslint-disable-line no-unused-vars @@ -74,7 +74,7 @@ test('#adapter.hasClass returns false if component does not contains class', () test('#adapter.setSelected adds selectedChipId to state', () => { const getSelectedChipIds = td.func(); const handleSelect = coerceForTesting<(selectedChipIds: string[]) => void>(td.func()); - const foundation = {getSelectedChipIds}; + const foundation = coerceForTesting({getSelectedChipIds}); const wrapper = shallow(
@@ -120,22 +120,22 @@ test(
); - wrapper.state().foundation.select = td.func(); + wrapper.state().foundation!.select = td.func<(chipId: string) => null>(); const selectedChipIds = ['1']; wrapper.setState({selectedChipIds}); wrapper.instance().initChipSelection(); - td.verify(wrapper.state().foundation.select('1'), {times: 1}); + td.verify(wrapper.state().foundation!.select('1'), {times: 1}); } ); test('#handleSelect calls foundation.handleChipSelection with selectedChipId and selected=true', () => { const handleChipSelection = td.func(); - const foundation = {handleChipSelection}; const wrapper = shallow(
); + const foundation = coerceForTesting({handleChipSelection}); wrapper.setState({foundation}); wrapper.instance().handleSelect('1', true); td.verify(handleChipSelection('1', true), {times: 1}); @@ -143,7 +143,7 @@ test('#handleSelect calls foundation.handleChipSelection with selectedChipId and test('#handleSelect calls foundation.handleChipSelection with selectedChipId and selected=false', () => { const handleChipSelection = td.func(); - const foundation = {handleChipSelection}; + const foundation = coerceForTesting({handleChipSelection}); const wrapper = shallow(
@@ -211,7 +211,7 @@ test('#chip.props.handleInteraction calls both #chip.handleInteraction calls #fo test('#handleInteraction calls #foundation.handleChipInteraction', () => { const handleChipInteraction = td.func(); - const foundation = {handleChipInteraction}; + const foundation = coerceForTesting({handleChipInteraction}); const wrapper = shallow(
@@ -224,7 +224,7 @@ test('#handleInteraction calls #foundation.handleChipInteraction', () => { test('#handleRemove calls foundation.handleChipRemoval with chipId', () => { const handleChipRemoval = td.func(); - const foundation = {handleChipRemoval}; + const foundation = coerceForTesting({handleChipRemoval}); const wrapper = shallow(
@@ -447,8 +447,8 @@ test('input variant of ChipSet will throw error if chip missing id', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); - const foundation = wrapper.state().foundation; - foundation.destroy = td.func(); + const foundation = wrapper.state().foundation!; + foundation.destroy = td.func<() => null>(); wrapper.unmount(); td.verify(foundation.destroy()); }); diff --git a/test/unit/dialog/DialogButton.test.tsx b/test/unit/dialog/DialogButton.test.tsx index 2c803ea2d..f83582a51 100644 --- a/test/unit/dialog/DialogButton.test.tsx +++ b/test/unit/dialog/DialogButton.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {DialogButton} from '../../../packages/dialog'; diff --git a/test/unit/dialog/DialogContent.test.tsx b/test/unit/dialog/DialogContent.test.tsx index 1940933f1..0a170ccd5 100644 --- a/test/unit/dialog/DialogContent.test.tsx +++ b/test/unit/dialog/DialogContent.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {DialogContent} from '../../../packages/dialog'; diff --git a/test/unit/dialog/DialogFooter.test.tsx b/test/unit/dialog/DialogFooter.test.tsx index b1f65cadf..838f685f6 100644 --- a/test/unit/dialog/DialogFooter.test.tsx +++ b/test/unit/dialog/DialogFooter.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {DialogFooter, DialogButton} from '../../../packages/dialog'; diff --git a/test/unit/dialog/DialogTitle.test.tsx b/test/unit/dialog/DialogTitle.test.tsx index 658be8f39..0567e9800 100644 --- a/test/unit/dialog/DialogTitle.test.tsx +++ b/test/unit/dialog/DialogTitle.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {DialogTitle} from '../../../packages/dialog'; diff --git a/test/unit/dialog/index.test.tsx b/test/unit/dialog/index.test.tsx index 3f0e472d0..d39593b43 100644 --- a/test/unit/dialog/index.test.tsx +++ b/test/unit/dialog/index.test.tsx @@ -1,14 +1,12 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {shallow, mount} from 'enzyme'; -// @ts-ignore import Dialog, { ChildTypes, DialogTitle, DialogContent, DialogFooter, DialogButton, } from '../../../packages/dialog'; -// @ts-ignore no mdc .d.ts file -import {util} from '@material/dialog/dist/mdc.dialog'; +import {isScrollable, areTopsMisaligned} from '@material/dialog/util'; import {cssClasses, LAYOUT_EVENTS} from '../../../packages/dialog/constants'; import {coerceForTesting} from '../helpers/types'; import {FocusTrap} from 'focus-trap'; @@ -26,6 +24,11 @@ const DialogStub = ( suite('Dialog'); +const getAdapter = (instance: Dialog) => { + // @ts-ignore adapter_ property is protection, we need to override it for testing purposes + return instance.foundation.adapter_; +}; + test('renders a dialog with default tag', () => { const wrapper = shallow(); assert.equal(wrapper.type(), 'div'); @@ -44,7 +47,7 @@ test('creates foundation', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy()); }); @@ -87,14 +90,14 @@ test('#componentDidMount calls #foundaiton.setScrimClickAction if prop present', test('when props.open updates to true, #foundation.open is called ', () => { const wrapper = shallow(); - wrapper.instance().foundation.open = td.func(); + wrapper.instance().foundation.open = td.func<() => void>(); wrapper.setProps({open: true}); td.verify(wrapper.instance().foundation.open(), {times: 1}); }); test('when props.open updates to false from true, #foundation.close is called ', () => { const wrapper = shallow(); - wrapper.instance().foundation.close = td.func(); + wrapper.instance().foundation.close = td.func<(action: string) => null>(); wrapper.setProps({open: false}); td.verify(wrapper.instance().foundation.close(), {times: 1}); }); @@ -103,7 +106,7 @@ test('when props.autoStackButtons updates to true, ' + ' #foundation.setAutoStackButtons is called ', () => { const wrapper = shallow(); assert.isFalse(wrapper.instance().foundation.getAutoStackButtons()); - wrapper.instance().foundation.setAutoStackButtons = td.func(); + wrapper.instance().foundation.setAutoStackButtons = td.func<(autoStack: boolean) => null>(); wrapper.setProps({autoStackButtons: true}); td.verify(wrapper.instance().foundation.setAutoStackButtons(true), {times: 1}); }); @@ -112,7 +115,7 @@ test('when props.autoStackButtons updates to false, ' + ' #foundation.setAutoStackButtons is called ', () => { const wrapper = shallow(); assert.isTrue(wrapper.instance().foundation.getAutoStackButtons()); - wrapper.instance().foundation.setAutoStackButtons = td.func(); + wrapper.instance().foundation.setAutoStackButtons = td.func<(autoStack: boolean) => null>(); wrapper.setProps({autoStackButtons: false}); td.verify(wrapper.instance().foundation.setAutoStackButtons(false), {times: 1}); }); @@ -121,7 +124,7 @@ test('when props.escapeKeyAction updates #foundation.setEscapeKeyAction is calle const wrapper = shallow(); const escapeKeyAction: string = 'meow'; - wrapper.instance().foundation.setEscapeKeyAction = td.func(); + wrapper.instance().foundation.setEscapeKeyAction = td.func<(action: string) => null>(); wrapper.setProps({escapeKeyAction}); td.verify(wrapper.instance().foundation.setEscapeKeyAction(escapeKeyAction), {times: 1}); }); @@ -130,7 +133,7 @@ test('when props.scrimClickAction updates #foundation.setScrimClickAction is cal const wrapper = shallow(); const scrimClickAction: string = 'meow'; - wrapper.instance().foundation.setScrimClickAction = td.func(); + wrapper.instance().foundation.setScrimClickAction = td.func<(action: string) => null>(); wrapper.setProps({scrimClickAction}); td.verify(wrapper.instance().foundation.setScrimClickAction(scrimClickAction), {times: 1}); }); @@ -159,26 +162,26 @@ test('classNames adds classes', () => { test('#adapter.addClass should update state with new className', () => { const wrapper = mount(); - wrapper.instance().foundation.adapter_.addClass('test-class'); + getAdapter(wrapper.instance()).addClass('test-class'); assert.isTrue(wrapper.state().classList.has('test-class')); }); test('#adapter.removeClass should update state with new className', () => { const wrapper = mount(); wrapper.setState({classList: new Set(['test-class'])}); - wrapper.instance().foundation.adapter_.removeClass('test-class'); + getAdapter(wrapper.instance()).removeClass('test-class'); assert.isFalse(wrapper.state().classList.has('test-class')); }); test('#adapter.hasClass returns true if class is contained in classes', () => { const wrapper = mount(); wrapper.setState({classList: new Set(['test-class'])}); - assert.isTrue(wrapper.instance().foundation.adapter_.hasClass('test-class')); + assert.isTrue(getAdapter(wrapper.instance()).hasClass('test-class')); }); test('#adapter.addBodyClass adds a class to the body', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.addBodyClass('test-class'); + getAdapter(wrapper.instance()).addBodyClass('test-class'); const body = document.querySelector('body')!; assert.isTrue(body.classList.contains('test-class')); }); @@ -232,7 +235,7 @@ test('#adapter.isContentScrollable returns the value of util.isScrollable', () = ); const content = wrapper.instance().content; assert.strictEqual( - wrapper.instance().adapter.isContentScrollable(), util.isScrollable(content) + wrapper.instance().adapter.isContentScrollable(), isScrollable(content) ); }); @@ -241,7 +244,7 @@ test('#adapter.areButtonsStacked returns result of util.areTopsMisaligned', () = const buttons = wrapper.instance().buttons; assert.strictEqual( wrapper.instance().adapter.areButtonsStacked(), - util.areTopsMisaligned(buttons) + areTopsMisaligned(buttons) ); }); @@ -249,7 +252,7 @@ test('#adapter.getActionFromEvent returns attribute value on event target', () = const wrapper = mount(DialogStub); const buttons = wrapper.instance().buttons!; - const action = wrapper.instance().adapter.getActionFromEvent({target: buttons[1]}); + const action = wrapper.instance().adapter.getActionFromEvent(coerceForTesting({target: buttons[1]})); assert.equal(action, 'accept'); }); @@ -268,7 +271,7 @@ test('#adapter.getActionFromEvent returns attribute value on parent of event tar ); const spanEl = wrapper.instance().content!.getElementsByTagName('span')[0]; - const action = wrapper.instance().adapter.getActionFromEvent({target: spanEl}); + const action = wrapper.instance().adapter.getActionFromEvent(coerceForTesting({target: spanEl})); assert.equal(action, 'pet'); }); @@ -288,7 +291,7 @@ test('#adapter.getActionFromEvent returns null when attribute is not present', ( ); const spanEl = wrapper.instance().content!.getElementsByTagName('span')[0]; - const action = wrapper.instance().adapter.getActionFromEvent({target: spanEl}); + const action = wrapper.instance().adapter.getActionFromEvent(coerceForTesting({target: spanEl})); assert.isNull(action); }); @@ -370,9 +373,9 @@ test('#handleOpening adds keydown handler on document that triggers ' + '#foundation.handleDocumentKeyDown', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleDocumentKeydown = td.func(); + wrapper.instance().foundation.handleDocumentKeydown = td.func<(evt: KeyboardEvent) => null>(); - const e = new Event('keydown'); + const e = new KeyboardEvent('keydown'); document.dispatchEvent(e); td.verify(wrapper.instance().foundation.handleDocumentKeydown(e), {times: 0}); @@ -402,7 +405,7 @@ test('#handleClosing removes keydown handler on document that triggers ' + coerceForTesting<(evt: KeyboardEvent) => void>(td.func()); wrapper.instance().handleOpening(); - const e = new Event('keydown'); + const e = new KeyboardEvent('keydown'); document.dispatchEvent(e); td.verify(wrapper.instance().foundation.handleDocumentKeydown(e), {times: 1}); @@ -419,7 +422,7 @@ test('#handleClosing removes handler for LAYOUT_EVENTS to window', () => { wrapper.instance().handleOpening(); LAYOUT_EVENTS.forEach((eventType) => { - let evt = new Event(eventType); + let evt = new KeyboardEvent(eventType); window.dispatchEvent(evt); // @ts-ignore expected 0 arguments but got 1 td.verify(wrapper.instance().handleLayout(evt), {times: 1}); @@ -521,19 +524,23 @@ test('#setId will set labelledby and from a custom DialogTitle', () => { test('#events.onKeyDown triggers #foundaiton.handleInteraction', () => { const wrapper = shallow(

meow

); - wrapper.instance().foundation.handleInteraction = td.func(); - const e = {}; + wrapper.instance().foundation.handleInteraction = td.func<(e: KeyboardEvent) => null>(); + const e = coerceForTesting({ + nativeEvent: {}, + }); wrapper.simulate('keydown', e); - td.verify(wrapper.instance().foundation.handleInteraction(e), {times: 1}); + td.verify(wrapper.instance().foundation.handleInteraction(e.nativeEvent), {times: 1}); }); test('#events.onClick triggers #foundaiton.handleInteraction', () => { const wrapper = shallow(

meow

); - wrapper.instance().foundation.handleInteraction = td.func(); - const e = {}; + wrapper.instance().foundation.handleInteraction = td.func<(e: KeyboardEvent) => null>(); + const e = coerceForTesting({ + nativeEvent: {}, + }); wrapper.simulate('click', e); - td.verify(wrapper.instance().foundation.handleInteraction(e), {times: 1}); + td.verify(wrapper.instance().foundation.handleInteraction(e.nativeEvent), {times: 1}); }); test('Dialog closes when esc key is pressed', () => { diff --git a/test/unit/drawer/index.test.tsx b/test/unit/drawer/index.test.tsx index 3686f7d95..86e8fc418 100644 --- a/test/unit/drawer/index.test.tsx +++ b/test/unit/drawer/index.test.tsx @@ -1,11 +1,17 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow, mount} from 'enzyme'; -import * as td from 'testdouble'; +import td from 'testdouble'; +import {MDCModalDrawerFoundation, MDCDismissibleDrawerFoundation, MDCDrawerAdapter} from '@material/drawer'; import Drawer from '../../../packages/drawer/index'; import {Options, DeactivateOptions, FocusTrap} from 'focus-trap'; // eslint-disable-line no-unused-vars import {coerceForTesting} from '../helpers/types'; +function getAdapter(foundation: MDCModalDrawerFoundation | MDCDismissibleDrawerFoundation): MDCDrawerAdapter { + // @ts-ignore adapter_ property is marked as protected in mdc-web. We need to override this behaviour for testing + return foundation.adapter_; +} + suite('Drawer'); test('creates foundation if dismissible', () => { @@ -25,30 +31,30 @@ test('doesnot create foundation if standard', () => { test('when props.open updates to true, #foundation.open is called when dismissible', () => { const wrapper = shallow(); - wrapper.instance().foundation.open = td.func(); + wrapper.instance().foundation!.open = coerceForTesting<() => void>(td.func()); wrapper.setProps({open: true}); - td.verify(wrapper.instance().foundation.open(), {times: 1}); + td.verify(wrapper.instance().foundation!.open(), {times: 1}); }); test('when props.open updates to false from true, #foundation.close is called when dismissible', () => { const wrapper = shallow(); - wrapper.instance().foundation.close = td.func(); + wrapper.instance().foundation!.close = coerceForTesting<() => void>(td.func()); wrapper.setProps({open: false}); - td.verify(wrapper.instance().foundation.close(), {times: 1}); + td.verify(wrapper.instance().foundation!.close(), {times: 1}); }); test('when props.open updates to true, #foundation.open is called when modal', () => { const wrapper = shallow(); - wrapper.instance().foundation.open = td.func(); + wrapper.instance().foundation!.open = coerceForTesting<() => void>(td.func()); wrapper.setProps({open: true}); - td.verify(wrapper.instance().foundation.open(), {times: 1}); + td.verify(wrapper.instance().foundation!.open(), {times: 1}); }); test('when props.open updates to false from true, #foundation.close is called when modal', () => { const wrapper = shallow(); - wrapper.instance().foundation.close = td.func(); + wrapper.instance().foundation!.close = coerceForTesting<() => void>(td.func()); wrapper.setProps({open: false}); - td.verify(wrapper.instance().foundation.close(), {times: 1}); + td.verify(wrapper.instance().foundation!.close(), {times: 1}); }); test('when changes from permanent to modal drawer with no foundation, creates a foundation', () => { @@ -75,18 +81,18 @@ test('when the drawer changes from dismissible to modal the foundation changes ' test('when the drawer changes from dismissible to modal the original foundation calls destroy', () => { const wrapper = shallow(); - const destroy = td.func(); - wrapper.instance().foundation = {destroy}; + const foundation = wrapper.instance().foundation; + foundation!.destroy = coerceForTesting<() => void>(td.func()); wrapper.setProps({modal: true}); - td.verify(destroy(), {times: 1}); + td.verify(foundation!.destroy(), {times: 1}); }); test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation!.destroy = coerceForTesting<() => void>(td.func()); wrapper.unmount(); - td.verify(foundation.destroy(), {times: 1}); + td.verify(foundation!.destroy(), {times: 1}); }); test('has dismissible drawer class when props.dismissible is true', () => { @@ -106,21 +112,21 @@ test('has mdc drawer class', () => { test('#adapter.addClass should update state with new className', () => { const wrapper = mount(); - wrapper.instance().foundation.adapter_.addClass('test-class'); + getAdapter(wrapper.instance().foundation!).addClass('test-class'); assert.isTrue(wrapper.state().classList.has('test-class')); }); test('#adapter.removeClass should update state with new className', () => { const wrapper = mount(); wrapper.setState({classList: new Set(['test-class'])}); - wrapper.instance().foundation.adapter_.removeClass('test-class'); + getAdapter(wrapper.instance().foundation!).removeClass('test-class'); assert.isFalse(wrapper.state().classList.has('test-class')); }); test('#adapter.hasClass returns true if class is contained in classes', () => { const wrapper = mount(); wrapper.setState({classList: new Set(['test-class'])}); - assert.isTrue(wrapper.instance().foundation.adapter_.hasClass('test-class')); + assert.isTrue(getAdapter(wrapper.instance().foundation!).hasClass('test-class')); }); test('#adapter.elementHasClass should return true when element has class', () => { @@ -142,15 +148,15 @@ test('#adapter.elementHasClass should return false when element does not have cl .childAt(0) .childAt(0) .getDOMNode(); - const hasClass = wrapper - .instance() - .foundation.adapter_.elementHasClass(element, 'test-class'); + const hasClass = getAdapter( + wrapper.instance().foundation! + ).elementHasClass(element, 'test-class'); assert.isFalse(hasClass); }); test('#adapter.saveFocus updates previousFocus', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.saveFocus(); + getAdapter(wrapper.instance().foundation!).saveFocus(); assert.exists(wrapper.instance().previousFocus); }); test( @@ -174,7 +180,7 @@ test( .childAt(0) .getDOMNode()); drawerButtonElement.focus(); - wrapper.instance().foundation.adapter_.restoreFocus(); + getAdapter(wrapper.instance().foundation!).restoreFocus(); assert.equal(focusedElement, document.activeElement); div.remove(); focusedElement.remove(); @@ -195,7 +201,7 @@ test('#adapter.focusActiveNavigationItem focuses on first list item in drawer', , options ); - wrapper.instance().foundation.adapter_.focusActiveNavigationItem(); + getAdapter(wrapper.instance().foundation!).focusActiveNavigationItem(); assert.isTrue( document.activeElement!.classList.contains('mdc-list-item--activated') ); @@ -205,14 +211,14 @@ test('#adapter.focusActiveNavigationItem focuses on first list item in drawer', test('#adapter.notifyClose calls props.onClose', () => { const onClose = coerceForTesting<() => void>(td.func()); const wrapper = shallow(); - wrapper.instance().foundation.adapter_.notifyClose(); + getAdapter(wrapper.instance().foundation!).notifyClose(); td.verify(onClose(), {times: 1}); }); test('#adapter.notifyOpen calls props.onOpen', () => { const onOpen = coerceForTesting<() => void>(td.func()); const wrapper = shallow(); - wrapper.instance().foundation.adapter_.notifyOpen(); + getAdapter(wrapper.instance().foundation!).notifyOpen(); td.verify(onOpen(), {times: 1}); }); @@ -220,7 +226,7 @@ test('#adapter.trapFocus calls focusTrap.activate if modal variant', () => { const wrapper = shallow(); const activate = coerceForTesting<(activateOptions?: Pick) => void>(td.func()); wrapper.instance().focusTrap = coerceForTesting({activate}); - wrapper.instance().foundation.adapter_.trapFocus(); + getAdapter(wrapper.instance().foundation!).trapFocus(); td.verify(activate(), {times: 1}); }); @@ -228,7 +234,7 @@ test('#adapter.releaseFocus calls focusTrap.deactivate if modal variant', () => const wrapper = shallow(); const deactivate = coerceForTesting<(deactivateOptions?: DeactivateOptions) => void>(td.func()); wrapper.instance().focusTrap = coerceForTesting({deactivate}); - wrapper.instance().foundation.adapter_.releaseFocus(); + getAdapter(wrapper.instance().foundation!).releaseFocus(); td.verify(deactivate(), {times: 1}); }); @@ -242,10 +248,14 @@ test('event keydown triggers props.onKeyDown', () => { test('event keydown triggers foundation.handleKeydown', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleKeydown = td.func(); - const evt = coerceForTesting({}); + const foundation = wrapper.instance().foundation as MDCModalDrawerFoundation; + foundation.handleKeydown = coerceForTesting<(event: KeyboardEvent) => void>( + td.func() + ); + const nativeEvent = coerceForTesting({}); + const evt = coerceForTesting({nativeEvent}); wrapper.childAt(0).simulate('keydown', evt); - td.verify(wrapper.instance().foundation.handleKeydown(evt), {times: 1}); + td.verify(foundation.handleKeydown(nativeEvent), {times: 1}); }); test('event transitionend triggers props.onTransitionEnd', () => { @@ -258,17 +268,19 @@ test('event transitionend triggers props.onTransitionEnd', () => { test('event transitionend triggers foundation.handleTransitionEnd', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleTransitionEnd = td.func(); - const evt = coerceForTesting({}); + const foundation = wrapper.instance().foundation as MDCModalDrawerFoundation; + foundation.handleTransitionEnd = coerceForTesting<() => void>(td.func()); + const nativeEvent = coerceForTesting({}); + const evt = coerceForTesting({nativeEvent}); wrapper.childAt(0).simulate('transitionend', evt); - td.verify(wrapper.instance().foundation.handleTransitionEnd(evt), { + td.verify(foundation.handleTransitionEnd(nativeEvent), { times: 1, }); }); test('does not render scrim when props.modal is false', () => { const wrapper = shallow(); - assert.equal(wrapper.childAt(1).type(), null); + assert.equal(wrapper.children().length, 1); }); test('renders scrim when props.modal is true', () => { @@ -278,10 +290,25 @@ test('renders scrim when props.modal is true', () => { test('click on scrim calls #foundation.handleScrimClick', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleScrimClick = td.func(); + const foundation = wrapper.instance().foundation as MDCModalDrawerFoundation; + foundation.handleScrimClick = coerceForTesting<() => void>(td.func()); const scrim = wrapper.childAt(1); scrim.simulate('click'); - td.verify(wrapper.instance().foundation.handleScrimClick(), {times: 1}); + td.verify(foundation.handleScrimClick(), {times: 1}); +}); + +test('handles object refs correctly', () => { + const myRef = React.createRef(); + const wrapper = mount(); + assert.isNotNull(myRef.current); + assert.isNotNull(wrapper.instance().drawerElement.current); +}); + +test('it handles function refs correctly', () => { + const refFn = coerceForTesting<(node: HTMLElement) => void>(td.func()); + const wrapper = mount(); + assert.isNotNull(wrapper.instance().drawerElement.current); + td.verify(refFn(wrapper.instance().drawerElement.current!), {times: 1}); }); test('handles object refs correctly', () => { diff --git a/test/unit/fab/index.test.tsx b/test/unit/fab/index.test.tsx index 290d9d757..9e2edf2b3 100644 --- a/test/unit/fab/index.test.tsx +++ b/test/unit/fab/index.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {mount} from 'enzyme'; // need mount for ripple ref call import Fab from '../../../packages/fab/index'; diff --git a/test/unit/floating-label/index.test.tsx b/test/unit/floating-label/index.test.tsx index b28b17a62..d0a1e2307 100644 --- a/test/unit/floating-label/index.test.tsx +++ b/test/unit/floating-label/index.test.tsx @@ -1,13 +1,19 @@ -import * as React from 'react'; -import * as td from 'testdouble'; +import React from 'react'; +import td from 'testdouble'; import {suite, test} from 'mocha'; import {assert} from 'chai'; import {mount, shallow} from 'enzyme'; import FloatingLabel from '../../../packages/floating-label/index'; +import {MDCFloatingLabelAdapter} from '@material/floating-label/adapter'; import {coerceForTesting} from '../helpers/types'; suite('Floating Label'); +function getAdapter(instance: FloatingLabel): MDCFloatingLabelAdapter { + // @ts-ignore adapter_ property is protected, we need to bypass this check for testing purposes + return instance.foundation.adapter_; +} + test('classNames adds classes', () => { const wrapper = shallow( Test @@ -21,14 +27,14 @@ test('adds text to children', () => { assert.equal(wrapper.text(), 'Test'); }); -test('creates labelElement_', () => { +test('creates labelElement', () => { const wrapper = mount(); - assert.exists(wrapper.instance().labelElement_.current); + assert.exists(wrapper.instance().labelElement.current); }); test('#initializeFoundation creates foundation', () => { const wrapper = shallow(); - assert.exists(wrapper.instance().foundation_); + assert.exists(wrapper.instance().foundation); }); test('initializing with float to true floats the label', () => { @@ -36,7 +42,7 @@ test('initializing with float to true floats the label', () => { assert.isTrue(wrapper.hasClass('mdc-floating-label--float-above')); }); -test('calls handleWidthChange with the offhandleWidthChange of the labelElement_', () => { +test('calls handleWidthChange with the offhandleWidthChange of the labelElement', () => { const handleWidthChange = coerceForTesting<(width: number) => void>(td.func()); const div = document.createElement('div'); // needs to be attached to real DOM to get width @@ -95,7 +101,7 @@ test('on animationend should remove the shake class', () => { test('#adapter.addClass', () => { const wrapper = mount(); - wrapper.instance().foundation_.adapter_.addClass('test-class-name'); + getAdapter(wrapper.instance()).addClass('test-class-name'); assert.isTrue(wrapper.state().classList.has('test-class-name')); }); @@ -105,14 +111,14 @@ test('#adapter.removeClass', () => { classList.add('test-class-name'); wrapper.setState({classList}); assert.isTrue(wrapper.state().classList.has('test-class-name')); - wrapper.instance().foundation_.adapter_.removeClass('test-class-name'); + getAdapter(wrapper.instance()).removeClass('test-class-name'); assert.isFalse(wrapper.state().classList.has('test-class-name')); }); test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); - const foundation = wrapper.instance().foundation_; - foundation.destroy = td.func(); + const foundation = wrapper.instance().foundation; + foundation.destroy = coerceForTesting<() => void>(td.func()); wrapper.unmount(); td.verify(foundation.destroy()); }); diff --git a/test/unit/icon-button/IconToggle.test.tsx b/test/unit/icon-button/IconToggle.test.tsx index 87f39a61f..0396e6abb 100644 --- a/test/unit/icon-button/IconToggle.test.tsx +++ b/test/unit/icon-button/IconToggle.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {IconToggle} from '../../../packages/icon-button/index'; diff --git a/test/unit/icon-button/index.test.tsx b/test/unit/icon-button/index.test.tsx index c5b73ce5f..bdc465180 100644 --- a/test/unit/icon-button/index.test.tsx +++ b/test/unit/icon-button/index.test.tsx @@ -1,9 +1,10 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {shallow} from 'enzyme'; import {IconButtonBase as IconButton} from '../../../packages/icon-button/index'; import {coerceForTesting} from '../helpers/types'; +import {MDCIconButtonToggleEventDetail} from '@material/icon-button/types'; suite('IconButton'); @@ -34,7 +35,7 @@ test('renders anchor tag when isLink is true', () => { test('#foundation.handleClick gets called onClick', () => { const wrapper = shallow>(); - wrapper.instance().foundation.handleClick = td.func(); + wrapper.instance().foundation.handleClick = td.func<() => void>(); wrapper.simulate('click'); td.verify(wrapper.instance().foundation.handleClick(), {times: 1}); }); @@ -62,13 +63,13 @@ test('aria-pressed is set false if passed as prop but on className is not passed test('#get.classes has a class added to state.classList', () => { const wrapper = shallow(); wrapper.setState({classList: new Set(['test-class'])}); - wrapper.hasClass('test-class'); + assert.isTrue(wrapper.hasClass('test-class')); }); test('#adapter.addClass adds a class to state.classList', () => { const wrapper = shallow>(); wrapper.instance().adapter.addClass('test-class'); - wrapper.state().classList.has('test-class'); + assert.isTrue(wrapper.state().classList.has('test-class')); }); test('#adapter.removeClass removes a class to state.classList', () => { @@ -91,7 +92,14 @@ test('#adapter.hasClass returns false if element does not contains class', () => test('#adapter.setAttr sets aria-pressed', () => { const wrapper = shallow>(); - wrapper.instance().adapter.setAttr('aria-pressed', true); - assert.isTrue(wrapper.state()['aria-pressed']); + wrapper.instance().adapter.setAttr('aria-pressed', 'true'); + assert.equal(wrapper.state('aria-pressed'), 'true'); }); +test('#adapter.notifyChange calls props.handleChange', () => { + const handleChange = td.func<(event: MDCIconButtonToggleEventDetail) => void>(); + const wrapper = shallow>(); + const event = {isOn: false}; + wrapper.instance().adapter.notifyChange(event); + td.verify(handleChange(event), {times: 1}); +}); diff --git a/test/unit/index.tsx b/test/unit/index.tsx index 033748dab..c9122d458 100644 --- a/test/unit/index.tsx +++ b/test/unit/index.tsx @@ -1,5 +1,5 @@ -import * as Enzyme from 'enzyme'; -import * as Adapter from 'enzyme-adapter-react-16'; +import Enzyme from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; Enzyme.configure({adapter: new Adapter()}); const context = require.context('.', true, /\.test\.(j|t)sx?$/); context.keys().forEach(context); diff --git a/test/unit/layout-grid/Cell.test.tsx b/test/unit/layout-grid/Cell.test.tsx index 20515b235..716584df4 100644 --- a/test/unit/layout-grid/Cell.test.tsx +++ b/test/unit/layout-grid/Cell.test.tsx @@ -1,6 +1,6 @@ import {assert} from 'chai'; import {shallow} from 'enzyme'; -import * as React from 'react'; +import React from 'react'; import {Cell} from '../../../packages/layout-grid/index'; suite('LayoutGridCell'); diff --git a/test/unit/layout-grid/Grid.test.tsx b/test/unit/layout-grid/Grid.test.tsx index f3c7407ae..a31a071e9 100644 --- a/test/unit/layout-grid/Grid.test.tsx +++ b/test/unit/layout-grid/Grid.test.tsx @@ -1,6 +1,6 @@ import {assert} from 'chai'; import {shallow} from 'enzyme'; -import * as React from 'react'; +import React from 'react'; import {Grid} from '../../../packages/layout-grid/index'; suite('LayoutGridGrid'); diff --git a/test/unit/layout-grid/Row.test.tsx b/test/unit/layout-grid/Row.test.tsx index 4a85f90ed..86d66f3da 100644 --- a/test/unit/layout-grid/Row.test.tsx +++ b/test/unit/layout-grid/Row.test.tsx @@ -1,6 +1,6 @@ import {assert} from 'chai'; import {shallow} from 'enzyme'; -import * as React from 'react'; +import React from 'react'; import {Row} from '../../../packages/layout-grid/index'; suite('LayoutGridRow'); diff --git a/test/unit/line-ripple/index.test.tsx b/test/unit/line-ripple/index.test.tsx index c8bd9dad2..a531f4459 100644 --- a/test/unit/line-ripple/index.test.tsx +++ b/test/unit/line-ripple/index.test.tsx @@ -1,12 +1,18 @@ -import * as React from 'react'; -import * as td from 'testdouble'; +import React from 'react'; +import td from 'testdouble'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import LineRipple from '../../../packages/line-ripple/index'; +import {MDCLineRippleAdapter} from '@material/line-ripple/adapter'; import {coerceForTesting} from '../helpers/types'; suite('LineRipple'); +function getAdapter(instance: LineRipple): MDCLineRippleAdapter { + // @ts-ignore adapter_ property is protected, we need to bypass this check for testing purposes + return instance.foundation_.adapter_; +} + test('classNames adds classes', () => { const wrapper = shallow(); assert.isTrue(wrapper.hasClass('test-class-name')); @@ -38,8 +44,8 @@ test( 'are called when active updates', () => { const wrapper = shallow(); - wrapper.instance().foundation_.activate = td.func(); - wrapper.instance().foundation_.deactivate = td.func(); + wrapper.instance().foundation_.activate = td.func<() => void>(); + wrapper.instance().foundation_.deactivate = td.func<() => void>(); wrapper.setProps({active: true}); td.verify(wrapper.instance().foundation_.activate(), {times: 1}); td.verify(wrapper.instance().foundation_.deactivate(), {times: 0}); @@ -54,7 +60,7 @@ test( '#foundation.setRippleCenter', () => { const wrapper = shallow(); - wrapper.instance().foundation_.setRippleCenter = td.func(); + wrapper.instance().foundation_.setRippleCenter = td.func<(xCoordinate: number) => null>(); wrapper.setProps({rippleCenter: 10}); td.verify(wrapper.instance().foundation_.setRippleCenter(10), {times: 1}); } @@ -62,7 +68,7 @@ test( test('does not call #foundation.setRippleCenter when props.rippleCenter is NaN', () => { const wrapper = shallow(); - wrapper.instance().foundation_.setRippleCenter = td.func(); + wrapper.instance().foundation_.setRippleCenter = td.func<(xCoordinate: number) => null>(); wrapper.setProps({rippleCenter: NaN}); td.verify( wrapper.instance().foundation_.setRippleCenter(td.matchers.anything()), @@ -72,7 +78,7 @@ test('does not call #foundation.setRippleCenter when props.rippleCenter is NaN', test('#adapter.addClass updates state.classList', () => { const wrapper = shallow(); - wrapper.instance().foundation_.adapter_.addClass('test-color-class'); + getAdapter(wrapper.instance()).addClass('test-color-class'); assert.isTrue(wrapper.state().classList.has('test-color-class')); }); @@ -81,7 +87,7 @@ test('#adapter.removeClass updates state.classList', () => { const classList = new Set(); classList.add('test-color-class'); wrapper.setState({classList}); - wrapper.instance().foundation_.adapter_.removeClass('test-color-class'); + getAdapter(wrapper.instance()).removeClass('test-color-class'); assert.isFalse(wrapper.state().classList.has('test-color-class')); }); @@ -90,25 +96,27 @@ test('#adapter.hasClass returns true if exists in classList', () => { const classList = new Set(); classList.add('test-color-class'); wrapper.setState({classList}); - const hasClass = wrapper - .instance() - .foundation_.adapter_.hasClass('test-color-class'); + const hasClass = getAdapter(wrapper.instance()).hasClass('test-color-class'); assert.isTrue(hasClass); }); test('#adapter.setStyle updates style', () => { const wrapper = shallow(); - wrapper.instance().foundation_.adapter_.setStyle('color', 'blue'); + getAdapter(wrapper.instance()).setStyle('color', 'blue'); const style = coerceForTesting(wrapper.state().style); assert.equal(style.color, 'blue'); }); test('onTransitionEnd calls the #foundation.handleTransitionEnd', () => { const wrapper = shallow(); - wrapper.instance().foundation_.handleTransitionEnd = td.func(); - const event = {test: '123'}; + wrapper.instance().foundation_.handleTransitionEnd = td.func<(env: TransitionEvent) => null>(); + const event: React.TransitionEvent = coerceForTesting({ + nativeEvent: { + test: '123', + }, + }); wrapper.simulate('transitionEnd', event); - td.verify(wrapper.instance().foundation_.handleTransitionEnd(event), { + td.verify(wrapper.instance().foundation_.handleTransitionEnd(event.nativeEvent), { times: 1, }); }); @@ -116,14 +124,14 @@ test('onTransitionEnd calls the #foundation.handleTransitionEnd', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); const foundation = wrapper.instance().foundation_; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy()); }); test('#adapter.setStyle updates style names to camel case', () => { const wrapper = shallow(); - wrapper.instance().foundation_.adapter_.setStyle('transform-origin', 25); + getAdapter(wrapper.instance()).setStyle('transform-origin', '25'); const style = coerceForTesting(wrapper.state().style); assert.equal(style.transformOrigin, 25); // @ts-ignore diff --git a/test/unit/linear-progress/index.test.tsx b/test/unit/linear-progress/index.test.tsx index 984913069..c00980222 100644 --- a/test/unit/linear-progress/index.test.tsx +++ b/test/unit/linear-progress/index.test.tsx @@ -1,7 +1,7 @@ import {assert} from 'chai'; import {shallow, mount} from 'enzyme'; -import * as React from 'react'; -import * as td from 'testdouble'; +import React from 'react'; +import td from 'testdouble'; import LinearProgress from '../../../packages/linear-progress/index'; suite('LinearProgress'); @@ -68,7 +68,7 @@ test('Keeps custom props', () => { test('#foundation.init gets called when the component mounts', () => { const wrapper = mount(); const instance = wrapper.instance(); - instance.foundation.init = td.func(); + instance.foundation.init = td.func<() => void>(); instance.componentDidMount(); td.verify(instance.foundation.init(), {times: 1}); }); @@ -76,7 +76,7 @@ test('#foundation.init gets called when the component mounts', () => { test('#foundation.setBuffer gets called when the component mounts', () => { const wrapper = mount(); const instance = wrapper.instance(); - instance.foundation.setBuffer = td.func(); + instance.foundation.setBuffer = td.func<(value: number) => void>(); instance.componentDidMount(); td.verify(instance.foundation.setBuffer(0.1), {times: 1}); }); @@ -84,7 +84,7 @@ test('#foundation.setBuffer gets called when the component mounts', () => { test('#foundation.setDeterminate gets called when the component mounts', () => { const wrapper = mount(); const instance = wrapper.instance(); - instance.foundation.setDeterminate = td.func(); + instance.foundation.setDeterminate = td.func<(isDeterminate: boolean) => void>(); instance.componentDidMount(); td.verify(instance.foundation.setDeterminate(false), {times: 1}); }); @@ -92,7 +92,7 @@ test('#foundation.setDeterminate gets called when the component mounts', () => { test('#foundation.setProgress gets called when the component mounts', () => { const wrapper = mount(); const instance = wrapper.instance(); - instance.foundation.setProgress = td.func(); + instance.foundation.setProgress = td.func<(value: number) => null>(); instance.componentDidMount(); td.verify(instance.foundation.setProgress(0.1), {times: 1}); }); @@ -100,7 +100,7 @@ test('#foundation.setProgress gets called when the component mounts', () => { test('#foundation.setReverse gets called when the component mounts', () => { const wrapper = mount(); const instance = wrapper.instance(); - instance.foundation.setReverse = td.func(); + instance.foundation.setReverse = td.func<(isReversed: boolean) => void>(); instance.componentDidMount(); td.verify(instance.foundation.setReverse(true), {times: 1}); }); @@ -108,49 +108,49 @@ test('#foundation.setReverse gets called when the component mounts', () => { test('#foundation.close gets called when the component mounts', () => { const wrapper = mount(); const instance = wrapper.instance(); - instance.foundation.close = td.func(); + instance.foundation.close = td.func<() => void>(); instance.componentDidMount(); td.verify(instance.foundation.close(), {times: 1}); }); test('#foundation.setBuffer gets called when props.buffer updates', () => { const wrapper = mount(); - wrapper.instance().foundation.setBuffer = td.func(); + wrapper.instance().foundation.setBuffer = td.func<(value: number) => void>(); wrapper.setProps({buffer: 0.2}); td.verify(wrapper.instance().foundation.setBuffer(0.2), {times: 1}); }); test('#foundation.close gets called when props.closed updates', () => { const wrapper = mount(); - wrapper.instance().foundation.close = td.func(); + wrapper.instance().foundation.close = td.func<() => void>(); wrapper.setProps({closed: true}); td.verify(wrapper.instance().foundation.close(), {times: 1}); }); test('#foundation.open gets called when props.closed updates', () => { const wrapper = mount(); - wrapper.instance().foundation.open = td.func(); + wrapper.instance().foundation.open = td.func<() => void>(); wrapper.setProps({closed: false}); td.verify(wrapper.instance().foundation.open(), {times: 1}); }); test('#foundation.setDeterminate gets called when props.indeterminate updates', () => { const wrapper = mount(); - wrapper.instance().foundation.setDeterminate = td.func(); + wrapper.instance().foundation.setDeterminate = td.func<(isDeterminate: boolean) => void>(); wrapper.setProps({indeterminate: true}); td.verify(wrapper.instance().foundation.setDeterminate(false), {times: 1}); }); test('#foundation.setProgress gets called when props.progress updates', () => { const wrapper = mount(); - wrapper.instance().foundation.setProgress = td.func(); + wrapper.instance().foundation.setProgress = td.func<(value: number) => void>(); wrapper.setProps({progress: 0.2}); td.verify(wrapper.instance().foundation.setProgress(0.2), {times: 1}); }); test('#foundation.setReverse gets called when props.reversed updates', () => { const wrapper = mount(); - wrapper.instance().foundation.setReverse = td.func(); + wrapper.instance().foundation.setReverse = td.func<(isReversed: boolean) => void>(); wrapper.setProps({reversed: true}); td.verify(wrapper.instance().foundation.setReverse(true), {times: 1}); }); @@ -158,7 +158,7 @@ test('#foundation.setReverse gets called when props.reversed updates', () => { test('#foundation.destroy gets called when the component unmounts', () => { const wrapper = mount(); const instance = wrapper.instance(); - instance.foundation.destroy = td.func(); + instance.foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(instance.foundation.destroy(), {times: 1}); }); diff --git a/test/unit/list/ListDivider.test.tsx b/test/unit/list/ListDivider.test.tsx index e7e2b3143..71f430542 100644 --- a/test/unit/list/ListDivider.test.tsx +++ b/test/unit/list/ListDivider.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {ListDivider} from '../../../packages/list/index'; diff --git a/test/unit/list/ListGroup.test.tsx b/test/unit/list/ListGroup.test.tsx index e19f33ffb..1a1c2eb71 100644 --- a/test/unit/list/ListGroup.test.tsx +++ b/test/unit/list/ListGroup.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {ListGroup} from '../../../packages/list/index'; diff --git a/test/unit/list/ListGroupSubheader.test.tsx b/test/unit/list/ListGroupSubheader.test.tsx index b87d2db9d..615c60748 100644 --- a/test/unit/list/ListGroupSubheader.test.tsx +++ b/test/unit/list/ListGroupSubheader.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {ListGroupSubheader} from '../../../packages/list/index'; diff --git a/test/unit/list/ListItem.test.tsx b/test/unit/list/ListItem.test.tsx index 23d601dfa..addbd8252 100644 --- a/test/unit/list/ListItem.test.tsx +++ b/test/unit/list/ListItem.test.tsx @@ -1,8 +1,8 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; +import td from 'testdouble'; import {mount, shallow} from 'enzyme'; -import * as td from 'testdouble'; -import {ListItem} from '../../../packages/list/index'; +import {ListItemBase as ListItem, ListItemState} from '../../../packages/list/ListItem'; import {coerceForTesting} from '../helpers/types'; suite('ListItem'); @@ -12,61 +12,49 @@ test('classNames adds classes', () => { assert.isTrue(wrapper.hasClass('test-class-name')); }); -test('classNamesFromList adds classes', () => { - const wrapper = shallow( -
meow
- ); - assert.isTrue(wrapper.hasClass('test-class-name')); +test('has mdc-list-item classname', () => { + const wrapper = shallow(
meow
); + assert.isTrue(wrapper.hasClass('mdc-list-item')); }); -test('attributesFromList adds props', () => { - const wrapper = shallow(
meow
); - assert.equal(wrapper.props().tabIndex, 0); +test('has activated class if props.activated = true', () => { + const wrapper = shallow(
meow
); + assert.isTrue(wrapper.hasClass('mdc-list-item--activated')); }); -test('calls focus when props.shouldFocus changes from false to true', () => { - const wrapper = mount>(
meow
); - wrapper.instance().focus = coerceForTesting<() => void>(td.func()); - wrapper.setProps({shouldFocus: true}); - td.verify(wrapper.instance().focus(), {times: 1}); +test('has activated class if props.disabled = true', () => { + const wrapper = shallow(
meow
); + assert.isTrue(wrapper.hasClass('mdc-list-item--disabled')); }); -test('calls followHref when props.shouldFollowHref changes from false to true', () => { - const wrapper = mount>(
meow
); - wrapper.instance().followHref = coerceForTesting<() => void>(td.func()); - wrapper.setProps({shouldFollowHref: true}); - td.verify(wrapper.instance().followHref(), {times: 1}); +test('has selected class if props.selected = true', () => { + const wrapper = shallow(
meow
); + assert.isTrue(wrapper.hasClass('mdc-list-item--selected')); }); -test('calls toggleCheckbox when props.shouldToggleCheckbox changes from false to true', () => { - const wrapper = mount>(
meow
); - wrapper.instance().toggleCheckbox = coerceForTesting<() => void>(td.func()); - wrapper.setProps({shouldToggleCheckbox: true}); - td.verify(wrapper.instance().toggleCheckbox(), {times: 1}); +test('has role=checkbox if props.checkboxList = true', () => { + const wrapper = shallow(
meow
); + assert.equal(wrapper.props().role, 'checkbox'); }); -test('#focus focuses the listItemElement_', () => { - const wrapper = mount>(
meow
); - wrapper.instance().listItemElement_.current!.focus = coerceForTesting<() => void>(td.func()); - wrapper.instance().focus(); - td.verify(wrapper.instance().listItemElement_.current!.focus(), {times: 1}); +test('has role=radio if props.radioList = true', () => { + const wrapper = shallow(
meow
); + assert.equal(wrapper.props().role, 'radio'); }); -test('#followHref simulates a click on the listItemElement_ if it has href', () => { - const wrapper = mount>(
meow
); - wrapper.instance().listItemElement_.current!.href = 'https://google.com'; - wrapper.instance().listItemElement_.current!.click = coerceForTesting<() => void>(td.func()); - wrapper.instance().followHref(); - td.verify(wrapper.instance().listItemElement_.current!.click(), {times: 1}); +test('has role=menu if props.role = menu', () => { + const wrapper = shallow(
meow
); + assert.equal(wrapper.props().role, 'menu'); }); -test('passes props.childrenTabIndex to children as props.tabIndex', () => { - const wrapper = mount( - -
- - ); - assert.equal(wrapper.find('.list-item-child').props().tabIndex, 2); +test('is anchor tag if tag=a', () => { + const wrapper = mount>(
meow
); + assert.equal(wrapper.find('a').length, 1); +}); + +test('listitem can have href tag', () => { + const wrapper = mount>(
meow
); + assert.equal(wrapper.props().href, 'google.com'); }); test('renders a list item with default tag', () => { @@ -88,3 +76,73 @@ test('renders a list item with an anchor tag', () => { const wrapper = shallow(
Test
); assert.equal(wrapper.type(), 'a'); }); + +test('componentWillUnmount calls props.onDestroy()', () => { + const onDestroy = td.func<(index: number) => void>(); + const wrapper = mount(
Test
); + wrapper.unmount(); + td.verify(onDestroy(-1), {times: 1}); +}); + +test('handleClick calls props.handleClick and props.onClick', () => { + const onClick = td.func<(evt: {}) => void>(); + const handleClick = td.func<(evt: {}, index: number) => void>(); + const wrapper = shallow(
Test
); + const evt = {}; + wrapper.simulate('click', evt); + td.verify(onClick(evt), {times: 1}); + td.verify(handleClick(evt, -1), {times: 1}); +}); + +test('handleKeyDown calls props.handleKeyDown and props.onKeyDown', () => { + const onKeyDown = td.func<(evt: {}) => void>(); + const handleKeyDown = td.func<(evt: {}, index: number) => void>(); + const wrapper = shallow(
Test
); + const evt = {}; + wrapper.simulate('keydown', evt); + td.verify(onKeyDown(evt), {times: 1}); + td.verify(handleKeyDown(evt, -1), {times: 1}); +}); + +test('handleFocus calls props.handleFocus and props.onFocus', () => { + const onFocus = td.func<(evt: {}) => void>(); + const handleFocus = td.func<(evt: {}, index: number) => void>(); + const wrapper = shallow(
Test
); + const evt = {}; + wrapper.simulate('focus', evt); + td.verify(onFocus(evt), {times: 1}); + td.verify(handleFocus(evt, -1), {times: 1}); +}); + +test('handleBlur calls props.handleBlur and props.onBlur', () => { + const onBlur = td.func<(evt: {}) => void>(); + const handleBlur = td.func<(evt: {}, index: number) => void>(); + const wrapper = shallow(
Test
); + const evt = {}; + wrapper.simulate('blur', evt); + td.verify(onBlur(evt), {times: 1}); + td.verify(handleBlur(evt, -1), {times: 1}); +}); + +test('renders with tabIndex based off of props.getListItemInitialTabIndex', () => { + const getListItemInitialTabIndex = td.func<(index: number) => number>(); + td.when(getListItemInitialTabIndex(-1)).thenReturn(2); + const wrapper = mount(Test); + assert.equal(coerceForTesting(wrapper.state()).tabIndex, 2); +}); + +test('if props.tabIndex updates, then it changes state.tabIndex', () => { + const wrapper = mount(Test); + wrapper.setProps({tabIndex: 1}); + assert.equal(coerceForTesting(wrapper.state()).tabIndex, 1); +}); + +test('get listElements', () => { + const wrapper = mount(
+ Test + Test + Test +
); + const {listElements} = coerceForTesting(wrapper.childAt(0).instance()); + assert.equal(listElements.length, 3); +}); diff --git a/test/unit/list/ListItemGraphic.test.tsx b/test/unit/list/ListItemGraphic.test.tsx index a31c3052e..3ac344f6b 100644 --- a/test/unit/list/ListItemGraphic.test.tsx +++ b/test/unit/list/ListItemGraphic.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {ListItemGraphic} from '../../../packages/list/index'; @@ -16,17 +16,3 @@ test('has mdc-list-item__graphic class', () => { const wrapper = shallow(} />); assert.isTrue(wrapper.hasClass('mdc-list-item__graphic')); }); - -test('has tabIndex of props.tabIndex if specified and tabbableOnListItemFocus is true', () => { - const wrapper = shallow( - } tabIndex={3} tabbableOnListItemFocus /> - ); - assert.equal(wrapper.find('.mdc-list-item__graphic').props().tabIndex, 3); -}); - -test('has tabIndex of -1 if tabbableOnListItemFocus is false', () => { - const wrapper = shallow( - } childrenTabIndex={3} /> - ); - assert.equal(wrapper.find('.mdc-list-item__graphic').props().tabIndex, -1); -}); diff --git a/test/unit/list/ListItemMeta.test.tsx b/test/unit/list/ListItemMeta.test.tsx index 376fde1e0..682d4fc42 100644 --- a/test/unit/list/ListItemMeta.test.tsx +++ b/test/unit/list/ListItemMeta.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {ListItemMeta} from '../../../packages/list/index'; @@ -38,17 +38,3 @@ test('renders element if meta is an element', () => { const wrapper = shallow(} />); assert.equal(wrapper.find('.mdc-list-item__meta').type(), 'button'); }); - -test('has tabIndex of props.tabIndex if specified and tabbableOnListItemFocus is true', () => { - const wrapper = shallow( - } tabIndex={3} tabbableOnListItemFocus /> - ); - assert.equal(wrapper.find('.mdc-list-item__meta').props().tabIndex, 3); -}); - -test('has tabIndex of -1 if tabbableOnListItemFocus is false', () => { - const wrapper = shallow( - } childrenTabIndex={3} /> - ); - assert.equal(wrapper.find('.mdc-list-item__meta').props().tabIndex, -1); -}); diff --git a/test/unit/list/ListItemText.test.tsx b/test/unit/list/ListItemText.test.tsx index db3eb3472..3fa986e50 100644 --- a/test/unit/list/ListItemText.test.tsx +++ b/test/unit/list/ListItemText.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {ListItemText} from '../../../packages/list/index'; @@ -40,17 +40,3 @@ test('renders primary and secondary text if text are elements', () => { assert.exists(wrapper.find('.mdc-list-item__primary-text')); assert.exists(wrapper.find('.mdc-list-item__secondary-text')); }); - -test('has tabIndex of props.tabIndex if specified and tabbableOnListItemFocus is true', () => { - const wrapper = shallow( - - ); - assert.equal(wrapper.find('.mdc-list-item__text').props().tabIndex, 3); -}); - -test('has tabIndex of -1 if tabbableOnListItemFocus is false', () => { - const wrapper = shallow( - - ); - assert.equal(wrapper.find('.mdc-list-item__text').props().tabIndex, -1); -}); diff --git a/test/unit/list/index.test.tsx b/test/unit/list/index.test.tsx index bc57390e3..d28ad2b2c 100644 --- a/test/unit/list/index.test.tsx +++ b/test/unit/list/index.test.tsx @@ -1,19 +1,28 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {shallow, mount} from 'enzyme'; import List, { ListItem, ListItemProps, // eslint-disable-line no-unused-vars } from '../../../packages/list/index'; import {coerceForTesting} from '../helpers/types'; +import {MDCListIndex} from '@material/list/types'; suite('List'); -const children: (key?: number) => React.ReactElement> - = (key: number = 0) => (
meow
); +const children = (opts?: { + key?: number, + hasCheckbox?: boolean + }): React.ReactElement> => ( + +
meow
+ {opts && opts.hasCheckbox ? : null} +
+); -const threeChildren: () => React.ReactElement>[] - = () => [0, 1, 2].map((key) => children(key)); +const threeChildren = (): React.ReactElement>[] => ( + [0, 1, 2].map((key) => children({key})) +); test('creates foundation', () => { const wrapper = shallow( @@ -25,14 +34,14 @@ test('creates foundation', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow({children()}); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation.destroy = coerceForTesting<() => void>(td.func()); wrapper.unmount(); td.verify(foundation.destroy()); }); test('calls foundation.setSingleSelection when props.singleSelection changes from false to true', () => { const wrapper = mount({children()}); - wrapper.instance().foundation.setSingleSelection = td.func(); + wrapper.instance().foundation.setSingleSelection = coerceForTesting<(arg: boolean) => void>(td.func()); wrapper.setProps({singleSelection: true}); td.verify(wrapper.instance().foundation.setSingleSelection(true), { times: 1, @@ -41,7 +50,7 @@ test('calls foundation.setSingleSelection when props.singleSelection changes fro test('calls foundation.setSingleSelection when props.singleSelection changes from true to false', () => { const wrapper = mount({children()}); - wrapper.instance().foundation.setSingleSelection = td.func(); + wrapper.instance().foundation.setSingleSelection = coerceForTesting<(arg: boolean) => void>(td.func()); wrapper.setProps({singleSelection: false}); td.verify(wrapper.instance().foundation.setSingleSelection(false), { times: 1, @@ -50,28 +59,28 @@ test('calls foundation.setSingleSelection when props.singleSelection changes fro test('calls foundation.setWrapFocus when props.wrapFocus changes from false to true', () => { const wrapper = mount({children()}); - wrapper.instance().foundation.setWrapFocus = td.func(); + wrapper.instance().foundation.setWrapFocus = coerceForTesting<(arg: boolean) => void>(td.func()); wrapper.setProps({wrapFocus: true}); td.verify(wrapper.instance().foundation.setWrapFocus(true), {times: 1}); }); test('calls foundation.setWrapFocus when props.wrapFocus changes from true to false', () => { const wrapper = mount({children()}); - wrapper.instance().foundation.setWrapFocus = td.func(); + wrapper.instance().foundation.setWrapFocus = coerceForTesting<(arg: boolean) => void>(td.func()); wrapper.setProps({wrapFocus: false}); td.verify(wrapper.instance().foundation.setWrapFocus(false), {times: 1}); }); test('calls foundation.setSelectedIndex when props.selectedIndex changes', () => { const wrapper = mount({children()}); - wrapper.instance().foundation.setSelectedIndex = td.func(); + wrapper.instance().foundation.setSelectedIndex = coerceForTesting<(arg: MDCListIndex) => void>(td.func()); wrapper.setProps({selectedIndex: 1}); td.verify(wrapper.instance().foundation.setSelectedIndex(1), {times: 1}); }); test('calls foundation.setVerticalOrientation when \'aria-orientation\' changes from vertical to horizontal', () => { const wrapper = mount({children()}); - wrapper.instance().foundation.setVerticalOrientation = td.func(); + wrapper.instance().foundation.setVerticalOrientation = coerceForTesting<(arg: boolean) => void>(td.func()); wrapper.setProps({'aria-orientation': 'horizontal'}); td.verify(wrapper.instance().foundation.setVerticalOrientation(false), { times: 1, @@ -80,7 +89,7 @@ test('calls foundation.setVerticalOrientation when \'aria-orientation\' changes test('calls foundation.setVerticalOrientation when \'aria-orientation\' changes from horizontal to vertical', () => { const wrapper = mount({children()}); - wrapper.instance().foundation.setVerticalOrientation = td.func(); + wrapper.instance().foundation.setVerticalOrientation = coerceForTesting<(arg: boolean) => void>(td.func()); wrapper.setProps({'aria-orientation': 'vertical'}); td.verify(wrapper.instance().foundation.setVerticalOrientation(true), { times: 1, @@ -132,266 +141,318 @@ test('#adapter.getListItemCount returns correct number of list items if List has assert.equal(wrapper.instance().adapter.getListItemCount(), 3); }); -test('#adapter.setAttributeForElementIndex updates state.listItemAttributes', () => { +test('#adapter.setAttributeForElementIndex calls setAttribute on listItem', () => { const wrapper = mount({children()}); - wrapper.instance().adapter.setAttributeForElementIndex(1, 'tabindex', '0'); - assert.equal(wrapper.state().listItemAttributes[1]['tabIndex'], 0); + wrapper.instance().listElements[0].setAttribute = coerceForTesting<(key: string, value: string) => void>(td.func()); + wrapper.instance().adapter.setAttributeForElementIndex(0, 'role', 'menu'); + td.verify(wrapper.instance().listElements[0].setAttribute('role', 'menu'), {times: 1}); }); -test('#adapter.removeAttributeForElementIndex removes attribute from state.listItemAttributes if it exists', () => { - const wrapper = mount({children()}); - wrapper.setState({listItemAttributes: {1: {tabIndex: 0}}}); - wrapper.instance().adapter.removeAttributeForElementIndex(1, 'tabindex'); - assert.isFalse( - wrapper.state().listItemAttributes[1].hasOwnProperty('tabIndex') - ); +test('#adapter.setAttributeForElementIndex call nothing when no children exist', () => { + const wrapper = mount(); + assert.doesNotThrow(() => wrapper.instance().adapter.setAttributeForElementIndex(0, 'role', 'menu')); }); -test('#adapter.removeAttributeForElementIndex does nothing if attribute is not in state.listItemAttributes', () => { +test('#adapter.addClassForElementIndex adds classes to state', () => { const wrapper = mount({children()}); - wrapper.instance().adapter.removeAttributeForElementIndex(1, 'tabindex'); - assert.isFalse(wrapper.state().listItemAttributes.hasOwnProperty(1)); + wrapper.instance().adapter.addClassForElementIndex = + coerceForTesting<(index: number, className: string) => void>(td.func()); + wrapper.instance().adapter.addClassForElementIndex(0, 'class4321'); + assert.isTrue(wrapper.state().listItemClassNames[0].includes('class4321')); }); -test('#adapter.addClassForElementIndex updates state.listItemClassNames if no classes have been added', () => { - const wrapper = mount({children()}); - wrapper.instance().adapter.addClassForElementIndex(1, 'class1'); - assert.isTrue(wrapper.state().listItemClassNames[1].indexOf('class1') >= 0); +test('#adapter.addClassForElementIndex adds multiple classes to state', () => { + const wrapper = mount( +
meow
+
); + wrapper.instance().adapter.addClassForElementIndex = + coerceForTesting<(index: number, className: string) => void>(td.func()); + wrapper.instance().adapter.addClassForElementIndex(0, 'class4321'); + wrapper.instance().adapter.addClassForElementIndex(0, 'class987'); + assert.isTrue(wrapper.state().listItemClassNames[0].includes('class4321')); + assert.isTrue(wrapper.state().listItemClassNames[0].includes('class987')); }); -test('#adapter.addClassForElementIndex updates state.listItemClassNames if other classes have been added', () => { - const wrapper = mount({children()}); - wrapper.state().listItemClassNames[1] = ['test']; - wrapper.instance().adapter.addClassForElementIndex(1, 'class1'); - assert.isTrue(wrapper.state().listItemClassNames[1].indexOf('class1') >= 0); - assert.isTrue(wrapper.state().listItemClassNames[1].indexOf('test') >= 0); +test('#adapter.removeClassForElementIndex removes classname from state.listItemClassNames', () => { + const wrapper = mount( +
meow
+
); + wrapper.setState({listItemClassNames: { + 0: ['class987', 'class4321'], + }}); + wrapper.instance().adapter.removeClassForElementIndex = + coerceForTesting<(index: number, className: string) => void>(td.func()); + wrapper.instance().adapter.removeClassForElementIndex(0, 'class4321'); + assert.isFalse(wrapper.state().listItemClassNames[0].includes('class4321')); + assert.isTrue(wrapper.state().listItemClassNames[0].includes('class987')); +}); + +test('#adapter.setTabIndexForListItemChildren updates the button and anchor tag to have tabindex=0', () => { + const wrapper = mount( + + + link + + ); + wrapper.instance().adapter.setTabIndexForListItemChildren(0, '0'); + const listItem = wrapper.childAt(0).childAt(0); + assert.isTrue(listItem.find('a').html().includes('tabindex="0"')); + assert.isTrue(listItem.find('button').html().includes('tabindex="0"')); }); -test('#adapter.removeClassForElementIndex removes class from state.listItemClassNames if it exists', () => { +test('#adapter.focusItemAtIndex calls focus on the listitem', () => { const wrapper = mount({children()}); - wrapper.state().listItemClassNames[1] = ['class1']; - wrapper.instance().adapter.removeClassForElementIndex(1, 'class1'); - assert.isFalse(wrapper.state().listItemClassNames[1].indexOf('class1') >= 0); + (wrapper.instance().listElements[0] as HTMLElement).focus + = coerceForTesting<(opts?: any) => void>(td.func()); + wrapper.instance().adapter.focusItemAtIndex(0); + td.verify((wrapper.instance().listElements[0] as HTMLElement).focus(), {times: 1}); }); -test('#adapter.removeClassForElementIndex does nothing if class is not in state.listItemClassNames', () => { - const wrapper = mount({children()}); - wrapper.state().listItemClassNames[1] = []; - wrapper.instance().adapter.removeClassForElementIndex(1, 'class1'); - assert.isFalse(wrapper.state().listItemClassNames[1].indexOf('class1') >= 0); +test('#adapter.focusItemAtIndex call nothing when no children exist', () => { + const wrapper = mount(); + assert.doesNotThrow(() => wrapper.instance().adapter.focusItemAtIndex(0)); +}); + +test('#adapter.setCheckedCheckboxOrRadioAtIndex does not throw', () => { + const wrapper = shallow({children()}); + assert.doesNotThrow(() => wrapper.instance().adapter.setCheckedCheckboxOrRadioAtIndex(0, true)); }); -test('#adapter.removeClassForElementIndex does nothing if index is not in state.listItemClassNames', () => { +test('#adapter.hasCheckboxAtIndex returns false with no checkbox', () => { const wrapper = mount({children()}); - wrapper.instance().adapter.removeClassForElementIndex(1, 'class1'); - assert.isFalse(wrapper.state().listItemClassNames.hasOwnProperty(1)); + assert.isFalse(wrapper.instance().adapter.hasCheckboxAtIndex(0)); }); -test('#adapter.setTabIndexForListItemChildren updates state.listItemChildrenTabIndex', () => { +test('#adapter.hasCheckboxAtIndex returns true with checkbox', () => { + const wrapper = mount( + + + + ); + assert.isTrue(wrapper.instance().adapter.hasCheckboxAtIndex(0)); +}); + +test('#adapter.hasRadioAtIndex returns false with no checkbox', () => { const wrapper = mount({children()}); - // wrapper.state().listItemClassNames[1] = -1; - wrapper.instance().adapter.setTabIndexForListItemChildren(1, 0); - assert.equal(wrapper.state().listItemChildrenTabIndex[1], 0); + assert.isFalse(wrapper.instance().adapter.hasRadioAtIndex(0)); }); -test('#adapter.focusItemAtIndex sets state.focusListItemAtIndex', () => { - const wrapper = shallow({children()}); - wrapper.instance().adapter.focusItemAtIndex(1); - assert.equal(wrapper.state().focusListItemAtIndex, 1); +test('#adapter.hasRadioAtIndex returns true with checkbox', () => { + const wrapper = mount( + + + + ); + assert.isTrue(wrapper.instance().adapter.hasRadioAtIndex(0)); }); -test('#adapter.followHref sets state.followHrefAtIndex', () => { - const wrapper = shallow({children()}); - wrapper.instance().adapter.followHref(1); - assert.equal(wrapper.state().followHrefAtIndex, 1); +test('#adapter.isCheckboxCheckedAtIndex returns false with a non-checked checkbox', () => { + const wrapper = mount( + + + + ); + assert.isFalse(wrapper.instance().adapter.isCheckboxCheckedAtIndex(0)); }); -test('#adapter.toggleCheckbox sets state.toggleCheckboxAtIndex', () => { - const wrapper = shallow({children()}); - wrapper.instance().adapter.toggleCheckbox(1); - assert.equal(wrapper.state().toggleCheckboxAtIndex, 1); +test('#adapter.isCheckboxCheckedAtIndex returns true with a checked checkbox', () => { + const wrapper = mount( + + {/* empty onChange to avoid a warning */} + {}} /> + + ); + assert.isTrue(wrapper.instance().adapter.isCheckboxCheckedAtIndex(0)); +}); + +test('#adapter.isFocusInsideList returns true if the list element has focus inside', () => { + const div = document.createElement('div'); + // needs to be attached to real DOM to get width + // https://github.com/airbnb/enzyme/issues/1525 + document.body.append(div); + const options = {attachTo: div}; + const wrapper = mount( + + + + , options); + wrapper.instance().listElements[0].querySelector('button')!.focus(); + assert.isTrue(wrapper.instance().adapter.isFocusInsideList()); + div.remove(); +}); + +test('#adapter.isFocusInsideList returns true if the list element has focus inside', () => { + const wrapper = mount( + + + + ); + assert.isFalse(wrapper.instance().adapter.isFocusInsideList()); +}); + +test('#adapter.notifyAction calls props.handleSelect with args', () => { + const handleSelect = td.func<(selectedIndex: number, selected: MDCListIndex) => void>(); + const wrapper = mount( + + + + ); + wrapper.instance().adapter.notifyAction(0); + td.verify(handleSelect(0, -1), {times: 1}); +}); + +test('renders with mdc-list class', () => { + const wrapper = shallow({children}); + assert.isTrue(wrapper.hasClass('mdc-list')); +}); + +test('renders with className', () => { + const wrapper = shallow({children}); + assert.isTrue(wrapper.hasClass('test-class')); + assert.isTrue(wrapper.hasClass('mdc-list')); +}); + +test('renders with mdc-list--non-interactive when non-interactive', () => { + const wrapper = shallow({children}); + assert.isTrue(wrapper.hasClass('mdc-list--non-interactive')); + assert.isTrue(wrapper.hasClass('mdc-list')); +}); + +test('renders with mdc-list--dense when dense', () => { + const wrapper = shallow({children}); + assert.isTrue(wrapper.hasClass('mdc-list--dense')); + assert.isTrue(wrapper.hasClass('mdc-list')); +}); + +test('renders with mdc-list--avatar-list when avatar-list', () => { + const wrapper = shallow({children}); + assert.isTrue(wrapper.hasClass('mdc-list--avatar-list')); + assert.isTrue(wrapper.hasClass('mdc-list')); +}); + +test('renders with mdc-list--two-line when two-line', () => { + const wrapper = shallow({children}); + assert.isTrue(wrapper.hasClass('mdc-list--two-line')); + assert.isTrue(wrapper.hasClass('mdc-list')); +}); + +test('renders with role=group if props.checkboxList', () => { + const wrapper = shallow({children}); + assert.equal(wrapper.props().role, 'group'); +}); + +test('renders with role=radiogroup if props.radioList', () => { + const wrapper = shallow({children}); + assert.equal(wrapper.props().role, 'radiogroup'); +}); + +test('renders with role=menu if props.role=menu', () => { + const wrapper = shallow({children}); + assert.equal(wrapper.props().role, 'menu'); +}); + +test('renders with role=menu if props.role=menu and props.checkboxList', () => { + const wrapper = shallow({children}); + assert.equal(wrapper.props().role, 'menu'); +}); + +test('#onDestroy removes item from state.listItemClassNames', () => { + const wrapper = mount( +
meow
+
); + wrapper.setState({listItemClassNames: {0: ['test']}}); + wrapper.instance().onDestroy(0); + assert.notExists(wrapper.state().listItemClassNames[0]); }); test('#handleKeyDown calls #foudation.handleKeydown', () => { const wrapper = shallow({children()}); - wrapper.instance().foundation.handleKeydown = td.func(); + wrapper.instance().foundation.handleKeydown + = coerceForTesting<(evt: KeyboardEvent, isItem: boolean, itemIndex: number) => void>(td.func()); const evt = coerceForTesting({persist: () => {}}); wrapper.instance().handleKeyDown(evt, 1); - td.verify(wrapper.instance().foundation.handleKeydown(evt, true, 1), { + td.verify(wrapper.instance().foundation.handleKeydown(evt.nativeEvent, true, 1), { times: 1, }); }); -test('#handleKeyDown calls #props.handleSelect if key is enter', () => { - const handleSelect = coerceForTesting<(selectedIndex: number) => void>(td.func()); - const wrapper = shallow({children()}); - const evt = coerceForTesting({persist: () => {}, key: 'Enter'}); - wrapper.instance().handleKeyDown(evt, 1); - td.verify(handleSelect(1), {times: 1}); -}); - test('#handleClick calls #foudation.handleClick', () => { const wrapper = shallow({children()}); const target = {type: 'span'}; const evt = coerceForTesting>({target}); - wrapper.instance().foundation.handleClick = td.func(); + wrapper.instance().foundation.handleClick + = coerceForTesting<(index: number, toggleCheckbox: boolean) => void>(td.func()); wrapper.instance().handleClick(evt, 1); td.verify(wrapper.instance().foundation.handleClick(1, false), {times: 1}); }); -test('#handleClick calls #props.handleSelect', () => { - const handleSelect = coerceForTesting<(selectedIndex: number) => void>(td.func()); - const target = {type: 'span'}; - const evt = coerceForTesting>({target}); - const wrapper = shallow({children()}); - wrapper.instance().handleClick(evt, 1); - td.verify(handleSelect(1), {times: 1}); -}); - test('#handleFocus calls #foudation.handleFocusIn', () => { const wrapper = shallow({children()}); - wrapper.instance().foundation.handleFocusIn = td.func(); + wrapper.instance().foundation.handleFocusIn + = coerceForTesting<(e: FocusEvent, itemIndex: number) => void>(td.func()); const evt = coerceForTesting({}); wrapper.instance().handleFocus(evt, 1); - td.verify(wrapper.instance().foundation.handleFocusIn(evt, 1), {times: 1}); + td.verify(wrapper.instance().foundation.handleFocusIn(evt.nativeEvent, 1), {times: 1}); }); test('#handleBlur calls #foudation.handleFocusOut', () => { const wrapper = shallow({children()}); - wrapper.instance().foundation.handleFocusOut = td.func(); + wrapper.instance().foundation.handleFocusOut + = coerceForTesting<(e: FocusEvent, itemIndex: number) => void>(td.func()); const evt = coerceForTesting({}); wrapper.instance().handleBlur(evt, 1); - td.verify(wrapper.instance().foundation.handleFocusOut(evt, 1), { + td.verify(wrapper.instance().foundation.handleFocusOut(evt.nativeEvent, 1), { times: 1, }); }); -test('#renderListItem renders default list item at index 0', () => { +test('renders 3 list items', () => { const wrapper = mount( {threeChildren()} ); - const listItemProps = wrapper.children().props().children[0].props; - assert.isFalse(listItemProps.shouldFocus); - assert.isFalse(listItemProps.shouldFollowHref); - assert.isFalse(listItemProps.shouldToggleCheckbox); - assert.equal(listItemProps.attributesFromList['tabIndex'], 0); - assert.isEmpty(listItemProps.classNamesFromList); - assert.equal(listItemProps.childrenTabIndex, -1); + assert.equal(wrapper.childAt(0).children().length, 3); }); -test('#renderListItem renders default list item at index not 0', () => { +test('renders list items with tabindex=-1 and first with tabindex=0', () => { const wrapper = mount( {threeChildren()} ); - const listItemProps = wrapper.children().props().children[1].props; - assert.isFalse(listItemProps.shouldFocus); - assert.isFalse(listItemProps.shouldFollowHref); - assert.isFalse(listItemProps.shouldToggleCheckbox); - assert.isEmpty(listItemProps.attributesFromList); - assert.isEmpty(listItemProps.classNamesFromList); - assert.equal(listItemProps.childrenTabIndex, -1); + const list = wrapper.childAt(0); + assert.equal(coerceForTesting(list.childAt(0).getDOMNode()).tabIndex, 0); + assert.equal(coerceForTesting(list.childAt(1).getDOMNode()).tabIndex, -1); + assert.equal(coerceForTesting(list.childAt(2).getDOMNode()).tabIndex, -1); }); -test('#renderListItem renders list item with prop.shouldFocus true if its index is state.focusListItemAtIndex', () => { +test('renders list items with tabindex=-1 and child at props.selectedIndex tabindex=0', () => { const wrapper = mount( - + {threeChildren()} ); - wrapper.setState({focusListItemAtIndex: 1}); - const children = wrapper.children().props().children; - assert.isFalse(children[0].props.shouldFocus); - assert.isTrue(children[1].props.shouldFocus); - assert.isFalse(children[2].props.shouldFocus); + const list = wrapper.childAt(0); + assert.equal(coerceForTesting(list.childAt(0).getDOMNode()).tabIndex, -1); + assert.equal(coerceForTesting(list.childAt(1).getDOMNode()).tabIndex, 0); + assert.equal(coerceForTesting(list.childAt(2).getDOMNode()).tabIndex, -1); }); -test( - '#renderListItem renders list item with prop.shouldFollowHref true ' + - 'if its index is state.followHrefAtIndex', - () => { - const wrapper = mount( - - {threeChildren()} - - ); - wrapper.setState({followHrefAtIndex: 1}); - const children = wrapper.children().props().children; - assert.isFalse(children[0].props.shouldFollowHref); - assert.isTrue(children[1].props.shouldFollowHref); - assert.isFalse(children[2].props.shouldFollowHref); - } -); - -test( - '#renderListItem renders list item with prop.shouldToggleCheckbox true ' + - 'if its index is state.toggleCheckboxAtIndex', +test('renders list items with tabindex=-1 and child at props.selectedIndex tabindex=0 as an array', () => { const wrapper = mount( - - {threeChildren()} + + {children({key: 0, hasCheckbox: true})} + {children({key: 1, hasCheckbox: true})} + {children({key: 2, hasCheckbox: true})} ); - wrapper.setState({toggleCheckboxAtIndex: 1}); - const children = wrapper.children().props().children; - assert.isFalse(children[0].props.shouldToggleCheckbox); - assert.isTrue(children[1].props.shouldToggleCheckbox); - assert.isFalse(children[2].props.shouldToggleCheckbox); - } -); - -test('#renderListItem renders list item with state.listItemAttributes at index as prop.attributesFromList', () => { - const wrapper = mount( - - {threeChildren()} - - ); - const attributes = {tabIndex: 0}; - wrapper.setState({listItemAttributes: {1: attributes}}); - const children = wrapper.children().props().children; - assert.isEmpty(children[0].props.attributesFromList); - assert.equal(children[1].props.attributesFromList, attributes); - assert.isEmpty(children[2].props.attributesFromList); -}); - -test('#renderListItem renders list item with state.listItemClassNames at index as prop.classNamesFromList', () => { - const wrapper = mount( - - {threeChildren()} - - ); - const classes = ['test-class']; - wrapper.setState({listItemClassNames: {1: classes}}); - const children = wrapper.children().props().children; - assert.isEmpty(children[0].props.classNamesFromList); - assert.equal(children[1].props.classNamesFromList, classes); - assert.isEmpty(children[2].props.classNamesFromList); -}); - -test('#renderListItem renders list item with state.listItemChildrenTabIndex at index as prop.childrenTabIndex', () => { - const wrapper = mount( - - {threeChildren()} - - ); - wrapper.setState({listItemChildrenTabIndex: {1: 0}}); - const children = wrapper.children().props().children; - assert.equal(children[0].props.childrenTabIndex, -1); - assert.equal(children[1].props.childrenTabIndex, 0); - assert.equal(children[2].props.childrenTabIndex, -1); -}); - -test('first item is selected if props.selectedIndex is 0', () => { - const wrapper = mount( - - {threeChildren()} - - ); - assert.isTrue(wrapper.state().listItemAttributes[0]['aria-selected']); -}); + const list = wrapper.childAt(0); + assert.equal(coerceForTesting(list.childAt(0).getDOMNode()).tabIndex, -1); + assert.equal(coerceForTesting(list.childAt(1).getDOMNode()).tabIndex, 0); + assert.equal(coerceForTesting(list.childAt(2).getDOMNode()).tabIndex, -1); + }); test('renders a list with default tag', () => { const wrapper = shallow({children()}); @@ -403,7 +464,7 @@ test('renders a list with a nav tag', () => { assert.equal(wrapper.type(), 'nav'); }); -test('renders a list with children which is not DOM', () => { +test('renders a list with children of non-DOM elements', () => { const wrapper = shallow( {} {false} diff --git a/test/unit/material-icon/index.test.tsx b/test/unit/material-icon/index.test.tsx index ddd99c695..292fb254d 100644 --- a/test/unit/material-icon/index.test.tsx +++ b/test/unit/material-icon/index.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {mount} from 'enzyme'; diff --git a/test/unit/menu-surface/index.test.tsx b/test/unit/menu-surface/index.test.tsx index 258ba449e..837280e63 100644 --- a/test/unit/menu-surface/index.test.tsx +++ b/test/unit/menu-surface/index.test.tsx @@ -1,28 +1,34 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {shallow, mount} from 'enzyme'; import MenuSurface, {Corner} from '../../../packages/menu-surface/index'; +import {MDCMenuDistance} from '@material/menu-surface'; suite('MenuSurface'); +function getAdapter(instance: MenuSurface) { + // @ts-ignore adapter_ property is protected and we need to override this + return instance.foundation.adapter_; +} + test('classNames adds classes', () => { const wrapper = mount(); - assert.isTrue(wrapper.childAt(0).hasClass('test-class-name')); - assert.isTrue(wrapper.childAt(0).hasClass('mdc-menu-surface')); + assert.isTrue(wrapper.getDOMNode().classList.contains('test-class-name')); + assert.isTrue(wrapper.getDOMNode().classList.contains('mdc-menu-surface')); wrapper.unmount(); }); test('classList adds classes', () => { const wrapper = mount(); wrapper.setState({classList: new Set(['test-class-name'])}); - assert.isTrue(wrapper.childAt(0).hasClass('test-class-name')); + assert.isTrue(wrapper.getDOMNode().classList.contains('test-class-name')); wrapper.unmount(); }); test('props.fixed adds fixed class', () => { const wrapper = mount(); - assert.isTrue(wrapper.childAt(0).hasClass('mdc-menu-surface--fixed')); + assert.isTrue(wrapper.getDOMNode().classList.contains('mdc-menu-surface--fixed')); wrapper.unmount(); }); @@ -33,7 +39,7 @@ test('foundation is created', () => { test('update to props.open will call foundation.open', () => { const wrapper = mount(); - wrapper.instance().foundation.open = td.func(); + wrapper.instance().foundation.open = td.func<() => void>(); wrapper.setProps({open: true}); td.verify(wrapper.instance().foundation.open(), {times: 1}); wrapper.unmount(); @@ -69,7 +75,7 @@ test('update to props.open sets lastFocusableElement', () => { test('update to props.open from true to false will call foundation.close', () => { const wrapper = mount(); - wrapper.instance().foundation.close = td.func(); + wrapper.instance().foundation.close = td.func<() => void>(); wrapper.setProps({open: false}); td.verify(wrapper.instance().foundation.close(), {times: 1}); wrapper.unmount(); @@ -77,7 +83,7 @@ test('update to props.open from true to false will call foundation.close', () => test('foundation.setAbsolutePosition is called when props.coordinates updates', () => { const wrapper = shallow(); - wrapper.instance().foundation.setAbsolutePosition = td.func(); + wrapper.instance().foundation.setAbsolutePosition = td.func<(x: number, y: number) => void>(); wrapper.setProps({coordinates: {x: 1, y: 11}}); td.verify(wrapper.instance().foundation.setAbsolutePosition(1, 11), { times: 1, @@ -86,7 +92,7 @@ test('foundation.setAbsolutePosition is called when props.coordinates updates', test('foundation.setAnchorCorner is called when props.anchorCorner updates', () => { const wrapper = shallow(); - wrapper.instance().foundation.setAnchorCorner = td.func(); + wrapper.instance().foundation.setAnchorCorner = td.func<(corner: Corner) => void>(); wrapper.setProps({anchorCorner: Corner.TOP_RIGHT}); td.verify(wrapper.instance().foundation.setAnchorCorner(Corner.TOP_RIGHT), { times: 1, @@ -95,7 +101,7 @@ test('foundation.setAnchorCorner is called when props.anchorCorner updates', () test('foundation.setAnchorMargin is called when props.anchorMargin updates', () => { const wrapper = shallow(); - wrapper.instance().foundation.setAnchorMargin = td.func(); + wrapper.instance().foundation.setAnchorMargin = td.func<(margin: Partial) => void>(); wrapper.setProps({anchorMargin: {top: 20}}); td.verify(wrapper.instance().foundation.setAnchorMargin({top: 20}), { times: 1, @@ -104,14 +110,14 @@ test('foundation.setAnchorMargin is called when props.anchorMargin updates', () test('foundation.setQuickOpen is called when props.quickOpen updates to true', () => { const wrapper = shallow(); - wrapper.instance().foundation.setQuickOpen = td.func(); + wrapper.instance().foundation.setQuickOpen = td.func<(quickOpen: boolean) => void>(); wrapper.setProps({quickOpen: true}); td.verify(wrapper.instance().foundation.setQuickOpen(true), {times: 1}); }); test('foundation.setQuickOpen is called when props.quickOpen updates to false', () => { const wrapper = shallow(); - wrapper.instance().foundation.setQuickOpen = td.func(); + wrapper.instance().foundation.setQuickOpen = td.func<(quickOpen: boolean) => void>(); wrapper.setProps({quickOpen: false}); td.verify(wrapper.instance().foundation.setQuickOpen(false), {times: 1}); }); @@ -130,9 +136,9 @@ test('foundation.isOpen is false when props.open is false', () => { test('#registerWindowClickListener adds click event handler to window', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleBodyClick = td.func(); + wrapper.instance().foundation.handleBodyClick = td.func<(evt: MouseEvent) => void>(); wrapper.instance().registerWindowClickListener!(); - const clickEvent = new Event('click'); + const clickEvent = new MouseEvent('click'); window.dispatchEvent(clickEvent); td.verify(wrapper.instance().foundation.handleBodyClick(clickEvent), { times: 1, @@ -141,10 +147,10 @@ test('#registerWindowClickListener adds click event handler to window', () => { test('#deregisterWindowClickListener removes click event handler to window', () => { const wrapper = shallow(); - wrapper.instance().foundation.handleBodyClick = td.func(); + wrapper.instance().foundation.handleBodyClick = td.func<(evt: MouseEvent) => void>(); wrapper.instance().registerWindowClickListener!(); wrapper.instance().deregisterWindowClickListener!(); - const clickEvent = new Event('click'); + const clickEvent = new MouseEvent('click'); window.dispatchEvent(clickEvent); td.verify(wrapper.instance().foundation.handleBodyClick(clickEvent), { times: 0, @@ -153,15 +159,15 @@ test('#deregisterWindowClickListener removes click event handler to window', () test('#adapter.notifyOpen calls #registerWindowClickListener', () => { const wrapper = shallow(); - wrapper.instance().registerWindowClickListener = td.func() as () => void; - wrapper.instance().foundation.adapter_.notifyOpen(); + wrapper.instance().registerWindowClickListener = td.func<() => void>(); + getAdapter(wrapper.instance()).notifyOpen(); td.verify(wrapper.instance().registerWindowClickListener!(), {times: 1}); }); test('#adapter.notifyOpen calls onOpen', () => { const onOpen = td.func() as () => void; const wrapper = shallow(); - wrapper.instance().foundation.adapter_.notifyOpen(); + getAdapter(wrapper.instance()).notifyOpen(); td.verify(onOpen(), {times: 1}); }); @@ -178,7 +184,7 @@ test('#adapter.isFocused returns true if menuSurfaceElement_ is the activeElemen options ); (wrapper.getDOMNode() as HTMLDivElement).focus(); - assert.isTrue(wrapper.instance().foundation.adapter_.isFocused()); + assert.isTrue(getAdapter(wrapper.instance()).isFocused()); wrapper.unmount(); div.remove(); }); @@ -189,7 +195,7 @@ test('#adapter.isFocused returns false if menuSurfaceElement_ is not the activeE hello ); - assert.isFalse(wrapper.instance().foundation.adapter_.isFocused()); + assert.isFalse(getAdapter(wrapper.instance()).isFocused()); wrapper.unmount(); }); @@ -207,7 +213,7 @@ test('#adapter.saveFocus saves the currently focused element', () => { .find('button') .getDOMNode() as HTMLButtonElement) .focus(); - wrapper.instance().foundation.adapter_.saveFocus(); + getAdapter(wrapper.instance()).saveFocus(); assert.equal( wrapper.instance().previousFocus, (wrapper.find('button').getDOMNode() as HTMLButtonElement) @@ -232,7 +238,7 @@ test('#adapter.restoreFocus restores focus to an element within the menuSurfaceE .find('button') .getDOMNode() as HTMLButtonElement) .focus(); - wrapper.instance().foundation.adapter_.restoreFocus(); + getAdapter(wrapper.instance()).restoreFocus(); assert.equal(document.activeElement, wrapper.find('a').getDOMNode()); wrapper.unmount(); div.remove(); @@ -252,7 +258,7 @@ test('#adapter.isFirstElementFocused returns true if firstFocusableElement is th .getDOMNode() as HTMLButtonElement) .focus(); assert.isTrue( - wrapper.instance().foundation.adapter_.isFirstElementFocused() + getAdapter(wrapper.instance()).isFirstElementFocused() ); wrapper.unmount(); }); @@ -270,7 +276,7 @@ test('#adapter.isLastElementFocused returns true if lastFocusableElement is the .find('button') .getDOMNode() as HTMLButtonElement) .focus(); - assert.isTrue(wrapper.instance().foundation.adapter_.isLastElementFocused()); + assert.isTrue(getAdapter(wrapper.instance()).isLastElementFocused()); wrapper.unmount(); }); @@ -283,7 +289,7 @@ test('#adapter.focusFirstElement focuses on firstFocusableElement', () => { wrapper.instance().firstFocusableElement = wrapper .find('button') .getDOMNode() as HTMLButtonElement; - wrapper.instance().foundation.adapter_.focusFirstElement(); + getAdapter(wrapper.instance()).focusFirstElement(); assert.equal(document.activeElement, wrapper.find('button').getDOMNode()); wrapper.unmount(); }); @@ -297,7 +303,7 @@ test('#adapter.focusLastElement focuses on lastFocusableElement', () => { wrapper.instance().lastFocusableElement = wrapper .find('button') .getDOMNode() as HTMLButtonElement; - wrapper.instance().foundation.adapter_.focusLastElement(); + getAdapter(wrapper.instance()).focusLastElement(); assert.equal(document.activeElement, wrapper.find('button').getDOMNode()); wrapper.unmount(); }); @@ -308,7 +314,7 @@ test('#adapter.getInnerDimensions returns width/height of menuSurfaceElement_', ); - const dim = wrapper.instance().foundation.adapter_.getInnerDimensions(); + const dim = getAdapter(wrapper.instance()).getInnerDimensions(); assert.isAbove(dim.width, 0); assert.isAbove(dim.height, 0); wrapper.unmount(); @@ -325,7 +331,7 @@ test('#adapter.getAnchorDimensions returns width/height of menuSurfaceElement_', options ); assert.deepInclude( - wrapper.instance().foundation.adapter_.getAnchorDimensions(), + getAdapter(wrapper.instance()).getAnchorDimensions(), div.getBoundingClientRect() ); wrapper.unmount(); @@ -334,10 +340,10 @@ test('#adapter.getAnchorDimensions returns width/height of menuSurfaceElement_', test('#adapter.getWindowDimensions returns width/height of menuSurfaceElement_', () => { const wrapper = shallow(); - const dim = wrapper + const dim = getAdapter(wrapper .update() - .instance() - .foundation.adapter_.getWindowDimensions(); + .instance()) + .getWindowDimensions(); assert.isAbove(dim.width, 0); assert.isAbove(dim.height, 0); }); @@ -352,10 +358,10 @@ test('#adapter.getBodyDimensions returns width/height of body', () => { , options ); - const dim = wrapper + const dim = getAdapter(wrapper .update() - .instance() - .foundation.adapter_.getBodyDimensions(); + .instance()) + .getBodyDimensions(); assert.isAtLeast(dim.width, 0); assert.isAtLeast(dim.height, 0); wrapper.unmount(); @@ -364,17 +370,17 @@ test('#adapter.getBodyDimensions returns width/height of body', () => { test('#adapter.getWindowScroll returns scroll of window', () => { const wrapper = shallow(); - const scroll = wrapper + const scroll = getAdapter(wrapper .update() - .instance() - .foundation.adapter_.getWindowScroll(); + .instance()) + .getWindowScroll(); assert.isAtLeast(scroll.x, 0); assert.isAtLeast(scroll.y, 0); }); test('#adapter.setPosition sets left, right, top, bottom state variables', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.setPosition({ + getAdapter(wrapper.instance()).setPosition({ left: 20, bottom: 30, top: 40, @@ -387,20 +393,20 @@ test('#adapter.setPosition sets left, right, top, bottom state variables', () => test('#adapter.setMaxHeight sets maxHeight state variables', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.setMaxHeight(500); - assert.equal(wrapper.state().maxHeight, 500); + getAdapter(wrapper.instance()).setMaxHeight('500'); + assert.equal(wrapper.state().maxHeight, '500'); }); test('#adapter.addClass adds to classList', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.addClass('test-class-name'); + getAdapter(wrapper.instance()).addClass('test-class-name'); assert.isTrue(wrapper.state().classList.has('test-class-name')); }); test('#adapter.removeClass removes from classList', () => { const wrapper = shallow(); wrapper.setState({classList: new Set(['test-class-name'])}); - wrapper.instance().foundation.adapter_.removeClass('test-class-name'); + getAdapter(wrapper.instance()).removeClass('test-class-name'); assert.isFalse(wrapper.state().classList.has('test-class-name')); }); @@ -408,40 +414,40 @@ test('#adapter.hasClass returns true if classList has class', () => { const wrapper = shallow(); wrapper.setState({classList: new Set(['test-class-name'])}); assert.isTrue( - wrapper.instance().foundation.adapter_.hasClass('test-class-name') + getAdapter(wrapper.instance()).hasClass('test-class-name') ); }); test('#adapter.notifyClose calls onClose', () => { const onClose = td.func() as () => void; const wrapper = shallow(); - wrapper.instance().foundation.adapter_.notifyClose(); + getAdapter(wrapper.instance()).notifyClose(); td.verify(onClose(), {times: 1}); }); test('#adapter.notifyClose calls deregisterWindowClickListener', () => { const wrapper = shallow(); wrapper.instance().deregisterWindowClickListener = td.func() as () => void; - wrapper.instance().foundation.adapter_.notifyClose(); + getAdapter(wrapper.instance()).notifyClose(); td.verify(wrapper.instance().deregisterWindowClickListener!(), {times: 1}); }); test('#adapter.hasAnchor calls returns false if there is no props.anchorElement', () => { const wrapper = shallow(); - assert.isFalse(wrapper.instance().foundation.adapter_.hasAnchor()); + assert.isFalse(getAdapter(wrapper.instance()).hasAnchor()); }); test('#adapter.hasAnchor calls returns true if there is props.anchorElement', () => { const anchorElement =
as unknown as HTMLDivElement; const wrapper = shallow(); - assert.isTrue(wrapper.instance().foundation.adapter_.hasAnchor()); + assert.isTrue(getAdapter(wrapper.instance()).hasAnchor()); }); test('#adapter.isElementInContainer returns true if the element is the menuSurfaceElement_', () => { const wrapper = mount(); const element = wrapper.getDOMNode(); assert.isTrue( - wrapper.instance().foundation.adapter_.isElementInContainer(element) + getAdapter(wrapper.instance()).isElementInContainer(element) ); wrapper.unmount(); }); @@ -454,7 +460,7 @@ test('#adapter.isElementInContainer returns true if the element is within the co ); const element = wrapper.find('button').getDOMNode(); assert.isTrue( - wrapper.instance().foundation.adapter_.isElementInContainer(element) + getAdapter(wrapper.instance()).isElementInContainer(element) ); wrapper.unmount(); }); @@ -470,41 +476,41 @@ test('#adapter.isRtl returns true is rtl', () => { options ); wrapper.getDOMNode().setAttribute('dir', 'rtl'); - assert.isTrue(wrapper.instance().foundation.adapter_.isRtl()); + assert.isTrue(getAdapter(wrapper.instance()).isRtl()); wrapper.unmount(); div.remove(); }); test('#adapter.setTransformOrigin sets maxHeight state variables', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.setTransformOrigin('translate()'); + getAdapter(wrapper.instance()).setTransformOrigin('translate()'); assert.equal(wrapper.state().transformOrigin, 'translate()'); }); test('onKeyDown calls props.onKeyDown', () => { const onKeyDown = td.func() as (event: React.KeyboardEvent) => {}; const wrapper = shallow(); - const evt = {} as React.KeyboardEvent; + const evt = {nativeEvent: {}} as React.KeyboardEvent; wrapper.instance().handleKeydown(evt); td.verify(onKeyDown(evt), {times: 1}); }); test('onKeyDown calls foundation.handleKeydown', () => { const wrapper = shallow(hello); - wrapper.instance().foundation.handleKeydown = td.func() as (event: React.KeyboardEvent) => {}; - const evt = {} as React.KeyboardEvent; + wrapper.instance().foundation.handleKeydown = td.func() as (event: KeyboardEvent) => {}; + const evt = {nativeEvent: ({} as KeyboardEvent)} as React.KeyboardEvent; wrapper.instance().handleKeydown(evt); - td.verify(wrapper.instance().foundation.handleKeydown(evt), {times: 1}); + td.verify(wrapper.instance().foundation.handleKeydown(evt.nativeEvent), {times: 1}); }); test('component styles is applied from this.styles', () => { const wrapper = mount(); wrapper.setState({ - maxHeight: 200, + maxHeight: '200', styleLeft: 50, }); - assert.equal(wrapper.childAt(0).props().style!.maxHeight, 200); - assert.equal(wrapper.childAt(0).props().style!.left, 50); + assert.equal(wrapper.instance().styles.maxHeight, 200); + assert.equal(wrapper.instance().styles.left, 50); wrapper.unmount(); }); @@ -519,7 +525,7 @@ test('#componentWillUnmount calls #deregisterWindowClickListener', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy()); }); diff --git a/test/unit/menu/MenuList.test.tsx b/test/unit/menu/MenuList.test.tsx new file mode 100644 index 000000000..f8aea8d9b --- /dev/null +++ b/test/unit/menu/MenuList.test.tsx @@ -0,0 +1,68 @@ +import * as React from 'react'; +import {assert} from 'chai'; +import * as td from 'testdouble'; +import {shallow, mount} from 'enzyme'; +import {MenuList} from '../../../packages/menu/index'; +import List from '../../../packages/list/index'; +import {MDCListIndex} from '@material/list/types'; +import {coerceForTesting} from '../helpers/types'; + +suite('MenuList'); + +test('classNames adds classes', () => { + const wrapper = mount(); + assert.isTrue(wrapper.getDOMNode().classList.contains('mdc-list')); + assert.isTrue(wrapper.getDOMNode().classList.contains('test-class-name')); +}); + +test('role is defaulted to menu', () => { + const wrapper = mount(); + assert.equal(wrapper.getDOMNode().getAttribute('role'), 'menu'); +}); + +test('role is set to props.role', () => { + const wrapper = mount(); + assert.equal(wrapper.getDOMNode().getAttribute('role'), 'menuitem'); +}); + +test('aria-hidden is defaulted to true', () => { + const wrapper = mount(); + assert.equal(wrapper.getDOMNode().getAttribute('aria-hidden'), 'true'); +}); + +test('aria-hidden is set to props.ariaHidden', () => { + const wrapper = mount(); + assert.equal(wrapper.getDOMNode().getAttribute('aria-hidden'), 'false'); +}); + +test('#handleSelect calls props.handleSelect', () => { + const handleSelect = td.func<(activatedItemIndex: number, selected: MDCListIndex) => void>(); + const wrapper = shallow(); + coerceForTesting(wrapper.instance()).handleSelect!(0, 0); + td.verify(handleSelect(0, 0), {times: 1}); +}); + +test('#handleSelect calls props.handleItemAction', () => { + const handleItemAction = td.func<(listItem: Element) => void>(); + const wrapper = mount( + + ); + coerceForTesting(wrapper.instance()).handleSelect!(0, 0); + td.verify(handleItemAction(wrapper.find('.mdc-list-item').getDOMNode()), {times: 1}); +}); + +// These tests with innerRef could be a global set of tests for an HOC +test('innerRef as function as function gets called with List', () => { + const innerRef = td.func<(list: List | null) => void>(); + const wrapper = mount(); + const list = coerceForTesting(wrapper.childAt(0).instance()); + td.verify(innerRef(list), {times: 1}); +}); + + +test('innerRef as refObject gets called with List', () => { + const innerRef = React.createRef(); + const wrapper = mount(); + const list = coerceForTesting(wrapper.childAt(0).instance()); + assert.equal(innerRef.current, list); +}); diff --git a/test/unit/menu/MenuListItem.test.tsx b/test/unit/menu/MenuListItem.test.tsx new file mode 100644 index 000000000..b63375e51 --- /dev/null +++ b/test/unit/menu/MenuListItem.test.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; +import {assert} from 'chai'; +import {mount} from 'enzyme'; +import {MenuListItem} from '../../../packages/menu/index'; + +suite('MenuListItem'); + +test('classNames adds classes', () => { + const wrapper = mount(); + assert.isTrue(wrapper.getDOMNode().classList.contains('mdc-list-item')); + assert.isTrue(wrapper.getDOMNode().classList.contains('test-class-name')); +}); + +test('role is defaulted to menuitem', () => { + const wrapper = mount(); + assert.equal(wrapper.getDOMNode().getAttribute('role'), 'menuitem'); +}); + +test('role is set to props.role', () => { + const wrapper = mount(); + assert.equal(wrapper.getDOMNode().getAttribute('role'), 'menu'); +}); diff --git a/test/unit/menu/index.test.tsx b/test/unit/menu/index.test.tsx new file mode 100644 index 000000000..bceec3d36 --- /dev/null +++ b/test/unit/menu/index.test.tsx @@ -0,0 +1,232 @@ +import * as React from 'react'; +import {assert} from 'chai'; +import * as td from 'testdouble'; +import {shallow, mount, ShallowWrapper, ReactWrapper} from 'enzyme'; +import Menu, {MenuState, MenuList, MenuListItem} from '../../../packages/menu/index'; +import {coerceForTesting} from '../helpers/types'; + +suite('Menu'); + +function getFoundation(wrapper: ReactWrapper | ShallowWrapper) { + return coerceForTesting(wrapper.state()).foundation!; +} + +function getAdapter(wrapper: ReactWrapper | ShallowWrapper) { + // @ts-ignore adapter_ property is protected and we need to override this + return getFoundation(wrapper).adapter_; +} + +test('classNames adds classes', () => { + const wrapper = shallow(); + assert.isTrue(wrapper.hasClass('test-class-name')); + assert.isTrue(wrapper.hasClass('mdc-menu')); +}); + +test('has state.foundation', () => { + const wrapper = shallow(); + const foundation = coerceForTesting(wrapper.state()).foundation; + assert.exists(foundation); +}); + +test('calls foundation.destroy on unmount', () => { + const wrapper = shallow(); + const destroy = getFoundation(wrapper).destroy = td.func<() => void>(); + wrapper.unmount(); + td.verify(destroy(), {times: 1}); +}); + +test('props.open updates from true to false, will set state.open to false', () => { + const wrapper = shallow(); + wrapper.setProps({open: false}); + assert.isFalse(coerceForTesting(wrapper.state()).open); +}); + +test('props.open updates from false to true, will set state.open to true', () => { + const wrapper = shallow(); + wrapper.setProps({open: true}); + assert.isTrue(coerceForTesting(wrapper.state()).open); +}); + +// TODO: implement with https://github.com/material-components/material-components-web-react/issues/796 +// test('adapter.addClassToElementAtIndex adds a class to a listItem', () => { +// }); +// test('adapter.removeClassToElementAtIndex adds a class to a listItem', () => { +// }); + +test('adapter.addAttributeToElementAtIndex adds a class to a listItem', () => { + const wrapper = mount( + + + + ); + getAdapter(wrapper).addAttributeToElementAtIndex(0, 'tabindex', '12'); + const listItem = wrapper.find('.mdc-list-item').getDOMNode(); + assert.equal(coerceForTesting(listItem).tabIndex, 12); + wrapper.unmount(); +}); + +test('adapter.removeAttributeToElementAtIndex adds a class to a listItem', () => { + const wrapper = mount( + + + + ); + getAdapter(wrapper).removeAttributeFromElementAtIndex(0, 'tabindex'); + const listItem = wrapper.find('.mdc-list-item').getDOMNode(); + assert.notEqual(coerceForTesting(listItem).tabIndex, 12); + wrapper.unmount(); +}); + +test('adapter.elementContainsClass returns true if element contains class', () => { + class Div extends React.Component { + render() { + return (
Meow
); + } + } + const wrapper = mount(
); + const contains = getAdapter(wrapper).elementContainsClass( + wrapper.find('div').last().getDOMNode(), 'test-class-name-1'); + assert.isTrue(contains); + wrapper.unmount(); +}); + +test('adapter.elementContainsClass returns FALSE if element does not contains class', () => { + class Div extends React.Component { + render() { + return (
Meow
); + } + } + const wrapper = mount(
); + const contains = getAdapter(wrapper).elementContainsClass( + wrapper.find('div').first().getDOMNode(), 'test-class-name-1'); + assert.isFalse(contains); + wrapper.unmount(); +}); + +test('adapter.closeSurface sets state.open to false', () => { + const wrapper = shallow(); + assert.isTrue(coerceForTesting(wrapper.state()).open); + getAdapter(wrapper).closeSurface(); + assert.isFalse(coerceForTesting(wrapper.state()).open); +}); + +test('adapter.getElementIndex returns index of list item', () => { + const wrapper = mount( + + + + + ); + const lastListItem = wrapper.find('.mdc-list-item').last().getDOMNode(); + const index = getAdapter(wrapper).getElementIndex(lastListItem); + assert.equal(index, 1); + wrapper.unmount(); +}); + +test('adapter.getParentElement returns MenuList if called on list item', () => { + const wrapper = mount( + + + + + ); + const lastListItem = wrapper.find('.mdc-list-item').last().getDOMNode(); + const menuList = getAdapter(wrapper).getParentElement(lastListItem); + assert.equal(menuList, wrapper.find('.mdc-list').getDOMNode()); + wrapper.unmount(); +}); + +test('adapter.getSelectedElementIndex returns selected list item\'s index', () => { + const wrapper = mount( + + + + + ); + const menuList = wrapper.find('.mdc-list').getDOMNode(); + const selectedListItem = getAdapter(wrapper).getSelectedElementIndex(menuList); + assert.equal(selectedListItem, 0); + wrapper.unmount(); +}); + +test('adapter.getSelectedElementIndex returns -1 if no list item is selected', () => { + const wrapper = mount( + + + + + ); + const menuList = wrapper.find('.mdc-list').getDOMNode(); + const selectedListItem = getAdapter(wrapper).getSelectedElementIndex(menuList); + assert.equal(selectedListItem, -1); + wrapper.unmount(); +}); + +test('adapter.notifySelected calls props.onSelected with the selectedindex and listElement DOM node', () => { + const onSelected = td.func<(index: number, element: Element) => void>(); + const wrapper = mount( + + + + + ); + const evtData = {index: 0}; + getAdapter(wrapper).notifySelected(evtData); + td.verify(onSelected(0, wrapper.find('.mdc-list-item').first().getDOMNode()), {times: 1}); + wrapper.unmount(); +}); + +test('onKeyDown calls foundation.handleKeydown', () => { + const wrapper = shallow(); + getFoundation(wrapper).handleKeydown = td.func<(evt: Event) => void>(); + const evt = coerceForTesting({ + nativeEvent: {}, + }); + wrapper.simulate('keydown', evt); + td.verify(getFoundation(wrapper).handleKeydown(evt.nativeEvent), {times: 1}); +}); + +test('onKeyDown calls props.onKeyDown', () => { + const onKeyDown = td.func<(evt: React.KeyboardEvent) => void>(); + const wrapper = shallow(); + const evt = coerceForTesting({ + nativeEvent: {}, + }); + wrapper.simulate('keydown', evt); + td.verify(onKeyDown(evt), {times: 1}); +}); + +test('handleOpen calls props.onOpen', () => { + const onOpen = td.func<() => void>(); + const wrapper = mount(); + coerceForTesting(wrapper.instance()).handleOpen!(); + td.verify(onOpen(), {times: 1}); +}); + +test('menu renders with tabindex=-1', () => { + const wrapper = shallow(); + assert.equal(wrapper.props().tabIndex, -1); +}); + +test('menu renders child with handleItemAction', () => { + class Div extends React.Component { + render() { + return (
Meow
); + } + } + const wrapper = mount(
); + assert.equal( + typeof coerceForTesting(wrapper.instance()).menuListElement.current!.props.handleItemAction, 'function'); + wrapper.unmount(); +}); + +test('menu renders child with wrapFocus', () => { + class Div extends React.Component { + render() { + return (
Meow
); + } + } + const wrapper = mount(
); + assert.isTrue(coerceForTesting(wrapper.instance()).menuListElement.current!.props.wrapFocus); + wrapper.unmount(); +}); diff --git a/test/unit/notched-outline/index.test.tsx b/test/unit/notched-outline/index.test.tsx index 4d7ffd661..16f5e92e8 100644 --- a/test/unit/notched-outline/index.test.tsx +++ b/test/unit/notched-outline/index.test.tsx @@ -1,189 +1,145 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {mount, shallow} from 'enzyme'; import NotchedOutline from '../../../packages/notched-outline/index'; +import {MDCNotchedOutlineFoundation} from '@material/notched-outline/foundation'; +import {coerceForTesting} from '../helpers/types'; + +const {cssClasses} = MDCNotchedOutlineFoundation; + + +const getFoundation = (instance: NotchedOutline) => { + return coerceForTesting(instance.foundation!); +}; + +const getAdapter = (instance: NotchedOutline) => { + // @ts-ignore adapter_ property is protection, we need to override it for testing purposes + return getFoundation(instance).adapter_; +}; + +const floatingLabel = () => ( + +); suite('NotchedOutline'); test('classNames adds classes', () => { const wrapper = shallow(); - assert.isTrue(wrapper.children().first().hasClass('mdc-notched-outline')); - assert.isTrue(wrapper.children().first().hasClass('test-class-name')); + assert.isTrue(wrapper.hasClass('mdc-notched-outline')); + assert.isTrue(wrapper.hasClass('test-class-name')); }); -test('creates outlineElement_', () => { - const wrapper = mount(); - assert.exists(wrapper.instance().outlineElement_.current); +test('has no label class if there is no label', () => { + const wrapper = mount(); + assert.isTrue(wrapper.childAt(0).hasClass('mdc-notched-outline')); + assert.isTrue(wrapper.childAt(0).hasClass(cssClasses.NO_LABEL)); }); -test('creates pathElement_', () => { - const wrapper = mount(); - assert.exists(wrapper.instance().pathElement_.current); +test('has upgraded class if label is present', () => { + const wrapper = mount({floatingLabel()}); + assert.isTrue(wrapper.childAt(0).hasClass('mdc-notched-outline')); + assert.isTrue(wrapper.childAt(0).hasClass(cssClasses.OUTLINE_UPGRADED)); }); -test('creates idleElement_', () => { - const wrapper = mount(); - assert.exists(wrapper.instance().idleElement_.current); +test('label should not have any style transitionDuration', () => { + const wrapper = mount({floatingLabel()}); + const floatingLabelElement = wrapper.find('.mdc-floating-label'); + assert.notExists(floatingLabelElement.props().style); }); -test('initializes foundation', () => { - const wrapper = shallow(); - assert.exists(wrapper.instance().foundation_); +test('should call foundation.notch if props.notchWidth changes and props.notch is true', () => { + const wrapper = shallow(); + getFoundation(wrapper.instance()).notch = td.func<() => void>(); + wrapper.setProps({notchWidth: 50}); + td.verify(getFoundation(wrapper.instance()).notch(50), {times: 1}); }); -test('calls #foundation.notch if notch adds the notched class', () => { - const wrapper = mount(); - wrapper - .first() - .first() - .hasClass('mdc-notched-outline--notched'); +test('should not call foundation.notch if props.notchWidth changes and props.notch is false', () => { + const wrapper = shallow(); + getFoundation(wrapper.instance()).notch = td.func<() => void>(); + wrapper.setProps({notchWidth: 50}); + td.verify(getFoundation(wrapper.instance()).notch(50), {times: 0}); }); -test('#componentDidUpdate updating notch to true calls #foundation.notch', () => { +test('should call foundation.closeNotch if props.notchWidth changes and props.notch is false', () => { const wrapper = shallow(); - wrapper.instance().foundation_.notch = td.func(); - wrapper.setProps({notch: true}); - td.verify(wrapper.instance().foundation_.notch(0, false), {times: 1}); -}); - -test( - '#componentDidUpdate updating notch to false calls ' + - '#foundation.closeNotch', - () => { - const wrapper = mount(); - wrapper.instance().foundation_.closeNotch = td.func(); - td.when( - wrapper.instance().foundation_.adapter_.getIdleOutlineStyleValue - ).thenReturn('0px'); - wrapper.setProps({notch: false}); - td.verify(wrapper.instance().foundation_.closeNotch(), {times: 1}); - } -); + getFoundation(wrapper.instance()).closeNotch = td.func<() => void>(); + wrapper.setProps({notchWidth: 50}); + td.verify(getFoundation(wrapper.instance()).closeNotch(), {times: 1}); +}); -test( - '#componentDidUpdate updating notchWidth calls ' + - '#foundation.notch with correct arguments', - () => { - const wrapper = mount(); - wrapper.instance().foundation_.notch = td.func(); - td.when( - wrapper.instance().foundation_.adapter_.getIdleOutlineStyleValue - ).thenReturn('0px'); - wrapper.setProps({notchWidth: 100}); - td.verify(wrapper.instance().foundation_.notch(100, false), {times: 1}); - } -); +test('should not call foundation.closeNotch if props.notchWidth changes and props.notch is true', () => { + const wrapper = shallow(); + getFoundation(wrapper.instance()).closeNotch = td.func<() => void>(); + wrapper.setProps({notchWidth: 50}); + td.verify(getFoundation(wrapper.instance()).closeNotch(), {times: 0}); +}); -test('#componentDidUpdate updating isRtl calls #foundation.notch', () => { - const wrapper = mount(); - wrapper.instance().foundation_.notch = td.func(); - td.when( - wrapper.instance().foundation_.adapter_.getIdleOutlineStyleValue - ).thenReturn('0px'); - wrapper.setProps({isRtl: true}); - td.verify(wrapper.instance().foundation_.notch(0, true), {times: 1}); -}); -test( - '#componentDidUpdate updating notch to true with and initial ' + - 'notchWidth calls #foundation.notch with correct arguments', - () => { - const wrapper = mount(); - wrapper.instance().foundation_.notch = td.func(); - wrapper.setProps({notch: true}); - td.verify(wrapper.instance().foundation_.notch(100, false), {times: 1}); - } -); -test( - '#componentDidUpdate shouldn\'t call #foundation notch or closeNotch' + - 'if another prop changes', - () => { - const wrapper = shallow(); - wrapper.setProps({className: 'test-class-name'}); - wrapper.instance().foundation_.notch = td.func(); - wrapper.instance().foundation_.closeNotch = td.func(); - td.verify( - wrapper - .instance() - .foundation_.notch(td.matchers.isA(Number), td.matchers.isA(Boolean)), - {times: 0} - ); - td.verify(wrapper.instance().foundation_.closeNotch(), {times: 0}); - } -); +test('should call foundation.notch if props.notch changes from false to true', () => { + const wrapper = shallow(); + getFoundation(wrapper.instance()).notch = td.func<() => void>(); + wrapper.setProps({notch: true}); + td.verify(getFoundation(wrapper.instance()).notch(50), {times: 1}); +}); + +test('should call foundation.closeNotch if props.notch changes from true to false', () => { + const wrapper = shallow(); + getFoundation(wrapper.instance()).closeNotch = td.func<() => void>(); + wrapper.setProps({notch: false}); + td.verify(getFoundation(wrapper.instance()).closeNotch(), {times: 1}); +}); -test('#adapter.getWidth returns width of outlineElement_', () => { - const div = document.createElement('div'); - // needs to be attached to real DOM to get width - // https://github.com/airbnb/enzyme/issues/1525 - document.body.append(div); - div.style.width = '150px'; - div.style.height = '50px'; - div.style.position = 'relative'; - const options = {attachTo: div}; - const wrapper = mount(, options); - const notchedOutlineElement = wrapper.find('.mdc-notched-outline').instance() as any; - const outlineWidth = notchedOutlineElement.offsetWidth; - assert.equal( - wrapper.instance().foundation_.adapter_.getWidth(), - outlineWidth - ); - div.remove(); -}); - -test('#adapter.getHeight returns height of outlineElement_', () => { - const div = document.createElement('div'); - document.body.append(div); - div.style.width = '150px'; - div.style.height = '50px'; - div.style.position = 'relative'; - const options = {attachTo: div}; - const wrapper = mount(, options); - const notchedOutlineElement = wrapper.find('.mdc-notched-outline').instance() as any; - const outlineHeight = notchedOutlineElement.offsetHeight; - assert.equal( - wrapper.instance().foundation_.adapter_.getHeight(), - outlineHeight - ); - div.remove(); -}); - -test('#adapter.addClass adds class to classList', () => { +test('#adapter.addClass should update state.classList', () => { const wrapper = shallow(); - wrapper.instance().foundation_.adapter_.addClass('test-class-name'); + getAdapter(wrapper.instance()).addClass('test-class-name'); assert.isTrue(wrapper.state().classList.has('test-class-name')); }); -test('#adapter.removeClass adds class to classList', () => { +test('#adapter.removeClass should update state.classList', () => { const wrapper = shallow(); - const classList = new Set(); - classList.add('test-class-name'); - wrapper.setState({classList}); - wrapper.instance().foundation_.adapter_.removeClass('test-class-name'); + wrapper.setState({classList: new Set(['test-class-name'])}); + getAdapter(wrapper.instance()).removeClass('test-class-name'); assert.isFalse(wrapper.state().classList.has('test-class-name')); }); -test('#adapter.setOutlinePathAttr add attr to pathElement_', () => { - const wrapper = mount(); - wrapper.instance().foundation_.adapter_.setOutlinePathAttr('M10 10'); - const path = wrapper.instance().pathElement_.current; - assert.equal(path!.getAttribute('d'), 'M10 10'); +test('#adapter.setNotchWidthProperty should update state.foundationNotchWidth', () => { + const wrapper = shallow(); + getAdapter(wrapper.instance()).setNotchWidthProperty(10); + assert.equal(wrapper.state().foundationNotchWidth, 10); +}); + +test('#adapter.removeNotchWidthProperty should update state.foundationNotchWidth to null', () => { + const wrapper = shallow(); + getAdapter(wrapper.instance()).removeNotchWidthProperty(); + assert.equal(wrapper.state().foundationNotchWidth, null); +}); + +test('renders __notch element if children exist', () => { + const wrapper = shallow({floatingLabel()}); + assert.equal(wrapper.find('.mdc-notched-outline__notch').length, 1); +}); + +test('does not render __notch element if children do not exist', () => { + const wrapper = shallow(); + assert.equal(wrapper.find('.mdc-notched-outline__notch').length, 0); +}); + +test('renders style.width on __notch element if state.foundationNotchWidth is set', () => { + const wrapper = shallow({floatingLabel()}); + wrapper.setState({foundationNotchWidth: 10}); + assert.equal(wrapper.find('.mdc-notched-outline__notch').props().style!.width, '10px'); }); -test('#adapter.getIdleOutlineStyleValue add attr to pathElement_', () => { - const div = document.createElement('div'); - document.body.append(div); - const options = {attachTo: div}; - const wrapper = mount(, options); - wrapper.instance().idleElement_.current!.style.borderRadius = '5px'; - const {adapter_} = wrapper.instance().foundation_; - assert.equal(adapter_.getIdleOutlineStyleValue('border-radius'), '5px'); +test('does not render style.width on __notch element if state.foundationNotchWidth is not set', () => { + const wrapper = shallow({floatingLabel()}); + assert.equal(wrapper.find('.mdc-notched-outline__notch').props().style!.width, undefined); }); test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); - const foundation = wrapper.instance().foundation_; - foundation.destroy = td.func(); + const foundation = getFoundation(wrapper.instance()); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy(), {times: 1}); }); diff --git a/test/unit/radio/NativeControl.test.tsx b/test/unit/radio/NativeControl.test.tsx index 945be5aa2..a849636a0 100644 --- a/test/unit/radio/NativeControl.test.tsx +++ b/test/unit/radio/NativeControl.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; import {shallow} from 'enzyme'; import {NativeRadioControl} from '../../../packages/radio/index'; diff --git a/test/unit/radio/index.test.tsx b/test/unit/radio/index.test.tsx index 78816935c..71ee29503 100644 --- a/test/unit/radio/index.test.tsx +++ b/test/unit/radio/index.test.tsx @@ -1,9 +1,10 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; +import td from 'testdouble'; import {mount, shallow, ReactWrapper} from 'enzyme'; import {Radio, NativeRadioControl, RadioProps} from '../../../packages/radio/index'; import {coerceForTesting} from '../helpers/types'; +import {MDCRadioFoundation} from '@material/radio'; const NativeControlUpdate: React.FunctionComponent> = ({ disabled, id, // eslint-disable-line react/prop-types @@ -83,13 +84,13 @@ test('initializes foundation', () => { }); test('calls foundation.setDisabled if child.props.disabled is true', () => { - const setDisabled = td.func(); + const setDisabled = td.func<(disabled: boolean) => void>(); const wrapper = mount( ); - wrapper.instance().foundation = {init: () => {}, setDisabled}; + wrapper.instance().foundation = {init: () => {}, setDisabled} as MDCRadioFoundation; wrapper.instance().componentDidMount(); td.verify(setDisabled(true), {times: 1}); }); @@ -134,7 +135,7 @@ test('renders label with for attribute tied to native control id', () => { test('calls foundation.setDisabled if children.props.disabled updates', () => { const wrapper = mount(); coerceForTesting>( - wrapper.children()).instance().foundation.setDisabled = td.func(); + wrapper.children()).instance().foundation.setDisabled = td.func<(disabled: boolean) => null>(); wrapper.setProps({disabled: true}); td.verify( coerceForTesting>(wrapper.children()) @@ -147,7 +148,7 @@ test('calls foundation.setDisabled if children.props.disabled updates', () => { test('calls foundation.setDisabled if children.props.disabled updates to false', () => { const wrapper = mount(); coerceForTesting>( - wrapper.children()).instance().foundation.setDisabled = td.func(); + wrapper.children()).instance().foundation.setDisabled = td.func<(disabled: boolean) => null>(); wrapper.setProps({disabled: false}); td.verify( coerceForTesting>(wrapper.children()) @@ -234,7 +235,7 @@ test('#componentWillUnmount destroys foundation', () => { ); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy(), {times: 1}); }); diff --git a/test/unit/ripple/index.test.tsx b/test/unit/ripple/index.test.tsx index 754ea7a1b..c2aa9337c 100644 --- a/test/unit/ripple/index.test.tsx +++ b/test/unit/ripple/index.test.tsx @@ -1,8 +1,9 @@ -import * as React from 'react'; +import React from 'react'; import {assert} from 'chai'; -import * as td from 'testdouble'; -// @ts-ignore no mdc .d.ts file -import {MDCRippleFoundation} from '@material/ripple/dist/mdc.ripple'; +import td from 'testdouble'; +import {MDCRippleFoundation} from '@material/ripple/foundation'; +import {MDCRippleAdapter} from '@material/ripple/adapter'; +import {SpecificEventListener} from '@material/base/types'; import {mount} from 'enzyme'; import {withRipple, InjectedProps} from '../../../packages/ripple/index'; import {createMockRaf} from '../helpers/raf'; @@ -39,6 +40,11 @@ interface RippledComponent extends React.Component isComponentMounted: boolean; } +function getAdapter(foundation: MDCRippleFoundation): MDCRippleAdapter { + // @ts-ignore adapter_ property is marked as protected in mdc-web. We need to override this behaviour for testing + return foundation.adapter_; +} + suite('Ripple'); test('classNames adds classes', () => { @@ -61,7 +67,7 @@ test('mouseDown event triggers activateRipple', () => { const mouseDownHandler = coerceForTesting(td.func()); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.activate = td.func(); + foundation.activate = td.func<(evt?: Event) => void>(); wrapper.simulate('mouseDown'); mockRaf.flush(); td.verify(foundation.activate(td.matchers.isA(Object)), {times: 1}); @@ -73,18 +79,18 @@ test('mouseUp event triggers deactivateRipple', () => { const mouseUpHandler = coerceForTesting(td.func()); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.deactivate = td.func(); + foundation.deactivate = td.func<() => void>(); wrapper.simulate('mouseUp'); - td.verify(foundation.deactivate(td.matchers.isA(Object)), {times: 1}); + td.verify(foundation.deactivate(), {times: 1}); td.verify(mouseUpHandler(td.matchers.isA(Object)), {times: 1}); }); test('mouseUp event triggers deactivateRipple with no onMouseUp handler', () => { const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.deactivate = td.func(); + foundation.deactivate = td.func<() => void>(); wrapper.simulate('mouseUp'); - td.verify(foundation.deactivate(td.matchers.isA(Object)), {times: 1}); + td.verify(foundation.deactivate(), {times: 1}); }); test('touchStart event triggers activateRipple', () => { @@ -92,7 +98,7 @@ test('touchStart event triggers activateRipple', () => { const touchStartHandler = coerceForTesting(td.func()); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.activate = td.func(); + foundation.activate = td.func<(evt?: Event) => void>(); wrapper.simulate('touchStart'); mockRaf.flush(); td.verify(foundation.activate(td.matchers.isA(Object)), {times: 1}); @@ -104,7 +110,7 @@ test('touchStart event triggers activateRipple with no onTouchStart handler', () const mockRaf = createMockRaf(); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.activate = td.func(); + foundation.activate = td.func<(evt?: Event) => void>(); wrapper.simulate('touchStart'); mockRaf.flush(); td.verify(foundation.activate(td.matchers.isA(Object)), {times: 1}); @@ -115,18 +121,18 @@ test('touchEnd event triggers deactivateRipple', () => { const touchEndHandler = coerceForTesting(td.func()); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.deactivate = td.func(); + foundation.deactivate = td.func<() => void>(); wrapper.simulate('touchEnd'); - td.verify(foundation.deactivate(td.matchers.isA(Object)), {times: 1}); + td.verify(foundation.deactivate(), {times: 1}); td.verify(touchEndHandler(td.matchers.isA(Object)), {times: 1}); }); test('touchEnd event triggers deactivateRipple with no onTouchEnd handler', () => { const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.deactivate = td.func(); + foundation.deactivate = td.func<() => void>(); wrapper.simulate('touchEnd'); - td.verify(foundation.deactivate(td.matchers.isA(Object)), {times: 1}); + td.verify(foundation.deactivate(), {times: 1}); }); test('keyDown event triggers activateRipple', () => { @@ -134,7 +140,7 @@ test('keyDown event triggers activateRipple', () => { const keyDownHandler = coerceForTesting(td.func()); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.activate = td.func(); + foundation.activate = td.func<(evt?: Event) => void>(); wrapper.simulate('keyDown'); mockRaf.flush(); td.verify(foundation.activate(td.matchers.isA(Object)), {times: 1}); @@ -146,7 +152,7 @@ test('keyDown event triggers activateRipple with no onKeyDown handler', () => { const mockRaf = createMockRaf(); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.activate = td.func(); + foundation.activate = td.func<(evt?: Event) => void>(); wrapper.simulate('keyDown'); mockRaf.flush(); td.verify(foundation.activate(td.matchers.isA(Object)), {times: 1}); @@ -157,25 +163,25 @@ test('keyUp event triggers deactivateRipple', () => { const keyUpHandler = coerceForTesting(td.func()); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.deactivate = td.func(); + foundation.deactivate = td.func<() => void>(); wrapper.simulate('keyUp'); - td.verify(foundation.deactivate(td.matchers.isA(Object)), {times: 1}); + td.verify(foundation.deactivate(), {times: 1}); td.verify(keyUpHandler(td.matchers.isA(Object)), {times: 1}); }); test('keyUp event triggers deactivateRipple with no onKeyUp handler', () => { const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.deactivate = td.func(); + foundation.deactivate = td.func<() => void>(); wrapper.simulate('keyUp'); - td.verify(foundation.deactivate(td.matchers.isA(Object)), {times: 1}); + td.verify(foundation.deactivate(), {times: 1}); }); test('focus event proxies to foundation focus handler', () => { const focusHandler = coerceForTesting(td.func()); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.handleFocus = td.func(); + foundation.handleFocus = td.func<() => void>(); wrapper.simulate('focus'); td.verify(foundation.handleFocus(), {times: 1}); td.verify(focusHandler(td.matchers.isA(Object)), {times: 1}); @@ -184,7 +190,7 @@ test('focus event proxies to foundation focus handler', () => { test('focus event proxies to foundation focus handler with no onFocus handler', () => { const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.handleFocus = td.func(); + foundation.handleFocus = td.func<() => void>(); wrapper.simulate('focus'); td.verify(foundation.handleFocus(), {times: 1}); }); @@ -193,7 +199,7 @@ test('blur event proxies to foundation blur handler', () => { const blurHandler = coerceForTesting(td.func()); const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.handleBlur = td.func(); + foundation.handleBlur = td.func<() => void>(); wrapper.simulate('blur'); td.verify(foundation.handleBlur(), {times: 1}); td.verify(blurHandler(td.matchers.isA(Object)), {times: 1}); @@ -202,34 +208,34 @@ test('blur event proxies to foundation blur handler', () => { test('blur event proxies to foundation blur handler with no onBlur handler', () => { const wrapper = mount(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.handleBlur = td.func(); + foundation.handleBlur = td.func<() => void>(); wrapper.simulate('blur'); td.verify(foundation.handleBlur(), {times: 1}); }); test('#adapter.isUnbounded returns true is prop is set', () => { const wrapper = mount(); - assert.isTrue(coerceForTesting(wrapper.instance()).foundation.adapter_.isUnbounded()); + assert.isTrue(getAdapter(coerceForTesting(wrapper.instance()).foundation).isUnbounded()); }); test('#adapter.isUnbounded returns false prop is not set', () => { const wrapper = mount(); - assert.isFalse(coerceForTesting(wrapper.instance()).foundation.adapter_.isUnbounded()); + assert.isFalse(getAdapter(coerceForTesting(wrapper.instance()).foundation).isUnbounded()); }); test('#adapter.isSurfaceDisabled returns true is prop is set', () => { const wrapper = mount(); - assert.isTrue(coerceForTesting(wrapper.instance()).foundation.adapter_.isSurfaceDisabled()); + assert.isTrue(getAdapter(coerceForTesting(wrapper.instance()).foundation).isSurfaceDisabled()); }); test('#adapter.isSurfaceDisabled returns false prop is not set', () => { const wrapper = mount(); - assert.isFalse(coerceForTesting(wrapper.instance()).foundation.adapter_.isSurfaceDisabled()); + assert.isFalse(getAdapter(coerceForTesting(wrapper.instance()).foundation).isSurfaceDisabled()); }); test('#adapter.addClass adds a class to the root element', () => { const wrapper = mount(); - coerceForTesting(wrapper.instance()).foundation.adapter_.addClass('test-class'); + getAdapter(coerceForTesting(wrapper.instance()).foundation).addClass('test-class'); assert.isTrue( wrapper .update() @@ -241,7 +247,7 @@ test('#adapter.addClass adds a class to the root element', () => { test('#adapter.addClass does not add class if isMounted is false', () => { const wrapper = mount(); coerceForTesting(wrapper.instance()).isComponentMounted = false; - coerceForTesting(wrapper.instance()).foundation.adapter_.addClass('test-class'); + getAdapter(coerceForTesting(wrapper.instance()).foundation).addClass('test-class'); assert.isFalse( wrapper .update() @@ -252,9 +258,9 @@ test('#adapter.addClass does not add class if isMounted is false', () => { test('#adapter.removeClass removes a class to the root element', () => { const wrapper = mount(); - coerceForTesting(wrapper.instance()).foundation.adapter_.addClass('test-class'); + getAdapter(coerceForTesting(wrapper.instance()).foundation).addClass('test-class'); wrapper.update(); - coerceForTesting(wrapper.instance()).foundation.adapter_.removeClass('test-class'); + getAdapter(coerceForTesting(wrapper.instance()).foundation).removeClass('test-class'); assert.isFalse( wrapper .update() @@ -265,10 +271,10 @@ test('#adapter.removeClass removes a class to the root element', () => { test('#adapter.removeClass removes a class to the root element', () => { const wrapper = mount(); - coerceForTesting(wrapper.instance()).foundation.adapter_.addClass('test-class'); + getAdapter(coerceForTesting(wrapper.instance()).foundation).addClass('test-class'); coerceForTesting(wrapper.instance()).isComponentMounted = false; wrapper.update(); - coerceForTesting(wrapper.instance()).foundation.adapter_.removeClass('test-class'); + getAdapter(coerceForTesting(wrapper.instance()).foundation).removeClass('test-class'); assert.isTrue( wrapper .update() @@ -279,53 +285,56 @@ test('#adapter.removeClass removes a class to the root element', () => { test('#adapter.updateCssVariable updates style', () => { const wrapper = mount(); - coerceForTesting(wrapper.instance()).foundation.adapter_.updateCssVariable('color', 'blue'); + getAdapter(coerceForTesting(wrapper.instance()).foundation).updateCssVariable('color', 'blue'); assert.equal(wrapper.state().style.color, 'blue'); }); test('#adapter.updateCssVariable does not update style if isComponentMounted is false', () => { const wrapper = mount(); coerceForTesting(wrapper.instance()).isComponentMounted = false; - coerceForTesting(wrapper.instance()).foundation.adapter_.updateCssVariable('color', 'blue'); + getAdapter(coerceForTesting(wrapper.instance()).foundation).updateCssVariable('color', 'blue'); assert.notEqual(wrapper.state().style.color, 'blue'); }); test('#adapter.registerDocumentInteractionHandler triggers handler on document scroll', () => { const wrapper = mount(); - const testHandler = td.func(); - coerceForTesting(wrapper.instance()) - .foundation.adapter_.registerDocumentInteractionHandler( - 'scroll', - testHandler - ); - const event = new Event('scroll'); + const testHandler = td.func>(); + getAdapter( + coerceForTesting(wrapper.instance()).foundation + ).registerDocumentInteractionHandler( + 'scroll', + testHandler + ); + const event = new UIEvent('scroll'); document.documentElement.dispatchEvent(event); td.verify(testHandler(event), {times: 1}); }); test('#adapter.deregisterDocumentInteractionHandler does not trigger handler on document scroll', () => { const wrapper = mount(); - const testHandler = td.func(); - coerceForTesting(wrapper.instance()) - .foundation.adapter_.registerDocumentInteractionHandler( - 'scroll', - testHandler - ); - const event = new Event('scroll'); - coerceForTesting(wrapper.instance()) - .foundation.adapter_.deregisterDocumentInteractionHandler( - 'scroll', - testHandler - ); + const testHandler = td.func>(); + getAdapter( + coerceForTesting(wrapper.instance()).foundation + ).registerDocumentInteractionHandler( + 'scroll', + testHandler + ); + const event = new UIEvent('scroll'); + getAdapter( + coerceForTesting(wrapper.instance()).foundation + ).deregisterDocumentInteractionHandler( + 'scroll', + testHandler + ); document.documentElement.dispatchEvent(event); td.verify(testHandler(event), {times: 0}); }); test('#adapter.registerResizeHandler triggers handler on window resize', () => { const wrapper = mount(); - const testHandler = td.func(); - coerceForTesting(wrapper.instance()).foundation.adapter_.registerResizeHandler(testHandler); - const event = new Event('resize'); + const testHandler = td.func>(); + getAdapter(coerceForTesting(wrapper.instance()).foundation).registerResizeHandler(testHandler); + const event = new UIEvent('resize'); window.dispatchEvent(event); td.verify(testHandler(event), {times: 1}); }); @@ -334,11 +343,12 @@ test( 'after registering resize handler', () => { const wrapper = mount(); - const testHandler = td.func(); - coerceForTesting(wrapper.instance()).foundation.adapter_.registerResizeHandler(testHandler); - const event = new Event('resize'); - coerceForTesting(wrapper.instance()) - .foundation.adapter_.deregisterResizeHandler(testHandler); + const testHandler = td.func>(); + getAdapter(coerceForTesting(wrapper.instance()).foundation).registerResizeHandler(testHandler); + const event = new UIEvent('resize'); + getAdapter( + coerceForTesting(wrapper.instance()).foundation + ).deregisterResizeHandler(testHandler); window.dispatchEvent(event); td.verify(testHandler(event), {times: 0}); } @@ -357,8 +367,9 @@ test('#adapter.computeBoundingRect returns height and width', () => { left: 0, }; assert.deepInclude( - coerceForTesting(wrapper.update().instance()) - .foundation.adapter_.computeBoundingRect(), + getAdapter( + coerceForTesting(wrapper.update().instance()).foundation + ).computeBoundingRect(), domRect ); }); @@ -367,8 +378,9 @@ test('#adapter.getWindowPageOffset returns height and width', () => { const wrapper = mount(); const offset = {x: 0, y: 0}; assert.deepEqual( - coerceForTesting(wrapper.update().instance()) - .foundation.adapter_.getWindowPageOffset(), + getAdapter( + coerceForTesting(wrapper.update().instance()).foundation + ).getWindowPageOffset(), offset ); }); @@ -378,7 +390,7 @@ test('#componentWillUnmount destroys foundation', () => { const wrapper = mount(); mockRaf.flush(); const foundation = coerceForTesting(wrapper.instance()).foundation; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => void>(); wrapper.unmount(); td.verify(foundation.destroy()); mockRaf.restore(); diff --git a/test/unit/select/BaseSelect.test.tsx b/test/unit/select/BaseSelect.test.tsx new file mode 100644 index 000000000..ffaa11317 --- /dev/null +++ b/test/unit/select/BaseSelect.test.tsx @@ -0,0 +1,249 @@ +import * as React from 'react'; +import * as td from 'testdouble'; +import {assert} from 'chai'; +import {shallow} from 'enzyme'; +import {coerceForTesting} from '../helpers/types'; + +import {BaseSelect} from '../../../packages/select/BaseSelect'; +import NativeSelect from '../../../packages/select/NativeSelect'; +import EnhancedSelect from '../../../packages/select/EnhancedSelect'; +import {MDCSelectFoundation} from '@material/select/foundation'; + +suite('Base Select'); + +test('renders EnhancedSelect when props.enhanced is true', () => { + const wrapper = shallow(); + assert.equal(wrapper.find(EnhancedSelect).length, 1); +}); + +test('renders NativeSelect when props.enhanced is false', () => { + const wrapper = shallow(); + assert.equal(wrapper.find(NativeSelect).length, 1); +}); + +test('NativeSelect onFocus calls handleFocus', () => { + const handleFocus = td.func(); + const onFocus = td.func<(evt: React.FocusEvent) => void>(); + const foundation = coerceForTesting({handleFocus}); + const wrapper = shallow(); + const nativeSelect = wrapper.find(NativeSelect); + const evt = coerceForTesting>({}); + nativeSelect.simulate('focus', evt); + td.verify(handleFocus(), {times: 1}); + td.verify(onFocus(evt), {times: 1}); +}); + +test('EnhancedSelect onFocus calls handleFocus', () => { + const handleFocus = td.func(); + const onFocus = td.func<(evt: React.FocusEvent) => void>(); + const foundation = coerceForTesting({handleFocus}); + const wrapper = shallow(); + const enhancedSelect = wrapper.find(EnhancedSelect); + const evt = coerceForTesting>({}); + enhancedSelect.simulate('focus', evt); + td.verify(handleFocus(), {times: 1}); + td.verify(onFocus(evt), {times: 1}); +}); + +test('NativeSelect onBlur calls handleBlur', () => { + const handleBlur = td.func(); + const onBlur = td.func<(evt: React.FocusEvent) => void>(); + const foundation = coerceForTesting({handleBlur}); + const wrapper = shallow(); + const nativeSelect = wrapper.find(NativeSelect); + const evt = coerceForTesting>({}); + nativeSelect.simulate('blur', evt); + td.verify(handleBlur(), {times: 1}); + td.verify(onBlur(evt), {times: 1}); +}); + +test('EnhancedSelect onBlur calls handleBlur', () => { + const handleBlur = td.func(); + const onBlur = td.func<(evt: React.FocusEvent) => void>(); + const foundation = coerceForTesting({handleBlur}); + const wrapper = shallow(); + const enhancedSelect = wrapper.find(EnhancedSelect); + const evt = coerceForTesting>({}); + enhancedSelect.simulate('blur', evt); + td.verify(handleBlur(), {times: 1}); + td.verify(onBlur(evt), {times: 1}); +}); + +test('NativeSelect onTouchStart calls handleClick', () => { + const handleClick = td.func(); + const onTouchStart = td.func<(evt: React.TouchEvent) => void>(); + const foundation = coerceForTesting({handleClick}); + const wrapper = shallow(); + const nativeSelect = wrapper.find(NativeSelect); + const clientX = 100; + const left = 10; + const getBoundingClientRect = td.func(); + const currentTarget = coerceForTesting({getBoundingClientRect}); + const evt = coerceForTesting>({ + currentTarget, + nativeEvent: { + touches: [{clientX}], + }, + }); + td.when(getBoundingClientRect()).thenReturn({left}); + + nativeSelect.simulate('touchstart', evt); + td.verify(handleClick(clientX - left), {times: 1}); + td.verify(onTouchStart(evt), {times: 1}); +}); + +test('EnhancedSelect onTouchStart calls handleClick', () => { + const handleClick = td.func(); + const onTouchStart = td.func<(evt: React.TouchEvent) => void>(); + const foundation = coerceForTesting({handleClick}); + const wrapper = shallow(); + const enhancedSelect = wrapper.find(EnhancedSelect); + const clientX = 100; + const left = 10; + const getBoundingClientRect = td.func(); + const currentTarget = coerceForTesting({getBoundingClientRect}); + const evt = coerceForTesting>({ + currentTarget, + nativeEvent: { + touches: [{clientX}], + }, + }); + td.when(getBoundingClientRect()).thenReturn({left}); + + enhancedSelect.simulate('touchstart', evt); + td.verify(handleClick(clientX - left), {times: 1}); + td.verify(onTouchStart(evt), {times: 1}); +}); + +test('NativeSelect onMouseDown calls handleClick', () => { + const handleClick = td.func(); + const onMouseDown = td.func<(evt: React.MouseEvent) => void>(); + const foundation = coerceForTesting({handleClick}); + const wrapper = shallow(); + const nativeSelect = wrapper.find(NativeSelect); + const clientX = 100; + const left = 10; + const getBoundingClientRect = td.func(); + const currentTarget = coerceForTesting({getBoundingClientRect}); + const evt = coerceForTesting>({ + currentTarget, + nativeEvent: {clientX}, + }); + td.when(getBoundingClientRect()).thenReturn({left}); + + nativeSelect.simulate('mousedown', evt); + td.verify(handleClick(clientX - left), {times: 1}); + td.verify(onMouseDown(evt), {times: 1}); +}); + +test('EnhancedSelect onMouseDown calls handleClick', () => { + const handleClick = td.func(); + const onMouseDown = td.func<(evt: React.MouseEvent) => void>(); + const foundation = coerceForTesting({handleClick}); + const wrapper = shallow(); + const enhancedSelect = wrapper.find(EnhancedSelect); + const clientX = 100; + const left = 10; + const getBoundingClientRect = td.func(); + const currentTarget = coerceForTesting({getBoundingClientRect}); + const evt = coerceForTesting>({ + currentTarget, + nativeEvent: {clientX}, + }); + td.when(getBoundingClientRect()).thenReturn({left}); + + enhancedSelect.simulate('mousedown', evt); + td.verify(handleClick(clientX - left), {times: 1}); + td.verify(onMouseDown(evt), {times: 1}); +}); + +test('NativeSelect onClick calls handleClick', () => { + const handleClick = td.func(); + const onClick = td.func<(evt: React.MouseEvent) => void>(); + const foundation = coerceForTesting({handleClick}); + const wrapper = shallow(); + const nativeSelect = wrapper.find(NativeSelect); + const clientX = 100; + const left = 10; + const getBoundingClientRect = td.func(); + const currentTarget = coerceForTesting({getBoundingClientRect}); + const evt = coerceForTesting>({ + currentTarget, + nativeEvent: {clientX}, + }); + td.when(getBoundingClientRect()).thenReturn({left}); + + nativeSelect.simulate('click', evt); + td.verify(handleClick(clientX - left), {times: 1}); + td.verify(onClick(evt), {times: 1}); +}); + +test('EnhancedSelect onClick calls handleClick', () => { + const handleClick = td.func(); + const onClick = td.func<(evt: React.MouseEvent) => void>(); + const foundation = coerceForTesting({handleClick}); + const wrapper = shallow(); + const enhancedSelect = wrapper.find(EnhancedSelect); + const clientX = 100; + const left = 10; + const getBoundingClientRect = td.func(); + const currentTarget = coerceForTesting({getBoundingClientRect}); + const evt = coerceForTesting>({ + currentTarget, + nativeEvent: {clientX}, + }); + td.when(getBoundingClientRect()).thenReturn({left}); + + enhancedSelect.simulate('click', evt); + td.verify(handleClick(clientX - left), {times: 1}); + td.verify(onClick(evt), {times: 1}); +}); + +test('NativeSelect onKeyDown calls props.onKeyDown', () => { + const onKeyDown = td.func<(evt: React.KeyboardEvent) => void>(); + const wrapper = shallow(); + const nativeSelect = wrapper.find(NativeSelect); + const clientX = 100; + const left = 10; + const getBoundingClientRect = td.func(); + const currentTarget = coerceForTesting({getBoundingClientRect}); + const evt = coerceForTesting>({ + currentTarget, + nativeEvent: {clientX}, + }); + td.when(getBoundingClientRect()).thenReturn({left}); + + nativeSelect.simulate('keydown', evt); + td.verify(onKeyDown(evt), {times: 1}); +}); + +test('EnhancedSelect onKeyDown calls handleKeydown', () => { + const handleKeydown = td.func(); + const onKeyDown = td.func<(evt: React.KeyboardEvent) => void>(); + const foundation = coerceForTesting({handleKeydown}); + const wrapper = shallow(); + const enhancedSelect = wrapper.find(EnhancedSelect); + const clientX = 100; + const left = 10; + const getBoundingClientRect = td.func(); + const currentTarget = coerceForTesting({getBoundingClientRect}); + const evt = coerceForTesting>({ + currentTarget, + nativeEvent: {clientX}, + }); + td.when(getBoundingClientRect()).thenReturn({left}); + + enhancedSelect.simulate('keydown', evt); + td.verify(handleKeydown(evt.nativeEvent), {times: 1}); + td.verify(onKeyDown(evt), {times: 1}); +}); + +test('props.selectClassName gets passed to props.className of NativeSelect', () => { + const wrapper = shallow(); + assert.equal(wrapper.find(NativeSelect).props().className, 'test-class-name'); +}); + +test('props.selectClassName gets passed to props.className of EnhancedSelect', () => { + const wrapper = shallow(); + assert.equal(wrapper.find(EnhancedSelect).props().className, 'test-class-name'); +}); diff --git a/test/unit/select/EnhancedSelect.test.tsx b/test/unit/select/EnhancedSelect.test.tsx new file mode 100644 index 000000000..91caac04d --- /dev/null +++ b/test/unit/select/EnhancedSelect.test.tsx @@ -0,0 +1,234 @@ +import * as React from 'react'; +import * as td from 'testdouble'; +import {assert} from 'chai'; +import {shallow, mount} from 'enzyme'; +import EnhancedSelect from '../../../packages/select/EnhancedSelect'; +import {Option} from '../../../packages/select/index'; +import {coerceForTesting} from '../helpers/types'; +import {MDCSelectFoundation} from '@material/select/foundation'; +import Menu from '../../../packages/menu/index'; + +suite('Enhanced Select'); + +const testEvt = { + test: 'test', + clientX: 20, + target: { + getBoundingClientRect: () => ({left: 15}), + value: 'value', + }, +}; + +test('#event.focus calls #props.onFocus', () => { + const onFocus = coerceForTesting>(td.func()); + const wrapper = shallow(); + const selectedTextEl = wrapper.find(MDCSelectFoundation.strings.SELECTED_TEXT_SELECTOR); + selectedTextEl.simulate('focus', testEvt); + td.verify(onFocus(coerceForTesting>(testEvt)), {times: 1}); +}); + +test('#event.click calls #props.onClick', () => { + const onClick = coerceForTesting>(td.func()); + const wrapper = shallow(); + const selectedTextEl = wrapper.find(MDCSelectFoundation.strings.SELECTED_TEXT_SELECTOR); + selectedTextEl.simulate('click', testEvt); + td.verify(onClick(coerceForTesting>(testEvt)), {times: 1}); +}); + + +test('#event.blur calls #props.onBlur', () => { + const onBlur = coerceForTesting>(td.func()); + const wrapper = shallow(); + const selectedTextEl = wrapper.find(MDCSelectFoundation.strings.SELECTED_TEXT_SELECTOR); + selectedTextEl.simulate('blur', testEvt); + td.verify(onBlur(coerceForTesting>(testEvt)), {times: 1}); +}); + +test('#event.mousedown calls #props.onMouseDown', () => { + const onMouseDown = coerceForTesting>(td.func()); + const wrapper = shallow(); + const selectedTextEl = wrapper.find(MDCSelectFoundation.strings.SELECTED_TEXT_SELECTOR); + selectedTextEl.simulate('mousedown', testEvt); + td.verify(onMouseDown(coerceForTesting>(testEvt)), {times: 1}); +}); + +test('#event.touchstart calls #props.onTouchStart', () => { + const onTouchStart = coerceForTesting>(td.func()); + const wrapper = shallow(); + const selectedTextEl = wrapper.find(MDCSelectFoundation.strings.SELECTED_TEXT_SELECTOR); + selectedTextEl.simulate('touchstart', testEvt); + td.verify(onTouchStart(coerceForTesting>(testEvt)), {times: 1}); +}); + +test('#event.keydown calls #props.onKeyDown', () => { + const onKeyDown = coerceForTesting>(td.func()); + const wrapper = shallow(); + const selectedTextEl = wrapper.find(MDCSelectFoundation.strings.SELECTED_TEXT_SELECTOR); + selectedTextEl.simulate('keydown', testEvt); + td.verify(onKeyDown(coerceForTesting>(testEvt)), {times: 1}); +}); + +test('#event.touchstart calls #props.onTouchStart', () => { + const onTouchStart = coerceForTesting>(td.func()); + const wrapper = shallow(); + const selectedTextEl = wrapper.find(MDCSelectFoundation.strings.SELECTED_TEXT_SELECTOR); + const evt = coerceForTesting>({ + test: 'test', + touches: [{clientX: 20}], + target: { + getBoundingClientRect: () => ({left: 15}), + value: 'value', + }, + }); + selectedTextEl.simulate('touchstart', evt); + td.verify(onTouchStart(evt), {times: 1}); +}); + +test('renders children', () => { + const wrapper = shallow( + + + + ); + assert.equal(wrapper.find(Option).length, 1); +}); + +test('state.selectedItem and state.selectedValue updates when props.value updates', () => { + const wrapper = mount( + + + + ); + wrapper.setProps({value: 'test'}); + const listItem = wrapper.find('.mdc-list-item').getDOMNode(); + assert.equal(wrapper.state().selectedItem, listItem); + assert.equal(wrapper.state().selectedValue, 'test'); + wrapper.unmount(); +}); + +test('state.selectedItem and state.selectedValue do not update when props.value updates with no Options', () => { + const wrapper = mount( + + ); + wrapper.setProps({value: 'test'}); + assert.equal(wrapper.state().selectedItem, null); + assert.equal(wrapper.state().selectedValue, ''); + wrapper.unmount(); +}); + +test('listElements returns Option element', () => { + const wrapper = mount( + + + + ); + const listElement = coerceForTesting(wrapper.instance().listElements)[0]; + assert.equal(listElement, wrapper.find('Option').getDOMNode()); + wrapper.unmount(); +}); + +test('Menu.onClose calls sets aria-expanded and calls props.closeMenu, foundation.handleBlur', () => { + const closeMenu = td.func<() => {}>(); + const handleBlur = td.func<() => {}>(); + const foundation = coerceForTesting({handleBlur}); + const wrapper = mount( + + + + ); + wrapper.setState({'aria-expanded': true}); + wrapper.find(Menu).props().onClose!(); + + td.verify(closeMenu(), {times: 1}); + td.verify(handleBlur(), {times: 1}); + assert.equal(wrapper.state()['aria-expanded'], undefined); + wrapper.unmount(); +}); + +test('Menu.onOpen calls sets aria-expanded sets list item to focus', () => { + const div = document.createElement('div'); + document.body.append(div); + const wrapper = mount( + + + , + {attachTo: div} + ); + wrapper.find(Menu).props().onOpen!(); + + assert.equal(document.activeElement, wrapper.find(Option).getDOMNode()); + assert.equal(wrapper.state()['aria-expanded'], true); + div.remove(); + wrapper.unmount(); +}); + +test('renders selectedText element aria-required if props.required true', () => { + const wrapper = mount(); + const selectedText = wrapper.find('.mdc-select__selected-text').getDOMNode(); + assert.equal(selectedText.getAttribute('aria-required'), 'true'); + wrapper.unmount(); +}); + +test('renders selectedText element aria-expanded if state.aria-expanded true', () => { + const wrapper = mount(); + wrapper.setState({'aria-expanded': true}); + const selectedText = wrapper.find('.mdc-select__selected-text').getDOMNode(); + assert.equal(selectedText.getAttribute('aria-expanded'), 'true'); + wrapper.unmount(); +}); + +test('renders selectedText element aria-expanded if state.aria-expanded "true"', () => { + const wrapper = mount(); + wrapper.setState({'aria-expanded': 'true'}); + const selectedText = wrapper.find('.mdc-select__selected-text').getDOMNode(); + assert.equal(selectedText.getAttribute('aria-expanded'), 'true'); + wrapper.unmount(); +}); + +test('renders selectedText element aria-invalid if props.isInvalid is true', () => { + const wrapper = mount(); + const selectedText = wrapper.find('.mdc-select__selected-text').getDOMNode(); + assert.equal(selectedText.getAttribute('aria-invalid'), 'true'); + wrapper.unmount(); +}); + +test('renders selectedText element aria-disabled if props.disabled true', () => { + const wrapper = mount(); + const selectedText = wrapper.find('.mdc-select__selected-text').getDOMNode(); + assert.equal(selectedText.getAttribute('aria-disabled'), 'true'); + wrapper.unmount(); +}); + +test('renders selectedText element aria-disabled as false if props.disabled false', () => { + const wrapper = mount(); + const selectedText = wrapper.find('.mdc-select__selected-text').getDOMNode(); + assert.equal(selectedText.getAttribute('aria-disabled'), 'false'); + wrapper.unmount(); +}); + +test('renders selectedText element tabindex as 0', () => { + const wrapper = mount(); + const selectedText = wrapper.find('.mdc-select__selected-text').getDOMNode(); + assert.equal(selectedText.getAttribute('tabindex'), '0'); + wrapper.unmount(); +}); + +test('renders selectedText element tabindex as -1 if disabled', () => { + const wrapper = mount(); + const selectedText = wrapper.find('.mdc-select__selected-text').getDOMNode(); + assert.equal(selectedText.getAttribute('tabindex'), '-1'); + wrapper.unmount(); +}); + +test('renders selectedText with state.selectedItem trimed', () => { + const wrapper = mount( + + + + ); + assert.equal(wrapper.find('.mdc-select__selected-text').text(), 'MEOW MEOW'); + wrapper.unmount(); +}); diff --git a/test/unit/select/NativeControl.test.tsx b/test/unit/select/NativeControl.test.tsx deleted file mode 100644 index def9168be..000000000 --- a/test/unit/select/NativeControl.test.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import * as React from 'react'; -import * as td from 'testdouble'; -import {assert} from 'chai'; -import {shallow, mount} from 'enzyme'; -import NativeControl from '../../../packages/select/NativeControl'; -import {coerceForTesting} from '../helpers/types'; - -suite('Select Native Input'); - -const testEvt = { - test: 'test', - clientX: 20, - target: { - getBoundingClientRect: () => ({left: 15}), - value: 'value', - }, -}; - -test('has mdc-select__native-control class', () => { - const wrapper = shallow(); - assert.isTrue(wrapper.hasClass('mdc-select__native-control')); -}); - -test('classNames adds classes', () => { - const wrapper = shallow(); - assert.isTrue(wrapper.hasClass('test-class-name')); -}); - -test('calls props.handleDisabled if props.disabled updates', () => { - const handleDisabled = coerceForTesting<(d: boolean) => void>(td.func()); - const wrapper = shallow(); - wrapper.setProps({disabled: true}); - td.verify(handleDisabled(true), {times: 1}); -}); - -test('#event.focus calls #foundation.handleFocus', () => { - const foundation = {handleFocus: td.func()}; - const wrapper = shallow(); - wrapper.simulate('focus', testEvt); - td.verify(foundation.handleFocus(testEvt), {times: 1}); -}); - -test('#event.focus calls #props.onFocus', () => { - const onFocus = coerceForTesting>(td.func()); - const wrapper = shallow(); - wrapper.simulate('focus', testEvt); - td.verify(onFocus(coerceForTesting>(testEvt)), {times: 1}); -}); - -test('#event.blur calls #foundation.handleBlur', () => { - const foundation = {handleBlur: coerceForTesting>(td.func())}; - const wrapper = shallow(); - wrapper.simulate('blur', testEvt); - td.verify(foundation.handleBlur(coerceForTesting>(testEvt)), {times: 1}); -}); - -test('#event.blur calls #props.onBlur', () => { - const onBlur = coerceForTesting>(td.func()); - const wrapper = shallow(); - wrapper.simulate('blur', testEvt); - td.verify(onBlur(coerceForTesting>(testEvt)), {times: 1}); -}); - -test('#event.change calls #props.onChange', () => { - const onChange = coerceForTesting>(td.func()); - const wrapper = shallow(); - wrapper.simulate('change', testEvt); - td.verify(onChange(coerceForTesting>(testEvt)), {times: 1}); -}); - -test('#event.mousedown calls #props.onMouseDown', () => { - const onMouseDown = coerceForTesting>(td.func()); - const wrapper = shallow(); - wrapper.simulate('mousedown', testEvt); - td.verify(onMouseDown(coerceForTesting>(testEvt)), {times: 1}); -}); - -test('#event.mousedown calls #props.setRippleCenter if target is nativeControl', () => { - const setRippleCenter = coerceForTesting<(rippleCenter: number) => void>(td.func()); - const wrapper = mount(); - wrapper.instance().nativeControl_ - = coerceForTesting>({current: testEvt.target}); - wrapper.simulate('mousedown', testEvt); - const left = testEvt.target.getBoundingClientRect().left; - td.verify(setRippleCenter(testEvt.clientX - left), {times: 1}); -}); - -test('#event.mousedown does not call #props.setRippleCenter if target is not nativeControl', () => { - const setRippleCenter = coerceForTesting<(rippleCenter: number) => void>(td.func()); - const wrapper = mount(); - wrapper.simulate('mousedown', testEvt); - const left = testEvt.target.getBoundingClientRect().left; - td.verify(setRippleCenter(testEvt.clientX - left), {times: 0}); -}); - -test('#event.touchstart calls #props.onTouchStart', () => { - const onTouchStart = coerceForTesting>(td.func()); - const wrapper = shallow(); - const evt = coerceForTesting>({ - test: 'test', - touches: [{clientX: 20}], - target: { - getBoundingClientRect: () => ({left: 15}), - value: 'value', - }, - }); - wrapper.simulate('touchstart', evt); - td.verify(onTouchStart(evt), {times: 1}); -}); - -test('#event.touchstart calls #props.setRippleCenter if target is nativeControl', () => { - const setRippleCenter = coerceForTesting<(rippleCenter: number) => void>(td.func()); - const wrapper = mount(); - const evt = { - test: 'test', - touches: [{clientX: 20}], - target: { - getBoundingClientRect: () => ({left: 15}), - value: 'value', - }, - }; - wrapper.instance().nativeControl_ = coerceForTesting>({current: evt.target}); - wrapper.simulate('touchstart', evt); - const left = evt.target.getBoundingClientRect().left; - td.verify(setRippleCenter(20 - left), {times: 1}); -}); - -test('#event.touchstart does not call #props.setRippleCenter if target is not nativeControl', () => { - const setRippleCenter = coerceForTesting<(rippleCenter: number) => void>(td.func()); - const wrapper = mount(); - const evt = { - test: 'test', - touches: [{clientX: 20}], - target: { - getBoundingClientRect: () => ({left: 15}), - value: 'value', - }, - }; - wrapper.simulate('touchstart', evt); - const left = evt.target.getBoundingClientRect().left; - td.verify(setRippleCenter(20 - left), {times: 0}); -}); - -test('renders children', () => { - const wrapper = shallow( - - - - ); - assert.equal(wrapper.find('option[value="test"]').length, 1); -}); diff --git a/test/unit/select/NativeSelect.test.tsx b/test/unit/select/NativeSelect.test.tsx new file mode 100644 index 000000000..2efa8b3b7 --- /dev/null +++ b/test/unit/select/NativeSelect.test.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import {assert} from 'chai'; +import {shallow} from 'enzyme'; +import NativeSelect from '../../../packages/select/NativeSelect'; + +suite('Select Native'); + +test('has mdc-select__native-control class', () => { + const wrapper = shallow(); + assert.isTrue(wrapper.hasClass('mdc-select__native-control')); +}); + +test('classNames adds classes', () => { + const wrapper = shallow(); + assert.isTrue(wrapper.hasClass('test-class-name')); +}); + +test('renders children', () => { + const wrapper = shallow( + + + + ); + assert.equal(wrapper.find('option[value="test"]').length, 1); +}); diff --git a/test/unit/select/Option.test.tsx b/test/unit/select/Option.test.tsx new file mode 100644 index 000000000..4b664ea48 --- /dev/null +++ b/test/unit/select/Option.test.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import {assert} from 'chai'; +import {shallow, mount} from 'enzyme'; +import {Option} from '../../../packages/select/index'; +import {MenuListItem} from '../../../packages/menu/index'; + +suite('Select Options'); + +test('renders an option tag if not enhanced', () => { + const wrapper = shallow(