@sanity/ui 2.2.0 → 2.3.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.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.esm.js +124 -113
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +123 -112
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +124 -113
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -9
- package/src/core/components/autocomplete/autocomplete.tsx +9 -12
- package/src/core/components/dialog/dialog.tsx +20 -32
- package/src/core/components/menu/menu.tsx +8 -6
- package/src/core/components/menu/menuItem.tsx +10 -10
- package/src/core/components/tab/tab.tsx +9 -12
- package/src/core/components/tree/tree.tsx +21 -8
- package/src/core/hooks/useForwardedRef.ts +9 -11
- package/src/core/hooks/useIsomorphicEffect.ts +1 -0
- package/src/core/primitives/checkbox/checkbox.tsx +10 -5
- package/src/core/primitives/popover/popover.tsx +13 -13
- package/src/core/primitives/radio/radio.tsx +8 -3
- package/src/core/primitives/select/select.tsx +8 -3
- package/src/core/primitives/switch/switch.tsx +8 -4
- package/src/core/primitives/textArea/textArea.tsx +8 -3
- package/src/core/primitives/textInput/textInput.tsx +16 -4
- package/src/core/primitives/tooltip/tooltip.tsx +8 -5
- package/src/core/utils/elementQuery/elementQuery.tsx +10 -11
- package/src/core/utils/layer/layer.tsx +8 -13
- package/src/core/utils/virtualList/virtualList.tsx +10 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"sanity",
|
|
6
6
|
"ui",
|
|
@@ -119,9 +119,9 @@
|
|
|
119
119
|
"@commitlint/cli": "^19.3.0",
|
|
120
120
|
"@commitlint/config-conventional": "^19.2.2",
|
|
121
121
|
"@juggle/resize-observer": "^3.4.0",
|
|
122
|
-
"@sanity/pkg-utils": "^6.8.
|
|
123
|
-
"@sanity/semantic-release-preset": "^4.1.
|
|
124
|
-
"@sanity/ui-workshop": "^2.0.
|
|
122
|
+
"@sanity/pkg-utils": "^6.8.19",
|
|
123
|
+
"@sanity/semantic-release-preset": "^4.1.8",
|
|
124
|
+
"@sanity/ui-workshop": "^2.0.15",
|
|
125
125
|
"@storybook/addon-a11y": "^8.0.8",
|
|
126
126
|
"@storybook/addon-docs": "^8.0.8",
|
|
127
127
|
"@storybook/addon-essentials": "^8.0.8",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
"@storybook/theming": "^8.0.8",
|
|
139
139
|
"@testing-library/dom": "^10.1.0",
|
|
140
140
|
"@testing-library/jest-dom": "^5.17.0",
|
|
141
|
-
"@testing-library/react": "^
|
|
141
|
+
"@testing-library/react": "^16.0.0",
|
|
142
142
|
"@types/jest": "^29.5.12",
|
|
143
143
|
"@types/jest-axe": "^3.5.9",
|
|
144
144
|
"@types/node": "^20.12.7",
|
|
@@ -147,8 +147,8 @@
|
|
|
147
147
|
"@types/react-is": "^18.3.0",
|
|
148
148
|
"@types/refractor": "^3.4.1",
|
|
149
149
|
"@types/testing-library__jest-dom": "^5.14.9",
|
|
150
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
151
|
-
"@typescript-eslint/parser": "^7.
|
|
150
|
+
"@typescript-eslint/eslint-plugin": "^7.12.0",
|
|
151
|
+
"@typescript-eslint/parser": "^7.12.0",
|
|
152
152
|
"commitizen": "^4.3.0",
|
|
153
153
|
"cypress": "^13.10.0",
|
|
154
154
|
"cypress-real-events": "^1.12.0",
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
|
161
161
|
"eslint-plugin-prettier": "^5.1.3",
|
|
162
162
|
"eslint-plugin-react": "^7.34.2",
|
|
163
|
-
"eslint-plugin-react-compiler": "0.0.0-experimental-
|
|
163
|
+
"eslint-plugin-react-compiler": "0.0.0-experimental-a97cca1-20240529",
|
|
164
164
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
165
165
|
"eslint-plugin-storybook": "^0.8.0",
|
|
166
166
|
"http-server": "^14.1.1",
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
"react-is": "^18.3.1",
|
|
179
179
|
"refractor": "^4.8.1",
|
|
180
180
|
"rimraf": "^5.0.5",
|
|
181
|
-
"semantic-release": "^
|
|
181
|
+
"semantic-release": "^24.0.0",
|
|
182
182
|
"start-server-and-test": "^2.0.3",
|
|
183
183
|
"storybook": "^8.0.8",
|
|
184
184
|
"styled-components": "^6.1.11",
|
|
@@ -202,5 +202,10 @@
|
|
|
202
202
|
},
|
|
203
203
|
"esm.sh": {
|
|
204
204
|
"bundle": false
|
|
205
|
+
},
|
|
206
|
+
"pnpm": {
|
|
207
|
+
"overrides": {
|
|
208
|
+
"conventional-changelog-conventionalcommits": ">= 8.0.0"
|
|
209
|
+
}
|
|
205
210
|
}
|
|
206
211
|
}
|
|
@@ -13,13 +13,14 @@ import {
|
|
|
13
13
|
forwardRef,
|
|
14
14
|
useCallback,
|
|
15
15
|
useEffect,
|
|
16
|
+
useImperativeHandle,
|
|
16
17
|
useMemo,
|
|
17
18
|
useReducer,
|
|
18
19
|
useRef,
|
|
19
20
|
} from 'react'
|
|
20
21
|
import {EMPTY_ARRAY, EMPTY_RECORD} from '../../constants'
|
|
21
22
|
import {_hasFocus, _raf, focusFirstDescendant} from '../../helpers'
|
|
22
|
-
import {useArrayProp
|
|
23
|
+
import {useArrayProp} from '../../hooks'
|
|
23
24
|
import {
|
|
24
25
|
Box,
|
|
25
26
|
BoxProps,
|
|
@@ -119,7 +120,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
|
|
|
119
120
|
| 'type'
|
|
120
121
|
| 'value'
|
|
121
122
|
>,
|
|
122
|
-
|
|
123
|
+
forwardedRef: React.ForwardedRef<HTMLInputElement>,
|
|
123
124
|
) {
|
|
124
125
|
const {
|
|
125
126
|
border = true,
|
|
@@ -191,7 +192,11 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
|
|
|
191
192
|
const valuePropRef = useRef(valueProp)
|
|
192
193
|
const popoverMouseWithinRef = useRef(false)
|
|
193
194
|
|
|
194
|
-
|
|
195
|
+
// Forward ref to parent
|
|
196
|
+
useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(
|
|
197
|
+
forwardedRef,
|
|
198
|
+
() => inputElementRef.current,
|
|
199
|
+
)
|
|
195
200
|
|
|
196
201
|
const listBoxId = `${id}-listbox`
|
|
197
202
|
const options = Array.isArray(optionsProp) ? optionsProp : EMPTY_ARRAY
|
|
@@ -432,14 +437,6 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
|
|
|
432
437
|
}
|
|
433
438
|
}, [activeValue, filteredOptions])
|
|
434
439
|
|
|
435
|
-
const setRef = useCallback(
|
|
436
|
-
(el: HTMLInputElement | null) => {
|
|
437
|
-
inputElementRef.current = el
|
|
438
|
-
forwardedRef.current = el
|
|
439
|
-
},
|
|
440
|
-
[forwardedRef],
|
|
441
|
-
)
|
|
442
|
-
|
|
443
440
|
const clearButton = useMemo(() => {
|
|
444
441
|
if (!loading && !disabled && value) {
|
|
445
442
|
return {
|
|
@@ -549,7 +546,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
|
|
|
549
546
|
prefix={prefix}
|
|
550
547
|
radius={radius}
|
|
551
548
|
readOnly={readOnly}
|
|
552
|
-
ref={
|
|
549
|
+
ref={inputElementRef}
|
|
553
550
|
role="combobox"
|
|
554
551
|
spellCheck={false}
|
|
555
552
|
suffix={suffix || openButtonNode}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {CloseIcon} from '@sanity/icons'
|
|
2
2
|
import {ThemeColorSchemeKey} from '@sanity/ui/theme'
|
|
3
|
-
import {forwardRef, useCallback, useEffect, useRef, useState} from 'react'
|
|
3
|
+
import {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'
|
|
4
4
|
import {styled} from 'styled-components'
|
|
5
5
|
import {
|
|
6
6
|
containsOrEqualsElement,
|
|
@@ -8,13 +8,7 @@ import {
|
|
|
8
8
|
focusLastDescendant,
|
|
9
9
|
isHTMLElement,
|
|
10
10
|
} from '../../helpers'
|
|
11
|
-
import {
|
|
12
|
-
useArrayProp,
|
|
13
|
-
useClickOutside,
|
|
14
|
-
useForwardedRef,
|
|
15
|
-
useGlobalKeyDown,
|
|
16
|
-
usePrefersReducedMotion,
|
|
17
|
-
} from '../../hooks'
|
|
11
|
+
import {useArrayProp, useClickOutside, useGlobalKeyDown, usePrefersReducedMotion} from '../../hooks'
|
|
18
12
|
import {Box, Button, Card, Container, Flex, Text} from '../../primitives'
|
|
19
13
|
import {ResponsivePaddingProps, ResponsiveWidthProps} from '../../primitives/types'
|
|
20
14
|
import {responsivePaddingStyle, ResponsivePaddingStyleProps} from '../../styles/internal'
|
|
@@ -151,13 +145,13 @@ const DialogFooter = styled(Box)`
|
|
|
151
145
|
|
|
152
146
|
const DialogCard = forwardRef(function DialogCard(
|
|
153
147
|
props: DialogCardProps,
|
|
154
|
-
|
|
148
|
+
forwardedRef: React.ForwardedRef<HTMLDivElement>,
|
|
155
149
|
) {
|
|
156
150
|
const {
|
|
157
151
|
__unstable_autoFocus: autoFocus,
|
|
158
152
|
__unstable_hideCloseButton: hideCloseButton,
|
|
159
153
|
children,
|
|
160
|
-
contentRef,
|
|
154
|
+
contentRef: forwardedContentRef,
|
|
161
155
|
footer,
|
|
162
156
|
header,
|
|
163
157
|
id,
|
|
@@ -175,23 +169,29 @@ const DialogCard = forwardRef(function DialogCard(
|
|
|
175
169
|
const radius = useArrayProp(radiusProp)
|
|
176
170
|
const shadow = useArrayProp(shadowProp)
|
|
177
171
|
const width = useArrayProp(widthProp)
|
|
178
|
-
const
|
|
172
|
+
const ref = useRef<HTMLDivElement | null>(null)
|
|
179
173
|
const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)
|
|
180
|
-
const
|
|
174
|
+
const contentRef = useRef<HTMLDivElement | null>(null)
|
|
181
175
|
const layer = useLayer()
|
|
182
176
|
const {isTopLayer} = layer
|
|
183
177
|
const labelId = `${id}_label`
|
|
184
178
|
const showCloseButton = Boolean(onClose) && hideCloseButton === false
|
|
185
179
|
const showHeader = Boolean(header) || showCloseButton
|
|
186
180
|
|
|
181
|
+
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
|
|
182
|
+
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(
|
|
183
|
+
forwardedContentRef,
|
|
184
|
+
() => contentRef.current,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
187
|
useEffect(() => {
|
|
188
188
|
if (!autoFocus) return
|
|
189
189
|
|
|
190
190
|
// On mount: focus the first focusable element
|
|
191
|
-
if (
|
|
192
|
-
focusFirstDescendant(
|
|
191
|
+
if (ref.current) {
|
|
192
|
+
focusFirstDescendant(ref.current)
|
|
193
193
|
}
|
|
194
|
-
}, [autoFocus,
|
|
194
|
+
}, [autoFocus, ref])
|
|
195
195
|
|
|
196
196
|
useGlobalKeyDown(
|
|
197
197
|
useCallback(
|
|
@@ -234,22 +234,10 @@ const DialogCard = forwardRef(function DialogCard(
|
|
|
234
234
|
[rootElement],
|
|
235
235
|
)
|
|
236
236
|
|
|
237
|
-
const setRef = useCallback(
|
|
238
|
-
(el
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
},
|
|
242
|
-
[forwardedRef],
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
const setContentRef = useCallback(
|
|
246
|
-
(el: HTMLDivElement | null) => {
|
|
247
|
-
localContentRef.current = el
|
|
248
|
-
if (typeof contentRef === 'function') contentRef(el)
|
|
249
|
-
else if (contentRef) contentRef.current = el
|
|
250
|
-
},
|
|
251
|
-
[contentRef],
|
|
252
|
-
)
|
|
237
|
+
const setRef = useCallback((el: HTMLDivElement | null) => {
|
|
238
|
+
setRootElement(el)
|
|
239
|
+
ref.current = el
|
|
240
|
+
}, [])
|
|
253
241
|
|
|
254
242
|
return (
|
|
255
243
|
<DialogContainer data-ui="DialogCard" width={width}>
|
|
@@ -281,7 +269,7 @@ const DialogCard = forwardRef(function DialogCard(
|
|
|
281
269
|
</DialogHeader>
|
|
282
270
|
)}
|
|
283
271
|
|
|
284
|
-
<DialogContent flex={1} ref={
|
|
272
|
+
<DialogContent flex={1} ref={contentRef} tabIndex={-1}>
|
|
285
273
|
{children}
|
|
286
274
|
</DialogContent>
|
|
287
275
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {forwardRef, useCallback, useEffect, useMemo} from 'react'
|
|
1
|
+
import {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef} from 'react'
|
|
2
2
|
import {styled} from 'styled-components'
|
|
3
|
-
import {useClickOutside,
|
|
3
|
+
import {useClickOutside, useGlobalKeyDown} from '../../hooks'
|
|
4
4
|
import {Box, Stack} from '../../primitives'
|
|
5
5
|
import {ResponsivePaddingProps} from '../../primitives/types'
|
|
6
6
|
import {useLayer} from '../../utils'
|
|
@@ -41,7 +41,7 @@ const Root = styled(Box)`
|
|
|
41
41
|
*/
|
|
42
42
|
export const Menu = forwardRef(function Menu(
|
|
43
43
|
props: MenuProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height' | 'role' | 'tabIndex'>,
|
|
44
|
-
|
|
44
|
+
forwardedRef: React.ForwardedRef<HTMLDivElement>,
|
|
45
45
|
) {
|
|
46
46
|
const {
|
|
47
47
|
children,
|
|
@@ -62,7 +62,9 @@ export const Menu = forwardRef(function Menu(
|
|
|
62
62
|
...restProps
|
|
63
63
|
} = props
|
|
64
64
|
|
|
65
|
-
const
|
|
65
|
+
const ref = useRef<HTMLDivElement | null>(null)
|
|
66
|
+
|
|
67
|
+
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
|
|
66
68
|
|
|
67
69
|
const {isTopLayer} = useLayer()
|
|
68
70
|
|
|
@@ -80,9 +82,9 @@ export const Menu = forwardRef(function Menu(
|
|
|
80
82
|
const handleRefChange = useCallback(
|
|
81
83
|
(el: HTMLDivElement | null) => {
|
|
82
84
|
setRootElement(el)
|
|
83
|
-
|
|
85
|
+
ref.current = el
|
|
84
86
|
},
|
|
85
|
-
[
|
|
87
|
+
[setRootElement],
|
|
86
88
|
)
|
|
87
89
|
|
|
88
90
|
// Trigger `onItemSelect` when active index changes
|
|
@@ -4,11 +4,13 @@ import {
|
|
|
4
4
|
isValidElement,
|
|
5
5
|
useCallback,
|
|
6
6
|
useEffect,
|
|
7
|
+
useImperativeHandle,
|
|
7
8
|
useMemo,
|
|
9
|
+
useRef,
|
|
8
10
|
useState,
|
|
9
11
|
} from 'react'
|
|
10
12
|
import {isValidElementType} from 'react-is'
|
|
11
|
-
import {useArrayProp
|
|
13
|
+
import {useArrayProp} from '../../hooks'
|
|
12
14
|
import {Box, Flex, Text} from '../../primitives'
|
|
13
15
|
import {Selectable} from '../../primitives/_selectable'
|
|
14
16
|
import {ResponsivePaddingProps, ResponsiveRadiusProps} from '../../primitives/types'
|
|
@@ -76,10 +78,11 @@ export const MenuItem = forwardRef(function MenuItem(
|
|
|
76
78
|
} = menu
|
|
77
79
|
const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)
|
|
78
80
|
const active = Boolean(activeElement) && activeElement === rootElement
|
|
81
|
+
const ref = useRef<HTMLDivElement | null>(null)
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
|
|
81
84
|
|
|
82
|
-
|
|
85
|
+
useEffect(() => mount(rootElement, selectedProp), [mount, rootElement, selectedProp])
|
|
83
86
|
|
|
84
87
|
const handleClick = useCallback(
|
|
85
88
|
(event: React.MouseEvent<HTMLDivElement>) => {
|
|
@@ -105,13 +108,10 @@ export const MenuItem = forwardRef(function MenuItem(
|
|
|
105
108
|
|
|
106
109
|
const hotkeysFontSize = useArrayProp(fontSize).map((s) => s - 1)
|
|
107
110
|
|
|
108
|
-
const setRef = useCallback(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
},
|
|
113
|
-
[ref],
|
|
114
|
-
)
|
|
111
|
+
const setRef = useCallback((el: HTMLDivElement | null) => {
|
|
112
|
+
ref.current = el
|
|
113
|
+
setRootElement(el)
|
|
114
|
+
}, [])
|
|
115
115
|
|
|
116
116
|
return (
|
|
117
117
|
<Selectable
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {forwardRef, useCallback, useEffect, useRef} from 'react'
|
|
1
|
+
import {forwardRef, useCallback, useEffect, useImperativeHandle, useRef} from 'react'
|
|
2
2
|
import {styled} from 'styled-components'
|
|
3
|
-
import {useForwardedRef} from '../../hooks'
|
|
4
3
|
import {Button} from '../../primitives'
|
|
5
4
|
import {ButtonTone} from '../../types'
|
|
6
5
|
|
|
@@ -49,9 +48,14 @@ export const Tab = forwardRef(function Tab(
|
|
|
49
48
|
selected,
|
|
50
49
|
...restProps
|
|
51
50
|
} = props
|
|
52
|
-
const
|
|
51
|
+
const ref = useRef<HTMLButtonElement | null>(null)
|
|
53
52
|
const focusedRef = useRef(false)
|
|
54
53
|
|
|
54
|
+
useImperativeHandle<HTMLButtonElement | null, HTMLButtonElement | null>(
|
|
55
|
+
forwardedRef,
|
|
56
|
+
() => ref.current,
|
|
57
|
+
)
|
|
58
|
+
|
|
55
59
|
const handleBlur = useCallback(() => {
|
|
56
60
|
focusedRef.current = false
|
|
57
61
|
}, [])
|
|
@@ -64,20 +68,13 @@ export const Tab = forwardRef(function Tab(
|
|
|
64
68
|
[onFocus],
|
|
65
69
|
)
|
|
66
70
|
|
|
67
|
-
const ref = useForwardedRef(forwardedRef)
|
|
68
|
-
|
|
69
71
|
useEffect(() => {
|
|
70
72
|
if (focused && !focusedRef.current) {
|
|
71
|
-
if (
|
|
73
|
+
if (ref.current) ref.current.focus()
|
|
72
74
|
focusedRef.current = true
|
|
73
75
|
}
|
|
74
76
|
}, [focused])
|
|
75
77
|
|
|
76
|
-
const setRef = (el: HTMLButtonElement | null) => {
|
|
77
|
-
elementRef.current = el
|
|
78
|
-
ref.current = el
|
|
79
|
-
}
|
|
80
|
-
|
|
81
78
|
return (
|
|
82
79
|
<CustomButton
|
|
83
80
|
data-ui="Tab"
|
|
@@ -91,7 +88,7 @@ export const Tab = forwardRef(function Tab(
|
|
|
91
88
|
onBlur={handleBlur}
|
|
92
89
|
onFocus={handleFocus}
|
|
93
90
|
padding={padding}
|
|
94
|
-
ref={
|
|
91
|
+
ref={ref}
|
|
95
92
|
role="tab"
|
|
96
93
|
selected={selected}
|
|
97
94
|
tabIndex={selected ? 0 : -1}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
memo,
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useImperativeHandle,
|
|
7
|
+
useMemo,
|
|
8
|
+
useRef,
|
|
9
|
+
useState,
|
|
10
|
+
} from 'react'
|
|
3
11
|
import {Stack} from '../../primitives'
|
|
4
12
|
import {_findNextItemElement, _findPrevItemElement, _focusItemElement} from './helpers'
|
|
5
13
|
import {TreeContext} from './treeContext'
|
|
@@ -21,10 +29,10 @@ export const Tree = memo(
|
|
|
21
29
|
forwardRef(function Tree(
|
|
22
30
|
props: TreeProps &
|
|
23
31
|
Omit<React.HTMLProps<HTMLDivElement>, 'align' | 'as' | 'height' | 'ref' | 'role' | 'wrap'>,
|
|
24
|
-
|
|
32
|
+
forwardedRef: React.ForwardedRef<HTMLDivElement>,
|
|
25
33
|
): React.ReactElement {
|
|
26
34
|
const {children, space = 1, onFocus, ...restProps} = props
|
|
27
|
-
const
|
|
35
|
+
const ref = useRef<HTMLDivElement | null>(null)
|
|
28
36
|
const [focusedElement, setFocusedElement] = useState<HTMLElement | null>(null)
|
|
29
37
|
const focusedElementRef = useRef(focusedElement)
|
|
30
38
|
const path: string[] = useMemo(() => [], [])
|
|
@@ -32,6 +40,11 @@ export const Tree = memo(
|
|
|
32
40
|
const [state, setState] = useState<TreeState>({})
|
|
33
41
|
const stateRef = useRef(state)
|
|
34
42
|
|
|
43
|
+
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(
|
|
44
|
+
forwardedRef,
|
|
45
|
+
() => ref.current,
|
|
46
|
+
)
|
|
47
|
+
|
|
35
48
|
useEffect(() => {
|
|
36
49
|
focusedElementRef.current = focusedElement
|
|
37
50
|
}, [focusedElement])
|
|
@@ -194,13 +207,13 @@ export const Tree = memo(
|
|
|
194
207
|
)
|
|
195
208
|
|
|
196
209
|
useEffect(() => {
|
|
197
|
-
if (!
|
|
210
|
+
if (!ref.current) return
|
|
198
211
|
const _itemElements = Array.from(
|
|
199
|
-
|
|
212
|
+
ref.current.querySelectorAll('[data-ui="TreeItem"]'),
|
|
200
213
|
) as HTMLElement[]
|
|
201
214
|
|
|
202
215
|
setItemElements(_itemElements)
|
|
203
|
-
}, [children,
|
|
216
|
+
}, [children, ref])
|
|
204
217
|
|
|
205
218
|
return (
|
|
206
219
|
<TreeContext.Provider value={contextValue}>
|
|
@@ -210,7 +223,7 @@ export const Tree = memo(
|
|
|
210
223
|
{...restProps}
|
|
211
224
|
onFocus={handleFocus}
|
|
212
225
|
onKeyDown={handleKeyDown}
|
|
213
|
-
ref={
|
|
226
|
+
ref={ref}
|
|
214
227
|
role="tree"
|
|
215
228
|
space={space}
|
|
216
229
|
>
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
import {useRef} from 'react'
|
|
2
|
-
import {useIsomorphicEffect} from './useIsomorphicEffect'
|
|
1
|
+
import {useImperativeHandle, useRef} from 'react'
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* @beta
|
|
5
|
+
* @deprecated use `useImperativeHandle` instead
|
|
6
|
+
* @example
|
|
7
|
+
* ```diff
|
|
8
|
+
* -const ref = useForwardedRef(forwardedRef)
|
|
9
|
+
* +const ref = useRef(null)
|
|
10
|
+
* +useImperativeHandle(forwardedRef, () => ref.current)
|
|
11
|
+
* ```
|
|
6
12
|
*/
|
|
7
13
|
export function useForwardedRef<T>(ref: React.ForwardedRef<T>): React.MutableRefObject<T | null> {
|
|
8
14
|
const innerRef = useRef<T | null>(null)
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
if (!ref) return
|
|
12
|
-
|
|
13
|
-
if (typeof ref === 'function') {
|
|
14
|
-
ref(innerRef.current)
|
|
15
|
-
} else {
|
|
16
|
-
ref.current = innerRef.current
|
|
17
|
-
}
|
|
18
|
-
})
|
|
16
|
+
useImperativeHandle(ref, () => innerRef.current!)
|
|
19
17
|
|
|
20
18
|
return innerRef
|
|
21
19
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {CheckmarkIcon, RemoveIcon} from '@sanity/icons'
|
|
2
|
-
import {forwardRef, useEffect} from 'react'
|
|
2
|
+
import {forwardRef, useEffect, useImperativeHandle, useRef} from 'react'
|
|
3
3
|
import {styled} from 'styled-components'
|
|
4
|
-
import {
|
|
4
|
+
import {useCustomValidity} from '../../hooks'
|
|
5
5
|
import {checkboxBaseStyles, inputElementStyles} from './styles'
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -34,16 +34,21 @@ export const Checkbox = forwardRef(function Checkbox(
|
|
|
34
34
|
style,
|
|
35
35
|
...restProps
|
|
36
36
|
} = props
|
|
37
|
-
const ref =
|
|
37
|
+
const ref = useRef<HTMLInputElement | null>(null)
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(
|
|
40
|
+
forwardedRef,
|
|
41
|
+
() => ref.current,
|
|
42
|
+
)
|
|
40
43
|
|
|
41
44
|
useEffect(() => {
|
|
42
45
|
if (ref.current) {
|
|
43
46
|
// Set the indeterminate state
|
|
44
47
|
ref.current.indeterminate = indeterminate || false
|
|
45
48
|
}
|
|
46
|
-
}, [indeterminate
|
|
49
|
+
}, [indeterminate])
|
|
50
|
+
|
|
51
|
+
useCustomValidity(ref, customValidity)
|
|
47
52
|
|
|
48
53
|
return (
|
|
49
54
|
<Root className={className} data-ui="Checkbox" style={style}>
|
|
@@ -19,16 +19,11 @@ import {
|
|
|
19
19
|
memo,
|
|
20
20
|
useCallback,
|
|
21
21
|
useEffect,
|
|
22
|
+
useImperativeHandle,
|
|
22
23
|
useMemo,
|
|
23
24
|
useRef,
|
|
24
25
|
} from 'react'
|
|
25
|
-
import {
|
|
26
|
-
useForwardedRef,
|
|
27
|
-
useArrayProp,
|
|
28
|
-
useElementSize,
|
|
29
|
-
useMediaIndex,
|
|
30
|
-
usePrefersReducedMotion,
|
|
31
|
-
} from '../../hooks'
|
|
26
|
+
import {useArrayProp, useElementSize, useMediaIndex, usePrefersReducedMotion} from '../../hooks'
|
|
32
27
|
import {origin} from '../../middleware/origin'
|
|
33
28
|
import {useTheme_v2} from '../../theme'
|
|
34
29
|
import {BoxOverflow, CardTone, Placement, PopoverMargins} from '../../types'
|
|
@@ -127,7 +122,7 @@ export const Popover = memo(
|
|
|
127
122
|
forwardRef(function Popover(
|
|
128
123
|
props: PopoverProps &
|
|
129
124
|
Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'children' | 'content' | 'width'>,
|
|
130
|
-
|
|
125
|
+
forwardedRef: React.ForwardedRef<HTMLDivElement>,
|
|
131
126
|
): React.ReactElement {
|
|
132
127
|
const {container, layer} = useTheme_v2()
|
|
133
128
|
const boundaryElementContext = useBoundaryElement()
|
|
@@ -172,10 +167,15 @@ export const Popover = memo(
|
|
|
172
167
|
const shadow = useArrayProp(shadowProp)
|
|
173
168
|
const widthArrayProp = useArrayProp(widthProp)
|
|
174
169
|
const zOffset = useArrayProp(zOffsetProp)
|
|
175
|
-
const
|
|
170
|
+
const ref = useRef<HTMLDivElement | null>(null)
|
|
176
171
|
const arrowRef = useRef<HTMLDivElement | null>(null)
|
|
177
172
|
const rootBoundary: RootBoundary = 'viewport'
|
|
178
173
|
|
|
174
|
+
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(
|
|
175
|
+
forwardedRef,
|
|
176
|
+
() => ref.current,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
179
|
const mediaIndex = useMediaIndex()
|
|
180
180
|
const boundaryWidth = constrainSize || preventOverflow ? boundarySize?.width : undefined
|
|
181
181
|
|
|
@@ -208,7 +208,7 @@ export const Popover = memo(
|
|
|
208
208
|
|
|
209
209
|
// Force apply width & max width to floating element
|
|
210
210
|
useEffect(() => {
|
|
211
|
-
const floatingElement =
|
|
211
|
+
const floatingElement = ref.current
|
|
212
212
|
|
|
213
213
|
if (!open || !floatingElement) return
|
|
214
214
|
|
|
@@ -225,7 +225,7 @@ export const Popover = memo(
|
|
|
225
225
|
if (typeof maxWidth === 'number') {
|
|
226
226
|
floatingElement.style.maxWidth = `${maxWidth}px`
|
|
227
227
|
}
|
|
228
|
-
}, [width,
|
|
228
|
+
}, [width, matchReferenceWidth, maxWidth, open])
|
|
229
229
|
|
|
230
230
|
const middleware = useMemo(() => {
|
|
231
231
|
const ret: Middleware[] = []
|
|
@@ -349,10 +349,10 @@ export const Popover = memo(
|
|
|
349
349
|
|
|
350
350
|
const setFloating = useCallback(
|
|
351
351
|
(node: HTMLDivElement | null) => {
|
|
352
|
-
|
|
352
|
+
ref.current = node
|
|
353
353
|
refs.setFloating(node)
|
|
354
354
|
},
|
|
355
|
-
[
|
|
355
|
+
[refs],
|
|
356
356
|
)
|
|
357
357
|
|
|
358
358
|
const setReference = useCallback(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {forwardRef} from 'react'
|
|
1
|
+
import {forwardRef, useImperativeHandle, useRef} from 'react'
|
|
2
2
|
import {styled} from 'styled-components'
|
|
3
|
-
import {
|
|
3
|
+
import {useCustomValidity} from '../../hooks'
|
|
4
4
|
import {radioBaseStyle, inputElementStyle} from './styles'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -23,7 +23,12 @@ export const Radio = forwardRef(function Radio(
|
|
|
23
23
|
forwardedRef: React.ForwardedRef<HTMLInputElement>,
|
|
24
24
|
) {
|
|
25
25
|
const {className, disabled, style, customValidity, readOnly, ...restProps} = props
|
|
26
|
-
const ref =
|
|
26
|
+
const ref = useRef<HTMLInputElement | null>(null)
|
|
27
|
+
|
|
28
|
+
useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(
|
|
29
|
+
forwardedRef,
|
|
30
|
+
() => ref.current,
|
|
31
|
+
)
|
|
27
32
|
|
|
28
33
|
useCustomValidity(ref, customValidity)
|
|
29
34
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {ChevronDownIcon} from '@sanity/icons'
|
|
2
|
-
import {forwardRef} from 'react'
|
|
2
|
+
import {forwardRef, useImperativeHandle, useRef} from 'react'
|
|
3
3
|
import {styled} from 'styled-components'
|
|
4
|
-
import {
|
|
4
|
+
import {useCustomValidity, useArrayProp} from '../../hooks'
|
|
5
5
|
import {Radius} from '../../types'
|
|
6
6
|
import {Box} from '../box'
|
|
7
7
|
import {Text} from '../text'
|
|
@@ -50,7 +50,12 @@ export const Select = forwardRef(function Select(
|
|
|
50
50
|
...restProps
|
|
51
51
|
} = props
|
|
52
52
|
|
|
53
|
-
const ref =
|
|
53
|
+
const ref = useRef<HTMLSelectElement | null>(null)
|
|
54
|
+
|
|
55
|
+
useImperativeHandle<HTMLSelectElement | null, HTMLSelectElement | null>(
|
|
56
|
+
forwardedRef,
|
|
57
|
+
() => ref.current,
|
|
58
|
+
)
|
|
54
59
|
|
|
55
60
|
useCustomValidity(ref, customValidity)
|
|
56
61
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {forwardRef, useEffect} from 'react'
|
|
1
|
+
import {forwardRef, useEffect, useImperativeHandle, useRef} from 'react'
|
|
2
2
|
import {styled} from 'styled-components'
|
|
3
|
-
import {useForwardedRef} from '../../hooks'
|
|
4
3
|
import {
|
|
5
4
|
switchBaseStyles,
|
|
6
5
|
switchRepresentationStyles,
|
|
@@ -34,14 +33,19 @@ export const Switch = forwardRef(function Switch(
|
|
|
34
33
|
forwardedRef: React.ForwardedRef<HTMLInputElement>,
|
|
35
34
|
) {
|
|
36
35
|
const {checked, className, disabled, indeterminate, readOnly, style, ...restProps} = props
|
|
37
|
-
const ref =
|
|
36
|
+
const ref = useRef<HTMLInputElement | null>(null)
|
|
37
|
+
|
|
38
|
+
useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(
|
|
39
|
+
forwardedRef,
|
|
40
|
+
() => ref.current,
|
|
41
|
+
)
|
|
38
42
|
|
|
39
43
|
useEffect(() => {
|
|
40
44
|
if (ref.current) {
|
|
41
45
|
// Set the indeterminate state
|
|
42
46
|
ref.current.indeterminate = indeterminate || false
|
|
43
47
|
}
|
|
44
|
-
}, [indeterminate
|
|
48
|
+
}, [indeterminate])
|
|
45
49
|
|
|
46
50
|
return (
|
|
47
51
|
<Root className={className} data-ui="Switch" style={style}>
|