@sanity/ui 3.1.14 → 3.2.0

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 (45) hide show
  1. package/dist/_chunks-cjs/_visual-editing.js +269 -249
  2. package/dist/_chunks-cjs/_visual-editing.js.map +1 -1
  3. package/dist/_chunks-es/_visual-editing.mjs +269 -249
  4. package/dist/_chunks-es/_visual-editing.mjs.map +1 -1
  5. package/dist/_visual-editing.d.mts +66 -1
  6. package/dist/_visual-editing.d.ts +66 -1
  7. package/dist/index.d.mts +86 -1
  8. package/dist/index.d.ts +86 -1
  9. package/dist/index.js +97 -93
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +97 -93
  12. package/dist/index.mjs.map +1 -1
  13. package/package.json +1 -1
  14. package/src/core/components/breadcrumbs/breadcrumbs.test.tsx +51 -0
  15. package/src/core/components/breadcrumbs/breadcrumbs.tsx +7 -3
  16. package/src/core/components/hotkeys/hotkeys.test.tsx +42 -0
  17. package/src/core/components/hotkeys/hotkeys.tsx +7 -3
  18. package/src/core/components/menu/menu.spacing.test.tsx +63 -0
  19. package/src/core/components/menu/menu.tsx +8 -2
  20. package/src/core/components/menu/menuGroup.spacing.test.tsx +69 -0
  21. package/src/core/components/menu/menuGroup.tsx +8 -2
  22. package/src/core/components/menu/menuItem.spacing.test.tsx +59 -0
  23. package/src/core/components/menu/menuItem.tsx +8 -2
  24. package/src/core/components/tab/tabList.test.tsx +48 -0
  25. package/src/core/components/tree/tree.test.tsx +55 -0
  26. package/src/core/components/tree/tree.tsx +10 -4
  27. package/src/core/components/tree/treeGroup.tsx +2 -2
  28. package/src/core/components/tree/treeItem.test.tsx +65 -0
  29. package/src/core/components/tree/treeItem.tsx +8 -2
  30. package/src/core/components/tree/types.ts +4 -0
  31. package/src/core/primitives/box/box.test.tsx +134 -0
  32. package/src/core/primitives/box/box.tsx +18 -6
  33. package/src/core/primitives/button/button.test.tsx +38 -0
  34. package/src/core/primitives/button/button.tsx +8 -3
  35. package/src/core/primitives/grid/grid.test.tsx +78 -0
  36. package/src/core/primitives/grid/grid.tsx +17 -4
  37. package/src/core/primitives/inline/inline.test.tsx +51 -0
  38. package/src/core/primitives/inline/inline.tsx +9 -3
  39. package/src/core/primitives/select/select.test.tsx +52 -0
  40. package/src/core/primitives/select/select.tsx +8 -2
  41. package/src/core/primitives/stack/stack.test.tsx +57 -0
  42. package/src/core/primitives/stack/stack.tsx +7 -2
  43. package/src/core/primitives/textInput/textInput.test.tsx +48 -0
  44. package/src/core/primitives/textInput/textInput.tsx +7 -2
  45. package/src/core/primitives/types.ts +33 -0
@@ -0,0 +1,65 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import {render} from '../../../../test'
4
+ import {Box} from '../../primitives'
5
+ import {TreeContext} from './treeContext'
6
+ import {TreeItem} from './treeItem'
7
+ import {TreeContextValue, TreeState} from './types'
8
+
9
+ jest.mock('../../primitives', () => {
10
+ const actual = jest.requireActual('../../primitives')
11
+
12
+ return {
13
+ ...actual,
14
+ Box: jest.fn((props: Record<string, unknown>) => (actual.Box as any).render(props, null)),
15
+ }
16
+ })
17
+
18
+ const treeContextValue: TreeContextValue = {
19
+ version: 0.0,
20
+ focusedElement: null,
21
+ gap: 1,
22
+ level: 0,
23
+ path: [],
24
+ registerItem: () => () => undefined,
25
+ setExpanded: () => undefined,
26
+ setFocusedElement: () => undefined,
27
+ space: 1,
28
+ state: {} as TreeState,
29
+ }
30
+
31
+ function renderTreeItem(props: Partial<React.ComponentProps<typeof TreeItem>> = {}) {
32
+ return render(
33
+ <TreeContext.Provider value={treeContextValue}>
34
+ <TreeItem text="Item" {...props} />
35
+ </TreeContext.Provider>,
36
+ )
37
+ }
38
+
39
+ describe('components/treeItem spacing', () => {
40
+ const mockedBox = jest.mocked(Box)
41
+
42
+ beforeEach(() => {
43
+ mockedBox.mockClear()
44
+ })
45
+
46
+ it('should support `space` and `gap` with the same behavior', () => {
47
+ renderTreeItem({space: 2})
48
+ expect(mockedBox.mock.calls.map(([props]) => props)).toContainEqual(
49
+ expect.objectContaining({marginRight: 2}),
50
+ )
51
+
52
+ mockedBox.mockClear()
53
+ renderTreeItem({gap: 2})
54
+ expect(mockedBox.mock.calls.map(([props]) => props)).toContainEqual(
55
+ expect.objectContaining({marginRight: 2}),
56
+ )
57
+ })
58
+
59
+ it('should prefer `gap` over `space` when both are provided', () => {
60
+ renderTreeItem({gap: 3, space: 1})
61
+ const propsList = mockedBox.mock.calls.map(([props]) => props)
62
+ expect(propsList).toContainEqual(expect.objectContaining({marginRight: 3}))
63
+ expect(propsList).not.toContainEqual(expect.objectContaining({marginRight: 1}))
64
+ })
65
+ })
@@ -26,6 +26,10 @@ export interface TreeItemProps {
26
26
  */
27
27
  linkAs?: BoxProps['as']
28
28
  padding?: number | number[]
29
+ gap?: number | number[]
30
+ /**
31
+ * @deprecated Use `gap` instead. `space` will be removed in v4.
32
+ */
29
33
  space?: number | number[]
30
34
  text?: React.ReactNode
31
35
  weight?: ThemeFontWeightKey
@@ -60,11 +64,13 @@ export function TreeItem(
60
64
  onClick,
61
65
  padding = 2,
62
66
  selected = false,
63
- space = 2,
67
+ gap,
68
+ space: deprecated_space = 2,
64
69
  text,
65
70
  weight,
66
71
  ...restProps
67
72
  } = props
73
+ const spacing = gap === undefined ? deprecated_space : gap
68
74
  const [rootElement, _setRootElement] = useState<HTMLLIElement | null>(null)
69
75
  /**
70
76
  * The startTransition wrapper here is to avoid an issue when on React 18 where this error can happen:
@@ -133,7 +139,7 @@ export function TreeItem(
133
139
  const content = (
134
140
  <Flex padding={padding}>
135
141
  <Box
136
- marginRight={space}
142
+ marginRight={spacing}
137
143
  style={{
138
144
  visibility: IconComponent || children ? 'visible' : 'hidden',
139
145
  pointerEvents: 'none',
@@ -16,6 +16,10 @@ export interface TreeContextValue {
16
16
  registerItem: (element: HTMLElement, path: string, expanded: boolean, selected: boolean) => void
17
17
  setExpanded: (path: string, expanded: boolean) => void
18
18
  setFocusedElement: (focusedElement: HTMLElement | null) => void
19
+ gap: number | number[]
20
+ /**
21
+ * @deprecated Use `gap` instead. `space` will be removed in v4.
22
+ */
19
23
  space: number | number[]
20
24
  state: TreeState
21
25
  }
@@ -0,0 +1,134 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import {type ComponentProps} from 'react'
4
+
5
+ import {render} from '../../../../test'
6
+ import {responsiveGridItemStyle} from '../../styles/internal'
7
+ import {Box} from './box'
8
+
9
+ jest.mock('../../styles/internal', () => {
10
+ const actual = jest.requireActual('../../styles/internal')
11
+
12
+ return {
13
+ ...actual,
14
+ responsiveGridItemStyle: jest.fn(actual.responsiveGridItemStyle),
15
+ }
16
+ })
17
+
18
+ describe('<Box />', () => {
19
+ const mockedResponsiveGridItemStyle = jest.mocked(responsiveGridItemStyle)
20
+
21
+ beforeEach(() => {
22
+ mockedResponsiveGridItemStyle.mockClear()
23
+ })
24
+
25
+ it('uses column when gridColumn is not provided', () => {
26
+ render(<Box column={3} />)
27
+
28
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(expect.objectContaining({$column: [3]}))
29
+ })
30
+
31
+ it('uses gridColumn when provided', () => {
32
+ render(<Box gridColumn={4} />)
33
+
34
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(expect.objectContaining({$column: [4]}))
35
+ })
36
+
37
+ it('prefers gridColumn over column when both are provided', () => {
38
+ render(<Box column={3} gridColumn={5} />)
39
+
40
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(expect.objectContaining({$column: [5]}))
41
+ expect(mockedResponsiveGridItemStyle).not.toHaveBeenCalledWith(expect.objectContaining({$column: [3]}))
42
+ })
43
+
44
+ it('supports responsive arrays with gridColumn', () => {
45
+ const gridColumn: ComponentProps<typeof Box>['gridColumn'] = [2, 'full']
46
+
47
+ render(<Box gridColumn={gridColumn} />)
48
+
49
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
50
+ expect.objectContaining({$column: [2, 'full']}),
51
+ )
52
+ })
53
+
54
+ it('uses columnStart when gridColumnStart is not provided', () => {
55
+ render(<Box columnStart={2} />)
56
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
57
+ expect.objectContaining({$columnStart: [2]}),
58
+ )
59
+ })
60
+
61
+ it('prefers gridColumnStart over columnStart when both are provided', () => {
62
+ render(<Box columnStart={2} gridColumnStart={4} />)
63
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
64
+ expect.objectContaining({$columnStart: [4]}),
65
+ )
66
+ expect(mockedResponsiveGridItemStyle).not.toHaveBeenCalledWith(
67
+ expect.objectContaining({$columnStart: [2]}),
68
+ )
69
+ })
70
+
71
+ it('uses columnEnd when gridColumnEnd is not provided', () => {
72
+ render(<Box columnEnd={3} />)
73
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
74
+ expect.objectContaining({$columnEnd: [3]}),
75
+ )
76
+ })
77
+
78
+ it('prefers gridColumnEnd over columnEnd when both are provided', () => {
79
+ render(<Box columnEnd={3} gridColumnEnd={5} />)
80
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
81
+ expect.objectContaining({$columnEnd: [5]}),
82
+ )
83
+ expect(mockedResponsiveGridItemStyle).not.toHaveBeenCalledWith(
84
+ expect.objectContaining({$columnEnd: [3]}),
85
+ )
86
+ })
87
+
88
+ it('uses row when gridRow is not provided', () => {
89
+ render(<Box row={1} />)
90
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(expect.objectContaining({$row: [1]}))
91
+ })
92
+
93
+ it('prefers gridRow over row when both are provided', () => {
94
+ render(<Box row={1} gridRow={2} />)
95
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(expect.objectContaining({$row: [2]}))
96
+ expect(mockedResponsiveGridItemStyle).not.toHaveBeenCalledWith(
97
+ expect.objectContaining({$row: [1]}),
98
+ )
99
+ })
100
+
101
+ it('uses rowStart when gridRowStart is not provided', () => {
102
+ render(<Box rowStart={2} />)
103
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
104
+ expect.objectContaining({$rowStart: [2]}),
105
+ )
106
+ })
107
+
108
+ it('prefers gridRowStart over rowStart when both are provided', () => {
109
+ render(<Box rowStart={2} gridRowStart={4} />)
110
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
111
+ expect.objectContaining({$rowStart: [4]}),
112
+ )
113
+ expect(mockedResponsiveGridItemStyle).not.toHaveBeenCalledWith(
114
+ expect.objectContaining({$rowStart: [2]}),
115
+ )
116
+ })
117
+
118
+ it('uses rowEnd when gridRowEnd is not provided', () => {
119
+ render(<Box rowEnd={3} />)
120
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
121
+ expect.objectContaining({$rowEnd: [3]}),
122
+ )
123
+ })
124
+
125
+ it('prefers gridRowEnd over rowEnd when both are provided', () => {
126
+ render(<Box rowEnd={3} gridRowEnd={5} />)
127
+ expect(mockedResponsiveGridItemStyle).toHaveBeenCalledWith(
128
+ expect.objectContaining({$rowEnd: [5]}),
129
+ )
130
+ expect(mockedResponsiveGridItemStyle).not.toHaveBeenCalledWith(
131
+ expect.objectContaining({$rowEnd: [3]}),
132
+ )
133
+ })
134
+ })
@@ -63,9 +63,12 @@ export const Box = forwardRef(function Box(
63
63
  ) {
64
64
  const {
65
65
  as: asProp = 'div',
66
- column,
67
- columnStart,
68
- columnEnd,
66
+ gridColumn,
67
+ column: deprecated_column,
68
+ gridColumnStart,
69
+ columnStart: deprecated_columnStart,
70
+ gridColumnEnd,
71
+ columnEnd: deprecated_columnEnd,
69
72
  display = 'block',
70
73
  flex,
71
74
  height,
@@ -84,12 +87,21 @@ export const Box = forwardRef(function Box(
84
87
  paddingRight,
85
88
  paddingBottom,
86
89
  paddingLeft,
87
- row,
88
- rowStart,
89
- rowEnd,
90
+ gridRow,
91
+ row: deprecated_row,
92
+ gridRowStart,
93
+ rowStart: deprecated_rowStart,
94
+ gridRowEnd,
95
+ rowEnd: deprecated_rowEnd,
90
96
  sizing,
91
97
  ...restProps
92
98
  } = props
99
+ const column = gridColumn === undefined ? deprecated_column : gridColumn
100
+ const columnStart = gridColumnStart === undefined ? deprecated_columnStart : gridColumnStart
101
+ const columnEnd = gridColumnEnd === undefined ? deprecated_columnEnd : gridColumnEnd
102
+ const row = gridRow === undefined ? deprecated_row : gridRow
103
+ const rowStart = gridRowStart === undefined ? deprecated_rowStart : gridRowStart
104
+ const rowEnd = gridRowEnd === undefined ? deprecated_rowEnd : gridRowEnd
93
105
 
94
106
  return (
95
107
  <StyledBox
@@ -5,9 +5,25 @@ import {screen} from '@testing-library/react'
5
5
  import {axe} from 'jest-axe'
6
6
 
7
7
  import {render} from '../../../../test'
8
+ import {Flex} from '../flex'
8
9
  import {Button, ButtonProps} from './button'
9
10
 
11
+ jest.mock('../flex', () => {
12
+ const actual = jest.requireActual('../flex')
13
+
14
+ return {
15
+ ...actual,
16
+ Flex: jest.fn((props: Record<string, unknown>) => (actual.Flex as any).render(props, null)),
17
+ }
18
+ })
19
+
10
20
  describe('atoms/button', () => {
21
+ const mockedFlex = jest.mocked(Flex)
22
+
23
+ beforeEach(() => {
24
+ mockedFlex.mockClear()
25
+ })
26
+
11
27
  it('Axe: should have no violations', async () => {
12
28
  const lightResult = render(<Button icon={AddIcon} text="Label" tone="positive" />, {
13
29
  scheme: 'light',
@@ -41,4 +57,26 @@ describe('atoms/button', () => {
41
57
 
42
58
  expect(screen.getByText('Button text')).toBeInTheDocument()
43
59
  })
60
+
61
+ it('should support `space`', () => {
62
+ render(<Button icon={AddIcon} space={17} text="Button text" />)
63
+
64
+ const propsList = mockedFlex.mock.calls.map(([props]) => props)
65
+ expect(propsList).toContainEqual(expect.objectContaining({gap: [17]}))
66
+ })
67
+
68
+ it('should support `gap`', () => {
69
+ render(<Button gap={18} icon={AddIcon} text="Button text" />)
70
+
71
+ const propsList = mockedFlex.mock.calls.map(([props]) => props)
72
+ expect(propsList).toContainEqual(expect.objectContaining({gap: [18]}))
73
+ })
74
+
75
+ it('should prefer `gap` over `space` when both are provided', () => {
76
+ render(<Button gap={19} icon={AddIcon} space={20} text="Button text" />)
77
+
78
+ const propsList = mockedFlex.mock.calls.map(([props]) => props)
79
+ expect(propsList).toContainEqual(expect.objectContaining({gap: [19]}))
80
+ expect(propsList).not.toContainEqual(expect.objectContaining({gap: [20]}))
81
+ })
44
82
  })
@@ -29,7 +29,11 @@ export interface ButtonProps extends ResponsivePaddingProps, ResponsiveRadiusPro
29
29
  */
30
30
  loading?: boolean
31
31
  selected?: boolean
32
+ /**
33
+ * @deprecated Use `gap` instead. `space` will be removed in v4.
34
+ */
32
35
  space?: number | number[]
36
+ gap?: number | number[]
33
37
  muted?: boolean
34
38
  text?: React.ReactNode
35
39
  textAlign?: ButtonTextAlign
@@ -84,7 +88,8 @@ export const Button = forwardRef(function Button(
84
88
  paddingRight: paddingRightProp,
85
89
  radius: radiusProp = 2,
86
90
  selected,
87
- space: spaceProp = 3,
91
+ gap,
92
+ space: deprecated_space = 3,
88
93
  text,
89
94
  textAlign,
90
95
  textWeight,
@@ -105,7 +110,7 @@ export const Button = forwardRef(function Button(
105
110
  const paddingLeft = _getArrayProp(paddingLeftProp)
106
111
  const paddingRight = _getArrayProp(paddingRightProp)
107
112
  const radius = _getArrayProp(radiusProp)
108
- const space = _getArrayProp(spaceProp)
113
+ const spacing = _getArrayProp(gap === undefined ? deprecated_space : gap)
109
114
 
110
115
  const boxProps = useMemo(
111
116
  () => ({
@@ -143,7 +148,7 @@ export const Button = forwardRef(function Button(
143
148
 
144
149
  {(IconComponent || text || IconRightComponent) && (
145
150
  <Box as="span" {...boxProps}>
146
- <Flex as="span" justify={justify} gap={space}>
151
+ <Flex as="span" justify={justify} gap={spacing}>
147
152
  {IconComponent && (
148
153
  <Text size={fontSize}>
149
154
  {isValidElement(IconComponent) && IconComponent}
@@ -0,0 +1,78 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import {render} from '../../../../test'
4
+ import {responsiveGridStyle} from '../../styles/internal'
5
+ import {Grid} from './grid'
6
+
7
+ jest.mock('../../styles/internal', () => {
8
+ const actual = jest.requireActual('../../styles/internal')
9
+
10
+ return {
11
+ ...actual,
12
+ responsiveGridStyle: jest.fn(actual.responsiveGridStyle),
13
+ }
14
+ })
15
+
16
+ describe('primitives/grid', () => {
17
+ const mockedResponsiveGridStyle = jest.mocked(responsiveGridStyle)
18
+
19
+ beforeEach(() => {
20
+ mockedResponsiveGridStyle.mockClear()
21
+ })
22
+
23
+ it('should support `columns` and `gridTemplateColumns` with the same behavior', () => {
24
+ render(
25
+ <Grid columns={2}>
26
+ <div>A</div>
27
+ </Grid>,
28
+ )
29
+ expect(mockedResponsiveGridStyle).toHaveBeenCalledWith(expect.objectContaining({$columns: [2]}))
30
+
31
+ mockedResponsiveGridStyle.mockClear()
32
+ render(
33
+ <Grid gridTemplateColumns={2}>
34
+ <div>A</div>
35
+ </Grid>,
36
+ )
37
+ expect(mockedResponsiveGridStyle).toHaveBeenCalledWith(expect.objectContaining({$columns: [2]}))
38
+ })
39
+
40
+ it('should prefer `gridTemplateColumns` over `columns` when both are provided', () => {
41
+ render(
42
+ <Grid columns={1} gridTemplateColumns={3}>
43
+ <div>A</div>
44
+ </Grid>,
45
+ )
46
+ expect(mockedResponsiveGridStyle).toHaveBeenCalledWith(expect.objectContaining({$columns: [3]}))
47
+ expect(mockedResponsiveGridStyle).not.toHaveBeenCalledWith(
48
+ expect.objectContaining({$columns: [1]}),
49
+ )
50
+ })
51
+
52
+ it('should support `rows` and `gridTemplateRows` with the same behavior', () => {
53
+ render(
54
+ <Grid rows={2}>
55
+ <div>A</div>
56
+ </Grid>,
57
+ )
58
+ expect(mockedResponsiveGridStyle).toHaveBeenCalledWith(expect.objectContaining({$rows: [2]}))
59
+
60
+ mockedResponsiveGridStyle.mockClear()
61
+ render(
62
+ <Grid gridTemplateRows={2}>
63
+ <div>A</div>
64
+ </Grid>,
65
+ )
66
+ expect(mockedResponsiveGridStyle).toHaveBeenCalledWith(expect.objectContaining({$rows: [2]}))
67
+ })
68
+
69
+ it('should prefer `gridTemplateRows` over `rows` when both are provided', () => {
70
+ render(
71
+ <Grid gridTemplateRows={3} rows={1}>
72
+ <div>A</div>
73
+ </Grid>,
74
+ )
75
+ expect(mockedResponsiveGridStyle).toHaveBeenCalledWith(expect.objectContaining({$rows: [3]}))
76
+ expect(mockedResponsiveGridStyle).not.toHaveBeenCalledWith(expect.objectContaining({$rows: [1]}))
77
+ })
78
+ })
@@ -22,8 +22,21 @@ export const Grid = forwardRef(function Grid(
22
22
  props: GridProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height' | 'rows'>,
23
23
  ref: React.ForwardedRef<HTMLDivElement>,
24
24
  ) {
25
- const {as, autoRows, autoCols, autoFlow, columns, gap, gapX, gapY, rows, children, ...restProps} =
26
- props
25
+ const {
26
+ as,
27
+ autoRows,
28
+ autoCols,
29
+ autoFlow,
30
+ columns,
31
+ gridTemplateColumns,
32
+ gap,
33
+ gapX,
34
+ gapY,
35
+ rows,
36
+ gridTemplateRows,
37
+ children,
38
+ ...restProps
39
+ } = props
27
40
 
28
41
  return (
29
42
  <StyledGrid
@@ -33,11 +46,11 @@ export const Grid = forwardRef(function Grid(
33
46
  $autoRows={_getArrayProp(autoRows)}
34
47
  $autoCols={_getArrayProp(autoCols)}
35
48
  $autoFlow={_getArrayProp(autoFlow)}
36
- $columns={_getArrayProp(columns)}
49
+ $columns={_getArrayProp(gridTemplateColumns === undefined ? columns : gridTemplateColumns)}
37
50
  $gap={_getArrayProp(gap)}
38
51
  $gapX={_getArrayProp(gapX)}
39
52
  $gapY={_getArrayProp(gapY)}
40
- $rows={_getArrayProp(rows)}
53
+ $rows={_getArrayProp(gridTemplateRows === undefined ? rows : gridTemplateRows)}
41
54
  forwardedAs={as}
42
55
  ref={ref}
43
56
  >
@@ -0,0 +1,51 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import {render} from '../../../../test'
4
+ import {Inline} from './inline'
5
+ import {inlineSpaceStyle} from './styles'
6
+
7
+ jest.mock('./styles', () => {
8
+ const actual = jest.requireActual('./styles')
9
+
10
+ return {
11
+ ...actual,
12
+ inlineSpaceStyle: jest.fn(actual.inlineSpaceStyle),
13
+ }
14
+ })
15
+
16
+ describe('primitives/inline', () => {
17
+ const mockedInlineSpaceStyle = jest.mocked(inlineSpaceStyle)
18
+
19
+ beforeEach(() => {
20
+ mockedInlineSpaceStyle.mockClear()
21
+ })
22
+
23
+ it('should support `space` and `gap` with the same behavior', () => {
24
+ render(
25
+ <Inline space={2}>
26
+ <span>One</span>
27
+ <span>Two</span>
28
+ </Inline>,
29
+ )
30
+ expect(mockedInlineSpaceStyle).toHaveBeenCalledWith(expect.objectContaining({$space: [2]}))
31
+
32
+ mockedInlineSpaceStyle.mockClear()
33
+ render(
34
+ <Inline gap={2}>
35
+ <span>One</span>
36
+ <span>Two</span>
37
+ </Inline>,
38
+ )
39
+ expect(mockedInlineSpaceStyle).toHaveBeenCalledWith(expect.objectContaining({$space: [2]}))
40
+ })
41
+
42
+ it('should prefer `gap` over `space` when both are provided', () => {
43
+ render(
44
+ <Inline gap={3} space={1}>
45
+ <span>One</span>
46
+ <span>Two</span>
47
+ </Inline>,
48
+ )
49
+ expect(mockedInlineSpaceStyle).toHaveBeenCalledWith(expect.objectContaining({$space: [3]}))
50
+ })
51
+ })
@@ -10,8 +10,13 @@ import {ResponsiveInlineSpaceStyleProps} from './types'
10
10
  * @public
11
11
  */
12
12
  export interface InlineProps extends Omit<BoxProps, 'display'> {
13
- /** The spacing between children. */
13
+ /**
14
+ * The spacing between children.
15
+ * @deprecated Use `gap` instead. `space` will be removed in v4.
16
+ */
14
17
  space?: number | number[]
18
+ /** The spacing between children. */
19
+ gap?: number | number[]
15
20
  }
16
21
 
17
22
  const StyledInline = styled(Box)<ResponsiveInlineSpaceStyleProps>(inlineBaseStyle, inlineSpaceStyle)
@@ -25,7 +30,8 @@ export const Inline = forwardRef(function Inline(
25
30
  props: InlineProps & React.HTMLProps<HTMLDivElement>,
26
31
  ref,
27
32
  ) {
28
- const {as, children: childrenProp, space, ...restProps} = props
33
+ const {as, children: childrenProp, gap, space: deprecated_space, ...restProps} = props
34
+ const spacing = gap === undefined ? deprecated_space : gap
29
35
 
30
36
  const children = useMemo(
31
37
  () => Children.map(childrenProp, (child) => child && <div>{child}</div>),
@@ -36,7 +42,7 @@ export const Inline = forwardRef(function Inline(
36
42
  <StyledInline
37
43
  data-ui="Inline"
38
44
  {...restProps}
39
- $space={_getArrayProp(space)}
45
+ $space={_getArrayProp(spacing)}
40
46
  forwardedAs={as}
41
47
  ref={ref as any}
42
48
  >
@@ -0,0 +1,52 @@
1
+ /** @jest-environment jsdom */
2
+
3
+ import {render} from '../../../../test'
4
+ import {Select} from './select'
5
+ import {selectStyle} from './styles'
6
+
7
+ jest.mock('./styles', () => {
8
+ const actual = jest.requireActual('./styles')
9
+
10
+ return {
11
+ ...actual,
12
+ selectStyle: {
13
+ ...actual.selectStyle,
14
+ input: jest.fn(actual.selectStyle.input),
15
+ },
16
+ }
17
+ })
18
+
19
+ describe('primitives/select spacing', () => {
20
+ const mockedSelectInputStyle = jest.mocked(selectStyle.input)
21
+
22
+ beforeEach(() => {
23
+ mockedSelectInputStyle.mockClear()
24
+ })
25
+
26
+ it('should support `space` and `gap` with the same behavior', () => {
27
+ render(
28
+ <Select space={2}>
29
+ <option>Option A</option>
30
+ </Select>,
31
+ )
32
+ expect(mockedSelectInputStyle).toHaveBeenCalledWith(expect.objectContaining({$space: [2]}))
33
+
34
+ mockedSelectInputStyle.mockClear()
35
+ render(
36
+ <Select gap={2}>
37
+ <option>Option A</option>
38
+ </Select>,
39
+ )
40
+ expect(mockedSelectInputStyle).toHaveBeenCalledWith(expect.objectContaining({$space: [2]}))
41
+ })
42
+
43
+ it('should prefer `gap` over `space` when both are provided', () => {
44
+ render(
45
+ <Select gap={3} space={1}>
46
+ <option>Option A</option>
47
+ </Select>,
48
+ )
49
+ expect(mockedSelectInputStyle).toHaveBeenCalledWith(expect.objectContaining({$space: [3]}))
50
+ expect(mockedSelectInputStyle).not.toHaveBeenCalledWith(expect.objectContaining({$space: [1]}))
51
+ })
52
+ })
@@ -14,8 +14,12 @@ import {selectStyle} from './styles'
14
14
  */
15
15
  export interface SelectProps {
16
16
  fontSize?: number | number[]
17
+ gap?: number | number[]
17
18
  padding?: number | number[]
18
19
  radius?: Radius | Radius[]
20
+ /**
21
+ * @deprecated Use `gap` instead. `space` will be removed in v4.
22
+ */
19
23
  space?: number | number[]
20
24
  customValidity?: string
21
25
  }
@@ -45,12 +49,14 @@ export const Select = forwardRef(function Select(
45
49
  customValidity,
46
50
  disabled,
47
51
  fontSize = 2,
52
+ gap,
48
53
  padding = 3,
49
54
  radius = 2,
50
55
  readOnly,
51
- space = 3,
56
+ space: deprecated_space = 3,
52
57
  ...restProps
53
58
  } = props
59
+ const spacing = gap === undefined ? deprecated_space : gap
54
60
 
55
61
  const ref = useRef<HTMLSelectElement | null>(null)
56
62
 
@@ -70,7 +76,7 @@ export const Select = forwardRef(function Select(
70
76
  $fontSize={_getArrayProp(fontSize)}
71
77
  $padding={_getArrayProp(padding)}
72
78
  $radius={_getArrayProp(radius)}
73
- $space={_getArrayProp(space)}
79
+ $space={_getArrayProp(spacing)}
74
80
  disabled={disabled || readOnly}
75
81
  ref={ref}
76
82
  >