@sanity/ui 3.2.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +12 -0
  2. package/dist/_chunks-cjs/_visual-editing.js +54 -43
  3. package/dist/_chunks-cjs/_visual-editing.js.map +1 -1
  4. package/dist/_chunks-es/_visual-editing.mjs +54 -43
  5. package/dist/_chunks-es/_visual-editing.mjs.map +1 -1
  6. package/dist/_visual-editing.d.mts +129 -75
  7. package/dist/_visual-editing.d.ts +129 -75
  8. package/dist/index.d.mts +222 -139
  9. package/dist/index.d.ts +222 -139
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/theme.d.mts +10 -4
  13. package/dist/theme.d.ts +10 -4
  14. package/package.json +19 -82
  15. package/src/core/components/autocomplete/autocomplete.tsx +1 -1
  16. package/src/core/components/autocomplete/types.ts +2 -2
  17. package/src/core/components/menu/__workshop__/asComponent.tsx +1 -1
  18. package/src/core/components/menu/menuDivider.ts +16 -5
  19. package/src/core/components/menu/menuGroup.spacing.test.tsx +1 -7
  20. package/src/core/components/menu/menuGroup.tsx +14 -6
  21. package/src/core/components/menu/menuItem.tsx +17 -6
  22. package/src/core/components/skeleton/skeleton.tsx +2 -2
  23. package/src/core/components/tab/tabList.tsx +2 -2
  24. package/src/core/components/tab/tabPanel.tsx +2 -2
  25. package/src/core/components/toast/styles.ts +2 -2
  26. package/src/core/components/tree/__workshop__/basic.perf.ts +1 -1
  27. package/src/core/components/tree/__workshop__/tabFromElement.tsx +1 -1
  28. package/src/core/components/tree/tree.tsx +9 -6
  29. package/src/core/components/tree/treeGroup.tsx +1 -1
  30. package/src/core/components/tree/treeItem.tsx +3 -2
  31. package/src/core/primitives/avatar/avatar.tsx +19 -11
  32. package/src/core/primitives/badge/badge.tsx +20 -12
  33. package/src/core/primitives/box/__workshop__/asComponent.tsx +31 -0
  34. package/src/core/primitives/box/__workshop__/index.ts +5 -0
  35. package/src/core/primitives/box/box.test.tsx +12 -4
  36. package/src/core/primitives/box/box.tsx +23 -12
  37. package/src/core/primitives/button/__workshop__/disabled.tsx +2 -2
  38. package/src/core/primitives/button/__workshop__/sanityUploadButton.tsx +1 -1
  39. package/src/core/primitives/button/__workshop__/uploadButton.tsx +1 -1
  40. package/src/core/primitives/button/button.test.tsx +3 -3
  41. package/src/core/primitives/button/button.tsx +28 -9
  42. package/src/core/primitives/card/__workshop__/asComponent.tsx +1 -1
  43. package/src/core/primitives/card/card.tsx +24 -13
  44. package/src/core/primitives/code/code.tsx +16 -7
  45. package/src/core/primitives/container/container.tsx +23 -10
  46. package/src/core/primitives/flex/flex.tsx +21 -11
  47. package/src/core/primitives/grid/grid.test.tsx +3 -1
  48. package/src/core/primitives/grid/grid.tsx +22 -9
  49. package/src/core/primitives/heading/heading.tsx +19 -11
  50. package/src/core/primitives/inline/inline.tsx +19 -9
  51. package/src/core/primitives/kbd/kbd.tsx +19 -11
  52. package/src/core/primitives/label/label.tsx +19 -11
  53. package/src/core/primitives/popover/__workshop__/SidePanelStory.tsx +1 -1
  54. package/src/core/primitives/stack/stack.tsx +20 -11
  55. package/src/core/primitives/text/text.tsx +19 -11
  56. package/src/core/primitives/textInput/textInput.tsx +2 -2
  57. package/src/core/types/component.ts +32 -0
  58. package/src/core/types/index.ts +1 -0
  59. package/src/core/utils/virtualList/virtualList.tsx +2 -2
  60. package/src/theme/system/css.ts +10 -4
@@ -3,8 +3,8 @@ import {styled} from 'styled-components'
3
3
 
4
4
  import {_getArrayProp} from '../../styles'
5
5
  import {responsiveRadiusStyle, ResponsiveRadiusStyleProps} from '../../styles/internal'
6
- import {BadgeMode, BadgeTone} from '../../types'
7
- import {Box, BoxProps} from '../box'
6
+ import {BadgeMode, BadgeTone, ElementType, Props} from '../../types'
7
+ import {Box, BoxOwnProps} from '../box'
8
8
  import {Text} from '../text'
9
9
  import {ResponsiveRadiusProps} from '../types'
10
10
  import {badgeStyle} from './styles'
@@ -13,26 +13,25 @@ import {BadgeStyleProps} from './types'
13
13
  /**
14
14
  * @public
15
15
  */
16
- export interface BadgeProps extends BoxProps, ResponsiveRadiusProps {
17
- as?: React.ElementType | keyof React.JSX.IntrinsicElements
16
+ export interface BadgeOwnProps extends BoxOwnProps, ResponsiveRadiusProps {
18
17
  fontSize?: number | number[]
19
18
  /** @deprecated No longer used. */
20
19
  mode?: BadgeMode
21
20
  tone?: BadgeTone
22
21
  }
23
22
 
23
+ /**
24
+ * @public
25
+ */
26
+ export type BadgeProps<E extends ElementType = 'div'> = Props<BadgeOwnProps, E>
27
+
24
28
  const StyledBadge = styled(Box)<BadgeStyleProps & ResponsiveRadiusStyleProps>(
25
29
  responsiveRadiusStyle,
26
30
  badgeStyle,
27
31
  )
28
32
 
29
- /**
30
- * Badges are used to tag resources.
31
- *
32
- * @public
33
- */
34
- export const Badge = forwardRef(function Badge(
35
- props: BadgeProps & React.HTMLProps<HTMLDivElement>,
33
+ const BadgeComponent = forwardRef(function Badge(
34
+ props: BadgeOwnProps & {as?: ElementType} & React.HTMLProps<HTMLDivElement>,
36
35
  ref,
37
36
  ) {
38
37
  const {
@@ -59,4 +58,13 @@ export const Badge = forwardRef(function Badge(
59
58
  </StyledBadge>
60
59
  )
61
60
  })
62
- Badge.displayName = 'ForwardRef(Badge)'
61
+ BadgeComponent.displayName = 'ForwardRef(Badge)'
62
+
63
+ /**
64
+ * Badges are used to tag resources.
65
+ *
66
+ * @public
67
+ */
68
+ export const Badge = BadgeComponent as unknown as <E extends ElementType = 'div'>(
69
+ props: BadgeProps<E>,
70
+ ) => React.JSX.Element
@@ -0,0 +1,31 @@
1
+ import {Box, Flex, Text} from '@sanity/ui'
2
+ import {forwardRef} from 'react'
3
+
4
+ // A custom component with its own props. When passed to `Box`'s `as` prop, these props are
5
+ // inferred on `Box` itself: `href` is required and `target` is optional, and unknown props
6
+ // are rejected by the type checker.
7
+ const Link = forwardRef(function Link(
8
+ props: {href: string; target?: string} & Omit<
9
+ React.HTMLProps<HTMLAnchorElement>,
10
+ 'as' | 'href' | 'target'
11
+ >,
12
+ ref: React.ForwardedRef<HTMLAnchorElement>,
13
+ ): React.JSX.Element {
14
+ const {children, ...restProps} = props
15
+
16
+ return (
17
+ <a {...restProps} ref={ref}>
18
+ {children}
19
+ </a>
20
+ )
21
+ })
22
+
23
+ export default function AsComponentStory() {
24
+ return (
25
+ <Flex align="center" height="fill" justify="center">
26
+ <Box as={Link} href="/" padding={4} target="_new">
27
+ <Text size={1}>As component</Text>
28
+ </Box>
29
+ </Flex>
30
+ )
31
+ }
@@ -15,5 +15,10 @@ export default defineScope({
15
15
  title: 'Responsive',
16
16
  component: lazy(() => import('./responsive')),
17
17
  },
18
+ {
19
+ name: 'as-component',
20
+ title: 'As component',
21
+ component: lazy(() => import('./asComponent')),
22
+ },
18
23
  ],
19
24
  })
@@ -25,20 +25,28 @@ describe('<Box />', () => {
25
25
  it('uses column when gridColumn is not provided', () => {
26
26
  render(<Box column={3} />)
27
27
 
28
- expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(expect.objectContaining({$column: [3]}))
28
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
29
+ expect.objectContaining({$column: [3]}),
30
+ )
29
31
  })
30
32
 
31
33
  it('uses gridColumn when provided', () => {
32
34
  render(<Box gridColumn={4} />)
33
35
 
34
- expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(expect.objectContaining({$column: [4]}))
36
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
37
+ expect.objectContaining({$column: [4]}),
38
+ )
35
39
  })
36
40
 
37
41
  it('prefers gridColumn over column when both are provided', () => {
38
42
  render(<Box column={3} gridColumn={5} />)
39
43
 
40
- expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(expect.objectContaining({$column: [5]}))
41
- expect(mockedResponsiveGridItemStyle).not.toHaveBeenCalledWith(expect.objectContaining({$column: [3]}))
44
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
45
+ expect.objectContaining({$column: [5]}),
46
+ )
47
+ expect(mockedResponsiveGridItemStyle).not.toHaveBeenCalledWith(
48
+ expect.objectContaining({$column: [3]}),
49
+ )
42
50
  })
43
51
 
44
52
  it('supports responsive arrays with gridColumn', () => {
@@ -15,6 +15,7 @@ import {
15
15
  responsivePaddingStyle,
16
16
  ResponsivePaddingStyleProps,
17
17
  } from '../../styles/internal'
18
+ import {ElementType, Props} from '../../types'
18
19
  import {
19
20
  ResponsiveBoxProps,
20
21
  ResponsiveFlexItemProps,
@@ -24,18 +25,24 @@ import {
24
25
  } from '../types'
25
26
 
26
27
  /**
28
+ * The props that `Box` adds on top of the element it renders as.
29
+ *
27
30
  * @public
28
31
  */
29
- export interface BoxProps
32
+ export interface BoxOwnProps
30
33
  extends ResponsiveFlexItemProps,
31
34
  ResponsiveBoxProps,
32
35
  ResponsiveGridItemProps,
33
36
  ResponsiveMarginProps,
34
37
  ResponsivePaddingProps {
35
- as?: React.ElementType | keyof React.JSX.IntrinsicElements
36
- forwardedAs?: React.ElementType | keyof React.JSX.IntrinsicElements
38
+ forwardedAs?: ElementType
37
39
  }
38
40
 
41
+ /**
42
+ * @public
43
+ */
44
+ export type BoxProps<E extends ElementType = 'div'> = Props<BoxOwnProps, E>
45
+
39
46
  const StyledBox = styled.div<
40
47
  FlexItemStyleProps &
41
48
  ResponsiveBoxStyleProps &
@@ -51,14 +58,8 @@ const StyledBox = styled.div<
51
58
  responsivePaddingStyle,
52
59
  )
53
60
 
54
- /**
55
- * The `Box` component is a basic layout wrapper component which provides utility properties
56
- * for flex, margins and padding.
57
- *
58
- * @public
59
- */
60
- export const Box = forwardRef(function Box(
61
- props: BoxProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height'>,
61
+ const BoxComponent = forwardRef(function Box(
62
+ props: BoxOwnProps & {as?: ElementType} & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height'>,
62
63
  ref: React.ForwardedRef<HTMLDivElement>,
63
64
  ) {
64
65
  const {
@@ -140,4 +141,14 @@ export const Box = forwardRef(function Box(
140
141
  </StyledBox>
141
142
  )
142
143
  })
143
- Box.displayName = 'ForwardRef(Box)'
144
+ BoxComponent.displayName = 'ForwardRef(Box)'
145
+
146
+ /**
147
+ * The `Box` component is a basic layout wrapper component which provides utility properties
148
+ * for flex, margins and padding.
149
+ *
150
+ * @public
151
+ */
152
+ export const Box = BoxComponent as unknown as <E extends ElementType = 'div'>(
153
+ props: BoxProps<E>,
154
+ ) => React.JSX.Element
@@ -5,12 +5,12 @@ import {Container} from '../../container/container'
5
5
  import {Grid} from '../../grid/grid'
6
6
  import {Stack} from '../../stack/stack'
7
7
  import {Text} from '../../text/text'
8
- import {Button, ButtonProps} from '../button'
8
+ import {Button, ButtonOwnProps} from '../button'
9
9
 
10
10
  const GAP = 4
11
11
  const COLUMNS = 3
12
12
 
13
- const DEFAULT_PROPS: ButtonProps = {
13
+ const DEFAULT_PROPS: ButtonOwnProps = {
14
14
  icon: SquareIcon,
15
15
  iconRight: SquareIcon,
16
16
  }
@@ -27,7 +27,7 @@ const SanityUploadButton = styled(Button).attrs({forwardedAs: 'label'})`
27
27
 
28
28
  export default function SanityUploadButtonWorkaroundStory() {
29
29
  return (
30
- <Flex align="center" height="fill" htmlFor="file" justify="center">
30
+ <Flex align="center" height="fill" justify="center">
31
31
  <SanityUploadButton icon={UploadIcon} tabIndex={0} text="Upload">
32
32
  <input type="file" />
33
33
  </SanityUploadButton>
@@ -11,7 +11,7 @@ export default function UploadButtonStory() {
11
11
  }, [])
12
12
 
13
13
  return (
14
- <Flex align="center" height="fill" htmlFor="file" justify="center">
14
+ <Flex align="center" height="fill" justify="center">
15
15
  <Button
16
16
  as="label"
17
17
  onKeyDown={handleKeyDown}
@@ -6,7 +6,7 @@ import {axe} from 'jest-axe'
6
6
 
7
7
  import {render} from '../../../../test'
8
8
  import {Flex} from '../flex'
9
- import {Button, ButtonProps} from './button'
9
+ import {Button, ButtonOwnProps} from './button'
10
10
 
11
11
  jest.mock('../flex', () => {
12
12
  const actual = jest.requireActual('../flex')
@@ -45,11 +45,11 @@ describe('atoms/button', () => {
45
45
  })
46
46
 
47
47
  it('should wrap button', () => {
48
- function WrappedButton({button: buttonProps}: {button: ButtonProps}) {
48
+ function WrappedButton({button: buttonProps}: {button: ButtonOwnProps}) {
49
49
  return <Button {...buttonProps} />
50
50
  }
51
51
 
52
- const buttonProps: ButtonProps = {
52
+ const buttonProps: ButtonOwnProps = {
53
53
  text: 'Button text',
54
54
  }
55
55
 
@@ -6,7 +6,15 @@ import {styled} from 'styled-components'
6
6
  import {_getArrayProp, ThemeProps} from '../../styles'
7
7
  import {responsiveRadiusStyle, ResponsiveRadiusStyleProps} from '../../styles/internal'
8
8
  import {useTheme_v2} from '../../theme'
9
- import {ButtonMode, ButtonTextAlign, ButtonTone, ButtonWidth, FlexJustify} from '../../types'
9
+ import {
10
+ ButtonMode,
11
+ ButtonTextAlign,
12
+ ButtonTone,
13
+ ButtonWidth,
14
+ ElementType,
15
+ FlexJustify,
16
+ Props,
17
+ } from '../../types'
10
18
  import {Box} from '../box'
11
19
  import {Flex} from '../flex'
12
20
  import {Spinner} from '../spinner'
@@ -17,8 +25,7 @@ import {buttonBaseStyles, buttonColorStyles} from './styles'
17
25
  /**
18
26
  * @public
19
27
  */
20
- export interface ButtonProps extends ResponsivePaddingProps, ResponsiveRadiusProps {
21
- as?: React.ElementType | keyof React.JSX.IntrinsicElements
28
+ export interface ButtonOwnProps extends ResponsivePaddingProps, ResponsiveRadiusProps {
22
29
  fontSize?: number | number[]
23
30
  mode?: ButtonMode
24
31
  icon?: React.ElementType | React.ReactNode
@@ -43,6 +50,11 @@ export interface ButtonProps extends ResponsivePaddingProps, ResponsiveRadiusPro
43
50
  width?: ButtonWidth
44
51
  }
45
52
 
53
+ /**
54
+ * @public
55
+ */
56
+ export type ButtonProps<E extends ElementType = 'button'> = Props<ButtonOwnProps, E>
57
+
46
58
  const StyledButton = styled.button<
47
59
  {$mode: ButtonMode; $tone: ButtonTone; $width?: ButtonWidth} & ResponsiveRadiusStyleProps &
48
60
  ThemeProps
@@ -63,11 +75,11 @@ const LoadingBox = styled.div`
63
75
  box-shadow: inherit;
64
76
  `
65
77
 
66
- /**
67
- * @public
68
- */
69
- export const Button = forwardRef(function Button(
70
- props: ButtonProps & Omit<React.HTMLProps<HTMLButtonElement>, 'as' | 'width'>,
78
+ const ButtonComponent = forwardRef(function Button(
79
+ props: ButtonOwnProps & {as?: ElementType} & Omit<
80
+ React.HTMLProps<HTMLButtonElement>,
81
+ 'as' | 'width'
82
+ >,
71
83
  ref: React.ForwardedRef<HTMLButtonElement>,
72
84
  ) {
73
85
  const {
@@ -188,4 +200,11 @@ export const Button = forwardRef(function Button(
188
200
  </StyledButton>
189
201
  )
190
202
  })
191
- Button.displayName = 'ForwardRef(Button)'
203
+ ButtonComponent.displayName = 'ForwardRef(Button)'
204
+
205
+ /**
206
+ * @public
207
+ */
208
+ export const Button = ButtonComponent as unknown as <E extends ElementType = 'button'>(
209
+ props: ButtonProps<E>,
210
+ ) => React.JSX.Element
@@ -19,7 +19,7 @@ export default function AsComponentStory() {
19
19
 
20
20
  return (
21
21
  <Flex align="center" height="fill" justify="center">
22
- <Card as={CustomLink} data-as="a" {...props} padding={3}>
22
+ <Card as={CustomLink} data-as="a" {...props} padding={3} req="example">
23
23
  <Text size={1}>As component</Text>
24
24
  </Card>
25
25
  </Flex>
@@ -13,8 +13,8 @@ import {
13
13
  ResponsiveShadowStyleProps,
14
14
  } from '../../styles/internal'
15
15
  import {ThemeColorProvider, useRootTheme} from '../../theme'
16
- import {CardTone} from '../../types'
17
- import {Box, BoxProps} from '../box'
16
+ import {CardTone, ElementType, Props} from '../../types'
17
+ import {Box, BoxOwnProps} from '../box'
18
18
  import {ResponsiveBorderProps, ResponsiveRadiusProps, ResponsiveShadowProps} from '../types'
19
19
  import {cardStyle} from './styles'
20
20
  import {CardStyleProps} from './types'
@@ -22,8 +22,8 @@ import {CardStyleProps} from './types'
22
22
  /**
23
23
  * @public
24
24
  */
25
- export interface CardProps
26
- extends BoxProps,
25
+ export interface CardOwnProps
26
+ extends BoxOwnProps,
27
27
  ResponsiveBorderProps,
28
28
  ResponsiveRadiusProps,
29
29
  ResponsiveShadowProps {
@@ -37,12 +37,19 @@ export interface CardProps
37
37
  * @beta
38
38
  */
39
39
  __unstable_focusRing?: boolean
40
+ disabled?: boolean
40
41
  muted?: boolean
41
42
  pressed?: boolean
42
43
  scheme?: ThemeColorSchemeKey
44
+ selected?: boolean
43
45
  tone?: CardTone
44
46
  }
45
47
 
48
+ /**
49
+ * @public
50
+ */
51
+ export type CardProps<E extends ElementType = 'div'> = Props<CardOwnProps, E>
52
+
46
53
  const StyledCard = styled(Box)<
47
54
  CardStyleProps &
48
55
  ResponsiveRadiusStyleProps &
@@ -50,14 +57,8 @@ const StyledCard = styled(Box)<
50
57
  ResponsiveShadowStyleProps
51
58
  >(responsiveBorderStyle, responsiveRadiusStyle, responsiveShadowStyle, cardStyle)
52
59
 
53
- /**
54
- * The `Card` component acts much like a `Box`, but with a background and foreground color.
55
- * Components within a `Card` inherit its colors.
56
- *
57
- * @public
58
- */
59
- export const Card = forwardRef(function Card(
60
- props: CardProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height'>,
60
+ const CardComponent = forwardRef(function Card(
61
+ props: CardOwnProps & {as?: ElementType} & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height'>,
61
62
  ref: React.ForwardedRef<HTMLDivElement>,
62
63
  ) {
63
64
  const {
@@ -114,4 +115,14 @@ export const Card = forwardRef(function Card(
114
115
  </ThemeColorProvider>
115
116
  )
116
117
  })
117
- Card.displayName = 'ForwardRef(Card)'
118
+ CardComponent.displayName = 'ForwardRef(Card)'
119
+
120
+ /**
121
+ * The `Card` component acts much like a `Box`, but with a background and foreground color.
122
+ * Components within a `Card` inherit its colors.
123
+ *
124
+ * @public
125
+ */
126
+ export const Card = CardComponent as unknown as <E extends ElementType = 'div'>(
127
+ props: CardProps<E>,
128
+ ) => React.JSX.Element
@@ -3,6 +3,7 @@ import {styled} from 'styled-components'
3
3
 
4
4
  import {_getArrayProp} from '../../styles'
5
5
  import {responsiveCodeFontStyle, ResponsiveFontStyleProps} from '../../styles/internal'
6
+ import {ElementType, Props} from '../../types'
6
7
  import {codeBaseStyle} from './styles'
7
8
 
8
9
  const LazyRefractor = lazy(() => import('./refractor'))
@@ -10,21 +11,22 @@ const LazyRefractor = lazy(() => import('./refractor'))
10
11
  /**
11
12
  * @public
12
13
  */
13
- export interface CodeProps {
14
- as?: React.ElementType | keyof React.JSX.IntrinsicElements
14
+ export interface CodeOwnProps {
15
15
  /** Define the language to use for syntax highlighting. */
16
16
  language?: string
17
17
  size?: number | number[]
18
18
  weight?: string
19
19
  }
20
20
 
21
- const StyledCode = styled.pre<ResponsiveFontStyleProps>(codeBaseStyle, responsiveCodeFontStyle)
22
-
23
21
  /**
24
22
  * @public
25
23
  */
26
- export const Code = forwardRef(function Code(
27
- props: CodeProps & Omit<React.HTMLProps<HTMLElement>, 'as' | 'size'>,
24
+ export type CodeProps<E extends ElementType = 'pre'> = Props<CodeOwnProps, E>
25
+
26
+ const StyledCode = styled.pre<ResponsiveFontStyleProps>(codeBaseStyle, responsiveCodeFontStyle)
27
+
28
+ const CodeComponent = forwardRef(function Code(
29
+ props: CodeOwnProps & {as?: ElementType} & Omit<React.HTMLProps<HTMLElement>, 'as' | 'size'>,
28
30
  ref: React.ForwardedRef<HTMLElement>,
29
31
  ) {
30
32
  const {children, language, size = 2, weight, ...restProps} = props
@@ -43,4 +45,11 @@ export const Code = forwardRef(function Code(
43
45
  </StyledCode>
44
46
  )
45
47
  })
46
- Code.displayName = 'ForwardRef(Code)'
48
+ CodeComponent.displayName = 'ForwardRef(Code)'
49
+
50
+ /**
51
+ * @public
52
+ */
53
+ export const Code = CodeComponent as unknown as <E extends ElementType = 'pre'>(
54
+ props: CodeProps<E>,
55
+ ) => React.JSX.Element
@@ -2,7 +2,8 @@ import {forwardRef} from 'react'
2
2
  import {styled} from 'styled-components'
3
3
 
4
4
  import {_getArrayProp} from '../../styles'
5
- import {Box, BoxProps} from '../box'
5
+ import {ElementType, Props} from '../../types'
6
+ import {Box, BoxOwnProps} from '../box'
6
7
  import {ResponsiveWidthProps} from '../types'
7
8
  import {containerBaseStyle, responsiveContainerWidthStyle} from './styles'
8
9
  import {ResponsiveWidthStyleProps} from './types'
@@ -10,20 +11,23 @@ import {ResponsiveWidthStyleProps} from './types'
10
11
  /**
11
12
  * @public
12
13
  */
13
- export interface ContainerProps extends BoxProps, ResponsiveWidthProps {}
14
+ export interface ContainerOwnProps extends BoxOwnProps, ResponsiveWidthProps {}
15
+
16
+ /**
17
+ * @public
18
+ */
19
+ export type ContainerProps<E extends ElementType = 'div'> = Props<ContainerOwnProps, E>
14
20
 
15
21
  const StyledContainer = styled(Box)<ResponsiveWidthStyleProps>(
16
22
  containerBaseStyle,
17
23
  responsiveContainerWidthStyle,
18
24
  )
19
25
 
20
- /**
21
- * The `Container` component wraps content layout in a defined set of widths.
22
- *
23
- * @public
24
- */
25
- export const Container = forwardRef(function Container(
26
- props: ContainerProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height' | 'width'>,
26
+ const ContainerComponent = forwardRef(function Container(
27
+ props: ContainerOwnProps & {as?: ElementType} & Omit<
28
+ React.HTMLProps<HTMLDivElement>,
29
+ 'as' | 'height' | 'width'
30
+ >,
27
31
  ref: React.ForwardedRef<HTMLDivElement>,
28
32
  ) {
29
33
  const {as, width = 2, ...restProps} = props
@@ -38,4 +42,13 @@ export const Container = forwardRef(function Container(
38
42
  />
39
43
  )
40
44
  })
41
- Container.displayName = 'ForwardRef(Container)'
45
+ ContainerComponent.displayName = 'ForwardRef(Container)'
46
+
47
+ /**
48
+ * The `Container` component wraps content layout in a defined set of widths.
49
+ *
50
+ * @public
51
+ */
52
+ export const Container = ContainerComponent as unknown as <E extends ElementType = 'div'>(
53
+ props: ContainerProps<E>,
54
+ ) => React.JSX.Element
@@ -8,31 +8,32 @@ import {
8
8
  responsiveFlexStyle,
9
9
  ResponsiveFlexStyleProps,
10
10
  } from '../../styles/internal'
11
- import {Box, BoxProps} from '../box'
11
+ import {ElementType, Props} from '../../types'
12
+ import {Box, BoxOwnProps} from '../box'
12
13
  import {ResponsiveFlexItemProps, ResponsiveFlexProps} from '../types'
13
14
 
14
15
  /**
15
16
  * @public
16
17
  */
17
- export interface FlexProps
18
- extends Omit<BoxProps, 'display'>,
18
+ export interface FlexOwnProps
19
+ extends Omit<BoxOwnProps, 'display'>,
19
20
  ResponsiveFlexProps,
20
21
  ResponsiveFlexItemProps {
21
22
  gap?: number | number[]
22
23
  }
23
24
 
25
+ /**
26
+ * @public
27
+ */
28
+ export type FlexProps<E extends ElementType = 'div'> = Props<FlexOwnProps, E>
29
+
24
30
  const StyledFlex = styled(Box)<FlexItemStyleProps & ResponsiveFlexStyleProps>(
25
31
  flexItemStyle,
26
32
  responsiveFlexStyle,
27
33
  )
28
34
 
29
- /**
30
- * The `Flex` component is a wrapper component for flexible elements (`Box`, `Card` and `Flex`).
31
- *
32
- * @public
33
- */
34
- export const Flex = forwardRef(function Flex(
35
- props: FlexProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'wrap'>,
35
+ const FlexComponent = forwardRef(function Flex(
36
+ props: FlexOwnProps & {as?: ElementType} & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'wrap'>,
36
37
  ref: React.ForwardedRef<HTMLDivElement>,
37
38
  ) {
38
39
  const {align, as, direction = 'row', gap, justify, wrap, ...restProps} = props
@@ -51,4 +52,13 @@ export const Flex = forwardRef(function Flex(
51
52
  />
52
53
  )
53
54
  })
54
- Flex.displayName = 'ForwardRef(Flex)'
55
+ FlexComponent.displayName = 'ForwardRef(Flex)'
56
+
57
+ /**
58
+ * The `Flex` component is a wrapper component for flexible elements (`Box`, `Card` and `Flex`).
59
+ *
60
+ * @public
61
+ */
62
+ export const Flex = FlexComponent as unknown as <E extends ElementType = 'div'>(
63
+ props: FlexProps<E>,
64
+ ) => React.JSX.Element
@@ -73,6 +73,8 @@ describe('primitives/grid', () => {
73
73
  </Grid>,
74
74
  )
75
75
  expect(mockedResponsiveGridStyle).toHaveBeenCalledWith(expect.objectContaining({$rows: [3]}))
76
- expect(mockedResponsiveGridStyle).not.toHaveBeenCalledWith(expect.objectContaining({$rows: [1]}))
76
+ expect(mockedResponsiveGridStyle).not.toHaveBeenCalledWith(
77
+ expect.objectContaining({$rows: [1]}),
78
+ )
77
79
  })
78
80
  })
@@ -3,23 +3,27 @@ import {styled} from 'styled-components'
3
3
 
4
4
  import {_getArrayProp} from '../../styles'
5
5
  import {responsiveGridStyle, ResponsiveGridStyleProps} from '../../styles/internal'
6
- import {Box, BoxProps} from '../box'
6
+ import {ElementType, Props} from '../../types'
7
+ import {Box, BoxOwnProps} from '../box'
7
8
  import {ResponsiveGridProps} from '../types'
8
9
 
9
10
  /**
10
11
  * @public
11
12
  */
12
- export interface GridProps extends Omit<BoxProps, 'display'>, ResponsiveGridProps {}
13
-
14
- const StyledGrid = styled(Box)<ResponsiveGridStyleProps>(responsiveGridStyle)
13
+ export interface GridOwnProps extends Omit<BoxOwnProps, 'display'>, ResponsiveGridProps {}
15
14
 
16
15
  /**
17
- * The `Grid` component is for building 2-dimensional layers (based on CSS grid).
18
- *
19
16
  * @public
20
17
  */
21
- export const Grid = forwardRef(function Grid(
22
- props: GridProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height' | 'rows'>,
18
+ export type GridProps<E extends ElementType = 'div'> = Props<GridOwnProps, E>
19
+
20
+ const StyledGrid = styled(Box)<ResponsiveGridStyleProps>(responsiveGridStyle)
21
+
22
+ const GridComponent = forwardRef(function Grid(
23
+ props: GridOwnProps & {as?: ElementType} & Omit<
24
+ React.HTMLProps<HTMLDivElement>,
25
+ 'as' | 'height' | 'rows'
26
+ >,
23
27
  ref: React.ForwardedRef<HTMLDivElement>,
24
28
  ) {
25
29
  const {
@@ -58,4 +62,13 @@ export const Grid = forwardRef(function Grid(
58
62
  </StyledGrid>
59
63
  )
60
64
  })
61
- Grid.displayName = 'ForwardRef(Grid)'
65
+ GridComponent.displayName = 'ForwardRef(Grid)'
66
+
67
+ /**
68
+ * The `Grid` component is for building 2-dimensional layers (based on CSS grid).
69
+ *
70
+ * @public
71
+ */
72
+ export const Grid = GridComponent as unknown as <E extends ElementType = 'div'>(
73
+ props: GridProps<E>,
74
+ ) => React.JSX.Element