diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCard.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCard.md new file mode 100644 index 00000000..fbc54dbe --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCard.md @@ -0,0 +1,55 @@ +--- +section: extensions +subsection: Component groups +id: Multi content card +source: react +propComponents: ['MultiContentCard'] +sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCard.md +--- + +import MultiContentCard from "@patternfly/react-component-groups/dist/dynamic/MultiContentCard"; +import { ArrowRightIcon, BellIcon, CogIcon, EllipsisVIcon, LockIcon } from '@patternfly/react-icons'; + +A **multi content card** component allows to display multiple card components in a single layout. To further customize this layout, you can also utilize all properties of the [card component](/components/card), with the exception of `children` and `title`. + +## Examples + +### Basic multi content card + +To display a basic multi content an array of content cards has to be passed using the `cards` property. It is recommended to use regular [card components](/components/card) in the content. + +```js file="./MultiContentCardExample.tsx" + +``` + +### Expandable multi content card + +To make the multi content card expandable, pass `isExpandable` flag together with `toggleText` or `toggleContent` property. Default expansion state can be adjusted using `defaultExpanded` property. + +```js file="./MultiContentCardExpandableExample.tsx" + +``` + +### Expandable multi content card with actions + +Actions can be displayed in the multi content card heading using `actions` property. + +```js file="./MultiContentCardExpandableActionsExample.tsx" + +``` + +### Expandable multi content card with left border and header border + +Left border can be displayed using `leftBorderVariant`. To display a border under the multi content card's heading, use `withHeaderBorder` flag. + +```js file="./MultiContentCardExpandableBorderExample.tsx" + +``` + +### Expandable multi content card with dividers + +Dividers between cards in the content can be shown using `withDividers` flag. + +```js file="./MultiContentCardExpandableDividerExample.tsx" + +``` diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExample.tsx new file mode 100644 index 00000000..ab3da5fe --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExample.tsx @@ -0,0 +1,99 @@ +import React from 'react'; +import MultiContentCard from "@patternfly/react-component-groups/dist/dynamic/MultiContentCard"; +import { Button, Card, CardHeader, CardBody, Text, TextContent, TextVariants, Icon, TextList, TextListItem, CardFooter } from '@patternfly/react-core'; +import { ArrowRightIcon, BellIcon, CogIcon, LockIcon } from '@patternfly/react-icons'; + +const cards = [ + + + + Getting Started + + + + + + + + + Configure application + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + , + + + + + + + + Configure access + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + + + + + + + + + , + + + + Next Steps + + + + + + + + + Configure notifications + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + +]; + +export const BasicExample: React.FunctionComponent = () => ; diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableActionsExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableActionsExample.tsx new file mode 100644 index 00000000..3c48f5c8 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableActionsExample.tsx @@ -0,0 +1,145 @@ +import React from 'react'; +import MultiContentCard from "@patternfly/react-component-groups/dist/dynamic/MultiContentCard"; +import { EllipsisVIcon } from '@patternfly/react-icons'; +import { Button, Card, CardHeader, CardBody, CardFooter, Text, TextContent, TextVariants, Icon, TextList, TextListItem, Divider, Dropdown, DropdownItem, DropdownList, MenuToggle, MenuToggleElement } from '@patternfly/react-core'; +import { ArrowRightIcon, BellIcon, CogIcon, LockIcon } from '@patternfly/react-icons'; + +const cards = [ + + + + Getting Started + + + + + + + + + Configure application + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + , + + + + + + + + Configure access + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + + + + + + + + + , + + + + Next Steps + + + + + + + + + Configure notifications + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + +]; + +export const BasicExample: React.FunctionComponent = () => { + const [ isMenuOpen, setMenuOpen ] = React.useState(false) + + const onToggleClick = () => { + setMenuOpen(!isMenuOpen); + }; + return ( + null} + onOpenChange={(isMenuOpen: boolean) => setMenuOpen(isMenuOpen)} + toggle={(toggleRef: React.Ref) => ( + + + + )} + shouldFocusToggleOnSelect + > + + + Action + + + Disabled Action + + + + Separated Action + + + + } + /> + ) +}; diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableBorderExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableBorderExample.tsx new file mode 100644 index 00000000..a913f430 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableBorderExample.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import MultiContentCard from "@patternfly/react-component-groups/dist/dynamic/MultiContentCard"; +import { Button, Card, CardHeader, CardBody, CardFooter, Text, TextContent, TextVariants, Icon, TextList, TextListItem } from '@patternfly/react-core'; +import { ArrowRightIcon, BellIcon, CogIcon, LockIcon } from '@patternfly/react-icons'; +const cards = [ + + + + Getting Started + + + + + + + + + Configure application + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + , + + + + + + + + Configure access + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + + + + + + + + + , + + + + Next Steps + + + + + + + + + Configure notifications + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + +]; + +export const BasicExample: React.FunctionComponent = () => ( + +); diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableDividerExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableDividerExample.tsx new file mode 100644 index 00000000..d3cdd92d --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableDividerExample.tsx @@ -0,0 +1,99 @@ +import React from 'react'; +import MultiContentCard from "@patternfly/react-component-groups/dist/dynamic/MultiContentCard"; +import { Button, Card, CardHeader, CardBody, CardFooter, Text, TextContent, TextVariants, Icon, TextList, TextListItem } from '@patternfly/react-core'; +import { ArrowRightIcon, BellIcon, CogIcon, LockIcon } from '@patternfly/react-icons'; + +const cards = [ + + + + Getting Started + + + + + + + + + Configure application + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + , + + + + + + + + Configure access + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + + + + + + + + + , + + + + Next Steps + + + + + + + + + Configure notifications + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + +]; + +export const BasicExample: React.FunctionComponent = () => ; diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableExample.tsx new file mode 100644 index 00000000..e119e168 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/MultiContentCard/MultiContentCardExpandableExample.tsx @@ -0,0 +1,99 @@ +import React from 'react'; +import MultiContentCard from "@patternfly/react-component-groups/dist/dynamic/MultiContentCard"; +import { Button, Card, CardHeader, CardBody, CardFooter, Text, TextContent, TextVariants, Icon, TextList, TextListItem } from '@patternfly/react-core'; +import { ArrowRightIcon, BellIcon, CogIcon, LockIcon } from '@patternfly/react-icons'; + +const cards = [ + + + + Getting Started + + + + + + + + + Configure application + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + , + + + + + + + + Configure access + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + + + + + + + + + , + + + + Next Steps + + + + + + + + + Configure notifications + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + +]; + +export const BasicExample: React.FunctionComponent = () => ; diff --git a/packages/module/src/LogSnippet/LogSnippet.tsx b/packages/module/src/LogSnippet/LogSnippet.tsx index da251aec..742a4e4e 100644 --- a/packages/module/src/LogSnippet/LogSnippet.tsx +++ b/packages/module/src/LogSnippet/LogSnippet.tsx @@ -3,7 +3,7 @@ import { CodeBlock, CodeBlockCode, Flex, FlexItem, FlexProps, Text, TextVariants import clsx from 'clsx'; import { createUseStyles } from 'react-jss' -export type BorderVariant = 'danger' | 'success' | 'info' | 'warning'; +export type LogSnippetBorderVariant = 'danger' | 'success' | 'info' | 'warning'; export interface LogSnippetProps extends FlexProps { /** Log snippet or code to be displayed */ @@ -11,7 +11,7 @@ export interface LogSnippetProps extends FlexProps { /** Message to appear above the log snippet */ message: string | React.ReactNode; /** Custom color for left border */ - leftBorderVariant?: BorderVariant; + leftBorderVariant?: LogSnippetBorderVariant; } const useStyles = createUseStyles({ diff --git a/packages/module/src/MultiContentCard/MultiContentCard.test.tsx b/packages/module/src/MultiContentCard/MultiContentCard.test.tsx new file mode 100644 index 00000000..806a0ca8 --- /dev/null +++ b/packages/module/src/MultiContentCard/MultiContentCard.test.tsx @@ -0,0 +1,194 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import { Button, Card, CardHeader, CardBody, Text, TextContent, TextVariants, Icon, TextList, TextListItem, CardFooter, Dropdown, MenuToggle, DropdownList, DropdownItem, MenuToggleElement } from '@patternfly/react-core'; +import { ArrowRightIcon, BellIcon, CogIcon, EllipsisVIcon, LockIcon } from '@patternfly/react-icons'; +import MultiContentCard from './MultiContentCard'; + +const cards = [ + + + + Getting Started + + + + + + + + + Configure application + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + + + + + + + + + + + , + + + + + + + + Configure access + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + + + + + + + + + , + + + + Next Steps + + + + + + + + + Configure notifications + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + + + + + + +]; + +describe('MultiContentCard component', () => { + it('should render basic multi content card', () => { + const { container } = render(); + expect(screen.getByText('Getting Started')).toBeInTheDocument(); + expect(screen.getByText('Next Steps')).toBeInTheDocument(); + expect(screen.getByText('Configure application')).toBeInTheDocument(); + expect(screen.getByText('Configure access')).toBeInTheDocument(); + expect(screen.getByText('Configure notifications')).toBeInTheDocument(); + expect(screen.getAllByText('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.')).toHaveLength(2); + expect(screen.getByText('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.')).toBeInTheDocument(); + expect(screen.getByText('First link')).toBeInTheDocument(); + expect(screen.getByText('Second link')).toBeInTheDocument(); + expect(screen.getByText('Another link')).toBeInTheDocument(); + expect(screen.getAllByText('Learn more')).toHaveLength(2); + + expect(container.firstChild).toMatchSnapshot(); + }); + + it('should render expandable multi content card - expanded', () => { + const { container } = render( + + ); + expect(screen.getByText('Expandable card toggle text')).toBeInTheDocument(); + expect(screen.getByText('Getting Started')).toBeInTheDocument(); + + expect(container.firstChild).toMatchSnapshot(); + }); + + it('should render expandable multi content card - collapsed', () => { + const { container } = render( + + ); + expect(screen.getByText('Expandable card toggle text')).toBeInTheDocument(); + expect(screen.queryByText('Getting Started')).toBe(null); + + expect(container.firstChild).toMatchSnapshot(); + }); + + it('should render expandable multi content card - with actions', () => { + const { container } = render( + null} + onOpenChange={() => null} + toggle={(toggleRef: React.Ref) => ( + null} + isExpanded + > + + + )} + shouldFocusToggleOnSelect + > + + + Action item + + + + } + /> + ); + expect(screen.getByText('Action item')).toBeInTheDocument(); + + expect(container.firstChild).toMatchSnapshot(); + }); + + it('should render multi content card with dividers', () => { + const { container } = render(); + + expect(screen.getAllByRole('separator')).toHaveLength(2); + + expect(container.firstChild).toMatchSnapshot(); + }); + +}); \ No newline at end of file diff --git a/packages/module/src/MultiContentCard/MultiContentCard.tsx b/packages/module/src/MultiContentCard/MultiContentCard.tsx new file mode 100644 index 00000000..28ce0273 --- /dev/null +++ b/packages/module/src/MultiContentCard/MultiContentCard.tsx @@ -0,0 +1,108 @@ +import React from 'react'; +import { + Card, + CardExpandableContent, + CardHeader, + CardProps, + CardTitle, + Divider, + Flex, + FlexItem, + Title, +} from '@patternfly/react-core'; +import { createUseStyles } from 'react-jss'; +import clsx from 'clsx'; + +export type MultiContentCardBorderVariant = 'primary' | 'danger' | 'success' | 'info' | 'warning' | 'hidden'; + +export interface MultiContentCardProps extends Omit { + /** Cards to be displayed as a content */ + cards?: React.ReactElement[]; + /** Actions to be displayed in the expandable section */ + actions?: React.ReactElement; + /** Toggle text for the expandable section */ + toggleText?: string; + /** Toggle content for the expandable section */ + toggleContent?: React.ReactElement; + /** Left border variant for the containing card */ + leftBorderVariant?: MultiContentCardBorderVariant; + /** Indicates whether the content is separated by dividers */ + withDividers?: boolean; + /** Indicates whether the card is expandable */ + isExpandable?: boolean; + /** Indicates whether the card is expanded by default */ + defaultExpanded?: boolean; + /** Indicates whether the actions toggle is right aligned */ + isToggleRightAligned?: boolean; + /** Indicates whether the card header has a bottom border */ + withHeaderBorder?: boolean +} + +const useStyles = createUseStyles({ + multiContentCardHeadingBorder: { + borderBottom: 'var(--pf-v5-global--BorderWidth--sm) solid var(--pf-v5-global--disabled-color--200)', + }, + multiContentCardLeftBorder: (leftBorderVariant: MultiContentCardBorderVariant) => ({ + borderLeft: `var(--pf-v5-global--BorderWidth--lg) solid var(--pf-v5-global--${leftBorderVariant}-color--100)` + }) +}) + +const MultiContentCard: React.FunctionComponent = ({ + cards = [], + isToggleRightAligned = false, + actions, + toggleText, + toggleContent, + withDividers = false, + leftBorderVariant = 'hidden', + isExpandable = false, + defaultExpanded = true, + withHeaderBorder = false, + ...rest +}: MultiContentCardProps) => { + const classes = useStyles(leftBorderVariant); + const [ isExpanded, setIsExpanded ] = React.useState(defaultExpanded); + const onExpand = () => { + setIsExpanded(!isExpanded); + }; + + const renderCards = (cards: React.ReactElement[], withDividers?: boolean) => ( + + {cards.map((card, index) => ( + <> + + {card} + + {(index + 1 < cards.length && withDividers) && ( + + )} + + ))} + + ); + + return( + + {isExpandable && ( + + {toggleText ? {toggleText} : toggleContent} + + )} + {isExpandable ? {renderCards(cards, withDividers)} : renderCards(cards, withDividers)} + + );} + + +export default MultiContentCard; diff --git a/packages/module/src/MultiContentCard/__snapshots__/MultiContentCard.test.tsx.snap b/packages/module/src/MultiContentCard/__snapshots__/MultiContentCard.test.tsx.snap new file mode 100644 index 00000000..039c3b05 --- /dev/null +++ b/packages/module/src/MultiContentCard/__snapshots__/MultiContentCard.test.tsx.snap @@ -0,0 +1,1394 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MultiContentCard component should render basic multi content card 1`] = ` +
+
+
+
+
+
+
+

+ Getting Started +

+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +

+
+
+ +
+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +

+
+
+ +
+
+
+
+
+
+
+

+ Next Steps +

+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +

+
+
+ +
+
+
+
+`; + +exports[`MultiContentCard component should render expandable multi content card - collapsed 1`] = ` +
+
+
+ +
+
+
+
+
+

+ Expandable card toggle text +

+
+
+
+
+
+`; + +exports[`MultiContentCard component should render expandable multi content card - expanded 1`] = ` +
+
+
+ +
+
+
+
+
+

+ Expandable card toggle text +

+
+
+
+
+
+
+
+
+
+
+
+

+ Getting Started +

+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +

+
+
+ +
+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +

+
+
+ +
+
+
+
+
+
+
+

+ Next Steps +

+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +

+
+
+ +
+
+
+
+
+`; + +exports[`MultiContentCard component should render expandable multi content card - with actions 1`] = ` +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+

+ Expandable card toggle text +

+
+
+
+
+
+`; + +exports[`MultiContentCard component should render multi content card with dividers 1`] = ` +
+
+
+
+
+
+
+

+ Getting Started +

+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +

+
+
+ +
+
+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +

+
+
+ +
+
+
+
+
+
+
+
+

+ Next Steps +

+
+
+
+
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +

+
+
+ +
+
+
+
+`; diff --git a/packages/module/src/MultiContentCard/index.ts b/packages/module/src/MultiContentCard/index.ts new file mode 100644 index 00000000..ca5de327 --- /dev/null +++ b/packages/module/src/MultiContentCard/index.ts @@ -0,0 +1,2 @@ +export { default } from './MultiContentCard' +export * from './MultiContentCard' diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts index 8dd9f102..93071ff6 100644 --- a/packages/module/src/index.ts +++ b/packages/module/src/index.ts @@ -39,6 +39,9 @@ export * from './InvalidObject'; export { default as LogSnippet } from './LogSnippet'; export * from './LogSnippet'; +export { default as MultiContentCard } from './MultiContentCard'; +export * from './MultiContentCard'; + export { default as NotAuthorized } from './NotAuthorized'; export * from './NotAuthorized';