@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.
- package/dist/_chunks-cjs/_visual-editing.js +269 -249
- package/dist/_chunks-cjs/_visual-editing.js.map +1 -1
- package/dist/_chunks-es/_visual-editing.mjs +269 -249
- package/dist/_chunks-es/_visual-editing.mjs.map +1 -1
- package/dist/_visual-editing.d.mts +66 -1
- package/dist/_visual-editing.d.ts +66 -1
- package/dist/index.d.mts +86 -1
- package/dist/index.d.ts +86 -1
- package/dist/index.js +97 -93
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +97 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/core/components/breadcrumbs/breadcrumbs.test.tsx +51 -0
- package/src/core/components/breadcrumbs/breadcrumbs.tsx +7 -3
- package/src/core/components/hotkeys/hotkeys.test.tsx +42 -0
- package/src/core/components/hotkeys/hotkeys.tsx +7 -3
- package/src/core/components/menu/menu.spacing.test.tsx +63 -0
- package/src/core/components/menu/menu.tsx +8 -2
- package/src/core/components/menu/menuGroup.spacing.test.tsx +69 -0
- package/src/core/components/menu/menuGroup.tsx +8 -2
- package/src/core/components/menu/menuItem.spacing.test.tsx +59 -0
- package/src/core/components/menu/menuItem.tsx +8 -2
- package/src/core/components/tab/tabList.test.tsx +48 -0
- package/src/core/components/tree/tree.test.tsx +55 -0
- package/src/core/components/tree/tree.tsx +10 -4
- package/src/core/components/tree/treeGroup.tsx +2 -2
- package/src/core/components/tree/treeItem.test.tsx +65 -0
- package/src/core/components/tree/treeItem.tsx +8 -2
- package/src/core/components/tree/types.ts +4 -0
- package/src/core/primitives/box/box.test.tsx +134 -0
- package/src/core/primitives/box/box.tsx +18 -6
- package/src/core/primitives/button/button.test.tsx +38 -0
- package/src/core/primitives/button/button.tsx +8 -3
- package/src/core/primitives/grid/grid.test.tsx +78 -0
- package/src/core/primitives/grid/grid.tsx +17 -4
- package/src/core/primitives/inline/inline.test.tsx +51 -0
- package/src/core/primitives/inline/inline.tsx +9 -3
- package/src/core/primitives/select/select.test.tsx +52 -0
- package/src/core/primitives/select/select.tsx +8 -2
- package/src/core/primitives/stack/stack.test.tsx +57 -0
- package/src/core/primitives/stack/stack.tsx +7 -2
- package/src/core/primitives/textInput/textInput.test.tsx +48 -0
- package/src/core/primitives/textInput/textInput.tsx +7 -2
- 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
|
-
|
|
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={
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
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
|
|
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={
|
|
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 {
|
|
26
|
-
|
|
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
|
-
/**
|
|
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(
|
|
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(
|
|
79
|
+
$space={_getArrayProp(spacing)}
|
|
74
80
|
disabled={disabled || readOnly}
|
|
75
81
|
ref={ref}
|
|
76
82
|
>
|