From 33a327c1f2c92ea69938e464b99e8233e5d215e6 Mon Sep 17 00:00:00 2001 From: gtkatakura Date: Wed, 29 Jul 2020 16:00:44 -0300 Subject: [PATCH 1/2] Support inference extra props from as props --- package.json | 1 + src/Button.stories.tsx | 60 +++++++++++++++++++++++++++++++++++++----- src/index.tsx | 26 +++++++++++++----- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 5a9f1b5..ec502c2 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "react-dom": "^16.13.1", "react-scripts": "^3.4.1", "reakit": "^1.1.2", + "reakit-utils": "^0.13.1", "theme-ui": "^0.3.1", "ts-loader": "^8.0.1", "tsdx": "^0.13.2", diff --git a/src/Button.stories.tsx b/src/Button.stories.tsx index 8e79f77..b0468fb 100644 --- a/src/Button.stories.tsx +++ b/src/Button.stories.tsx @@ -1,8 +1,7 @@ -import React from 'react' +import React, { useReducer, useRef, useEffect, forwardRef, Ref } from 'react' import { ThemeProvider } from 'theme-ui' import { withA11y } from '@storybook/addon-a11y' import { withKnobs, text, color, boolean } from '@storybook/addon-knobs' -import { Checkbox, useCheckboxState } from 'reakit' import Button from '.' @@ -46,8 +45,55 @@ export function TheSXProp() { ) } -export function TheAsProp() { - const checkbox = useCheckboxState() +export function TheAsPropWithIntrinsicElement() { + const ref = useRef(null) + const [checked, toggle] = useReducer((value) => !value, false) + + useEffect(() => { + console.warn( + `TheAsPropWithIntrinsicElement: Detects properly type of \`ref\` from \`as\``, + ref.current + ) + }, []) + + return ( + + + + ) +} + +const Link = forwardRef(function Link( + { children, ...props }: JSX.IntrinsicElements['a'], + ref: Ref +) { + return ( + + {children} + + ) +}) + +export function TheAsPropWithCustomElement() { + const ref = useRef(null) + const [checked, toggle] = useReducer((value) => !value, false) + + useEffect(() => { + console.warn( + `TheAsPropWithCustomElement: Detects properly type of \`ref\` from \`as\``, + ref.current + ) + }, []) return ( - - {checkbox.state ? '😄 Happy' : '😞 Sad'} - + ) } diff --git a/src/index.tsx b/src/index.tsx index 14b8276..04e4a41 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,15 +1,29 @@ -import React, { forwardRef, Ref } from 'react' +import React, { forwardRef, Ref, PropsWithoutRef } from 'react' import { Button as A11yButton, ButtonProps as A11yProps } from 'reakit' +import { PropsWithAs, As } from 'reakit-utils/types' import { Button as ThemeAwareButton, ButtonProps as ThemeAwareProps, } from 'theme-ui' -type Props = A11yProps & ThemeAwareProps +type Component = { + ( + props: PropsWithAs, T> + ): JSX.Element +} + +type ButtonProps = A11yProps & { as?: As } -function Button({ as, ...props }: Props, ref: Ref) { - return +const Button = ( + { as = ThemeAwareButton, ...props }: ButtonProps, + ref: Ref +) => { + return } -export { A11yProps, ThemeAwareProps } -export default forwardRef(Button) +export { ButtonProps, A11yProps, ThemeAwareProps } + +export default forwardRef(Button) as Component< + typeof ThemeAwareButton, + A11yProps +> From c64a62afd0a1e809463d9d8ca293d5bcae4409dc Mon Sep 17 00:00:00 2001 From: gtkatakura Date: Wed, 29 Jul 2020 19:07:28 -0300 Subject: [PATCH 2/2] Utility types Props and Components to reuse in another packages --- src/index.tsx | 19 +++++-------------- src/typings.d.ts | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 04e4a41..297db2e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,21 +1,15 @@ -import React, { forwardRef, Ref, PropsWithoutRef } from 'react' +import React, { forwardRef, Ref } from 'react' import { Button as A11yButton, ButtonProps as A11yProps } from 'reakit' -import { PropsWithAs, As } from 'reakit-utils/types' import { Button as ThemeAwareButton, ButtonProps as ThemeAwareProps, } from 'theme-ui' +import { As, Props, Component } from '@vtex-components/types' -type Component = { - ( - props: PropsWithAs, T> - ): JSX.Element -} - -type ButtonProps = A11yProps & { as?: As } +type ButtonProps = Props const Button = ( - { as = ThemeAwareButton, ...props }: ButtonProps, + { as = ThemeAwareButton, ...props }: ButtonProps, ref: Ref ) => { return @@ -23,7 +17,4 @@ const Button = ( export { ButtonProps, A11yProps, ThemeAwareProps } -export default forwardRef(Button) as Component< - typeof ThemeAwareButton, - A11yProps -> +export default forwardRef(Button) as Component diff --git a/src/typings.d.ts b/src/typings.d.ts index e3ec8c5..f9abb28 100644 --- a/src/typings.d.ts +++ b/src/typings.d.ts @@ -15,3 +15,27 @@ declare module '*.svg' { export default svgUrl export { svgComponent as ReactComponent } } + +declare module '@vtex-components/types' { + import { PropsWithoutRef } from 'react' + import { As, PropsWithAs } from 'reakit-utils/types' + + export { As } + + export type Props = PropsWithAs< + PropsWithoutRef, + T + > + + export type AsOf = T extends Props ? TAs : never + + export type BasePropsOf = T extends Props + ? TProps + : never + + export type Component> = { + >( + props: Props> + ): JSX.Element + } +}