Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / react-polymorphic-types / README.md
bloba3958754059ecca0e7526112ae193a014137c400
1 # react-polymorphic-types
3 > This is a "fork" of [kripod/react-polymorphic-types](https://github.com/kripod/react-polymorphic-types) which fixes the types export declaration for TS when using a `moduleResolution` mode that relies on the package.json `exports` field.
5 <hr>
7 Zero-runtime polymorphic component definitions for React
9 [![npm](https://img.shields.io/npm/v/react-polymorphic-types)](https://www.npmjs.com/package/react-polymorphic-types)
11 ## Motivation
13 Being a successor to [react-polymorphic-box](https://github.com/kripod/react-polymorphic-box), this project offers more accurate typings with less overhead.
15 ## Features
17 -   Automatic code completion, based on the value of the `as` prop
18 -   Static type checking against the associated component’s inferred props
19 -   HTML element name validation
21 ## Usage
23 A `Heading` component can demonstrate the effectiveness of polymorphism:
25 ```tsx
26 <Heading color="rebeccapurple">Heading</Heading>
27 <Heading as="h3">Subheading</Heading>
28 ```
30 Custom components like the previous one may utilize the package as shown below.
32 ```tsx
33 import type { PolymorphicPropsWithoutRef } from 'react-polymorphic-types';
35 // An HTML tag or a different React component can be rendered by default
36 export const HeadingDefaultElement = 'h2';
38 // Component-specific props should be specified separately
39 export type HeadingOwnProps = {
40     color?: string;
43 // Extend own props with others inherited from the underlying element type
44 // Own props take precedence over the inherited ones
45 export type HeadingProps<T extends React.ElementType = typeof HeadingDefaultElement> = PolymorphicPropsWithoutRef<
46     HeadingOwnProps,
47     T
50 export function Heading<T extends React.ElementType = typeof HeadingDefaultElement>({
51     as,
52     color,
53     style,
54     ...restProps
55 }: HeadingProps<T>) {
56     const Element: React.ElementType = as || HeadingDefaultElement;
57     return <Element style={{ color, ...style }} {...restProps} />;
59 ```
61 ---
63 ⚠️ All the additional typings below will be deprecated as soon as [microsoft/TypeScript#30134](https://github.com/microsoft/TypeScript/issues/30134) is resolved.
65 ### With [`React.forwardRef`](https://reactjs.org/docs/react-api.html#reactforwardref)
67 ```tsx
68 import * as React from 'react';
69 import type {
70     PolymorphicForwardRefExoticComponent,
71     PolymorphicPropsWithRef,
72     PolymorphicPropsWithoutRef,
73 } from 'react-polymorphic-types';
75 import { HeadingDefaultElement, HeadingOwnProps } from './Heading';
77 export type HeadingProps<T extends React.ElementType = typeof HeadingDefaultElement> = PolymorphicPropsWithRef<
78     HeadingOwnProps,
79     T
82 export const Heading: PolymorphicForwardRefExoticComponent<HeadingOwnProps, typeof HeadingDefaultElement> =
83     React.forwardRef(function Heading<T extends React.ElementType = typeof HeadingDefaultElement>(
84         { as, color, style, ...restProps }: PolymorphicPropsWithoutRef<HeadingOwnProps, T>,
85         ref: React.ForwardedRef<Element>
86     ) {
87         const Element: React.ElementType = as || HeadingDefaultElement;
88         return <Element ref={ref} style={{ color, ...style }} {...restProps} />;
89     });
90 ```
92 ### With [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo)
94 ```tsx
95 import * as React from 'react';
96 import type { PolymorphicMemoExoticComponent } from 'react-polymorphic-types';
98 import { Heading, HeadingDefaultElement, HeadingOwnProps } from './Heading';
100 export const MemoizedHeading: PolymorphicMemoExoticComponent<HeadingOwnProps, typeof HeadingDefaultElement> =
101     React.memo(Heading);
104 ### With [`React.lazy`](https://reactjs.org/docs/react-api.html#reactlazy)
106 ```tsx
107 import * as React from 'react';
108 import type { PolymorphicLazyExoticComponent } from 'react-polymorphic-types';
110 import type { HeadingDefaultElement, HeadingOwnProps } from './Heading';
112 export const LazyHeading: PolymorphicLazyExoticComponent<HeadingOwnProps, typeof HeadingDefaultElement> = React.lazy(
113     async () => {
114         const { Heading } = await import('./Heading');
115         return { default: Heading };
116     }