@sanity/ui 2.2.0 → 2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ui",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "keywords": [
5
5
  "sanity",
6
6
  "ui",
@@ -106,22 +106,22 @@
106
106
  "dependencies": {
107
107
  "@floating-ui/react-dom": "^2.1.0",
108
108
  "@sanity/color": "^3.0.6",
109
- "@sanity/icons": "^3.0.0",
109
+ "@sanity/icons": "^3.2.0",
110
110
  "csstype": "^3.1.3",
111
111
  "framer-motion": "11.0.8",
112
112
  "react-refractor": "^2.2.0"
113
113
  },
114
114
  "devDependencies": {
115
- "@babel/core": "^7.24.6",
116
- "@babel/preset-env": "^7.24.6",
117
- "@babel/preset-react": "^7.24.6",
118
- "@babel/preset-typescript": "^7.24.6",
115
+ "@babel/core": "^7.24.7",
116
+ "@babel/preset-env": "^7.24.7",
117
+ "@babel/preset-react": "^7.24.7",
118
+ "@babel/preset-typescript": "^7.24.7",
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.18",
123
- "@sanity/semantic-release-preset": "^4.1.7",
124
- "@sanity/ui-workshop": "^2.0.13",
122
+ "@sanity/pkg-utils": "^6.9.1",
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": "^15.0.7",
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,10 +147,10 @@
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.11.0",
151
- "@typescript-eslint/parser": "^7.11.0",
150
+ "@typescript-eslint/eslint-plugin": "^7.12.0",
151
+ "@typescript-eslint/parser": "^7.12.0",
152
152
  "commitizen": "^4.3.0",
153
- "cypress": "^13.10.0",
153
+ "cypress": "^13.11.0",
154
154
  "cypress-real-events": "^1.12.0",
155
155
  "cz-conventional-changelog": "^3.3.0",
156
156
  "eslint": "^8.57.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-c8b3f72-20240517",
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",
@@ -171,15 +171,15 @@
171
171
  "lint-staged": "^14.0.1",
172
172
  "module-alias": "^2.2.3",
173
173
  "npm-run-all2": "^5.0.2",
174
- "prettier": "^3.3.0",
174
+ "prettier": "^3.3.1",
175
175
  "prettier-plugin-packagejson": "^2.5.0",
176
176
  "react": "^18.3.1",
177
177
  "react-dom": "^18.3.1",
178
178
  "react-is": "^18.3.1",
179
179
  "refractor": "^4.8.1",
180
180
  "rimraf": "^5.0.5",
181
- "semantic-release": "^23.1.1",
182
- "start-server-and-test": "^2.0.3",
181
+ "semantic-release": "^24.0.0",
182
+ "start-server-and-test": "^2.0.4",
183
183
  "storybook": "^8.0.8",
184
184
  "styled-components": "^6.1.11",
185
185
  "tsconfig-paths": "^4.2.0",
@@ -193,7 +193,7 @@
193
193
  "react-is": "^18",
194
194
  "styled-components": "^5.2 || ^6"
195
195
  },
196
- "packageManager": "pnpm@9.1.3",
196
+ "packageManager": "pnpm@9.2.0",
197
197
  "engines": {
198
198
  "node": ">=14.0.0"
199
199
  },
@@ -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, useForwardedRef} from '../../hooks'
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
- ref: Ref<HTMLInputElement>,
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
- const forwardedRef = useForwardedRef(ref)
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={setRef}
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
- ref: React.ForwardedRef<HTMLDivElement>,
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 forwardedRef = useForwardedRef(ref)
172
+ const ref = useRef<HTMLDivElement | null>(null)
179
173
  const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)
180
- const localContentRef = useRef<HTMLDivElement | null>(null)
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 (forwardedRef.current) {
192
- focusFirstDescendant(forwardedRef.current)
191
+ if (ref.current) {
192
+ focusFirstDescendant(ref.current)
193
193
  }
194
- }, [autoFocus, forwardedRef])
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: HTMLDivElement | null) => {
239
- setRootElement(el)
240
- forwardedRef.current = el
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={setContentRef} tabIndex={-1}>
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, useForwardedRef, useGlobalKeyDown} from '../../hooks'
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
- ref: React.ForwardedRef<HTMLDivElement>,
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 forwardedRef = useForwardedRef(ref)
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
- forwardedRef.current = el
85
+ ref.current = el
84
86
  },
85
- [forwardedRef, setRootElement],
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, useForwardedRef} from '../../hooks'
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
- useEffect(() => mount(rootElement, selectedProp), [mount, rootElement, selectedProp])
83
+ useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
81
84
 
82
- const ref = useForwardedRef(forwardedRef)
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
- (el: HTMLDivElement | null) => {
110
- ref.current = el
111
- setRootElement(el)
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 elementRef = useRef<HTMLButtonElement | null>(null)
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 (elementRef.current) elementRef.current.focus()
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={setRef}
91
+ ref={ref}
95
92
  role="tab"
96
93
  selected={selected}
97
94
  tabIndex={selected ? 0 : -1}
@@ -1,5 +1,13 @@
1
- import {forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState} from 'react'
2
- import {useForwardedRef} from '../../hooks'
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
- ref: React.ForwardedRef<HTMLDivElement>,
32
+ forwardedRef: React.ForwardedRef<HTMLDivElement>,
25
33
  ): React.ReactElement {
26
34
  const {children, space = 1, onFocus, ...restProps} = props
27
- const forwardedRef = useForwardedRef(ref)
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 (!forwardedRef.current) return
210
+ if (!ref.current) return
198
211
  const _itemElements = Array.from(
199
- forwardedRef.current.querySelectorAll('[data-ui="TreeItem"]'),
212
+ ref.current.querySelectorAll('[data-ui="TreeItem"]'),
200
213
  ) as HTMLElement[]
201
214
 
202
215
  setItemElements(_itemElements)
203
- }, [children, forwardedRef])
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={forwardedRef}
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
- useIsomorphicEffect(() => {
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
  }
@@ -2,5 +2,6 @@ import {useEffect, useLayoutEffect} from 'react'
2
2
 
3
3
  /**
4
4
  * @beta
5
+ * @deprecated use `useLayoutEffect` instead, or `useEffect` if possible
5
6
  */
6
7
  export const useIsomorphicEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect
@@ -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 {useForwardedRef, useCustomValidity} from '../../hooks'
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 = useForwardedRef(forwardedRef)
37
+ const ref = useRef<HTMLInputElement | null>(null)
38
38
 
39
- useCustomValidity(ref, customValidity)
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, ref])
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
- ref: React.ForwardedRef<HTMLDivElement>,
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 forwardedRef = useForwardedRef(ref)
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 = forwardedRef.current
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, forwardedRef, matchReferenceWidth, maxWidth, open])
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
- forwardedRef.current = node
352
+ ref.current = node
353
353
  refs.setFloating(node)
354
354
  },
355
- [forwardedRef, refs],
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 {useForwardedRef, useCustomValidity} from '../../hooks'
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 = useForwardedRef(forwardedRef)
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