Skip to content

Commit

Permalink
Merge pull request #281 from brionmario/migrate-default-props
Browse files Browse the repository at this point in the history
fix(react): fix component composition issues
  • Loading branch information
brionmario authored Oct 11, 2024
2 parents a9685e1 + 262b1c9 commit 6a4c3d4
Show file tree
Hide file tree
Showing 165 changed files with 4,390 additions and 1,846 deletions.
52 changes: 43 additions & 9 deletions packages/react/src/components/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com).
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
Expand All @@ -17,23 +17,57 @@
*/

import MuiAccordion, {AccordionProps as MuiAccordionProps} from '@mui/material/Accordion';
import type {OverridableComponent} from '@mui/material/OverridableComponent';
import clsx from 'clsx';
import {FC, ReactElement} from 'react';
import {forwardRef} from 'react';
import type {ElementType, ReactElement, Ref} from 'react';
import type {WithWrapperProps} from '../../models/component';
import composeComponentDisplayName from '../../utils/compose-component-display-name';
import type {PaperTypeMap} from '../Paper';
import './accordion.scss';

export type AccordionProps = MuiAccordionProps;
export type AccordionProps<C extends ElementType = ElementType> = {
/**
* The component used for the root node. Either a string to use a HTML element or a component.
*/
component?: C;
} & Omit<MuiAccordionProps, 'component'>;

const COMPONENT_NAME: string = 'Accordion';

const Accordion: FC<AccordionProps> & WithWrapperProps = (props: AccordionProps): ReactElement => {
const {className, ...rest} = props;

const classes: string = clsx('oxygen-accordion', className);
/**
* The Accordion component lets users show and hide sections of related content on a page.
*
* Demos:
*
* - [Accordion (Oxygen UI)](https://wso2.github.io/oxygen-ui/react/?path=/docs/surfaces-accordion)
* - [Accordion (MUI)](https://mui.com/material-ui/react-accordion/)
*
* API:
*
* - [Accordion API](https://mui.com/material-ui/api/accordion/)
* - inherits [Paper API](https://mui.com/material-ui/api/paper/)
*
* @remarks
* - ✔️ Props of the [Paper](https://mui.com/material-ui/api/paper/) component are also available.
* - ✅ `component` prop is supported.
* - ✅ The `ref` is forwarded to the root element.
*
* @template C - The type of the component.
* @param props - The props for the Accordion component.
* @param ref - The ref to be forwarded to the MuiAccordion component.
* @returns The rendered Accordion component.
*/
const Accordion: OverridableComponent<PaperTypeMap<AccordionProps>> & WithWrapperProps = forwardRef(
<C extends ElementType = ElementType>(
{className, ...rest}: AccordionProps<C>,
ref: Ref<HTMLDivElement>,
): ReactElement => {
const classes: string = clsx('oxygen-accordion', className);

return <MuiAccordion className={classes} {...rest} />;
};
return <MuiAccordion ref={ref} className={classes} {...rest} />;
},
) as OverridableComponent<PaperTypeMap<AccordionProps>> & WithWrapperProps;

Accordion.displayName = composeComponentDisplayName(COMPONENT_NAME);
Accordion.muiName = COMPONENT_NAME;
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/components/Accordion/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
*/

export {default} from './Accordion';
export type {AccordionProps} from './Accordion';
export * from './Accordion';
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,48 @@
* under the License.
*/

import MuiAccordionDetails, {AccordionDetailsProps as MuiAccordionDetailsProps} from '@mui/material/AccordionDetails';
import MuiAccordionDetails from '@mui/material/AccordionDetails';
import type {AccordionDetailsProps as MuiAccordionDetailsProps} from '@mui/material/AccordionDetails';
import clsx from 'clsx';
import {forwardRef, ForwardRefExoticComponent, ReactElement, MutableRefObject} from 'react';
import {forwardRef} from 'react';
import type {ForwardRefExoticComponent, ReactElement, Ref} from 'react';
import type {WithWrapperProps} from '../../models/component';
import composeComponentDisplayName from '../../utils/compose-component-display-name';

export type AccordionDetailsProps = MuiAccordionDetailsProps;

const COMPONENT_NAME: string = 'AccordionDetails';

/**
* The Accordion Details component is the wrapper for the Accordion content.
*
* Demos:
*
* - [Accordion (Oxygen UI)](https://wso2.github.io/oxygen-ui/react/?path=/docs/surfaces-accordion)
* - [Accordion (MUI)](https://mui.com/material-ui/react-accordion/)
*
* API:
*
* - [AccordionDetails API](https://mui.com/material-ui/api/accordion-details/)
*
* @remarks
* - ✔️ Props of the native component are also available.
* - ❌ `component` prop is not supported.
* - ✅ The `ref` is forwarded to the root element.
*
* @param props - The props for the AccordionDetails component.
* @param ref - The ref to be forwarded to the MuiAccordionDetails component.
* @returns The rendered AccordionDetails component.
*/
const AccordionDetails: ForwardRefExoticComponent<AccordionDetailsProps> & WithWrapperProps = forwardRef(
(props: AccordionDetailsProps, ref: MutableRefObject<HTMLDivElement>): ReactElement => {
const {className, ...rest} = props;

({className, ...rest}: AccordionDetailsProps, ref: Ref<HTMLDivElement>): ReactElement => {
const classes: string = clsx('oxygen-accordion-details', className);

return <MuiAccordionDetails className={classes} {...rest} ref={ref} />;
return <MuiAccordionDetails ref={ref} className={classes} {...rest} />;
},
) as ForwardRefExoticComponent<AccordionDetailsProps> & WithWrapperProps;

AccordionDetails.displayName = composeComponentDisplayName(COMPONENT_NAME);
AccordionDetails.muiName = COMPONENT_NAME;
AccordionDetails.defaultProps = {};

export default AccordionDetails;
2 changes: 1 addition & 1 deletion packages/react/src/components/AccordionDetails/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
*/

export {default} from './AccordionDetails';
export type {AccordionDetailsProps} from './AccordionDetails';
export * from './AccordionDetails';
63 changes: 51 additions & 12 deletions packages/react/src/components/AccordionSummary/AccordionSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,67 @@
* under the License.
*/

import MuiAccordionSummary, {AccordionSummaryProps as MuiAccordionSummaryProps} from '@mui/material/AccordionSummary';
import MuiAccordionSummary from '@mui/material/AccordionSummary';
import type {
AccordionSummaryProps as MuiAccordionSummaryProps,
AccordionSummaryTypeMap,
} from '@mui/material/AccordionSummary';
import type {OverridableComponent} from '@mui/material/OverridableComponent';
import clsx from 'clsx';
import {forwardRef, ForwardRefExoticComponent, ReactElement, MutableRefObject} from 'react';
import {forwardRef} from 'react';
import type {ReactElement, ElementType, Ref} from 'react';
import type {WithWrapperProps} from '../../models/component';
import composeComponentDisplayName from '../../utils/compose-component-display-name';

export type AccordionSummaryProps = MuiAccordionSummaryProps;
export type AccordionSummaryProps<
C extends ElementType = ElementType,
D extends ElementType = AccordionSummaryTypeMap['defaultComponent'],
P = {},
> = {
/**
* The component used for the root node. Either a string to use a HTML element or a component.
*/
component?: C;
} & Omit<MuiAccordionSummaryProps<D, P>, 'component'>;

const COMPONENT_NAME: string = 'AccordionSummary';

const AccordionSummary: ForwardRefExoticComponent<AccordionSummaryProps> & WithWrapperProps = forwardRef(
(props: AccordionSummaryProps, ref: MutableRefObject<HTMLDivElement>): ReactElement => {
const {className, ...rest} = props;

const classes: string = clsx('oxygen-accordion-summary', className);
/**
* The Accordion Summary component is the wrapper for the Accordion header, which expands or collapses the content when clicked.
*
* Demos:
*
* - [Accordion (Oxygen UI)](https://wso2.github.io/oxygen-ui/react/?path=/docs/surfaces-accordion)
* - [Accordion (MUI)](https://mui.com/material-ui/react-accordion/)
*
* API:
*
* - [AccordionSummary API](https://mui.com/material-ui/api/accordion-summary/)
* - inherits [ButtonBase API](https://mui.com/material-ui/api/button-base/)
*
* @remarks
* - ✔️ Props of the [ButtonBase](https://mui.com/material-ui/api/button-base/) component are also available.
* - ✅ `component` prop is supported.
* - ✅ The `ref` is forwarded to the root element.
*
* @template C - The type of the component.
* @param props - The props for the AccordionSummary component.
* @param ref - The ref to be forwarded to the MuiAccordionSummary component.
* @returns The rendered AccordionSummary component.
*/
const AccordionSummary: OverridableComponent<AccordionSummaryTypeMap<AccordionSummaryProps>> & WithWrapperProps =
forwardRef(
<C extends ElementType = ElementType>(
{className, ...rest}: AccordionSummaryProps<C>,
ref: Ref<HTMLDivElement>,
): ReactElement => {
const classes: string = clsx('oxygen-accordion-summary', className);

return <MuiAccordionSummary className={classes} {...rest} ref={ref} />;
},
) as ForwardRefExoticComponent<AccordionSummaryProps> & WithWrapperProps;
return <MuiAccordionSummary ref={ref} className={classes} {...rest} />;
},
) as OverridableComponent<AccordionSummaryTypeMap<AccordionSummaryProps>> & WithWrapperProps;

AccordionSummary.displayName = composeComponentDisplayName(COMPONENT_NAME);
AccordionSummary.muiName = COMPONENT_NAME;
AccordionSummary.defaultProps = {};

export default AccordionSummary;
4 changes: 3 additions & 1 deletion packages/react/src/components/AccordionSummary/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@
*/

export {default} from './AccordionSummary';
export type {AccordionSummaryProps} from './AccordionSummary';
export * from './AccordionSummary';

export type {AccordionSummaryTypeMap} from '@mui/material/AccordionSummary';
125 changes: 80 additions & 45 deletions packages/react/src/components/AccountOverview/AccountOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,29 @@
* under the License.
*/

import type {OverridableComponent} from '@mui/material/OverridableComponent';
import clsx from 'clsx';
import {FC, ReactElement, ReactNode} from 'react';
import {forwardRef} from 'react';
import type {ElementType, ReactElement, ReactNode, Ref} from 'react';
import type {WithWrapperProps} from '../../models/component';
import composeComponentDisplayName from '../../utils/compose-component-display-name';
import Box from '../Box';
import Card, {CardProps} from '../Card';
import CardHeader, {CardHeaderProps} from '../CardHeader';
import Carousel, {CarouselStep} from '../Carousel';
import Card from '../Card';
import type {CardProps, CardTypeMap} from '../Card';
import CardHeader from '../CardHeader';
import type {CardHeaderProps} from '../CardHeader';
import Carousel from '../Carousel';
import type {CarouselStep} from '../Carousel';
import CircularProgressAvatar from '../CircularProgressAvatar';
import Divider from '../Divider';
import {UserTemplate} from '../UserDropdownMenu';
import type {UserTemplate} from '../UserDropdownMenu';
import './account-overview.scss';

export interface AccountOverviewProps extends Omit<CardProps, 'title'> {
export type AccountOverviewProps<
C extends ElementType = ElementType,
D extends ElementType = CardTypeMap['defaultComponent'],
P = {},
> = Omit<CardProps<C, D, P>, 'title'> & {
/**
* Account completion steps.
*/
Expand Down Expand Up @@ -60,51 +69,77 @@ export interface AccountOverviewProps extends Omit<CardProps, 'title'> {
* Logged user information.
*/
user: UserTemplate;
}
};

export type AccountCompletionSteps = CarouselStep;

const COMPONENT_NAME: string = 'AccountOverview';

const AccountOverview: FC<AccountOverviewProps> & WithWrapperProps = (props: AccountOverviewProps): ReactElement => {
const {
className,
title,
subheader,
accountCompletionStepsTitle,
accountCompletionSteps,
accountProgress,
user,
cardHeaderProps,
...rest
} = props;

const classes: string = clsx('oxygen-account-overview', className);
/**
* The Account Overview component lets you display the progress of the user's account.
* It includes the user's profile picture, name, email, account progress and account completion steps.
*
* Demos:
*
* - [Account Overview (Oxygen UI)](https://wso2.github.io/oxygen-ui/react/?path=/docs/patterns-account-overview)
*
* API:
*
* - inherits [Card API](https://mui.com/material-ui/api/card/)
*
* @remarks
* - ✨ This is a custom component that is not available in the Material-UI library.
* - ✔️ Props of the [Paper](https://mui.com/material-ui/api/card/) component are also available.
* - ✅ `component` prop is supported.
* - ✅ The `ref` is forwarded to the root element.
*
* @template C - The type of the component.
* @param props - The props for the AccountOverview component.
* @param ref - The ref to be forwarded to the Card component.
* @returns The rendered AccountOverview component.
*/
const AccountOverview: OverridableComponent<CardTypeMap<AccountOverviewProps>> & WithWrapperProps = forwardRef(
<C extends ElementType = ElementType>(
{
className,
title,
subheader,
accountCompletionStepsTitle,
accountCompletionSteps,
accountProgress,
user,
cardHeaderProps,
...rest
}: AccountOverviewProps<C>,
ref: Ref<HTMLDivElement>,
): ReactElement => {
const classes: string = clsx('oxygen-account-overview', className);

return (
<Card className={classes} elevation={0} variant="outlined" {...rest}>
<CardHeader
avatar={
<CircularProgressAvatar
color={accountProgress < 100 ? 'warning' : 'success'}
progress={accountProgress}
avatarOptions={{alt: "User's avatar", src: user?.image}}
badgeOptions={{badgeContent: `${accountProgress}%`, color: accountProgress < 100 ? 'warning' : 'success'}}
/>
}
title={title}
subheader={subheader}
{...cardHeaderProps}
/>
{accountCompletionSteps && (
<Box className="oxygen-account-completion-steps-box">
<Divider />
<Carousel title={accountCompletionStepsTitle} steps={accountCompletionSteps} />
</Box>
)}
</Card>
);
};
return (
<Card ref={ref} className={classes} elevation={0} variant="outlined" {...rest}>
<CardHeader
avatar={
<CircularProgressAvatar
color={accountProgress < 100 ? 'warning' : 'success'}
progress={accountProgress}
avatarOptions={{alt: "User's avatar", src: user?.image}}
badgeOptions={{badgeContent: `${accountProgress}%`, color: accountProgress < 100 ? 'warning' : 'success'}}
/>
}
title={title}
subheader={subheader}
{...cardHeaderProps}
/>
{accountCompletionSteps && (
<Box className="oxygen-account-completion-steps-box">
<Divider />
<Carousel title={accountCompletionStepsTitle} steps={accountCompletionSteps} />
</Box>
)}
</Card>
);
},
) as OverridableComponent<CardTypeMap<AccountOverviewProps>> & WithWrapperProps;

AccountOverview.displayName = composeComponentDisplayName(COMPONENT_NAME);
AccountOverview.muiName = COMPONENT_NAME;
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/components/AccountOverview/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
*/

export {default} from './AccountOverview';
export type {AccountOverviewProps} from './AccountOverview';
export * from './AccountOverview';
Loading

0 comments on commit 6a4c3d4

Please sign in to comment.