From 285e195b0e8e713640c9439b8949342b96eb086b Mon Sep 17 00:00:00 2001 From: Evan McLaughlin Date: Mon, 20 Dec 2021 12:17:43 -0500 Subject: [PATCH 01/72] Make UI Strong --- demos/storybook/stories/welcome.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/storybook/stories/welcome.stories.tsx b/demos/storybook/stories/welcome.stories.tsx index 0665d5730..252f6fd0a 100644 --- a/demos/storybook/stories/welcome.stories.tsx +++ b/demos/storybook/stories/welcome.stories.tsx @@ -86,7 +86,7 @@ stories.add('Brightlayer UI React Components', () => {
blui-icon
- Brightlayer UI + Brightlayer UI React Component Library {packageJSON.version && v{packageJSON.version}} From 4499c1de3ed089055782248f380d45c9dfdb4dda Mon Sep 17 00:00:00 2001 From: Evan McLaughlin Date: Mon, 20 Dec 2021 12:26:15 -0500 Subject: [PATCH 02/72] Run prettier --- demos/storybook/stories/welcome.stories.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/demos/storybook/stories/welcome.stories.tsx b/demos/storybook/stories/welcome.stories.tsx index 252f6fd0a..8f94546ec 100644 --- a/demos/storybook/stories/welcome.stories.tsx +++ b/demos/storybook/stories/welcome.stories.tsx @@ -86,7 +86,9 @@ stories.add('Brightlayer UI React Components', () => {
blui-icon
- Brightlayer UI + + Brightlayer UI + React Component Library {packageJSON.version && v{packageJSON.version}} From a9bd3bfc04726a9d234e8266088451f9db528f23 Mon Sep 17 00:00:00 2001 From: daileytj Date: Mon, 20 Dec 2021 12:59:39 -0500 Subject: [PATCH 03/72] Update submodule pointer --- .gitmodules | 2 +- demos/showcase | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index eab36736d..0eccb03a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "demos/showcase"] path = demos/showcase - url = https://github.com/pxblue/react-showcase-demo + url = https://github.com/brightlayer-ui/react-showcase-demo branch = dev diff --git a/demos/showcase b/demos/showcase index 4fed6d0e3..991a41e30 160000 --- a/demos/showcase +++ b/demos/showcase @@ -1 +1 @@ -Subproject commit 4fed6d0e3be4e74bb14180b6f3bb84b4c843a97c +Subproject commit 991a41e304657334ba7fc1e1a142e8afa5741965 From 18b77b761f54316319f4d2f9567b3d6b590b4b9e Mon Sep 17 00:00:00 2001 From: daileytj Date: Thu, 6 Jan 2022 15:49:27 -0500 Subject: [PATCH 04/72] Update README.md links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5bf3dd9fd..a420a50fe 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This is a library of re-usable React components for use in Brightlayer UI applications. For the most part, these components are meant to simplify building your application by providing drop-in components that implement common use cases in Brightlayer UI and eliminate the need for multiple teams to build their own components for these. -Refer to the [Component Library](https://brightlayer-ui-components.github.io/react/?path=/story/channel-value--with-value) API documentation site for a list of available components or see the repository [documentation](https://github.com/brightlayer-ui/react-component-library/tree/dev/docs) for each individual component. +Refer to the [Component Library](https://brightlayer-ui-components.github.io/react/?path=/story/channel-value--with-value) API documentation site for a list of available components or see the repository [documentation](https://github.com/brightlayer-ui/react-component-library/tree/master/docs) for each individual component. ## Installation @@ -58,7 +58,7 @@ from the root directory. ## Using the Components -See the [documentation](https://github.com/brightlayer-ui/react-component-library/tree/dev/docs) for information on using these components. +See the [documentation](https://github.com/brightlayer-ui/react-component-library/tree/master/docs) for information on using these components. ## Browser Support From 861a85fbb33555d0903ed9c84cd683834763bb08 Mon Sep 17 00:00:00 2001 From: huayunh <96_mouse@sina.com> Date: Fri, 7 Jan 2022 12:15:42 -0500 Subject: [PATCH 05/72] Make changelog more clear --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b91d72202..942ba320f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### Fixed -- Avoid rendering of HTML elements in DOM when `subtitle` or `info` prop is not available. +- Avoid rendering of HTML elements in ``'s DOM tree when `subtitle` or `info` prop is not available. ([#318](https://github.com/brightlayer-ui/react-component-library/issues/318)) + ## v5.3.2 (November 11, 2021) ### Changed From f387deb3986ff626d26bc18d51a764a9f00d0f92 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Mon, 10 Jan 2022 17:09:57 +0530 Subject: [PATCH 06/72] 2714 Changed chevron color to gray in right component in info list item --- components/src/core/InfoListItem/InfoListItem.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/src/core/InfoListItem/InfoListItem.tsx b/components/src/core/InfoListItem/InfoListItem.tsx index 9e2bc6040..a8ba5c2db 100644 --- a/components/src/core/InfoListItem/InfoListItem.tsx +++ b/components/src/core/InfoListItem/InfoListItem.tsx @@ -6,6 +6,7 @@ import ListItemAvatar from '@material-ui/core/ListItemAvatar'; import ListItemText from '@material-ui/core/ListItemText'; import Typography from '@material-ui/core/Typography'; import Chevron from '@material-ui/icons/ChevronRight'; +import * as Colors from '@brightlayer-ui/colors'; import { InfoListItemClasses, useStyles } from './InfoListItem.styles'; @@ -152,6 +153,7 @@ const InfoListItemRender: React.ForwardRefRenderFunction ); } From 138881b10b572cb16d7a8804690427018fb08f5a Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Mon, 10 Jan 2022 17:41:11 +0530 Subject: [PATCH 07/72] 2714 Updated Changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b91d72202..46b1eac64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,11 @@ # Changelog + +## v5.3.4 (Not yet published) + +### Fixed + +- Fixed `InfoListItem` right component chevron color to be `gray[500]` + ## v5.3.3 (December 6, 2021) ### Fixed From e7a083ee49be1ee1fc5a50c0c8ba3571f1428621 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Tue, 11 Jan 2022 14:31:32 +0530 Subject: [PATCH 08/72] 2714 Added a class for chevron icon and changed color to secondary --- components/src/core/InfoListItem/InfoListItem.styles.tsx | 4 ++++ components/src/core/InfoListItem/InfoListItem.tsx | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/components/src/core/InfoListItem/InfoListItem.styles.tsx b/components/src/core/InfoListItem/InfoListItem.styles.tsx index dc5ca08a2..ece8d5162 100644 --- a/components/src/core/InfoListItem/InfoListItem.styles.tsx +++ b/components/src/core/InfoListItem/InfoListItem.styles.tsx @@ -15,6 +15,7 @@ export type InfoListItemClasses = { statusStripe?: string; subtitle?: string; title?: string; + chevronIcon?: string; }; const getHeight = (props: InfoListItemProps): string => (props.dense ? `3.25rem` : `4.5rem`); @@ -107,6 +108,9 @@ export const useStyles = makeStyles((theme: Theme) => display: 'flex', alignItems: 'center', }, + chevronIcon: { + color: theme.palette.text.secondary, + }, separator: { display: 'inline-block', lineHeight: 1.3, diff --git a/components/src/core/InfoListItem/InfoListItem.tsx b/components/src/core/InfoListItem/InfoListItem.tsx index a8ba5c2db..4e5baad40 100644 --- a/components/src/core/InfoListItem/InfoListItem.tsx +++ b/components/src/core/InfoListItem/InfoListItem.tsx @@ -152,8 +152,7 @@ const InfoListItemRender: React.ForwardRefRenderFunction ); } @@ -260,6 +259,7 @@ InfoListItem.propTypes = { avatar: PropTypes.string, icon: PropTypes.string, rightComponent: PropTypes.string, + chevronIcon: PropTypes.string, separator: PropTypes.string, subtitle: PropTypes.string, title: PropTypes.string, From ee917e835fa9d9601f9579d60c795c0a32f421a1 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Tue, 11 Jan 2022 14:36:11 +0530 Subject: [PATCH 09/72] Removed unused import of Colors --- components/src/core/InfoListItem/InfoListItem.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/components/src/core/InfoListItem/InfoListItem.tsx b/components/src/core/InfoListItem/InfoListItem.tsx index 4e5baad40..e37c3762a 100644 --- a/components/src/core/InfoListItem/InfoListItem.tsx +++ b/components/src/core/InfoListItem/InfoListItem.tsx @@ -6,7 +6,6 @@ import ListItemAvatar from '@material-ui/core/ListItemAvatar'; import ListItemText from '@material-ui/core/ListItemText'; import Typography from '@material-ui/core/Typography'; import Chevron from '@material-ui/icons/ChevronRight'; -import * as Colors from '@brightlayer-ui/colors'; import { InfoListItemClasses, useStyles } from './InfoListItem.styles'; From 6910eef2892a0eedffdba628b93c0cd9f7e55a07 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Tue, 11 Jan 2022 15:31:45 +0530 Subject: [PATCH 10/72] 2714 Added chevronColor prop to InfoListItem --- CHANGELOG.md | 4 ++-- components/src/core/InfoListItem/InfoListItem.styles.tsx | 7 ++++++- components/src/core/InfoListItem/InfoListItem.tsx | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46b1eac64..390e2f8c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,9 @@ ## v5.3.4 (Not yet published) -### Fixed +### Added -- Fixed `InfoListItem` right component chevron color to be `gray[500]` +- Added `chevronColor` property onto ``. ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/InfoListItem/InfoListItem.styles.tsx b/components/src/core/InfoListItem/InfoListItem.styles.tsx index ece8d5162..82231a75a 100644 --- a/components/src/core/InfoListItem/InfoListItem.styles.tsx +++ b/components/src/core/InfoListItem/InfoListItem.styles.tsx @@ -42,6 +42,11 @@ const getIconAlignment = (props: InfoListItemProps): 'flex-end' | 'flex-start' | } }; +const getChevronColor = (props: InfoListItemProps, theme: Theme): string => { + const { chevronColor } = props; + return chevronColor ? chevronColor : theme.palette.text.secondary; +}; + /* eslint-disable @typescript-eslint/explicit-function-return-type */ export const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -109,7 +114,7 @@ export const useStyles = makeStyles((theme: Theme) => alignItems: 'center', }, chevronIcon: { - color: theme.palette.text.secondary, + color: (props) => getChevronColor(props, theme), }, separator: { display: 'inline-block', diff --git a/components/src/core/InfoListItem/InfoListItem.tsx b/components/src/core/InfoListItem/InfoListItem.tsx index e37c3762a..5bc719d93 100644 --- a/components/src/core/InfoListItem/InfoListItem.tsx +++ b/components/src/core/InfoListItem/InfoListItem.tsx @@ -86,6 +86,8 @@ export type InfoListItemProps = Omit & { * Default: false */ wrapTitle?: boolean; + /** Color override for the chevron icon */ + chevronColor?: string; }; const InfoListItemRender: React.ForwardRefRenderFunction = ( props: InfoListItemProps, @@ -117,6 +119,7 @@ const InfoListItemRender: React.ForwardRefRenderFunction Date: Tue, 11 Jan 2022 15:49:19 +0530 Subject: [PATCH 11/72] 2714 Updated readme with newly added prop --- docs/InfoListItem.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/InfoListItem.md b/docs/InfoListItem.md index 5c867442f..923c2eebc 100644 --- a/docs/InfoListItem.md +++ b/docs/InfoListItem.md @@ -49,6 +49,7 @@ import * as Colors from '@brightlayer-ui/colors'; | wrapInfo | Whether to wrap info on overflow | `boolean` | no | false | | wrapSubtitle | Whether to wrap subtitle on overflow | `boolean` | no | false | | wrapTitle | Whether to wrap title on overflow | `boolean` | no | false | +| chevronColor | Color override for the chevron icon | `string` | no | | From 0c3d31ad5d3e3b91c07aea5e6e0733d38a4a212f Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Tue, 11 Jan 2022 23:15:07 +0530 Subject: [PATCH 12/72] 2714 Updated InfoListItem readme --- docs/InfoListItem.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/InfoListItem.md b/docs/InfoListItem.md index 923c2eebc..deec7da9b 100644 --- a/docs/InfoListItem.md +++ b/docs/InfoListItem.md @@ -29,6 +29,7 @@ import * as Colors from '@brightlayer-ui/colors'; | avatar | Show colored background for icon | `boolean` | no | false | | backgroundColor | The color used for the background | `string` | no | | | chevron | Add a chevron icon on the right | `boolean` | no | false | +| chevronColor | Color override for the chevron icon | `string` | no | | | classes | Style overrides | `InfoListItemClasses` | no | | | dense | Smaller height row with less padding | `boolean` | no | false | | divider | Show a row separator below the row | `'full'` \| `'partial'` | no | | @@ -49,7 +50,6 @@ import * as Colors from '@brightlayer-ui/colors'; | wrapInfo | Whether to wrap info on overflow | `boolean` | no | false | | wrapSubtitle | Whether to wrap subtitle on overflow | `boolean` | no | false | | wrapTitle | Whether to wrap title on overflow | `boolean` | no | false | -| chevronColor | Color override for the chevron icon | `string` | no | | From 8bacf0e27a0cf67a95f2e7f09510dfcac3b99e0a Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Tue, 11 Jan 2022 23:23:24 +0530 Subject: [PATCH 13/72] Updated changelog and readme with new class --- CHANGELOG.md | 1 + docs/InfoListItem.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66720ec2a..ee9ff7b26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - Added `chevronColor` property onto ``. +- Added `chevronIcon` class for `chevron` element in ``. ## v5.3.3 (December 6, 2021) diff --git a/docs/InfoListItem.md b/docs/InfoListItem.md index deec7da9b..5902d8580 100644 --- a/docs/InfoListItem.md +++ b/docs/InfoListItem.md @@ -63,6 +63,7 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. | -------------- | --------------------------------------------------- | | root | Styles applied to the root element | | avatar | Styles applied to the Avatar element | +| chevronIcon | Styles applied to the chevron element | | divider | Styles applied to the divider element | | icon | Styles applied to the icon element | | info | Styles applied to the third line of text element | From 5aaabe2d0fcac05652ca5123f20524e67a7b4486 Mon Sep 17 00:00:00 2001 From: jeffvg Date: Tue, 11 Jan 2022 13:43:20 -0500 Subject: [PATCH 14/72] echo da id --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index e274ce884..4d4d51f1d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -116,8 +116,10 @@ jobs: STORYBOOK_GA_ID=$MASTER_GA fi if [ $CIRCLE_BRANCH == $DEV_BRANCH ]; then + STORYBOOK_GA_ID=$DEV_GA; else STORYBOOK_GA_ID=$DEV_GA fi + echo $STORYBOOK_GA_ID yarn build-storybook cd storybook-static From dc6354a5a17742699248c3d80d6c4b0c3430607d Mon Sep 17 00:00:00 2001 From: jeffvg Date: Tue, 11 Jan 2022 14:19:22 -0500 Subject: [PATCH 15/72] test echo --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4d4d51f1d..a0518eab3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -115,6 +115,7 @@ jobs: if [ $CIRCLE_BRANCH == $MASTER_BRANCH ]; then STORYBOOK_GA_ID=$MASTER_GA fi + echo test echo if [ $CIRCLE_BRANCH == $DEV_BRANCH ]; then STORYBOOK_GA_ID=$DEV_GA; else STORYBOOK_GA_ID=$DEV_GA From 179decfee16d8ce855a7a09494956399cb233b5e Mon Sep 17 00:00:00 2001 From: daileytj Date: Wed, 12 Jan 2022 08:20:00 -0500 Subject: [PATCH 16/72] Update package version --- CHANGELOG.md | 2 +- components/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee9ff7b26..c90d53800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v5.3.4 (Not yet published) +## v5.4.0 (Unreleased) ### Added diff --git a/components/package.json b/components/package.json index dcc1abe14..ef5579259 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "@brightlayer-ui/react-components", - "version": "5.3.3", + "version": "5.4.0-beta.0", "description": "React components for Brightlayer UI applications", "scripts": { "test": "jest src", From 88493fd4caf5f08c886aa2cdf0befb0c8ef6f45e Mon Sep 17 00:00:00 2001 From: jeffvg Date: Wed, 12 Jan 2022 12:35:27 -0500 Subject: [PATCH 17/72] deploy feature branch to dev --- .circleci/config.yml | 7 +- demos/storybook/package.json | 6 +- demos/storybook/yarn.lock | 290 +++++++++++++++++++++++++++++++++-- 3 files changed, 281 insertions(+), 22 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a0518eab3..14cbe6c2b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -74,7 +74,7 @@ jobs: - image: circleci/node:12.9.1-browsers environment: - MASTER_BRANCH: master - - DEV_BRANCH: dev + - DEV_BRANCH: feature/analytics steps: - checkout - attach_workspace: @@ -115,7 +115,6 @@ jobs: if [ $CIRCLE_BRANCH == $MASTER_BRANCH ]; then STORYBOOK_GA_ID=$MASTER_GA fi - echo test echo if [ $CIRCLE_BRANCH == $DEV_BRANCH ]; then STORYBOOK_GA_ID=$DEV_GA; else STORYBOOK_GA_ID=$DEV_GA @@ -184,7 +183,7 @@ jobs: - image: circleci/node:12.9.1-browsers environment: - MASTER_BRANCH: master - - DEV_BRANCH: dev + - DEV_BRANCH: feature/analytics - DEV_TARGET: https://github.com/brightlayer-ui-components/react-dev - MASTER_TARGET: https://github.com/brightlayer-ui-components/react - GH_EMAIL: brightlayer-ui@eaton.com @@ -265,7 +264,7 @@ workflows: branches: only: - master - - dev + - feature/analytics - publish: requires: - build_storybook diff --git a/demos/storybook/package.json b/demos/storybook/package.json index fa259671d..a78973429 100644 --- a/demos/storybook/package.json +++ b/demos/storybook/package.json @@ -4,14 +4,14 @@ "private": true, "prettier": "@brightlayer-ui/prettier-config", "dependencies": { - "@material-ui/core": "^4.7.2", - "@material-ui/icons": "^4.5.1", "@brightlayer-ui/colors": "^3.0.1", "@brightlayer-ui/icons-mui": "^2.7.0", "@brightlayer-ui/react-components": "^5.3.2-beta.0", "@brightlayer-ui/react-themes": "^6.1.0", "@brightlayer-ui/storybook-rtl-addon": "^1.1.0", "@brightlayer-ui/storybook-themes": "^1.1.0", + "@material-ui/core": "^4.7.2", + "@material-ui/icons": "^4.5.1", "@sambego/storybook-state": "^2.0.0", "@storybook/addon-actions": "^5.3.18", "@storybook/addon-info": "^5.3.18", @@ -58,7 +58,7 @@ "@brightlayer-ui/eslint-config": "2.0.5", "@brightlayer-ui/prettier-config": "1.0.3", "@storybook/addon-a11y": "^5.3.18", - "@storybook/addon-google-analytics": "^5.3.18", + "@storybook/addon-google-analytics": "^6.2.9", "@types/node": "12.11.7", "@types/react": "16.9.43", "@types/react-dom": "16.9.3", diff --git a/demos/storybook/yarn.lock b/demos/storybook/yarn.lock index 6a05dd8a2..c16952df5 100644 --- a/demos/storybook/yarn.lock +++ b/demos/storybook/yarn.lock @@ -1137,6 +1137,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.14.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" + integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/standalone@^7.4.5": version "7.12.6" resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.12.6.tgz#fa59cf6f1cea940a790179f1375394ab31f025b9" @@ -1303,6 +1310,18 @@ "@emotion/sheet" "0.9.4" "@emotion/utils" "0.11.3" +"@emotion/core@^10.1.1": + version "10.3.1" + resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.3.1.tgz#4021b6d8b33b3304d48b0bb478485e7d7421c69d" + integrity sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww== + dependencies: + "@babel/runtime" "^7.5.5" + "@emotion/cache" "^10.0.27" + "@emotion/css" "^10.0.27" + "@emotion/serialize" "^0.11.15" + "@emotion/sheet" "0.9.4" + "@emotion/utils" "0.11.3" + "@emotion/css@^10.0.27", "@emotion/css@^10.0.9": version "10.0.27" resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.27.tgz#3a7458198fbbebb53b01b2b87f64e5e21241e14c" @@ -1317,7 +1336,7 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@emotion/is-prop-valid@0.8.8": +"@emotion/is-prop-valid@0.8.8", "@emotion/is-prop-valid@^0.8.6": version "0.8.8" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== @@ -1355,6 +1374,16 @@ "@emotion/serialize" "^0.11.15" "@emotion/utils" "0.11.3" +"@emotion/styled-base@^10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.3.0.tgz#9aa2c946100f78b47316e4bc6048321afa6d4e36" + integrity sha512-PBRqsVKR7QRNkmfH78hTSSwHWcwDpecH9W6heujWAcyp2wdz/64PP73s7fWS1dIPm8/Exc8JAzYS8dEWXjv60w== + dependencies: + "@babel/runtime" "^7.5.5" + "@emotion/is-prop-valid" "0.8.8" + "@emotion/serialize" "^0.11.15" + "@emotion/utils" "0.11.3" + "@emotion/styled@^10.0.17": version "10.0.27" resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.27.tgz#12cb67e91f7ad7431e1875b1d83a94b814133eaf" @@ -1363,6 +1392,14 @@ "@emotion/styled-base" "^10.0.27" babel-plugin-emotion "^10.0.27" +"@emotion/styled@^10.0.27": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.3.0.tgz#8ee959bf75730789abb5f67f7c3ded0c30aec876" + integrity sha512-GgcUpXBBEU5ido+/p/mCT2/Xx+Oqmp9JzQRuC+a4lYM4i4LBBn/dWvc0rQ19N9ObA8/T4NWMrPNe79kMBDJqoQ== + dependencies: + "@emotion/styled-base" "^10.3.0" + babel-plugin-emotion "^10.0.27" + "@emotion/stylis@0.8.5": version "0.8.5" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" @@ -1694,7 +1731,7 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@reach/router@^1.2.1": +"@reach/router@^1.2.1", "@reach/router@^1.3.4": version "1.3.4" resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.3.4.tgz#d2574b19370a70c80480ed91f3da840136d10f8c" integrity sha512-+mtn9wjlB9NN2CNnnC/BRYtwdKBfSyyasPYraNAyvaV1occr/5NnB4CVzjEZipNHwYebQwcndGUmpFzxAUoqSA== @@ -1757,16 +1794,17 @@ react-inspector "^4.0.0" uuid "^3.3.2" -"@storybook/addon-google-analytics@^5.3.18": - version "5.3.21" - resolved "https://registry.yarnpkg.com/@storybook/addon-google-analytics/-/addon-google-analytics-5.3.21.tgz#e395027360bc1dca2d2cf2c0f7e217990aab33bb" - integrity sha512-JKa/RcWXqVQfCHcEKqbsImegPTYF0KKsNXCc9Gkwm7/SmunQGCJHN74/ZASoNrBnXocVaQrzvv2mUIYWAb31gA== +"@storybook/addon-google-analytics@^6.2.9": + version "6.2.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-google-analytics/-/addon-google-analytics-6.2.9.tgz#400ca73445eaedeeab58a37dc4f40d012182f5cd" + integrity sha512-L+cSXCWZ6y0QWd2gSeUGBfA6iVCirI/OF2TtlbeJkFshqtKlT2ypwtKaGHK9Euw1e0PbS0+RTUW31m96ofBhDg== dependencies: - "@storybook/addons" "5.3.21" - "@storybook/core-events" "5.3.21" - core-js "^3.0.1" - global "^4.3.2" - react-ga "^2.5.7" + "@storybook/addons" "6.2.9" + "@storybook/core-events" "6.2.9" + core-js "^3.8.2" + global "^4.4.0" + react-ga "^2.7.0" + regenerator-runtime "^0.13.7" "@storybook/addon-info@^5.3.18": version "5.3.21" @@ -1897,6 +1935,21 @@ global "^4.3.2" util-deprecate "^1.0.2" +"@storybook/addons@6.2.9": + version "6.2.9" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.2.9.tgz#b7ba2b9f0e15b852c7d6b57d04fb0a493c57477c" + integrity sha512-GnmEKbJwiN1jncN9NSA8CuR1i2XAlasPcl/Zn0jkfV9WitQeczVcJCPw86SGH84AD+tTBCyF2i9UC0KaOV1YBQ== + dependencies: + "@storybook/api" "6.2.9" + "@storybook/channels" "6.2.9" + "@storybook/client-logger" "6.2.9" + "@storybook/core-events" "6.2.9" + "@storybook/router" "6.2.9" + "@storybook/theming" "6.2.9" + core-js "^3.8.2" + global "^4.4.0" + regenerator-runtime "^0.13.7" + "@storybook/api@5.3.21", "@storybook/api@^5.3.3": version "5.3.21" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.3.21.tgz#8f1772de53b65e1a65d2f0257463d621a8617c58" @@ -1923,6 +1976,32 @@ telejson "^3.2.0" util-deprecate "^1.0.2" +"@storybook/api@6.2.9": + version "6.2.9" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.2.9.tgz#a9b46569192ad5d8da6435c9d63dc4b0c8463b51" + integrity sha512-okkA3HAScE9tGnYBrjTOcgzT+L1lRHNoEh3ZfGgh1u/XNEyHGNkj4grvkd6nX7BzRcYQ/l2VkcKCqmOjUnSkVQ== + dependencies: + "@reach/router" "^1.3.4" + "@storybook/channels" "6.2.9" + "@storybook/client-logger" "6.2.9" + "@storybook/core-events" "6.2.9" + "@storybook/csf" "0.0.1" + "@storybook/router" "6.2.9" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.2.9" + "@types/reach__router" "^1.3.7" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.20" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + store2 "^2.12.0" + telejson "^5.1.0" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/channel-postmessage@5.3.21": version "5.3.21" resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.3.21.tgz#9c08bf1c108ff973dbca18e582680d25178db1d4" @@ -1941,6 +2020,15 @@ dependencies: core-js "^3.0.1" +"@storybook/channels@6.2.9": + version "6.2.9" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.2.9.tgz#a9fd7f25102cbec15fb56f76abf891b7b214e9de" + integrity sha512-6dC8Fb2ipNyOQXnUZMDeEUaJGH5DMLzyHlGLhVyDtrO5WR6bO8mQdkzf4+5dSKXgCBNX0BSkssXth4pDjn18rg== + dependencies: + core-js "^3.8.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/client-api@5.3.21": version "5.3.21" resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.3.21.tgz#5b218a28f24219c32ab4b92a6af2a3e452fb8089" @@ -1971,6 +2059,14 @@ dependencies: core-js "^3.0.1" +"@storybook/client-logger@6.2.9": + version "6.2.9" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.2.9.tgz#77c1ea39684ad2a2cf6836051b381fc5b354e132" + integrity sha512-IfOQZuvpjh66qBInQCJOb9S0dTGpzZ/Cxlcvokp+PYt95KztaWN3mPm+HaDQCeRsrWNe0Bpm1zuickcJ6dBOXg== + dependencies: + core-js "^3.8.2" + global "^4.4.0" + "@storybook/components@5.3.21", "@storybook/components@^5.3.3": version "5.3.21" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.3.21.tgz#17ee371a2455c6e807c3d3135a9266e63ad7651a" @@ -2005,6 +2101,13 @@ dependencies: core-js "^3.0.1" +"@storybook/core-events@6.2.9": + version "6.2.9" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.2.9.tgz#4f12947cd15d1eb3c4109923657c012feef521cd" + integrity sha512-xQmbX/oYQK1QsAGN8hriXX5SUKOoTUe3L4dVaVHxJqy7MReRWJpprJmCpbAPJzWS6WCbDFfCM5kVEexHLOzJlQ== + dependencies: + core-js "^3.8.2" + "@storybook/core@5.3.21": version "5.3.21" resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.3.21.tgz#da963166ea24601f318266a3aa6bbc06fc8fb175" @@ -2155,6 +2258,30 @@ qs "^6.6.0" util-deprecate "^1.0.2" +"@storybook/router@6.2.9": + version "6.2.9" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.2.9.tgz#547543031dd8330870bb6b473dcf7e51982e841c" + integrity sha512-7Bn1OFoItCl8whXRT8N1qp1Lky7kzXJ3aslWp5E8HcM8rxh4OYXfbaeiyJEJxBTGC5zxgY+tAEXHFjsAviFROg== + dependencies: + "@reach/router" "^1.3.4" + "@storybook/client-logger" "6.2.9" + "@types/reach__router" "^1.3.7" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.20" + memoizerific "^1.11.3" + qs "^6.10.0" + ts-dedent "^2.0.0" + +"@storybook/semver@^7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@storybook/semver/-/semver-7.3.2.tgz#f3b9c44a1c9a0b933c04e66d0048fcf2fa10dac0" + integrity sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg== + dependencies: + core-js "^3.6.5" + find-up "^4.1.0" + "@storybook/source-loader@5.3.21": version "5.3.21" resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-5.3.21.tgz#d5f8758fc6b2d9f0ca45e2ffbffa513d5151fd9e" @@ -2189,6 +2316,24 @@ resolve-from "^5.0.0" ts-dedent "^1.1.0" +"@storybook/theming@6.2.9": + version "6.2.9" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.2.9.tgz#16bf40180861f222c7ed1d80abd5d1e3cb315660" + integrity sha512-183oJW7AD7Fhqg5NT4ct3GJntwteAb9jZnQ6yhf9JSdY+fk8OhxRbPf7ov0au2gYACcGrWDd9K5pYQsvWlP5gA== + dependencies: + "@emotion/core" "^10.1.1" + "@emotion/is-prop-valid" "^0.8.6" + "@emotion/styled" "^10.0.27" + "@storybook/client-logger" "6.2.9" + core-js "^3.8.2" + deep-object-diff "^1.1.0" + emotion-theming "^10.0.27" + global "^4.4.0" + memoizerific "^1.11.3" + polished "^4.0.5" + resolve-from "^5.0.0" + ts-dedent "^2.0.0" + "@storybook/ui@5.3.21": version "5.3.21" resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.3.21.tgz#b42568e03353b47aaab1b6449311f38858585f81" @@ -2466,6 +2611,13 @@ "@types/history" "*" "@types/react" "*" +"@types/reach__router@^1.3.7": + version "1.3.10" + resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.10.tgz#141d500213a452d9d9d71d5ad96c4104094f55a3" + integrity sha512-iHAFGaVOrWi00/q7oBybggGsz5TOmwOW4M1H9sT7i9lly4qFC8XOgsdf6jUsoaOz2sknFHALEtZqCoDbokdJ2Q== + dependencies: + "@types/react" "*" + "@types/react-color@^3.0.1": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/react-color/-/react-color-3.0.4.tgz#c63daf012ad067ac0127bdd86725f079d02082bd" @@ -4312,6 +4464,14 @@ call-bind@^1.0.0: function-bind "^1.1.1" get-intrinsic "^1.0.0" +call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -4915,6 +5075,11 @@ core-js@^3.0.1, core-js@^3.0.4, core-js@^3.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== +core-js@^3.6.5, core-js@^3.8.2: + version "3.20.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.2.tgz#46468d8601eafc8b266bd2dd6bf9dee622779581" + integrity sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -5790,6 +5955,15 @@ emotion-theming@^10.0.19: "@emotion/weak-memoize" "0.2.5" hoist-non-react-statics "^3.3.0" +emotion-theming@^10.0.27: + version "10.3.0" + resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.3.0.tgz#7f84d7099581d7ffe808aab5cd870e30843db72a" + integrity sha512-mXiD2Oj7N9b6+h/dC6oLf9hwxbtKHQjoIqtodEyL8CpkN4F3V4IK/BT4D0C7zSs4BBFOu4UlPJbvvBLa88SGEA== + dependencies: + "@babel/runtime" "^7.5.5" + "@emotion/weak-memoize" "0.2.5" + hoist-non-react-statics "^3.3.0" + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -6457,7 +6631,7 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-deep-equal@^3.0.0, fast-deep-equal@^3.1.1: +fast-deep-equal@^3.0.0, fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -6976,6 +7150,15 @@ get-intrinsic@^1.0.0: has "^1.0.3" has-symbols "^1.0.1" +get-intrinsic@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -7239,6 +7422,18 @@ has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -7999,7 +8194,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-function@^1.0.1: +is-function@^1.0.1, is-function@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== @@ -8120,6 +8315,14 @@ is-regex@^1.0.4, is-regex@^1.1.1: dependencies: has-symbols "^1.0.1" +is-regex@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -9235,7 +9438,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.0.0, lodash@~4.17.10: +lodash@^4.0.0, lodash@^4.17.21, lodash@~4.17.10: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -10044,6 +10247,11 @@ object-inspect@^1.8.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== +object-inspect@^1.9.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== + object-is@^1.0.1: version "1.1.3" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81" @@ -10654,6 +10862,13 @@ polished@^3.3.1: dependencies: "@babel/runtime" "^7.9.2" +polished@^4.0.5: + version "4.1.3" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.1.3.tgz#7a3abf2972364e7d97770b827eec9a9e64002cfc" + integrity sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA== + dependencies: + "@babel/runtime" "^7.14.0" + popper.js@1.16.1-lts: version "1.16.1-lts" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" @@ -11572,6 +11787,13 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@^6.10.0: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + qs@^6.6.0: version "6.9.4" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" @@ -11838,7 +12060,7 @@ react-focus-lock@^2.1.0: use-callback-ref "^1.2.1" use-sidecar "^1.0.1" -react-ga@^2.5.7: +react-ga@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-2.7.0.tgz#24328f157f31e8cffbf4de74a3396536679d8d7c" integrity sha512-AjC7UOZMvygrWTc2hKxTDvlMXEtbmA0IgJjmkhgmQQ3RkXrWR11xEagLGFGaNyaPnmg24oaIiaNPnEoftUhfXA== @@ -12205,6 +12427,11 @@ regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.3, regenerator-runtime@^0 resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== +regenerator-runtime@^0.13.7: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + regenerator-transform@^0.14.2: version "0.14.5" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" @@ -12891,6 +13118,15 @@ side-channel@^1.0.2: es-abstract "^1.18.0-next.0" object-inspect "^1.8.0" +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" @@ -13192,6 +13428,11 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= +store2@^2.12.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/store2/-/store2-2.13.1.tgz#fae7b5bb9d35fc53dc61cd262df3abb2f6e59022" + integrity sha512-iJtHSGmNgAUx0b/MCS6ASGxb//hGrHHRgzvN+K5bvkBTN7A9RTpPSf1WSp+nPGvWCJ1jRnvY7MKnuqfoi3OEqg== + store2@^2.7.1: version "2.12.0" resolved "https://registry.yarnpkg.com/store2/-/store2-2.12.0.tgz#e1f1b7e1a59b6083b2596a8d067f6ee88fd4d3cf" @@ -13563,6 +13804,20 @@ telejson@^3.2.0: lodash "^4.17.15" memoizerific "^1.11.3" +telejson@^5.1.0: + version "5.3.3" + resolved "https://registry.yarnpkg.com/telejson/-/telejson-5.3.3.tgz#fa8ca84543e336576d8734123876a9f02bf41d2e" + integrity sha512-PjqkJZpzEggA9TBpVtJi1LVptP7tYtXB6rEubwlHap76AMjzvOdKX41CxyaW7ahhzDU1aftXnMCx5kAPDZTQBA== + dependencies: + "@types/is-function" "^1.0.0" + global "^4.4.0" + is-function "^1.0.2" + is-regex "^1.1.2" + is-symbol "^1.0.3" + isobject "^4.0.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + term-size@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" @@ -13773,6 +14028,11 @@ ts-dedent@^1.1.0: resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-1.2.0.tgz#6aa2229d837159bb6d635b6b233002423b91e0b0" integrity sha512-6zSJp23uQI+Txyz5LlXMXAHpUhY4Hi0oluXny0OgIR7g/Cromq4vDBnhtbBdyIV34g0pgwxUvnvg+jLJe4c1NA== +ts-dedent@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + ts-loader@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.2.tgz#dffa3879b01a1a1e0a4b85e2b8421dc0dfff1c58" From 30782128d5cb69f21d55055eb7e5c3d49234fdda Mon Sep 17 00:00:00 2001 From: jeffvg Date: Wed, 12 Jan 2022 13:23:57 -0500 Subject: [PATCH 18/72] remove echo & feature branch --- .circleci/config.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 14cbe6c2b..e274ce884 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -74,7 +74,7 @@ jobs: - image: circleci/node:12.9.1-browsers environment: - MASTER_BRANCH: master - - DEV_BRANCH: feature/analytics + - DEV_BRANCH: dev steps: - checkout - attach_workspace: @@ -116,10 +116,8 @@ jobs: STORYBOOK_GA_ID=$MASTER_GA fi if [ $CIRCLE_BRANCH == $DEV_BRANCH ]; then - STORYBOOK_GA_ID=$DEV_GA; else STORYBOOK_GA_ID=$DEV_GA fi - echo $STORYBOOK_GA_ID yarn build-storybook cd storybook-static @@ -183,7 +181,7 @@ jobs: - image: circleci/node:12.9.1-browsers environment: - MASTER_BRANCH: master - - DEV_BRANCH: feature/analytics + - DEV_BRANCH: dev - DEV_TARGET: https://github.com/brightlayer-ui-components/react-dev - MASTER_TARGET: https://github.com/brightlayer-ui-components/react - GH_EMAIL: brightlayer-ui@eaton.com @@ -264,7 +262,7 @@ workflows: branches: only: - master - - feature/analytics + - dev - publish: requires: - build_storybook From 7dd3e6b0ab4774071a0aebf506396718126f37f1 Mon Sep 17 00:00:00 2001 From: daileytj Date: Wed, 12 Jan 2022 14:34:00 -0500 Subject: [PATCH 19/72] Add 1rem padding to root of EmptyState component --- CHANGELOG.md | 1 + components/src/core/EmptyState/EmptyState.tsx | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c90d53800..a569feceb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Added `chevronColor` property onto ``. - Added `chevronIcon` class for `chevron` element in ``. +- Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/EmptyState/EmptyState.tsx b/components/src/core/EmptyState/EmptyState.tsx index 3d98b378b..611757b67 100755 --- a/components/src/core/EmptyState/EmptyState.tsx +++ b/components/src/core/EmptyState/EmptyState.tsx @@ -27,14 +27,13 @@ export type EmptyStateProps = HTMLAttributes & { const useStyles = makeStyles((theme) => ({ root: { - height: '100%', color: theme.palette.text.primary, - minHeight: '100%', display: 'flex', justifyContent: 'center', flexDirection: 'column', textAlign: 'center', alignItems: 'center', + padding: '1rem', }, icon: { color: theme.palette.text.secondary, From 4f0611834bdaef10040d92d8e8e0fb39a95ff0ed Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Thu, 13 Jan 2022 16:43:18 +0530 Subject: [PATCH 20/72] Added titleDivider prop to DrawerNavGroup --- CHANGELOG.md | 1 + components/src/core/Drawer/DrawerNavGroup.tsx | 8 +++++++- docs/Drawer.md | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c90d53800..776a8323e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Added `chevronColor` property onto ``. - Added `chevronIcon` class for `chevron` element in ``. +- Added `titleDivider` property onto ``. ([#315](https://github.com/brightlayer-ui/react-component-library/issues/315)) ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/Drawer/DrawerNavGroup.tsx b/components/src/core/Drawer/DrawerNavGroup.tsx index e2c77c74a..d9a4e0151 100644 --- a/components/src/core/Drawer/DrawerNavGroup.tsx +++ b/components/src/core/Drawer/DrawerNavGroup.tsx @@ -33,6 +33,9 @@ export type DrawerNavGroupProps = SharedStyleProps & /** Custom element, substitute for title */ titleContent?: ReactNode; + + /** Divider for the title */ + titleDivider?: boolean; }; type DrawerNavGroupClasses = { @@ -106,6 +109,7 @@ const DrawerNavGroupRender: React.ForwardRefRenderFunction - {variant !== 'rail' &&
{(title || titleContent) && }
} + {variant !== 'rail' && ( +
{(title || titleContent) && titleDivider && }
+ )} {items.map((drawerItem: DrawerNavItemProps | DrawerRailItemProps, index: number) => { if (variant === 'rail') { const railItem = drawerItem as DrawerRailItemProps; diff --git a/docs/Drawer.md b/docs/Drawer.md index 78ae7aef2..5f229a96b 100644 --- a/docs/Drawer.md +++ b/docs/Drawer.md @@ -231,6 +231,7 @@ The `items` property supports nested items to generate collapsible sections in t | title | Text to display in the group header | `string` | no | | | titleColor | Color used for the title text | `string` | no | varies for light/dark theme | | titleContent | Custom element, substitute for title | `ReactNode` | no | | +| titleDivider | Divider for the title | `boolean` | no | | [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | | From 19edf2c5af17354752b001ccd7a9e5e5a1b485c6 Mon Sep 17 00:00:00 2001 From: daileytj Date: Thu, 13 Jan 2022 09:19:49 -0500 Subject: [PATCH 21/72] Re-add root height styles for the EmptyState component --- components/src/core/EmptyState/EmptyState.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/src/core/EmptyState/EmptyState.tsx b/components/src/core/EmptyState/EmptyState.tsx index 611757b67..656f92395 100755 --- a/components/src/core/EmptyState/EmptyState.tsx +++ b/components/src/core/EmptyState/EmptyState.tsx @@ -28,6 +28,8 @@ export type EmptyStateProps = HTMLAttributes & { const useStyles = makeStyles((theme) => ({ root: { color: theme.palette.text.primary, + height: '100%', + minHeight: '100%', display: 'flex', justifyContent: 'center', flexDirection: 'column', From e77608e5b3f46232a6f89ecb1285f076f43c89e7 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Fri, 14 Jan 2022 16:13:35 +0530 Subject: [PATCH 22/72] Added stories for titleDivider --- components/src/core/Drawer/Drawer.tsx | 6 ++++++ components/src/core/Drawer/DrawerNavGroup.tsx | 6 ------ components/src/core/Drawer/types.tsx | 6 ++++++ demos/storybook/stories/drawer/with-full-config.tsx | 12 ++++++++++-- docs/Drawer.md | 2 +- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/components/src/core/Drawer/Drawer.tsx b/components/src/core/Drawer/Drawer.tsx index a313587e0..ef692e2e2 100755 --- a/components/src/core/Drawer/Drawer.tsx +++ b/components/src/core/Drawer/Drawer.tsx @@ -152,6 +152,8 @@ const DrawerRenderer: React.ForwardRefRenderFunction = (pr nestedBackgroundColor, nestedDivider, ripple, + titleColor, + titleDivider, // Drawer-specific props activeItem, classes, @@ -225,6 +227,8 @@ const DrawerRenderer: React.ForwardRefRenderFunction = (pr nestedBackgroundColor: mergeStyleProp(nestedBackgroundColor, child.props.nestedBackgroundColor), nestedDivider: mergeStyleProp(nestedDivider, child.props.nestedDivider), ripple: mergeStyleProp(ripple, child.props.ripple), + titleColor: mergeStyleProp(titleColor, child.props.titleColor), + titleDivider: mergeStyleProp(titleDivider, child.props.titleDivider), } as DrawerBodyProps) ), [ @@ -378,6 +382,8 @@ Drawer.propTypes = { openOnHover: PropTypes.bool, openOnHoverDelay: PropTypes.number, sideBorder: PropTypes.bool, + titleColor: PropTypes.string, + titleDivider: PropTypes.bool, variant: PropTypes.oneOf(['persistent', 'permanent', 'temporary', 'rail']), width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }; diff --git a/components/src/core/Drawer/DrawerNavGroup.tsx b/components/src/core/Drawer/DrawerNavGroup.tsx index d9a4e0151..83a5432aa 100644 --- a/components/src/core/Drawer/DrawerNavGroup.tsx +++ b/components/src/core/Drawer/DrawerNavGroup.tsx @@ -28,14 +28,8 @@ export type DrawerNavGroupProps = SharedStyleProps & /** Text to display in the group header */ title?: string; - /** Color used for the title text */ - titleColor?: string; - /** Custom element, substitute for title */ titleContent?: ReactNode; - - /** Divider for the title */ - titleDivider?: boolean; }; type DrawerNavGroupClasses = { diff --git a/components/src/core/Drawer/types.tsx b/components/src/core/Drawer/types.tsx index fcd0083c1..fab41d8c9 100644 --- a/components/src/core/Drawer/types.tsx +++ b/components/src/core/Drawer/types.tsx @@ -36,6 +36,12 @@ export type SharedStyleProps = { /** Whether to apply material ripple effect to items */ ripple?: boolean; + + /** Color used for the title text */ + titleColor?: string; + + /** Divider for the title */ + titleDivider?: boolean; }; export type NavItemSharedStyleProps = { diff --git a/demos/storybook/stories/drawer/with-full-config.tsx b/demos/storybook/stories/drawer/with-full-config.tsx index 53136caf0..a6e1aa1ad 100644 --- a/demos/storybook/stories/drawer/with-full-config.tsx +++ b/demos/storybook/stories/drawer/with-full-config.tsx @@ -163,7 +163,8 @@ export const withFullConfig = (): StoryFnReactReturnType => { const navGroupKnobs: Partial = { title: text('drawerNavGroup[0].title', 'NavGroup 1', navGroupId), - titleColor: color('drawerNavGroup[0].titleColor', Colors.black[500], navGroupId), + titleColor: color('titleColor', Colors.black[500], navGroupId), + titleDivider: boolean('titleDivider', true, navGroupId), }; const navItemKnobs: Partial = { @@ -346,7 +347,12 @@ export const withFullConfig = (): StoryFnReactReturnType => { title={headerKnobs.title} /> - + {
Software Version v1.0.3
} + titleColor={navGroupKnobs.titleColor} + titleDivider={navGroupKnobs.titleDivider} />
diff --git a/docs/Drawer.md b/docs/Drawer.md index 5f229a96b..4edbb6288 100644 --- a/docs/Drawer.md +++ b/docs/Drawer.md @@ -231,7 +231,7 @@ The `items` property supports nested items to generate collapsible sections in t | title | Text to display in the group header | `string` | no | | | titleColor | Color used for the title text | `string` | no | varies for light/dark theme | | titleContent | Custom element, substitute for title | `ReactNode` | no | | -| titleDivider | Divider for the title | `boolean` | no | +| titleDivider | Divider for the title | `boolean` | no | true | | [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | | From ddba94078bb97709aa2c148a9d81619c30a30c3c Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Fri, 14 Jan 2022 18:00:03 +0530 Subject: [PATCH 23/72] Updated story with multi nav and moved titleColor and titleDivider props to DrawerNavGroup --- components/src/core/Drawer/Drawer.tsx | 6 ------ components/src/core/Drawer/DrawerNavGroup.tsx | 7 +++++++ components/src/core/Drawer/types.tsx | 6 ------ .../stories/drawer/with-multiple-DrawerNavGroups.tsx | 12 ++++++++++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/components/src/core/Drawer/Drawer.tsx b/components/src/core/Drawer/Drawer.tsx index ef692e2e2..a313587e0 100755 --- a/components/src/core/Drawer/Drawer.tsx +++ b/components/src/core/Drawer/Drawer.tsx @@ -152,8 +152,6 @@ const DrawerRenderer: React.ForwardRefRenderFunction = (pr nestedBackgroundColor, nestedDivider, ripple, - titleColor, - titleDivider, // Drawer-specific props activeItem, classes, @@ -227,8 +225,6 @@ const DrawerRenderer: React.ForwardRefRenderFunction = (pr nestedBackgroundColor: mergeStyleProp(nestedBackgroundColor, child.props.nestedBackgroundColor), nestedDivider: mergeStyleProp(nestedDivider, child.props.nestedDivider), ripple: mergeStyleProp(ripple, child.props.ripple), - titleColor: mergeStyleProp(titleColor, child.props.titleColor), - titleDivider: mergeStyleProp(titleDivider, child.props.titleDivider), } as DrawerBodyProps) ), [ @@ -382,8 +378,6 @@ Drawer.propTypes = { openOnHover: PropTypes.bool, openOnHoverDelay: PropTypes.number, sideBorder: PropTypes.bool, - titleColor: PropTypes.string, - titleDivider: PropTypes.bool, variant: PropTypes.oneOf(['persistent', 'permanent', 'temporary', 'rail']), width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }; diff --git a/components/src/core/Drawer/DrawerNavGroup.tsx b/components/src/core/Drawer/DrawerNavGroup.tsx index 83a5432aa..e2c4fd40c 100644 --- a/components/src/core/Drawer/DrawerNavGroup.tsx +++ b/components/src/core/Drawer/DrawerNavGroup.tsx @@ -28,8 +28,14 @@ export type DrawerNavGroupProps = SharedStyleProps & /** Text to display in the group header */ title?: string; + /** Color used for the title text */ + titleColor?: string; + /** Custom element, substitute for title */ titleContent?: ReactNode; + + /** Divider for the title */ + titleDivider?: boolean; }; type DrawerNavGroupClasses = { @@ -379,6 +385,7 @@ DrawerNavGroup.propTypes = { title: PropTypes.string, titleColor: PropTypes.string, titleContent: PropTypes.element, + titleDivider: PropTypes.bool, }; DrawerNavGroup.defaultProps = { classes: {}, diff --git a/components/src/core/Drawer/types.tsx b/components/src/core/Drawer/types.tsx index fab41d8c9..fcd0083c1 100644 --- a/components/src/core/Drawer/types.tsx +++ b/components/src/core/Drawer/types.tsx @@ -36,12 +36,6 @@ export type SharedStyleProps = { /** Whether to apply material ripple effect to items */ ripple?: boolean; - - /** Color used for the title text */ - titleColor?: string; - - /** Divider for the title */ - titleDivider?: boolean; }; export type NavItemSharedStyleProps = { diff --git a/demos/storybook/stories/drawer/with-multiple-DrawerNavGroups.tsx b/demos/storybook/stories/drawer/with-multiple-DrawerNavGroups.tsx index a8701e75a..94ac7a080 100644 --- a/demos/storybook/stories/drawer/with-multiple-DrawerNavGroups.tsx +++ b/demos/storybook/stories/drawer/with-multiple-DrawerNavGroups.tsx @@ -64,9 +64,17 @@ export const withMultipleNavGroups = (): StoryFnReactReturnType => { subtitle={'with multiple navigation groups'} /> - + {boolean('Add Spacer', true) && } - + ); From 16b81ac4be98b6a904ca5a11094ea5cce7bcc149 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Mon, 17 Jan 2022 13:18:23 +0530 Subject: [PATCH 24/72] 2480 Changed chevronIcon classname to chevron --- CHANGELOG.md | 2 +- components/src/core/InfoListItem/InfoListItem.styles.tsx | 4 ++-- components/src/core/InfoListItem/InfoListItem.tsx | 4 ++-- docs/InfoListItem.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a569feceb..96508e1dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ### Added - Added `chevronColor` property onto ``. -- Added `chevronIcon` class for `chevron` element in ``. +- Added `chevron` class onto ``. - Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/InfoListItem/InfoListItem.styles.tsx b/components/src/core/InfoListItem/InfoListItem.styles.tsx index 82231a75a..929563339 100644 --- a/components/src/core/InfoListItem/InfoListItem.styles.tsx +++ b/components/src/core/InfoListItem/InfoListItem.styles.tsx @@ -15,7 +15,7 @@ export type InfoListItemClasses = { statusStripe?: string; subtitle?: string; title?: string; - chevronIcon?: string; + chevron?: string; }; const getHeight = (props: InfoListItemProps): string => (props.dense ? `3.25rem` : `4.5rem`); @@ -113,7 +113,7 @@ export const useStyles = makeStyles((theme: Theme) => display: 'flex', alignItems: 'center', }, - chevronIcon: { + chevron: { color: (props) => getChevronColor(props, theme), }, separator: { diff --git a/components/src/core/InfoListItem/InfoListItem.tsx b/components/src/core/InfoListItem/InfoListItem.tsx index 5bc719d93..3412e3b98 100644 --- a/components/src/core/InfoListItem/InfoListItem.tsx +++ b/components/src/core/InfoListItem/InfoListItem.tsx @@ -154,7 +154,7 @@ const InfoListItemRender: React.ForwardRefRenderFunction ); } @@ -261,7 +261,7 @@ InfoListItem.propTypes = { avatar: PropTypes.string, icon: PropTypes.string, rightComponent: PropTypes.string, - chevronIcon: PropTypes.string, + chevron: PropTypes.string, separator: PropTypes.string, subtitle: PropTypes.string, title: PropTypes.string, diff --git a/docs/InfoListItem.md b/docs/InfoListItem.md index 5902d8580..acd4582bb 100644 --- a/docs/InfoListItem.md +++ b/docs/InfoListItem.md @@ -63,7 +63,7 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. | -------------- | --------------------------------------------------- | | root | Styles applied to the root element | | avatar | Styles applied to the Avatar element | -| chevronIcon | Styles applied to the chevron element | +| chevron | Styles applied to the chevron element | | divider | Styles applied to the divider element | | icon | Styles applied to the icon element | | info | Styles applied to the third line of text element | From ee80b378bcffe962ae84c15b3336b54d32ed068a Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 17 Jan 2022 13:38:59 +0530 Subject: [PATCH 25/72] ltr styling for unitspace prop --- .../src/core/ChannelValue/ChannelValue.tsx | 46 +++++++++++++++++-- .../channel-value/with-full-config.tsx | 6 +-- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/components/src/core/ChannelValue/ChannelValue.tsx b/components/src/core/ChannelValue/ChannelValue.tsx index 17b0ee0c3..a5d48789a 100644 --- a/components/src/core/ChannelValue/ChannelValue.tsx +++ b/components/src/core/ChannelValue/ChannelValue.tsx @@ -34,6 +34,14 @@ export type ChannelValueProps = Omit, 'prefix'> units?: string; /** Text to display for the value (bold text) */ value: number | string; + /** Whether to show a space between the value and units + * + * Default: auto (shows space except for white list items) + * + * prefixUnitWhitelist: ['$']; + * suffixUnitWhitelist: ['%', '℉','°F','℃','°C','°'] + */ + unitSpace?: 'show' | 'hide' | 'auto'; }; const useStyles = makeStyles((theme: Theme) => @@ -46,7 +54,7 @@ const useStyles = makeStyles((theme: Theme) => color: (props: ChannelValueProps): string => props.color, }, icon: { - marginRight: theme.spacing(0.5), + marginRight: '0.35em', display: 'inline', fontSize: 'inherit', }, @@ -60,7 +68,19 @@ const useStyles = makeStyles((theme: Theme) => }, value: { fontWeight: 600, + '& + $suffix': { + marginLeft: '0.25em', + }, }, + prefix: { + color: 'green', + '& + h6': { + marginLeft: '0.25em', + }, + }, + suffix: { + color: 'red', + } }) ); @@ -78,6 +98,7 @@ const ChannelValueRender: React.ForwardRefRenderFunction { + if((!prefixUnitWhitelist.includes(units) && unitSpace !== 'hide') || unitSpace === 'show') { + return true + } + }, [prefix, units, unitSpace]); + + const applySuffix = useCallback((): boolean => { + if((!suffixUnitWhitelist.includes(units) && unitSpace !== 'hide') || unitSpace === 'show') { + return true + } + }, [prefix, units, unitSpace]); const getUnitElement = useCallback( (): JSX.Element => ( @@ -95,7 +129,12 @@ const ChannelValueRender: React.ForwardRefRenderFunction {units} @@ -103,7 +142,7 @@ const ChannelValueRender: React.ForwardRefRenderFunction ), - [units, classes, defaultClasses] + [units, prefix, classes, defaultClasses, unitSpace] ); return ( @@ -147,6 +186,7 @@ ChannelValue.propTypes = { icon: PropTypes.element, prefix: PropTypes.bool, units: PropTypes.string, + unitSpace: PropTypes.oneOf(['show', 'hide', 'auto']), value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, }; ChannelValue.defaultProps = { diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 816570ae9..ca739db98 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -4,7 +4,7 @@ import * as Colors from '@brightlayer-ui/colors'; import { ChannelValue } from '@brightlayer-ui/react-components'; import { WITH_FULL_CONFIG_STORY_NAME } from '../../src/constants'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; -import { boolean, color, number, text } from '@storybook/addon-knobs'; +import { boolean, color, number, select, text } from '@storybook/addon-knobs'; import { getLeftToRightIconTransform } from '../../src/utils'; export const withFullConfig = (): StoryFnReactReturnType => { @@ -19,9 +19,9 @@ export const withFullConfig = (): StoryFnReactReturnType => { ); const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); - + const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); return ( - + ); }; From 4db6adc18d25d797619e914f45e21f29d5acad58 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Mon, 17 Jan 2022 14:37:07 +0530 Subject: [PATCH 26/72] 2480 Added chevronColor prop to drawer --- components/src/core/Drawer/Drawer.tsx | 3 +++ components/src/core/Drawer/DrawerBody.tsx | 2 ++ components/src/core/Drawer/DrawerNavGroup.tsx | 4 ++++ components/src/core/Drawer/DrawerNavItem.tsx | 14 +++++++++++++- components/src/core/Drawer/types.tsx | 4 ++++ components/src/core/InfoListItem/InfoListItem.tsx | 6 +++--- 6 files changed, 29 insertions(+), 4 deletions(-) diff --git a/components/src/core/Drawer/Drawer.tsx b/components/src/core/Drawer/Drawer.tsx index a313587e0..dea5633a9 100755 --- a/components/src/core/Drawer/Drawer.tsx +++ b/components/src/core/Drawer/Drawer.tsx @@ -142,6 +142,7 @@ const DrawerRenderer: React.ForwardRefRenderFunction = (pr activeItemIconColor, backgroundColor, chevron, + chevronColor, collapseIcon, disableActiveItemParentStyles, divider, @@ -212,6 +213,7 @@ const DrawerRenderer: React.ForwardRefRenderFunction = (pr activeItemIconColor: mergeStyleProp(activeItemIconColor, child.props.activeItemIconColor), backgroundColor: mergeStyleProp(backgroundColor, child.props.backgroundColor), chevron: mergeStyleProp(chevron, child.props.chevron), + chevronColor: mergeStyleProp(chevronColor, child.props.chevronColor), collapseIcon: mergeStyleProp(collapseIcon, child.props.collapseIcon), disableActiveItemParentStyles: mergeStyleProp( disableActiveItemParentStyles, @@ -233,6 +235,7 @@ const DrawerRenderer: React.ForwardRefRenderFunction = (pr activeItemFontColor, activeItemIconColor, chevron, + chevronColor, collapseIcon, disableActiveItemParentStyles, divider, diff --git a/components/src/core/Drawer/DrawerBody.tsx b/components/src/core/Drawer/DrawerBody.tsx index fe25dd12f..8f65f8523 100644 --- a/components/src/core/Drawer/DrawerBody.tsx +++ b/components/src/core/Drawer/DrawerBody.tsx @@ -40,6 +40,7 @@ const DrawerBodyRender: React.ForwardRefRenderFunction activeItemIconColor, backgroundColor, chevron, + chevronColor, collapseIcon, disableActiveItemParentStyles, divider, @@ -85,6 +86,7 @@ const DrawerBodyRender: React.ForwardRefRenderFunction activeItemIconColor={mergeStyleProp(activeItemIconColor, groupProps.activeItemIconColor)} backgroundColor={mergeStyleProp(backgroundColor, groupProps.backgroundColor)} chevron={mergeStyleProp(chevron, groupProps.chevron)} + chevronColor={mergeStyleProp(chevronColor, child.props.chevronColor)} collapseIcon={mergeStyleProp(collapseIcon, groupProps.collapseIcon)} disableActiveItemParentStyles={mergeStyleProp( disableActiveItemParentStyles, diff --git a/components/src/core/Drawer/DrawerNavGroup.tsx b/components/src/core/Drawer/DrawerNavGroup.tsx index e2c4fd40c..59e7554ae 100644 --- a/components/src/core/Drawer/DrawerNavGroup.tsx +++ b/components/src/core/Drawer/DrawerNavGroup.tsx @@ -117,6 +117,7 @@ const DrawerNavGroupRender: React.ForwardRefRenderFunction theme.spacing(depth ? (depth - 1) * 4 : 0) + theme.spacing(2); +const getChevronColor = (props: DrawerNavItemProps, theme: Theme): string => { + const { chevronColor } = props; + return chevronColor ? chevronColor : theme.palette.text.secondary; +}; + const useStyles = makeStyles((theme: Theme) => createStyles({ active: { @@ -106,6 +111,9 @@ const useStyles = makeStyles((theme: Theme) => borderRadius: 0, }, }, + chevron: { + color: (props) => getChevronColor(props, theme), + }, drawerOpen: {}, expanded: {}, expandIcon: { @@ -209,6 +217,7 @@ const DrawerNavItemRender: React.ForwardRefRenderFunction {}, onClick, rightComponent = props.chevron && !props.items && !props.children ? ( - + ) : undefined, ripple = true, statusColor, @@ -329,6 +338,7 @@ const DrawerNavItemRender: React.ForwardRefRenderFunction & { * Default: false */ chevron?: boolean; + /** Color override for the chevron icon */ + chevronColor?: string; /** Custom classes for default style overrides */ classes?: InfoListItemClasses; /** Show a row separator below the row */ @@ -86,8 +88,6 @@ export type InfoListItemProps = Omit & { * Default: false */ wrapTitle?: boolean; - /** Color override for the chevron icon */ - chevronColor?: string; }; const InfoListItemRender: React.ForwardRefRenderFunction = ( props: InfoListItemProps, @@ -98,6 +98,7 @@ const InfoListItemRender: React.ForwardRefRenderFunction Date: Mon, 17 Jan 2022 15:39:53 +0530 Subject: [PATCH 27/72] update changelog --- CHANGELOG.md | 1 + .../src/core/ChannelValue/ChannelValue.tsx | 37 ++++++++---------- .../channel-value/with-full-config.tsx | 14 +++++-- docs/ChannelValue.md | 19 ++++----- docs/images/channelValueAnatomy.png | Bin 25163 -> 22034 bytes 5 files changed, 37 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a569feceb..59f0c3d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Added `chevronColor` property onto ``. - Added `chevronIcon` class for `chevron` element in ``. - Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) +- Added new property `unitSpace` to `` to manage spacing between the value and units. ([#350](https://github.com/brightlayer-ui/react-component-library/issues/350)) ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/ChannelValue/ChannelValue.tsx b/components/src/core/ChannelValue/ChannelValue.tsx index a5d48789a..6132842ef 100644 --- a/components/src/core/ChannelValue/ChannelValue.tsx +++ b/components/src/core/ChannelValue/ChannelValue.tsx @@ -32,8 +32,6 @@ export type ChannelValueProps = Omit, 'prefix'> prefix?: boolean; /** Text to display for the units (light text) */ units?: string; - /** Text to display for the value (bold text) */ - value: number | string; /** Whether to show a space between the value and units * * Default: auto (shows space except for white list items) @@ -41,7 +39,9 @@ export type ChannelValueProps = Omit, 'prefix'> * prefixUnitWhitelist: ['$']; * suffixUnitWhitelist: ['%', '℉','°F','℃','°C','°'] */ - unitSpace?: 'show' | 'hide' | 'auto'; + unitSpace?: 'show' | 'hide' | 'auto'; + /** Text to display for the value (bold text) */ + value: number | string; }; const useStyles = makeStyles((theme: Theme) => @@ -54,7 +54,7 @@ const useStyles = makeStyles((theme: Theme) => color: (props: ChannelValueProps): string => props.color, }, icon: { - marginRight: '0.35em', + marginRight: '0.35rem', display: 'inline', fontSize: 'inherit', }, @@ -63,24 +63,21 @@ const useStyles = makeStyles((theme: Theme) => lineHeight: 'inherit', letterSpacing: 0, }, + prefix: { + '& + h6': { + marginLeft: '0.25rem', + }, + }, + suffix: {}, units: { fontWeight: 300, }, value: { fontWeight: 600, '& + $suffix': { - marginLeft: '0.25em', - }, - }, - prefix: { - color: 'green', - '& + h6': { - marginLeft: '0.25em', + marginLeft: '0.25rem', }, }, - suffix: { - color: 'red', - } }) ); @@ -109,16 +106,16 @@ const ChannelValueRender: React.ForwardRefRenderFunction { - if((!prefixUnitWhitelist.includes(units) && unitSpace !== 'hide') || unitSpace === 'show') { - return true + if ((!prefixUnitWhitelist.includes(units) && unitSpace !== 'hide') || unitSpace === 'show') { + return true; } }, [prefix, units, unitSpace]); const applySuffix = useCallback((): boolean => { - if((!suffixUnitWhitelist.includes(units) && unitSpace !== 'hide') || unitSpace === 'show') { - return true + if ((!suffixUnitWhitelist.includes(units) && unitSpace !== 'hide') || unitSpace === 'show') { + return true; } }, [prefix, units, unitSpace]); @@ -129,8 +126,6 @@ const ChannelValueRender: React.ForwardRefRenderFunction { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : ( - undefined - ); + ) : undefined; const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); return ( - + ); }; diff --git a/docs/ChannelValue.md b/docs/ChannelValue.md index 5bf8df608..12d3bbfb5 100644 --- a/docs/ChannelValue.md +++ b/docs/ChannelValue.md @@ -24,15 +24,16 @@ import { ChannelValue } from '@brightlayer-ui/react-components';
-| Prop Name | Description | Type | Required | Default | -| --------- | ---------------------------------------------- | --------------------- | -------- | --------- | -| color | The color of the font | `string` | no | 'inherit' | -| classes | Style overrides | `ChannelValueClasses` | no | | -| fontSize | The size of the font | `string` \| `number` | no | 'inherit' | -| icon | The inline icon to display | `JSX.Element` | no | | -| prefix | Show units before the value | `boolean` | no | false | -| units | The text to display for the units (light text) | `string` | no | | -| value | The value (bold text) to display | `string` \| `number` | yes | | +| Prop Name | Description | Type | Required | Default | +| --------- | ---------------------------------------------- | -------------------------------- | -------- | --------- | +| color | The color of the font | `string` | no | 'inherit' | +| classes | Style overrides | `ChannelValueClasses` | no | | +| fontSize | The size of the font | `string` \| `number` | no | 'inherit' | +| icon | The inline icon to display | `JSX.Element` | no | | +| prefix | Show units before the value | `boolean` | no | false | +| units | The text to display for the units (light text) | `string` | no | | +| unitSpace | Show/Hide spacing between the value and units | `'auto'` \| `'hide'` \| `'show'` | yes | 'auto' | +| value | The value (bold text) to display | `string` \| `number` | yes | |
diff --git a/docs/images/channelValueAnatomy.png b/docs/images/channelValueAnatomy.png index 8dbb7a354d3fee02130a6f8920f850a13971bea4..46c54142bb5c66aa650fd3828e721a5f502faeaf 100644 GIT binary patch literal 22034 zcmeIacT`hf*Dgx$9TAigdPkZ9QbJV(q$o%gDWO-TmxL|>rCBJ7fQU5dT{2&MgjO+8J2y#2;W)U9fBo(X09Ywg4c9B1J6}B z!<`HrY*i@9$MA@prLx__URjITCVg5Hr5D$_wxYcv#mx1CS(PGXP&>+53vZp}Mf1-t zTh3SWT?}GT=2{hm>T}F70_eW&z<|t&jrEP7AeS%t=Ql{EhYZE@zl8Yqwia2fq=ulj z8(F~z_*89pe}5`GBxh%-*B?c-sV=o&zQUu5!S5hlpv0VQT;ypH;liQpx zCMB`P1AeG*v8`riW0wcR34kml$O z_*)w&A4A(g`mZtEw8ul?Kh+IijDt&aT+|M`=$;UT|37!XI3M><_x~vW{})rQt%XG{ zcpKHDjMh9ykF64dPU+g~IMGj<4i0;kMNAxaiu_A0C!zZze`NZab{AF_a?9Ljpqm>= zU*yYtm1S-)0X08kL0h)u3|V{%Rg=%UYdRK$?ig52v6yXDg~myvS4N5~+Wopqc32Nx z85kMpCKBSePAK&~Z;}*pD(?3?-rY|~?%7#f+`y2b=H&^|WHW%h2HUHABScAZe4eR4 z8tQpRs@#10e0V5lF`J1hmb^r2Yi~704|hJ8TjojJUH1g$?v2R|t~;rjPR^R`M7XPg zxWN2ASFIV+05jL?z*~Tf;?=TKGBQCH7Her|E10g;cZ>RGV#bbSW9eEY<5SYkOC9IDjaf9sUx0EpGy1pX%0AdvnV`+1!Fp#x5PxjnO{# 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 K8l`I15&r`}V`5nV literal 25163 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 V5Mwta3=BP!k)D}u#a-9u{{?q4!=(TK From 205627a5814313866418b35e8501c3a36f5f2575 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Mon, 17 Jan 2022 16:18:40 +0530 Subject: [PATCH 28/72] 2480 Added stories for chevronColor prop --- demos/storybook/stories/drawer/with-full-config.tsx | 2 ++ demos/storybook/stories/info-list-item/with-full-config.tsx | 1 + 2 files changed, 3 insertions(+) diff --git a/demos/storybook/stories/drawer/with-full-config.tsx b/demos/storybook/stories/drawer/with-full-config.tsx index a6e1aa1ad..76bbc7be2 100644 --- a/demos/storybook/stories/drawer/with-full-config.tsx +++ b/demos/storybook/stories/drawer/with-full-config.tsx @@ -102,6 +102,7 @@ export const withFullConfig = (): StoryFnReactReturnType => { activeItemIconColor: color('activeItemIconColor', Colors.blue[500], drawerGroupId), activeItemBackgroundShape: select('activeItemBackgroundShape', ['round', 'square'], 'square', drawerGroupId), chevron: boolean('chevron', false, drawerGroupId), + chevronColor: color('chevronColor', Colors.gray[500], drawerGroupId), collapseIcon: getIcon( select('collapseIcon', ['undefined', '', ''], 'undefined', drawerGroupId) ), @@ -316,6 +317,7 @@ export const withFullConfig = (): StoryFnReactReturnType => { activeItemIconColor={drawerKnobs.activeItemIconColor} activeItemBackgroundShape={drawerKnobs.activeItemBackgroundShape} chevron={drawerKnobs.chevron} + chevronColor={drawerKnobs.chevronColor} collapseIcon={drawerKnobs.collapseIcon} condensed={drawerKnobs.condensed} divider={drawerKnobs.divider} diff --git a/demos/storybook/stories/info-list-item/with-full-config.tsx b/demos/storybook/stories/info-list-item/with-full-config.tsx index d390695ff..51554ab9a 100644 --- a/demos/storybook/stories/info-list-item/with-full-config.tsx +++ b/demos/storybook/stories/info-list-item/with-full-config.tsx @@ -26,6 +26,7 @@ export const withFullConfig = (): StoryFnReactReturnType => { backgroundColor={color('backgroundColor', Colors.white[50])} avatar={boolean('avatar', false)} chevron={boolean('chevron', true)} + chevronColor={color('chevronColor', Colors.gray[500])} dense={boolean('dense', false)} divider={appliedDivider} ripple={boolean('ripple', false)} From 330e342503d3aaf4fdb5ecb0594e62fa4f97a08c Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Mon, 17 Jan 2022 16:34:27 +0530 Subject: [PATCH 29/72] 2480 Updated changelog and Readme --- CHANGELOG.md | 2 ++ docs/Drawer.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c03adaf61..83faae32d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added +- Added `chevronColor` property onto ``. +- Added `chevron` class onto ``. - Added `chevronColor` property onto ``. - Added `chevron` class onto ``. - Added `titleDivider` property onto ``. ([#315](https://github.com/brightlayer-ui/react-component-library/issues/315)) diff --git a/docs/Drawer.md b/docs/Drawer.md index 4edbb6288..7fc58fc92 100644 --- a/docs/Drawer.md +++ b/docs/Drawer.md @@ -320,6 +320,7 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. | ---------------- | --------------------------------------------------------------- | | root | Styles applied to the root element wrapping the InfoListItem | | active | Styles applied to the active item highlight element | +| chevron | Styles applied to the chevron element | | expandIcon | Styles applied to the expand/collapse icon wrapper | | infoListItemRoot | Styles applied to the InfoListItem root element | | nestedListGroup | Styles applied to wrapper surrounded nested children | @@ -449,6 +450,7 @@ The following are additional shared props that will apply when using a non-rail | ----------------------------- | ----------------------------------------------------------------------------- | ----------------------- | -------- | ------------------------------------------------------------ | | activeItemBackgroundShape | shape of the active item background highlight | `'round'` \| `'square'` | no | square | | chevron | Whether to have chevrons for all menu items | `boolean` | no | | +| chevronColor | Color override for the chevron icon | `string` | no | | | collapseIcon | Icon used to collapse drawer | `JSX.Element` | no | `expandIcon` rotated 180 degrees | | expandIcon | Icon used to expand drawer | `JSX.Element` | no | `` at top-level, `` otherwise | | hidePadding | Whether to hide the paddings reserved for menu item icons | `boolean` | no | | From 3eceb9cf90d1251b42b3379e0055e9eaa5b67997 Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Mon, 17 Jan 2022 16:47:37 +0530 Subject: [PATCH 30/72] Fixed failing lint --- components/src/core/InfoListItem/InfoListItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/src/core/InfoListItem/InfoListItem.tsx b/components/src/core/InfoListItem/InfoListItem.tsx index 6e1beef01..dbb932ecb 100644 --- a/components/src/core/InfoListItem/InfoListItem.tsx +++ b/components/src/core/InfoListItem/InfoListItem.tsx @@ -98,7 +98,6 @@ const InfoListItemRender: React.ForwardRefRenderFunction Date: Mon, 17 Jan 2022 22:31:35 +0530 Subject: [PATCH 31/72] update score card and hero component --- CHANGELOG.md | 1 + .../src/core/ChannelValue/ChannelValue.tsx | 10 +++--- components/src/core/Hero/Hero.test.tsx | 8 ++--- components/src/core/Hero/Hero.tsx | 28 +++------------ .../src/core/HeroBanner/HeroBanner.test.tsx | 10 +++--- components/src/core/UserMenu/UserMenu.tsx | 8 ++--- .../hero/with-channelValue-children.tsx | 4 +-- .../stories/hero/with-full-config.tsx | 15 ++++---- .../stories/hero/with-icon-colors.tsx | 3 +- .../stories/hero/with-value-and-units.tsx | 8 +---- .../stories/hero/within-a-HeroBanner.tsx | 13 +++---- .../stories/score-card/with-heroes.tsx | 8 ++--- .../stories/score-card/with-score-badge.tsx | 4 +-- docs/Drawer.md | 36 +++++++++---------- docs/Hero.md | 24 ++++++------- docs/ScoreCard.md | 4 +-- 16 files changed, 73 insertions(+), 111 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59f0c3d7f..84c39ca31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Added `chevronIcon` class for `chevron` element in ``. - Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) - Added new property `unitSpace` to `` to manage spacing between the value and units. ([#350](https://github.com/brightlayer-ui/react-component-library/issues/350)) +- In `` component, `fontSize`, `value`, `valueIcon`, `valueColor` and `units` props have been replaced by `ChannelValueProps` prop, which will allow you to specify any props on the underlying `` component. ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/ChannelValue/ChannelValue.tsx b/components/src/core/ChannelValue/ChannelValue.tsx index 6132842ef..df10acda0 100644 --- a/components/src/core/ChannelValue/ChannelValue.tsx +++ b/components/src/core/ChannelValue/ChannelValue.tsx @@ -1,6 +1,6 @@ import React, { useCallback, HTMLAttributes } from 'react'; import Typography from '@material-ui/core/Typography'; -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'; +import { makeStyles, createStyles } from '@material-ui/core/styles'; import clsx from 'clsx'; import PropTypes from 'prop-types'; @@ -44,7 +44,7 @@ export type ChannelValueProps = Omit, 'prefix'> value: number | string; }; -const useStyles = makeStyles((theme: Theme) => +const useStyles = makeStyles(() => createStyles({ root: { display: 'inline-flex', @@ -54,7 +54,7 @@ const useStyles = makeStyles((theme: Theme) => color: (props: ChannelValueProps): string => props.color, }, icon: { - marginRight: '0.35rem', + marginRight: '0.35em', display: 'inline', fontSize: 'inherit', }, @@ -65,7 +65,7 @@ const useStyles = makeStyles((theme: Theme) => }, prefix: { '& + h6': { - marginLeft: '0.25rem', + marginLeft: '0.25em', }, }, suffix: {}, @@ -75,7 +75,7 @@ const useStyles = makeStyles((theme: Theme) => value: { fontWeight: 600, '& + $suffix': { - marginLeft: '0.25rem', + marginLeft: '0.25em', }, }, }) diff --git a/components/src/core/Hero/Hero.test.tsx b/components/src/core/Hero/Hero.test.tsx index 3412c9c74..1e79236b0 100644 --- a/components/src/core/Hero/Hero.test.tsx +++ b/components/src/core/Hero/Hero.test.tsx @@ -25,19 +25,19 @@ describe('Hero', () => { it('renders without crashing', () => { const div = document.createElement('div'); - ReactDOM.render(, div); + ReactDOM.render(, div); }); it('should render with the wrapper class', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(findByTestId('wrapper', wrapper)).toBeTruthy(); }); it('renders without children', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(ChannelValue).length).toEqual(1); }); it('renders with children', () => { const wrapper = shallow( - + diff --git a/components/src/core/Hero/Hero.tsx b/components/src/core/Hero/Hero.tsx index 582b10c12..7ba6bc991 100644 --- a/components/src/core/Hero/Hero.tsx +++ b/components/src/core/Hero/Hero.tsx @@ -1,14 +1,11 @@ import React, { HTMLAttributes, ReactNode } from 'react'; import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; -import { ChannelValue } from '../ChannelValue'; +import { ChannelValue, ChannelValueProps as ChannelValuePropsType } from '../ChannelValue'; import clsx from 'clsx'; import PropTypes from 'prop-types'; const normalizeIconSize = (size: number): number => Math.max(10, size); -const normalizeFontSize = (size: FontSize): string => (size === 'small' ? '1rem' : '1.25rem'); - -type FontSize = 'normal' | 'small'; export type HeroClasses = { root?: string; @@ -20,8 +17,6 @@ export type HeroClasses = { export type HeroProps = HTMLAttributes & { /** Custom classes for default style overrides */ classes?: HeroClasses; - /** The text size for the value line */ - fontSize?: FontSize; /** The primary icon */ icon: ReactNode; /** The color used behind the primary icon @@ -36,12 +31,8 @@ export type HeroProps = HTMLAttributes & { iconSize?: number | string; /** The text shown below the `ChannelValue` */ label: string; - /** The value for the channel */ - value?: string | number; - /** The inline icon with the value */ - valueIcon?: JSX.Element; - /** Text to show after the value */ - units?: string; + /** Props to be passed through to ChannelValue child component */ + ChannelValueProps?: ChannelValuePropsType; }; const useStyles = makeStyles((theme: Theme) => @@ -86,7 +77,6 @@ const useStyles = makeStyles((theme: Theme) => lineHeight: 1.2, maxWidth: '100%', overflow: 'hidden', - fontSize: (props: HeroProps): string => normalizeFontSize(props.fontSize), }, label: { fontSize: 'inherit', @@ -108,12 +98,9 @@ const HeroRender: React.ForwardRefRenderFunction = (props: H classes, icon, label, - value, - valueIcon, - units, + ChannelValueProps, // ignore unused vars so that we can do prop transferring to the root element /* eslint-disable @typescript-eslint/no-unused-vars */ - fontSize, iconBackgroundColor, iconSize, /* eslint-enable @typescript-eslint/no-unused-vars */ @@ -124,7 +111,7 @@ const HeroRender: React.ForwardRefRenderFunction = (props: H

{icon} - {!props.children && value && } + {!props.children && ChannelValueProps?.value && } {props.children} @@ -148,18 +135,13 @@ Hero.propTypes = { icon: PropTypes.string, labels: PropTypes.string, }), - fontSize: PropTypes.oneOf(['normal', 'small']), icon: PropTypes.node.isRequired, iconBackgroundColor: PropTypes.string, iconSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), label: PropTypes.string.isRequired, - value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - valueIcon: PropTypes.element, - units: PropTypes.string, }; Hero.defaultProps = { classes: {}, - fontSize: 'normal', iconBackgroundColor: 'transparent', iconSize: 36, }; diff --git a/components/src/core/HeroBanner/HeroBanner.test.tsx b/components/src/core/HeroBanner/HeroBanner.test.tsx index 185f3490b..7ecafe1c6 100644 --- a/components/src/core/HeroBanner/HeroBanner.test.tsx +++ b/components/src/core/HeroBanner/HeroBanner.test.tsx @@ -26,11 +26,11 @@ describe('HeroBanner', () => { it('renders only 4 children', () => { const hero = mount( - - - - - + + + + + ); expect(hero.find(Hero).length).toEqual(4); diff --git a/components/src/core/UserMenu/UserMenu.tsx b/components/src/core/UserMenu/UserMenu.tsx index 41cf78154..d7e1c89cd 100644 --- a/components/src/core/UserMenu/UserMenu.tsx +++ b/components/src/core/UserMenu/UserMenu.tsx @@ -220,10 +220,10 @@ const UserMenuRender: React.ForwardRefRenderFunction = ( [menuGroups, defaultClasses] ); - const printMenu = useCallback((): JSX.Element[] => [printHeader()].concat(printMenuItems()), [ - printHeader, - printMenuItems, - ]); + const printMenu = useCallback( + (): JSX.Element[] => [printHeader()].concat(printMenuItems()), + [printHeader, printMenuItems] + ); const formatMenu = useCallback((): JSX.Element => { const showBottomSheet = useMediaQuery(`(max-width:${useBottomSheetAt}px)`); diff --git a/demos/storybook/stories/hero/with-channelValue-children.tsx b/demos/storybook/stories/hero/with-channelValue-children.tsx index a2b3adb8f..e70c3b617 100644 --- a/demos/storybook/stories/hero/with-channelValue-children.tsx +++ b/demos/storybook/stories/hero/with-channelValue-children.tsx @@ -6,8 +6,8 @@ import React from 'react'; export const withChannelValueChildren = (): StoryFnReactReturnType => ( }> - - + + ); diff --git a/demos/storybook/stories/hero/with-full-config.tsx b/demos/storybook/stories/hero/with-full-config.tsx index d6a2d7963..338e8b342 100644 --- a/demos/storybook/stories/hero/with-full-config.tsx +++ b/demos/storybook/stories/hero/with-full-config.tsx @@ -12,16 +12,19 @@ import { getLeftToRightIconTransform } from '../../src/utils'; export const withFullConfig = (): StoryFnReactReturnType => ( : undefined - } + ChannelValueProps={{ + value: '470', + units: 'RPM', + icon: boolean('Show Value Icon', true) ? ( + + ) : undefined, + unitSpace: select('unitSpace', ['show', 'hide', 'auto'], 'hide'), + fontSize: select('fontSize', ['normal', 'small'], 'normal'), + }} iconBackgroundColor={color('iconBackgroundColor', Colors.blue[500])} icon={} iconSize={number('iconSize', 35)} - fontSize={select('fontSize', ['normal', 'small'], 'normal')} /> ); diff --git a/demos/storybook/stories/hero/with-icon-colors.tsx b/demos/storybook/stories/hero/with-icon-colors.tsx index 1fefee4d8..55f5862a2 100644 --- a/demos/storybook/stories/hero/with-icon-colors.tsx +++ b/demos/storybook/stories/hero/with-icon-colors.tsx @@ -10,8 +10,7 @@ export const withIconColors = (): StoryFnReactReturnType => ( iconBackgroundColor={color('iconBackgroundColor', Colors.red[500])} icon={} label={'Temperature'} - value={'38'} - units={'°C'} + ChannelValueProps={{ units: '°C', value: '38' }} /> ); diff --git a/demos/storybook/stories/hero/with-value-and-units.tsx b/demos/storybook/stories/hero/with-value-and-units.tsx index d732d7027..a58ce809b 100644 --- a/demos/storybook/stories/hero/with-value-and-units.tsx +++ b/demos/storybook/stories/hero/with-value-and-units.tsx @@ -1,16 +1,10 @@ import { GradeB } from '@brightlayer-ui/icons-mui'; import { Hero } from '@brightlayer-ui/react-components'; -import { text } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import React from 'react'; export const withValueUnits = (): StoryFnReactReturnType => ( - } - label={'Efficiency'} - value={text('value', '88')} - units={text('units', '%')} - /> + } label={'Efficiency'} ChannelValueProps={{ units: '%', value: '88' }} /> ); withValueUnits.story = { name: 'with value and units' }; diff --git a/demos/storybook/stories/hero/within-a-HeroBanner.tsx b/demos/storybook/stories/hero/within-a-HeroBanner.tsx index 707578e1b..117a87095 100644 --- a/demos/storybook/stories/hero/within-a-HeroBanner.tsx +++ b/demos/storybook/stories/hero/within-a-HeroBanner.tsx @@ -11,30 +11,25 @@ export const inBanner = (): StoryFnReactReturnType => { key={'hero1'} icon={} label={'Healthy'} - value={96} - units={'/100'} + ChannelValueProps={{ value: '96', units: '/100', unitSpace: 'hide' }} />, } label={'Load'} - value={'90'} - units={'%'} - fontSize={'normal'} + ChannelValueProps={{ value: '90', units: '%', fontSize: 'normal' }} />, } label={'Temp'} - value={55} - units={'C'} + ChannelValueProps={{ value: '55', units: '°C' }} />, } label={'Battery'} - value={96} - units={'/100'} + ChannelValueProps={{ value: '96', units: '/100', unitSpace: 'hide' }} />, ]; const numberDisplayed = number('count', 4, { range: true, min: 0, max: 4, step: 1 }); diff --git a/demos/storybook/stories/score-card/with-heroes.tsx b/demos/storybook/stories/score-card/with-heroes.tsx index 7b7da8689..28608853f 100644 --- a/demos/storybook/stories/score-card/with-heroes.tsx +++ b/demos/storybook/stories/score-card/with-heroes.tsx @@ -18,19 +18,15 @@ export const heroes: JSX.Element[] = [ label={'Temperature'} iconSize={48} iconBackgroundColor={Colors.white[50]} - value={98} - units={'°F'} - fontSize={'normal'} + ChannelValueProps={{ value: '98', units: '°F' }} />, } label={'Humidity'} - value={54} + ChannelValueProps={{ value: '54', units: '%' }} iconBackgroundColor={Colors.white[50]} - units={'%'} iconSize={48} - fontSize={'normal'} />, ]; diff --git a/demos/storybook/stories/score-card/with-score-badge.tsx b/demos/storybook/stories/score-card/with-score-badge.tsx index 2facb03ae..3dce21a76 100644 --- a/demos/storybook/stories/score-card/with-score-badge.tsx +++ b/demos/storybook/stories/score-card/with-score-badge.tsx @@ -39,9 +39,7 @@ export const withScoreBadge = (): StoryFnReactReturnType => { label={'Grade'} iconSize={72} iconBackgroundColor={useDarkMode() ? Colors.black[900] : Colors.white[50]} - value={'98'} - units={'/100'} - fontSize={'normal'} + ChannelValueProps={{ value: '98', units: '/100', unitSpace: 'hide' }} /> } diff --git a/docs/Drawer.md b/docs/Drawer.md index 78ae7aef2..ce078d979 100644 --- a/docs/Drawer.md +++ b/docs/Drawer.md @@ -287,25 +287,25 @@ The `` is an individual line item in the ``. These can be
-| Prop Name | Description | Type | Required | Default | -| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------- | ------- | -| classes | Style overrides | `DrawerNavItemClasses` | no | | -| depth\* | The nested depth of the item | `number` | no | 0 | -| hidden | Sets whether to hide the nav item | `boolean` | no | | -| hidePadding | Remove left padding if no icon is used | `boolean` | no | false | -| icon | A component to render for the left icon | `JSX.Element` | no | | -| isInActiveTree\* | Sets whether the item is a parent of the currently active item (managed automatically) | `boolean` | no | | -| itemID | A unique identifier of the NavItem. Item will have 'active' style when this matches activeItem | `string` | yes | | -| items | The items nested under this item | `NestedNavItem[]` | no | | -| notifyActiveParent\* | Callback function to the parent element to update active hierarchy styles | `(ids: string[]) => void` | no | | -| onClick | A function to execute when clicked | `function` | no | | -| rightComponent | An icon/component to display to the right | `ReactNode` | no | | -| statusColor | Status stripe and icon color | `string` | no | | -| subtitle | The text to show on the second line | `string` | no | | -| title | The text to show on the first line | `string` | yes | | -| disableRailTooltip | Sets whether to disable the tooltip on hover for the condensed `rail` variant | `boolean` | no | | +| Prop Name | Description | Type | Required | Default | +| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------- | ------- | +| classes | Style overrides | `DrawerNavItemClasses` | no | | +| depth\* | The nested depth of the item | `number` | no | 0 | +| hidden | Sets whether to hide the nav item | `boolean` | no | | +| hidePadding | Remove left padding if no icon is used | `boolean` | no | false | +| icon | A component to render for the left icon | `JSX.Element` | no | | +| isInActiveTree\* | Sets whether the item is a parent of the currently active item (managed automatically) | `boolean` | no | | +| itemID | A unique identifier of the NavItem. Item will have 'active' style when this matches activeItem | `string` | yes | | +| items | The items nested under this item | `NestedNavItem[]` | no | | +| notifyActiveParent\* | Callback function to the parent element to update active hierarchy styles | `(ids: string[]) => void` | no | | +| onClick | A function to execute when clicked | `function` | no | | +| rightComponent | An icon/component to display to the right | `ReactNode` | no | | +| statusColor | Status stripe and icon color | `string` | no | | +| subtitle | The text to show on the second line | `string` | no | | +| title | The text to show on the first line | `string` | yes | | +| disableRailTooltip | Sets whether to disable the tooltip on hover for the condensed `rail` variant | `boolean` | no | | | InfoListItemProps | Used to override [InfoListItem](https://brightlayer-ui-components.github.io/react/?path=/info/components-info-list-item--get-read-me-story) default props | `InfoListItemProps` | no | | -| [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | | +| [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | |
diff --git a/docs/Hero.md b/docs/Hero.md index fb93c0051..7fb2a4535 100644 --- a/docs/Hero.md +++ b/docs/Hero.md @@ -8,7 +8,7 @@ The Brightlayer UI `` components are used to call attention to particular The `` component displays a particular icon, value/units, and a label. The icon property will accept any valid component - this will typically be a Material icon, [Brightlayer UI icon](https://github.com/brightlayer-ui/icons), or [Progress Icon](https://github.com/brightlayer-ui/icons/tree/master/progress). It will also accept Text/Emoji values. -The value section of the Hero utilizes a [``](./ChannelValue.md) component. To display a single simple value, the information can be passed as props (`value`, `units`, `valueIcon`). For more complex values (such as a duration that displays hours and minutes), you can pass in `` components as children and they will be displayed inline. +The value section of the Hero utilizes a [``](./ChannelValue.md) component. To display a single simple value, the information can be passed as `ChannelValueProps`. For more complex values (such as a duration that displays hours and minutes), you can pass in `` components as children and they will be displayed inline. ## Hero Usage @@ -23,8 +23,7 @@ import { Hero } from '@brightlayer-ui/react-components'; } label={'Label'} - value={99} - units={'%'} + ChannelValueProps={{ value: 99, units: '%' }} /> // Complex example with multiple values as children -| Prop Name | Description | Type | Required | Default | -| ------------------- | --------------------------------------- | ----------------------- | -------- | ------------- | -| classes | Style overrides | `HeroClasses` | no | | -| fontSize | The text size for the value line | `'normal'` \| `'small'` | no | 'normal' | -| icon | The primary icon | `ReactNode` | yes | | -| iconBackgroundColor | The color used behind the primary icon | `string` | no | 'transparent' | -| iconSize | The size of the primary icon (min 10px) | `number` \| `string` | no | 36 | -| label | The text shown below the `ChannelValue` | `string` | yes | | -| units | Text to show after the value | `string` | no | | -| value | The value for the channel | `string` \| `number` | no | | -| valueIcon | The inline icon with the value | `JSX.Element` | no | | +| Prop Name | Description | Type | Required | Default | +| ------------------- | ------------------------------------------ | -------------------- | -------- | ------------- | +| classes | Style overrides | `HeroClasses` | no | | +| ChannelValueProps | Props passed through to ChannelValue child | `ChannelValueProps` | no | | +| icon | The primary icon | `ReactNode` | yes | | +| iconBackgroundColor | The color used behind the primary icon | `string` | no | 'transparent' | +| iconSize | The size of the primary icon (min 10px) | `number` \| `string` | no | 36 | +| label | The text shown below the `ChannelValue` | `string` | yes | |
diff --git a/docs/ScoreCard.md b/docs/ScoreCard.md index e7c891033..7f8cfc636 100644 --- a/docs/ScoreCard.md +++ b/docs/ScoreCard.md @@ -34,9 +34,7 @@ import { Temp } from '@brightlayer-ui/icons-mui'; icon={} label={'Temperature'} iconSize={48} - value={98} - units={'°F'} - fontSize={'normal'} + ChannelValueProps={{ value: '98', units: '°F', fontSize: 'normal' }} /> } From 4b3c65adab6ebd2593ae9e886f3e145a4caa060d Mon Sep 17 00:00:00 2001 From: Suraj Karambe Date: Mon, 17 Jan 2022 23:40:32 +0530 Subject: [PATCH 32/72] 2480 Review changes - Updated changelog for v5.4.0 --- CHANGELOG.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83faae32d..a64b4b2e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,8 @@ ### Added -- Added `chevronColor` property onto ``. -- Added `chevron` class onto ``. -- Added `chevronColor` property onto ``. -- Added `chevron` class onto ``. +- Added `chevronColor` property to `` and SharedProps of ``. +- Added class override for `chevron` on `` and ``. - Added `titleDivider` property onto ``. ([#315](https://github.com/brightlayer-ui/react-component-library/issues/315)) - Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) From a1d5802dc4a392647b68ff27615a160c1bb8b0ec Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 18 Jan 2022 13:14:10 +0530 Subject: [PATCH 33/72] add knob for hero component --- components/src/core/UserMenu/UserMenu.tsx | 8 ++++---- .../stories/hero/with-channelValue-children.tsx | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/components/src/core/UserMenu/UserMenu.tsx b/components/src/core/UserMenu/UserMenu.tsx index d7e1c89cd..41cf78154 100644 --- a/components/src/core/UserMenu/UserMenu.tsx +++ b/components/src/core/UserMenu/UserMenu.tsx @@ -220,10 +220,10 @@ const UserMenuRender: React.ForwardRefRenderFunction = ( [menuGroups, defaultClasses] ); - const printMenu = useCallback( - (): JSX.Element[] => [printHeader()].concat(printMenuItems()), - [printHeader, printMenuItems] - ); + const printMenu = useCallback((): JSX.Element[] => [printHeader()].concat(printMenuItems()), [ + printHeader, + printMenuItems, + ]); const formatMenu = useCallback((): JSX.Element => { const showBottomSheet = useMediaQuery(`(max-width:${useBottomSheetAt}px)`); diff --git a/demos/storybook/stories/hero/with-channelValue-children.tsx b/demos/storybook/stories/hero/with-channelValue-children.tsx index e70c3b617..2b4350559 100644 --- a/demos/storybook/stories/hero/with-channelValue-children.tsx +++ b/demos/storybook/stories/hero/with-channelValue-children.tsx @@ -1,13 +1,23 @@ import { Schedule } from '@material-ui/icons'; import { ChannelValue, Hero } from '@brightlayer-ui/react-components'; -import { number } from '@storybook/addon-knobs'; +import { number, select } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import React from 'react'; export const withChannelValueChildren = (): StoryFnReactReturnType => ( }> - - + + ); From b82e743a4e238cf1bda1e683c62fbe91de4f4942 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 18 Jan 2022 14:38:12 +0530 Subject: [PATCH 34/72] fix prettier --- components/src/core/UserMenu/UserMenu.tsx | 8 ++++---- .../storybook/stories/channel-value/with-full-config.tsx | 4 +++- demos/storybook/stories/hero/with-full-config.tsx | 4 +++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/components/src/core/UserMenu/UserMenu.tsx b/components/src/core/UserMenu/UserMenu.tsx index 41cf78154..d7e1c89cd 100644 --- a/components/src/core/UserMenu/UserMenu.tsx +++ b/components/src/core/UserMenu/UserMenu.tsx @@ -220,10 +220,10 @@ const UserMenuRender: React.ForwardRefRenderFunction = ( [menuGroups, defaultClasses] ); - const printMenu = useCallback((): JSX.Element[] => [printHeader()].concat(printMenuItems()), [ - printHeader, - printMenuItems, - ]); + const printMenu = useCallback( + (): JSX.Element[] => [printHeader()].concat(printMenuItems()), + [printHeader, printMenuItems] + ); const formatMenu = useCallback((): JSX.Element => { const showBottomSheet = useMediaQuery(`(max-width:${useBottomSheetAt}px)`); diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 4748c1323..603719147 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,7 +14,9 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : undefined; + ) : ( + undefined + ); const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); diff --git a/demos/storybook/stories/hero/with-full-config.tsx b/demos/storybook/stories/hero/with-full-config.tsx index 338e8b342..7ef27658c 100644 --- a/demos/storybook/stories/hero/with-full-config.tsx +++ b/demos/storybook/stories/hero/with-full-config.tsx @@ -18,7 +18,9 @@ export const withFullConfig = (): StoryFnReactReturnType => ( units: 'RPM', icon: boolean('Show Value Icon', true) ? ( - ) : undefined, + ) : ( + undefined + ), unitSpace: select('unitSpace', ['show', 'hide', 'auto'], 'hide'), fontSize: select('fontSize', ['normal', 'small'], 'normal'), }} From 0177d77601cd7aaf4c9be3f8f0f07dac279ac188 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 18 Jan 2022 14:47:42 +0530 Subject: [PATCH 35/72] fix prettier --- components/src/core/UserMenu/UserMenu.tsx | 8 ++++---- .../storybook/stories/channel-value/with-full-config.tsx | 4 +--- demos/storybook/stories/hero/with-full-config.tsx | 4 +--- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/components/src/core/UserMenu/UserMenu.tsx b/components/src/core/UserMenu/UserMenu.tsx index d7e1c89cd..41cf78154 100644 --- a/components/src/core/UserMenu/UserMenu.tsx +++ b/components/src/core/UserMenu/UserMenu.tsx @@ -220,10 +220,10 @@ const UserMenuRender: React.ForwardRefRenderFunction = ( [menuGroups, defaultClasses] ); - const printMenu = useCallback( - (): JSX.Element[] => [printHeader()].concat(printMenuItems()), - [printHeader, printMenuItems] - ); + const printMenu = useCallback((): JSX.Element[] => [printHeader()].concat(printMenuItems()), [ + printHeader, + printMenuItems, + ]); const formatMenu = useCallback((): JSX.Element => { const showBottomSheet = useMediaQuery(`(max-width:${useBottomSheetAt}px)`); diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 603719147..4748c1323 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,9 +14,7 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : ( - undefined - ); + ) : undefined; const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); diff --git a/demos/storybook/stories/hero/with-full-config.tsx b/demos/storybook/stories/hero/with-full-config.tsx index 7ef27658c..338e8b342 100644 --- a/demos/storybook/stories/hero/with-full-config.tsx +++ b/demos/storybook/stories/hero/with-full-config.tsx @@ -18,9 +18,7 @@ export const withFullConfig = (): StoryFnReactReturnType => ( units: 'RPM', icon: boolean('Show Value Icon', true) ? ( - ) : ( - undefined - ), + ) : undefined, unitSpace: select('unitSpace', ['show', 'hide', 'auto'], 'hide'), fontSize: select('fontSize', ['normal', 'small'], 'normal'), }} From 643bef72ac150db8d0d9231254c7e5706145f040 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 18 Jan 2022 15:10:56 +0530 Subject: [PATCH 36/72] fix prettier storybook --- components/src/core/UserMenu/UserMenu.tsx | 8 ++++---- .../storybook/stories/channel-value/with-full-config.tsx | 4 +++- demos/storybook/stories/hero/with-full-config.tsx | 4 +++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/components/src/core/UserMenu/UserMenu.tsx b/components/src/core/UserMenu/UserMenu.tsx index 41cf78154..d7e1c89cd 100644 --- a/components/src/core/UserMenu/UserMenu.tsx +++ b/components/src/core/UserMenu/UserMenu.tsx @@ -220,10 +220,10 @@ const UserMenuRender: React.ForwardRefRenderFunction = ( [menuGroups, defaultClasses] ); - const printMenu = useCallback((): JSX.Element[] => [printHeader()].concat(printMenuItems()), [ - printHeader, - printMenuItems, - ]); + const printMenu = useCallback( + (): JSX.Element[] => [printHeader()].concat(printMenuItems()), + [printHeader, printMenuItems] + ); const formatMenu = useCallback((): JSX.Element => { const showBottomSheet = useMediaQuery(`(max-width:${useBottomSheetAt}px)`); diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 4748c1323..603719147 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,7 +14,9 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : undefined; + ) : ( + undefined + ); const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); diff --git a/demos/storybook/stories/hero/with-full-config.tsx b/demos/storybook/stories/hero/with-full-config.tsx index 338e8b342..7ef27658c 100644 --- a/demos/storybook/stories/hero/with-full-config.tsx +++ b/demos/storybook/stories/hero/with-full-config.tsx @@ -18,7 +18,9 @@ export const withFullConfig = (): StoryFnReactReturnType => ( units: 'RPM', icon: boolean('Show Value Icon', true) ? ( - ) : undefined, + ) : ( + undefined + ), unitSpace: select('unitSpace', ['show', 'hide', 'auto'], 'hide'), fontSize: select('fontSize', ['normal', 'small'], 'normal'), }} From eb28011077e31a370761a644296037e776389b8f Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Thu, 20 Jan 2022 12:16:59 +0530 Subject: [PATCH 37/72] revert hero and score card changes --- CHANGELOG.md | 1 - components/src/core/Hero/Hero.test.tsx | 8 +++--- components/src/core/Hero/Hero.tsx | 28 +++++++++++++++---- .../src/core/HeroBanner/HeroBanner.test.tsx | 10 +++---- .../channel-value/with-full-config.tsx | 4 +-- .../stories/hero/with-full-config.tsx | 17 ++++------- .../stories/hero/with-icon-colors.tsx | 3 +- .../stories/hero/with-value-and-units.tsx | 8 +++++- .../stories/hero/within-a-HeroBanner.tsx | 13 ++++++--- .../stories/score-card/with-heroes.tsx | 8 ++++-- .../stories/score-card/with-score-badge.tsx | 4 ++- docs/Hero.md | 24 +++++++++------- docs/ScoreCard.md | 4 ++- 13 files changed, 83 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84c39ca31..59f0c3d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,6 @@ - Added `chevronIcon` class for `chevron` element in ``. - Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) - Added new property `unitSpace` to `` to manage spacing between the value and units. ([#350](https://github.com/brightlayer-ui/react-component-library/issues/350)) -- In `` component, `fontSize`, `value`, `valueIcon`, `valueColor` and `units` props have been replaced by `ChannelValueProps` prop, which will allow you to specify any props on the underlying `` component. ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/Hero/Hero.test.tsx b/components/src/core/Hero/Hero.test.tsx index 1e79236b0..3412c9c74 100644 --- a/components/src/core/Hero/Hero.test.tsx +++ b/components/src/core/Hero/Hero.test.tsx @@ -25,19 +25,19 @@ describe('Hero', () => { it('renders without crashing', () => { const div = document.createElement('div'); - ReactDOM.render(, div); + ReactDOM.render(, div); }); it('should render with the wrapper class', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(findByTestId('wrapper', wrapper)).toBeTruthy(); }); it('renders without children', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(ChannelValue).length).toEqual(1); }); it('renders with children', () => { const wrapper = shallow( - + diff --git a/components/src/core/Hero/Hero.tsx b/components/src/core/Hero/Hero.tsx index 7ba6bc991..582b10c12 100644 --- a/components/src/core/Hero/Hero.tsx +++ b/components/src/core/Hero/Hero.tsx @@ -1,11 +1,14 @@ import React, { HTMLAttributes, ReactNode } from 'react'; import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; -import { ChannelValue, ChannelValueProps as ChannelValuePropsType } from '../ChannelValue'; +import { ChannelValue } from '../ChannelValue'; import clsx from 'clsx'; import PropTypes from 'prop-types'; const normalizeIconSize = (size: number): number => Math.max(10, size); +const normalizeFontSize = (size: FontSize): string => (size === 'small' ? '1rem' : '1.25rem'); + +type FontSize = 'normal' | 'small'; export type HeroClasses = { root?: string; @@ -17,6 +20,8 @@ export type HeroClasses = { export type HeroProps = HTMLAttributes & { /** Custom classes for default style overrides */ classes?: HeroClasses; + /** The text size for the value line */ + fontSize?: FontSize; /** The primary icon */ icon: ReactNode; /** The color used behind the primary icon @@ -31,8 +36,12 @@ export type HeroProps = HTMLAttributes & { iconSize?: number | string; /** The text shown below the `ChannelValue` */ label: string; - /** Props to be passed through to ChannelValue child component */ - ChannelValueProps?: ChannelValuePropsType; + /** The value for the channel */ + value?: string | number; + /** The inline icon with the value */ + valueIcon?: JSX.Element; + /** Text to show after the value */ + units?: string; }; const useStyles = makeStyles((theme: Theme) => @@ -77,6 +86,7 @@ const useStyles = makeStyles((theme: Theme) => lineHeight: 1.2, maxWidth: '100%', overflow: 'hidden', + fontSize: (props: HeroProps): string => normalizeFontSize(props.fontSize), }, label: { fontSize: 'inherit', @@ -98,9 +108,12 @@ const HeroRender: React.ForwardRefRenderFunction = (props: H classes, icon, label, - ChannelValueProps, + value, + valueIcon, + units, // ignore unused vars so that we can do prop transferring to the root element /* eslint-disable @typescript-eslint/no-unused-vars */ + fontSize, iconBackgroundColor, iconSize, /* eslint-enable @typescript-eslint/no-unused-vars */ @@ -111,7 +124,7 @@ const HeroRender: React.ForwardRefRenderFunction = (props: H
{icon} - {!props.children && ChannelValueProps?.value && } + {!props.children && value && } {props.children} @@ -135,13 +148,18 @@ Hero.propTypes = { icon: PropTypes.string, labels: PropTypes.string, }), + fontSize: PropTypes.oneOf(['normal', 'small']), icon: PropTypes.node.isRequired, iconBackgroundColor: PropTypes.string, iconSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), label: PropTypes.string.isRequired, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + valueIcon: PropTypes.element, + units: PropTypes.string, }; Hero.defaultProps = { classes: {}, + fontSize: 'normal', iconBackgroundColor: 'transparent', iconSize: 36, }; diff --git a/components/src/core/HeroBanner/HeroBanner.test.tsx b/components/src/core/HeroBanner/HeroBanner.test.tsx index 7ecafe1c6..185f3490b 100644 --- a/components/src/core/HeroBanner/HeroBanner.test.tsx +++ b/components/src/core/HeroBanner/HeroBanner.test.tsx @@ -26,11 +26,11 @@ describe('HeroBanner', () => { it('renders only 4 children', () => { const hero = mount( - - - - - + + + + + ); expect(hero.find(Hero).length).toEqual(4); diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 603719147..4748c1323 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,9 +14,7 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : ( - undefined - ); + ) : undefined; const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); diff --git a/demos/storybook/stories/hero/with-full-config.tsx b/demos/storybook/stories/hero/with-full-config.tsx index 7ef27658c..d6a2d7963 100644 --- a/demos/storybook/stories/hero/with-full-config.tsx +++ b/demos/storybook/stories/hero/with-full-config.tsx @@ -12,21 +12,16 @@ import { getLeftToRightIconTransform } from '../../src/utils'; export const withFullConfig = (): StoryFnReactReturnType => ( - ) : ( - undefined - ), - unitSpace: select('unitSpace', ['show', 'hide', 'auto'], 'hide'), - fontSize: select('fontSize', ['normal', 'small'], 'normal'), - }} + value={text('value', '470')} + valueIcon={ + boolean('Show Value Icon', true) ? : undefined + } iconBackgroundColor={color('iconBackgroundColor', Colors.blue[500])} icon={} iconSize={number('iconSize', 35)} + fontSize={select('fontSize', ['normal', 'small'], 'normal')} /> ); diff --git a/demos/storybook/stories/hero/with-icon-colors.tsx b/demos/storybook/stories/hero/with-icon-colors.tsx index 55f5862a2..1fefee4d8 100644 --- a/demos/storybook/stories/hero/with-icon-colors.tsx +++ b/demos/storybook/stories/hero/with-icon-colors.tsx @@ -10,7 +10,8 @@ export const withIconColors = (): StoryFnReactReturnType => ( iconBackgroundColor={color('iconBackgroundColor', Colors.red[500])} icon={} label={'Temperature'} - ChannelValueProps={{ units: '°C', value: '38' }} + value={'38'} + units={'°C'} /> ); diff --git a/demos/storybook/stories/hero/with-value-and-units.tsx b/demos/storybook/stories/hero/with-value-and-units.tsx index a58ce809b..d732d7027 100644 --- a/demos/storybook/stories/hero/with-value-and-units.tsx +++ b/demos/storybook/stories/hero/with-value-and-units.tsx @@ -1,10 +1,16 @@ import { GradeB } from '@brightlayer-ui/icons-mui'; import { Hero } from '@brightlayer-ui/react-components'; +import { text } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import React from 'react'; export const withValueUnits = (): StoryFnReactReturnType => ( - } label={'Efficiency'} ChannelValueProps={{ units: '%', value: '88' }} /> + } + label={'Efficiency'} + value={text('value', '88')} + units={text('units', '%')} + /> ); withValueUnits.story = { name: 'with value and units' }; diff --git a/demos/storybook/stories/hero/within-a-HeroBanner.tsx b/demos/storybook/stories/hero/within-a-HeroBanner.tsx index 117a87095..707578e1b 100644 --- a/demos/storybook/stories/hero/within-a-HeroBanner.tsx +++ b/demos/storybook/stories/hero/within-a-HeroBanner.tsx @@ -11,25 +11,30 @@ export const inBanner = (): StoryFnReactReturnType => { key={'hero1'} icon={} label={'Healthy'} - ChannelValueProps={{ value: '96', units: '/100', unitSpace: 'hide' }} + value={96} + units={'/100'} />, } label={'Load'} - ChannelValueProps={{ value: '90', units: '%', fontSize: 'normal' }} + value={'90'} + units={'%'} + fontSize={'normal'} />, } label={'Temp'} - ChannelValueProps={{ value: '55', units: '°C' }} + value={55} + units={'C'} />, } label={'Battery'} - ChannelValueProps={{ value: '96', units: '/100', unitSpace: 'hide' }} + value={96} + units={'/100'} />, ]; const numberDisplayed = number('count', 4, { range: true, min: 0, max: 4, step: 1 }); diff --git a/demos/storybook/stories/score-card/with-heroes.tsx b/demos/storybook/stories/score-card/with-heroes.tsx index 28608853f..7b7da8689 100644 --- a/demos/storybook/stories/score-card/with-heroes.tsx +++ b/demos/storybook/stories/score-card/with-heroes.tsx @@ -18,15 +18,19 @@ export const heroes: JSX.Element[] = [ label={'Temperature'} iconSize={48} iconBackgroundColor={Colors.white[50]} - ChannelValueProps={{ value: '98', units: '°F' }} + value={98} + units={'°F'} + fontSize={'normal'} />, } label={'Humidity'} - ChannelValueProps={{ value: '54', units: '%' }} + value={54} iconBackgroundColor={Colors.white[50]} + units={'%'} iconSize={48} + fontSize={'normal'} />, ]; diff --git a/demos/storybook/stories/score-card/with-score-badge.tsx b/demos/storybook/stories/score-card/with-score-badge.tsx index 3dce21a76..2facb03ae 100644 --- a/demos/storybook/stories/score-card/with-score-badge.tsx +++ b/demos/storybook/stories/score-card/with-score-badge.tsx @@ -39,7 +39,9 @@ export const withScoreBadge = (): StoryFnReactReturnType => { label={'Grade'} iconSize={72} iconBackgroundColor={useDarkMode() ? Colors.black[900] : Colors.white[50]} - ChannelValueProps={{ value: '98', units: '/100', unitSpace: 'hide' }} + value={'98'} + units={'/100'} + fontSize={'normal'} /> } diff --git a/docs/Hero.md b/docs/Hero.md index 7fb2a4535..fb93c0051 100644 --- a/docs/Hero.md +++ b/docs/Hero.md @@ -8,7 +8,7 @@ The Brightlayer UI `` components are used to call attention to particular The `` component displays a particular icon, value/units, and a label. The icon property will accept any valid component - this will typically be a Material icon, [Brightlayer UI icon](https://github.com/brightlayer-ui/icons), or [Progress Icon](https://github.com/brightlayer-ui/icons/tree/master/progress). It will also accept Text/Emoji values. -The value section of the Hero utilizes a [``](./ChannelValue.md) component. To display a single simple value, the information can be passed as `ChannelValueProps`. For more complex values (such as a duration that displays hours and minutes), you can pass in `` components as children and they will be displayed inline. +The value section of the Hero utilizes a [``](./ChannelValue.md) component. To display a single simple value, the information can be passed as props (`value`, `units`, `valueIcon`). For more complex values (such as a duration that displays hours and minutes), you can pass in `` components as children and they will be displayed inline. ## Hero Usage @@ -23,7 +23,8 @@ import { Hero } from '@brightlayer-ui/react-components'; } label={'Label'} - ChannelValueProps={{ value: 99, units: '%' }} + value={99} + units={'%'} /> // Complex example with multiple values as children -| Prop Name | Description | Type | Required | Default | -| ------------------- | ------------------------------------------ | -------------------- | -------- | ------------- | -| classes | Style overrides | `HeroClasses` | no | | -| ChannelValueProps | Props passed through to ChannelValue child | `ChannelValueProps` | no | | -| icon | The primary icon | `ReactNode` | yes | | -| iconBackgroundColor | The color used behind the primary icon | `string` | no | 'transparent' | -| iconSize | The size of the primary icon (min 10px) | `number` \| `string` | no | 36 | -| label | The text shown below the `ChannelValue` | `string` | yes | | +| Prop Name | Description | Type | Required | Default | +| ------------------- | --------------------------------------- | ----------------------- | -------- | ------------- | +| classes | Style overrides | `HeroClasses` | no | | +| fontSize | The text size for the value line | `'normal'` \| `'small'` | no | 'normal' | +| icon | The primary icon | `ReactNode` | yes | | +| iconBackgroundColor | The color used behind the primary icon | `string` | no | 'transparent' | +| iconSize | The size of the primary icon (min 10px) | `number` \| `string` | no | 36 | +| label | The text shown below the `ChannelValue` | `string` | yes | | +| units | Text to show after the value | `string` | no | | +| value | The value for the channel | `string` \| `number` | no | | +| valueIcon | The inline icon with the value | `JSX.Element` | no | |
diff --git a/docs/ScoreCard.md b/docs/ScoreCard.md index 7f8cfc636..e7c891033 100644 --- a/docs/ScoreCard.md +++ b/docs/ScoreCard.md @@ -34,7 +34,9 @@ import { Temp } from '@brightlayer-ui/icons-mui'; icon={} label={'Temperature'} iconSize={48} - ChannelValueProps={{ value: '98', units: '°F', fontSize: 'normal' }} + value={98} + units={'°F'} + fontSize={'normal'} /> } From e2d61539c598a4d69d3390a75157af07cae0db82 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Thu, 20 Jan 2022 12:20:55 +0530 Subject: [PATCH 38/72] revert user and drawer changes --- components/src/core/UserMenu/UserMenu.tsx | 10 +++--- docs/Drawer.md | 41 ++++++++++++----------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/components/src/core/UserMenu/UserMenu.tsx b/components/src/core/UserMenu/UserMenu.tsx index d7e1c89cd..615c81734 100644 --- a/components/src/core/UserMenu/UserMenu.tsx +++ b/components/src/core/UserMenu/UserMenu.tsx @@ -220,10 +220,10 @@ const UserMenuRender: React.ForwardRefRenderFunction = ( [menuGroups, defaultClasses] ); - const printMenu = useCallback( - (): JSX.Element[] => [printHeader()].concat(printMenuItems()), - [printHeader, printMenuItems] - ); + const printMenu = useCallback((): JSX.Element[] => [printHeader()].concat(printMenuItems()), [ + printHeader, + printMenuItems, + ]); const formatMenu = useCallback((): JSX.Element => { const showBottomSheet = useMediaQuery(`(max-width:${useBottomSheetAt}px)`); @@ -318,4 +318,4 @@ UserMenu.defaultProps = { MenuProps: {}, onClose: (): void => {}, onOpen: (): void => {}, -}; +}; \ No newline at end of file diff --git a/docs/Drawer.md b/docs/Drawer.md index ce078d979..e93000df8 100644 --- a/docs/Drawer.md +++ b/docs/Drawer.md @@ -231,6 +231,7 @@ The `items` property supports nested items to generate collapsible sections in t | title | Text to display in the group header | `string` | no | | | titleColor | Color used for the title text | `string` | no | varies for light/dark theme | | titleContent | Custom element, substitute for title | `ReactNode` | no | | +| titleDivider | Divider for the title | `boolean` | no | true | | [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | | @@ -287,25 +288,25 @@ The `` is an individual line item in the ``. These can be
-| Prop Name | Description | Type | Required | Default | -| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------- | ------- | -| classes | Style overrides | `DrawerNavItemClasses` | no | | -| depth\* | The nested depth of the item | `number` | no | 0 | -| hidden | Sets whether to hide the nav item | `boolean` | no | | -| hidePadding | Remove left padding if no icon is used | `boolean` | no | false | -| icon | A component to render for the left icon | `JSX.Element` | no | | -| isInActiveTree\* | Sets whether the item is a parent of the currently active item (managed automatically) | `boolean` | no | | -| itemID | A unique identifier of the NavItem. Item will have 'active' style when this matches activeItem | `string` | yes | | -| items | The items nested under this item | `NestedNavItem[]` | no | | -| notifyActiveParent\* | Callback function to the parent element to update active hierarchy styles | `(ids: string[]) => void` | no | | -| onClick | A function to execute when clicked | `function` | no | | -| rightComponent | An icon/component to display to the right | `ReactNode` | no | | -| statusColor | Status stripe and icon color | `string` | no | | -| subtitle | The text to show on the second line | `string` | no | | -| title | The text to show on the first line | `string` | yes | | -| disableRailTooltip | Sets whether to disable the tooltip on hover for the condensed `rail` variant | `boolean` | no | | +| Prop Name | Description | Type | Required | Default | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------- | ------- | +| classes | Style overrides | `DrawerNavItemClasses` | no | | +| depth\* | The nested depth of the item | `number` | no | 0 | +| hidden | Sets whether to hide the nav item | `boolean` | no | | +| hidePadding | Remove left padding if no icon is used | `boolean` | no | false | +| icon | A component to render for the left icon | `JSX.Element` | no | | +| isInActiveTree\* | Sets whether the item is a parent of the currently active item (managed automatically) | `boolean` | no | | +| itemID | A unique identifier of the NavItem. Item will have 'active' style when this matches activeItem | `string` | yes | | +| items | The items nested under this item | `NestedNavItem[]` | no | | +| notifyActiveParent\* | Callback function to the parent element to update active hierarchy styles | `(ids: string[]) => void` | no | | +| onClick | A function to execute when clicked | `function` | no | | +| rightComponent | An icon/component to display to the right | `ReactNode` | no | | +| statusColor | Status stripe and icon color | `string` | no | | +| subtitle | The text to show on the second line | `string` | no | | +| title | The text to show on the first line | `string` | yes | | +| disableRailTooltip | Sets whether to disable the tooltip on hover for the condensed `rail` variant | `boolean` | no | | | InfoListItemProps | Used to override [InfoListItem](https://brightlayer-ui-components.github.io/react/?path=/info/components-info-list-item--get-read-me-story) default props | `InfoListItemProps` | no | | -| [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | | +| [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | |
@@ -319,6 +320,7 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. | ---------------- | --------------------------------------------------------------- | | root | Styles applied to the root element wrapping the InfoListItem | | active | Styles applied to the active item highlight element | +| chevron | Styles applied to the chevron element | | expandIcon | Styles applied to the expand/collapse icon wrapper | | infoListItemRoot | Styles applied to the InfoListItem root element | | nestedListGroup | Styles applied to wrapper surrounded nested children | @@ -448,6 +450,7 @@ The following are additional shared props that will apply when using a non-rail | ----------------------------- | ----------------------------------------------------------------------------- | ----------------------- | -------- | ------------------------------------------------------------ | | activeItemBackgroundShape | shape of the active item background highlight | `'round'` \| `'square'` | no | square | | chevron | Whether to have chevrons for all menu items | `boolean` | no | | +| chevronColor | Color override for the chevron icon | `string` | no | | | collapseIcon | Icon used to collapse drawer | `JSX.Element` | no | `expandIcon` rotated 180 degrees | | expandIcon | Icon used to expand drawer | `JSX.Element` | no | `` at top-level, `` otherwise | | hidePadding | Whether to hide the paddings reserved for menu item icons | `boolean` | no | | @@ -501,4 +504,4 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. | root | Styles applied to the root element | | content | Styles applied to the body content container | | drawer | Styles applied to the drawer container | -| expanded | Styles applied to the root element when the drawer is expanded | +| expanded | Styles applied to the root element when the drawer is expanded | \ No newline at end of file From ebc5c5e31583f1152fe7313ee0d2678703d07461 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Thu, 20 Jan 2022 12:24:20 +0530 Subject: [PATCH 39/72] run prettier --- components/src/core/UserMenu/UserMenu.tsx | 10 +++--- docs/Drawer.md | 38 +++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/components/src/core/UserMenu/UserMenu.tsx b/components/src/core/UserMenu/UserMenu.tsx index 615c81734..d7e1c89cd 100644 --- a/components/src/core/UserMenu/UserMenu.tsx +++ b/components/src/core/UserMenu/UserMenu.tsx @@ -220,10 +220,10 @@ const UserMenuRender: React.ForwardRefRenderFunction = ( [menuGroups, defaultClasses] ); - const printMenu = useCallback((): JSX.Element[] => [printHeader()].concat(printMenuItems()), [ - printHeader, - printMenuItems, - ]); + const printMenu = useCallback( + (): JSX.Element[] => [printHeader()].concat(printMenuItems()), + [printHeader, printMenuItems] + ); const formatMenu = useCallback((): JSX.Element => { const showBottomSheet = useMediaQuery(`(max-width:${useBottomSheetAt}px)`); @@ -318,4 +318,4 @@ UserMenu.defaultProps = { MenuProps: {}, onClose: (): void => {}, onOpen: (): void => {}, -}; \ No newline at end of file +}; diff --git a/docs/Drawer.md b/docs/Drawer.md index e93000df8..a3da5c47d 100644 --- a/docs/Drawer.md +++ b/docs/Drawer.md @@ -288,25 +288,25 @@ The `` is an individual line item in the ``. These can be
-| Prop Name | Description | Type | Required | Default | -| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------- | ------- | -| classes | Style overrides | `DrawerNavItemClasses` | no | | -| depth\* | The nested depth of the item | `number` | no | 0 | -| hidden | Sets whether to hide the nav item | `boolean` | no | | -| hidePadding | Remove left padding if no icon is used | `boolean` | no | false | -| icon | A component to render for the left icon | `JSX.Element` | no | | -| isInActiveTree\* | Sets whether the item is a parent of the currently active item (managed automatically) | `boolean` | no | | -| itemID | A unique identifier of the NavItem. Item will have 'active' style when this matches activeItem | `string` | yes | | -| items | The items nested under this item | `NestedNavItem[]` | no | | -| notifyActiveParent\* | Callback function to the parent element to update active hierarchy styles | `(ids: string[]) => void` | no | | -| onClick | A function to execute when clicked | `function` | no | | -| rightComponent | An icon/component to display to the right | `ReactNode` | no | | -| statusColor | Status stripe and icon color | `string` | no | | -| subtitle | The text to show on the second line | `string` | no | | -| title | The text to show on the first line | `string` | yes | | -| disableRailTooltip | Sets whether to disable the tooltip on hover for the condensed `rail` variant | `boolean` | no | | +| Prop Name | Description | Type | Required | Default | +| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------- | ------- | +| classes | Style overrides | `DrawerNavItemClasses` | no | | +| depth\* | The nested depth of the item | `number` | no | 0 | +| hidden | Sets whether to hide the nav item | `boolean` | no | | +| hidePadding | Remove left padding if no icon is used | `boolean` | no | false | +| icon | A component to render for the left icon | `JSX.Element` | no | | +| isInActiveTree\* | Sets whether the item is a parent of the currently active item (managed automatically) | `boolean` | no | | +| itemID | A unique identifier of the NavItem. Item will have 'active' style when this matches activeItem | `string` | yes | | +| items | The items nested under this item | `NestedNavItem[]` | no | | +| notifyActiveParent\* | Callback function to the parent element to update active hierarchy styles | `(ids: string[]) => void` | no | | +| onClick | A function to execute when clicked | `function` | no | | +| rightComponent | An icon/component to display to the right | `ReactNode` | no | | +| statusColor | Status stripe and icon color | `string` | no | | +| subtitle | The text to show on the second line | `string` | no | | +| title | The text to show on the first line | `string` | yes | | +| disableRailTooltip | Sets whether to disable the tooltip on hover for the condensed `rail` variant | `boolean` | no | | | InfoListItemProps | Used to override [InfoListItem](https://brightlayer-ui-components.github.io/react/?path=/info/components-info-list-item--get-read-me-story) default props | `InfoListItemProps` | no | | -| [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | | +| [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | |
@@ -504,4 +504,4 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. | root | Styles applied to the root element | | content | Styles applied to the body content container | | drawer | Styles applied to the drawer container | -| expanded | Styles applied to the root element when the drawer is expanded | \ No newline at end of file +| expanded | Styles applied to the root element when the drawer is expanded | From bab27091491b97836bd4a81d0c8608491dcbfc88 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Thu, 20 Jan 2022 12:26:04 +0530 Subject: [PATCH 40/72] run prettier --- components/src/core/UserMenu/UserMenu.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/src/core/UserMenu/UserMenu.tsx b/components/src/core/UserMenu/UserMenu.tsx index d7e1c89cd..41cf78154 100644 --- a/components/src/core/UserMenu/UserMenu.tsx +++ b/components/src/core/UserMenu/UserMenu.tsx @@ -220,10 +220,10 @@ const UserMenuRender: React.ForwardRefRenderFunction = ( [menuGroups, defaultClasses] ); - const printMenu = useCallback( - (): JSX.Element[] => [printHeader()].concat(printMenuItems()), - [printHeader, printMenuItems] - ); + const printMenu = useCallback((): JSX.Element[] => [printHeader()].concat(printMenuItems()), [ + printHeader, + printMenuItems, + ]); const formatMenu = useCallback((): JSX.Element => { const showBottomSheet = useMediaQuery(`(max-width:${useBottomSheetAt}px)`); From 27635cc69d5405d71d6fa6936ea6bde4970615bb Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Thu, 20 Jan 2022 13:18:52 +0530 Subject: [PATCH 41/72] run prettier --- .../channel-value/with-full-config.tsx | 4 +- docs/Drawer.md | 38 +++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 4748c1323..603719147 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,7 +14,9 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : undefined; + ) : ( + undefined + ); const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); diff --git a/docs/Drawer.md b/docs/Drawer.md index a3da5c47d..e93000df8 100644 --- a/docs/Drawer.md +++ b/docs/Drawer.md @@ -288,25 +288,25 @@ The `` is an individual line item in the ``. These can be
-| Prop Name | Description | Type | Required | Default | -| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------- | ------- | -| classes | Style overrides | `DrawerNavItemClasses` | no | | -| depth\* | The nested depth of the item | `number` | no | 0 | -| hidden | Sets whether to hide the nav item | `boolean` | no | | -| hidePadding | Remove left padding if no icon is used | `boolean` | no | false | -| icon | A component to render for the left icon | `JSX.Element` | no | | -| isInActiveTree\* | Sets whether the item is a parent of the currently active item (managed automatically) | `boolean` | no | | -| itemID | A unique identifier of the NavItem. Item will have 'active' style when this matches activeItem | `string` | yes | | -| items | The items nested under this item | `NestedNavItem[]` | no | | -| notifyActiveParent\* | Callback function to the parent element to update active hierarchy styles | `(ids: string[]) => void` | no | | -| onClick | A function to execute when clicked | `function` | no | | -| rightComponent | An icon/component to display to the right | `ReactNode` | no | | -| statusColor | Status stripe and icon color | `string` | no | | -| subtitle | The text to show on the second line | `string` | no | | -| title | The text to show on the first line | `string` | yes | | -| disableRailTooltip | Sets whether to disable the tooltip on hover for the condensed `rail` variant | `boolean` | no | | +| Prop Name | Description | Type | Required | Default | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------- | ------- | +| classes | Style overrides | `DrawerNavItemClasses` | no | | +| depth\* | The nested depth of the item | `number` | no | 0 | +| hidden | Sets whether to hide the nav item | `boolean` | no | | +| hidePadding | Remove left padding if no icon is used | `boolean` | no | false | +| icon | A component to render for the left icon | `JSX.Element` | no | | +| isInActiveTree\* | Sets whether the item is a parent of the currently active item (managed automatically) | `boolean` | no | | +| itemID | A unique identifier of the NavItem. Item will have 'active' style when this matches activeItem | `string` | yes | | +| items | The items nested under this item | `NestedNavItem[]` | no | | +| notifyActiveParent\* | Callback function to the parent element to update active hierarchy styles | `(ids: string[]) => void` | no | | +| onClick | A function to execute when clicked | `function` | no | | +| rightComponent | An icon/component to display to the right | `ReactNode` | no | | +| statusColor | Status stripe and icon color | `string` | no | | +| subtitle | The text to show on the second line | `string` | no | | +| title | The text to show on the first line | `string` | yes | | +| disableRailTooltip | Sets whether to disable the tooltip on hover for the condensed `rail` variant | `boolean` | no | | | InfoListItemProps | Used to override [InfoListItem](https://brightlayer-ui-components.github.io/react/?path=/info/components-info-list-item--get-read-me-story) default props | `InfoListItemProps` | no | | -| [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | | +| [...sharedProps](#shared-props) | Props that can be set at any level in the drawer hierarchy | - | - | |
@@ -504,4 +504,4 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. | root | Styles applied to the root element | | content | Styles applied to the body content container | | drawer | Styles applied to the drawer container | -| expanded | Styles applied to the root element when the drawer is expanded | +| expanded | Styles applied to the root element when the drawer is expanded | \ No newline at end of file From 215a5b7cab4a13ac9c3436556f74814f919cc95f Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Thu, 20 Jan 2022 16:47:46 +0530 Subject: [PATCH 42/72] add ToolbarMenu component --- .../src/core/ToolbarMenu/ToolbarMenu.tsx | 87 +++++++++++++++++++ components/src/core/ToolbarMenu/index.ts | 1 + components/src/core/index.ts | 1 + .../stories/toolbar-menu/_module.stories.tsx | 18 ++++ .../stories/toolbar-menu/icon-with-label.tsx | 19 ++++ .../stories/toolbar-menu/with-basic-usage.tsx | 13 +++ docs/ToolbarMenu.md | 27 ++++++ 7 files changed, 166 insertions(+) create mode 100644 components/src/core/ToolbarMenu/ToolbarMenu.tsx create mode 100644 components/src/core/ToolbarMenu/index.ts create mode 100644 demos/storybook/stories/toolbar-menu/_module.stories.tsx create mode 100644 demos/storybook/stories/toolbar-menu/icon-with-label.tsx create mode 100644 demos/storybook/stories/toolbar-menu/with-basic-usage.tsx create mode 100644 docs/ToolbarMenu.md diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx new file mode 100644 index 000000000..444c3d2d3 --- /dev/null +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -0,0 +1,87 @@ +import React, { HTMLAttributes, ReactNode } from 'react'; +// import { Theme } from '@material-ui/core/styles/createMuiTheme'; +import createStyles from '@material-ui/core/styles/createStyles'; +import makeStyles from '@material-ui/core/styles/makeStyles'; +import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; +// import clsx from 'clsx'; + +export type ToolbarMenuClasses = { + root?: string; + label?: string; + dropdownArrow?: string; + menuItem?: string; +}; + +const useStyles = makeStyles(() => + createStyles({ + // root: { + // display: 'flex', + // height: '100%', + // flexDirection: 'column', + // justifyContent: 'center', + // transition: (props: ToolbarMenuProps): string => + // theme.transitions.create(['all'], { + // duration: props.animationDuration || theme.transitions.duration.standard, + // easing: theme.transitions.easing.easeInOut, + // }), + // }, + // title: { + // fontSize: '1.875rem', + // transition: (props: ToolbarMenuProps): string => + // theme.transitions.create(['all'], { + // duration: props.animationDuration || theme.transitions.duration.standard, + // easing: theme.transitions.easing.easeInOut, + // }), + // }, + // subtitle: { + // fontSize: '1rem', + // transition: (props: ToolbarMenuProps): string => + // theme.transitions.create(['all'], { + // duration: props.animationDuration || theme.transitions.duration.standard, + // easing: theme.transitions.easing.easeInOut, + // }), + // }, + // info: { + // fontSize: '0.875rem', + // transition: (props: ToolbarMenuProps): string => + // theme.transitions.create(['all'], { + // duration: props.animationDuration || theme.transitions.duration.standard, + // easing: theme.transitions.easing.easeInOut, + // }), + // fontWeight: 300, + // }, + }) +); + +export type ToolbarMenuProps = HTMLAttributes & { + /** Label Content */ + label?: ReactNode; +}; + +const ToolbarMenuRenderer: React.ForwardRefRenderFunction = ( + props: ToolbarMenuProps, + ref: any +) => { + const { + label, + className, + ...otherDivProps + } = props; + // const defaultClasses = useStyles(props); + //const animationDuration = durationProp || theme.transitions.duration.standard; + return ( +
+
{label}
+ +
+ ); +}; +/** + * [ToolbarMenu](https://brightlayer-ui-components.github.io/react/?path=/info/components-three-liner--get-read-me-story) component + * + * The `ToolbarMenu` used to display a dropdown menu with label. + */ +export const ToolbarMenu = React.forwardRef(ToolbarMenuRenderer); +ToolbarMenu.displayName = 'ToolbarMenu'; diff --git a/components/src/core/ToolbarMenu/index.ts b/components/src/core/ToolbarMenu/index.ts new file mode 100644 index 000000000..607ec076e --- /dev/null +++ b/components/src/core/ToolbarMenu/index.ts @@ -0,0 +1 @@ +export * from './ToolbarMenu'; diff --git a/components/src/core/index.ts b/components/src/core/index.ts index 3645f494a..cc78a46c4 100644 --- a/components/src/core/index.ts +++ b/components/src/core/index.ts @@ -12,3 +12,4 @@ export * from './UserMenu'; export * from './DropdownToolbar'; export * from './AppBar'; export * from './ThreeLiner'; +export * from './ToolbarMenu'; diff --git a/demos/storybook/stories/toolbar-menu/_module.stories.tsx b/demos/storybook/stories/toolbar-menu/_module.stories.tsx new file mode 100644 index 000000000..0639d2770 --- /dev/null +++ b/demos/storybook/stories/toolbar-menu/_module.stories.tsx @@ -0,0 +1,18 @@ +import { ToolbarMenu } from '@brightlayer-ui/react-components'; +import { COMPONENT_SECTION_NAME } from '../../src/constants'; +import { storyParams, storyWrapper } from '../../src/utils'; +import { withA11y } from '@storybook/addon-a11y'; + +const toolbarMenuModule = { + title: `${COMPONENT_SECTION_NAME}/Toolbar Menu`, + component: ToolbarMenu, + // @accessibility remove withA11y from decorators array to hide a11y addon + decorators: [storyWrapper, withA11y], + parameters: { ...storyParams, notes: { markdown: require('./../../../../docs/ToolbarMenu.md') } }, +}; + +/* Display order goe6s here */ +export { getReadMeStory } from '../../src/utils'; +export { withBasicUsage } from './with-basic-usage'; +export { iconWithLabel } from './icon-with-label'; +export default toolbarMenuModule; diff --git a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx new file mode 100644 index 000000000..6cf13744a --- /dev/null +++ b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { text } from '@storybook/addon-knobs'; +import { GradeA } from '@brightlayer-ui/icons-mui'; +import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; +import { WITH_MIN_PROPS_STORY_NAME } from '../../src/constants'; +import { ToolbarMenu } from '@brightlayer-ui/react-components'; + +export const iconWithLabel = (): StoryFnReactReturnType => { + // const label = text('label', 'label'); + + return + + Dropdown Toolbar + + }/>; +}; + +iconWithLabel.story = { name: WITH_MIN_PROPS_STORY_NAME }; diff --git a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx new file mode 100644 index 000000000..8db2173d2 --- /dev/null +++ b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { text } from '@storybook/addon-knobs'; +import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; +import { WITH_MIN_PROPS_STORY_NAME } from '../../src/constants'; +import { ToolbarMenu } from '@brightlayer-ui/react-components'; + +export const withBasicUsage = (): StoryFnReactReturnType => { + const label = text('label', 'label'); + + return ; +}; + +withBasicUsage.story = { name: WITH_MIN_PROPS_STORY_NAME }; diff --git a/docs/ToolbarMenu.md b/docs/ToolbarMenu.md new file mode 100644 index 000000000..df8358e36 --- /dev/null +++ b/docs/ToolbarMenu.md @@ -0,0 +1,27 @@ +# Three Liner + +The `ThreeLiner` can display up to three lines of stylized text or other custom content. It is most commonly used within the context of a [`AppBar`](./AppBar.md) component where the text can grow / shrink as the App Bar is expanded and collapsed. + +## API + +
+ +| Prop Name | Description | Type | Required | Default | +| ----------------- | ------------------------------------------------- | ------------------- | -------- | ------------------------------------- | +| animationDuration | Time in milliseconds to transition between states | `number` | no | `theme.transitions.duration.standard` | +| classes | Style overrides | `ThreeLinerClasses` | no | | +| info | Third line content | `ReactNode` | no | | +| title | First line content | `ReactNode` | no | | +| subtitle | Second line content | `ReactNode` | no | | + +
+### Classes + +You can override the classes used by Brightlayer UI by passing a `classes` prop. It supports the following keys: + +| Name | Description | +| -------- | ---------------------------------- | +| root | Styles applied to the root element | +| title | Styles applied to the first line | +| subtitle | Styles applied to the second line | +| info | Styles applied to the third line | From d89c1796340b7f8db7662ff597309840988bd45d Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 21 Jan 2022 16:57:17 +0530 Subject: [PATCH 43/72] update menu --- .../src/core/ToolbarMenu/ToolbarMenu.tsx | 216 ++++++++++++++---- .../stories/toolbar-menu/_module.stories.tsx | 1 + .../stories/toolbar-menu/icon-with-label.tsx | 15 +- .../stories/toolbar-menu/with-menu.tsx | 34 +++ 4 files changed, 209 insertions(+), 57 deletions(-) create mode 100644 demos/storybook/stories/toolbar-menu/with-menu.tsx diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 444c3d2d3..e7236e5d4 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -1,61 +1,75 @@ -import React, { HTMLAttributes, ReactNode } from 'react'; -// import { Theme } from '@material-ui/core/styles/createMuiTheme'; +import React, { HTMLAttributes, ReactNode, useState, useCallback, useRef, useEffect } from 'react'; +import { Theme } from '@material-ui/core/styles/createMuiTheme'; import createStyles from '@material-ui/core/styles/createStyles'; import makeStyles from '@material-ui/core/styles/makeStyles'; import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; -// import clsx from 'clsx'; +import clsx from 'clsx'; +import { NavItem, DrawerNavGroup } from '../Drawer'; +import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; +import { Typography, useTheme } from '@material-ui/core'; export type ToolbarMenuClasses = { root?: string; label?: string; + toolbarMenuContent?: string; dropdownArrow?: string; menuItem?: string; }; -const useStyles = makeStyles(() => +export type ToolbarMenuItem1 = Omit & { itemID?: string }; +export type ToolbarMenuGroup1 = { + /** The color used for the text */ + fontColor?: string; + /** The color used for icons */ + iconColor?: string; + /** List of navigation items to render */ + items: ToolbarMenuItem1[]; + /** Text to display in the group header */ + title?: string; +}; + +const useStyles = makeStyles((theme: Theme) => createStyles({ - // root: { - // display: 'flex', - // height: '100%', - // flexDirection: 'column', - // justifyContent: 'center', - // transition: (props: ToolbarMenuProps): string => - // theme.transitions.create(['all'], { - // duration: props.animationDuration || theme.transitions.duration.standard, - // easing: theme.transitions.easing.easeInOut, - // }), - // }, - // title: { - // fontSize: '1.875rem', - // transition: (props: ToolbarMenuProps): string => - // theme.transitions.create(['all'], { - // duration: props.animationDuration || theme.transitions.duration.standard, - // easing: theme.transitions.easing.easeInOut, - // }), - // }, - // subtitle: { - // fontSize: '1rem', - // transition: (props: ToolbarMenuProps): string => - // theme.transitions.create(['all'], { - // duration: props.animationDuration || theme.transitions.duration.standard, - // easing: theme.transitions.easing.easeInOut, - // }), - // }, - // info: { - // fontSize: '0.875rem', - // transition: (props: ToolbarMenuProps): string => - // theme.transitions.create(['all'], { - // duration: props.animationDuration || theme.transitions.duration.standard, - // easing: theme.transitions.easing.easeInOut, - // }), - // fontWeight: 300, - // }, + root: { + display: 'flex', + alignItems: 'center', + verticalAlign: 'middle', + }, + toolbarMenuContent: { + display: 'flex', + }, + navGroups: { + '&:active, &:focus': { + outline: 'none', + }, + }, + cursorPointer: { + cursor: 'pointer', + }, + dropdownArrow: { + marginLeft: theme.spacing(0.5), + }, + rotateDropdownArrow: { + transform: 'rotate(180deg)', + }, }) ); export type ToolbarMenuProps = HTMLAttributes & { /** Label Content */ label?: ReactNode; + /** Custom content to be displayed in the menu */ + menu?: JSX.Element; + /** Groups of menu items to display */ + menuGroups?: ToolbarMenuGroup1[]; + /** Property overrides for the MUI Menu */ + MenuProps?: Omit; + /** Function called when the menu is opened */ + onOpen?: () => void; + /** Function called when the menu is closed */ + onClose?: () => void; + /** Custom classes for default style overrides */ + classes?: Partial; }; const ToolbarMenuRenderer: React.ForwardRefRenderFunction = ( @@ -64,17 +78,123 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { const { label, - className, + classes = {}, + menuGroups, + menu, + MenuProps, + onClose, + onOpen, ...otherDivProps } = props; - // const defaultClasses = useStyles(props); - //const animationDuration = durationProp || theme.transitions.duration.standard; + const theme = useTheme(); + const rtl = theme.direction === 'rtl'; + const defaultClasses = useStyles(props); + const [anchorEl, setAnchorEl] = useState(null); + const anchor = useRef(null); + + const closeMenu = useCallback(() => { + if (onClose) { + onClose(); + } + setAnchorEl(null); + }, [onClose]); + + const openMenu = useCallback( + (event: MouseEvent) => { + if (onOpen) { + onOpen(); + } + setAnchorEl(event); + }, + [onOpen] + ); + + useEffect(() => { + if(menuGroups) { + for (const group of menuGroups) { + for (const item of group.items) { + const onClick = item.onClick; + if (onClick) { + item.onClick = (e: React.MouseEvent): void => { + onClick(e); + closeMenu(); + }; + } + } + } + } + + }, [menuGroups]); + + const getMenu = useCallback(() => { + if (menu && Boolean(anchorEl)) { + return React.cloneElement(menu, { + anchorEl: anchorEl, + open: Boolean(anchorEl), + onClose: closeMenu, + ...menu.props, + }); + } + if (menuGroups && Boolean(anchorEl)) { + return ( + closeMenu()} + {...MenuProps} + MenuListProps={{ style: { padding: 0 } }} + > + {!menu && + menuGroups.map((group: ToolbarMenuGroup1, index: number) => ( +
+ + Object.assign({ itemID: itemIndex.toString() }, item) + )} + /> +
+ ))} +
+ ); + } + }, [menuGroups, menu, anchorEl, MenuProps, defaultClasses]); + return ( -
-
{label}
- +
+ { + openMenu(anchor.current); + }} + className={clsx( + defaultClasses.toolbarMenuContent, + classes.toolbarMenuContent, + menuGroups || menu ? defaultClasses.cursorPointer : '' + )} + > + {label || ''} + {(menuGroups || menu) && ( + + )} + + {getMenu()}
); }; diff --git a/demos/storybook/stories/toolbar-menu/_module.stories.tsx b/demos/storybook/stories/toolbar-menu/_module.stories.tsx index 0639d2770..c9c106474 100644 --- a/demos/storybook/stories/toolbar-menu/_module.stories.tsx +++ b/demos/storybook/stories/toolbar-menu/_module.stories.tsx @@ -15,4 +15,5 @@ const toolbarMenuModule = { export { getReadMeStory } from '../../src/utils'; export { withBasicUsage } from './with-basic-usage'; export { iconWithLabel } from './icon-with-label'; +export { withMenu } from './with-menu'; export default toolbarMenuModule; diff --git a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx index 6cf13744a..48258ea0c 100644 --- a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx +++ b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx @@ -1,19 +1,16 @@ import React from 'react'; -import { text } from '@storybook/addon-knobs'; import { GradeA } from '@brightlayer-ui/icons-mui'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; -import { WITH_MIN_PROPS_STORY_NAME } from '../../src/constants'; import { ToolbarMenu } from '@brightlayer-ui/react-components'; +import { typography } from '@storybook/theming'; export const iconWithLabel = (): StoryFnReactReturnType => { - // const label = text('label', 'label'); - return - - Dropdown Toolbar - + + + Dropdown Toolbar + }/>; }; -iconWithLabel.story = { name: WITH_MIN_PROPS_STORY_NAME }; +iconWithLabel.story = { name: 'icon with label' }; \ No newline at end of file diff --git a/demos/storybook/stories/toolbar-menu/with-menu.tsx b/demos/storybook/stories/toolbar-menu/with-menu.tsx new file mode 100644 index 000000000..4d3fc25d4 --- /dev/null +++ b/demos/storybook/stories/toolbar-menu/with-menu.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { GradeA } from '@brightlayer-ui/icons-mui'; +import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; +import { ToolbarMenu } from '@brightlayer-ui/react-components'; +import { AppBar,} from '@material-ui/core'; +import { action } from '@storybook/addon-actions'; +import { text, } from '@storybook/addon-knobs'; +export const withMenu = (): StoryFnReactReturnType => { + const menuItems = [ + { title: 'Item 1', onClick: action('Item 1 selected') }, + { title: 'Item 2', onClick: action('Item 2 selected') }, + { title: 'Item 3', onClick: action('Item 3 selected') }, + ]; + + const menuGroups = [ + { + items: menuItems, + }, + ]; + return ( + // + + + Dropdown Toolbar + } + menuGroups={menuGroups} + > + + // + ); +}; + +withMenu.story = { name: 'with menu' }; \ No newline at end of file From 09589f583a1fb48c662c2e0af95f7e886ab940fe Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 21 Jan 2022 17:28:43 +0530 Subject: [PATCH 44/72] rename white list variable --- .../src/core/ChannelValue/ChannelValue.tsx | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/components/src/core/ChannelValue/ChannelValue.tsx b/components/src/core/ChannelValue/ChannelValue.tsx index df10acda0..77e3eb5d1 100644 --- a/components/src/core/ChannelValue/ChannelValue.tsx +++ b/components/src/core/ChannelValue/ChannelValue.tsx @@ -36,8 +36,8 @@ export type ChannelValueProps = Omit, 'prefix'> * * Default: auto (shows space except for white list items) * - * prefixUnitWhitelist: ['$']; - * suffixUnitWhitelist: ['%', '℉','°F','℃','°C','°'] + * prefixUnitAllowSpaceList: ['$']; + * suffixUnitAllowSpaceList: ['%', '℉','°F','℃','°C','°'] */ unitSpace?: 'show' | 'hide' | 'auto'; /** Text to display for the value (bold text) */ @@ -105,19 +105,12 @@ const ChannelValueRender: React.ForwardRefRenderFunction { - if ((!prefixUnitWhitelist.includes(units) && unitSpace !== 'hide') || unitSpace === 'show') { - return true; - } - }, [prefix, units, unitSpace]); + const prefixUnitAllowSpaceList = ['$']; + const suffixUnitAllowSpaceList = ['%', '℉', '°F', '℃', '°C', '°']; - const applySuffix = useCallback((): boolean => { - if ((!suffixUnitWhitelist.includes(units) && unitSpace !== 'hide') || unitSpace === 'show') { - return true; - } - }, [prefix, units, unitSpace]); + const applyPrefix = useCallback((): boolean => prefix && unitSpace !== 'hide' && (unitSpace === 'show' || !prefixUnitAllowSpaceList.includes(units)), [units, unitSpace]); + + const applySuffix = useCallback((): boolean => !prefix && unitSpace !== 'hide' && (unitSpace === 'show' || !suffixUnitAllowSpaceList.includes(units)), [units, unitSpace]); const getUnitElement = useCallback( (): JSX.Element => ( @@ -127,8 +120,8 @@ const ChannelValueRender: React.ForwardRefRenderFunction From 40dfbed527ac2703498188c9ae559098accb6c03 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 21 Jan 2022 17:31:18 +0530 Subject: [PATCH 45/72] fix prettier --- components/src/core/ChannelValue/ChannelValue.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/src/core/ChannelValue/ChannelValue.tsx b/components/src/core/ChannelValue/ChannelValue.tsx index 77e3eb5d1..b2996f78f 100644 --- a/components/src/core/ChannelValue/ChannelValue.tsx +++ b/components/src/core/ChannelValue/ChannelValue.tsx @@ -108,9 +108,17 @@ const ChannelValueRender: React.ForwardRefRenderFunction prefix && unitSpace !== 'hide' && (unitSpace === 'show' || !prefixUnitAllowSpaceList.includes(units)), [units, unitSpace]); + const applyPrefix = useCallback( + (): boolean => + prefix && unitSpace !== 'hide' && (unitSpace === 'show' || !prefixUnitAllowSpaceList.includes(units)), + [units, unitSpace] + ); - const applySuffix = useCallback((): boolean => !prefix && unitSpace !== 'hide' && (unitSpace === 'show' || !suffixUnitAllowSpaceList.includes(units)), [units, unitSpace]); + const applySuffix = useCallback( + (): boolean => + !prefix && unitSpace !== 'hide' && (unitSpace === 'show' || !suffixUnitAllowSpaceList.includes(units)), + [units, unitSpace] + ); const getUnitElement = useCallback( (): JSX.Element => ( From 6403b42d3b1baa28f6eaa9f8901cbb337ddedf87 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Sat, 22 Jan 2022 11:07:47 +0530 Subject: [PATCH 46/72] fix p tag issue --- .../src/core/ToolbarMenu/ToolbarMenu.tsx | 18 +++-- .../stories/toolbar-menu/icon-with-label.tsx | 18 +++-- .../stories/toolbar-menu/with-basic-usage.tsx | 4 +- .../stories/toolbar-menu/with-menu.tsx | 78 +++++++++++++++---- 4 files changed, 88 insertions(+), 30 deletions(-) diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index e7236e5d4..06c90bbfb 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -37,6 +37,7 @@ const useStyles = makeStyles((theme: Theme) => }, toolbarMenuContent: { display: 'flex', + cursor: 'pointer', }, navGroups: { '&:active, &:focus': { @@ -169,33 +170,34 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction + <> { - openMenu(anchor.current); - }} + component={'span'} className={clsx( defaultClasses.toolbarMenuContent, classes.toolbarMenuContent, - menuGroups || menu ? defaultClasses.cursorPointer : '' + )} > {label || ''} {(menuGroups || menu) && ( { + openMenu(anchor.current); + }} className={clsx( defaultClasses.dropdownArrow, classes.dropdownArrow, - anchorEl ? defaultClasses.rotateDropdownArrow : '' + anchorEl ? defaultClasses.rotateDropdownArrow : '', + menuGroups || menu ? defaultClasses.cursorPointer : '' )} /> )} {getMenu()} -
+ ); }; /** diff --git a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx index 48258ea0c..afc2348a3 100644 --- a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx +++ b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx @@ -5,12 +5,16 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components'; import { typography } from '@storybook/theming'; export const iconWithLabel = (): StoryFnReactReturnType => { - return - - Dropdown Toolbar - - }/>; + return ( + + + Dropdown Toolbar + + } + /> + ); }; -iconWithLabel.story = { name: 'icon with label' }; \ No newline at end of file +iconWithLabel.story = { name: 'icon with label' }; diff --git a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx index 8db2173d2..0f0cf0a07 100644 --- a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx +++ b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx @@ -6,8 +6,8 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components'; export const withBasicUsage = (): StoryFnReactReturnType => { const label = text('label', 'label'); - - return ; + + return ; }; withBasicUsage.story = { name: WITH_MIN_PROPS_STORY_NAME }; diff --git a/demos/storybook/stories/toolbar-menu/with-menu.tsx b/demos/storybook/stories/toolbar-menu/with-menu.tsx index 4d3fc25d4..d47491154 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu.tsx +++ b/demos/storybook/stories/toolbar-menu/with-menu.tsx @@ -2,9 +2,13 @@ import React from 'react'; import { GradeA } from '@brightlayer-ui/icons-mui'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import { ToolbarMenu } from '@brightlayer-ui/react-components'; -import { AppBar,} from '@material-ui/core'; +import Toolbar from '@material-ui/core/Toolbar'; +import AppBar from '@material-ui/core/AppBar'; +import ListItemText from '@material-ui/core/ListItemText'; +import Typography from '@material-ui/core/Typography'; import { action } from '@storybook/addon-actions'; -import { text, } from '@storybook/addon-knobs'; +import makeStyles from '@material-ui/core/styles/makeStyles'; +import clsx from 'clsx'; export const withMenu = (): StoryFnReactReturnType => { const menuItems = [ { title: 'Item 1', onClick: action('Item 1 selected') }, @@ -17,18 +21,66 @@ export const withMenu = (): StoryFnReactReturnType => { items: menuItems, }, ]; + const useStyles = makeStyles({ + labelContent: { + display: 'flex', + }, + textContent: { + overflow: 'hidden', + whiteSpace: 'nowrap', + // set margins to default to avoid the height of the app bar exceeding 56px on mobile + '&.MuiListItemText-multiline': { + marginTop: '0.25rem', + marginBottom: '0.25rem', + }, + }, + root: { + color: 'white', + } + }); + + const classes = useStyles(); return ( - // - - - Dropdown Toolbar - } - menuGroups={menuGroups} - > - - // + + {/* + + Title +
+ } + secondary={ + + + Dropdown Toolbar + + } + menuGroups={menuGroups} + > + } + /> + */} + + {/* {getNavigationIcon()} */} + + Title +
+ } + secondary={ + + } + /> + {/* {props.children} */} + + ); }; -withMenu.story = { name: 'with menu' }; \ No newline at end of file +withMenu.story = { name: 'with menu' }; From a9c0c544eeb83a78133bc3298bfc55595918f3c4 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 24 Jan 2022 13:11:44 +0530 Subject: [PATCH 47/72] update changelog, story, readme --- CHANGELOG.md | 1 + .../src/core/ToolbarMenu/ToolbarMenu.tsx | 66 ++++----- .../channel-value/with-full-config.tsx | 4 +- .../stories/toolbar-menu/_module.stories.tsx | 3 +- .../stories/toolbar-menu/icon-with-label.tsx | 46 +++++- .../{with-menu.tsx => with-app-bar.tsx} | 50 ++----- .../stories/toolbar-menu/with-basic-usage.tsx | 15 +- .../toolbar-menu/with-blui-app-bar.tsx | 137 ++++++++++++++++++ docs/ToolbarMenu.md | 82 +++++++++-- docs/images/ToolbarMenuAnatomy.png | Bin 0 -> 55606 bytes 10 files changed, 302 insertions(+), 102 deletions(-) rename demos/storybook/stories/toolbar-menu/{with-menu.tsx => with-app-bar.tsx} (53%) create mode 100644 demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx create mode 100644 docs/images/ToolbarMenuAnatomy.png diff --git a/CHANGELOG.md b/CHANGELOG.md index a64b4b2e6..68b25f9e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Added class override for `chevron` on `` and ``. - Added `titleDivider` property onto ``. ([#315](https://github.com/brightlayer-ui/react-component-library/issues/315)) - Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) +- Added `` component. ([#351](https://github.com/brightlayer-ui/react-component-library/issues/351)) ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 06c90bbfb..6f76ede40 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -4,14 +4,13 @@ import createStyles from '@material-ui/core/styles/createStyles'; import makeStyles from '@material-ui/core/styles/makeStyles'; import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; import clsx from 'clsx'; -import { NavItem, DrawerNavGroup } from '../Drawer'; +import { DrawerNavGroup, NavItem } from '../Drawer'; import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; import { Typography, useTheme } from '@material-ui/core'; export type ToolbarMenuClasses = { root?: string; label?: string; - toolbarMenuContent?: string; dropdownArrow?: string; menuItem?: string; }; @@ -31,11 +30,6 @@ export type ToolbarMenuGroup1 = { const useStyles = makeStyles((theme: Theme) => createStyles({ root: { - display: 'flex', - alignItems: 'center', - verticalAlign: 'middle', - }, - toolbarMenuContent: { display: 'flex', cursor: 'pointer', }, @@ -53,12 +47,16 @@ const useStyles = makeStyles((theme: Theme) => rotateDropdownArrow: { transform: 'rotate(180deg)', }, + label: { + textOverflow: 'ellipsis', + overflow: 'hidden', + }, }) ); export type ToolbarMenuProps = HTMLAttributes & { /** Label Content */ - label?: ReactNode; + label: ReactNode; /** Custom content to be displayed in the menu */ menu?: JSX.Element; /** Groups of menu items to display */ @@ -73,20 +71,8 @@ export type ToolbarMenuProps = HTMLAttributes & { classes?: Partial; }; -const ToolbarMenuRenderer: React.ForwardRefRenderFunction = ( - props: ToolbarMenuProps, - ref: any -) => { - const { - label, - classes = {}, - menuGroups, - menu, - MenuProps, - onClose, - onOpen, - ...otherDivProps - } = props; +const ToolbarMenuRenderer: React.ForwardRefRenderFunction = (props: ToolbarMenuProps) => { + const { label, classes = {}, menuGroups, menu, MenuProps, onClose, onOpen } = props; const theme = useTheme(); const rtl = theme.direction === 'rtl'; const defaultClasses = useStyles(props); @@ -111,7 +97,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { - if(menuGroups) { + if (menuGroups) { for (const group of menuGroups) { for (const item of group.items) { const onClick = item.onClick; @@ -124,7 +110,6 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { @@ -176,32 +161,31 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { + openMenu(anchor.current); + }} > - {label || ''} + {label || ''} {(menuGroups || menu) && ( - { - openMenu(anchor.current); - }} - className={clsx( - defaultClasses.dropdownArrow, - classes.dropdownArrow, - anchorEl ? defaultClasses.rotateDropdownArrow : '', - menuGroups || menu ? defaultClasses.cursorPointer : '' - )} - /> - )} + + )} {getMenu()} ); }; /** - * [ToolbarMenu](https://brightlayer-ui-components.github.io/react/?path=/info/components-three-liner--get-read-me-story) component + * [ToolbarMenu](https://brightlayer-ui-components.github.io/react/?path=/info/components-toolbar-menu--get-read-me-story) component * * The `ToolbarMenu` used to display a dropdown menu with label. */ diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 816570ae9..f4426f81c 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,9 +14,7 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : ( - undefined - ); + ) : undefined; const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); diff --git a/demos/storybook/stories/toolbar-menu/_module.stories.tsx b/demos/storybook/stories/toolbar-menu/_module.stories.tsx index c9c106474..9a91e5b55 100644 --- a/demos/storybook/stories/toolbar-menu/_module.stories.tsx +++ b/demos/storybook/stories/toolbar-menu/_module.stories.tsx @@ -15,5 +15,6 @@ const toolbarMenuModule = { export { getReadMeStory } from '../../src/utils'; export { withBasicUsage } from './with-basic-usage'; export { iconWithLabel } from './icon-with-label'; -export { withMenu } from './with-menu'; +export { withAppBar } from './with-app-bar'; +export { withBluiAppBar } from './with-blui-app-bar'; export default toolbarMenuModule; diff --git a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx index afc2348a3..6257f6259 100644 --- a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx +++ b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx @@ -1,18 +1,58 @@ import React from 'react'; import { GradeA } from '@brightlayer-ui/icons-mui'; +import { makeStyles } from '@material-ui/core/styles'; +import createStyles from '@material-ui/core/styles/createStyles'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import { ToolbarMenu } from '@brightlayer-ui/react-components'; -import { typography } from '@storybook/theming'; +import { Theme } from '@material-ui/core/styles/createMuiTheme'; +import useTheme from '@material-ui/core/styles/useTheme'; +import { action } from '@storybook/addon-actions'; +import { text } from '@storybook/addon-knobs'; +import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; +import clsx from 'clsx'; +const menuItems = [ + { title: 'Item 1', onClick: action('Item 1 selected') }, + { title: 'Item 2', onClick: action('Item 2 selected') }, + { title: 'Item 3', onClick: action('Item 3 selected') }, +]; + +const menuGroups = [ + { + items: menuItems, + }, +]; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + labelContent: { + '& > span': { + display: 'flex', + }, + }, + iconMarginRight: { + marginRight: `${theme.spacing(1)}px`, + }, + iconMarginLeft: { + marginLeft: `${theme.spacing(1)}px`, + }, + }) +); export const iconWithLabel = (): StoryFnReactReturnType => { + const theme = useTheme(); + const classes = useStyles(theme); + const label = text('label', 'Subtitle'); + const direction = getDirection(); return ( - - Dropdown Toolbar + + {label} } + menuGroups={menuGroups} /> ); }; diff --git a/demos/storybook/stories/toolbar-menu/with-menu.tsx b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx similarity index 53% rename from demos/storybook/stories/toolbar-menu/with-menu.tsx rename to demos/storybook/stories/toolbar-menu/with-app-bar.tsx index d47491154..3f875c4ad 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu.tsx +++ b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { GradeA } from '@brightlayer-ui/icons-mui'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import { ToolbarMenu } from '@brightlayer-ui/react-components'; import Toolbar from '@material-ui/core/Toolbar'; @@ -8,8 +7,9 @@ import ListItemText from '@material-ui/core/ListItemText'; import Typography from '@material-ui/core/Typography'; import { action } from '@storybook/addon-actions'; import makeStyles from '@material-ui/core/styles/makeStyles'; -import clsx from 'clsx'; -export const withMenu = (): StoryFnReactReturnType => { +import * as Colors from '@brightlayer-ui/colors'; +import { text } from '@storybook/addon-knobs'; +export const withAppBar = (): StoryFnReactReturnType => { const menuItems = [ { title: 'Item 1', onClick: action('Item 1 selected') }, { title: 'Item 2', onClick: action('Item 2 selected') }, @@ -35,52 +35,28 @@ export const withMenu = (): StoryFnReactReturnType => { }, }, root: { - color: 'white', - } + color: Colors.white[500], + }, }); const classes = useStyles(); return ( - {/* - - Title - - } - secondary={ - - - Dropdown Toolbar - - } - menuGroups={menuGroups} - > - } - /> - */} - - {/* {getNavigationIcon()} */} + - Title - - } + primary={Title} secondary={ - + } /> - {/* {props.children} */} ); }; -withMenu.story = { name: 'with menu' }; +withAppBar.story = { name: 'with app bar' }; diff --git a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx index 0f0cf0a07..ed5dff08b 100644 --- a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx +++ b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx @@ -3,11 +3,22 @@ import { text } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import { WITH_MIN_PROPS_STORY_NAME } from '../../src/constants'; import { ToolbarMenu } from '@brightlayer-ui/react-components'; +import { action } from '@storybook/addon-actions'; +const menuItems = [ + { title: 'Item 1', onClick: action('Item 1 selected') }, + { title: 'Item 2', onClick: action('Item 2 selected') }, + { title: 'Item 3', onClick: action('Item 3 selected') }, +]; + +const menuGroups = [ + { + items: menuItems, + }, +]; export const withBasicUsage = (): StoryFnReactReturnType => { const label = text('label', 'label'); - - return ; + return ; }; withBasicUsage.story = { name: WITH_MIN_PROPS_STORY_NAME }; diff --git a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx new file mode 100644 index 000000000..8f521de2f --- /dev/null +++ b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx @@ -0,0 +1,137 @@ +import React from 'react'; +import { boolean, number, select, text } from '@storybook/addon-knobs'; +import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; +import { AppBar, Spacer, ThreeLiner, ToolbarMenu } from '@brightlayer-ui/react-components'; +import bgImage from '../../assets/farm.jpg'; +import { Menu, Work, Settings, Home } from '@material-ui/icons'; +import { IconButton, makeStyles, Toolbar } from '@material-ui/core'; +import { action } from '@storybook/addon-actions'; +import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; +import clsx from 'clsx'; +import * as Colors from '@brightlayer-ui/colors'; +import { getBodyFiller } from '../../src/utils'; +const menuItems = [ + { title: 'Item 1', onClick: action('Item 1 selected') }, + { title: 'Item 2', onClick: action('Item 2 selected') }, + { title: 'Item 3', onClick: action('Item 3 selected') }, +]; + +const menuGroups = [ + { + items: menuItems, + }, +]; + +const useStyles = makeStyles(() => ({ + title: {}, + subtitle: {}, + info: {}, + liner: { + top: 0, + position: 'absolute', + flexGrow: 1, + marginLeft: 56, + }, + linerRTL: { + marginLeft: 0, + marginRight: 56, + }, + expanded: { + '& $liner': { + top: 64, + }, + }, + collapsed: { + '& $title': { + fontSize: '1.25rem', + fontWeight: 600, + }, + '& $subtitle': { + display: 'none', + }, + '& $info': { + fontSize: '1rem', + fontWeight: 400, + marginTop: '-0.25rem', + }, + }, + toolbarGutters: { + paddingLeft: 16, + paddingRight: 4, + }, + toolbarGuttersRTL: { + paddingLeft: 4, + paddingRight: 16, + }, + toolbarMenuRoot: { + color: Colors.white[500], + }, +})); + +export const withBluiAppBar = (): StoryFnReactReturnType => { + const classes = useStyles(); + const direction = getDirection(); + const appBarGroupId = 'AppBar'; + const threeLinerGroupId = 'ThreeLiner'; + // AppBar props + const animationDuration = number('animationDuration', 300, {}, appBarGroupId); + const showBackgroundImage = boolean('show backgroundImage', true, appBarGroupId); + const collapsedHeight = number('collapsedHeight', 64, {}, appBarGroupId); + const expandedHeight = number('expandedHeight', 200, {}, appBarGroupId); + const scrollThreshold = number('scrollThreshold', 136, {}, appBarGroupId); + const variant = select('variant', ['snap', 'collapsed', 'expanded'], 'snap', appBarGroupId); + // ThreeLiner props + const title = text('title', 'title', threeLinerGroupId); + const info = text('info', 'info', threeLinerGroupId); + + return ( + <> + + + + + + + + } + info={info} + animationDuration={animationDuration} + /> +
+ + + + + + + + + +
+ + +
{getBodyFiller()}
+ + ); +}; + +withBluiAppBar.story = { name: 'with blui app bar' }; diff --git a/docs/ToolbarMenu.md b/docs/ToolbarMenu.md index df8358e36..a0b8da844 100644 --- a/docs/ToolbarMenu.md +++ b/docs/ToolbarMenu.md @@ -1,27 +1,79 @@ -# Three Liner +# Toolbar Menu -The `ThreeLiner` can display up to three lines of stylized text or other custom content. It is most commonly used within the context of a [`AppBar`](./AppBar.md) component where the text can grow / shrink as the App Bar is expanded and collapsed. +The `ToolbarMenu` component is used to display a dropdown menu with label. The Menu can be populated via the `menuGroups` prop, or can be entirely customized by supplying your own `` via the `menu` prop. + +## Usage + +
+ Toolbar Menu +
+ +```tsx +import { ToolbarMenu } from '@brightlayer-ui/react-components'; +... +const useStyles = makeStyles((theme: Theme) => + createStyles({ + labelContent: { + '& > span': { + display: 'flex', + } + }, + icon: { + marginRight: `${theme.spacing(1)}px`, + }, + }) +); + + + + Subtitle + + } + menuGroups={[ + { + items: [{ + title: "Menu Item 1"; + onClick: () => {}; + }, + { + title: "Menu Item 2"; + onClick: () => {}; + }, + { + title: "Menu Item 3"; + onClick: () => {}; + } + ] + } + ]} +/> +``` ## API
-| Prop Name | Description | Type | Required | Default | -| ----------------- | ------------------------------------------------- | ------------------- | -------- | ------------------------------------- | -| animationDuration | Time in milliseconds to transition between states | `number` | no | `theme.transitions.duration.standard` | -| classes | Style overrides | `ThreeLinerClasses` | no | | -| info | Third line content | `ReactNode` | no | | -| title | First line content | `ReactNode` | no | | -| subtitle | Second line content | `ReactNode` | no | | +| Prop Name | Description | Type | Required | Default | +| -------------- | -------------------------------------------- | --------------------- | -------- | ------- | +| classes | Style Overrides | `ToolbarMenuClasses` | no | | +| menu | Custom content to be displayed in the menu | Material-UI `Menu` | no | | +| menuGroups | Groups of menu items to display | `ToolbarMenuGroups[]` | no | | +| MenuProps | Property overrides for the MUI Menu | `MenuProps` | no | | +| navigationIcon | Navigation Icon to be displayed | `JSX.Element` | no | | +| onClose | Function called when the menu is closed | `Function` | no | | +| onOpen | Function called when the menu is opened | `Function` | no | | +| label | Custom content for label text / icon + label | `ReactNode` | yes | |
### Classes You can override the classes used by Brightlayer UI by passing a `classes` prop. It supports the following keys: -| Name | Description | -| -------- | ---------------------------------- | -| root | Styles applied to the root element | -| title | Styles applied to the first line | -| subtitle | Styles applied to the second line | -| info | Styles applied to the third line | +| Name | Description | +| ------------- | --------------------------------------------- | +| root | Styles applied to the root element | +| label | Styles applied to the label text | +| dropdownArrow | Styles applied to the dropdownArrow container | +| menuItem | Styles applied to the menuItem | diff --git a/docs/images/ToolbarMenuAnatomy.png b/docs/images/ToolbarMenuAnatomy.png new file mode 100644 index 0000000000000000000000000000000000000000..081860962af887d4f9403d5d0f732a730a6a8947 GIT binary patch literal 55606 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 Jc{2B({~w$+7Iy#u literal 0 HcmV?d00001 From a9ce817709c8615816b579e6c2b73ca89438ed51 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 24 Jan 2022 13:47:28 +0530 Subject: [PATCH 48/72] fix prettier --- demos/storybook/stories/channel-value/with-full-config.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 4748c1323..603719147 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,7 +14,9 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : undefined; + ) : ( + undefined + ); const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); From 7808b17540d755300a33035559b6fed444952f6c Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 24 Jan 2022 15:31:24 +0530 Subject: [PATCH 49/72] test cases --- .../src/core/ToolbarMenu/ToolbarMenu.test.tsx | 51 ++++++++ .../src/core/ToolbarMenu/ToolbarMenu.tsx | 59 ++++++---- .../stories/toolbar-menu/_module.stories.tsx | 1 + .../stories/toolbar-menu/icon-with-label.tsx | 12 +- .../stories/toolbar-menu/with-app-bar.tsx | 18 ++- .../stories/toolbar-menu/with-basic-usage.tsx | 6 +- .../toolbar-menu/with-blui-app-bar.tsx | 1 + .../with-menu-placement-options.tsx | 110 ++++++++++++++++++ 8 files changed, 214 insertions(+), 44 deletions(-) create mode 100644 components/src/core/ToolbarMenu/ToolbarMenu.test.tsx create mode 100644 demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx new file mode 100644 index 000000000..b84bc30cb --- /dev/null +++ b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import * as ReactDOM from 'react-dom'; +import * as Enzyme from 'enzyme'; +import { Mount } from '../types'; +import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; +import { ToolbarMenu } from './ToolbarMenu'; +import Typography from '@material-ui/core/Typography'; +import { act } from 'react-dom/test-utils'; +import { createMount } from '@material-ui/core/test-utils'; + +Enzyme.configure({ adapter: new Adapter() }); +let mount: Mount; + +describe('ToolbarMenu', () => { + beforeEach(() => { + mount = createMount({ strict: true }); + }); + + afterEach(() => { + mount.cleanUp(); + }); + it('should render without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + }); + + it('should render correct label', () => { + const toolbar = Enzyme.mount(); + const typography = toolbar.find(Typography); + expect(typography.length).toEqual(1); + }); + + it('should open menu when label is clicked', () => { + const menuItems = [{ title: 'Item 1', onClick: (): void => {}, itemID: 'item1' }]; + const menuGroups = [ + { + items: menuItems, + }, + ]; + const onOpen = jest.fn(); + const toolbar = Enzyme.mount(); + const typography = toolbar.find(Typography); + expect(typography.length).toEqual(1); + const labelWithDropdownArrow = typography.get(0); + expect(onOpen).not.toHaveBeenCalled(); + act(() => { + labelWithDropdownArrow.props.onClick(); + }); + expect(onOpen).toHaveBeenCalled(); + }); +}); diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 6f76ede40..c635d059d 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -1,17 +1,19 @@ import React, { HTMLAttributes, ReactNode, useState, useCallback, useRef, useEffect } from 'react'; -import { Theme } from '@material-ui/core/styles/createMuiTheme'; -import createStyles from '@material-ui/core/styles/createStyles'; -import makeStyles from '@material-ui/core/styles/makeStyles'; import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; import clsx from 'clsx'; +import createStyles from '@material-ui/core/styles/createStyles'; import { DrawerNavGroup, NavItem } from '../Drawer'; +import makeStyles from '@material-ui/core/styles/makeStyles'; import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; -import { Typography, useTheme } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import { Theme } from '@material-ui/core/styles/createMuiTheme'; +import useTheme from '@material-ui/core/styles/useTheme'; export type ToolbarMenuClasses = { root?: string; - label?: string; dropdownArrow?: string; + label?: string; + labelContent?: string; menuItem?: string; }; @@ -29,28 +31,31 @@ export type ToolbarMenuGroup1 = { const useStyles = makeStyles((theme: Theme) => createStyles({ - root: { - display: 'flex', + cursorPointer: { cursor: 'pointer', }, + dropdownArrow: { + marginLeft: theme.spacing(0.5), + }, + label: { + textOverflow: 'ellipsis', + overflow: 'hidden', + }, + labelContent: { + display: 'inline-flex', + }, navGroups: { '&:active, &:focus': { outline: 'none', }, }, - cursorPointer: { + root: { + display: 'flex', cursor: 'pointer', }, - dropdownArrow: { - marginLeft: theme.spacing(0.5), - }, rotateDropdownArrow: { transform: 'rotate(180deg)', }, - label: { - textOverflow: 'ellipsis', - overflow: 'hidden', - }, }) ); @@ -71,8 +76,11 @@ export type ToolbarMenuProps = HTMLAttributes & { classes?: Partial; }; -const ToolbarMenuRenderer: React.ForwardRefRenderFunction = (props: ToolbarMenuProps) => { - const { label, classes = {}, menuGroups, menu, MenuProps, onClose, onOpen } = props; +const ToolbarMenuRenderer: React.ForwardRefRenderFunction = ( + props: ToolbarMenuProps, + ref: any +) => { + const { label, classes = {}, menuGroups, menu, MenuProps, onClose, onOpen, ...otherSpanProps } = props; const theme = useTheme(); const rtl = theme.direction === 'rtl'; const defaultClasses = useStyles(props); @@ -155,19 +163,20 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction + { openMenu(anchor.current); }} + component={'span'} + className={clsx(defaultClasses.labelContent, classes.labelContent)} > {label || ''} {(menuGroups || menu) && ( @@ -181,7 +190,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction {getMenu()} - + ); }; /** diff --git a/demos/storybook/stories/toolbar-menu/_module.stories.tsx b/demos/storybook/stories/toolbar-menu/_module.stories.tsx index 9a91e5b55..e37959ea5 100644 --- a/demos/storybook/stories/toolbar-menu/_module.stories.tsx +++ b/demos/storybook/stories/toolbar-menu/_module.stories.tsx @@ -17,4 +17,5 @@ export { withBasicUsage } from './with-basic-usage'; export { iconWithLabel } from './icon-with-label'; export { withAppBar } from './with-app-bar'; export { withBluiAppBar } from './with-blui-app-bar'; +export { withMenuPlacementOptions } from './with-menu-placement-options'; export default toolbarMenuModule; diff --git a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx index 6257f6259..f6d9ba9a7 100644 --- a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx +++ b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx @@ -1,15 +1,15 @@ import React from 'react'; +import { action } from '@storybook/addon-actions'; import { GradeA } from '@brightlayer-ui/icons-mui'; -import { makeStyles } from '@material-ui/core/styles'; +import clsx from 'clsx'; import createStyles from '@material-ui/core/styles/createStyles'; +import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; +import makeStyles from '@material-ui/core/styles/makeStyles'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; -import { ToolbarMenu } from '@brightlayer-ui/react-components'; +import { text } from '@storybook/addon-knobs'; import { Theme } from '@material-ui/core/styles/createMuiTheme'; +import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; import useTheme from '@material-ui/core/styles/useTheme'; -import { action } from '@storybook/addon-actions'; -import { text } from '@storybook/addon-knobs'; -import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; -import clsx from 'clsx'; const menuItems = [ { title: 'Item 1', onClick: action('Item 1 selected') }, diff --git a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx index 3f875c4ad..d183f2891 100644 --- a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx @@ -1,14 +1,15 @@ import React from 'react'; -import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; -import { ToolbarMenu } from '@brightlayer-ui/react-components'; -import Toolbar from '@material-ui/core/Toolbar'; +import { action } from '@storybook/addon-actions'; import AppBar from '@material-ui/core/AppBar'; +import * as Colors from '@brightlayer-ui/colors'; import ListItemText from '@material-ui/core/ListItemText'; -import Typography from '@material-ui/core/Typography'; -import { action } from '@storybook/addon-actions'; import makeStyles from '@material-ui/core/styles/makeStyles'; -import * as Colors from '@brightlayer-ui/colors'; +import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import { text } from '@storybook/addon-knobs'; +import Toolbar from '@material-ui/core/Toolbar'; +import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; +import Typography from '@material-ui/core/Typography'; + export const withAppBar = (): StoryFnReactReturnType => { const menuItems = [ { title: 'Item 1', onClick: action('Item 1 selected') }, @@ -22,9 +23,6 @@ export const withAppBar = (): StoryFnReactReturnType => { }, ]; const useStyles = makeStyles({ - labelContent: { - display: 'flex', - }, textContent: { overflow: 'hidden', whiteSpace: 'nowrap', @@ -51,7 +49,7 @@ export const withAppBar = (): StoryFnReactReturnType => { classes={{ root: classes.root }} label={text('label', text('label', 'Subtitle'))} menuGroups={menuGroups} - > + /> } /> diff --git a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx index ed5dff08b..0c5063f09 100644 --- a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx +++ b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import { text } from '@storybook/addon-knobs'; +import { action } from '@storybook/addon-actions'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; +import { text } from '@storybook/addon-knobs'; +import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; import { WITH_MIN_PROPS_STORY_NAME } from '../../src/constants'; -import { ToolbarMenu } from '@brightlayer-ui/react-components'; -import { action } from '@storybook/addon-actions'; const menuItems = [ { title: 'Item 1', onClick: action('Item 1 selected') }, diff --git a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx index 8f521de2f..c3c76e320 100644 --- a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx @@ -10,6 +10,7 @@ import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; import clsx from 'clsx'; import * as Colors from '@brightlayer-ui/colors'; import { getBodyFiller } from '../../src/utils'; + const menuItems = [ { title: 'Item 1', onClick: action('Item 1 selected') }, { title: 'Item 2', onClick: action('Item 2 selected') }, diff --git a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx new file mode 100644 index 000000000..623bc3895 --- /dev/null +++ b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx @@ -0,0 +1,110 @@ +import { ToolbarMenu } from '@brightlayer-ui/react-components'; +import { action } from '@storybook/addon-actions'; +import { select } from '@storybook/addon-knobs'; +import { text } from '@storybook/addon-knobs'; +import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; +import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; +import React from 'react'; +import AppBar from '@material-ui/core/AppBar'; +import Toolbar from '@material-ui/core/Toolbar'; +import ListItemText from '@material-ui/core/ListItemText'; +import Typography from '@material-ui/core/Typography'; +import makeStyles from '@material-ui/core/styles/makeStyles'; +import * as Colors from '@brightlayer-ui/colors'; +import createStyles from '@material-ui/core/styles/createStyles'; +import { Theme } from '@material-ui/core/styles/createMuiTheme'; +import { GradeA } from '@brightlayer-ui/icons-mui'; +import clsx from 'clsx'; + +export const withMenuPlacementOptions = (): StoryFnReactReturnType => { + const anchorOriginHorizontal = select( + 'menuProps.anchorOrigin.horizontal', + ['left', 'center', 'right'], + 'left', + 'Menu' + ); + const anchorOriginVertical = select('menuProps.anchorOrigin.vertical', ['top', 'center', 'bottom'], 'top', 'Menu'); + const transformOriginHorizontal = select( + 'menuProps.transformOrigin.horizontal', + ['left', 'center', 'right'], + 'left', + 'Menu' + ); + const transformOriginVertical = select( + 'menuProps.transformOrigin.vertical', + ['top', 'center', 'bottom'], + 'top', + 'Menu' + ); + + const menuItems = [ + { title: 'Item 1', onClick: action('Item 1 selected') }, + { title: 'Item 2', onClick: action('Item 2 selected') }, + { title: 'Item 3', onClick: action('Item 3 selected') }, + ]; + + const menuGroups = [ + { + items: menuItems, + }, + ]; + const useStyles = makeStyles((theme: Theme) => + createStyles({ + labelContent: { + '& > span': { + display: 'flex', + }, + }, + iconMarginRight: { + marginRight: `${theme.spacing(1)}px`, + }, + iconMarginLeft: { + marginLeft: `${theme.spacing(1)}px`, + }, + textContent: { + overflow: 'hidden', + whiteSpace: 'nowrap', + // set margins to default to avoid the height of the app bar exceeding 56px on mobile + '&.MuiListItemText-multiline': { + marginTop: '0.25rem', + marginBottom: '0.25rem', + }, + }, + root: { + color: Colors.white[500], + }, + }) + ); + + const classes = useStyles(); + const label = text('label', 'Subtitle'); + const direction = getDirection(); + return ( + + + Title} + secondary={ + + + {label} + + } + menuGroups={menuGroups} + MenuProps={{ + anchorOrigin: { horizontal: anchorOriginHorizontal, vertical: anchorOriginVertical }, + transformOrigin: { horizontal: transformOriginHorizontal, vertical: transformOriginVertical }, + }} + > + } + /> + + + ); +}; + +withMenuPlacementOptions.story = { name: 'with menu placement options' }; From c2ad4b995898d034c5f9b1fea1ea1586db857333 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 24 Jan 2022 15:38:01 +0530 Subject: [PATCH 50/72] fix prettier --- .../stories/toolbar-menu/icon-with-label.tsx | 6 +++--- .../toolbar-menu/with-menu-placement-options.tsx | 13 ++++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx index f6d9ba9a7..d5fb517c2 100644 --- a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx +++ b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx @@ -12,9 +12,9 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; import useTheme from '@material-ui/core/styles/useTheme'; const menuItems = [ - { title: 'Item 1', onClick: action('Item 1 selected') }, - { title: 'Item 2', onClick: action('Item 2 selected') }, - { title: 'Item 3', onClick: action('Item 3 selected') }, + { title: 'Menu Item 1', onClick: action('Item 1 selected') }, + { title: 'Menu Item 2', onClick: action('Item 2 selected') }, + { title: 'Menu Item 3', onClick: action('Item 3 selected') }, ]; const menuGroups = [ diff --git a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx index 623bc3895..9d62d1e8e 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx +++ b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx @@ -87,17 +87,24 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { primary={Title} secondary={ - + {label} } menuGroups={menuGroups} MenuProps={{ anchorOrigin: { horizontal: anchorOriginHorizontal, vertical: anchorOriginVertical }, - transformOrigin: { horizontal: transformOriginHorizontal, vertical: transformOriginVertical }, + transformOrigin: { + horizontal: transformOriginHorizontal, + vertical: transformOriginVertical, + }, }} > } From 15063cdf7de891368ffb60d17cbe20ea060b0115 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 24 Jan 2022 15:47:08 +0530 Subject: [PATCH 51/72] fix prettier --- demos/storybook/stories/toolbar-menu/with-app-bar.tsx | 3 ++- demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx | 3 ++- .../stories/toolbar-menu/with-menu-placement-options.tsx | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx index d183f2891..56696f7a0 100644 --- a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx @@ -33,7 +33,8 @@ export const withAppBar = (): StoryFnReactReturnType => { }, }, root: { - color: Colors.white[500], + color: Colors.white[50], + marginTop: '-0.125rem', }, }); diff --git a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx index c3c76e320..fd44bf0f1 100644 --- a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx @@ -65,7 +65,8 @@ const useStyles = makeStyles(() => ({ paddingRight: 16, }, toolbarMenuRoot: { - color: Colors.white[500], + color: Colors.white[50], + marginTop: '-0.125rem', }, })); diff --git a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx index 9d62d1e8e..366b49d9b 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx +++ b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx @@ -1,7 +1,6 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components'; import { action } from '@storybook/addon-actions'; -import { select } from '@storybook/addon-knobs'; -import { text } from '@storybook/addon-knobs'; +import { select, text } from '@storybook/addon-knobs'; import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import React from 'react'; From d60ffd189fa6bfbb402dd3babaebcbcad58a7970 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 24 Jan 2022 18:25:02 +0530 Subject: [PATCH 52/72] update readme --- docs/ToolbarMenu.md | 90 +++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/docs/ToolbarMenu.md b/docs/ToolbarMenu.md index a0b8da844..773fe952c 100644 --- a/docs/ToolbarMenu.md +++ b/docs/ToolbarMenu.md @@ -1,6 +1,6 @@ # Toolbar Menu -The `ToolbarMenu` component is used to display a dropdown menu with label. The Menu can be populated via the `menuGroups` prop, or can be entirely customized by supplying your own `` via the `menu` prop. +The `ToolbarMenu` component is used to display a dropdown menu with label, primarily inside of `` or Card Header elements. The Menu can be populated via the `menuGroups` prop, or can be entirely customized by supplying your own `` via the `menu` prop. ## Usage @@ -11,26 +11,8 @@ The `ToolbarMenu` component is used to display a dropdown menu with label. The M ```tsx import { ToolbarMenu } from '@brightlayer-ui/react-components'; ... -const useStyles = makeStyles((theme: Theme) => - createStyles({ - labelContent: { - '& > span': { - display: 'flex', - } - }, - icon: { - marginRight: `${theme.spacing(1)}px`, - }, - }) -); - - - Subtitle - - } + label={'label'} menuGroups={[ { items: [{ @@ -41,10 +23,6 @@ const useStyles = makeStyles((theme: Theme) => title: "Menu Item 2"; onClick: () => {}; }, - { - title: "Menu Item 3"; - onClick: () => {}; - } ] } ]} @@ -55,25 +33,57 @@ const useStyles = makeStyles((theme: Theme) =>
-| Prop Name | Description | Type | Required | Default | -| -------------- | -------------------------------------------- | --------------------- | -------- | ------- | -| classes | Style Overrides | `ToolbarMenuClasses` | no | | -| menu | Custom content to be displayed in the menu | Material-UI `Menu` | no | | -| menuGroups | Groups of menu items to display | `ToolbarMenuGroups[]` | no | | -| MenuProps | Property overrides for the MUI Menu | `MenuProps` | no | | -| navigationIcon | Navigation Icon to be displayed | `JSX.Element` | no | | -| onClose | Function called when the menu is closed | `Function` | no | | -| onOpen | Function called when the menu is opened | `Function` | no | | -| label | Custom content for label text / icon + label | `ReactNode` | yes | | +| Prop Name | Description | Type | Required | Default | +| ---------- | -------------------------------------------- | --------------------- | -------- | ------- | +| classes | Style Overrides | `ToolbarMenuClasses` | no | | +| label | Custom content for label text / icon + label | `ReactNode` | yes | | +| menu | Custom content to be displayed in the menu | Material-UI `Menu` | no | | +| menuGroups | Groups of menu items to display | `ToolbarMenuGroups[]` | no | | +| MenuProps | Property overrides for the MUI Menu | `MenuProps` | no | | +| onClose | Function called when the menu is closed | `Function` | no | | +| onOpen | Function called when the menu is opened | `Function` | no | |
+ ### Classes You can override the classes used by Brightlayer UI by passing a `classes` prop. It supports the following keys: -| Name | Description | -| ------------- | --------------------------------------------- | -| root | Styles applied to the root element | -| label | Styles applied to the label text | -| dropdownArrow | Styles applied to the dropdownArrow container | -| menuItem | Styles applied to the menuItem | +| Name | Description | +| ------------- | ---------------------------------------------------- | +| dropdownArrow | Styles applied to the dropdownArrow container | +| label | Styles applied to the label / icon + label text | +| labelContent | Styles applied to the label / icon + label container | +| menuItem | Styles applied to the menu item | +| root | Styles applied to the root element | + +### Toolbar Menu Groups Object + +The `menuGroups` prop of the `` includes many properties from the [``](https://brightlayer-ui-components.github.io/react/?path=/info/components-drawer--get-read-me-story) array found within a [``](https://brightlayer-ui-components.github.io/react/?path=/info/components-drawer--get-read-me-story). + +
+ +| Prop Name | Description | Type | Required | Default | +| --------- | ----------------------------------- | ------------------- | -------- | ------- | +| fontColor | The color used for the text | `string` | no | | +| iconColor | The color used for icons | `string` | no | | +| items | List of navigation items to render | `ToolbarMenuItem[]` | yes | | +| title | Text to display in the group header | `string` | no | | + +
+ +### Toolbar Menu Item Object + +
+ +| Attribute | Description | Type | Required | Default | +| ----------- | ----------------------------------- | ------------- | -------- | ------- | +| chevron | Show chevron icon to the right | `boolean` | no | false | +| divider | Show a divider line below the item | `boolean` | no | | +| icon | A component to render for the icon | `JSX.Element` | no | | +| onClick | A function to execute when clicked | `function` | no | | +| statusColor | Status stripe and icon color | `string` | no | | +| subtitle | The text to show on the second line | `string` | no | | +| title | The text to show on the first line | `string` | yes | | + +
From ad56760dde7ca044822f30753c6af98d704eefd9 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 25 Jan 2022 12:15:03 +0530 Subject: [PATCH 53/72] add color, icon prop --- .../src/core/ToolbarMenu/ToolbarMenu.tsx | 97 +++++++++++++++++-- .../stories/toolbar-menu/icon-with-label.tsx | 44 ++------- .../stories/toolbar-menu/with-app-bar.tsx | 8 +- .../stories/toolbar-menu/with-basic-usage.tsx | 6 +- .../toolbar-menu/with-blui-app-bar.tsx | 11 ++- .../with-menu-placement-options.tsx | 36 +------ docs/ToolbarMenu.md | 22 +++-- 7 files changed, 128 insertions(+), 96 deletions(-) diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index c635d059d..1131b52dc 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -8,10 +8,12 @@ import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; import Typography from '@material-ui/core/Typography'; import { Theme } from '@material-ui/core/styles/createMuiTheme'; import useTheme from '@material-ui/core/styles/useTheme'; +import PropTypes from 'prop-types'; export type ToolbarMenuClasses = { root?: string; dropdownArrow?: string; + icon?: string; label?: string; labelContent?: string; menuItem?: string; @@ -31,28 +33,33 @@ export type ToolbarMenuGroup1 = { const useStyles = makeStyles((theme: Theme) => createStyles({ + root: { + cursor: 'pointer', + color: (props: ToolbarMenuProps): string => props.color, + }, cursorPointer: { cursor: 'pointer', }, dropdownArrow: { marginLeft: theme.spacing(0.5), }, + icon: { + marginRight: `${theme.spacing(1)}px`, + display: 'inline-flex', + fontSize: 'inherit', + }, label: { textOverflow: 'ellipsis', overflow: 'hidden', }, labelContent: { - display: 'inline-flex', + display: 'flex', }, navGroups: { '&:active, &:focus': { outline: 'none', }, }, - root: { - display: 'flex', - cursor: 'pointer', - }, rotateDropdownArrow: { transform: 'rotate(180deg)', }, @@ -60,6 +67,13 @@ const useStyles = makeStyles((theme: Theme) => ); export type ToolbarMenuProps = HTMLAttributes & { + /** The color used for the text elements + * + * Default: 'inherit' + */ + color?: string; + /** A component to render for the icon */ + icon?: JSX.Element; /** Label Content */ label: ReactNode; /** Custom content to be displayed in the menu */ @@ -80,7 +94,19 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { - const { label, classes = {}, menuGroups, menu, MenuProps, onClose, onOpen, ...otherSpanProps } = props; + const { + classes = {}, + /* eslint-disable @typescript-eslint/no-unused-vars */ + color, + icon, + label, + menuGroups, + menu, + MenuProps, + onClose, + onOpen, + ...otherSpanProps + } = props; const theme = useTheme(); const rtl = theme.direction === 'rtl'; const defaultClasses = useStyles(props); @@ -172,15 +198,24 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { openMenu(anchor.current); }} - component={'span'} - className={clsx(defaultClasses.labelContent, classes.labelContent)} > - {label || ''} + {icon && ( + + {icon} + + )} + + {label || ''} + {(menuGroups || menu) && ( {}, + onOpen: (): void => {}, +}; diff --git a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx index d5fb517c2..4e82e3f7c 100644 --- a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx +++ b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx @@ -1,15 +1,10 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; +import { color, text } from '@storybook/addon-knobs'; import { GradeA } from '@brightlayer-ui/icons-mui'; -import clsx from 'clsx'; -import createStyles from '@material-ui/core/styles/createStyles'; -import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; -import makeStyles from '@material-ui/core/styles/makeStyles'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; -import { text } from '@storybook/addon-knobs'; -import { Theme } from '@material-ui/core/styles/createMuiTheme'; import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; -import useTheme from '@material-ui/core/styles/useTheme'; +import * as Colors from '@brightlayer-ui/colors'; const menuItems = [ { title: 'Menu Item 1', onClick: action('Item 1 selected') }, @@ -23,38 +18,13 @@ const menuGroups = [ }, ]; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - labelContent: { - '& > span': { - display: 'flex', - }, - }, - iconMarginRight: { - marginRight: `${theme.spacing(1)}px`, - }, - iconMarginLeft: { - marginLeft: `${theme.spacing(1)}px`, - }, - }) -); export const iconWithLabel = (): StoryFnReactReturnType => { - const theme = useTheme(); - const classes = useStyles(theme); const label = text('label', 'Subtitle'); - const direction = getDirection(); - return ( - - - {label} - - } - menuGroups={menuGroups} - /> - ); + const textColor = color('color', Colors.black[500]); + const iconColor = color('icon.htmlColor', Colors.green[500]); + const icon = ; + + return ; }; iconWithLabel.story = { name: 'icon with label' }; diff --git a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx index 56696f7a0..bda4c23f8 100644 --- a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx @@ -1,14 +1,15 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; import AppBar from '@material-ui/core/AppBar'; -import * as Colors from '@brightlayer-ui/colors'; +import { color, text } from '@storybook/addon-knobs'; import ListItemText from '@material-ui/core/ListItemText'; import makeStyles from '@material-ui/core/styles/makeStyles'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; -import { text } from '@storybook/addon-knobs'; + import Toolbar from '@material-ui/core/Toolbar'; import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; import Typography from '@material-ui/core/Typography'; +import * as Colors from '@brightlayer-ui/colors'; export const withAppBar = (): StoryFnReactReturnType => { const menuItems = [ @@ -33,7 +34,7 @@ export const withAppBar = (): StoryFnReactReturnType => { }, }, root: { - color: Colors.white[50], + // color: Colors.white[50], marginTop: '-0.125rem', }, }); @@ -47,6 +48,7 @@ export const withAppBar = (): StoryFnReactReturnType => { primary={Title} secondary={ { const label = text('label', 'label'); - return ; + const textColor = color('color', Colors.black[500]); + return ; }; withBasicUsage.story = { name: WITH_MIN_PROPS_STORY_NAME }; diff --git a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx index fd44bf0f1..b9f66eb24 100644 --- a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { boolean, number, select, text } from '@storybook/addon-knobs'; +import { boolean, color, number, select, text } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import { AppBar, Spacer, ThreeLiner, ToolbarMenu } from '@brightlayer-ui/react-components'; import bgImage from '../../assets/farm.jpg'; @@ -65,7 +65,6 @@ const useStyles = makeStyles(() => ({ paddingRight: 16, }, toolbarMenuRoot: { - color: Colors.white[50], marginTop: '-0.125rem', }, })); @@ -75,6 +74,7 @@ export const withBluiAppBar = (): StoryFnReactReturnType => { const direction = getDirection(); const appBarGroupId = 'AppBar'; const threeLinerGroupId = 'ThreeLiner'; + const toolbarMenuGroupId = 'ToolbarMenu'; // AppBar props const animationDuration = number('animationDuration', 300, {}, appBarGroupId); const showBackgroundImage = boolean('show backgroundImage', true, appBarGroupId); @@ -85,7 +85,9 @@ export const withBluiAppBar = (): StoryFnReactReturnType => { // ThreeLiner props const title = text('title', 'title', threeLinerGroupId); const info = text('info', 'info', threeLinerGroupId); - + // ToolbarMenu props + const toolbarColor = color('color', Colors.white[50], toolbarMenuGroupId); + const toolbarLabel = text('label', 'Subtitle', toolbarMenuGroupId); return ( <> { subtitle={ } diff --git a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx index 366b49d9b..d97f57e83 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx +++ b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx @@ -1,7 +1,6 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components'; import { action } from '@storybook/addon-actions'; -import { select, text } from '@storybook/addon-knobs'; -import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; +import { color, select, text } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import React from 'react'; import AppBar from '@material-ui/core/AppBar'; @@ -11,9 +10,7 @@ import Typography from '@material-ui/core/Typography'; import makeStyles from '@material-ui/core/styles/makeStyles'; import * as Colors from '@brightlayer-ui/colors'; import createStyles from '@material-ui/core/styles/createStyles'; -import { Theme } from '@material-ui/core/styles/createMuiTheme'; import { GradeA } from '@brightlayer-ui/icons-mui'; -import clsx from 'clsx'; export const withMenuPlacementOptions = (): StoryFnReactReturnType => { const anchorOriginHorizontal = select( @@ -47,19 +44,8 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { items: menuItems, }, ]; - const useStyles = makeStyles((theme: Theme) => + const useStyles = makeStyles(() => createStyles({ - labelContent: { - '& > span': { - display: 'flex', - }, - }, - iconMarginRight: { - marginRight: `${theme.spacing(1)}px`, - }, - iconMarginLeft: { - marginLeft: `${theme.spacing(1)}px`, - }, textContent: { overflow: 'hidden', whiteSpace: 'nowrap', @@ -69,15 +55,11 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { marginBottom: '0.25rem', }, }, - root: { - color: Colors.white[500], - }, }) ); const classes = useStyles(); const label = text('label', 'Subtitle'); - const direction = getDirection(); return ( @@ -86,17 +68,9 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { primary={Title} secondary={ - - {label} - - } + color={color('color', Colors.white[50])} + icon={} + label={label} menuGroups={menuGroups} MenuProps={{ anchorOrigin: { horizontal: anchorOriginHorizontal, vertical: anchorOriginVertical }, diff --git a/docs/ToolbarMenu.md b/docs/ToolbarMenu.md index 773fe952c..777089524 100644 --- a/docs/ToolbarMenu.md +++ b/docs/ToolbarMenu.md @@ -33,15 +33,17 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components';
-| Prop Name | Description | Type | Required | Default | -| ---------- | -------------------------------------------- | --------------------- | -------- | ------- | -| classes | Style Overrides | `ToolbarMenuClasses` | no | | -| label | Custom content for label text / icon + label | `ReactNode` | yes | | -| menu | Custom content to be displayed in the menu | Material-UI `Menu` | no | | -| menuGroups | Groups of menu items to display | `ToolbarMenuGroups[]` | no | | -| MenuProps | Property overrides for the MUI Menu | `MenuProps` | no | | -| onClose | Function called when the menu is closed | `Function` | no | | -| onOpen | Function called when the menu is opened | `Function` | no | | +| Prop Name | Description | Type | Required | Default | +| ---------- | -------------------------------------------- | --------------------- | -------- | --------- | +| classes | Style Overrides | `ToolbarMenuClasses` | no | | +| color | The color of the font | `string` | no | 'inherit' | +| icon | The inline icon to display | `JSX.Element` | no | | +| label | Custom content for label text / icon + label | `ReactNode` | yes | | +| menu | Custom content to be displayed in the menu | Material-UI `Menu` | no | | +| menuGroups | Groups of menu items to display | `ToolbarMenuGroups[]` | no | | +| MenuProps | Property overrides for the MUI Menu | `MenuProps` | no | | +| onClose | Function called when the menu is closed | `Function` | no | | +| onOpen | Function called when the menu is opened | `Function` | no | |
@@ -59,7 +61,7 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. ### Toolbar Menu Groups Object -The `menuGroups` prop of the `` includes many properties from the [``](https://brightlayer-ui-components.github.io/react/?path=/info/components-drawer--get-read-me-story) array found within a [``](https://brightlayer-ui-components.github.io/react/?path=/info/components-drawer--get-read-me-story). +The `menuGroups` prop of the `` includes many properties from the [``](https://brightlayer-ui-components.github.io/react/?path=/info/components-drawer--get-read-me-story) array found within a [``](https://brightlayer-ui-components.github.io/react/?path=/info/components-drawer--get-read-me-story).
From 05fd84add7f8478fb33962a4c2bd74fe5b1d4499 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 25 Jan 2022 12:17:23 +0530 Subject: [PATCH 54/72] fix prettier --- components/src/core/ToolbarMenu/ToolbarMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 1131b52dc..54f214c6d 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -94,7 +94,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { - const { + const { classes = {}, /* eslint-disable @typescript-eslint/no-unused-vars */ color, From 0be2698b4bfad81370eb51df675da23ce40d8fdd Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 25 Jan 2022 18:41:38 +0530 Subject: [PATCH 55/72] update deprecation warninga --- CHANGELOG.md | 2 +- components/src/core/DropdownToolbar/DropdownToolbar.tsx | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b21fda48c..b582c8c1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) - Added new property `unitSpace` to `` to manage spacing between the value and units. ([#350](https://github.com/brightlayer-ui/react-component-library/issues/350)) - Added `` component. ([#351](https://github.com/brightlayer-ui/react-component-library/issues/351)) - +- Added Deprecation warnings for DropdownToolbar component that will be removing in version 6.0.0. ## v5.3.3 (December 6, 2021) ### Fixed diff --git a/components/src/core/DropdownToolbar/DropdownToolbar.tsx b/components/src/core/DropdownToolbar/DropdownToolbar.tsx index 464a2dc38..938209f7b 100644 --- a/components/src/core/DropdownToolbar/DropdownToolbar.tsx +++ b/components/src/core/DropdownToolbar/DropdownToolbar.tsx @@ -159,6 +159,12 @@ const DropdownToolbarRender: React.ForwardRefRenderFunction { + console.warn( + `DropdwonToolbar component has been deprecated and will be removed in version 6.0.0. Instead of DropdwonToolbar use ToolbarMenu component in regular Toolbar like Mui Appbar, BLUI Appbar.` + ); + }); useEffect(() => { for (const group of menuGroups) { From 382bf492c46b95cb5d2452a04b683bbb5cdfee99 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 25 Jan 2022 20:05:12 +0530 Subject: [PATCH 56/72] fix prettier --- CHANGELOG.md | 1 + components/src/core/DropdownToolbar/DropdownToolbar.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b582c8c1c..79880bbde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Added new property `unitSpace` to `` to manage spacing between the value and units. ([#350](https://github.com/brightlayer-ui/react-component-library/issues/350)) - Added `` component. ([#351](https://github.com/brightlayer-ui/react-component-library/issues/351)) - Added Deprecation warnings for DropdownToolbar component that will be removing in version 6.0.0. + ## v5.3.3 (December 6, 2021) ### Fixed diff --git a/components/src/core/DropdownToolbar/DropdownToolbar.tsx b/components/src/core/DropdownToolbar/DropdownToolbar.tsx index 938209f7b..c7ac6201d 100644 --- a/components/src/core/DropdownToolbar/DropdownToolbar.tsx +++ b/components/src/core/DropdownToolbar/DropdownToolbar.tsx @@ -159,7 +159,7 @@ const DropdownToolbarRender: React.ForwardRefRenderFunction { console.warn( `DropdwonToolbar component has been deprecated and will be removed in version 6.0.0. Instead of DropdwonToolbar use ToolbarMenu component in regular Toolbar like Mui Appbar, BLUI Appbar.` From 5885c1908438a28e9439274ee5f86d1349c661fa Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 25 Jan 2022 21:01:56 +0530 Subject: [PATCH 57/72] fix lint --- components/src/core/DropdownToolbar/DropdownToolbar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/src/core/DropdownToolbar/DropdownToolbar.tsx b/components/src/core/DropdownToolbar/DropdownToolbar.tsx index c7ac6201d..6219e2b9c 100644 --- a/components/src/core/DropdownToolbar/DropdownToolbar.tsx +++ b/components/src/core/DropdownToolbar/DropdownToolbar.tsx @@ -161,6 +161,7 @@ const DropdownToolbarRender: React.ForwardRefRenderFunction { + // eslint-disable-next-line no-console console.warn( `DropdwonToolbar component has been deprecated and will be removed in version 6.0.0. Instead of DropdwonToolbar use ToolbarMenu component in regular Toolbar like Mui Appbar, BLUI Appbar.` ); From fa9310950cfc5a6ee3d78bc0b13daa90e7615d70 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Thu, 27 Jan 2022 11:27:42 +0530 Subject: [PATCH 58/72] fixed mobile view blui app bar --- .../storybook/stories/toolbar-menu/with-blui-app-bar.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx index b9f66eb24..33b56e7f1 100644 --- a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx @@ -4,7 +4,7 @@ import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/typ import { AppBar, Spacer, ThreeLiner, ToolbarMenu } from '@brightlayer-ui/react-components'; import bgImage from '../../assets/farm.jpg'; import { Menu, Work, Settings, Home } from '@material-ui/icons'; -import { IconButton, makeStyles, Toolbar } from '@material-ui/core'; +import { IconButton, makeStyles, Toolbar, useMediaQuery, useTheme } from '@material-ui/core'; import { action } from '@storybook/addon-actions'; import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; import clsx from 'clsx'; @@ -72,13 +72,16 @@ const useStyles = makeStyles(() => ({ export const withBluiAppBar = (): StoryFnReactReturnType => { const classes = useStyles(); const direction = getDirection(); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('xs')); const appBarGroupId = 'AppBar'; const threeLinerGroupId = 'ThreeLiner'; const toolbarMenuGroupId = 'ToolbarMenu'; // AppBar props const animationDuration = number('animationDuration', 300, {}, appBarGroupId); const showBackgroundImage = boolean('show backgroundImage', true, appBarGroupId); - const collapsedHeight = number('collapsedHeight', 64, {}, appBarGroupId); + const collapsedDesktopHeight = number('collapsedDesktopHeight', 64, {}, appBarGroupId); + const collapsedMobileHeight = number('collapsedMobileHeight', 56, {}, appBarGroupId); const expandedHeight = number('expandedHeight', 200, {}, appBarGroupId); const scrollThreshold = number('scrollThreshold', 136, {}, appBarGroupId); const variant = select('variant', ['snap', 'collapsed', 'expanded'], 'snap', appBarGroupId); @@ -92,7 +95,7 @@ export const withBluiAppBar = (): StoryFnReactReturnType => { <> Date: Thu, 27 Jan 2022 16:01:36 +0530 Subject: [PATCH 59/72] change dom structure --- .../src/core/ToolbarMenu/ToolbarMenu.test.tsx | 76 ++++++++++++++----- .../src/core/ToolbarMenu/ToolbarMenu.tsx | 41 +++++----- .../stories/toolbar-menu/_module.stories.tsx | 1 + .../stories/toolbar-menu/icon-with-label.tsx | 3 +- .../stories/toolbar-menu/with-app-bar.tsx | 23 +++--- .../toolbar-menu/with-blui-app-bar.tsx | 9 +-- .../with-menu-placement-options.tsx | 40 ++++++---- .../with-three-liner-custom-content.tsx | 64 ++++++++++++++++ 8 files changed, 181 insertions(+), 76 deletions(-) create mode 100644 demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx index b84bc30cb..d3a8ac688 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx @@ -1,19 +1,22 @@ import React from 'react'; import * as ReactDOM from 'react-dom'; import * as Enzyme from 'enzyme'; -import { Mount } from '../types'; +import { Mount, Shallow } from '../types'; import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; import { ToolbarMenu } from './ToolbarMenu'; -import Typography from '@material-ui/core/Typography'; import { act } from 'react-dom/test-utils'; -import { createMount } from '@material-ui/core/test-utils'; +import { createMount, createShallow } from '@material-ui/core/test-utils'; +import Trend from '@material-ui/icons/TrendingUp'; +import { findByTestId } from '../test-utils'; Enzyme.configure({ adapter: new Adapter() }); let mount: Mount; +let shallow: Shallow; -describe('ToolbarMenu', () => { +fdescribe('ToolbarMenu', () => { beforeEach(() => { mount = createMount({ strict: true }); + shallow = createShallow({ dive: false }); }); afterEach(() => { @@ -24,28 +27,61 @@ describe('ToolbarMenu', () => { ReactDOM.render(, div); }); - it('should render correct label', () => { - const toolbar = Enzyme.mount(); - const typography = toolbar.find(Typography); - expect(typography.length).toEqual(1); + // it('should render correct label', () => { + // const toolbar = Enzyme.mount(); + // const typography = toolbar.find(Typography); + // expect(typography.length).toEqual(1); + // }); + + // it('renders with icon', () => { + // const avatar = ( + // + // + // + // ); + // const wrapper = shallow(); + // expect(findByTestId('send-icon', wrapper).length).toEqual(1); + // }); + + it('renders with label', () => { + const wrapper = shallow(); + expect(findByTestId('toolbar-menu', wrapper).length).toEqual(1); }); - it('should open menu when label is clicked', () => { - const menuItems = [{ title: 'Item 1', onClick: (): void => {}, itemID: 'item1' }]; - const menuGroups = [ - { - items: menuItems, - }, - ]; + it('renders with icon', () => { + const icon = ; + const wrapper = shallow(); + expect(findByTestId('trend-icon', wrapper).length).toEqual(1); + }); + + it('runs onOpen function when toolbarMenu is clicked', () => { const onOpen = jest.fn(); - const toolbar = Enzyme.mount(); - const typography = toolbar.find(Typography); - expect(typography.length).toEqual(1); - const labelWithDropdownArrow = typography.get(0); + const icon = ; + const wrapper = shallow(); + const toolbarMenu = findByTestId('wrapper', wrapper); expect(onOpen).not.toHaveBeenCalled(); act(() => { - labelWithDropdownArrow.props.onClick(); + toolbarMenu.props.onClick(); }); expect(onOpen).toHaveBeenCalled(); }); + + // it('should open menu when label is clicked', () => { + // const menuItems = [{ title: 'Item 1', onClick: (): void => {}, itemID: 'item1' }]; + // const menuGroups = [ + // { + // items: menuItems, + // }, + // ]; + // const onOpen = jest.fn(); + // const toolbar = Enzyme.mount(); + // const typography = toolbar.find(Typography); + // expect(typography.length).toEqual(1); + // const labelWithDropdownArrow = typography.get(0); + // expect(onOpen).not.toHaveBeenCalled(); + // act(() => { + // labelWithDropdownArrow.props.onClick(); + // }); + // expect(onOpen).toHaveBeenCalled(); + // }); }); diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 54f214c6d..ed492670c 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -1,11 +1,10 @@ -import React, { HTMLAttributes, ReactNode, useState, useCallback, useRef, useEffect } from 'react'; +import React, { HTMLAttributes, useState, useCallback, useRef, useEffect } from 'react'; import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; import clsx from 'clsx'; import createStyles from '@material-ui/core/styles/createStyles'; import { DrawerNavGroup, NavItem } from '../Drawer'; import makeStyles from '@material-ui/core/styles/makeStyles'; import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; -import Typography from '@material-ui/core/Typography'; import { Theme } from '@material-ui/core/styles/createMuiTheme'; import useTheme from '@material-ui/core/styles/useTheme'; import PropTypes from 'prop-types'; @@ -15,7 +14,6 @@ export type ToolbarMenuClasses = { dropdownArrow?: string; icon?: string; label?: string; - labelContent?: string; menuItem?: string; }; @@ -35,6 +33,9 @@ const useStyles = makeStyles((theme: Theme) => createStyles({ root: { cursor: 'pointer', + fontSize: '1rem', + display: 'flex', + alignItems: 'center', color: (props: ToolbarMenuProps): string => props.color, }, cursorPointer: { @@ -52,9 +53,6 @@ const useStyles = makeStyles((theme: Theme) => textOverflow: 'ellipsis', overflow: 'hidden', }, - labelContent: { - display: 'flex', - }, navGroups: { '&:active, &:focus': { outline: 'none', @@ -75,7 +73,7 @@ export type ToolbarMenuProps = HTMLAttributes & { /** A component to render for the icon */ icon?: JSX.Element; /** Label Content */ - label: ReactNode; + label: string; /** Custom content to be displayed in the menu */ menu?: JSX.Element; /** Groups of menu items to display */ @@ -92,11 +90,12 @@ export type ToolbarMenuProps = HTMLAttributes & { const ToolbarMenuRenderer: React.ForwardRefRenderFunction = ( props: ToolbarMenuProps, + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ ref: any ) => { const { classes = {}, - /* eslint-disable @typescript-eslint/no-unused-vars */ + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ color, icon, label, @@ -105,7 +104,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction - +
{ openMenu(anchor.current); }} @@ -223,9 +221,9 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction )} - +
{getMenu()} - + ); }; /** @@ -241,7 +239,6 @@ ToolbarMenu.propTypes = { dropdownArrow: PropTypes.string, icon: PropTypes.string, label: PropTypes.string, - labelContent: PropTypes.string, menuItem: PropTypes.string, }), color: PropTypes.string, diff --git a/demos/storybook/stories/toolbar-menu/_module.stories.tsx b/demos/storybook/stories/toolbar-menu/_module.stories.tsx index e37959ea5..2d1cd5ce2 100644 --- a/demos/storybook/stories/toolbar-menu/_module.stories.tsx +++ b/demos/storybook/stories/toolbar-menu/_module.stories.tsx @@ -18,4 +18,5 @@ export { iconWithLabel } from './icon-with-label'; export { withAppBar } from './with-app-bar'; export { withBluiAppBar } from './with-blui-app-bar'; export { withMenuPlacementOptions } from './with-menu-placement-options'; +export { withThreeLinerCustomContent } from './with-three-liner-custom-content'; export default toolbarMenuModule; diff --git a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx index 4e82e3f7c..b60587d82 100644 --- a/demos/storybook/stories/toolbar-menu/icon-with-label.tsx +++ b/demos/storybook/stories/toolbar-menu/icon-with-label.tsx @@ -20,11 +20,10 @@ const menuGroups = [ export const iconWithLabel = (): StoryFnReactReturnType => { const label = text('label', 'Subtitle'); - const textColor = color('color', Colors.black[500]); const iconColor = color('icon.htmlColor', Colors.green[500]); const icon = ; - return ; + return ; }; iconWithLabel.story = { name: 'icon with label' }; diff --git a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx index bda4c23f8..b619f2cd1 100644 --- a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx @@ -1,15 +1,14 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; import AppBar from '@material-ui/core/AppBar'; -import { color, text } from '@storybook/addon-knobs'; +import { text } from '@storybook/addon-knobs'; import ListItemText from '@material-ui/core/ListItemText'; import makeStyles from '@material-ui/core/styles/makeStyles'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; - import Toolbar from '@material-ui/core/Toolbar'; import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; import Typography from '@material-ui/core/Typography'; -import * as Colors from '@brightlayer-ui/colors'; +// import * as Colors from '@brightlayer-ui/colors'; export const withAppBar = (): StoryFnReactReturnType => { const menuItems = [ @@ -34,8 +33,7 @@ export const withAppBar = (): StoryFnReactReturnType => { }, }, root: { - // color: Colors.white[50], - marginTop: '-0.125rem', + marginTop: '-0.25rem', }, }); @@ -47,14 +45,15 @@ export const withAppBar = (): StoryFnReactReturnType => { className={classes.textContent} primary={Title} secondary={ - + + + } - /> + >
); diff --git a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx index 33b56e7f1..490a1b6bd 100644 --- a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { boolean, color, number, select, text } from '@storybook/addon-knobs'; +import { boolean, number, select, text } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import { AppBar, Spacer, ThreeLiner, ToolbarMenu } from '@brightlayer-ui/react-components'; import bgImage from '../../assets/farm.jpg'; @@ -8,7 +8,7 @@ import { IconButton, makeStyles, Toolbar, useMediaQuery, useTheme } from '@mater import { action } from '@storybook/addon-actions'; import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; import clsx from 'clsx'; -import * as Colors from '@brightlayer-ui/colors'; +// import * as Colors from '@brightlayer-ui/colors'; import { getBodyFiller } from '../../src/utils'; const menuItems = [ @@ -65,7 +65,7 @@ const useStyles = makeStyles(() => ({ paddingRight: 16, }, toolbarMenuRoot: { - marginTop: '-0.125rem', + marginTop: '-0.25rem', }, })); @@ -89,7 +89,7 @@ export const withBluiAppBar = (): StoryFnReactReturnType => { const title = text('title', 'title', threeLinerGroupId); const info = text('info', 'info', threeLinerGroupId); // ToolbarMenu props - const toolbarColor = color('color', Colors.white[50], toolbarMenuGroupId); + // const toolbarColor = color('color', Colors.white[50], toolbarMenuGroupId); const toolbarLabel = text('label', 'Subtitle', toolbarMenuGroupId); return ( <> @@ -116,7 +116,6 @@ export const withBluiAppBar = (): StoryFnReactReturnType => { subtitle={ diff --git a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx index d97f57e83..5e03e33d2 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx +++ b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx @@ -1,6 +1,6 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components'; import { action } from '@storybook/addon-actions'; -import { color, select, text } from '@storybook/addon-knobs'; +import { select, text } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import React from 'react'; import AppBar from '@material-ui/core/AppBar'; @@ -8,9 +8,10 @@ import Toolbar from '@material-ui/core/Toolbar'; import ListItemText from '@material-ui/core/ListItemText'; import Typography from '@material-ui/core/Typography'; import makeStyles from '@material-ui/core/styles/makeStyles'; -import * as Colors from '@brightlayer-ui/colors'; +// import * as Colors from '@brightlayer-ui/colors'; import createStyles from '@material-ui/core/styles/createStyles'; import { GradeA } from '@brightlayer-ui/icons-mui'; +import { typography } from '@storybook/theming'; export const withMenuPlacementOptions = (): StoryFnReactReturnType => { const anchorOriginHorizontal = select( @@ -55,6 +56,9 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { marginBottom: '0.25rem', }, }, + root: { + marginTop: '-0.25rem', + }, }) ); @@ -67,19 +71,25 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { className={classes.textContent} primary={Title} secondary={ - } - label={label} - menuGroups={menuGroups} - MenuProps={{ - anchorOrigin: { horizontal: anchorOriginHorizontal, vertical: anchorOriginVertical }, - transformOrigin: { - horizontal: transformOriginHorizontal, - vertical: transformOriginVertical, - }, - }} - > + + } + label={label} + menuGroups={menuGroups} + MenuProps={{ + anchorOrigin: { + horizontal: anchorOriginHorizontal, + vertical: anchorOriginVertical, + }, + transformOrigin: { + horizontal: transformOriginHorizontal, + vertical: transformOriginVertical, + }, + }} + > + } /> diff --git a/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx b/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx new file mode 100644 index 000000000..1cb5269a1 --- /dev/null +++ b/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import AppBar from '@material-ui/core/AppBar'; +import { select, text } from '@storybook/addon-knobs'; +import ListItemText from '@material-ui/core/ListItemText'; +// import makeStyles from '@material-ui/core/styles/makeStyles'; +import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; +import Toolbar from '@material-ui/core/Toolbar'; +import { ThreeLiner, ChannelValue, ToolbarMenu } from '@brightlayer-ui/react-components'; +import Typography from '@material-ui/core/Typography'; +// import * as Colors from '@brightlayer-ui/colors'; +import Trend from '@material-ui/icons/TrendingUp'; +import * as Colors from '@brightlayer-ui/colors'; +import { makeStyles } from '@material-ui/core/styles'; +import { getLeftToRightIconTransform } from '../../src/utils'; +const menuItems = [ + { title: 'Item 1', onClick: action('Item 1 selected') }, + { title: 'Item 2', onClick: action('Item 2 selected') }, + { title: 'Item 3', onClick: action('Item 3 selected') }, +]; + +const menuGroups = [ + { + items: menuItems, + }, +]; + +const useStyles = makeStyles(() => ({ + toolbarMenuRoot: { + marginTop: '-0.25rem', + }, +})); +export const withThreeLinerCustomContent = (): StoryFnReactReturnType => { + const title = text('title', 'title'); + // const subtitle = text('subtitle', 'subtitle'); + const info = text('info', 'info'); + const infoContent = select('infoContent', ['text', ''], ''); + const classes = useStyles(); + return ( +
+ } + info={ + infoContent === '' ? ( + } + /> + ) : ( + info + ) + } + /> + ); +}; + +withThreeLinerCustomContent.story = { name: 'with three liner custom content' }; From d92f795c1617a7c3c4aef72b8abbe29f9888fc59 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Thu, 27 Jan 2022 18:29:40 +0530 Subject: [PATCH 60/72] add prefix in dep array --- components/src/core/ChannelValue/ChannelValue.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/src/core/ChannelValue/ChannelValue.tsx b/components/src/core/ChannelValue/ChannelValue.tsx index b2996f78f..906afbf65 100644 --- a/components/src/core/ChannelValue/ChannelValue.tsx +++ b/components/src/core/ChannelValue/ChannelValue.tsx @@ -111,13 +111,13 @@ const ChannelValueRender: React.ForwardRefRenderFunction prefix && unitSpace !== 'hide' && (unitSpace === 'show' || !prefixUnitAllowSpaceList.includes(units)), - [units, unitSpace] + [prefix, units, unitSpace] ); const applySuffix = useCallback( (): boolean => !prefix && unitSpace !== 'hide' && (unitSpace === 'show' || !suffixUnitAllowSpaceList.includes(units)), - [units, unitSpace] + [prefix, units, unitSpace] ); const getUnitElement = useCallback( From 31317905836ac7dd52c4088c18b60c2c7dff0e40 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 28 Jan 2022 10:36:49 +0530 Subject: [PATCH 61/72] update dom to add typography --- components/package.json | 7 +-- .../src/core/ToolbarMenu/ToolbarMenu.test.tsx | 50 +------------------ .../src/core/ToolbarMenu/ToolbarMenu.tsx | 21 ++++---- components/yarn.lock | 5 ++ demos/storybook/package.json | 1 + .../stories/toolbar-menu/with-app-bar.tsx | 12 ++--- .../with-menu-placement-options.tsx | 38 +++++++------- .../with-three-liner-custom-content.tsx | 10 +--- demos/storybook/yarn.lock | 5 ++ 9 files changed, 52 insertions(+), 97 deletions(-) diff --git a/components/package.json b/components/package.json index ef5579259..ef67f7326 100644 --- a/components/package.json +++ b/components/package.json @@ -14,14 +14,15 @@ "prettier": "@brightlayer-ui/prettier-config", "dependencies": { "@brightlayer-ui/colors": "^3.0.0", + "@seznam/compose-react-refs": "^1.0.6", "color": "^3.1.2" }, "devDependencies": { - "@material-ui/core": "^4.11.0", - "@material-ui/icons": "^4.0.0", "@brightlayer-ui/eslint-config": "^2.0.1", "@brightlayer-ui/prettier-config": "^1.0.2", "@brightlayer-ui/react-themes": "^6.0.0", + "@material-ui/core": "^4.11.0", + "@material-ui/icons": "^4.0.0", "@types/color": "^3.0.1", "@types/enzyme": "^3.10.4", "@types/enzyme-adapter-react-16": "^1.0.5", @@ -44,8 +45,8 @@ "typescript": "^4.2.3" }, "peerDependencies": { - "@material-ui/core": "^4.11.0", "@brightlayer-ui/colors": "^3.0.0", + "@material-ui/core": "^4.11.0", "react": "^16.0.0 || ^17.0.0", "react-dom": "^16.0.0 || ^17.0.0" }, diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx index d3a8ac688..5d20ed729 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx @@ -4,7 +4,6 @@ import * as Enzyme from 'enzyme'; import { Mount, Shallow } from '../types'; import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; import { ToolbarMenu } from './ToolbarMenu'; -import { act } from 'react-dom/test-utils'; import { createMount, createShallow } from '@material-ui/core/test-utils'; import Trend from '@material-ui/icons/TrendingUp'; import { findByTestId } from '../test-utils'; @@ -13,7 +12,7 @@ Enzyme.configure({ adapter: new Adapter() }); let mount: Mount; let shallow: Shallow; -fdescribe('ToolbarMenu', () => { +describe('ToolbarMenu', () => { beforeEach(() => { mount = createMount({ strict: true }); shallow = createShallow({ dive: false }); @@ -27,22 +26,6 @@ fdescribe('ToolbarMenu', () => { ReactDOM.render(, div); }); - // it('should render correct label', () => { - // const toolbar = Enzyme.mount(); - // const typography = toolbar.find(Typography); - // expect(typography.length).toEqual(1); - // }); - - // it('renders with icon', () => { - // const avatar = ( - // - // - // - // ); - // const wrapper = shallow(); - // expect(findByTestId('send-icon', wrapper).length).toEqual(1); - // }); - it('renders with label', () => { const wrapper = shallow(); expect(findByTestId('toolbar-menu', wrapper).length).toEqual(1); @@ -53,35 +36,4 @@ fdescribe('ToolbarMenu', () => { const wrapper = shallow(); expect(findByTestId('trend-icon', wrapper).length).toEqual(1); }); - - it('runs onOpen function when toolbarMenu is clicked', () => { - const onOpen = jest.fn(); - const icon = ; - const wrapper = shallow(); - const toolbarMenu = findByTestId('wrapper', wrapper); - expect(onOpen).not.toHaveBeenCalled(); - act(() => { - toolbarMenu.props.onClick(); - }); - expect(onOpen).toHaveBeenCalled(); - }); - - // it('should open menu when label is clicked', () => { - // const menuItems = [{ title: 'Item 1', onClick: (): void => {}, itemID: 'item1' }]; - // const menuGroups = [ - // { - // items: menuItems, - // }, - // ]; - // const onOpen = jest.fn(); - // const toolbar = Enzyme.mount(); - // const typography = toolbar.find(Typography); - // expect(typography.length).toEqual(1); - // const labelWithDropdownArrow = typography.get(0); - // expect(onOpen).not.toHaveBeenCalled(); - // act(() => { - // labelWithDropdownArrow.props.onClick(); - // }); - // expect(onOpen).toHaveBeenCalled(); - // }); }); diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index ed492670c..64a97b7a7 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -1,4 +1,5 @@ import React, { HTMLAttributes, useState, useCallback, useRef, useEffect } from 'react'; +import composeRefs from '@seznam/compose-react-refs' import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; import clsx from 'clsx'; import createStyles from '@material-ui/core/styles/createStyles'; @@ -8,6 +9,7 @@ import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; import { Theme } from '@material-ui/core/styles/createMuiTheme'; import useTheme from '@material-ui/core/styles/useTheme'; import PropTypes from 'prop-types'; +import { Typography } from '@material-ui/core'; export type ToolbarMenuClasses = { root?: string; @@ -17,14 +19,14 @@ export type ToolbarMenuClasses = { menuItem?: string; }; -export type ToolbarMenuItem1 = Omit & { itemID?: string }; -export type ToolbarMenuGroup1 = { +export type ToolbarMenuCompItem = Omit & { itemID?: string }; +export type ToolbarMenuCompGroup = { /** The color used for the text */ fontColor?: string; /** The color used for icons */ iconColor?: string; /** List of navigation items to render */ - items: ToolbarMenuItem1[]; + items: ToolbarMenuCompItem[]; /** Text to display in the group header */ title?: string; }; @@ -77,7 +79,7 @@ export type ToolbarMenuProps = HTMLAttributes & { /** Custom content to be displayed in the menu */ menu?: JSX.Element; /** Groups of menu items to display */ - menuGroups?: ToolbarMenuGroup1[]; + menuGroups?: ToolbarMenuCompGroup[]; /** Property overrides for the MUI Menu */ MenuProps?: Omit; /** Function called when the menu is opened */ @@ -167,7 +169,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction {!menu && - menuGroups.map((group: ToolbarMenuGroup1, index: number) => ( + menuGroups.map((group: ToolbarMenuCompGroup, index: number) => (
+ (item: ToolbarMenuCompItem, itemIndex: number): NavItem => Object.assign({ itemID: itemIndex.toString() }, item) )} /> @@ -189,8 +191,9 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction -
)} -
+ {getMenu()} ); diff --git a/components/yarn.lock b/components/yarn.lock index 4c3fb29ef..c4a6a2859 100644 --- a/components/yarn.lock +++ b/components/yarn.lock @@ -826,6 +826,11 @@ "@nodelib/fs.scandir" "2.1.4" fastq "^1.6.0" +"@seznam/compose-react-refs@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@seznam/compose-react-refs/-/compose-react-refs-1.0.6.tgz#6ec4e70bdd6e32f8e70b4100f27267cf306bd8df" + integrity sha512-izzOXQfeQLonzrIQb8u6LQ8dk+ymz3WXTIXjvOlTXHq6sbzROg3NWU+9TTAOpEoK9Bth24/6F/XrfHJ5yR5n6Q== + "@sinonjs/commons@^1.7.0": version "1.8.2" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b" diff --git a/demos/storybook/package.json b/demos/storybook/package.json index a78973429..cb28b1251 100644 --- a/demos/storybook/package.json +++ b/demos/storybook/package.json @@ -13,6 +13,7 @@ "@material-ui/core": "^4.7.2", "@material-ui/icons": "^4.5.1", "@sambego/storybook-state": "^2.0.0", + "@seznam/compose-react-refs": "^1.0.6", "@storybook/addon-actions": "^5.3.18", "@storybook/addon-info": "^5.3.18", "@storybook/addon-knobs": "^5.3.18", diff --git a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx index b619f2cd1..fc71e1462 100644 --- a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx @@ -45,13 +45,11 @@ export const withAppBar = (): StoryFnReactReturnType => { className={classes.textContent} primary={Title} secondary={ - - - + } > diff --git a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx index 5e03e33d2..bb5041a8d 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx +++ b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx @@ -8,10 +8,8 @@ import Toolbar from '@material-ui/core/Toolbar'; import ListItemText from '@material-ui/core/ListItemText'; import Typography from '@material-ui/core/Typography'; import makeStyles from '@material-ui/core/styles/makeStyles'; -// import * as Colors from '@brightlayer-ui/colors'; import createStyles from '@material-ui/core/styles/createStyles'; import { GradeA } from '@brightlayer-ui/icons-mui'; -import { typography } from '@storybook/theming'; export const withMenuPlacementOptions = (): StoryFnReactReturnType => { const anchorOriginHorizontal = select( @@ -71,25 +69,23 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { className={classes.textContent} primary={Title} secondary={ - - } - label={label} - menuGroups={menuGroups} - MenuProps={{ - anchorOrigin: { - horizontal: anchorOriginHorizontal, - vertical: anchorOriginVertical, - }, - transformOrigin: { - horizontal: transformOriginHorizontal, - vertical: transformOriginVertical, - }, - }} - > - + } + label={label} + menuGroups={menuGroups} + MenuProps={{ + anchorOrigin: { + horizontal: anchorOriginHorizontal, + vertical: anchorOriginVertical, + }, + transformOrigin: { + horizontal: transformOriginHorizontal, + vertical: transformOriginVertical, + }, + }} + > + } /> diff --git a/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx b/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx index 1cb5269a1..c897f4a59 100644 --- a/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx +++ b/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx @@ -1,14 +1,8 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; -import AppBar from '@material-ui/core/AppBar'; import { select, text } from '@storybook/addon-knobs'; -import ListItemText from '@material-ui/core/ListItemText'; -// import makeStyles from '@material-ui/core/styles/makeStyles'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; -import Toolbar from '@material-ui/core/Toolbar'; import { ThreeLiner, ChannelValue, ToolbarMenu } from '@brightlayer-ui/react-components'; -import Typography from '@material-ui/core/Typography'; -// import * as Colors from '@brightlayer-ui/colors'; import Trend from '@material-ui/icons/TrendingUp'; import * as Colors from '@brightlayer-ui/colors'; import { makeStyles } from '@material-ui/core/styles'; @@ -32,7 +26,7 @@ const useStyles = makeStyles(() => ({ })); export const withThreeLinerCustomContent = (): StoryFnReactReturnType => { const title = text('title', 'title'); - // const subtitle = text('subtitle', 'subtitle'); + const subtitle = text('subtitle', 'subtitle'); const info = text('info', 'info'); const infoContent = select('infoContent', ['text', ''], ''); const classes = useStyles(); @@ -42,7 +36,7 @@ export const withThreeLinerCustomContent = (): StoryFnReactReturnType => { subtitle={ } diff --git a/demos/storybook/yarn.lock b/demos/storybook/yarn.lock index c16952df5..210e9dee6 100644 --- a/demos/storybook/yarn.lock +++ b/demos/storybook/yarn.lock @@ -1752,6 +1752,11 @@ "@storybook/react" "^5.3.3" uuid "^3.1.0" +"@seznam/compose-react-refs@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@seznam/compose-react-refs/-/compose-react-refs-1.0.6.tgz#6ec4e70bdd6e32f8e70b4100f27267cf306bd8df" + integrity sha512-izzOXQfeQLonzrIQb8u6LQ8dk+ymz3WXTIXjvOlTXHq6sbzROg3NWU+9TTAOpEoK9Bth24/6F/XrfHJ5yR5n6Q== + "@storybook/addon-a11y@^5.3.18": version "5.3.21" resolved "https://registry.yarnpkg.com/@storybook/addon-a11y/-/addon-a11y-5.3.21.tgz#29ab480c2b1e647da15f571448824a7f29ccfb50" From 74acfc616d67a5d9c3b686133b7a825df4a87ccc Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 28 Jan 2022 14:52:19 +0530 Subject: [PATCH 62/72] update color in storybook --- .../core/DropdownToolbar/DropdownToolbar.tsx | 2 +- .../src/core/ToolbarMenu/ToolbarMenu.tsx | 12 ++++-------- .../channel-value/with-full-config.tsx | 4 +--- .../stories/toolbar-menu/with-app-bar.tsx | 5 ++++- .../stories/toolbar-menu/with-basic-usage.tsx | 6 ++---- .../with-menu-placement-options.tsx | 7 +++++-- .../with-three-liner-custom-content.tsx | 3 +-- docs/images/ToolbarMenuAnatomy.png | Bin 55606 -> 82638 bytes 8 files changed, 18 insertions(+), 21 deletions(-) diff --git a/components/src/core/DropdownToolbar/DropdownToolbar.tsx b/components/src/core/DropdownToolbar/DropdownToolbar.tsx index 6219e2b9c..5003fe504 100644 --- a/components/src/core/DropdownToolbar/DropdownToolbar.tsx +++ b/components/src/core/DropdownToolbar/DropdownToolbar.tsx @@ -163,7 +163,7 @@ const DropdownToolbarRender: React.ForwardRefRenderFunction { // eslint-disable-next-line no-console console.warn( - `DropdwonToolbar component has been deprecated and will be removed in version 6.0.0. Instead of DropdwonToolbar use ToolbarMenu component in regular Toolbar like Mui Appbar, BLUI Appbar.` + `DropdwonToolbar component has been deprecated and will be removed in version 6.0.0. Instead of DropdwonToolbar use ToolbarMenu (https://brightlayer-ui-components.github.io/react/?path=/info/components-toolbar-menu--get-read-me-story) component in regular Toolbar like Mui Appbar, BLUI Appbar.` ); }); diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 64a97b7a7..214b233c6 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -1,5 +1,5 @@ import React, { HTMLAttributes, useState, useCallback, useRef, useEffect } from 'react'; -import composeRefs from '@seznam/compose-react-refs' +import composeRefs from '@seznam/compose-react-refs'; import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; import clsx from 'clsx'; import createStyles from '@material-ui/core/styles/createStyles'; @@ -9,7 +9,7 @@ import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; import { Theme } from '@material-ui/core/styles/createMuiTheme'; import useTheme from '@material-ui/core/styles/useTheme'; import PropTypes from 'prop-types'; -import { Typography } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; export type ToolbarMenuClasses = { root?: string; @@ -38,7 +38,6 @@ const useStyles = makeStyles((theme: Theme) => fontSize: '1rem', display: 'flex', alignItems: 'center', - color: (props: ToolbarMenuProps): string => props.color, }, cursorPointer: { cursor: 'pointer', @@ -92,7 +91,6 @@ export type ToolbarMenuProps = HTMLAttributes & { const ToolbarMenuRenderer: React.ForwardRefRenderFunction = ( props: ToolbarMenuProps, - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ ref: any ) => { const { @@ -106,7 +104,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { openMenu(anchor.current); }} @@ -244,7 +242,6 @@ ToolbarMenu.propTypes = { label: PropTypes.string, menuItem: PropTypes.string, }), - color: PropTypes.string, menu: PropTypes.element, label: PropTypes.string, icon: PropTypes.element, @@ -273,7 +270,6 @@ ToolbarMenu.propTypes = { ToolbarMenu.defaultProps = { classes: {}, - color: 'inherit', menuGroups: [], MenuProps: {}, onClose: (): void => {}, diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 603719147..4748c1323 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,9 +14,7 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : ( - undefined - ); + ) : undefined; const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); diff --git a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx index fc71e1462..b8f215513 100644 --- a/demos/storybook/stories/toolbar-menu/with-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-app-bar.tsx @@ -8,9 +8,11 @@ import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/typ import Toolbar from '@material-ui/core/Toolbar'; import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; import Typography from '@material-ui/core/Typography'; -// import * as Colors from '@brightlayer-ui/colors'; +import * as Colors from '@brightlayer-ui/colors'; +import { useDarkMode } from 'storybook-dark-mode'; export const withAppBar = (): StoryFnReactReturnType => { + const isDarkMode = useDarkMode(); const menuItems = [ { title: 'Item 1', onClick: action('Item 1 selected') }, { title: 'Item 2', onClick: action('Item 2 selected') }, @@ -34,6 +36,7 @@ export const withAppBar = (): StoryFnReactReturnType => { }, root: { marginTop: '-0.25rem', + color: isDarkMode ? Colors.black[50] : Colors.white[50], }, }); diff --git a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx index 4113e8eef..4ea724594 100644 --- a/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx +++ b/demos/storybook/stories/toolbar-menu/with-basic-usage.tsx @@ -1,10 +1,9 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; -import { color, text } from '@storybook/addon-knobs'; +import { text } from '@storybook/addon-knobs'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; import { ToolbarMenu } from '@brightlayer-ui/react-components/core/ToolbarMenu'; import { WITH_MIN_PROPS_STORY_NAME } from '../../src/constants'; -import * as Colors from '@brightlayer-ui/colors'; const menuItems = [ { title: 'Item 1', onClick: action('Item 1 selected') }, @@ -19,8 +18,7 @@ const menuGroups = [ ]; export const withBasicUsage = (): StoryFnReactReturnType => { const label = text('label', 'label'); - const textColor = color('color', Colors.black[500]); - return ; + return ; }; withBasicUsage.story = { name: WITH_MIN_PROPS_STORY_NAME }; diff --git a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx index bb5041a8d..c9a2a9c49 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx +++ b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx @@ -10,6 +10,8 @@ import Typography from '@material-ui/core/Typography'; import makeStyles from '@material-ui/core/styles/makeStyles'; import createStyles from '@material-ui/core/styles/createStyles'; import { GradeA } from '@brightlayer-ui/icons-mui'; +import { useDarkMode } from 'storybook-dark-mode'; +import * as Colors from '@brightlayer-ui/colors'; export const withMenuPlacementOptions = (): StoryFnReactReturnType => { const anchorOriginHorizontal = select( @@ -43,6 +45,7 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { items: menuItems, }, ]; + const isDarkMode = useDarkMode(); const useStyles = makeStyles(() => createStyles({ textContent: { @@ -56,6 +59,7 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { }, root: { marginTop: '-0.25rem', + color: isDarkMode ? Colors.black[50] : Colors.white[50], }, }) ); @@ -84,8 +88,7 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { vertical: transformOriginVertical, }, }} - > - + > } /> diff --git a/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx b/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx index c897f4a59..d376c5dd4 100644 --- a/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx +++ b/demos/storybook/stories/toolbar-menu/with-three-liner-custom-content.tsx @@ -26,7 +26,6 @@ const useStyles = makeStyles(() => ({ })); export const withThreeLinerCustomContent = (): StoryFnReactReturnType => { const title = text('title', 'title'); - const subtitle = text('subtitle', 'subtitle'); const info = text('info', 'info'); const infoContent = select('infoContent', ['text', ''], ''); const classes = useStyles(); @@ -36,7 +35,7 @@ export const withThreeLinerCustomContent = (): StoryFnReactReturnType => { subtitle={ } diff --git a/docs/images/ToolbarMenuAnatomy.png b/docs/images/ToolbarMenuAnatomy.png index 081860962af887d4f9403d5d0f732a730a6a8947..00e15dcf4a661606d8cae79fd7ba6e9ea1ece56a 100644 GIT binary patch literal 82638 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�sJy`_EZP2uERyT7U03uzi}=VaW0?(zYJs zaJhZ$>J|(3p`;zW?a-2~fVC}4i8xBR^CMI+?Es|b5iOH%8$C;Lc&W-SlH1uQ_tl{h z4xJ4-7ljE+Lgk%4<@2zhs$r|`lb!A4K^#MB(Cx)K}FJ6M#P z^1w~yPSC4N4`@(j8lt^8eoe#{89xUpo zYIY*!JlP5S_tj24m6ADT^Px9e*~4S1Pw@hzmZ?sb33@VM&u->wc5<(jMklf_pVB^tNtuw#0-}Q5C%dljR4_tqNP#U?9C8k#)kYUlt@2B$ zw(^Is^?x=mNch~+wTFDSS=H-~ zmc45g!tE5~zGjAs&G1{Q&C-htUwuZp$)-e7dGnQ*h3Qq~674HZJ2*#X6YPW2;e=>~ z_$ZIZ{@4bsssmf;_?HV4sb{<(2ERDPaALMrf{ERo`L1wWGTwMk;_N;Al4)< zA+*Zc_}B2lNnfo^nK;CMs@d_L<@JRlGmKoa) zEu`1Dju0EQ=+8Wu(m|bPD2%89R)T{S!E#`De&10cjoL=hj$^MM9MZzB+)g)4>+a*u zXA7zs78tKd{O4PwZ9Wu@b3mQcNIt`B^G-nJA%oDrBFSx zG9fNht!WHd<(92m@dr1-HWt8&`K@`)d3{xvBF~S9HN{yLLJZgme8qjq3dS)m>8@c) z{*GI+U)nMM&7DsIcP>*Vqn`tJRtfqT#+s<0qjZtR7>#M>WDXH;ojKUHtb7z~o*hfD z1C3U$%4R}~k(!Hz%XCF~w|@o4<}_ZyF5AIpg(PrR3j4m+@@ zyr^%#=Up&|`wJgI3>TGwNwTpIg#qtEGB};jWyq4$H6!*3c3gPS5QfO07gw{j6}ZJ~ z=ff<{Qhq7;qrgiW-lt=5pAa$Cx59SH$_jW@VR3sc_Ogq+KTnx$%P?meQK75%MuB^w zhl!8=Zsx^(%kNSh$^@403>{OAi*kYp*9*obO(Y`x7)&}7gl073P5VDs?b{@|U(DmZ z;Fsf&NRnNL*nFrO*Z0Wt47QQyBbJ_=ryD;k&H2W-r|*s1%qZywMyf}4 zAv?PHyo!X7YLnel_LGIUEV^`ZR-vF=SEb(fyo`ojDR2zcHIkUVx;WNXMXNMl#V^rjWPw}GSZ#0de4tll5kRD|vGH6TFxQrEm z^&&#m1zs`Ya&gCeXpcvjKNZnDXETMn^SZno+*6T0CEsAVXY~4;SmouvWOg=K8u-AS z!~&``4VzPv5_`_iRJV+**xJ_4^A9?Mxs{n37`Y$8RZO0?EOQ~RI;7~Jmg$Wpc=;K% z9?>;&G}7^LXgtEq6=BHk?v$x5dQEO3ZlbS7(~8k zum(P3R`Q;iYZowVUAn;I1`(B=54LE6-Fv!+`j}m=2sj<7Pt5hV2$$tUptkA zJ_2~Ugm9>{ibQVQW9d_>Hu2%audLv7n#@V8E*5O5mJn4GFA^can-tXC zbw=j41}`wl&DT8Hawg;P{?j1`xe-LaDVG|UT!Ba!)aTb>!MpPLaych8*HLM@k9@GeQ2jBu9S4LXi%ube8_8-y zXU`DvK!_8&>~_a{)L!4}?$q`i!>^dtqZBXOwYqA${}{>x7C>i`Ux_im;q0Lo4Vunx zMwxh2A9FY=C{`Msh1u?>M$&^Up&0{G=*7c?>XJXWwFx4KU|G8HC#vF2%**@?yhzsh zhx)htU*T01)(toZa`Rnep`(QLTQs=Sp#1oop@Ep=N73MPsuu=;w;4dR71W>8x3nX| zfL#`ET(WK8GtWDn>_(*Hfb~RL0*nvq4NJM)B@0|=ZY}(#6GLRP|FP=dM1z9U$p6+7AZI2YP*V@ zU@1_KtZj^qYqmx%O91^*wzQ9IKUkGW=9TwtT}Q-RCSyil(Tj`QN2|ib88VMzjGBX) zqxJ5*yYf1us@QP+Tr}whCHGm%LVIUWif#%Z7+WAX)QoE@>SL)@6T_ zltT7~i(n*Nadoe&EX z?x3O_hl9kKB=69mGPj9VlZL4C%6QJBP^Lkl$9wn1tvJS zdp0;i@TJaRS+L(z0Lk$vc&K=gI_%XEjpW)8{1ub$rjafaB`zS8R$kN!;eg$o{tx)rtU4dgz^4k4XjTB`T5aF**5yqR4*M+iKwQij8H!ZuVCpVys@nKm(D` z>qEVqKA~~V!J`cgZx{GmU=e0M))YWax6}J=eAi0a_wIsAI`~MHt~5B2=L>*berwbg zJ@8%|&!~~$y)N*>)I>busm96KFP4$2qJmFZ3kp@u;!E$w6(_UU)q$S1ab~tuCkQ<< z-1yW3hF5FEgkQnl&BwBep~9O%{Fy-r%q7VQ4-iE8K+g91+0S{M|Myay%UE zHZOtK0wIx&jeIxH4GS}Bb(#)d2#DZKdL5VTi)Wq38NR5;=A%o_kopK-E#8Ya|Ebrr z^?<*h+bp(uIYYuO(g<>Eukl}}IWuX0wH%RF=?}|! zV%Oy>e>8e=NXdTBu3OH1Mi@c6KIoFDSbLu7-KZ6Lgp-If^?aL2@*=K3w(FWA#-*QB zysz;NylsLP`Z z#iT@YzDuF9;C`g2mGX&fMV{B9e;uyoL&hSCs8>JNPtVU%p?K4}Wq7kg_RI4_A+R;l zHRg5QYuX!46DgF|_Ek2eUp32miizp>v1~`Y7QY$I4cF!Tv> zlNv*|dN5x_kQ&~8(%XxO{oKK-!eB~oMt^!sO(nvF-dvNlTv)3#;cRyCOyN`6<@ZYr znO)xWq#;O;Hjo2n%$F~!jDxtXhjL!IE|1qkF+>-d1yI1<5kLg1FJ+QrBY1rujI=&|}(E948 zqE_tX?&61W4pv$*zP7CF;Z4OsmyQhxLpVB3aU+$I9uI|?kOxMolt7|~-UE#)@iIws zm-huZkrd9l%Mudl5ir?}Xq|e`fpQlSh*s9V^+d-xiK$th>-iaXEbF|f0KquLR9?C~ zB48>_h%^GNyU^k<^dA=A+(*o9UmKzY+m$yA>T#{Ss){~>ArIUh5oTT<2~e}?Tm+12 z2y(!M8v>1zlDs#+k$19xU1VFj?NW7^Woh(Nm#&7VAo|B5>TBC;dgNSU*^<2}KYLhp z5G@p1XB!{PY6NbM-dPk2SoE^d_0%qZFyV0AF-h;)^5gQ2 zBHeM`1FlTSaohQSA%xQZ2w9X8l{_+1mTqJ&7t@<)bJ%yor*iS(Vy&un1`9K+Do}CO zc*!@))brVg=oI>l{oaL1>STZJbrF@`{rJAit-#<+AxwbFXKu;PR3s>#1Ea+mE4$X* z+&S^JP+7z8nuK+2u3k53Z)kBomVewot1(8_^R`VIHh>c4=@W=>S<a2{N59^0mJZ$GF?ch{3~Ew}XPcwKv@KsIsR=gYg#Us%-Yk1PiCrr-P7 zF1Qd`9m%m2`QVy#BvMY=At5Ap@NMfs?mM`1A{m?mS4WQ0R9cYkgys7Iv9!-K!4LM6 z21i?oPXKG5fsVbA@=T>7VoW+sWSHY4eYbyHE%m9vC$o7zVBiG>-4Rb~*N^=(B^{!Y z!fo$Z`IzjULdE9uvX@`3L?l;@7ZA8so!!#k-CCXym<Yn< z%Fjz8RfLy-Y(7oTWv&_SpxtoCpI0vdCLqS`P=<*uHoPm9xi61F===ZGtRIBXNv~t0 za>b*VZ6h`8*b9^1i*7~M2B7u*PzKgTcC6o8 zc?0~yv+Gr^1!`Fx<$Q%}Hnw|HaEFHjmo+)w7y#6>zF8{dE9uy6^ zpCPMFAE{M4Y$@r`HEc0sw6<15G>Jq~Uk5r}8%WIx3JugRJ;E0W6_SXKLdSD^jufHi z^x_?h0+Re|_p1FeV}jt+YqfR^PKZY$cQp{b(GU(6Q&X$m_)^Pri&4TdsSAMqv03w( zn0RE>7j=gp@Om+y%o2(B;UsCog&8y-ir2EpSU*_~MAUTSF;LjDsQZ!4kK+VQ86oZp zY=3{R98Kk{{Pd#Ais^%YxnUFpWQ&5x9A@jzfLE{3=xn7zHN(HE8h8|2TDlaL+BfoL z3Q8rhU<<{MCxtf?m{~(FaYOOKcCcnc0ZlnWNezp@&L^w7S+Mik^oFZ&bn)s_dR#R> zZ?yEBJKTuOE+*VdVAG+(h2;+GxmcmtkdX3AD_=h9NkQ}nBWr`)j z&f0(dohpyS( zY!lm7v_@OQuL%`%_QHKeu3|5e8B^a8d7h`Mblh`fhHl^zjo5WAavi~Y&$maE!+;do zcvH^C=Un#FV;>D0tNDv?GtWJywBK_t`lY5yzX)*blD>{AvWycJR~1j-EBbK8SR^v6 zNSM(y3G?B7k>+OKlX4%kse!+t*zbUBbw3l*@lF8X{ZY0!7~Hj}^+w%xUup^}R1d;o z0;Iq`VHW@L0x7bhxKaIzl(>*wOYyiXh61SOTnT8&1wC0r3a<1r#!tFPh;w?f!`edJ zY%`X-Bfj6bvA4hM3%KL7N^K85W7dAgYfl-^m_{W!_>7&n^|`6D*E6&WI$ zuw1;sQoxQ0y$_^a&8}F8Z~MTa`1(tkUrZ0Hl-QfkB(L#m3Ljy8G`4GcM-ltEImw%O za|b~YDar=N^Kir`5WEmy)V6gP#{IiUr1I63TB&o*nd^xaE?T6>b-&5!oMf%zBhPGn z+gs_8;=HPHjdu=ufgI*NU62Pk7a|j(k8I_i$x>X;zCIDwpL-WL&L3F{{?y-3sa)dp z(;-1+)Rov&?rL{tP9c)LLz}~p*)mO{r#H%cYWRwhrEIvQF6a0#Tm~e3nf>x~dkR(K z>4%Q*auic|Fq{^zHX$`AVO^SPbX_xZ;loiOf_SW$xtIcl`4;E>TfwGXtr!bwt<{$mDuEGnI zv(C5K)<0)|X#iKyj(lxduP1EOji9TZ3&~=GFjDe!vo}Ljp30o?f|^(|UhSGXHnDpH z9)5k=8TuwqgFUob9Mw#n%krlEly6ZX*va@xvyC1eDnO&viD1p+znQ14$eQEUc1+bT zTCG$dZ)i6`5p3jt+;|4WU)VGD`-KW2h98NFt=b1(+xVENT}LfF5RN6k+5veYq>Q=` zaW1&I&2CR5D_^}|xbEJ{T6gaDF@98Ywim8L0arQdGBsU#dtf?Jn)UH>q{^`~AFFv# z&GLn}d=-6Z435oUgW!urxG}g~1nFzbd}QNSE@aYiM_7eAh$k=y5RP386F015GmF#% z%Jvgf|0yNr3IddQ9#sdd;j{pcL8L}zlkh!+!}4-lm{PU|U%bi8wRmLG?Z-&9CeU^& z-ddW;tVQp0&rni5A5Gm_74!Fi7!L;oN_7O>Sy{&lJn1Muk&&iFBeuXSZPehDL{0g5 zC|cRhko^!Y+2d%==G`daqerR*9iRFJmXeFRWN6~0U%&AVwBjImbGVGP@0vzd8fN%P z@ZJ^fZd<^j0bL{fx0dhcU5L_+RAbB@$WH5&B zK(qV9AsHIAbt_YDYQnL{1SSZ_`YS)XXH#$WtjzA=73=B>e?Dd(@#+OUa>~=H_L0Co z(}4&^hy{E)X@Zl+GU9}-;)gMkvyW8xvc%av>2>WX8kjo<4 zSXrV9YPXAzM@Z-}Az3TEzbH4F*Gjq!uoq^fUi_I+8S8EHUc$oM65*!y>G{3L-noPz z3dMEE!g6!E zjB(d5-;;@7|G3?~;iHoZW(lDe>p!iXU(Dqn{*(T`genAM7Kjlc)K2YItUK!TNW&@a zDxdIsc(>$6&$&7CBSe+s_A*LU2X5LpJ@UkXJ=-+1n)Ggn!Qx<0dJaFiUEmz+RX%ls z-1s!F?FXM08I0F}pR}IO0K=? zxn3P(BNYN(yxgg&NJ;_Y4-+M&qa**!U8WI(sfs2pttrS9>-0`K$Oq-5Xs>q*esN(D4S9;9&aB_TXWp2;*Un z&QRu4x=53U3D8`HYKK=1PgC$dkbDpc@k^Ei7JWl4U%gC#a~Roo7i z5;{BZ`Kzn?aXZD6n1(Fj#^Laau}8=mDNd%nS9W=zQ1(_MkAJ)dvQcMR=(+v-(U$qb zjiU!!gVMQ{YjLI>&Z1yf8s4m2G83@>c8b}|RH}M!89W4W+X>IEL_u`EX+z)frqAn_ z>mMy>*V)2f?Pp%=RNBRN>(w4cMkmz*M0NDou`U+HyNpy;ObIA+!$yXgBqL*M23NId z&?e8{{AX~W24U^1CGR?UaY??s{?+LC3$U=p`1uk^TV+Ypss1fvv$Hs!N z;WLxmu8{;v9NPl|Lx2^cPrX;ESGGuMvOk?vrxMy(n^T!#`t8I}?VVGB1hZQHlHLWr z+0md`7QW|IbqSQn?|wmUL0Cqv;`Vb7@BB$uvWhIb8rHkXUEhguwYUCfu6+w8oQASA zi6B2nYWQ}Tr=O?zv4foOuX9!$K)Mm zI^*X%K}@k!fZZG^&BX%n0AFIYa*t97W;}g~_VHa6LSu1`WM`+tZnUbj}g*=yi!zcwt#@eu`wAP&ATW34A^Z%*_G%`;>05#@ewg+HGu>3)xxk*w75w-Bt zBm;nDQLNME~Maz^K*<@1@2FCg`{1?rOFFPlI?y6;b?}(bDb+BAXvi z-w%KV*Pyo=Pl==yq!#9xo+~$?m7StWXs)Dd5tyIWm$~p-=C0P~d%gci3>;jR6hePY zW`PZGA9e;tPy?W_dBTfnOr%O~X~OZoBeMRCGQyl;(b%p;(Y)lJAeANk{j4G~lpj4* zDv!2Mjf;uOwMD{o3vLh|Q>*KFp|AkL=>El0_|Y*)se`fIb7bl{z$F2F9_5tdEvv6JVmJ631wbBcOymn3%y~dBQkt4JBtIq&j;n&>YH2jGv5EuM@MkL1Jl8w&+JzF1$J}5?juHdk{^OPF zbRCYAn8c-92GLv%6{7&86)GM})n@-NRQ{Ort<@INHM%wZzeqkwa?io*xX|^kmP{+s z@Kv?Y5IiTwU0gca&KG(oR~!uV=K*x*o&^qJ$dhL<4G}+nOM#=IP-H7pCl+lfKy#cV zX~4v@b>VaKgZU-vzu^S1rT#|*r*u|#H?GK6eVj$;*P4vq#Xu4gXz2Wce1q2L6r#(? zz;e_vEY47pHn}|(_ack%R0wUI&vsZ~>pU-}H}req{CC#0hN(!|@gcXlzFaRG=D)V> z=Zj?QVrOq_0bmyh4o*BQgY<}{;7`!4cXdX(waBwWv4UKN(QTzS&m1*oDxuCVPG(=H zT<6(pPSbdxVPmY<0C% z)bD+_0yEzDa4pHX9DnN%)vhf9d8v9Mt)SfhS-1Lak+I8NH|;ugu-#+i7_tw=Bql=< z3Ie*t;voM5u9gKHI}IAIYyj*x!k54|;p}YujlLLh+l`qHlwLg=QDf$_<*!ZEq)E6u}|V= zkEJI);tEJezV{ow$J2C9U{voAO-(ePsc&?4e% zP(q$W^Y7=yb=hO*vwODeA@|3el!@2hJTjjNVm8O#9IGVCHJ^+dW(}QU5anbG>~Q_{ zE#A6=qa}HO_Y44kfXIY#i1WrLLt~6CnasF+0vHYK61Sz@90w3viE@UOrCs#v;Le01 z9ml#$29jJ5`+jr&-y9tx4hA z?&_}A z35Ja^7j40F)PU276uz%7i{%kV3|*f_F$xPOHWMkf?$W8xV$U)s4);=d9ak%x{a7uQ z71GYLt)G>luY|icDWx}V;e4IFT702kC-A-dY?{%S+f?|RMpltX?P?z(F`3!5c&ps~ z*1$3w5<^gz`r|v1do;2!?L||1hPYUZ2Yyk_(SSW8*kS2|-iNyjqU)^n$5vm7b#BOe z4gacB8wgOT)(<`0mNx=X(UyUFHPTP-pOU>$med58lbHJGw#j zXh^c?OR!kfZN0focTy6g_2r$!>X+D-btnEm;yCo3w~obARK>V}ov zcf(Yh`X&zcCbZ)lwW{m7!(W6Mo*br`?W<$3>&sQ^bu3`u6fFN1 zMXezL^ecg)lsxCff^n}nh^4u7;aQ){maogZ_R94va+BQOK2KEd5Grn}9dPo0m7kX` z8FhIm817gVd{uQreMhhV^3$sMsTEVNwSjZ{=6C$$Cl1%%sJn<+T*zcCYx=d@uFE&T zu`?FtAoqfRl*#t>f$pC(vfUoKn6cW<2Xv#(QJp?-H?lZ!B{7lPQV>v9Wfj}DoyM|7 zG^n-jUWL$W`a+S2Vq7Wc)bY($o}7L7r^xUNCNe6?tBHU^+)`+(b^4gi^j$SQbK7-B zdTbKS5*7l)b3f`5%xkwZJtigD)N+^f#_lv77hE@XI?=DhcSjpZGtHJ1=O0xNGjnox zo?~r{)x+XK{O095--vBYxt7W4Gd7|g#?^_N>FrI49-;a6itd{;i;rB~+AzA-rWrS~ zMbjhejRIm85;x=wPO1x7gXYETu5Q70f1XS{a-;Rt3V&bZ(JY9&_&lk(>gJyq)&6D`R(>Paid~JIP$1G+N~{+h1h% z63ltwDfl|8T}!sBrkvY&q7rz2vcr1kH3h6R$cB+#@T@S4TwL_Loso!``j#GTk{~)& zraerZ=qRAHI?(37{aCyE(^wL&q1Ov8Y!I*Jmpk;(qqv%{o69*&axHP9V%u=cng`k#`1R=HYwv{+6wC3DskgWqH^!UFnj4B-a3}K4Z;7tMT%=aq_*nReCZgZjru0v2Ax)m(lg~MvCX0z|vjz!LW1*OPq z3O~~Zh1cGs4!&65mb2E)w<%!_sgS^B(*{8<>ln9|;T)&XHbjP~FoEt!pd18h zg~BLEMM3?(=p|;!wZybYwLI8ny{iostG=FA@?@Kr5(&GDlhfoI4`y-cG0hHpc+%}e zw>*R1jyxgjEv9@ox^9%Nq_V!iVg6I4xcb2=+m=hBu5oR(;Iii4U(u`bUwp&efRwSm&tr%aSDV1t^u(fBX&rP zl>+Fzz5q})3-A#^4?u}*O>`cy)b76o!lTDzd@FCb@h}TKS2}P03kNOdnL9U&alX-& z0nl^&%YV-22_6+Xip|Dp;TQ5>`j|Py)g6KHEcKNi2@!j+-d-hGe6O@D1Y$T)r)MwJ zwV~K^QO$#hX6tHEESgC0#W1hs&Nj5(xLRM7H0jZ?c=?6P_^-I}Z|aWDg%ce>bLhUx zsF0AwUFKPGi+;nj!I^T9V3Bh9jGw!_TuP;SgB~T5>=FlDNXe4(A^kwdra$=!ko_WQ z7)n4iuWEZMC)2Nv>^Mx|R~tYpv~=^_!=PPMuYEGf#xc$ps{J|jsCpK>p0x`a4U@M6 z5!rXO$}n(K-G(fg8*Ezwq7=>yemIxS{Vy`kryY-Bt7j!ylZgyxpSVqwD1XcPi{bQ| zk>d8G`F?04D5NdDY5A!-$HNoogU5Nl_ZHV6`Qi>fYNbp~auquZ+{=|IVar{Lk8nOa zS`od2XB2ucROT^4%-7L0ir-Vgj& zI<&n@`O$>3<;$*Rk#nuAw>4PrObI1kXUzRVSGYsEx$x%tha5dqfrN+QFBWSz#>=WC zTyqa$$lh-n~n`U^-o*?Di5ILMO8b0ny zJv#(uj$R~cm0Vnm_|YNvs$Ahc&z<)Z3x$2powdUb#B|$u7jELs7gh|Gq*>x@dyZ^a zY;_v-c?hG^%j|YaT<(VNp7>JyOml3-0rP=tXx8J^_3ujp=z_XMmIBP1nEtFd$CEo}#_y<@ZiUuwhE9f^>sGPcw5bFY z_bEzM`u!(hPI>FpT_PuSxQ{*4VS*{Yeu{0IfTilL09W8q%4~U2;iApL#&&Mz1Io_yuZm$JrutK zI?eCJ%om+znV~0qSn|#**}e9kKK?234|NI$j=NQP^apF!l2vNQ*qHs0ZL|?{>PT;pT9uTzorH<48X?3ObNmAYJjOYd>rMO3i z<|B2AW99*r3@obr`Sh>n(@%|q`8ZK_pQ^p2S-L+&t!Y7YF=gFKOao-MX3{$v!FLm& zj~Sk-m)?mubywj|oUW(7sp3Y{{r2B;f`5~7cNIN`{cKxu;OeWGum**8gq8mv6rlmC z0`#<$1ilQYS~p*KetOkvnFArLi2no*TQi21w%%@0j3 zw-{1M_lS$Sh!P2QqK^N2{^;9KX*zf3UOVvSHm=+{Yw@1hacZT(KB+;;V=wF4=~D?7 zFAH8D9MVH2WtS8{N5ESmHw4_EZ`JI(YXN?EM)#3@bPLYK78f}gPf1|$L$3xRO0Z1L zvP;Q1hG@&ZFUqp^Ysq6(V9Ik5%3;ZALhn~z8>Rrr4U|k>&=W!+2RFv}=JEvMu;k;Z zA|7F;3ByLc>pPF442(&B^5ifwRnz*cg}7B1p=Zo&;ZcQvEMwJnsKV% zK!EuMCETicFcAbR(>g@)mE6&g3kF|l1!DzVrDouh1lqIr?wpA@Q^XNr1jFKw46rb^ z74f(J8On=ytT4i{rixPdtDJ0(mk-%_itn^DX^1IltsMx_9P1h|viR`wK)x4K7Vd?3 z0N)Gr(aAE09NU`>c>uG`Rf3P-FTBER|v+HI^^w`^`m?$X3=M{rX`ZdNRXW; z*nx*bM~-6UbOYi3hy5w{xJ%IjMFbjOwL4&m_?~uYC$A4Q2_7-f=DrIHUf^81 zI8%4^+ZG1QelkHm3+;I=5fQmpUWO_XpitlNm&n=iWgqH4=PYV^WpW_%Mz-Tk<$eQC zCel&>*WT0bB~avOZ~Dq+`rLR)Nr=BCW;MR3WACj@x_0_(c$e($nq{T862Hc1K<5I8 zpAQF5kwpfY90zUZY|*EF^R?7!!; z|4i;k7lBl{dQAvC6FmdIsiVpOf3LF5CE}L_@s~BB*qSu5@4i?4QNF9Woe_!+lj%5H z{E)JayvC;}b~w~2ki-!kysxsPxS92An`J;|_EOKtgz9FF?1!GGaI9onJ)>^(qzq}c zDOk>^#dOaS&b)G?b0;gECvcmw`6?(~dB0oNW4um#d?V_=7s}e9EkV5B+~>~H)jlxo z`YYIwfmp}J1u(eD6oY7-pL`6nDysst1E?^U0RvO44h*ZI5mNe=cVSo2ocvzxzpYhq z(SJD)I&i-Em>Hm|Me+^uE}$B0X^>eL%RSFnD72%}1KLw0L;%g?7=^l{GQ6b!h1xZo z&Kxsb>AOqlutJUwMs{qQW{GxGQZ|nMU|o$h$MAt7#UT%&Io@ zFcZ~B61+o3CrvP3D_Z?+B{zD@vu9+!T=AM7dZIlV7USkK=I~9?ef!gXl?BYLi4rMI zvp4vGeKF5oRbZoQ!<)sr=u>;4?s(Drp9lE7{KqrvZu|#}s!spZ*mlZ`ez>wlv+XbS zVz*+IvEk+^3)uK;f;B8-{8-C$Qj^1uTQ9);NaR7`7V`by^ z?Clg)Kjj{--vZf;T4r3x5ag9@lQ}RBUAMk(j)O424Q*Ds*~EnCAq556Td9$>_vtGGx;{ z#+Onz3xYZnSB-}-DGY+i;oVC=mDHI$fhaS$Bal-M&?)TZusF4_WPcGd_T(NhfU=ia zzwX^M7!paHB*4Nnd>0cA6QZ4}9{&KH8l=Drb4af}Gf@O%>m>7Cog0dCJj*m_86DA= zN&R0l!|njS7@!yUCnVD1i^#|T1tk(~VMl`$=0v?#aEnRe0n!8aQ*U+CZgTTxAg!ZF z#54d)=|ep8z{29vdjMuaUYI0#VLpm=WC6!%iv6qR@ddj$U5!8Uxq49aUGjS7jZC^m zY*1r1l(}vN(0W<{zz&mGPS&FOL-`@<(MHFZMKq=!HVd@^E}{`XKxF=Kr<;msJsqO& ze(8eLTSNCN^tS$oCf;0d7-Xp5Un>r!*OnqyZqFB{d>Qomm9FLZz=@b|c39E`e-NhT z>yzqm_Nhx&q*Q(<-!fjZS)gnnW`Cp z)}jgF(bFxKL{d3E9rDxu&Imp*R|QD|Gn2K`SbuP|=rs;egi06FK9eXr0DvE(JEkI# z7D<|6R0excE$poHYkpyco5j<-IY(VEr&r9t^7>)yXW zFg6V^)PJS%jXdDsr{MJ!vr}MsHqU5`Hg+G)r)d_Xvk_)TRe~XbdjhTAI`0B3URJ|0 z3y4`kwl7Qe2y0Zhne{q}bNOf&C%dn$5swCWE$Cj^Uf;btKf?$4_cQ8XCD&nZ^FWpj ziv(PcWjx7F;c4lpP67>Q=)GZP9rYtu3C ztltPoWV(D`I=4+!q-rUxrAy1ru2{O*(fA5^+!N|Bm3)@igZmrG2Q#qOXo zYCcqU0&4EK5z0j1r#k) zqEECC|8R>sc^&EvNb5KHRvPoQ&ZEkJR#baA3rK>_-Xu|dsJ)@>w3B8b)KXZ?^m0Qg zwm>~CPh*ZNertuUNs6e+d*dGWcbts(BZheWih+B?RN1$5mg<89w z$7#XOQ;LII)~vrLj6cp$r;oNY7?j!RCtF8cYLz0trObCAQW;&uN5V4aoz*X+P4cyN zEP$rDHv;4jBYfTb=xNXgl)Lq2S*^GZF%9d!i!ghMFTY*SalxYO3(iVg;4BamYuq-V zP;dNrv5qtwa5?qk==;TO6XM)9YahJ`P$ghp){R?2a^E<4KSs2#2?es%V zWMViRw3q?TPk|LT(5QGGmxt+3TLX^; zV_lQu5sRqaCmQkv|-{TCav;laj2}D-SU_9HvRYV(T@4@ zUF_z|EWhc>Fqc-EdD`c_PsGLVU_hSz`yl>{j_C`tNT2t7 z#AY@1cqODP=Fk%rK-nPO{HRq+Ne}_rXDFe3wyv(C;_cm*yz-f|&8J?b3wBF=kGm#p zId?_(HYoXq`5dO&id53r<{^gC9s7^kZ&oYZ^wEAU3d|%;IVCx-*|7uM{}dgegf5G= z;{5m>W>VLDcR}Z}RQYq@1M*sRYsYq@VBy2>(3%MYapF*?shM{X35hhM54TuRaxu*ogU^As~^O5zBO)U>;%&HH@zKS!l9!yUOK&~6W!=%&6 zM6JpEJn!UffT?rgry{(ZoK|Cat_Eit3~b1ky?Lj-2<*(C)JC|`Y#uCb`1Ct?^dCDg z8=2@cPccU)xI4FXPlxQ;Xl~=}eWs&B9k~3rwc3w@>a)^xZO-9=uG7W69*5G?c)uMh zr~N&e{Ytmb$$K73Azwq)iURZ^9kxuBPh*vi8jZW`M-*%qcw}H4sXnx6e5KWc8>o8b zP3%70oA{c%elcYQtAMi&;sC``ZkSup)0W3lL(w#xC@OClSJg~yJM;VK`zL8A#wixV zHyZv+ekVo2%fZdd(b)xx9YdM;kdnUXASrL&v(uNbXK`+TKq~@v38Dm-ZgTKq<$?Mj zw!l^1_;kWBj!jI-KYm-kYQa;&aeva$i`Av=#ZBIWh?OBm*T!JV%A{*{1%H^j9-n{US& z2{h!u)y035`DdL>c9H=y{KJKp0j_Qv;LGbrTpUYGgy$ulx56l!+ZYS8_n*d=qAXnj z#_T7@MxJzV8g?jr5G!#f#mR_lcDpP;Mp!(nS&Ric0?ZmN*PY)`M;m#*| zfAnfu?n-DiiX-VB8oj#~FK{%>;%TVYcY)$2ZDuf1foHAoGymyMseZ?&= z(aya$2|3c;&QHo-zL>6`a{-m(x&h z6?Qo|?N!5KO3dGVM z{2}&r;il{f%^@EdG%aV;&Fy}S*VYe+^|}QshSN15aT6B{2c&*&|^8L>B+nEBn15+d8C_?0~A?Hq4h&fY-b8 z-6eO;BOQfW2_3mHq+w4OXB~?>s7($d(;e1WCsLcUC8HI4L|&nKuWSaxX+A9zVTT# zA_pq?;m#cdp85%@HrjUQ2BQL(YqZgBk@KIQYRbh2;5 zLeG7oKT-(TJ_y6WMM09dx)@u~ED6rzfo!?=ap{8bRLsrQP<8V>@fUCCeX9-=K37#M z|LDg6jf^ZTo+w!hB5N`O%UdjD~K>3EncN@yjCB z62g3h`OxjF8=9=S{Oxzq4Sg$|+#gbjeO}gZPs4gAGiOYQ`|<}G`joPQKPWa)sm>IIii6W!4N9OZ^)#~H?5YFDpO zC)e)jRrEAERSx9wYZx1b)?Ut9|m_YuTo?^ z9EsODbZfWyEsxWiNT^z=r}>`!Qs==e9X0oe%!~#_@g`BI@53|UM4P&AJfa=9tBQAT zWE?2qm70TbbjBd<}o-SK{Y$DmF2wuKR|zed)R(UQ4?KWGjlyo^>S=J*xT zyKi?PEL*+^tvBfPGcxHOTULdrq~~dLIXXa!C%qiU4~X|JLdmcVqAOpJ895 zUyVTwS3Eyt|JsiKv?H-5yLiDYQV;1FULKLq)lHWqL5=Xu2uSE3y@Gfwp!K(lUcO-i zySU}8>=e7;S(TAxM{;q4{zE=pXp20X8AeL4$3{AfeEVys^KravG#ySLJi z*ysQYE&AHZ*V+A=)QbC6mmoD4fmg;_Mdp8cxhTo`8+<#nk#BkfTOvMxc~X#(6g($Tt?AYOOi)v~y^(8X03eVE`mch!QAi@~bD zx00)5Qm;K(rj36?wm|N@ngth!rsn6DzAcJhJk(_($C@q{1^Tv>%76C(&Cw?{sz&9o zn#plm6t}rexTchQc ziv=<^l4@495)tW!mX>K2L|?Vr;+QEqILg^0|KQ`};A04I#rI$O8U{bc#PMe`JA_I9 zinP3UPaN}vMpgbS2t9Q2?!?xc7L`(9ZS6!uNFI+&ccP;tZ2p;zOL?#kZgX$wBgqFA z1RZ1Ml@E2`6z8w zb233^@bL?%0m}Rn-#lIl^oHVh+AdlkO5C294jb>RuN_t}NIMi?kr$a%w&gKE*EDn(DaP$@gCaX4Fd!6J(lc|^E3w9#^)wEHU3+Ka*Gh*_+QQmyQ01lS8hcsRDn`&9J0 zV=j;{tpiAHjswDE#l+OB2r!>0mXMZBzYGR+K~m3Gy(vO1@HL@*>oHjivS={zFLm}m z&5}|N(MKimpF0sPTTvEH&o~2rN|Ley-I%xtXDUrfWvD8{`TtF5Qz%kTkXQ~(obR_A z(WT5Beq3}J2`Ma+S?3WuV!=#_Tu|I-uG1be_d+jc@u=U?zTC1QZ2{mTg4AxwjU@3* zyHsCa#*I3KsJ>!4wdTe=#YqMmlH^_00qYA|`64Fep+8jA9&dO0HYfhu2uyC$V7!Vq z7+W5lD@@PGD~zR{zt+KJn6K3ZEk79W3~jK|{|0oOL&3H>tNmvvghbR)$ZAmTQQ?J` z2#=yJ3R|jvoRp`6IV@L~IqEmyt@=uG?=06vTzOGeNy=vJ(j+mvgvRGbIMjSTv&?sv zb+z!3mbjQa4fw-l3a|CJfsml?Jz&T@ zBt4Mr|GFbu=<%3vuQ#v8afk9F@JaFN{>ucc47eE>Ub*(67;OBhpWcC*)Ij9H?uV~Q zIHo5GKbAo)%-)PJf0GAPa7vQ_odKv6fJAt4oZ*NAVG;;Xlv@^4mlnHrbvuG>Us%uT zw*=4}RBi%UPE=MI+2_kI=6FiRjiY2F7Bnd40K1aB78*$pW+MqKJQ4lKU6;LA>~wi z@HjZsl}Eq1J*k@Ca(VB4xr5Pifl*!QCQUIG!*>5$-}t$f+3GFzid?VvOUt`P=KImt zrdGnwMFOglJW7bL-l(vY8HQ_NX?!fTp`0ElJ1WKARTge-AlXYcp9AI5pxDmubNBWn zD36{!20mzHD=r+p%nZ@#EX!WCi~^&8$*9xEski1>s38uVwC`U>$SS7UFon(-J(kL? zYRyWacfg>64`JmL*Z%Mcxzo12(lE)JbqM9YoW+GlhpsD&eMcUSo4!)>bolNXre!;H z{K`>Ho(`lcIgAuHsgt%G(-F~&8E?a^AVo?TZ;5ISP=~#Z(sIL1U#(1 zckx$X0njYpta&~&~><_+gX48oR)Oe@SRUD?H6s{9Mp@z#G6L*Wf2}l+h1Bo_n*qeRpy(L z$}Ljc;|Wb_%U^Jlul2QsyCwGGCO2)=FXblE+7$_MMW~qaMRKb#ehPpRZjY~g=e8eP z9dS_9^kLEsuj9ey-_xzC=y&Q$U}Ub}Nz0F1TO83LOMoUP57xUUUz7Hqq$t%MoSJz# z0^~sW+i@G_`#ExzudlWY)q7symrcoCyu7e&QeD6AV(WtSgWmgW$CnqrIdV=2@R|_G zDz1BlwMh|u>ytE&8jH#8Pvv(9?w46D$(@L9yTA7FM%LQZxywrhMm18kk-Jq^K2x1v zji6xsn-pZ(BA+f6$W4KoVeyL()pbvHIWIC-MG_~y7uP)n7E&SZG#{SYDJTc{s$>((JAHeQw#c zT|;|^U^XTA)nE4&)7T#fQ9ct9=IlR5)@GkqKSZIfYlJ5QLGep)t|BXQg*fDW<#a`B zgPJL_N(NZWxzRj`1kb_dD;b3$|N0lv2TB3cnMaCFC2BLV(=%!c@?dp~VPW8{5W$$y zT=jLS?_o3_ebP;ci2@GC=o1okHcQ#tRwJ4t>uf@R*h5Led;yfYpwRyI#B11>vlg@KjK}t8L0uEmN`yglDT^t2h4fQOP zf{=KQlG_sQ7%$4j-G^7Sibonfk+#MK@*B@v)fJe|HZAr`QH;lqr-3eN>#r`#HU&Jq z7qFK;;A2{WIcmH9s+e&O(xQx{3|FrM+N)1TyF}r1LFHC0_}x+wFeKMt0f>z7sb&Ng z9ukDkvGSDPjXLC?5oi(IiAh*~=yE}%_hEAt@OjC+f5?UG^s?}m(@QL<^Dn5r^CF8v z)HpIWoqmkaFcGngA=uFk{8@M5Q{1AQp-{q1S7ODs>B1Oz zsIdr_k#6*xEFwsR0zW_0J^j#fifwOzeTDJ zYiJ&;6@n?#UyUcBOy{C}(W{K^%9ipSKa6_;3I7y|pg?xbfoe<_B1$;?Gq{O@jMSbe zC&ABOM^W`FZ|FbX_W!?nU(oOScUrHUWyX7#$NK_lwV+x(1d;I-Td`I}S;$KtR! zfO+8?@b##6wj~U0aFIc?*H;+AwNU+m`GR%scHaq zxSkp%*ezeusC>60MtPUNYLmb88D1cR#zlkF6_8t5AN&53cqwwLqRW7RI$ ziOaO*z%4L_HVBixT`lFRMhqtxk{>?+C(Qpa`LPC)8H}q++B{L?Pa+gE4QM-CaUnGb zVCUR{um_r}luAC-592!8!^mbqzzLM1Eu}5vmbjW))c_pSC=t7K29yQk?B`LEk;WrC?caF#8>HJA{sTK2p5>;MEtq#XX^ zSg$=$!_?*mqD(kV#UiF534ye&@utlXJ%&R5cfp=b#G{^Sn>=bA1=N=d$UdLIebWMj;HkOv-ywJm#E|fm%3?D4 z&KmfGkQlr)sMmZ3fV)75p?$y|^r=ZkLttQ9m({Hfb(t4QX_$rsY#ws#vD%JB2ax*M ztNJQXM$;nL4XN%q5TPq{jZow>#Te=JG}q9ONV9~K_GD{^KiS;B-E;Y{$&Ko=HUAYum$a2qJ$Ks*-> zdhAI!JfHTt3QlJ^^Az}~{IMso)TzuXCnNjKU0-~MlS{(&&FUM!<}Ck?^|p;h16K)L z#ib;7<1D60jH!Z3GbXH#MAs-dx}FT4nk9_0i*m{@D(K_mnSg1a(FL?A^2X1@YYA~7M_beA4Oj30pJ>V<82HZ4#Y*HxOlOD5<(76gO%A!^ zjJOHZXfsYLp!1CvGJ0}vAE5QXj1^FpRREec`bQ|gP@rHd1I#cgiX~*kJNXTx?kP`c7~Z7lrG^1 zZ!B7*|B}Q1vk4Ibr#XM6z**+fV@>Zf?yvIrfg@_5P^XC!4p0ibf`Hfed$QMe1MtGq zn`T5Xf;Kl$h`Ko+B-UP7Xazy^c!0S$K7b#IgfLDrxW@z{XNZ_d z#(mRNybUQ#zPIg?7T6#c7mt1hyzHrO>Ay=oV4+zuiumdcem=>^!Krr2NOONO2en3* zXLTZjS1eWW#4EL4qf#g~qJhro2cO17f#om~%=S%G+pWf;ppfGsM!kG$RTA-uc1APr zwty8exMpWufA>o7H_SignODF;{$*{JSjGHCPOhfjros@Y_`*(?qiaFfXDfIvZUr`flq@-Pz} z%dsfi7Oa8?(tBVwVf%}E5J_?N>CN{d6ypKlYJwAgUrq22Z^Bj>&~IPv_7dzuXhriY zvwKr}LJjGj(H7wv6<#AC4qK#|WoI%-tieHnC}D5{n)b5+l*2(iFY&r;xd zFY`8f=n_4y^m!yDDBaS$r0c|fPutbN$<{&L0w?_~BM7^3=PCNRbzG}*y;h@@lNviC zEzzfmg3QFH;A#(i^$*?-8Wf{JcX;6Hy@pVBy3+Po?uTbit7ht@i=nq9?IrVy#`mwo zKoJGbv-qQ0e~+KU9S{v{|FJG`<$_z*O43lv(u_Cy${bs~o$_g2kW#?c2i1%*_81o7 z-~fpQ0(QP&X?QU@{)>f4now28^dQXur*Z$Y`1-v%@?Db{?j{*E;ng4+UNxT zBdEPzmSlNLv7{$XKh7=~!;pXy>ckmEG)U&uJ9}>`;ttg-JoN&w`DA9;$H(nLNFW#| zDq2BhNSp1k*SHisNo_BP;Va+axJ3;gn*X$vHH4j^2oXp~W&t19@fZ|Qui7{*%AiJU z_-2L5QK0GvH+eSR1E#V`hsahzb}&x=xCFXM#WKXFM2yT){Z5BJvoy>F2B)&Woj(n! zp&CB{#+p|DS&AZoyZ&pwKvPp!*96sLkofs>8m3ql5_no=uRxdYM!!L=(TWMBy5Rr+UqdfY)Hc z7ACYT2kpo%l~YWyjlc1_cWXMn-`s|L7s7}CybA#sR8xe-){ilNtvq9MDvsxxz`Po0 zPf;aV)D*|q2U98)yMGkh>QF}4paGIR`U()ldY?&0eNxLZV91J#Ojt39;3ivJk*_JB z{=cp%Ai+3nsCjt(t0GHL1-1j!8S8Zj_Usbc=QV*kcfnyUg{d?sRQ8F|TEV3xxUY$I zgKIe4!8II2sCo=0#r6kRqbHqw&q&(->DP5ef91~qdG!Y`I|f$I>!+dCJ{wElS=Myc zk5fA*e!T?{S`5KDLV&nha2_P;YamfyWhkB`$-}U8vMkmT{0>sOW^9q?MXoN#X5B7@ z-aD{!qk5pdHGx~0s9k*fo6yhzNvQt=ythpJXgA;M3T+#@TK1!voA1? z`{Px>UNQf zHL94`B^kZ{;Xxe*t_WI<2bO>}jgpXKkFzy=`U%Zv9!M8s%czp{JwdomvqljHJd)H%rg69^8HwwAv#~5;% zeEor(I<)+*4zPzdn3Kz~VvFWsr)htRREtwRnK+$@sqF;iDCitM%q_}!7`gn$`2T%N zz)6rV)ikz2_HvEGC>zHzctZ6gsf0je$8&>e4HjnvbV-4&-~yUu$``jjjJ{vN^8`YT zO=O4Zy~jByhTZHL{?w9Hf5+plKW^grR``Kv&Gc>7;Iu#h+V4 zXyq$!`RT%bXqW84KKR>%y+HyrMJK6jEWjiHTp$7Z6yQi8M*_T%b-E&cV6m?4(Jbf* zs@)fz9`yIgH?>UD50~1ggOpu7Ohv}5fpKd~rGhyG2kOZ%VBP;+A}-R}0I2BgQ>x5v z`W;$SSd6^?`M+=$O-dIi##>X%>Xb~UB)M{ps4b9=BQ`UHjgjs>TA z{umF1(AkewH_lN+c)fYTzMOGa$o%@i>l7yK2VWujfIVz}HKbLcY*KDju6M0p(A@9>=Z*~ z2I3E0E!oYY1WX_7lLYLoZf4n@gBTt-ju~6v_XRpkW@E+-l+h}_Y{We@)IIQEHc%N-kWMX&3 zA(Tfw;*s%<<7ps1;;Qwg_s0r8WidOFFs6rdgeJ@m-q^!J)1bv>}Tu?^$cG~3F{P}Pzc2zjWzIBrJv z4tMMARo}jRCqMEK@@hfi5*)bOjL4jl0=xi%Xh}DwJpLced>^e+n31wnTDSr8)A>t9v8z33S z^j6TJ5&Y}l+<9SVnM&qi5rUSgEW52n`!#jX6>G>YTZT%{KfG0bECgYymuruaZx#Y~ z;^gpK*})zM(#``bJ5)z!BnJQcUL>DCR>xN>GXMJq6+pF-v_bG+6-?+*_Ca<<#{1@~ z{^`%S@3pfI3SR{##2{&=YwiiX>W_!|gJXHMI&W<@!-#NcmJq!dnHxYhj3fSJeG1S4 zm!*K^aD?Ue@#lG1V1SnoI8g&q8Dmw?D?duJ;y>itRi>BwSXbxAg|RR1L<$o)Piciz`#dHkgOlM8IJWeBfbHJS7e zlI0eM7|g)@MQ5I*F)wl&*p&2UB+%IZKkdC~T+>$*HmpbsqBn~yf&vk&B7!JVc1RSZ zw6zi~3IW+8AR@A)Y?1_AkX2%fvO`p=Xbk~m-$5WzfkXupWD5{TfUt$ICM0&%(y4kz5wUv8OtztKN8bDiN~u=%3e@aKBV@u3rb`Qbml zFq+(QHU8&aw$0vn!W~GRwpVHFdEra~qd_r-eQW4NCs7)aRBuyaQxE8>x3Y<*)#H=8 z1X*kAKx0u`AE4 z?ULGRFc?H7@%w}CA7HY6zPSa`uZgbioqu@B!JikFlXNF$fjjzc28YwXQA+OKi?epO zTIxCM0I^dKITP5iKF^z$h<-klj2^cQh@8|98!$PqMV1{=T}YZu)ZIHxPj< zYB?auG*5sJh$Ebx%Yi1E>|Ka29~qnj^|-=&_wbbXSv=|yA|bYXExrHEe_n(3;*SC* zYR;$I9=q|Sxp)pm*y=*u5m%lirb&S^`861EQdo;8-s}>L4%Dvv&>xX2PInP4n&!0$ zu)LTkKMUKrJx6DfHm?5>K=Uwtt$V9nabI*3;zCs!G-!NQ6~fT6mocr}wDnz&*zCZ8 z8tLC}@r1^dJDvNfCgC5hhb+zyK0tWbT(Iulh?LCr$pmuBYF-kUNEhq$Q`DRXKaydzjN zuYW*#M)#Pm%VhT(|3Jog6)f6Z0*$MQ=QVB3$a(maLc%dgZTaicu4%_4XvUN2mJ$lp z2R6$>*hv@{Ci+cMYk`ysCc%;aRG_J!-~5Qu?bI8;DyuJf8@K+rDUx}rb&hv*Wo;qc z_Le~Uc*3`kwb!_zb=Jrahh*T^!gsB8WkcA=QTFrroiAg?pEpG>?tPD5EM6ba35up$ z;%3$i+mqnJMYslDf@%G|5uGl_oBuX5Ix^>JI6ll$Z2XmeXv|n~V`%P_2YSXs-6H{h zQ|GAMCc%UFH?4mWyV>TxU8Ig7KcS5#sR|8M+dmKF9#Y z@0)8)Mi%V$NbKA@JR)ZaroiJ%c@K`_8?|p&?hHwAlyORMS}&j1+J>la0+PYPn;3pZ zkZ5cLy>gOw(yhfa$!$g92KsXHMc8VPD66%jN?fFay=^xH$MAzR@Oy0bto1Nf+Z2T< zsH;v}3|aavaKN{igKBBqP@F;VN2I#9{)+Fk`& zuAk$z#_POqTzXq6&!PUv&0_|wW2SXrLSDR119s-XQ{nV#e`buL-0|j7om=Z2H=$8+ zOZ#S_fsZ{OXSNIBBT1Dv?m6NaKa}e(7B|{iW89NB)qgCOBm^iJ1pR4#Cx>e#ca#u2 zs-_hZn!nl_yqeiwDRo@1*!^VIc6aHU$T&Uzv%QWXTCO1@(MunkAk%PZg@Xqmt0Qun z?FA@pvf;%1L(il58#Sk-v*$Yb!*aqJW|O*KqkqiWo-^pFZdlAOT&#h&UzYb*qBWy> zH9HLj+m_dOQjuXqQ8bB)hDMnP<{a=GSk-c&LWwW5O%E$^?T==q%6kqx`^}uyd-RdP zpA!-SMsyEkF7)h<>($-gwfZ_hRMeR%ps_L9S3r%VFXMzli97)eiD678F)PE0N-N9gdxxPdXc5eWXo}3*3mov|9^iT3T$d!Adav&! zsU3V?LLExmqNO;B_o;k_>S~nT)ymGU-3-{n&l#^)F4QVr1dY>?2?Ns(t>8QcOJ0W7xh>qWS?)*6e{+x@c zVY==sE2YgHf)n5Ks&+{F_^IqI}zkaAbM%}*L=xdmv3rE_~Dy*F3Tc0C6X*Z-qQ_VRet2yGG?Il{n@E|kv2ol&}*wZ|0AA@Srlu!J-=(xo+KxX z7SE0pCKTe$j^g1)d5ULdU8OpQ#%ISpO{M>IvxU+^6?T=u7{3O{xz zdg6NZGIc!N@`Kbq?IC^t-Po|em*co&k_O+!wo1jd#xEJy#P5(xL!eV1QXWG%iU=8} z#x2Q(#qQBF6*(Cm*r+_#p#VK!0=)l#+5GQHqwidl9?^7yIwPi@JzeWj;bFupn7Qob z#AQD$H^W`*^p(?b?>f6m6hzKTLW!-NQahXSB#^xP5 zB4XGP#8cQu!m=1nj2ZOKZ4{=8rc~m{f`4QF?Zs;csk=CgZgWwjmP8Hn|PmQHT^MXc+6~$}C?^qh(-o88ZPFzCVrMUUyc`sKIZKT8ciOH4iwTvJ5 z70dk;cig7v;l?#a5~s_N^`||9*kW)Rw32v#vSTL*F?Tk_%WaE?_VKMGr&@`IyyhEb zKKd_}F*1(N?=Fc}ni&3!(C5KrG6_Gj8 z!?zzl2NwPSEZmrJLa}6ja#&GBMHRs9wdWoUYr`I^rOcv%Wo+?lFJW{|a;q^Pwo*gY z`0C&-y>`7eg04F^@5ZK=wr97u%thQy7fr5MZf)`*O?CYF{`0%Unyx{lqX57EMD*Yv zB(@?les?BHpB(-}(rOcc5UilQE$YlWyJ+`Sf5DitgbGY!Q77(#dd(f8r&Y)C`Y%zw^C78uA)4BpbRqw*_J7!u^DaPx6({wepzo&<>?nm(9pkH zhJkjp`{VT6^@Nqm1?7Z1Xj8QbbtAJ-%CUKf*Hvau1H>vxBhXPBAm9J65RcU2x4A zG~>PQ$V8(Ajo;mBXEY>6B`FuuN_~I+yczU$-Lc&bI01oSY$Ohpc!vosS_vi!-%1jq zg67tcjHp$*toT@)>)iFGuES`q*s@l^&BH3;_j@p|b<8>oF5=EXY4~v|nAW-ag{}IG z>&EQ|CFKt{!j(=c6|%A?bK)XLeVzNuiupcUJB6c7Tke0hvP#=Mn*%NgK3v{g5+I=| zDhbGfauA0{txJB|oNRGJnTD4oYSUEmn@2^B^X)OAt!YL|9`~@b<1^$3t>i$Px9gLG zQljamkXCBT(50-Gq%xHfR@y}n&a&s4uN81YAez~+#&qT`JZ*^Gz6{UdLAi}vPH}%s zmX3=Ze|#qHeErW)v%Px=mg1=k{Uo2_6R~2=YCqA+u!Yfm<1f@e9#Dg?KZJg_N5V<# z!4cy${KC7KAFJQv&e)D@YPBW&ITSG+25Gx$3;G^79)E*J5N z_?mCb(x3b$KQ_#q=#%spOSIAh-at+Ig$K+jC_6U3IqQ3d)i5Ao~$n zN0i(Y&dY}_7h5boo5n~!$a)(!$KN_qBg#5u_%-8%d4Gxzra> zJXpWJ(DCG2N70RL^UcW_H8C6EGBGS)u~7Obqb75$>}1;`T+HJ}ofFX;d1qo4Z(KcDR*YW4Ll`Yf za^iO|DD?4C3xtm%N5YbpbGk3#WFRAa3l8y1|fqg%hT3N-G33r%4t-ijC(6a35TB{-TI0r6Lg4;F0*39iQ~P0O)3Ag-4NzMBV-)a@TJlFqIW;&fpTNZS$kI zPf{a|I2BDnf*~H;BQ5NB4wwx3dE`XXOY$|E&hPS1 zp-YqarWMNq`>ios5#+$eSMi`c-bM+gHRg9ybW8r%*La14?z*>r8o8`oaEZf=epMUJ zHwabSS95<;{h+DXGME!<@tHkFo&jsp>eYa_d_ zorrp}#cO(Qeb8e&YI%IqCd>36P98sJA#+j6IXGNnDrRhtCZ@GZ4$W8@M2km$c)F3= z;V0~x`E4VKdu4b8_zn$Al9U8ZERquyGZj5z*leizwS0p1AHQB`c{5Z6$q(n#A{scX zR`ENW1`0g^6TRZbjX*?lG1G}U6)8;}LlHs`^XV=>QK3iu8bdZ9=C^l{nl*vA<8WT? z?SZC+=S|D2ajck3J?&n(^+{M*Yw{|+uv)$ZJF*ipZk@sS!RJQ-u~$y~!6{YHndVi+ zHC@?Vnl|Yts>9cSm~01MZ1~kRLzPzp`jjl`lst)z>%A2jcYeM3nxQGi9gRc4Dh&Ag zWyHhL))LcqqBCQ|tSLUJpAzR};BOVL(oKQCnSsPPfLn5jaXHb6@W{SNYNvk2T=UBX zie8%@zU`6luKOs(y8c6)PP}L`NLZ$m-je1H4O~1)HoAg_bMt$*FiF8yY+xo)}m`P9~@Mr-b{|)sjr=GqXKsYn6Re! zGJa83f6j6@0N?cHjZVS^d)gHpMYn=6iFKp#D%?a1TP>LY3^5q!4;scoqelMt*5-i* zUeo3b{Nt1_koR9(Acrp8(O zSBvErdX#r+tH2Q>lwVKL_*G>w*A%*`kXT5Dg9qvEHe zP!1%8f-?vAgSRa&$+}LhP2aLLtiRU*y6#Z^^Q+NB{q^-*@(_u1v5c1l?Pjk?MFC`0 znRCrHPqX3P+`%LGm!oyITDL6PE0cSIF4Xbql_4N?85S@wKQ`A|F^&R0vhhh0H<)@K z7-a)0}8R zHLaIYVfwb9a&skKr2GBZs?#Y;KXC5_Eju--Z(iBT0t}kz^5id5Y%T*dbcyi2DI6rZ z3KHtae7R@Lggw*><>wRZO$F`Laq8C?DHXW)KF`ymANJ0pcMNX@X6G?BOWg{lyI7Ye zoR@Lz(>>`-2XlfLrrm|&wQuXc7yNke8>m*D0L#XmF(ik zxZ=QGDDlR_-MuE6uL1v&31h@O&RiN=X^hCL37dtjwCpT8A#hANzfxhF^ zphCN!@7vO-z)I`Md{Hp#?L z<~(htd$jNyck9u40(1lqjN;OUQEVhD!wcY54XEY7#haD425)*8JYN8nyS02eKpi>1 zAtwP4tpE9yP4$8`qDQghfm32L?{utA33^5O#s>n5o#2AT?}^>xdG-p=&Bl#Ux=_vF z_Z2ciHguO}=sr(3T+nCH<(~<=ee8)>`eoJ}(lGPxM7LA9!gHlE`QmwQ_wniHfY9=( zQrwLW^oHk6z!L4ZqGwU~x~TsCp>QQL`QrL&H_1Z=ZE|mvh)QMCmS0VNr*r0*;{F_XPy6acOk-95Giwt`v$MTS8|+d{_T>91SqtV)W;r8xHJxz!a&ls z?~h6`j!V0si&s%L6T?lX@45(R%e>R8MNO8=9o9cJU*oJ4C~xS0;1kPF2RPEbLk|ip ztV23@wFFqcHD=l04<805f*6zq<`ovn6DC$B^==V{K*8n}$$Sq9ym+0BgY8@d-_&Kq zKaP#7wmmC35`C$`(FW_}rCWKYJIE4H7c{*tV#5eszZfA{mRs_bs0|}jJafrKk-2i_ zsWHhg$*~f%a{q=3+*5&>hTv@_Nb39h?ww!XajY5S<@owhp%WMuim!ZWHzK$lP`M;< zL++0L<4EJe73mTkkRaX;EBmyZ|4Of#ukFbV0+N7&V4# z4AqVBVtsvyq-t{TulPLgxa0fgYkHHW5#UkhB$e{4lq@1Ozw^a&U1ar1qXjeInZe+x z!V0>(WhDc2Znpg7&Z|2j@?VaQ)=4Dawbi%|qBxx-aGhAd>9dT z_i=DLReH_fVHeOT#_PU1CDvaq5~(p)x&sXXpUTlWveGdpHpN$L|4gU;JIUV^kE@83 zb`_GmYf_kRZK7SK+#5mE+UAvvSHO}Z&}436N?2+iaA4l?VbFB5VeNfJ<6>KMF=#Jh zbMNJSv4mD&BfMVedHJetU!C-z=`7J|iE%o14!gXSg=RZ_hK*ho;KzY8PS5W&6M_C; z{k${N*)La0rTw6+p_RYS?iQKN9UVF^8o@BLHP-GX?(VtlT9Ncg&jLxTcqK;6iomiX zQh}n-K7+_7z2uK6Gt_!?duk3OX`|T_RravPC4n@oT^;9waZdv}r90380w_+ipZT%D zDG*OzSaqm?c$x)-ji^1jVFLD1v!|*j236&bfIBKquB(xA_u-yezFcVT#wZ57?sK3L zQWdUm45c8?eHCNzG;+M@yH_jmaCfa(gngp(vLUN-G~&HmNY(h$xk=z`)*8i+KBa4N zcYvdx=>L@lXkPBV2lKy}48J{|BGsx^h_G!6JEW~_`|ii%$(7!;Ds)HHK>gzTQ${{Z zATpZonZI9*9%prUh!(j1dXjpFPl7uc?fQ*QO2y@?PdwDIQXgZc>XIAZfOdh^bEFY~=b`NlBtZM9xy|O+-^4|pS=^Ke!86Uudn@g?!#%)gCGRyO8+~mR zWaLhoDZ15E-W|k}{4Ek5Vm>_x%QVF@4_sbF9S0%dH1N(Cn+XTRfCbio)2*2oFDD4x z&0Kl6=+p$=Tn)5wJj&=Z82p2?bhYGrf~~ae8fk=z5+8O*COb<7%j&@ms6I6$8cJeVv%{`k%6)g-w1H;mNqfK+F#0M~3j*$n`I0@#-1V6S# zkGjNsmw=l~b5{DJe7Qfr^g}UxlW2A?WA1;5lk(S(H@6N4TZhCh9`jdsgv9R@_5>mo zo>f2H>v@(;F|pZ+Z9lBP*7>YG$m?ooWTf$J(IgoDY_88CUxR2q;!ak{an{?;(%<{3 zGZ&Hm4vP*E`cMPX&%Uz#s|i)qUS=#A!fJML-4e)g3GGA^TM^UGa`_Vx8Yp`-$7RNJ zsFd}RQrqduNU5Tz(@Ih6rOf$|%TPfAo>%QFXprk;g`}Xmb>OIx0y9#5YI|SMpot@% zyLzDfwSQBXu#EuiC%!YG)vl?+TY^d{k>p4`;?}mWbU6u5jZ7Kt8xx^4B88`YmC{nb zcovbdRKT3~(hubDM0YwqB^eu5IDi9|FEmqDzAkNbOoHP@+h-4xvg_9z^N%+C8us$H zba0?ls6^a29??NBrnOc_%@D07Kr z9iAe$t|U9(=JIO9V*aB^{s1AdG9W9AXO@oO5OI+PeQZKh%0p`;dw^w}Zk8lMGDD(g z(yCT$r&A0Iv7-d)l04h^BjlzWgk^ZU6qWC63QLdNhN^SoyWKQIU?~3m<`?}4NOs?% z7ro{c(m=pgKl&($q;?bU&9Inzwp8=A$bHZ#)J)}FB6^XzH(p!CTlo<<+;Hmt*)(6h zCo!ynQuLVdg4A0H1El>*TC6yl!J4`dw!wI3z^QScNHbgt!07c&Qf;XAn}^cPWV6** zpP@!pUUUHo@kPStjUb-pgzkfgxKeQC2wDiS~hq?>qohQ2CP%@$rAN}Z# zv3ng0WV1{D*0*wUq9(~fgs8j#lIG59EF>ks9c?uCEGl8&?I?N3Ff2L1*KH_SSXpR1 z6lU2JP8uy6E>vX;`*HZ()h=rRD^iGHqX;33<~tkB@z_J9>0wq_`t8T6C}NAle+8D4k_)ST0gF#juT!gV-Jr$ zb8wFwi7S}d3*39>=BD`NF#2HN#-|X!fe&6YcF#A!=Ef!|hi&5ceLj3bw;jfv6nd8g zJEX0o{kmR>AYXYv#swS`IgMqtn>*h$>@nZI_qOhj@_u>TveWfZ&-!uuq>n}Ox05%T|Hd|R0O}%F0XV*4og3dN6u3#vin79r}82V zwwXJ}*QnXG__=X1KhD)AjD$9fF@s2@E~wl$aD!1-i21Ad$DLR-D-%opjch(+O76=q zHM(tHow9H!0wNY6LCTtNZ!1AK7E0>}+P8UkM+HyIpjJ~2~sE&vuN zS0nQk!a#6Ez-!jMXsFU;h*D<;Qlo^hYo$tp67?sq{omR3H>%CGs6*&|;kl?jlXxzn z+rp4|-TY2F#e}38@CpGfZtg zYMO47!n457Ae))0q+E`v0q~MffkQjk65x3MS`YY^Rj`ESMfOqa15-w%6W?gdw4Z=s z4f+z!(?EM&#o|ocyu#vn#ST?80?o_jG4XLG@kr9y63wK^ocQ67%R^6a-13@N{yDiu zau~vg(nW;=d}Sl@x7K*6@cz{H_iX;8sY-_xuPe1#q)GD0%i-N1N$U7(x^`L=iKSrM1sfUbG zJ2Db4q#z;b1F0cUp8Q-cu_f}PHebz>m%Rnj?%Fe1R@5HULT*QhtD03goj-8>Zj?79 zc%MxBGeKQGxZh z(R$@e3UjtiHuvG)3Wd1bHVaM8=KB`$F8b}pYDhuv+UgcOcWn90PlHhXxD(%U9t1L& z-xgDS@XQME){0QOA}B|PDh$)jwxQnB{Bp2UN`hBjge5f`t|s9fZhS#=;sV`U#Jq@u zb;2+`e#DRLT)uCAZGg6Ej1=WKER6QOS1}UmA0^;RuO0Kjk^NJSBh9V* zM{#kg2C^AefpL%V2mwX-%Ui6sTKwJP54)~shEz`K-a-!Nr8= zyZe1pwdm@8vudUoRxZDJ^3NgqX{4jEC^bpl8V zC;Gi}tO`jSBT6NDF-I;L-eKXo4a;OlqS+$Z37&gV_i|(Dy(qXHd8DmZuaZPVp7U-lS&W&-<`#Ut;Oy6Z3fR(j}1hX{7$@ND~mn&>bmmg%gZ5| zte-cPo!&0xy*|dqQ)t0$(ZV+vx2{AwPqS>^48_$9kNy?$C_R+eSX6qzo!R-3-NRIhp4l)(h z5Ma-y!*ikrPM}ona%`+(JVb6aCiI&Xjl^wDD^^uA>nL+~9YN+3^g(-*XtS__A z44iEhd>{|>`1KpEPDc+1QhJFaJ8d2j8wC8rGJ=2rcwg7VWTsIyLEUfbKTQ^X*aGxAa~I0%wkIW}0) z4`XMedV}iMmZ;HBsL=&iAz>t=6^LFP?oh(l?*wVUnul2ni#fDeMie56D42 z?YPWmuOeTN*Pib7bH`BZazg(QK4qW96Z{$-%ry$`<4Ro?&SY3Gy}rk73vL1#m~WQV zz+wI~Dq?CD7mzJXZK?fEKLa_5gbG=$ra}ND_>i7Mw2J33ZW%%Z{btc;`~(hSWep&- z(2te?{A061^-Oc*D?1XuRnZA z?G!%FRlRmHhxeYU)xXwt2XC=+g`~JY=~CO#+g7eLjhkVz-k2YKSo=vF;C3sg|LSQL_S{#*&8cajWha*_h4RxcHYAty4nK@Dg&Ein3zgEfgcH>e@a zBduuG5uC7l$KKuSho{|HEfg$0k=o=&^U@DvlS4e0n=G%P14^m z8V&O53bNZ={@!_Y#o^e?+}I!bTMLAmDRW)5`vI}4Wl zKINnvK9irnAwU@goCHz>XkysPeCG3h?qNDsu3r7yXZ8bb2U!$rVoo+^|LsVDFCjoXBaE3?0A)TyolV(W%p1WQmcx}%xl`z8+zacH(#JA*gIY<(;ZKdu$%gM2^hfuUzw^6r3KC|3 z>@3(v3iC>A|CwM!vm*TjDXn~l*Bg8KdF=oyTyFyt@G(o@I4CiaYTX8kgfBG^+AWrKz_?9x-ueguDj~DsptX%pMXDrjP6lbmJg+ljQt`tnLsJ z)nv(m*YVY_%@&+Txw~)TM;p2#$<_AA1P{Ud*(VHRi+qzft5y5^=2F5G=M}0dA!Dr` zZ(hZFFSXnISq>S|N4#I-m#5m_RbKrJiDhr1RA~fPd8ueT0TXXRC-l2KZlE z{ZgYKWARe$(MV0T5x)UfamwDE?G;{y@aySZCDcb>P0|@vHiF;fLr7Ppc}}Yb<)K+6 zssDt@`lt=Qo$sXvNQKmQp4LCr)=yTYR@mo;$v#wfwEh<9Cst=?BAZ{0^oHezR5^!U zJLArayu0ifs7by=H&z4#SS(RpAx2f$=_ykk+FIuwoK5tS^;Fbi)WKq;{a~HBawsbj zz(UtiwR<0Ckr}NIb#o@ zbYIBwxp#A!4u)%g@}$3H<{>i>4NNJ-UpFj#f3sHTA4h>0`0+;c$wzfWBUa3t42A_2!50 zee0wAa?O3AYll{AT+=vNT+(IuAiIyPnMtm18z~Ef zVR^MGXca*@zw~)fWf4-BgSKOD6{qmr)ng3ki`3{}25JN^gHp^>Q(NOP<&(^#I1FFo zW*&ynZU~Z$TwXsO)U|zHVI*=xUk45sobEv8(Z0&vlmFitW{$R;H<-vv=avL zr_lUB)Najdbgb-f`p0<2%@QQr3sCE#5K4U5f7&{^q=B$K;Z`(rwkrLJaWM+1n;N0d zRYALU`(a4MArybYS_uz3gGY5*aM^v&@rXBz7huLZrKlKnPG(r(Dt#35KH{oeZhtAu zqdx%4)|u_G(7=UhpbXHJT^Nd=0kbplL;TWQPsK;}dUr8SRY)mwK~^kUlDHI~e)ZIr zpzRpiWCq?4K~@N8Vx|;eoSadE${sQQSXH+I5b-VCZGphLd*86uYR|$9bJLrafh~t< zjk=o-oavp@%2>Wu60x3}5h+tT_E?_1d36F**cx6P{bYEeIjDuBQ}CRBeEN7rJnCnx4IdgFTXZG|Qn-6^tQ~yD7GdAubYSPHUW`+jZ8% z`%wQODo6iummG;)RG7Hx#fOYA#Ja2tCCeu;87ppcqr2k%VA~G z)Kgl6AlRw082&_B6B5@Fj|&q9^jlRGeHdVU8&34Ui2-M%Uve`G;Eu%B z3c?23d^7wIrFnO$YrJo+ri4v-fK&)2vdg!_kL9&jXZcYA#p=jB=v*|(5Idy9 zH7X1vzlWiUxMf|4ZAi+}NW^I)`z9u$kP|$(?BB4nPX*0kyx=JqvCC6qh>Us)$HIQR zlsZtU7O>uFr{1npq*;-Fan!{XPa8-vtirhP3=6r$c2)fhED1r+w&NiBKYk$$^4B>V z#htSB7eMEfyB8aOhR|Lsbrv}Rs;^3E*3%SMeu?J28M;M&CAUWyMVlrE<@A1hGJAc! zH)Qn)X^l%Yr?gvYcA%5Cbq8tA1aiF9LzG4d5RG_TUFcitSFO&7opI2w)cQEtbaOYo zQg%|nBM{8}NYoQN*VfLk zpR7VHeTmmq+0MLSd@0HN>i`(?5XGo}h_MTX;-d_svdIJG>_|ZtnV(`jgzYEVHX$!j z8|(VoC=FUoOgA0#t9mJT8%U|qVWHB(S(Z8_Y&vp%#Cn$>B=F62;c3|p3*V)>!>L*3 zOa7A=*xHO~51u(>xu-V^MapImsItZ$F$PfeA~hp{-yj0BqK3TkPk##q{$@aa@e^3n z?XAHF9tR^TW@mcc|fH=hx%Z=621WMF^(pK@4!g#%p^Z+ju8*%0=K`XD}7|2-=ZN<|61uWN@gOJ9bnm ze5l((E^r~VhzXE4JK|0ub=2Zc3&mR&gBmiXWk%uJf@`D@F_Z+xIw}Rqd$%mg?GEeg zb;cu$kU&84!(xoCy5&Tb3}v7Kx{UhE>|ryg@ybRNa^o`9=N)rR1=}@_NCy|Ldcja$ z>6HhaGZRfSG~e}DmYAAq~wJuPyrn@(lSYj~g^axa0A1 za{TT-Q^2J#q+O;(A#DRH5f}2q)B|mm=WcR|RCBh4FP7xc=~XX6vPY1V=s%zs)b=p? zQTBXL3zpn#0-43()|cC4(4}W|Km8M-gtwn?3(S`1x^KSHCstjPs}V{@DNyU zM?EjYEnm9}9k*0IF%amZ!R(V)b^Nt;sirbapJ#?8U?HCQIP5Je6BZYH4`e~RVR=~hD%Ram2b4GL5&_DBxms};OO(Kl2N z2(jHYNsCoBqq?rde1^}anjyQG=vDZAWBM~ybi}xpFY5)CZpJKGa7De#_hGq`)%@K1 z3#U^`p(y+=BMhkUTXt?Ln)CPeB>;VZ@-p|!ksFAi@f!!aBeSRVz$u=|Nl)wT_zSgC zsF`QgOM3#Zk}py3G|a?eiF4o3eR zpC;$KFc$H<;hp*!DHl+KAAB_eQlQhUGgzyl`M(~#3@#Z2Km-GB|8V=iU%qR@TBd0g z^Z)a~a^S&&UiR$K|Fr}EZta&{?)`UbKfB1kUi&v3{Oh$}VD(=>{({Z_0`lLu`ERWK z9EwZ+jkRB7#eZqkmz?uohWrIL|7FNuSopum&zE%N-{j~22YIa+a#z6JX0%rLY7_YP NgRT8ZqK)T`{{wCzeR%)? literal 55606 zcmeFZhg%cf7CwrIijAt$gdkOrDoQ6H(g`3%sUboHq=a4s0*In?P(V7wLJ?`A5ReiO zDN+Mcf{FAdgdR!=?GDQKo%6f*{ss3Qo+oCQnZ0MvUTeMYyVl+qc}HLK{2BH$R8&;w zwYAiYsHmv(fR8=xN#IOeqUtp&s&mecw{PFkzI~hfj;EWwql+CCl~&{{(^F=~ZI`kw z6JEUNp?;%vy6*Ik!XyR@nqvh|VqefO>6|-#tJ(U}MXQ zaE5{Wj@opreY%aWsH*BAmEHS;n%bJvh&NVVM(%rFyY*3YFz(4?k0D{QPsJyvZ~da7 z!bA$byhNp9@>?|jqSl2+Tus$RtlUk`7iD!Lx30QBXOf}A^R;}wf}wuQ{;K1Z{jt{` zp!u|CwIbi&t)8}Jk%aM`RPo|#3RS$4LSM$S`O@Ft_+r&%TZM<>p{y;(k=HTfofM9c z7768)jGHm9{Le>Oyw?(Fo9-qn>yqmE#ZAFe-%d(@xWmp?`W-a5;@jPS^+cZPFVXIZ z$h-aQ6JSP|xgXV?s5@L~IpvzM{@108K=)M^8fTwt+;TbRQ6(!QV3CXce&LxH_w&LN zSz^Lte5x)~t4yIHBDd^5>&f4=o<3XLmGsG6cu%gxyQj1fciUf|Nw@hxJzu#DqpY%xBEe&~v$_m|T z?h_QEjWq3U7E1Uf`%206%JUtAP;KQqyG!reo7dljO6%j)fQ{o1P;3Ih6U z^cW_!nvKU;v~FEupb~s#|4^fSEP~aVS%r~&oafk! z^VqX&moGk6eSe@>bk{mdWoGQ*_*l&4l?xM!3@1FtL$=36RzFrgSfO!JJ6P#{7JF*4 z>zSV9{_@6cd@1{-ezn3IYgghST~~B%StXNLwa*FSCp8{%FU4zqbCz&%t)gF2NNP0= zY&2Ho7?&JB`6kQVA?ji1dd=0=C%)f7B_GsVDk~Zg-1&lBPfn@$evgrI=N$_RR8baD zqz%{%vp@^Gs^3i=^*9iH>bCT}J#Il&qm43k|I_f6)XmE`6vNFgRP3X{?PgNXiCtV= z+at<58S^9?&_*3Unnod};=W)R$&B~jsnns@ywB;(#piZRCwdmCNYts6tqvLUOXa*3u{oA_Vw8?rK(o_}tIgZX!|S-pYKb8j zGjjdp=oQ+@M$=(cFCd)HojZ3UctHKD!_qk1eP?vf@-LtRctvs$Y zSzv^pl!pi~tg|5dl=_(*6l%`Gk3^KW>cN3hw(%JR5I&@)AZ zUFp?QOo+^~!1G(WsRy?pmwdrI-g^Ix~Pu0X$YOz}p&F)?Ae zc?;2F_@2I9^<9seH&gnvnRn{HdA#K;;_kiO>9JVn3t+4ZMZXj8wLW)$p7pp?Yo-J! zCbrqu(M&*~dFDR98QZ8sBgwM(_b+9%IyLyD(@NZCzLm z64lcyLaP)*5T$sJib5xBKc&s$f%7MjTym!%mb;XDnNQ}0c%nkv-UURIDF5RGt+u?* z{3K(is}5JUgxm%O21NUV23iZE`)3PM3PC2y`TJUX$M1&EtJoO}8cp|4_Ye0A%yZ6L zvd7xrKAV@@d*)$>=zqC)A zvFYkaAGUZP${~urWa=Du@7bVXv86>F-Wy@MXtt=hXonB1z&b1AuFMVn4x3x?xiq)X zBbVEEtMzxXw{(^!OlwqI`Sx-@|2%%))BCfJuFn<`J-_*T?zjJMexe?(uty;e*WJJ> zeU6SdrR<4Egh%44;iwuaSG))I0roEB?m^vG+NbxAhu(_(dh993NznPU=Qhvfo)?}Y zo&&LtYtU&-#^kXfB<11#N~(Tg2ecy*35?+yziw*8a>h)?I^K(wsm5%;gS4# z-?Kf3kYvN|l8&ezT(5FWVH+0dfjmGDE`i9W$R^~~9V_CEu+WfI5Gwh_C1gsPl>52;{KLxRB8- z?IVpvoOh8!tD^_dTZ<2UZ~1QfzVgK_Ms9*P_=K${>V-g+##Y z?>MSxD%Xb1$D1nl_XEbz4V&B~Zr3|@J(Kr4?gy`wj5&w|-jj9)5${ImM%jvIbVrZZOVfbJ_9HHK}dG0)vH}F{|!4IogK2_q(gjt zs#B7%PO$-RE`R=_4l#>C+GaScJ2IO&T5u%ufr29?hm;sAFsl!iR`)vN*FNs88lXcN zSvUA)=E`3w^E9zc=v{d0Oz~{p)F~2ft%l~Ou2iK{}%<+D4}r5(#J zHMITO7=H4Z2Zf65zOU!2Og!KYF<~_`GaQl;^~aCT;rp8V#Jk*6%e-4Yzg>BYvY(Lh zm&$NR!=@_}dtC+>7QJ4`v3aG>T69BiRC-xA)hdyMNM17s=mxv5^CvAY3&!`hXdII_`>LWeno6GdA_1vh&Fuvpq{xOrt_T(F`zwQo3gp~ zdyR7b9>+aba=BsEs)o8&bEsZRMzU)_eOmqYeDav+O-ns=vg=-zUisqYX2fE}E9qBu z3K0rt{1k`NYClg4qEH`v*%pO|H~cFf`R!zrmGTQ~3qNeKFGCGu?{yT`Z0h~;vkUpX zPhrnbUp&QnN{9Z*)3vAK!TJZ=GjHDC?g|g0!|mGcb>#7`^YT|{Eym!p>)3qB!Sv7paoB*t)nPrA{0NTdn)i zBVD~n9(Y|SSo+LbAu!8pZz49810j>>I)b^mdT$4@zc}mXxm=5}d{lWbQo9qj!%tt% zm85hd*lfFIZ}}9y4j->{Cdhlvqj55jvoaf=behGdRfI-=n?a`fP={Ee5^Z{G1Q0@+8Dotd`1o*tDja7;@@bBvwp1aNc= z_<)ab{Cli%>?+mqKj*2bsKOnoXpZjD2fhz~UI3rNHh;g5Cp@P*1^mVYd>*}~{^xG$ zyw}J7J+=p~QQb1Wt*s4w8^b;A>|DJbx_Mixo(up^oOahT_oAY@#DDlXrftNx0`x!V zXkzAVrU#LSyCKAE9=O@si9JHNANE6~_(&c&MA&)Ta6dx0xO&MyQsVh@hdgk6cv_r? z`_C=j&PqIHdUv>QyLsAiON&W}N$`NraC37jdOon1H&W9$Y7YFS#PiVG+g)B<+|SQX z%uh#|pH;49D)S@YAtG-X|S< z*%8j#<|}5UzvZ@YK$asGDWz=HN;zP&M-w)8iZ+TIpqp-sKS|2Y*v>EWjV~?{yz{w&q=7JL<8`bN96JF6wXoaKE1PX zK{@i>#g!w~kH*i!s^V>YmlC}kTyqGnH3-K&-Xq9pC_jA_l3xdQ$Q}*{ufJ(7gze4S z?QGS~Dn(b;PK!D$IYVz#Fq3f#$yY$TW2Xdpspb4wxxa%#c2|A!?`QpkG0az9OJsdl z&D^?iA@58d36r;A@E7_%x>29$3u4Bo?p=di%rpJ{!^`Y%^fjab55~s0;?G|MS~$Yq zbnE|Z;VuNAU@pXd+%Q!b;^1*5@GsW68v*z!1$BK^(CD3)g3jmv^8!)=z;ov&mV_bO zj{Nv3!DRAJK}>JAfl9G1e6&4eB2qAUuh*A=37C{XZPg#_6$;OkcVU&ci+3+xm->sL zp_5nKzuwTL{$?NpWi4r(mW*g!k_+DajH+`#*xQ1!hK&eIBWzDyc{Kj@6lek6y4`S` zz6gJP<~F_34Lm3)wkwzOJ~=YKH~8e6!13(BCC3aalWsZ5JnbXw51r&5i$fPnDR?<(XdzWul-VGLnnK%-JYh@gr(F^?_?vI&Mw?R&tZ0! zEEk{CHGV9%PA0|)DWqL4hs&S^X1#*^^v&291Qr3k-bB{aNbnnG7zaJ#fWL^6& zL*(h*mt35atNF~N(xXn}x}!A|%2ZY5~nwUHN)CQfa;Jf!g=fT*Q>Do29@ z5x&}(Y!E6Dk=R(yZ)^T{#w3COmzgW=O|v(9MyQ5%>Sf`AEv{%2gds9PS0c%H*tM%N zk@xX}2&S?#eJ_6K{2g~(_+wZwJNoxbDtdd(c)6DJOc3*^Y4tmAyhweI+5)#Q%hR!% z_iV67)rZcE87J&Sn0ian67GJl+Zw6awY@+`nTR$fGQr$= zBn4;gCBlL~-00Ljde+m&jq9?5jj*C3HQE8)tuyTy0Z95JUyIouN^76-N{U*l5OZw*xBx@w^$`<^=h5T&RlapHg$78Fo-VYz|%Fxk{R|$2fCcGdDGW88#Cw3 zP?e!tobp%6Xx-ACZ+l)WNq-$ z(6(BC02;cw)}aUTC5r!FtXRUF=i`vT*}iG0ys=#?s1Qd0w;PB&`4p^?v_F*A<$85* zfD+)@ln0t1tD4jp>sliHM*L?#VXa|j`g8`4tU4x3dleE7&+^UYZxns<>0-9G?`Y6g z@qFa%8$7gySNY<9N56JC!Lv67Kh^|Z@43xVVSsW(ZTHwiZ9C=T%Q-%u>GQc!ocPxg zm+65ZS}hvTmm21S%$*AzVt!292H?RCbxlgn0vH(ZcKsq_-Izxu}+*bi-KcFN&Did8=waQrFpW5@ngsG*LBaud#(`RpGmV3PF* z;y1CLhUP!AHSbWi#`?Hl`UfPm#-;%HH`r%lIC>ZmSg9w0cfK+B)%-u5CknonP}fJ%VL8 zVAeFT65#H$M8_llvWEbM?Q6aZ+-;*Idc^E8fN347s}AojI^t=jR7t?N5Ej$_4U&dW z;(s&wKcD_Ap~ zCY?gyWjFs0OFABg(sGGst>x$^ZC?wOVEFec1VO$KzU&K5+*@L!ySYoyxe2G`Sy{!F`iJ0eyvtr}QnNY-89$(Y z!xib@R<4HJ*bP0!W!4;fQpwa1ZWC-hTj6L$JevG`tp?6MrLza5rTtBU8?1J#ZW-#+ zF-h53s&U&M%7&`?(#ee+>~D#KS3>DUCc7tJZaOu*>;(Hl(n7$3?X#xazkcU6efbs& z7bzp`zM&6#Xs%TIyR|Vn*bjo6C^P!&K<*^~8_q^~9b`cPW-Yw+=-ghd4fMBYOPCcqf%BZo@9VKkCDH?}lgPx(KI3>kIUP zSP63}QoyUvK%k=W!dD2Y+-@s*Gi1Xwq(TJ}vQrtd(<1&rQrTBJk)Z(jvQU6Bp@sL> z?>u4e)0*b?v$9}6y}{fUVlL<#__Lr}Zq&0wRF}&Kvsl$?wEqmYUomYGGPX17En@7O z{bwNVA~gD|q_eF7-AIggRmr_mr~*aj4}0fST@W$^WcR1N7$Gmt;A+Qp(#NMNH4+gx z-IiQVQUQshqY{->?6D|UoS}=*#N;8ml~xIzSvNT_Nv{Mn9Y%L_>jTD7m`#)@{n}Bb zv%#OKiVP(y2BJ&71RuX<^OZ4u8@p?+u743;9N{d8iIsJJCPZBn*V`d=a4!?Rw~lYF zjF!;LK)5I!AiA?2sR`KzX6%P&O-YqnW)a?y?j{NA)9a0{9;%hhlgB{Q^g0u%Mtc)< zq?ulc_;+PBITZ7OTd86@tj_galM9=M!IZadmps-+@l(9K$Tul z_Vlm7*)G|qD)kQ+J}>#YrIY+|TfRD<;p{~C9x2Z?jcGaS774b zI(y7!`Jti3?Yj?*XSyesY_{C*YUb_T+vkSJ?8nVX&o&(dVz>Fui_bl%@$LIUdX(Kt z*3OtQ$7Zzd74@3*Rkv=zy*A7CS=sjfxaG(50J2CY30!{aKJht~_KP(;vkoDmYQ0iB zlM#2O&!*MOg>_#u@6LgS%_)p-cTXRrCZUTXnnsr{Z`%Ig0#ZcfLC(J9^U61y zm1)r0MViC>BYClsM-XAooI1MoMUj`bT-hCqy)kgZs=v@JfnN2)J!pd44!hbczvQ=8 z+IxGwTPt7sb!|U9l_Xxqqx5ZKEDZkoPCjY>%ll21vvK1Yn;Ehe;(zNsRYo+IOr7qx z4vUB0gPf)ysIE#sOcf(>o{X>W;OjRajR_yN_cxcwDE_*b;^Ypz)2y=IOW@JFFppHFw z_5NbQ`oNhX#4{m}^`B>yDMdB8@IA>C;Tw*9n*-T_u^{HWMg28_uQjm})0y)_5`h5s z5ax>8o7~v_F1lzO;k4>uP2%;{IQ|Nlgzd=F`<6ikk>Uyi;);gK5joRtcDBw=^&9$} zl1R32@b)-)cXTPqx&G-#i*t>ozJ6^fC?`AHIo_bWV21DSl&@n;&q`o(e1khH_Eq+z zVZZ0IWcJ)8l;^j3F2P@-x6hkS$i{ExSN~279@CuowLL)7@>Q93F?Uq?uU&yj)Eo;_ zBln`5d?DevH4npGixeYJ6*V!7OE#sbb;*drfz$BZd(7(kx=p}jNQ?lxZXwlyYpv9@#GWQuQ z@8qqfVlK|s`ffUwy-$>vnq1~eCHbh*14=3E98Xk8mB`6nba`E{QMjHCYE{yJ&S>V* zAuxCB76j!iepvegaSL9rC_&8QF;|UK;xFBo67LR#eh3l(SrT&H<`Z1m2cN%dEyro% z2f)H8w4NwVdQS7&Q9)B40FQpthw&s!LC@XVWI z6Rb623H$=j-J9O5ED0(u+>TMQCk&N&?iLTDN3E?WZ{v{S6*zUvJUuLqsEhjR>|;eh zmk#`XC-CYj_ud%h8}8jSfQZIVGlzGXO%ciqf=WdZS_RG>#1<_mrwryZ-glR@5ICH9 zUEf9A7YdySlvILElofzJN9qNYLb8r(!ym-~K^gS2t}~d?y_oj>Td{5VPWfA9VkLw8 zqnj5)umWfqhl$o*xq3u*u8b?eZN?BzNVTYR#w=c&9zxekhH&7nZFN7ZLSxIStWgdd zcIS%z>Dl10=O0S&(TMnT9@>EY!4zLcW+BszYP0!-_~sPMWOQzcUWJ&yONJAwKlfKl zZakUbxl456tdBF^D=+n#D~(G*ib%G>wdZ*EbG^uk6!zPgme^(n%@1W2Rs_-G3L!tx z6?3ODzU2Gc8jrNNN~Itul7B;1KjTpH5=YO3l@;6_mq-RV*F>YX*D0kKJd9X6oepwN zWOXr0E%zx#k(>IF8;D65%kAOnq%vD)7vj6j@+B*$nsfsK-T-O(LmvS)O?U?XQ+RDy zI>d4*g_KKoV|r}br!0>pc#24B4`_mfS_SAVgQm0{KZ_(O`+%$Z&=t9D!WpTrCci*h za#B5rvK7#-d{nl$&wv1(ZaeELZYbR#Xu%A+OYFV^#|=%jx*+<9H3(cwJ|-(fR1lOQ zT}H+YJhPj?nNuW>(h^@_jbr%Ppj->Ok=JcvRmx;7qe+E>#fH%`AKF^5k08N=T+=5@ z_O@Esh?62^ufCxdnOO)KSToN3oFbNKuF5j-kKimQPTK2XYtjBxAiRiJ6AQx`a5x_o zz8L_Uy^wv3IC1Owug&wyPwcbwP($cZG&EKZEGYz^{5E()0L%n~x5aNWo9-BlR_GNQ z018VsW`iw+V5+d07yJ;FiY~QCNge7R@N6lO4jQZ~*Bdrd+$eA+TvE+y@ zGav9AuLlAmE{zatjf=%?nztHY5S9eKldvvaD!Qa)0Lf8V65rnoF4%m9EDrZ+Zxa*? zD*9YEv|d?~^_Pd-(*Yx%ve>FE&@`#|Hq%u-h(nHy!TZ3Hj`7Oiwbe;yf)Of-k_0cT zp9$Pptw7^SV&7OzCIGt-QmV;Dak0wM`$J^EGKt-q`kk6+v*#WJ?2s&cAHA2iRvrAF z*Uohj-#W?xht^kMtqDGuPMhH&BHr?Ev7B^RPi$b<b z&n-p@!#*fPlT&ZN53n5>~Bf}}+Vr7sQ!>qn z52bs>(Tf8c$i>WvD~NASY_hv-M4646b#;yjsdx+5odS;n!i|(pA?Zb{!h>xCe8>r(?nOrH1+`b4_Yulh!laij z3b#tftyP=sn6o(iT^Y=z1JFEsP~L554(!$_WNJCOzM7A~=U5T?ck?Lh8OTz-7Tr$& zq0gKCgT9?#5E-5>%eCDWz{)^kY1~~Bd=VWvSD~k{P+g9=9JEf+*@-cPJ3+-^@ILFm ze35@BY4n{(nFEN`0vL=?8eNI|xx6#24DM)ON=50$$Sui{9$R`?3vBCe3w+|1y~R?|M|U|X%ZYm0r-=ndng ziegN8a|Fm$2V%!UAGyJg+Q&6BWK^M{Eu|Z~$EibRGNp_4GN7%lJ7pq&h%+Ckum|W9 zGi82L1hSEwZ)cr}1esN|+XQnTv6RBZl2K;l3O5ERduTf*db)7veqpiP(aBhsyad~E zBH%nJ+Vyj8S-E=ieO#7+OqPjfPf=V=Ges~fV;0T`ioso+``jjoL#xf#FBRYfX01ib z5Nt4`EU$_8h5HsIlLBDrpcZscQ|Vu+-UlG1QhtTCARYe7nmrU@iw`y`ahqA~&6_R7 ztVb6weh3l4v}6J{Q6Rl`&FJ5}wSz~C;=qJzd0&F~G}7elrbjZ8;78C@C@rJt?e&zj z^dlFU5Au>y@u#-YwI!(aTb*V#^QA!p=m9tDKRQuA94Lll4$41qD5}xhC@+*mfZgx| zsIryVx}UhzDR^I;=i0zT=_DGSV+DVBTL+o}yO*qdv!p8Jr;iW9MHIJP9@Jl5?g*a% zNIHJ_0&Z|?rl)1Sy>1ncF>)oeqBe>*$Xa#71LcLQQ-#0R&|>k==FVu=O9MHQE?BZ6GqsanQpovF{buY2P;e9X z$|7<&jX+kX^(q%JE%|gXg1v|s;v=DnFK%ezc`nqY6q~6#-_k9(Kg14GF8w*k93F2n zc~wyQ5{wB`Ms8}F+4UT83|EE=qB*Zkn@t34lhJch@a8;3dxnd`$wfKY(i}2VH2*-^ z_ttPdm)(l4>+a-4`Svz=AG#&BVtKo-1aDnmG4gkDt}_L2j_WvSH*`jIf!o+r;NpkU z8Ind9>)o(Bd18P|(o1dv)tSn$BBp&lJVPRSwRKQ(^4qc(~j~24@A&>>RJD| z&TH_y8T<3Baya}c4@b@HBxxTyawE^AGRNL7%+_ht@o8}oKPZDT8yFB==M*xf-T72H zXZ;pKkCB>D01DeG5 zTB5GgN1e7mNoH!E*T9OSMh}9|8BHo9^QZtc_`P5{CPiis58h)=R77YOyEn$uk8_MC zrk1~fQu4(}5adL}6+`{{BxgcDTzmZ$Sju&xY>s1R8n!ZWRnUqoY6v+ z>q2CiGPZ4;vxi19nG(IQvO;}=;EC(jNE^!z*rpu}O=;EWu8G^pg;8<~z4AGIDqzT_ zF+fL}zzK@ezS(KF@o<7KBBN=rifjRllhE=vNxUor;J;l7$gP%WG?MCU)zv3GJv3;l ze#`e(WGqUN=a}UQJ&H48h9l%6RU5B0kITwkx^pSXr8>-q8zrIUpmP4V8(6VKJ^YtY3JQ#P_l`-%$|fj9)8VvBJwNtOHO8R0WUUl63AHI=~47WfQSO*W1=i9k%kWt zD4tmPuFqRVe*6G?zA|H0-h9GA>Qi*vtxXf8)0KN0iVQp9(*|eOg)yFU3>V+KukCZL zo%SqK<5fxBREH<`<$`Z{7)k>6Q4=3s zhiv~>QAxA7PQjr2&V;6X@ZK~3i848m3#E9nM_N_f>#ODmTM3d=tMy5`kojGPz@$EU zY0~SU_B48*oK8te@^{=*x$C9nZ^Y*rzomuX^Pv=N7tw2wH#P|kj!a|O_Y)e>03s0* z*dvK`V{0u|#7Cq!6)n?>Y-F79w_qD1r;mSO@nuCmr^Q-=#QRFFHRup-R@2Y1>l*d)`pS1i682HiyA zR4$_Y&ks~hRhTBL33-^$a0GLT%p4yCktS{<{nF#^s+uJSgnCjX(3jhf>N1bei31D@ket zrHy`1mlE?5Y(&pcL@ITV+s?=s{+aeG539FkmPLv$?Vi zl0eA(mo^87r14d+6^&6mOYPW+=u&c2sq8lq1W)K5!~NDIP0IFQ@I^pH$*s($I|!^g z+)E-*n(l@m9rKkGj}1okmvoFfOhf<^@$0Z?W;MRqVl`^z4BfyD-?23^on-uwRK{35 zL@ccz5m#KS(s;g{LWP??+&)$tMK|l>;|aqu)pp!G`7qWTa<1d2q5k7zPR~et7I?M9t#Xv2v~bw`bhaAv^8>r7hHA| z$al7aW4Ny1<5|hLLWv1;hKxN%c!ajO!dJo+eLi412JPH9Z)= z4R!$jm`#aSg;y1B-0A~*!<->6ayrBsgbm2vvz#m(-3>k+7U-t8sqm=|NPhD*RBWoh zMU~bF&32(%n!;JTI1ph%-;A&?Tgi+$10zUM*FVFbj911Wldx_Jo(NtY#@ACnMVmd< zk`hXVHpuvD@|wk4%#5@04E=3x=OiE5&i8RVKn0!$fN8qI5ukTHDW4(o?`n#3cB&#; zkj^8$b*s%72xl0iLYq2~XQheRKtx@TCyBT5MoqpIG2%zW0By!lCPcJyyVg1)H_kIw z8-(9urroL**Z~bN0_AgKfXI|4Kj1iS$ShVfr;9nC+fHKU0I8NQB@FKBTCXK|=f7%r zK#QDUMwy*43KN6{t7gvV-l^r1C3gy)&Tv+y&c{zh@|Ps9zFdhNP~sRL4PyG9{(y5! zE;;CMX7mnchT`UBtPc?xPBcj4P;8XKMD+Vsu1CXmC!S1l)UR^*rM`K?BzrDYc{@?r zd@146?I`YI*yHw;*9?VxB^!!A;=4q6A6>;E=Pmz`*V;7j0>4_t>NNuow`cbNS>vJ? z+r~^wXRN&c6KC*rlNwS$VA?E9xF*j(ES{VHU>h3}y!s;r0 z_N#^hsO!>T5uT(B1!)hn_J}(oPcFP{UlKZnaU(x>Guxa5orXj=uKY|K<8-=H&Ad!KjCwqK2Oq5Y+3&R0SkfUJnC)%mS#{KL_|2Ee zvC^%kkt2-49$w6iFhPn3{_OBQnyUDa-N}wDBg`ulHibv+vvU;fG&}Zd5f7wLy!7cv zQJ{|!th5+I;%8X;lAq;)n8~NX}rE(9MLOmA~oEfn~5_N6^xIS{QxF~ zUt!o>tXq_Lrw|2zqz(X*3PrxI?PZG`Li>`S38}@8Ns-MnWlB67X8|amHw5!+OpAwX z(@EVhp$@Ewv?` zU6;qxE=Z9vWZep^85v?#yOV!@ze!4$TDdA^sV&cFWYa%PE%SF81l*R zf{r*x>)VXVO^L0el=o7c0K8vu_W3V(S19tX6T%^@zjHXwTSSu~sz}ez00>n@7&Qq` zB$;u|U4z_)DDYF$8ml?@>Xj`d4Yrc|HIW(*jSQlCBDbfFCf{7Vf%`XSE04UPv%P9S5mi=y*B&!wjh1i$xwYjc9lm53Xj)WqcoT z$5&s-E0$MvRXy|iz!aRgzB+(2Xkw6@Dk#L@2minh6tx%ka2dej0w9lA`ndK5z=edo z)#kyamFWhMhfbicRzb9EZs%7z;l>Lc9>n6xL9s4f;4d7w{HIU~Le218rI$x|&{ zHWs4(biSI5Zx>$AkaB^lSigQOl|tS^1dr;reelIx@|TeU-k0$o--wk)lZ{y{iC!ZG zy5@mq)Z?fMxrN_xfHP(?{lPS-Tl>@(^GeL1ft)1cn{$!z*H2$*cXd<~Qpnpbn!5(u zZnujG;gjH}rdL|;Su+d{7CXbp{-)ja>M1*sNZc9C_JPWCtowITa60qGEF7UppEf0E z8tY21HX6Pc0Eh1favki)iN&t8>!)Ovt+|e+%da)5CGn_uJ;(%r9{;osn8$G^{ zFlr^6D6MHyE&!UHPHnj1AG9XBm$d;6V>17-0z>IqPEo1)EbwQ&bq9dV;n1ZaJ+_b$ zHD|~g;~S!ykk3N8Mka-=kMmMX&r{|<`@G{<7~j$w(Se=YZ-PA1IgQoyd~cUA=BC}) zU<8*HI4|Z=q(|1a82~Kn>&`a~Jlr;Lw7XhEiRjv1;4Jz?O2)@mqfm<<8%i6?4+@=k zfM}*PMqPtE=Io0wngHeEL!jR&>e|=z zrUB-{ zFNYQyB1UNozF!$v8c$&uu%|&AeqtliHYPr8hp1|%7! zGL4TPdn2}88)uX!RxqoZKIFZRKqz9~4=H|{6;Gd#Pz`r>GFYb-Q@wl`5y zdK^uTYQVD6>PrV)KPO=4?>$c$AA+VGT5mL#M;VuFTxQHOW7^N2zL{9vUx~51eQ-HU zW$?*OiNnI;kl^9)y$KnfBUj7ns=c!UXs-IZ(6!SV#woV6YUBWpbEjWFQe{{YSXF%q zuE~#J4RfGtUwDyVVG|Wkp+zN;0zT~b+vtV!zwr59ec9Jr6WAT29|^=}_`uRIkk1qk zH;3Eh1BCP>Nf8V%5|Y+%H)(r~S@jjCF=*QK?M%Mv>L=5QhJ@pZj800MSpau&j@y}EAdGFm9Zqh8psyix@PDe9LM@V$RcNbn$ zUr@bqyWILxxK9c4mR?I_(LDG-jFVRMa$)al#A>))Q4{H>(_+*VbuTA z=|}XwP+HcMZnej9N$PN(s>z}4N6rZ;sKCO|jP8+YP+@m7wMi$iA z`uNYA%>pk4#oh|~_-FM~$V?gFazFztnTLOinZJ6N9sFUW`ML~Gq?zkTMP|wB6%Fl( zuBNfuFDAattSU(ZtGDZHeV~xm;b?;(id3|v_2!Re!t!o!X14DsYWk3c$!OHUGQCK4 z041%N14dGcmceWW`aV?3>d^!RdGo6==5F(tG+m{>XrrA*%u+m6`m$C(p;cf2i5zhK zP+B&FJrr#tKEX-^pjf~i8V#VH_)HnPzedOuCLS-Ykn`(T8}2D3!Wct!mqgnywAZj- zPrlmq|}8MEfXlb1Ei8MZ-ExGr~Io<*1mV3WO6zg6+oG5 z4hfhIF-J~q?T@NMIi=ohb{O2v;jv|S`%@|Ra;Of5%YTnbU_Y8$$@Fze%ckx6Vm#HZ zc2VfzVq*jN5cXf!EagFs4D=#EuX_#JwYd3b( zBo*uj4O;6%S=a7y`iX<(kTg%$-Ga$+Ct|c(MIc1_1%PoF+b5AULOA8=g>=sn+P;Nk z&qdQWI!cInq5#-MuPK$zfcuxZ!k_sMI&=sX85uj59RWPWNyI-c!bI(AB-D`dl}D#+ z8;1IL*_aXo{5in7=28G*f;nEs|bAQ!Xd3Biu zd2T`hwuMbuj5AMNJHEr1W5zYhtMOSkDwbiIJ)S|mXw5=P?#U_cDY^Hh`zlM@M)|;Q zjE@e8{|1|1Nu-&yJV2U&fT9ntDr0V>dW=0TDHR*EhiE`$i88Fp*KywJH%5)OQxk!GJWJS|CspVntcDv z_&Z%JuOB5D1nbnp<^<^y)j&{GD>l#zY65bss!!4z6obxqI5*Mbn18c5pO z>u{}U()e9R+($v9>S5$*m}PJ#_eL2479to1@QiL9Mim~2u z@TRWjf;E%w0g`P_p?(tGJCyPZ+4m%Chy+PnmX7K6`bAoZ#-`ebmoFuMdK$%`{o}w^gCLlQ%qH!R2xAvty+DOL+5tFatxv3R z-7k1+i)CxK6=nVdw6oxtETDW#J#ARmSJFAE=i3(MV6$W(CC2I8Hj*t;(U!~-K2%oT zvD-pnB{^UKRNLk>_El!giRk?!3s9n6-9jQ0yr4J6q{DUOM0_f_Vh6~i7lT~u-{EWi z4MWNhAS((P^s=vfxSE>@HED97aS9gu0RDj@zT2(l-6nv@C~h{rjh7(?K$yiYzR#N! z&OBJH-2c{G2Oyb|Ph@euL=Oik;iQ5r5K@=&wo#~geaA3ip6383JT(#Zx8@kQhrCO} zAD^q&esg4Z|8$sw^MC7vnLMje?#Xu<)?Bb%Ga5jiHVHjRLV`^#>S=D`IQw=-ghqoy z2rGy^pGfgr)Aef$kzZ)*mML+BWRx){vG7cvwQ@yPWBHG&8`wA?>8i=4?OjNoSqSNBjuSU*^iKWlL-9g^$J{&{fpv?iV{1advKKy|rWT3IWoLi<)zHYnM zgl{($)u|hY{}+JV%FEJ5KnJP5;L!(c)w<$k*pbM(zrX|R7c+LODPBCS^K1^i-YpKu z8dc3Lxt7k&(&ne7`?w(uyLWOi3cr zGgU%fPfKKGr{HrrEzKzC53}7V#&=Uc`MXLSF|Q1UCHGQtYJhTi+Xz;t*fK(f4t6hK z(ph}J(TFl1If%!Jk-S>V6KZatfS{?oF>zr$?f9FtEJJIV%d6_Y`?Hx7asL-xZypcz z+W(KA9Os0StQ|>~VJt&96rv)GZH#TklD!7WzAMX6B4cNar7Tm7v6DRtbyBvFeWxth z$4s&;;WWJXFL7B~^aH1Qug5|aD`O9y04kT;rZ%YL=!3O<7 zS%`!+Z;bE};oKUmAu^@JMZH_TU#xAu5S0KiK}kQM+X3ia^PA}@qZR6pF7d0oC^kKp z7jjLpNhG2x6|V>wGs#Utg_DBGJ<8ROYoW(G@<+OPe|!7wU*2K@wRr>piWv4+ZQY|V zHE({`ylF}tUCg)qWC~$4@zQ3EM{*anT$cT>a@lo_Y=NDTU(^9|7n`$5gyw@gz8dQS znq@3`dvl`5CAY|ib(zVxkCvDw8)iI{l^A*}^xwXdT}}lI!<{A=hV5QthlB$yEV(b) zuXsi#@g`t=6G|Qa@3oGW4>ewEoboMH$l)#sD!2)xxpmz~Vk+P^_!V0#Y(Vu7GUaWx zbk>JR>!7JI0oI!RIgV_|4>*vAcNQjeC1OtH7yYs>TN z$1NBr&ROwxqZ?L7IIfh`@6>(j)l;fs&p5Q+k-^UF1_gfzmZ#+F1(WOE?w48K33K2W zw94Q;n%CekvBqwDhO;Zb=t>^Y*aytjr415YI<8MaE6{HoS~4)WQ#`p5L~nbmT=BoV z68E-25nTF(@#foC3op1)hd#{&g(mx|ZSX>9MH_$T8|3sZH%4nm3Xs(IYd8HE%JvPi z-omOLuASrGUdSbyO6Ldf758#X25wG?Kh0B1uhzOZ!a5u*AGa|KQ;QyuRDt}p^r4FA zNvm5W)AhyA^854yYnzDi6HWycY7F=9ySPcsdYxcM*jpoV`}0`4iFI8pU(DU&t~d)IYqgANu}Aq>Z;{Tq4Dd7gV}No^J=hIGoCf2TQ@iKMyf5Rs=^`hl1dN+ zOD+r9r@1oHAe7OLwVEMg#>VS+n9XKgq@)xTDeM+~yr=F%rK8wSDVS|4zq_=N-!2f? zcA3CJmS-lhWl=sKzH`rWPY2+j8U2e^>-2Z@Of$^Qs>C)8=5#&+I zkfI-kg*+@3qxO~e~I7UY0Y??r6 zPPK(YuI2XgNowr5v=R*00GqFyL?teg)&Ox)n4EUqE_Q~6NGOxfYwvVWG>PmGz|t-f z8j>1+6;-v@eTgN2@XW6%pk8J%?ep*&e-$Mpa)>lj=I3I-5j=HTfBK03Z-F(KCcRG~ z4<|4DX?-{h$+1v#JiG&lW^?j>0`?*B20m3L^~d0Nr4&KRL$%?$>&y|)of;wyg<742 zF~UI5kf?{;78g76(x+Kbxa{qImddt7QXhJ@#4Wb9H~l8y6ZdRbUV++tJy8QU7034p zl(#p?t#57WKGJad|3y_{!a8=XEiIV7<$N#=dXSv?xi-d{kE_OqASY|!SC5G4eH>JF%hYNu=(D|M2|l+9nIV5_aEybgqplRUi~F+QKzRP^mTEmueVlyC}BmA zJal|Cd4iR+X#^u#s>t8uJqwxlq8j(2GI1&hNG`L1H*}B=<=IwSx~hCzUu*A0z16$V z@h+Fjs}x~tN;Ffe7gvIr9Hi)IpYXY}K4I=F3pukZhvMDYm}!0KslSt5?~E$hG0sIM6MDE6=rIiRInlbl^hzwf zJXwd%FdAkwe-0}uE60}Z9Q;C$Y03&DAJ1jme+wQVYKL9io{^9b2vQ(c5)%e$fH~!q*PR|Uv%{(MStAf;s-YeJQ3@~qopWlZnD~L~PJcr5~ zsldBU|CXDZ&E+XLbmpXiBO~H3NfqNQb7H;5XAdvka%qJfvl0s`>Km-A`2GWyhlblr2NcQvBoh$YfCGwFi#AGm$^~v(P z>j_(rTueU`E58Jl%QkxPeM`Mg?C7?q(9tO0m1Cik;+9&~ZA13pztq)k5A`MC4chKI z!x2evgwqT=-hbFGrC%cJ?33c#@7GdU#lxai;HI5&j%_kD^lFzl)$sBsRR(%Okb0|| zE!Can+XB0Ib%+&Qqd{FAU>XAioqkwH;1%&4Uk7YRnI~s7-fE(O0j@7RpQZ|!CE3c<=v=K?&bTjOc^siHk{`DFyW4<$9p$qH+M28sHZ4M zJ;hjAHm{8I=daDVbc}hm3gPUnzUtb7h0F$-VxMB0f);X8V#hwdIs0UR#T_;&0!u&x zyKBkAZ>C$&7X*aIEWvq~=b6l5 zX5ym-lf4?62!*Is8=x~Kb($)}VM^w>$J+aF;Ejl^EL+W7?fv*mZBY6GxQ4m4X^?t&{zcL%jNGg{5kdVX9HfaGc(LSBvh42wrS3#A0+OE(!_ z6R2T4GubALVmRXizn1=x|tW;zEE9lQJLO zGCvK3ETBHF^;~OY_7QLtC!a$xNX~?`0-R9ZzI$xm^DapV<36PzMsqwTJn=bPpC3Y+ zzcTIBnLQXC^F_Wi77ANZuB@)Mz-H@30r#tQ8R6+YjZ%?Rvrcdmo;9))+Ng_m>m#^) zi8r7ZO+ZT2BFRPf(zVrN}MDR!eHV0fp;d9Vo2q`v0|ky9VH!Ih0M_w-)y zp7C&NwmH6~6$c*ovhS%6x@QpT{iUj8(0@LY35eezP-Tb(L3BF`C*hs)$Osaqi4y)L8+ zO^v;{?~A%$E-Q+-I)O|mE`_t-P|zx8kP5>M*lYK1*5>`o#i`LqT{|IOw}RG41uc+k zCERCPI`dbd>#$4pxn~)}+|8tnLEqmWUw!~Qyn-5uSQqWsDt7Ep(uiB3hN#F4B+1az zOdvNRHTLq$H(eo*S$Yvj!Q6O#Ty%Gjarx6BO;#Q|x4>`qX!CI)$~C&{e|Ea{ZsCoe z-UbVfV_&5`;0a`u#TBW&3@c0y_ZITT3Hzv+eU6AR5}HCX;px77c68)I5eQ73Yo`5a<6_r`CRul_f%2V$pt;NTYT<2fL- zP$|DGbG2+byF(LpoRmtLV#BvM;PP?mu52`ccX_25=)qquh;;g7lQr>n^ylIIPG{5V zn)8Tuv(j(36MBI|N25{TftBwfs0WuNR^}|c==*nxouNyUW(>9J^YKQ3#i|44#|fK|Z+H6qTpA{N(O}`X zp;RmDE=eqxL!4S~yE;-#J}gxQkzk90t`Kskk%;u$hT20Hw>Y`ho{ z5kK7pkLS6ATddSf%Fm4Pzm#nyZ10xGstdd>|Kt77XE(G$;*dBCbAU{wXoOuZ>W z<$2K(yg1fUxxD{ zNmZi4gg6iEY^T%mKi*+6sdLTm!Gosff6;PO54b*0lj_zN@@*~XMzsT87%I*nuJbnD;#`(>y7gp5# zp>`U9C|^lMI$BEB^^3?*TNBaau&8kmUzXEPa%X~x2 zYvgMgS{6NEqJkKvgM}J;B4}l__g|(~y3oBLFv09N8ylW?ZT~{=W7>$=|4^x+GcC`p^FTny<)S{?Vu{LGjq7Qc_ za><$QiU2t&8leJ_xu2cCoG1IRF1c1nWJ$xc-elvd7)@;0^j}VM3s=BnW}GG@_kfC` z#Lf7Lk<`92WkoGGLW=;&wQUixqZi!(@K>Fmd<(TdEKAErR!1CJuy>6otc(0+he*M0RVs|Sm+C?1^lRO}|xoLd-uZ`Fv68W+l4r!Ic-Wz&4 z(i-&)v-Z_}#PiPTTY{v)bf($%L1&tqWY1{`dJJ67A=)z|y+5f+-dSCzds|8c!6_Yi z%`B3XndgwaA@-shJZeOK`yK!p`RTptx)2#wF1iBf1=B>uHnZG@0$pOuk;d(@jE_5w z;guI@ft_8aIx_C+y$2{)7sB%%U(sF?-O1K5{m+0`_~GYQID&K^g}6Z9jAy zGYUHRWQHvxI>U+f#_Wr&?Mnqdiz~7t0=a6p$42*EN38ypm#J{G#enxkYMFzEbVQ9E zT^=};?);~D#+b;AdGNSu;+|>DKRM9?q##>fPX`h^D*_+tX{o8$-NC~F^p(;+s?~Km zTMhukf*TP0wF*xy*EMrZ=tW?v>kRO^=iT~gJ!eg?1`(3xnf2Q=Tk>fyaAHKW5=KLR z(cYJs`9~)GjQh>iN_4mz(}@7U-)2sw79a`p{?kQl z*C_Gzcq1SFS9_vmZ`0#K(-HcxIVGi-)7*JGCKZ8L2z(p{8FB8bX2TK1$wQ;J{#&pKtE zSa=~P5^RU6E3B3qZ zS)$G&V&rS{QoBM;MEY5PfiC}8kg2C)ps3UQ@8d?$?L@qIu=HA4vA#^@_Ig7601oEE zYMAmfX>_YLZ}8pDvrpr@fj%CsY>fdPM}<}&AVS5;zerOil)%*>aY~2X=idhCt~Y#p z=Voeg*tBM9u{qskZQ(xQm)qwOpp0=O8PczZhKkCcbSL1^u^kT_Z|OQ)p;;j$*}$s7 zl`Oru$8QG9QX2-hnE&IpOC$>)As2e#4%2W;ngUCu6;0{(UFT*wWH)#y<72(UzN%YN zVaTH%uF2QzwQpA&>^;5;glIFl!av=ZILiEVp!icGDj;sM##4-LQPTSn57e^_)zFo4 zNqkluOP>#pS7eZ;R@_DaCZ=CpEN(JM%~(5~F1&1an+#3mIrw7FF?ce@80BR3^YD|NZ^C;^oyMPHjUyUb^2Y)iJT-g7 zE^O!20g+N4wRwXTL7C!yC~>?-46^My>*+t87QFuc%G%}z8qr=c>Igb9W}Mh!_8tRSVr0au9xy({ZPS6@?gf=FE2uCCuk5 zwC|sdNo|;Qaa+p@Bj!!vE?)IIJ;xjWPV@EH z$zGI%#k;Dg7d)Z10MajN>&uuiKytqLb@nu%$``9%ImZRGDB3#JX#1T2GUW4LFp!4$ zfCdhfFJE1R?b?weW6lYn8BKVpg6PgK)!ql7cR{xPu+kL<@<#0bq8PE_&0?E< z_G*q#S4Plr)WaR^G1vFyyMlTYo+xd>u1dVb^^*@AIKDtR>>)Z}w8$}P1#me#F@d}3 zI|d0~D$-9nts6af%`;12I2en8GzlGocpge1AoR2?%Tvzstb&06l;@kfxe`wc8{{~hmwQD%43$&9v!a7y#G zaLY7RMhvIfiVu}ib)m)6h8akQFuC_I%y!%kx3W>rllApqJhpF;22{HI{D z`wt{MdYSfM0@=(Rg>U7)jdH|3`hc4kiI`Jd z&p9Fn4M%Zw1%AGed-D%7EYZC?>}YhuSx$`-sPUo{jHFJlNV=9EYZxAArjB}+ zhtQ2lM(9SQ^N`k3V+G0T3=#1gJzZa;R4V;e3axwDI-`i!FB=e2Lv9fBLfDydWEK8^ z)i1W)g+28&D>T^*r>Mpu(~HA zlyDAKti6ABVK!H)Y0HN9WM*nx>4eOaY1fq*nL&J+^~H+>mvSm-^1e_zEw7t72UUJH zSv94WEp=eBYZq-L@VSs~J5_dWW0temm!22Tz+&WCQWMI~^&D=gGg4MnH)v5c=t89) z07UT+Zhk@C`Yd16GE@zz^WDeS=2l6fL} zh5Kxfs1&zjuB)`5l#AAaWW#zeZ>nIR6cGHtbt2+bP=aJ;Eoq{ zox%(kabQcQ7>&<;53p*tVx+d!7donwU39tZTswv6giXzX;b>zA*!|)aUn@P^)AIae zhn9znFtJJ%lL)0}ZX-rD*knIVIaAi7^Ak`w`~G1`XLVgcQgVJX*>H`K2^8cGy*0_% zAQhdyxhmBpQjN=7?@!!JSR6@+*K@7wd!?-|CY6*2;zzoQW>UBh%vxH0%M|w7Jh^1m z%GhzzqNW(qV>ZgEnx2bG<@poEKvuM2fCx%QhDO%~#)aZ8L6Qgvm4y4vEuQtsMd-Tv z*%s=r0jz9s3R?7BQ&s8T%JnX0*CSf;6#=>w@g=#<9I*D?!-`Gf7CvcDRPz4q_k4wq zx%VR+!FhJF?I8>dKyI<~w&dHg!3<^(Q(hykB{_%3>N#agoF*7%+VgVMAo$rtrB%pi zSKSfa_q?#w01Za3arsT`T0)-wcLd1WoV{0%+%!gYkxX2$*>oWc1E&l|RN04~*rnl- z>E&`;r5{oV)yic}3##I&CofvBbf5A#%HQ1iKoRVDx%R_(!B(;l#Rw+#Ndtwr1vLy| z;M`sboVkbnyrnZ9zOB@Uy-V~aPtuRy$M|2=g4z5q-)Ba*2uUg_UxDPQBa-mw>Zfl! zS8WQPFTE7ZsESscQBC_-Ny+E_=#)xL1~hGitlNtTZ%{9P0`R)N-Vvw? ztE0Ve)T1rwQ&Axy=Oer zp%Tf3M|tB(Xulr+#kGPu^eyx$>p}bE>Ay&HrwHLR%=CRztq0q^C5#b_o{^+wR6`TH zO553;gtIUV1J9woVAd;=lQjju%1E)_RZxnrqPS`7D}qb7u$Cul>iKgwNG3kry~2Ub zVeALqgX6p2E8`7sW~)d28(+muxd}+s@AMCDC!o&L{2lngZ!Y8JOPNNE*vlZ>9#qeb zR<-*M<^;9~x9>@OS4GwG@a1XZM6^^QJEFPANu`64K8WQ-S2j+n)zZ;~|3RhcrxzG| zbsUG&$kh;f&QB5$weUdHGf>|wd6Ca9aH8GwwYLaeD-HdAGcC1I)6HuuTEZv(734I< z_151`JhxU?mH3La+p}Jesw0=|^9Q)m=E2IlrKqkgyVunnur_rN%;VLpgF;eO{u;%> z4j%LRb_RG?9B7y-xfJ*1R^@`a`1E0Zr50P$cj)cwwJ0G!>*d zoGhu0gk;Tlb;{ejElhw;h+tT}fBoILF*%jC3A6C6k#6I-`z^*x|Bf3UsHtRT&!ZPQ z$VHOtsn&fU1Ua4D@YV#rZ44XH4HPdwuR$O*%}T#IU9WZd;9Q}HQu%4L!C6& z+~Ap;bU!!HG58G{Li;`|swEE;#3cCKrGmi(yHc*2s%6<0(mz2X{WNHpxWyw}NsHIe z+h(6752GwIKklUw?G+(G9 z)l;&BPx%!P?N53CH=Y$U>I*t(EjFW?A|3iOYQlwJ3v$5VTxdE!lPBO{Dm`x9Jtc2^ zHvEW?JUlerWmthe&n{;$anwfdA9wy3 zPGvu&W`E4bR4i7}yS*Ix+N!P_6N?crbL6(|vqxHfeyF9?m1^vr?e+(aqD`A;Ju%W# zp6Eo&O@F2s%0BKyrzM*|=)Xju+=)F$bNZwo!>DVnhibm~y2MEEEN<503IgO2J-?Zc zCJ5y!FLDlf$cN5SH1CqSnztjOSue==GeAJ=p!J@nt~sn5UOmV*YV_95_LR^D2c&y? zKu+2>hbya;uh)MtD~+3BkLV}|x{-T}_#i5SD^yY;@a-WITiqwOnUH>>iHEbNb)%M( zyLI}!EFT^5jb5{L!h%q8`hZWPs1I0{cy~ajz~#9F3-~BjZV)r7ZR8M6AQ9}2uFRTL zQeRhMmJ4RYDiwAY6c5p&WnQ;#|0Vd`Xl_r$E9Q=MoZtWJPgRWfShshg*^c_?$Q5l(SoYvKsic<_S;g)?I8sf)bCfwg6`_9ArN{jB1tbk`;N2>$ zXm#~+ny=5&>i|Y0qRU5t1Gaw!or9;~mFX@oF|v+(x~Qb#6}AvSh7HLc(1K&dh#N<{ zlZ^l$J#bO$C0C@1)mQl`^$ofa3}u=h#Q z>Nc{OWCAWfjRJ$j);twjfu~3!H-@^A^PEYOl-sjt6%=;hnxv8u ziE29yNlcu@lUH+)&u*)zB-m=^J-7L0_PWysF!bhR*B0ZN2*v34Q~`q|U+T#g&}H8U z+>{I6oC*)#3+K=aru1@fB}@qq641=;AE)5<+T#^P2U?}7IgY` z3hS#3$P=0{JI%aSI+!i{jZi~#esUIjtqa{AH#$>F28GySpVBmCjSPMHLPT4l+v#sz z*HTHBy*ih135p}_o$5yLIf9*ZtL*|4ajO%`pd?>zAuEgV#s$+h>)+6eAZZQRQ$3JI zl-{nQpk~%g7^b#pAIh!-ytyxh7(W9?2DEHc*wKOi;3FwIiOPq)_G~Z-0ew*|ZvI!| z3l=65(wfzt5BZXne*UWTl@00pbHy$AU`kEWzuS1#$(P!B<@<#iEjyngWXF+d_%v9Z z-4S2bNa1~%N?3?R3lGuEuaQPJZ+!N|#d=vGOkDa*#P#6so4=m2k ztTMf>cbe8ap3!@h{S*GMLh(aY)Bed;u2Ox?z0z8NbHa7@=DX*&uxkO6^v?Yn+yT4J zGns4Bv%Dwkyn5d4BiIvHb32V?BGw!6oc5>^jM0d*Z zyvx*H@!7Z|UCfDj=hyI&d3%X7I_7y+;ggL-uxlg zxL?`z2gSli;>~2boT|;7qQ>t}Ea7*{qRwK4n%_mIdZGoH5KOLczRrjDL0$dT+cw>Dx_+l$B#m)U1s(u3T>=hqf>sKw`x#4HQEdQCr zExZ%6?!|3ds%mlg3BVy^0&RcsQ z+r*BcfbsJNVKV$^Um$9;P8}&fDZdLL!?j~lJuMBv5|=R>6T1yHjpW5`-;a!P%j5Hc zbj(kaal`9DZ5wo4pn;smXcqKtoRph~&568KbA;CekqE|Z z=UyS_!|%UXQR}C4s*EB3QPGutF1vnn%pz-p0R$>HjnIXVugqTcnDpwpCCo=2_wqS{ zsy7iH^ih4ibc|^D`;&^WUz+-Gu=cepvuskc7C+*|J6A4AxkSLk{;=SXm<`CDyT7t+ zSSl4;VL8QH_dP1S=@+~dVZK?>B;hIIX1Jzdac;fQ0quwKF1yfS$`Kzq=@HXCce1RM zFY$x7WytbEBZJr?6t{JiK;|bePnIi=GbMk!bw1^|xN!PiwBZsLs50KGf_@@aL`YkF zOhjwqFMxZv#O+cx1al-TS;eI>ZH#F+*7gkBETp)U9SqOf z?pH<4J((On7SDD9xJ&YxXx_$BvC!4`T()9j5SNI2+A3DG_2Ur2#!Vgrp)8$uhfU=o z?b+iRC3=AyiNwog4?P%ZHX*mKSz{Kjf`efb7gU{(PCZ|LIO7>)*%mx2W<8wPO*u;( zyrf~AoxYU$yr^rh3TTEp>=N1|Nl;%AN?q*De&4Syg@RWpF%Z|JUl>_nqa&fI1DfPf zqlIH5(+Gzsk8O0RjdW!r1-5jZk!2eek$>OGR{h#)`pkk51236{I|| zb(<4S#o%DSD~&J+c;8Zl)46&pr=-*p0oncjQRo}|+E5bNw)qG*cM*?u>H7Fe*5(fyGa{7qmB zQ5YDJ1BnlLFUx=1JAMsx24hlLkL17yy6uvFL5YIKTQv(>)8I&zDiG7CpYdqK!Dbwh zuFaUVh|1)D4Z4;K#Luu6;?^_9fE`QZCu#H0Cp91r09Hih+!UcGxHqxrFjM`0?g? zF@6a*d57O5Wy56KdS%E(~MfCZWZ^$Jyl^=&TeuuCuKE>RNcuIuGm zBdOHi|0})Yk%ggU+pgL4%RaGJ78tz{c8C54of`h&BVlN?QoXYAf~O6ac-1mWQEnE3L3p>WrEYAn$@yiDPEXGQ zLD$9fH=U7>oBC=t|dC$%QZ~38sH^Q1@ z5NYZXkh7}Wd(QZsv{Zz#Eck?+YD>5DP0{mvaquo~MEu4gw&Q1cX(K<>J`Y@pOusITxqs`Rx}g3Nw&~#o zo+=&9ugtAZyNTsZ5j){{xa)A)ITv*6Ou?L$yss8Tddj#t)#Fa`gLdrf9a#u@k13`G z+qYwO)5K+NM|1SzQ|ob1_FXTcJJ)qReEUJy&o|I4gj=R+6MINohY7}PvJE8Ac0DAf z;jk&KgodNR#x4?P+jx6!qljPKmXjt&wGQye{84NwmRI;K=|CnKxn)Tlp*)SV* z!!Z0MdF5pDGX87O=Wr*szt7T#-aN;WeMap=!Suid%%lBIQlzCe5Pc+;WVqkHhFOa*d3G42;BsELcsU*y; zJ2v$(Ewjb6{UcJk07Oc0X?q)NEaF#>jA7{PQvV-Nz>dj0y9s{hzv^7|g$w9l6dS42mvMcyhcucgvTd6|#q zj*VP*)m$tvJkePxsCJ!Ke6(hAW`G5~xL$K>=IimjLej{Q?Ulu9pF?QetG*&LmH0x z8N~Vb!S=z88e3Bdae*^H!T$(Oq<-3AcaRou%bDTyY3aB8ViTUd?uJg|r7rkd%hnW7 zTLJEhYUj;zn{{U@f&*?zc^(+W|tb$Ci z46RB@O1JVIwv*-Lq^9*0oqPg32sP^}7b zdfXCw`4Vk1ORuWeWBGVKcfbrwam(u`xqD`BJ)`f2ni^}Mgjwvka3Vo~3MFX5X4o;2 z#pcJ>P|S!bfhex}^5A`to+cza9wm@7pFSOL)akLTiOZiMsD21{E~wicFdC-x*Uc+` zLsC0YY+L0n%tK1lGX8EWW3^D*m`FmE?hV^M{|KNqF%kqicnpInP@_{N*#i=QCoaDI zGT?J%93W>-P8I9f%m$tNr!8qHIk`;hTGGh7XCi3@an+!#wFZ8+%7J$frc39f=9l&9 zXA3%PT2s&R#}(3YuAKP<8U-2cdvNUzb)5==Bp%3<9t2`~>*ldN*PgV~5422YfxAAgV!?X$@$Vj2wfFD39EMZz4Jhd99d@Ba4r8Y^w*MJfr; z?BDBswH@J_&aBV2^FlCp2%3x6Z;MA~ii1^w?2YBgPH~{7XjhVoCWI)X3QDIcBhOmo zT&h#X#dARPc8BezCWhoQ5tR65-3!zMYOoE!xShacrc>!pLEG%>e>+U zOzzEDSXJx1@?A0JZ=C4l^%#5|fk}CGy@NdC+wWL+wy(p{)mu^rd##M&weW{n1U}Ay7u{;)K$i13SmaFGB#xSevz`O^ZxsW2O2;p4H!3;uyj0V&)x*ed36LNF^S}PnH33r?(}l8zj@l1tNq_h zI<+~=Ekz!?IZD!TsJELbKgW`D9^bZ6&pV_61kD<8JXNhNzsA0=Z;q2(t>1kV%s!VH zVC%7(AaHgEcNm*bVyB0NYr6%i247ZHdN_{l zntG{08y@Qv&8R}@ob>CO8W>f4+kJnqapOXi{n57zT>Gw1*_!$uW_HYn5Pq6BQwNkkUx0%WU#GWZpknf2#CV<3-%f*MWL7`}M(l z8c|BeKQ(swLYAikm{9;g%L5WCsMH zOpq}ssb0+Grr(D`I))%G36N|>Yleu~jzg-z42q#7*VJRz8<+y!b0c6jfhHO^-2zA5 zB#!62h!uEe6=d*tlb|FW|3;&P`3VQ@pg=Ke6vKLGH0s%1R<)!%DD}YsJo2bu>yjgr z32`9P^PiJAe`?LyP|%62UFtmZ@lIr z9F$&j9pgA9RqNMI4ptaz6yCam_Js6e@RN{G%v^d34wIN(KGYfr3lW|X%9?LrLkK=VvwqHoIZZM4oyJ!HnYX223kCGd!-E<@==8) zfwGHMX1ikxbB&MYrlPp>Wilq~FMGEp4oJFeB0)X8$s70tH@lUlcnnK3`(MqLADTnz z=GgAVbS>GH>K*0PcQ8i*EIZhxh4;z#z$8s%O5qr zo$OW8z01{BUEK8$y7w8Ju6yG;cE8=K{Lu(H_r!w3`o=fG{HN?v+c(Hb1Qp#@@W%rv zdEVuRLj0EDf=utol^f*K;i=g6oAu-rfc<@0s6L*(s#B@kSsde8oa-k*(rktKwum$^ zqex&vq;HE4j`SrP<1TIXjI1mc!(1GSfbSk>+1NLqn*wyvOmyyk?JT*f3; zHe&wAy2Mngz!|cUBw7pUaDwIC%RZ(GxY&^IoVUVmtj>?T?IHu|z?NWC6tNGxu~=2Q zr1ZVA?cpK^es%F@-H+U$y2%l;Hi9*gS-?nej)w!mz`SW2c$*q1&L7*N-q|DbSq z{X{(ANb}j^_w&P!*i(&h^ZgfAJ&sg6eHk!TnD#&yn<$)jMeQzKfg{k=j1+{%OLxBw zWHJQ}1#arRT+4#8|7QY6P|1QKOwCLU`rDg^y-lDlTyCVQxF&qK{bm?_|4+shD7Lk@ z8kP;jn%TL5?~m(w_wMp?=Wz2U?)4n&H7)5kefXs^u7&R5s%tz-z7QtG^?#NAHHjPg!(4?vh?JiR&}BHhP?to&fv)LMdAr0Cw)(sM@Ky5a=tT^rEH2n{ zok9#oH!hUh>$wc-=^F_7Yq3`Vs%mn7Np7d>`GCJq=Jbr8F01XHWyV_hwfiT@Rj-bo zoot@?#<3mhSZ^7eWw@#GvobemZK^=x?@^w_QP)B!MwHVIHrWDx(t$+qvIN48EA&Q= zn~wxll9Sq(2Q+lSkj7Qr{~n?!k?T^Buc=eK7Ufz!rjCqBo;qs~M&P&XR4QUYH;g;L zJ;&4L_x6jsAgp3imVX-f;KV$Rk7Jn|zS{?XE(mX-ggtqs$Xot_;i;rtmBdY5_jNYn zP-5@XEo+}rzH5cl4H!y?TQRa1YC0$)1A0^+dGamh6?xR#~vS>{(`zL>hjp+#-ecr=gEMgIX`BQE>w z&J#d&$zT>Y!B|E~f+&QTelh}8SiLdpxJfDFF!QKzZ}$g@Xqd3Re`Xa@3?s#Of%uxec#v%~eTN)iTenuh}{^Q(q=MYo~8k37f1>QeaQmC?sD%Wl>gL6Oun<*)tjTk9O?pm9rVC8^hr9 z5k!ui@OP^op;B*<3x7y$@1t7C?fcBAl$Gw$QKc21{#=ZgIN zbtFMD`Dfq~`v6r^UC?`lmOx*RHw+XJu@$0V zEHNz*L7kvWKf$B6Uc{u9d-W?;R`k_4vk}MP1F<&VQCLLi{agRO3hr8p(PvZcb(%lo(GEc zDGnyoy{$XpuUcqC-bzd%uGYE96w%td{j|Zr8=QiD)9-Ax5{y@KS*W?t&_oyb8%eoaM zJN!8=&32;;kB5@`UfBq1BNCWKic|rmh29Ar&I&s7&b;US zaQ=YfkB<>{_TKARPr2`Fm2kJNCE;qulh3Kc*(ig@S&%KYuTl6eyHV90;Yg&q%)vR#E~nizzkDGo*mGQ){Z0@hTj(IJULo;n8(wJ9~yy4ScG- zvLU-x0wbzg=pC@<>sP&JEeY!uwqxYCIQ;nI@L)#4J$Ym?-y&qr zM|}KJP=?oN=cn;52SykTF!Y8Yp>p&`-~rz@MQx6V_uu9V5T0Si3WMuUcJ)JmpDyI3 z*-iEQ85pQ3jgItQnMXcvVEY<`yn)(bA-PIU(Mttc4qElaOhasYL+TR`& z2*^e)yEm{=Bo7Lj6s;1DkzTH}c0KuC6)$B)Sel$tGr0IsL5Ze%ZEhAS=HuRt^eooJ zpg#kiUF>i@N~4zDpr_+njix>xiZ&oDkv)qbmF^;Rv#G&& z^W1g;Xhcu1)h!t%31NYbNX#OjNk~2i6AUd$AjdHQf{OR5r@_VtEL;IV5DX>2Cupsv zMBazL=jg0XEZ&Ty+B;9m-)5+(JsK@561zxs#_yTleUhauDo3u2`_dg5WC5_UOBw)I z0xVNbMd7@Lp{4A{G*3`OBT=uh*~+(J8Bq{X%vEULCyfD7Di!9|qf8fX_AfhTh&wK( zI+i78n5{%s2GL|~R_O0*n$x<4>9X_KZXSPi9%#B8is_qO0Fh!EdioI~{2P9oSMv@* z^u{Kmi_{2AoCskP~pU9wYTb4=Al&IN>FuFJ~2PLz>* z9cRk!&`nO1XlMeW4|)M0Ex{_OKyc;=&c0*NNZ$$1j6^wHYQ`;WQtwDqkWEh@4Ydd1 zePE^X8fgo-L27KAs>NY#%4Y?w%3G8aZPvAEl_Y4iPiL0`If?CGX62+HOiUq`Y9^H% zY^v6=60(H2+cM5Q;TY!7H#}y{g)_|Xs{q;IDQu)}1t-0eq_{tE>4qS`jaFBxDCRs3 zj02P@zzUs7i?YVwOqZ}F>F_+ao1+sw8?c!isSyH%vQ&Cg)=PKF@O79iU4O60_5~IK zDR=pfInsq{k!-rhhmUM4tj!~jAgS^Im|(fh#Bm82?Nq?{|Bo+dVUlqhrljPD1udyJ z^2+eTc8qrZxn{M<>E6B$@f~;GHo&vk}hLjXSWk4!`!{Q7830a)ZZgz*p&ZQ~sV|NTfj=XF5_<#76 zkKCOD0ujPwMM`sFJ>g$@xF9JHn=|>Or8Q)KzhJjb2PMsv>Wg1TU6!8QxlQ=at^;Tr zqI=lc{ZqqKld0Rl1k-4LAfZS?4$Pk=JuUe`#6Ub-{9S_~tS=TZJbnG3->$A~8L%|I zHTZZ}?5(yAJ=CH+Zb_PxdX)khkmk!67I+3M3HV(dC1U2DJz5*gM9*$P+kvs|-}fOe zLLfr0!Xhryoo9|6ap$h75*7#?JH7BdlY3Qrg1;~&K*gIXBrDz?rkVF=^K~)Ht9>WY z01zPYw6`}Z$6+1Vc6OZ;<4gOFoYf@1wkWCx7H8XFZp1#Dt>tiugI@>*)^cl@R?~Hi z3h1AfZZkjhYOdgHQ8S+H$)SndYG?J{sV z!tMU9!^ZCp%SDvLQgrxQXgnyRoN14IXmb^c)kavqj@k*fiu_CPIqT!SS}Q4i8HiA|YN|2OmoTpUw4*N!qGp{C50Fqcb&Mv`D|0#E4&Rl{y;&X~32BG3Q zV>abXU&C^H6_NlF#?tn`7O{ZyT$tKemX{H=Z8^9Vb#rv3>wBXzS>TtcMEAVw{&JI@}d z^fkYz`8`FFbAV|gt#rE!_`uV`=84nqu}ec+l9piZV1Ahgy`6}YX4iBWs|a5%Mq|r` z0rkX=^?$M#Hs$r$3FwLq#WPuCk$Ii%Rr9{gw1rBPB;zZ|0L=>0RaqrSCeWFtq$)L0 zl*2L>1)cL5Y%!2jXFGd3I2DMHB5mC^M^qVxBWlg8Yy`@t$S|!!QztpOADW4MjpYQU zYS5B8vcYeyMksFq@o(TW&?kzg)q;s}bV_5&nX+@EB(Bf#9C3!kqTBl%kJ7z9Qo08p zL!0J_w(H& zs-pM%aBkM>^kUq4(~=>$x8pbN)y}YkP(Dnu&`iYKXB)Kyz^?*I})I6@9n|%?vkq`LrXZ&{w^fp5-jUE{T7#D&L$Q=V+A7`Sa(Gs2RKAyT=Mx z#m4)4%Iy>=CHzSOtTvEHB%b=Af;VTI6V;@e+2MqxDPmf;!a9M1#WCHD>rn92^>~$# z+g=UYrrCnlgTNp*f2A+PJVPmuu9Zp7pqB~Gd^|)NH~z0I{mO!~Y3V!j;|jO5qI^wd zH@A_%=uwa&tC*!gD@`hV6c!(RfAMks^j7)xrcA!uG^79o-wb?%N@RrG$u5efWkLf^ zL{nV0Pl-a(g=0@Fxg-AG?%gj>i^938WA#fBErZwMw;-e(f)+V152#+q8o(6;!?GCC z%>XbJEdjD(Ala)?mg|J%By3Kna;~iDTg~~+d!5*hr8w4@9rDE%mytqhN}eS(CF>Sa zgRjJ8=4Lc!E6Wvxb3_CL0D=)no&bZ&ydLP3H#8@uEckN8EJNi4~pu#w87SJ%xOdI%g2=KxTEcsufiNF*{um zP#u}G2$*J`Xy1zo?ax}Uji{j$`VSrUks~I6(E_*gF;M@N5R;RnbJRhv1rcm?C18iv z)L<-7(?eteHy1)NfU_%r1A{tPi#USeP-`7r09NF)lTV~x$*wmVGSvZP#?Br9wR&!;Q8r4G0?+6vjSlAT-#^cm(#hsj-eN%Y@b zAP1lxL?f65W(mn(AvZTBGorACDO=pEILup%jiM`$L;<6UJE8SB2_+_dpOaJ`u*}s5 zulphB2JP~qxM;pm{uKO7a;oc@T9ZXaC#?qm0{DQn$C_?P1x8Y@Z`+ zIepp&4IQQ5k4QMxc$et2uM6EWp zh9KD2#E$Y#D&K}=C2V35)K}51{j);QONEIQ)^&-3ASxR-S|%p`LZJDP#sM@Y!W{QJ zaoIPf1 zoiiktbPBBOa@)TXm2-wpbgDIn1wR3lB2qX_RZl)HD=3FlN_?cY!eu&VE( z&i;JY5rd3!l9B0*WD4^2FBHYh)fLu!1Ia6(5tx1Y@DGv-v;w2TZY}Imc-OjUUO24d zE;y|Md!Ap&`Z7qo?vF`w9R~quXg5=`Bl0rO%S@Erhg3eAFYI{O%g1r=FI~OEt`$mw5Y~US*th}7aBI+}CykT?Imm#ts1uy# zGlqyI%i_P6Y;Clpy~l0Pv0;k2rgxMS=bQ1Xcl@eTk2aEkGCD^ds+s;l?n`MlEUDC> zY(rwsN`uAmYYSNp&f*haq0n+_3Zl_+N=`AS^#xN_Xa-N;)xM0uuh9brwb)Gt5~Jn& z0WqxiC{+CJ{1np_SwJJoEaL9;@m@*`w!c~dQlFm7JTO!D?aAoS-yF3qpxGXd&87=R6cYyMLHKguxB0l@mVY{(nT8MS1H zrKI)%00_l%PQ=SMn7=amj{$&7ickW!3CK+VY9sse_&I5qUVh%YKI+mqs3PEW07gB7$%-knb?WYq`BxjWuNRR(3fx}_vRJ9n}&(Bb+v!S5~fmit;cLO{e@oo4u zkP1=JOb#FevM!AU;^Cq8soFBuv31&weKtxscc%!VHHd9T*ZbuEzTR9Vhh#wtnq2fW z55Qc}Uj2gi@p_($0YWal7UrXj=-JLQuYl_vu`-g79BMTn_D!PI%A*i)&O3RAO3WBN zH*_Lf($1)*o77gY_*YvY@z_HB_b4mM=go3zS49I+MlFqMvF{dXC526%1F)JqnEzUw zrsfw?n#I(RSVXbs!M6S5@*5SIe7$&Y<9k~%{}UZ`RFb*r3{-GJ5>%F{HCd9UF;abal>x4Ev<;ok5k`B^Oh z`_YPChrHolV1>L%7@fw%WovbmJh*yIQNQ}(`phx+9~nFMJV?cmOXI`8VVR`R(zz+G z&rZ18=l`&?9SeD@bD4vL5bQ)IXABWnyMKX0s<#41i?-5k)x4F8dYg1a4_Pc%xIkcn z3us?8@c(GE349D-iseof^a5Bd$%&8@IaNsFLohJEd^$a~yRa|Nm;71}FbU}_MeenQ zJT)8BZL2vka|2{^xFems246h3z`);}Hs7M+&3T$!V6nP{M-dbqY~;h zRTMPmv*`Clh|l$4jNNB%oAvAP)jp38~&u$vXMSJ6{d!{rRTKQ21d)!Gn{B@ zq+;fTwv19ey{Y^9bf?d441Q`=)Xeu}&l^#T7wQ_g0>=bzi#U z`lD_BPP9CCP19W_M%6)(vuK*Q>mMryg*SpT);{xDkI z(;O9DX`TUD+t=h(Oh)b;2LuQlBwZPwLmHkl9061MYS#K33=K&Q(NG2Or-AT|R_in< ztRfRo?`bv9aP_?ue!E&BjdU1rpE#;`PJuke@SoAth<%cnuD1Zr*D`N@lq0Le#lKOG zJk3D_574NA{6$W_Cw?rOE6M1m?(RRQ%RVDz+`MjG&6&xikY;d@#W}o`Lw?-kDi|WC5I;-V?tMH(}Yv`Cfp?U(;&%)AkS*uwdYxJf(_ z8@VIy2K`t(Yrz@Fu~55o!ly?8I&=6uFPC*V`dAIXgpe%IMOj};_`I6O#@NwGRkKl@ zOAGTkp4&T5JDx8JJ-*!HAvWf1rci_6{weE;Adidz3Ps60J`N$J>)k3n6=C z_gTnAXR^3@%XiEFpoAzNAwtfv6j)+(KNEO7iLVdxz!;YpCpKN*0}LYRal^%yZ zJXR1QAlj#1V$~;wk|euAPAJ}XS5qf-(Jmi#(Y_<}^loji>Cg2*;!~C6I2buz`XULm zfF{sS#l^qh-zZh?y5CWI=Hi9cM2Q8iN@l5ix!7r#W?LKp)wNE5=1zye%4m+_2E1eB z>t66c?Za-ZSC|JoyI*b{ELFoiag?0=)!S3?yP4Nh>AN`KpdP*p5deUxKbdW5ugt0p zaDCjP@zKH4T6*ezN{1aotQ$^E!la4`sUw64vDJC*!0S+}wk*i_Uks6BC;09a_^Rvo z`o%C6m#uDxa7c_ zw9+mXR>0MO(Tb>C@syGVU*&w^;Dp{cm}cwg`!MghME(trj4CoGqs`KT?0RL58WF*s zJYcUWXDsruR8pDqaT$y41Mq|7PqOsg=v~PVD|&*ZhZw9SfYAarYnEo0l6(oI+8HXb z@Kal?;vmO*Ma$IIh$Y!w|^q?h@{Ifab4BZidt@_)-3V`WEhFSxfh~y1v-V+62!l& z(EPQ*Vu|z(QnmQ!QP0kV9gL)#tTUSRfumJHAlo-M4w7mfF#CWlT^|0|WO(FJ?M^vW z&9{(zJBsk$!Cpf!L!JJVZD~AE_CiTz+YnoSGze>i@xQdiToV@3&wg!_yyN;>H@}Bh z`g5Wn^HGQBpY0s}F_jjTuV_@B@Vb7wl@}OHn#TjKi4Ivjz@^ zrtP8aUc*Q1Skr4>cHBGVO6Q|9mPEIFiG#`Nk9*x4`TF~=FT5?4L4}(F0tgVsY9p>& zD6(Uq{F8BE!KTqb!h@FcQr*!uSf2rj3!!MnLxqa8VmOah%n0Z^r%w*bm1MC(5~CnV zP(YDE0Y`^wxId@`!KhgC%S{9r2M#CQgr}qVd~t}O-2ywHzs6`m>$L?qX(D~~{U#Kh z^z}B|E6~4^)hp)+@BilZ@#=P}3bLEfP+hj6x%m7nV}x*hcQa!(o9BCk8b<^ytsjyO zq92$i?Z5ZtomCyKCG2TzF2NC&J2;KNAEn%ryNK+AAH92?1-tp$2b)=qCQhA+w+>bA z$7=x#c$j7ps0Ot2`~iXoG1;H3HZVtyE6(%m;v(Usb#FNQSB9d*W`l;czct99Tx$H}(Y?gqECohzF_b!?kZ_b7nO#?bc>+5GmpFqAy4x=|E zj6BNt?EjhvL(-Fll6+%iB)x6|xgX6-PbDQ-Qe;eFH0@QA&h(pqNW+5PtSO*`KXH+a z&&xQ1Vg6Pj=^j?{@?n7CRFfOR6MiSJ)l#y5$n5r-Bg zbPj22dK&?NpLVQPzCxy zQHZQayRjIpw%3OXUv09{g9gkC;Uo&}zo^7-hSXY04AJpDr)DPPgX_};k*}blXD_8u z4o}Yr?<*riZM0@Ek_UU_scRi#4h!l3#*Kgmo8om4HI2)VG=F+ zqYgd$x|VR1F!OFu`NvknjHi&+%WXtiLF75)L2h3=H8OgP1ZR{Wb+ za}b4(Kq3v&07Z6ltkmbPk++}WH=YY>MlDa*l|0Bs=h*h%Q3JvQO)y^_`88h+278!Q zu(udoi|wWx)l8ViEaxR11tq1xm|lk%88H6(-HLzb&c(cHHB}Xj?R^BA>h6VEv&LHB z;9sxbtw7+OBN1W#Gx<}Nw?q0gv7ZT4Z7%eR=i+~v$uyDX`6NKx6AXd%N&(ZIaR+Kk zeJKqZ>1a~T@;tv@0cd?{@@jVEN2QLsYKQu2${?tbJ<|dkh{T_vk!d;+h3H&gU(qaC z87{;f_FY?!aG>OdWkS-q{GpMSXP#A%tUJ7utl*@IbJUtGh9{y1ELw!DvnghTCeSZl z_e81duZfW#H(ly)`)?$D)7!v7_c-mod$h0W{h&ba*5dy`2D$CcfvEy}c=6~@faaw< zX6%g#V`-<=Y|88eQ#B_T;ZOkiDzq=8PxquJ38JA+;{FQ%&5$#qPX5i1`%JCr4V22z84V=i-8G(wXHKk&YXKqMaK zGn9s(e;e=j>*0OqTZzpp`$eWDNdisR=The>bj}o*ujWbiD-MRq-9hw7E0)k)jZ7Fj z0iVp>qwZ$PBONgS$XGPMDSA3P90{A~Zi6TSaMAbZWsQtQw0W#(cUXHx6PUfb5DNc` zJ_rI44q-s658;ONVAX`ZX-8$^oCRsDRQ6sXAJ;mxgIHUl-~x5H^Q{m@5;z~)zIU(5u`@69h<;u zTMBR{!t1D2;Tq+gFl~%7ky=BM!UCzRQlQDVQZT=vz0eDZn7Z@v$z#K*1&JdL`EQTZ zTZCSGp>PJpnH8Xr#3o080epe994v$TC!G+?6d+q(JzBSu{t;zhKZ9UP1$JxFL|e!m zmO`sN`+@0t{QKDIhnaP~=@5gth}8oUPtTKB8~qEhJ3Vz^pWHmy=4W|agJ1gGfQBBU zs*FhaF-Abj-gfdJ5mu)aXCbM!j-y_iFJq4DclAPU*JBwHuO$IhIrpftOhNdEhs)zt z%q*!)SG*(t0Kl1zCO1+$w(`HehE9Zl9H!ZT8P=W>0n1dRrDaiyiUCY~GH|A*H)<*V zNKXMGN%UG^T(YdV5#B!)^MMzd159gwo}ogzBG7X0^6iw=r?lvz(|>*>g}Y#TccYcBMEEx-Hw@DK2|_lsqy zb}Q>skVMbs96sytuWD^kk;1yI(+>k5!2l)L>t}N&N4*e@77fY5!3p}Euhz?vpe2(o zJJDknzN~Rq0aeY-RcS{O7F_`7!oQE=2qQINNR)PUhc`|7>P6q~qJcIA>zm5Wk*1PL z4`xmp+lJayS|s{P0BHQ5zRo8Ofsy(>E3oXyH_48Ptg43UJlh5Ds8D~c%`(UDg4Jo? zNXg=_^Dd+WIc&5_+xg#Wk$3ixvt(2F*mw2Fs)b{a^U;PV#E^N5^pAI}A8)2_+|PN4aQ$j^sh>zbpE);Lrl@Iey{uh^-_cqAywnJw8 zEJ4`nuL>+}*XVoL1hBOnUovWzq0-<;iaUancG6F&=9T3kZvoza>=iVX(5k& zSHqqe1>6~rIU6Hza)bykS|xo+=;*YBAd*Dp;sz;>kBIXq-?q_X4A*pO;=r5+plfQK zc?J{Dl>mug8|oNx5NZLVkXAbt1RCpgZ5HdReKN4@`6tSr++_+yZ6iBrRkftSa{obT z;;-H^6_7COT)SXX@)l7(7*oY_FVMb${4+uZ>GwuS4$N_?IG{qnTzEB#bix4`46H`f z1Hn^0J;ydS43(GS$fN7uu8p?S$;-*F=>(1I0vF?<(cW%-(vakbG#HXF*PG@}rM5wb zXQOOb`qp+eH&fNL#8 z^k5Ca2<8MW5=~i`nbmh1qteyO5C{6nj<0S4raf9R{_T(x4d_cyk`x`LUt_WNhDGL5 zB~oR@3(8`zbC7+DPP{&@45tAOK>EG`a1u%)V690sPv`*`necjEvZ1DDrT6oecJd@? zzd3|~0Cn>8chX@BBtpwbP}pT2u>Am!RCCGwhkdZTgw0g<+-XarB@ORv2Yvbsla(Oxg`e91Bn8$g`&fBm(tp3B`Z3jlYQpOyywQM*6@r4 z(SYU9&9c0a@8h*H$>&q@86PZVMhSC}D)~ZCjf)mx^xhFNpN=hu} zKB$b^9F?d?BYya7E8A4B{UyXhQy_gER*^_81}ZZ+%w0)vR;+eSOkvRij7ObLfA`*9 z*oQByN~8j}kkM!G*+Qi*KS?=Zm{bp+a{LzekT9{El(+V&)u!1VS*UbLs3mJpCghM> z+s3J!B1xU(vP(XvGs(VL?16f0r_5`pj0Z1u=oudhjCd5!DiSOpx6M8 zdOD+I(y10bK#Akq!#1Glt`Sx3{obaVos=lnhBQ}sgdLq!LsC~L1g}>h+%lOMV*`OB zsK+nlDgt0o1+3SxW$WePbV3rSiKc++*EZDsCS)PZQZ-xPjJ7fbnb#Q3zyws@WeBi? zJqk0QMPRfxHKbZ~^0IThJ2PZI^50+lhcaCeoEPzs&93>O*t2_;;hJ`(lLC?(Aj8nq zxs|OnflZ(%o05NeeI~kQJuMMSV)*UYX3+{LVX*EJx9`G7VX2C9%Nco5-wecR5NoU& z;Ix*JZZojbjt=Lr3NH0U4Wt8Y%nq1w#!m3aDj_iHEpjRxvTB_?X5*)PfD@M3+3m2C z?x0_Ku7Ld6P5Gyf_DP7VFMTz{l9QdtCUycdKsqH}%jkdiB1}fKo%XWxDV!l9tIvO9 zL9K6Lr~*rn{rDtvT*zc;hU6YJ0_4?oK?RR*WW&9h#*qUjQ_^X*EM6zfvRVlp526xn z_WoM(HsVA1{W@}i&fcVT_vJ72vjcu@!lea^Y&u?@5EkNODKX87arcek?zawis9jfS zmVI5R`R*45#)=xIl#P<$_S9O7A$d&LR*(6>cwgB@r}6&E6O-(#!>9#1oVN&rN@-9k zPh$cq*Q`>%fhwN13(;_jMo3m>1;~z^-$Pc|Be4AoIl~}C%3fEzE4b8s`Qz5{z9i;>bc7Of%8LQ z-+KjwONFfRcT*{{^7r-9@sb-E?G>*pHcEebm(fZ!rM0erGqZri6aBDdixpw7P+4rT zyB=hsx~Nt1manMH8&H724*ZLDyMDew3w5JME?2h95Z%lPjewGXmXX0g{_#OZ{_6@% zGwO|o{ccKII}>x$v)#A37;;;CbpvRNt)uW@uJXVBy+;vtm~WdZ*B*zj&^D&@Rb+opZQ%e4dMW>xooxAk9#5 zvvWx$mEw>zrUb$JDV+O~kSM3L1>)lxW}rgbZtwM3j{v>ierz54b}Q z>^`eA&wi&IF74rnScd31Fe(yVbQt&jhN-;gLx;Xz5GfwgVjD=`SX9n+^vRyT<^3ar zsOR;ae5HVDeoHftY(z5a=1dS&&r+)28Yk*J$gX4H;QB+Ma@RE0I)K$eV57uj=;fmd z9^o_W6BvPwhl43Kw0dP}RC^r$F}*aen8=*ZJrgBg=nW@4QYQy3vu^2J+oIX$Yg755 z$meOPaHpH~7}BvDY6Z&LFiFMv;&x)#A4Af&23!mpcp(qOoM1J@4%Ib-*ZZ7d5{jPh z%%s-uWEii`OCm!T`8E9JHA+MFvlcX*N0(U#m@0-Kh^>lhbgq>1=BV9w_Lkm2t;%Yz zA2!S_6%@j>Ln(ctD+^aEn0L$ghEkYtUi!{^TOZVkFST6^Je&Hzg$F-F?iYl5**cgR z6w+vw747Ti?Y2pVuZ!u4ZuITTvK>vUo_|~fpbd9Fvv!IyHiyhX&Icc(-%&6-Ezqi@ zg(F+GX!!473J?djF9e#2vo()Wm@04WS!aZhz5N=}!;G6KUC$Zm{e~JIvCH)Dna-FO zyY8hewxE0W9;Kba)j+$ZE72CIjad{vM0F2?hEO>P-Jvo}MfSL*$KU|f`l}aqEE1Aw zLx^h|S-SyLfx?i`4e`vOnLaTWDXdL{TBUhuN(k|5b3aFXZpOQi`i|1Der}Jw>Ys-W zqvylG@_=p~n%E>5M$71ZgWiK?C@A~u(VV$P-So=1=yUt9s-4*=E&+fPIKqyDpF`V| z`YKY}yNe3zAuUt|B2nb{hQ#(F?d6L_3A9B4rU%N|ZadqqFI*r$gEh?%*QTBT{*w^A zerQ)_buP5^*d9u^PAj@j?CF{@{#fgF0+qd`>xIw^0xO#uBsJ!EJt2)bSf| zLhWw!eB^(zhL3cxv^Ao1o#fBR@M|t`bL_#vqQtCbL;I#J%GdD|S!*AhR@HX-QtEp? zK5nQpOS?f2Z7_O=}zffxv80=#oFNK zVjcH&cZhEpt|Uz0j$MdgkaXmxY~a3-Sly>Qo-c*^**5`YKZS1>Yn6n@e2FD*BL+l9 zUv^!p^xpmW9*{^?DJ6tdC<%0C>&w(0M0`)R|3%Y|-trf4?{iCXlxx+KqDxSD%H6i{ znP)COHlxxbUJ8!urjHjro}5}5HrC8PB%E#Ir}FEEp&5|yOtT)r^1#VeZa?u-m!YB$ zo@Y~UpH2PPq4DO+dPMCSFLh|9q0HV7dn(J>DUl-A`@9)FO`78-O4~77bxqq%(oEtj zyqxu>hV%h&pfGl|X+0rdm002CxO~5->52MFGj68Mt79o**P{Y_)j=9?XrK_@CVZ`2ywe`ss92&r>B3 zUzvpK+_IaWKe?KtSjXVlk4>hb6aGSIKV|MKF`I-cp$|92YfqfIFa)n3@vril5D$9G z%o}Ym%Ns~^=UW|leR;b&2}~lk_>v~t#`QF+Pw-dAxNTRrnpVGni%;#s4MO^?eYC(^ za_yuy<~UEf$-2!NzgNeFI)%Z0Dq$wprQ=Zioo|vY)^fX~?6H>!ym6$?P064k8xQD52-GdLx&RBar0xFc&M zx%TL@xV6FP<_oHXsvjajD-u71+56ldCSF9X1`7EzEL{rax7@9I(F!dwQki)x&%`Z{ z>%U@5=eWA)RX?aeakDg0{TaRDGx{yPv&AvqolEWhk)hel{bKsjbk+&{%R{mwjiM`K z^JvXtUM6mrw|La;Vc3I?ABHT`Y0kW->Zd+c1PmxstPO8)^WLwjJ2&0OjEVuyG!@nJ zt<+PVtGyp>P`0m&E{@VLtu_!Hm?d`A?!WVJX3|Z>O# zRjzBU8yV>#6K{TXK=|C3ACnK53WONwSMM8M4BkvkTsWB$UN`MeK5sQ-d39+x zldpp)7M~!F3V7ik=h6?0d1n@MPNla8R3t5KURL95dquitjO&R_#Zc@psP;KEhkO@-6h(Z_3h)wSVAx9#0cVjJ? zS-tpbeumn4rnSV0HV@~J50e{-21Q8;gvw2qQW0_a(3_v;9S&c)dfj^bs8V7?l`ooq zL=2vEMSfmSow5q;5jg42!Q?Y9)%EgMaF$YhcA=YZuVDXT?H!I&OA3Qmym(m?ns=$q z>hBBAxt>>xroBM+exj5-VQXz3DZOv68P+;DMm*1Vk!j6!aVoevNo41S>0;HzorOQu z7X_^)Ysy?iwkN`6y)C;5hUFhy`1pj%o&BoV$zz0OFJ6i9O!$->FI1js)pMc9ZS>0( z@1>?>&Re>sAC^ZVV(VSsOQL8EG8)Ck__tS3xDH5F@%RH0N%eSRN$q&X73y_yL3<@JWveZ)2L7R6X(TW`rpJQsXv0 zp{RP@c7DIvAjO^!9vlOY-(;Go5B!n@H)YyU^U&5JFR!W_Il*gIy+@3_$2ICP`pn|% zVWr6~jvZfBWjXJ0qr><{!h+s;%O{DS9Q|au41to!1TUF&*-;Gt;{Vd;qb9jfxcavEJ9+Le}^ zaX~E4A3qyKRmE(BzrVHo0uB$HTt4qFA^{h1GsKDvjf+1a{&e}Ie?@n8O5EZ6RPmQ5 z3=Gi6>&U*~jd&@KvZ?cqTkV}(><2t4>J%c3t&k2>z$b%ETTj%WgOU13(UqyH6DxRV z!~9xs^mu)d_Rc88D~_LP2|W<;Z; znK+dzvnhOiswXj~sL159_deY0AYO-&UrgQDW-G$X=C6B~NV>$m_}vG+H}O=(iC35( zNzG1pWj?4kT_%n#c-%Q4_;}e;xp_#8X9a!Af7a;S+dvE-GG@55TG`K?c=;jzQbYc? z!$hy%dCOBJ-HXdP&%E%GHmgZh@fifc?U<$W9sx!daP0n@!~K#~Zg__Qe7|0Xyo<|= zKJm3Gx@}x-Op$z5sn?Xc{o3zpW={W>zP#a3r9h;)DHKbF(aXHxD>G`D!$6~ zafY7dsVT33NmR{RJ$LkB+?>QaH=m`)y)Kjzy_;8s)xFBA&TTL7m%2PLC~8djP$^l^ zQ@o&+Q6#UDzoZmOyk5KUCBh}0@Xc)Z-8k+=--Lu?eGeYK9zL`wUeG(?992Db%VDAI z&kT@mfS*6W&T`OjNa@VsD%cwePxKG1J@4feaYjN`^Ocj`w4DKv%6iD`_{9D)thehvg7(*RrBP|u#}=sJ%knD<(O%cT`bS5_5C6~GR`n|WB7f?^|y1bSH z`DOkWixl>zm^NZE2vr@u;^RVu1mk%;LB-pqtxk7j$<^c))d6?t+B5gwh!d5y$KVuK zri_A{hlj1^h~){Q-7!0HE|L-#mzpFd;MEtaBwUx|^1t&vtv!e-QXl!^Dp@e~I~(VC z%=r~?%~l!Bqz)Wj(~mbAy(>r**JU8v)#b*+UMC89v<*~#PcRA*rt1Adm*fAj$7X-r z-h`SrYBlEtzZbE~k`La|+U(Xo(vDU;%0m>NgK`;NW15_?24GRZpXQ`yYUe;)(*rR2#z&%v7?gF{9xlx(%a?zk-&G#p?0&_p&)2< z$4Clp>xSFc-wu5^HM-WyPCg=LaLdmDUY6l_v~+Ht^^^zOTSw+*dv#^i2l@ooFVk5` z{YEVHfd$U1mn+`{j#jm%!#^1QsBaBzte=-Cb?zh2h{2&z{ak)q_HOG;V+@vjYfVeG zPl$m93bigLD+_j-DuoKf6cSvV8%(SHje`%`80XaOO}8hhWk=R}MgMv;?~xwEpPUD5 zAx0MrsV{m>>4`86@UmJi5xFV78G6dxM{;m`l}KoZh z{IWOv{i-pqIC`OK)1#V*JD3+67ZZm^3s;LQZ3GZBM-K8=M{b24pG!Pl)}#h2#Sj7xAVW>{Hcyy_=q^^ncyTq<7#~B<;;P zmAU-6g@?_veqVYpl2g0;+~-)$D?-ZJ=d|B{>m~@?UVgLfD!*So(s%m+o`ZXMs@(7Q z;pm!ve{P(MqV$hHj@u#Rq_zKF|Ih#b-2c9p|Np-HKi!vQzNRt$+N|fXB7cB?h&yU> Jc{2B({~w$+7Iy#u From f8f52f4df8f82cd601419361c7cd3babdf9f2815 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 28 Jan 2022 17:08:02 +0530 Subject: [PATCH 63/72] remove color prop --- .../src/core/ToolbarMenu/ToolbarMenu.test.tsx | 3 +- .../src/core/ToolbarMenu/ToolbarMenu.tsx | 28 +++------------ .../toolbar-menu/with-blui-app-bar.tsx | 2 -- docs/ToolbarMenu.md | 35 +++++++++---------- 4 files changed, 24 insertions(+), 44 deletions(-) diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx index 5d20ed729..32a073629 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx @@ -21,6 +21,7 @@ describe('ToolbarMenu', () => { afterEach(() => { mount.cleanUp(); }); + it('should render without crashing', () => { const div = document.createElement('div'); ReactDOM.render(, div); @@ -28,7 +29,7 @@ describe('ToolbarMenu', () => { it('renders with label', () => { const wrapper = shallow(); - expect(findByTestId('toolbar-menu', wrapper).length).toEqual(1); + expect(findByTestId('label', wrapper).length).toEqual(1); }); it('renders with icon', () => { diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 214b233c6..d984b9e0a 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -1,14 +1,14 @@ import React, { HTMLAttributes, useState, useCallback, useRef, useEffect } from 'react'; -import composeRefs from '@seznam/compose-react-refs'; import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; import clsx from 'clsx'; import createStyles from '@material-ui/core/styles/createStyles'; +import composeRefs from '@seznam/compose-react-refs'; import { DrawerNavGroup, NavItem } from '../Drawer'; import makeStyles from '@material-ui/core/styles/makeStyles'; import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; +import PropTypes from 'prop-types'; import { Theme } from '@material-ui/core/styles/createMuiTheme'; import useTheme from '@material-ui/core/styles/useTheme'; -import PropTypes from 'prop-types'; import Typography from '@material-ui/core/Typography'; export type ToolbarMenuClasses = { @@ -65,12 +65,7 @@ const useStyles = makeStyles((theme: Theme) => }) ); -export type ToolbarMenuProps = HTMLAttributes & { - /** The color used for the text elements - * - * Default: 'inherit' - */ - color?: string; +export type ToolbarMenuProps = HTMLAttributes & { /** A component to render for the icon */ icon?: JSX.Element; /** Label Content */ @@ -93,19 +88,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { - const { - classes = {}, - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - color, - icon, - label, - menuGroups, - menu, - MenuProps, - onClose, - onOpen, - ...otherSpanProps - } = props; + const { icon, label, menu, menuGroups, MenuProps, onClose, onOpen, classes = {} } = props; const theme = useTheme(); const rtl = theme.direction === 'rtl'; const defaultClasses = useStyles(props); @@ -190,7 +173,6 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { openMenu(anchor.current); }} diff --git a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx index 490a1b6bd..834066302 100644 --- a/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx +++ b/demos/storybook/stories/toolbar-menu/with-blui-app-bar.tsx @@ -8,7 +8,6 @@ import { IconButton, makeStyles, Toolbar, useMediaQuery, useTheme } from '@mater import { action } from '@storybook/addon-actions'; import { getDirection } from '@brightlayer-ui/storybook-rtl-addon'; import clsx from 'clsx'; -// import * as Colors from '@brightlayer-ui/colors'; import { getBodyFiller } from '../../src/utils'; const menuItems = [ @@ -89,7 +88,6 @@ export const withBluiAppBar = (): StoryFnReactReturnType => { const title = text('title', 'title', threeLinerGroupId); const info = text('info', 'info', threeLinerGroupId); // ToolbarMenu props - // const toolbarColor = color('color', Colors.white[50], toolbarMenuGroupId); const toolbarLabel = text('label', 'Subtitle', toolbarMenuGroupId); return ( <> diff --git a/docs/ToolbarMenu.md b/docs/ToolbarMenu.md index 777089524..97b05e95a 100644 --- a/docs/ToolbarMenu.md +++ b/docs/ToolbarMenu.md @@ -33,17 +33,16 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components';
-| Prop Name | Description | Type | Required | Default | -| ---------- | -------------------------------------------- | --------------------- | -------- | --------- | -| classes | Style Overrides | `ToolbarMenuClasses` | no | | -| color | The color of the font | `string` | no | 'inherit' | -| icon | The inline icon to display | `JSX.Element` | no | | -| label | Custom content for label text / icon + label | `ReactNode` | yes | | -| menu | Custom content to be displayed in the menu | Material-UI `Menu` | no | | -| menuGroups | Groups of menu items to display | `ToolbarMenuGroups[]` | no | | -| MenuProps | Property overrides for the MUI Menu | `MenuProps` | no | | -| onClose | Function called when the menu is closed | `Function` | no | | -| onOpen | Function called when the menu is opened | `Function` | no | | +| Prop Name | Description | Type | Required | Default | +| ---------- | -------------------------------------------- | --------------------- | -------- | ------- | +| classes | Style Overrides | `ToolbarMenuClasses` | no | | +| icon | The inline icon to display | `JSX.Element` | no | | +| label | Custom content for label text / icon + label | `ReactNode` | yes | | +| menu | Custom content to be displayed in the menu | Material-UI `Menu` | no | | +| menuGroups | Groups of menu items to display | `ToolbarMenuGroups[]` | no | | +| MenuProps | Property overrides for the MUI Menu | `MenuProps` | no | | +| onClose | Function called when the menu is closed | `Function` | no | | +| onOpen | Function called when the menu is opened | `Function` | no | |
@@ -51,13 +50,13 @@ import { ToolbarMenu } from '@brightlayer-ui/react-components'; You can override the classes used by Brightlayer UI by passing a `classes` prop. It supports the following keys: -| Name | Description | -| ------------- | ---------------------------------------------------- | -| dropdownArrow | Styles applied to the dropdownArrow container | -| label | Styles applied to the label / icon + label text | -| labelContent | Styles applied to the label / icon + label container | -| menuItem | Styles applied to the menu item | -| root | Styles applied to the root element | +| Name | Description | +| ------------- | --------------------------------------------- | +| dropdownArrow | Styles applied to the dropdownArrow container | +| icon | Styles applied to the icon container | +| label | Styles applied to the label text | +| menuItem | Styles applied to the menu item | +| root | Styles applied to the root element | ### Toolbar Menu Groups Object From 7ee158eb1aadc05fee941348567bb4adbf27f2fa Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 28 Jan 2022 17:14:32 +0530 Subject: [PATCH 64/72] fix prettier --- CHANGELOG.md | 2 +- components/src/core/ToolbarMenu/ToolbarMenu.test.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79880bbde..4c189864d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - Added 1rem default padding to the root styles of ``. ([#320](https://github.com/brightlayer-ui/react-component-library/issues/320)) - Added new property `unitSpace` to `` to manage spacing between the value and units. ([#350](https://github.com/brightlayer-ui/react-component-library/issues/350)) - Added `` component. ([#351](https://github.com/brightlayer-ui/react-component-library/issues/351)) -- Added Deprecation warnings for DropdownToolbar component that will be removing in version 6.0.0. +- Added Deprecation warnings for DropdownToolbar component that will be removed in version 6.0.0. ## v5.3.3 (December 6, 2021) diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx index 32a073629..87a70690c 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.test.tsx @@ -21,7 +21,7 @@ describe('ToolbarMenu', () => { afterEach(() => { mount.cleanUp(); }); - + it('should render without crashing', () => { const div = document.createElement('div'); ReactDOM.render(, div); From 934f9fb103d17cc133a6d418dd6a44357165c525 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 28 Jan 2022 17:21:06 +0530 Subject: [PATCH 65/72] fix prettier --- demos/storybook/stories/channel-value/with-full-config.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/demos/storybook/stories/channel-value/with-full-config.tsx b/demos/storybook/stories/channel-value/with-full-config.tsx index 4748c1323..603719147 100644 --- a/demos/storybook/stories/channel-value/with-full-config.tsx +++ b/demos/storybook/stories/channel-value/with-full-config.tsx @@ -14,7 +14,9 @@ export const withFullConfig = (): StoryFnReactReturnType => { const iconColor = color('icon.htmlColor', Colors.red[500]); const icon = boolean('Show Icon', true) ? ( - ) : undefined; + ) : ( + undefined + ); const fontSize = number('fontSize', 30); const prefix = boolean('prefix', false); const unitSpace = select('unitSpace', ['show', 'hide', 'auto'], 'auto'); From 4b58886ab107fbbddab49f991709be7c1c458aa1 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 31 Jan 2022 17:13:33 +0530 Subject: [PATCH 66/72] add other typography prop --- .../src/core/ToolbarMenu/ToolbarMenu.tsx | 12 ++-- .../stories/toolbar-menu/_module.stories.tsx | 1 + .../toolbar-menu/label-with-variant.tsx | 59 +++++++++++++++++++ docs/ToolbarMenu.md | 1 - 4 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 demos/storybook/stories/toolbar-menu/label-with-variant.tsx diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index d984b9e0a..797da0a20 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -1,4 +1,4 @@ -import React, { HTMLAttributes, useState, useCallback, useRef, useEffect } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; import clsx from 'clsx'; import createStyles from '@material-ui/core/styles/createStyles'; @@ -9,14 +9,13 @@ import Menu, { MenuProps as standardMenuProps } from '@material-ui/core/Menu'; import PropTypes from 'prop-types'; import { Theme } from '@material-ui/core/styles/createMuiTheme'; import useTheme from '@material-ui/core/styles/useTheme'; -import Typography from '@material-ui/core/Typography'; +import Typography, { TypographyProps } from '@material-ui/core/Typography'; export type ToolbarMenuClasses = { root?: string; dropdownArrow?: string; icon?: string; label?: string; - menuItem?: string; }; export type ToolbarMenuCompItem = Omit & { itemID?: string }; @@ -35,7 +34,6 @@ const useStyles = makeStyles((theme: Theme) => createStyles({ root: { cursor: 'pointer', - fontSize: '1rem', display: 'flex', alignItems: 'center', }, @@ -65,7 +63,7 @@ const useStyles = makeStyles((theme: Theme) => }) ); -export type ToolbarMenuProps = HTMLAttributes & { +export type ToolbarMenuProps = TypographyProps & { /** A component to render for the icon */ icon?: JSX.Element; /** Label Content */ @@ -88,7 +86,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { - const { icon, label, menu, menuGroups, MenuProps, onClose, onOpen, classes = {} } = props; + const { icon, label, menu, menuGroups, MenuProps, onClose, onOpen, classes = {}, ...otherTypographyProps } = props; const theme = useTheme(); const rtl = theme.direction === 'rtl'; const defaultClasses = useStyles(props); @@ -175,6 +173,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction { + const menuItems = [ + { title: 'Item 1', onClick: action('Item 1 selected') }, + { title: 'Item 2', onClick: action('Item 2 selected') }, + { title: 'Item 3', onClick: action('Item 3 selected') }, + ]; + + const menuGroups = [ + { + items: menuItems, + }, + ]; + const useStyles = makeStyles({ + textContent: { + overflow: 'hidden', + whiteSpace: 'nowrap', + // set margins to default to avoid the height of the app bar exceeding 56px on mobile + '&.MuiListItemText-multiline': { + marginTop: '0.25rem', + marginBottom: '0.25rem', + }, + }, + toolbarGutters: { + padding: `0 16px`, + }, + root: { + marginLeft: 20, + }, + }); + + const classes = useStyles(); + return ( + + + + + + + + + ); +}; + +labelWithVariant.story = { name: 'label with variant' }; diff --git a/docs/ToolbarMenu.md b/docs/ToolbarMenu.md index 97b05e95a..257ec3e43 100644 --- a/docs/ToolbarMenu.md +++ b/docs/ToolbarMenu.md @@ -55,7 +55,6 @@ You can override the classes used by Brightlayer UI by passing a `classes` prop. | dropdownArrow | Styles applied to the dropdownArrow container | | icon | Styles applied to the icon container | | label | Styles applied to the label text | -| menuItem | Styles applied to the menu item | | root | Styles applied to the root element | ### Toolbar Menu Groups Object From 697f95800aee085b867d98e617a22668e57963ba Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 1 Feb 2022 10:56:19 +0530 Subject: [PATCH 67/72] fix rtl menuprops --- components/src/core/ToolbarMenu/ToolbarMenu.tsx | 1 + .../toolbar-menu/with-menu-placement-options.tsx | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 797da0a20..1fa6acce3 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -36,6 +36,7 @@ const useStyles = makeStyles((theme: Theme) => cursor: 'pointer', display: 'flex', alignItems: 'center', + maxWidth: 'fit-content', }, cursorPointer: { cursor: 'pointer', diff --git a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx index c9a2a9c49..c71edcc78 100644 --- a/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx +++ b/demos/storybook/stories/toolbar-menu/with-menu-placement-options.tsx @@ -20,7 +20,12 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { 'left', 'Menu' ); - const anchorOriginVertical = select('menuProps.anchorOrigin.vertical', ['top', 'center', 'bottom'], 'top', 'Menu'); + const anchorOriginVertical = select( + 'menuProps.anchorOrigin.vertical', + ['top', 'center', 'bottom'], + 'bottom', + 'Menu' + ); const transformOriginHorizontal = select( 'menuProps.transformOrigin.horizontal', ['left', 'center', 'right'], @@ -35,9 +40,9 @@ export const withMenuPlacementOptions = (): StoryFnReactReturnType => { ); const menuItems = [ - { title: 'Item 1', onClick: action('Item 1 selected') }, - { title: 'Item 2', onClick: action('Item 2 selected') }, - { title: 'Item 3', onClick: action('Item 3 selected') }, + { title: 'Menu Item 1', onClick: action('Item 1 selected') }, + { title: 'Menu Item 2', onClick: action('Item 2 selected') }, + { title: 'Menu Item 3', onClick: action('Item 3 selected') }, ]; const menuGroups = [ From 84aad63d7d48c4b1e7ff09bf91ed3c1050d63ac0 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Tue, 1 Feb 2022 22:43:15 +0530 Subject: [PATCH 68/72] allow classname prop --- components/src/core/ToolbarMenu/ToolbarMenu.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/src/core/ToolbarMenu/ToolbarMenu.tsx b/components/src/core/ToolbarMenu/ToolbarMenu.tsx index 1fa6acce3..bf265f635 100644 --- a/components/src/core/ToolbarMenu/ToolbarMenu.tsx +++ b/components/src/core/ToolbarMenu/ToolbarMenu.tsx @@ -64,7 +64,7 @@ const useStyles = makeStyles((theme: Theme) => }) ); -export type ToolbarMenuProps = TypographyProps & { +export type ToolbarMenuProps = Omit & { /** A component to render for the icon */ icon?: JSX.Element; /** Label Content */ @@ -178,6 +178,7 @@ const ToolbarMenuRenderer: React.ForwardRefRenderFunction Date: Thu, 3 Feb 2022 16:13:32 +0530 Subject: [PATCH 69/72] publish beta version --- CHANGELOG.md | 2 +- components/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c189864d..2aaaf13e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v5.4.0 (Unreleased) +## v5.4.0-beta.1 (Unreleased) ### Added diff --git a/components/package.json b/components/package.json index ef67f7326..0cad89a9e 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "@brightlayer-ui/react-components", - "version": "5.4.0-beta.0", + "version": "5.4.0-beta.1", "description": "React components for Brightlayer UI applications", "scripts": { "test": "jest src", From ba4247f2b17b8ff4ed704acbf4058713375a514b Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 4 Feb 2022 11:05:35 +0530 Subject: [PATCH 70/72] update variant knob --- .../storybook/stories/toolbar-menu/label-with-variant.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/demos/storybook/stories/toolbar-menu/label-with-variant.tsx b/demos/storybook/stories/toolbar-menu/label-with-variant.tsx index 47370da86..fba6b4166 100644 --- a/demos/storybook/stories/toolbar-menu/label-with-variant.tsx +++ b/demos/storybook/stories/toolbar-menu/label-with-variant.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; +import { select } from '@storybook/addon-knobs'; import AppBar from '@material-ui/core/AppBar'; import makeStyles from '@material-ui/core/styles/makeStyles'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; @@ -39,6 +40,11 @@ export const labelWithVariant = (): StoryFnReactReturnType => { }); const classes = useStyles(); + const variant = select( + 'variant', + ['body1', 'body2', 'button', 'caption', 'h5', 'h6', 'inherit', 'overline', 'subtitle1', 'subtitle2'], + 'h6' + ); return ( @@ -47,7 +53,7 @@ export const labelWithVariant = (): StoryFnReactReturnType => { From 2db3fb2271a1e4a5f26680bf93f14a1a1f55e325 Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Fri, 4 Feb 2022 11:24:23 +0530 Subject: [PATCH 71/72] update label knob --- .../stories/toolbar-menu/label-with-variant.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/demos/storybook/stories/toolbar-menu/label-with-variant.tsx b/demos/storybook/stories/toolbar-menu/label-with-variant.tsx index fba6b4166..67d0121f2 100644 --- a/demos/storybook/stories/toolbar-menu/label-with-variant.tsx +++ b/demos/storybook/stories/toolbar-menu/label-with-variant.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; -import { select } from '@storybook/addon-knobs'; +import { select, text } from '@storybook/addon-knobs'; import AppBar from '@material-ui/core/AppBar'; import makeStyles from '@material-ui/core/styles/makeStyles'; import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; @@ -40,6 +40,7 @@ export const labelWithVariant = (): StoryFnReactReturnType => { }); const classes = useStyles(); + const label = text('label', 'Click To Open'); const variant = select( 'variant', ['body1', 'body2', 'button', 'caption', 'h5', 'h6', 'inherit', 'overline', 'subtitle1', 'subtitle2'], @@ -51,12 +52,7 @@ export const labelWithVariant = (): StoryFnReactReturnType => { - + ); From 74a1f3c34348597d570850069244b9c5d6c80dba Mon Sep 17 00:00:00 2001 From: Ekta Ghag Date: Mon, 7 Feb 2022 18:53:06 +0530 Subject: [PATCH 72/72] 5.4.0 package publish --- CHANGELOG.md | 2 +- components/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aaaf13e6..4f6be1c38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v5.4.0-beta.1 (Unreleased) +## v5.4.0 (February 8, 2022) ### Added diff --git a/components/package.json b/components/package.json index 0cad89a9e..60d6e5455 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "@brightlayer-ui/react-components", - "version": "5.4.0-beta.1", + "version": "5.4.0", "description": "React components for Brightlayer UI applications", "scripts": { "test": "jest src",