@sanity/ui 1.8.2 → 1.9.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/index.esm.js +22 -8
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +22 -8
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
- package/src/primitives/_selectable/style.ts +1 -0
- package/src/primitives/button/__workshop__/sanityUploadButton.tsx +2 -1
- package/src/primitives/card/styles.ts +1 -0
- package/src/primitives/select/styles.ts +1 -0
- package/src/primitives/tooltip/tooltip.test.tsx +67 -0
- package/src/primitives/tooltip/tooltip.tsx +25 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"source": "./src/index.ts",
|
|
@@ -53,40 +53,40 @@
|
|
|
53
53
|
"@sanity/color": "^2.2.5",
|
|
54
54
|
"@sanity/icons": "^2.4.1",
|
|
55
55
|
"csstype": "^3.1.2",
|
|
56
|
-
"framer-motion": "^10.16.
|
|
56
|
+
"framer-motion": "^10.16.2",
|
|
57
57
|
"react-refractor": "^2.1.7"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@babel/core": "^7.22.
|
|
61
|
-
"@babel/preset-env": "^7.22.
|
|
60
|
+
"@babel/core": "^7.22.11",
|
|
61
|
+
"@babel/preset-env": "^7.22.14",
|
|
62
62
|
"@babel/preset-react": "^7.22.5",
|
|
63
|
-
"@babel/preset-typescript": "^7.22.
|
|
63
|
+
"@babel/preset-typescript": "^7.22.11",
|
|
64
64
|
"@commitlint/cli": "^17.7.1",
|
|
65
65
|
"@commitlint/config-conventional": "^17.7.0",
|
|
66
66
|
"@juggle/resize-observer": "^3.4.0",
|
|
67
67
|
"@sanity/pkg-utils": "^2.4.8",
|
|
68
|
-
"@sanity/semantic-release-preset": "^4.1.
|
|
68
|
+
"@sanity/semantic-release-preset": "^4.1.4",
|
|
69
69
|
"@sanity/ui-workshop": "^1.2.11",
|
|
70
70
|
"@testing-library/dom": "^9.3.1",
|
|
71
71
|
"@testing-library/jest-dom": "^5.17.0",
|
|
72
72
|
"@testing-library/react": "^14.0.0",
|
|
73
73
|
"@types/jest": "^29.5.4",
|
|
74
74
|
"@types/jest-axe": "^3.5.5",
|
|
75
|
-
"@types/node": "^20.5.
|
|
75
|
+
"@types/node": "^20.5.9",
|
|
76
76
|
"@types/react": "^18.2.21",
|
|
77
77
|
"@types/react-dom": "^18.2.7",
|
|
78
78
|
"@types/react-is": "^18.2.1",
|
|
79
79
|
"@types/refractor": "^3.0.2",
|
|
80
80
|
"@types/testing-library__jest-dom": "^5.14.9",
|
|
81
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
82
|
-
"@typescript-eslint/parser": "^6.
|
|
81
|
+
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
|
82
|
+
"@typescript-eslint/parser": "^6.5.0",
|
|
83
83
|
"commitizen": "^4.3.0",
|
|
84
|
-
"cypress": "^
|
|
85
|
-
"cypress-real-events": "^1.10.
|
|
84
|
+
"cypress": "^13.1.0",
|
|
85
|
+
"cypress-real-events": "^1.10.1",
|
|
86
86
|
"cz-conventional-changelog": "^3.3.0",
|
|
87
87
|
"esbuild": "^0.19.2",
|
|
88
88
|
"esbuild-register": "^3.4.2",
|
|
89
|
-
"eslint": "^8.
|
|
89
|
+
"eslint": "^8.48.0",
|
|
90
90
|
"eslint-config-prettier": "^9.0.0",
|
|
91
91
|
"eslint-plugin-import": "^2.28.1",
|
|
92
92
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
@@ -101,17 +101,17 @@
|
|
|
101
101
|
"lint-staged": "^14.0.1",
|
|
102
102
|
"module-alias": "^2.2.3",
|
|
103
103
|
"npm-run-all": "^4.1.5",
|
|
104
|
-
"prettier": "^3.0.
|
|
104
|
+
"prettier": "^3.0.3",
|
|
105
105
|
"react": "^18.2.0",
|
|
106
106
|
"react-dom": "^18.2.0",
|
|
107
107
|
"react-is": "^18.2.0",
|
|
108
108
|
"refractor": "^4.8.1",
|
|
109
109
|
"rimraf": "^5.0.1",
|
|
110
|
-
"semantic-release": "^21.1.
|
|
110
|
+
"semantic-release": "^21.1.1",
|
|
111
111
|
"start-server-and-test": "^2.0.0",
|
|
112
112
|
"styled-components": "^6.0.7",
|
|
113
113
|
"tsconfig-paths": "^4.2.0",
|
|
114
|
-
"typescript": "^5.
|
|
114
|
+
"typescript": "^5.2.2"
|
|
115
115
|
},
|
|
116
116
|
"peerDependencies": {
|
|
117
117
|
"react": "^18",
|
|
@@ -4,7 +4,7 @@ import styled from 'styled-components'
|
|
|
4
4
|
|
|
5
5
|
const SanityUploadButton = styled(Button).attrs({forwardedAs: 'label'})`
|
|
6
6
|
& input {
|
|
7
|
-
|
|
7
|
+
appearance: none;
|
|
8
8
|
overflow: hidden;
|
|
9
9
|
overflow: clip;
|
|
10
10
|
top: 0;
|
|
@@ -14,6 +14,7 @@ const SanityUploadButton = styled(Button).attrs({forwardedAs: 'label'})`
|
|
|
14
14
|
opacity: 0;
|
|
15
15
|
position: absolute;
|
|
16
16
|
max-width: 0;
|
|
17
|
+
width: -webkit-fill-available;
|
|
17
18
|
width: stretch;
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -275,4 +275,71 @@ describe('Tooltip', () => {
|
|
|
275
275
|
jest.clearAllMocks()
|
|
276
276
|
})
|
|
277
277
|
})
|
|
278
|
+
describe('Closing the <Tooltip /> with the Escape key', () => {
|
|
279
|
+
it('Standalone tooltip closes immediately with Escape key', () => {
|
|
280
|
+
const delay = 150
|
|
281
|
+
|
|
282
|
+
jest.useFakeTimers()
|
|
283
|
+
|
|
284
|
+
render(
|
|
285
|
+
<Tooltip
|
|
286
|
+
content={<Text size={1}>{'Tooltip content'}</Text>}
|
|
287
|
+
placement={'top'}
|
|
288
|
+
delay={delay}
|
|
289
|
+
>
|
|
290
|
+
<Button mode="bleed" text="Hover me" />
|
|
291
|
+
</Tooltip>,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
const button = screen.getByText('Hover me')
|
|
295
|
+
|
|
296
|
+
// Validate tooltip content is not rendered
|
|
297
|
+
expect(screen.queryByText('Tooltip content')).not.toBeInTheDocument()
|
|
298
|
+
fireEvent.focus(button)
|
|
299
|
+
act(() => jest.advanceTimersByTime(delay))
|
|
300
|
+
|
|
301
|
+
// Validate tooltip content is rendered
|
|
302
|
+
screen.getByText('Tooltip content')
|
|
303
|
+
|
|
304
|
+
act(() => {
|
|
305
|
+
fireEvent.keyDown(button, {key: 'Escape', code: 'Escape'})
|
|
306
|
+
})
|
|
307
|
+
// Validate tooltip content is not rendered anymore
|
|
308
|
+
expect(screen.queryByText('Tooltip content')).not.toBeInTheDocument()
|
|
309
|
+
})
|
|
310
|
+
it('With <TooltipDelayGroupProvider /> closes immediately with Escape key', () => {
|
|
311
|
+
const delay = 150
|
|
312
|
+
|
|
313
|
+
jest.useFakeTimers()
|
|
314
|
+
|
|
315
|
+
render(
|
|
316
|
+
<TooltipDelayGroupProvider delay={{close: delay}}>
|
|
317
|
+
<Tooltip
|
|
318
|
+
content={<Text size={1}>{'Tooltip content'}</Text>}
|
|
319
|
+
placement={'top'}
|
|
320
|
+
delay={{close: delay}}
|
|
321
|
+
>
|
|
322
|
+
<Button mode="bleed" text="Hover me" />
|
|
323
|
+
</Tooltip>
|
|
324
|
+
</TooltipDelayGroupProvider>,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
const button = screen.getByText('Hover me')
|
|
328
|
+
|
|
329
|
+
// Validate tooltip content is not rendered
|
|
330
|
+
expect(screen.queryByText('Tooltip content')).not.toBeInTheDocument()
|
|
331
|
+
fireEvent.focus(button)
|
|
332
|
+
|
|
333
|
+
act(() => jest.advanceTimersByTime(delay))
|
|
334
|
+
|
|
335
|
+
// Validate tooltip content is rendered
|
|
336
|
+
screen.getByText('Tooltip content')
|
|
337
|
+
|
|
338
|
+
act(() => {
|
|
339
|
+
fireEvent.keyDown(button, {key: 'Escape', code: 'Escape'})
|
|
340
|
+
})
|
|
341
|
+
// Validate tooltip content is not rendered anymore
|
|
342
|
+
expect(screen.queryByText('Tooltip content')).not.toBeInTheDocument()
|
|
343
|
+
})
|
|
344
|
+
})
|
|
278
345
|
})
|
|
@@ -177,23 +177,27 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
177
177
|
const closeDelay = isInsideGroup ? delayGroupContext.closeDelay : closeDelayProp
|
|
178
178
|
|
|
179
179
|
const handleIsOpenChange = useCallback(
|
|
180
|
-
(open: boolean) => {
|
|
180
|
+
(open: boolean, immediate?: boolean) => {
|
|
181
181
|
if (isInsideGroup) {
|
|
182
182
|
// When it's inside a group, the open or close status will be handled by the group.
|
|
183
183
|
if (open) {
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
const groupedOpenDelay = immediate ? 0 : openDelay
|
|
185
|
+
|
|
186
|
+
delayGroupContext.setIsGroupActive(open, groupedOpenDelay)
|
|
187
|
+
delayGroupContext.setOpenTooltipId(tooltipId, groupedOpenDelay)
|
|
186
188
|
} else {
|
|
187
189
|
const minimumGroupDeactivateDelay = 200 // We should provide some delay to allow the user to reach the next tooltip.
|
|
188
190
|
const groupDeactivateDelay =
|
|
189
191
|
closeDelay > minimumGroupDeactivateDelay ? closeDelay : minimumGroupDeactivateDelay
|
|
190
192
|
|
|
191
193
|
delayGroupContext.setIsGroupActive(open, groupDeactivateDelay)
|
|
192
|
-
delayGroupContext.setOpenTooltipId(null, closeDelay)
|
|
194
|
+
delayGroupContext.setOpenTooltipId(null, immediate ? 0 : closeDelay)
|
|
193
195
|
}
|
|
194
196
|
} else {
|
|
197
|
+
const standaloneDelay = immediate ? 0 : open ? openDelay : closeDelay
|
|
198
|
+
|
|
195
199
|
// When it's not inside a group, the open or close status will be handled by the tooltip itself.
|
|
196
|
-
setIsOpen(open,
|
|
200
|
+
setIsOpen(open, standaloneDelay)
|
|
197
201
|
}
|
|
198
202
|
},
|
|
199
203
|
[isInsideGroup, delayGroupContext, openDelay, tooltipId, closeDelay, setIsOpen],
|
|
@@ -243,6 +247,22 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
243
247
|
// Update reference
|
|
244
248
|
useEffect(() => refs.setReference(referenceElement), [referenceElement, refs])
|
|
245
249
|
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
// If the user clicks on escape key, close the tooltip.
|
|
252
|
+
if (!showTooltip) return
|
|
253
|
+
|
|
254
|
+
function handleWindowKeyDown(event: KeyboardEvent) {
|
|
255
|
+
if (event.key === 'Escape') {
|
|
256
|
+
handleIsOpenChange(false, true)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
window.addEventListener('keydown', handleWindowKeyDown)
|
|
261
|
+
|
|
262
|
+
return () => {
|
|
263
|
+
window.removeEventListener('keydown', handleWindowKeyDown)
|
|
264
|
+
}
|
|
265
|
+
}, [handleIsOpenChange, showTooltip])
|
|
246
266
|
const setArrow = useCallback(
|
|
247
267
|
(arrowEl: HTMLDivElement | null) => {
|
|
248
268
|
arrowRef.current = arrowEl
|