@sanity/ui 2.3.6-canary.2 → 2.3.6-canary.4

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.3.6-canary.2",
3
+ "version": "2.3.6-canary.4",
4
4
  "keywords": [
5
5
  "sanity",
6
6
  "ui",
@@ -84,7 +84,7 @@
84
84
  "dependencies": {
85
85
  "@floating-ui/react-dom": "^2.1.0",
86
86
  "@sanity/color": "^3.0.6",
87
- "@sanity/icons": "^3.2.0",
87
+ "@sanity/icons": "3.2.1-canary.0",
88
88
  "csstype": "^3.1.3",
89
89
  "framer-motion": "11.0.8",
90
90
  "react-refractor": "^2.2.0"
@@ -200,7 +200,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
200
200
 
201
201
  const listBoxId = `${id}-listbox`
202
202
  const options = Array.isArray(optionsProp) ? optionsProp : EMPTY_ARRAY
203
- const padding = useMemo(() => _getArrayProp(paddingProp), [paddingProp])
203
+ const padding = _getArrayProp(paddingProp)
204
204
  const currentOption = useMemo(
205
205
  () => (value !== null ? options.find((o) => o.value === value) : undefined),
206
206
  [options, value],
@@ -213,44 +213,41 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
213
213
  const activeItemId = activeValue ? `${id}-option-${activeValue}` : undefined
214
214
  const expanded = (query !== null && loading) || (focused && query !== null)
215
215
 
216
- const handleRootBlur = useCallback(
217
- (event: FocusEvent<HTMLInputElement>) => {
218
- setTimeout(() => {
219
- // NOTE: This is a workaround for a bug that may happen in Chrome (clicking the scrollbar
220
- // closes the results in certain situations):
221
- // - Do not handle blur if the mouse is within the popover
222
- if (popoverMouseWithinRef.current) {
223
- return
224
- }
216
+ const handleRootBlur = (event: FocusEvent<HTMLInputElement>) => {
217
+ setTimeout(() => {
218
+ // NOTE: This is a workaround for a bug that may happen in Chrome (clicking the scrollbar
219
+ // closes the results in certain situations):
220
+ // - Do not handle blur if the mouse is within the popover
221
+ if (popoverMouseWithinRef.current) {
222
+ return
223
+ }
225
224
 
226
- const elements: HTMLElement[] = (relatedElements || []).concat(
227
- rootElementRef.current ? [rootElementRef.current] : [],
228
- resultsPopoverElementRef.current ? [resultsPopoverElementRef.current] : [],
229
- )
225
+ const elements: HTMLElement[] = (relatedElements || []).concat(
226
+ rootElementRef.current ? [rootElementRef.current] : [],
227
+ resultsPopoverElementRef.current ? [resultsPopoverElementRef.current] : [],
228
+ )
230
229
 
231
- let focusInside = false
230
+ let focusInside = false
232
231
 
233
- if (document.activeElement) {
234
- for (const e of elements) {
235
- if (e === document.activeElement || e.contains(document.activeElement)) {
236
- focusInside = true
237
- break
238
- }
232
+ if (document.activeElement) {
233
+ for (const e of elements) {
234
+ if (e === document.activeElement || e.contains(document.activeElement)) {
235
+ focusInside = true
236
+ break
239
237
  }
240
238
  }
239
+ }
241
240
 
242
- if (focusInside === false) {
243
- dispatch({type: 'root/blur'})
244
- popoverMouseWithinRef.current = false
245
- if (onQueryChange) onQueryChange(null)
246
- if (onBlur) onBlur(event)
247
- }
248
- }, 0)
249
- },
250
- [onBlur, onQueryChange, relatedElements],
251
- )
241
+ if (focusInside === false) {
242
+ dispatch({type: 'root/blur'})
243
+ popoverMouseWithinRef.current = false
244
+ if (onQueryChange) onQueryChange(null)
245
+ if (onBlur) onBlur(event)
246
+ }
247
+ }, 0)
248
+ }
252
249
 
253
- const handleRootFocus = useCallback((event: FocusEvent<HTMLDivElement>) => {
250
+ const handleRootFocus = (event: FocusEvent<HTMLDivElement>) => {
254
251
  const listBoxElement = listBoxElementRef.current
255
252
  const focusedElement = event.target instanceof HTMLElement ? event.target : null
256
253
  const listFocused = listBoxElement?.contains(focusedElement) || false
@@ -260,7 +257,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
260
257
 
261
258
  dispatch({type: 'root/setListFocused', listFocused})
262
259
  }
263
- }, [])
260
+ }
264
261
 
265
262
  const handleOptionSelect = useCallback(
266
263
  (v: string) => {
@@ -316,13 +316,15 @@ export const Dialog = forwardRef(function Dialog(
316
316
  onFocus,
317
317
  padding: paddingProp = 3,
318
318
  portal: portalProp,
319
- position: positionProp = dialog.position || 'fixed',
319
+ position: _position,
320
320
  scheme,
321
321
  width: widthProp = 0,
322
- zOffset: zOffsetProp = dialog.zOffset || layer.dialog.zOffset,
322
+ zOffset: _zOffset,
323
323
  animate: _animate = false,
324
324
  ...restProps
325
325
  } = props
326
+ const positionProp = _position ?? (dialog.position || 'fixed')
327
+ const zOffsetProp = _zOffset ?? (dialog.zOffset || layer.dialog.zOffset)
326
328
  const prefersReducedMotion = usePrefersReducedMotion()
327
329
  const animate = prefersReducedMotion ? false : _animate
328
330
  const portal = usePortal()
@@ -57,10 +57,12 @@ export const Menu = forwardRef(function Menu(
57
57
  originElement,
58
58
  padding = 1,
59
59
  registerElement,
60
- shouldFocus = (props.focusFirst && 'first') || (props.focusLast && 'last') || null,
60
+ shouldFocus: _shouldFocus,
61
61
  space = 1,
62
62
  ...restProps
63
63
  } = props
64
+ const shouldFocus =
65
+ _shouldFocus ?? ((props.focusFirst && 'first') || (props.focusLast && 'last') || null)
64
66
 
65
67
  const ref = useRef<HTMLDivElement | null>(null)
66
68
 
@@ -53,9 +53,10 @@ export function MenuGroup(
53
53
  onClickOutside,
54
54
  onEscape,
55
55
  onItemClick,
56
- onItemMouseEnter = menu.onMouseEnter,
56
+ onItemMouseEnter: _onItemMouseEnter,
57
57
  registerElement,
58
58
  } = menu
59
+ const onItemMouseEnter = _onItemMouseEnter ?? menu.onMouseEnter
59
60
  const [rootElement, setRootElement] = useState<HTMLButtonElement | HTMLDivElement | null>(null)
60
61
  const [open, setOpen] = useState(false)
61
62
  const shouldFocusRef = useRef<'first' | 'last' | null>(null)
@@ -72,9 +72,11 @@ export const MenuItem = forwardRef(function MenuItem(
72
72
  activeElement,
73
73
  mount,
74
74
  onItemClick,
75
- onItemMouseEnter = menu.onMouseEnter,
76
- onItemMouseLeave = menu.onMouseLeave,
75
+ onItemMouseEnter: _onItemMouseEnter,
76
+ onItemMouseLeave: _onItemMouseLeave,
77
77
  } = menu
78
+ const onItemMouseEnter = _onItemMouseEnter ?? menu.onMouseEnter
79
+ const onItemMouseLeave = _onItemMouseLeave ?? menu.onMouseLeave
78
80
  const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)
79
81
  const active = Boolean(activeElement) && activeElement === rootElement
80
82
  const ref = useRef<HTMLDivElement | null>(null)
@@ -45,8 +45,6 @@ const ToastContainer = styled.div`
45
45
  width: 100%;
46
46
  `
47
47
 
48
- let toastId = 0
49
-
50
48
  /**
51
49
  * @public
52
50
  */
@@ -57,27 +55,7 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
57
55
  const mounted = useMounted()
58
56
  const prefersReducedMotion = usePrefersReducedMotion()
59
57
  const variants = useMemo<Variants>(
60
- () => ({
61
- initial: {
62
- opacity: 0,
63
- [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: 0,
64
- y: 32,
65
- scale: 0.25,
66
- willChange: 'transform',
67
- },
68
- animate: {
69
- opacity: [0, 1, 1],
70
- [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: [0, 0, 1],
71
- y: 0,
72
- scale: 1,
73
- },
74
- exit: {
75
- opacity: [1, 1, 0],
76
- [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: [1, 0, 0],
77
- scale: 0.5,
78
- transition: prefersReducedMotion ? {duration: 0} : {duration: 0.2},
79
- },
80
- }),
58
+ () => getVariants(prefersReducedMotion),
81
59
  [prefersReducedMotion],
82
60
  )
83
61
 
@@ -86,7 +64,7 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
86
64
  // Wrap setState in startTransition to allow React to give input state updates higher priority
87
65
  const setState: typeof _setState = (state) => startTransition(() => _setState(state))
88
66
 
89
- const id = params.id || String(toastId++)
67
+ const id = params.id || crypto.randomUUID()
90
68
  const duration = params.duration || 5000
91
69
 
92
70
  const dismiss = () => {
@@ -188,3 +166,27 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
188
166
  </ToastContext.Provider>
189
167
  )
190
168
  }
169
+
170
+ function getVariants(prefersReducedMotion: boolean) {
171
+ return {
172
+ initial: {
173
+ opacity: 0,
174
+ [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: 0,
175
+ y: 32,
176
+ scale: 0.25,
177
+ willChange: 'transform',
178
+ },
179
+ animate: {
180
+ opacity: [0, 1, 1],
181
+ [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: [0, 0, 1],
182
+ y: 0,
183
+ scale: 1,
184
+ },
185
+ exit: {
186
+ opacity: [1, 1, 0],
187
+ [POPOVER_MOTION_CONTENT_OPACITY_PROPERTY as string]: [1, 0, 0],
188
+ scale: 0.5,
189
+ transition: {duration: prefersReducedMotion ? 0 : 0.2},
190
+ },
191
+ }
192
+ }
@@ -0,0 +1,21 @@
1
+ import {memo} from 'react'
2
+ import {styled} from 'styled-components'
3
+ import {Box, Text} from '../../primitives'
4
+ import {
5
+ treeItemRootStyle,
6
+ treeItemRootColorStyle,
7
+ treeItemBoxStyle,
8
+ TreeItemBoxStyleProps,
9
+ } from './style'
10
+
11
+ export const Root = memo(styled.li(treeItemRootStyle, treeItemRootColorStyle))
12
+
13
+ export const TreeItemBox = styled(Box).attrs({forwardedAs: 'a'})<TreeItemBoxStyleProps>(
14
+ treeItemBoxStyle,
15
+ )
16
+
17
+ export const ToggleArrowText = styled(Text)`
18
+ & > svg {
19
+ transition: transform 100ms;
20
+ }
21
+ `
@@ -1,16 +1,10 @@
1
1
  import {ToggleArrowRightIcon} from '@sanity/icons'
2
2
  import {ThemeFontWeightKey} from '@sanity/ui/theme'
3
3
  import {memo, useCallback, useEffect, useId, useMemo, useRef} from 'react'
4
- import {styled} from 'styled-components'
5
4
  import {Box, BoxProps, Flex, Text} from '../../primitives'
6
- import {
7
- treeItemRootStyle,
8
- treeItemRootColorStyle,
9
- treeItemBoxStyle,
10
- TreeItemBoxStyleProps,
11
- } from './style'
12
5
  import {TreeContext} from './treeContext'
13
6
  import {TreeGroup} from './treeGroup'
7
+ import {Root, ToggleArrowText, TreeItemBox} from './treeItem.styles'
14
8
  import {useTree} from './useTree'
15
9
 
16
10
  /**
@@ -30,16 +24,6 @@ export interface TreeItemProps {
30
24
  weight?: ThemeFontWeightKey
31
25
  }
32
26
 
33
- const Root = memo(styled.li(treeItemRootStyle, treeItemRootColorStyle))
34
-
35
- const TreeItemBox = styled(Box).attrs({forwardedAs: 'a'})<TreeItemBoxStyleProps>(treeItemBoxStyle)
36
-
37
- const ToggleArrowText = styled(Text)`
38
- & > svg {
39
- transition: transform 100ms;
40
- }
41
- `
42
-
43
27
  /**
44
28
  * This API might change. DO NOT USE IN PRODUCTION.
45
29
  * @beta
@@ -70,7 +54,7 @@ export const TreeItem = memo(function TreeItem(
70
54
  const {path, registerItem, setExpanded, setFocusedElement} = tree
71
55
  const _id = useId()
72
56
  const id = idProp || _id
73
- const itemPath = useMemo(() => path.concat([id || '']), [id, path])
57
+ const itemPath = useMemo(() => [...path, id || ''], [id, path])
74
58
  const itemKey = itemPath.join('/')
75
59
  const itemState = tree.state[itemKey]
76
60
  const focused = tree.focusedElement === rootRef.current
@@ -83,7 +67,7 @@ export const TreeItem = memo(function TreeItem(
83
67
 
84
68
  const handleClick = useCallback(
85
69
  (event: React.MouseEvent<HTMLLIElement>) => {
86
- if (onClick) onClick(event)
70
+ onClick?.(event)
87
71
 
88
72
  const target = event.target
89
73
 
@@ -117,32 +101,35 @@ export const TreeItem = memo(function TreeItem(
117
101
  return registerItem(rootRef.current, itemPath.join('/'), expanded, selected)
118
102
  }, [expanded, itemPath, registerItem, selected])
119
103
 
120
- const content = (
121
- <Flex padding={padding}>
122
- <Box
123
- marginRight={space}
124
- style={{
125
- visibility: IconComponent || children ? 'visible' : 'hidden',
126
- pointerEvents: 'none',
127
- }}
128
- >
129
- {IconComponent && (
130
- <Text muted={muted} size={fontSize} weight={weight}>
131
- <IconComponent />
104
+ const content = useMemo(
105
+ () => (
106
+ <Flex padding={padding}>
107
+ <Box
108
+ marginRight={space}
109
+ style={{
110
+ visibility: IconComponent || children ? 'visible' : 'hidden',
111
+ pointerEvents: 'none',
112
+ }}
113
+ >
114
+ {IconComponent && (
115
+ <Text muted={muted} size={fontSize} weight={weight}>
116
+ <IconComponent />
117
+ </Text>
118
+ )}
119
+ {!IconComponent && (
120
+ <ToggleArrowText muted={muted} size={fontSize} weight={weight}>
121
+ <ToggleArrowRightIcon style={{transform: expanded ? 'rotate(90deg)' : undefined}} />
122
+ </ToggleArrowText>
123
+ )}
124
+ </Box>
125
+ <Box flex={1}>
126
+ <Text muted={muted} size={fontSize} textOverflow="ellipsis" weight={weight}>
127
+ {text}
132
128
  </Text>
133
- )}
134
- {!IconComponent && (
135
- <ToggleArrowText muted={muted} size={fontSize} weight={weight}>
136
- <ToggleArrowRightIcon style={{transform: expanded ? 'rotate(90deg)' : undefined}} />
137
- </ToggleArrowText>
138
- )}
139
- </Box>
140
- <Box flex={1}>
141
- <Text muted={muted} size={fontSize} textOverflow="ellipsis" weight={weight}>
142
- {text}
143
- </Text>
144
- </Box>
145
- </Flex>
129
+ </Box>
130
+ </Flex>
131
+ ),
132
+ [IconComponent, children, expanded, fontSize, muted, padding, space, text, weight],
146
133
  )
147
134
 
148
135
  if (href) {
@@ -1,5 +1,5 @@
1
1
  import {ThemeColorAvatarColorKey} from '@sanity/ui/theme'
2
- import {forwardRef, useCallback, useEffect, useId, useMemo, useState} from 'react'
2
+ import {forwardRef, useCallback, useEffect, useId, useState} from 'react'
3
3
  import {isValidElementType} from 'react-is'
4
4
  import {styled} from 'styled-components'
5
5
  import {_getArrayProp} from '../../styles'
@@ -74,7 +74,7 @@ export const Avatar = forwardRef(function Avatar(
74
74
  } = props
75
75
  const {avatar} = useTheme_v2()
76
76
  const as = isValidElementType(asProp) ? asProp : 'div'
77
- const size = useMemo(() => _getArrayProp(sizeProp), [sizeProp])
77
+ const size = _getArrayProp(sizeProp)
78
78
 
79
79
  // @todo: remove this
80
80
  const avatarSize = avatar.sizes[size[0]] || avatar.sizes[0]
@@ -111,17 +111,13 @@ export const Avatar = forwardRef(function Avatar(
111
111
  }
112
112
  }, [onImageLoadError])
113
113
 
114
- const initialsSize = useMemo(
115
- () =>
116
- size.map((s) => {
117
- if (s === 1) return 1
118
- if (s === 2) return 3
119
- if (s === 3) return 5
114
+ const initialsSize = size.map((s) => {
115
+ if (s === 1) return 1
116
+ if (s === 2) return 3
117
+ if (s === 3) return 5
120
118
 
121
- return 0
122
- }),
123
- [size],
124
- )
119
+ return 0
120
+ })
125
121
 
126
122
  return (
127
123
  <Root
@@ -1,5 +1,5 @@
1
1
  import {getTheme_v2} from '@sanity/ui/theme'
2
- import {forwardRef, useMemo} from 'react'
2
+ import {forwardRef} from 'react'
3
3
  import {styled, css} from 'styled-components'
4
4
  import {EMPTY_RECORD} from '../../constants'
5
5
  import {rem, _responsive, ThemeProps, _getArrayProp} from '../../styles'
@@ -66,23 +66,18 @@ export const AvatarCounter = forwardRef(function AvatarCounter(
66
66
  props: AvatarCounterProps,
67
67
  ref: React.Ref<HTMLDivElement>,
68
68
  ) {
69
- const {count, size: sizeProp = 1} = props
70
- const size = useMemo(() => _getArrayProp(sizeProp), [sizeProp])
69
+ const {count, size} = props
70
+ const $size = _getArrayProp(size ?? 1)
71
+ const fontSize = $size.map((s) => {
72
+ if (s === 1) return 1
73
+ if (s === 2) return 3
74
+ if (s === 3) return 5
71
75
 
72
- const fontSize = useMemo(
73
- () =>
74
- size.map((s) => {
75
- if (s === 1) return 1
76
- if (s === 2) return 3
77
- if (s === 3) return 5
78
-
79
- return 0
80
- }),
81
- [size],
82
- )
76
+ return 0
77
+ })
83
78
 
84
79
  return (
85
- <Root $size={size} data-ui="AvatarCounter" ref={ref}>
80
+ <Root $size={$size} data-ui="AvatarCounter" ref={ref}>
86
81
  <Label as="span" size={fontSize} weight="medium">
87
82
  {count}
88
83
  </Label>
@@ -64,10 +64,7 @@ export const AvatarStack = forwardRef(function AvatarStack(
64
64
  size: sizeProp = 1,
65
65
  ...restProps
66
66
  } = props
67
- const children = useMemo<React.ReactElement[]>(
68
- () => Children.toArray(childrenProp).filter(isValidElement),
69
- [childrenProp],
70
- )
67
+ const children: React.ReactElement[] = Children.toArray(childrenProp).filter(isValidElement)
71
68
  const maxLength = Math.max(maxLengthProp, 0)
72
69
  const size = useMemo(() => _getArrayProp(sizeProp), [sizeProp])
73
70
 
@@ -14,7 +14,6 @@ import {AnimatePresence} from 'framer-motion'
14
14
  import {
15
15
  MutableRefObject,
16
16
  RefCallback,
17
- cloneElement,
18
17
  forwardRef,
19
18
  memo,
20
19
  useCallback,
@@ -66,6 +65,7 @@ export interface PopoverProps
66
65
  arrow?: boolean
67
66
  /** @deprecated Use `floatingBoundary` and/or `referenceBoundary` instead */
68
67
  boundaryElement?: HTMLElement | null
68
+ /** @deprecated Use `referenceElement` instead */
69
69
  children?: React.ReactElement
70
70
  /**
71
71
  * When `true`, prevent overflow within the current boundary:
@@ -132,15 +132,14 @@ export const Popover = memo(
132
132
  __unstable_margins: margins = DEFAULT_POPOVER_MARGINS,
133
133
  animate: _animate = false,
134
134
  arrow: arrowProp = false,
135
- boundaryElement = boundaryElementContext.element,
136
- children: childProp,
135
+ boundaryElement: _boundaryElement,
136
+ children,
137
137
  constrainSize = false,
138
138
  content,
139
139
  disabled,
140
- fallbackPlacements = props.fallbackPlacements ??
141
- DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom'],
140
+ fallbackPlacements: _fallbackPlacements,
142
141
  matchReferenceWidth,
143
- floatingBoundary = props.boundaryElement ?? boundaryElementContext.element,
142
+ floatingBoundary: _floatingBoundary,
144
143
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
145
144
  onActivate,
146
145
  open,
@@ -150,23 +149,31 @@ export const Popover = memo(
150
149
  portal,
151
150
  preventOverflow = true,
152
151
  radius: radiusProp = 3,
153
- referenceBoundary = props.boundaryElement ?? boundaryElementContext.element,
152
+ referenceBoundary: _referenceBoundary,
154
153
  referenceElement,
155
154
  scheme,
156
155
  shadow: shadowProp = 3,
157
156
  tone = 'inherit',
158
157
  width: widthProp = 'auto',
159
- zOffset: zOffsetProp = layer.popover.zOffset,
158
+ zOffset: _zOffset,
160
159
  updateRef,
161
160
  ...restProps
162
161
  } = props
162
+ const boundaryElement = _boundaryElement ?? boundaryElementContext.element
163
+ const referenceBoundary =
164
+ _referenceBoundary ?? props.boundaryElement ?? boundaryElementContext.element
165
+ const floatingBoundary =
166
+ _floatingBoundary ?? props.boundaryElement ?? boundaryElementContext.element
167
+ const fallbackPlacements =
168
+ _fallbackPlacements ?? DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom']
169
+ const zOffsetProp = _zOffset ?? layer.popover.zOffset
163
170
  const prefersReducedMotion = usePrefersReducedMotion()
164
171
  const animate = prefersReducedMotion ? false : _animate
165
172
  const boundarySize = useElementSize(boundaryElement)?.border
166
173
  const padding = useMemo(() => _getArrayProp(paddingProp), [paddingProp])
167
174
  const radius = useMemo(() => _getArrayProp(radiusProp), [radiusProp])
168
175
  const shadow = useMemo(() => _getArrayProp(shadowProp), [shadowProp])
169
- const widthArrayProp = useMemo(() => _getArrayProp(widthProp), [widthProp])
176
+ const widthArrayProp = _getArrayProp(widthProp)
170
177
  const zOffset = useMemo(() => _getArrayProp(zOffsetProp), [zOffsetProp])
171
178
  const ref = useRef<HTMLDivElement | null>(null)
172
179
  const arrowRef = useRef<HTMLDivElement | null>(null)
@@ -356,45 +363,15 @@ export const Popover = memo(
356
363
  [refs],
357
364
  )
358
365
 
359
- const setReference = useCallback(
360
- (node: HTMLElement | null) => {
361
- refs.setReference(node)
362
-
363
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
364
- const childRef = (childProp as any)?.ref
365
-
366
- if (typeof childRef === 'function') {
367
- childRef(node)
368
- } else if (childRef) {
369
- childRef.current = node
370
- }
371
- },
372
- [childProp, refs],
373
- )
374
-
375
- const child = useMemo(() => {
376
- if (!childProp || referenceElement) return null
377
-
378
- return cloneElement(childProp, {ref: setReference})
379
- }, [childProp, referenceElement, setReference])
366
+ useImperativeHandle(updateRef, () => update, [update])
380
367
 
381
368
  useEffect(() => {
382
- if (updateRef) {
383
- if (typeof updateRef === 'function') {
384
- updateRef(update)
385
- } else if (updateRef) {
386
- updateRef.current = update
387
- }
388
- }
389
- }, [update, updateRef])
390
-
391
- useEffect(() => {
392
- if (child) return
369
+ if (children) return
393
370
  refs.setReference(referenceElement || null)
394
- }, [referenceElement, refs, child])
371
+ }, [children, referenceElement, refs])
395
372
 
396
373
  if (disabled) {
397
- return childProp || <></>
374
+ return children || <></>
398
375
  }
399
376
 
400
377
  const popover = (
@@ -450,10 +427,30 @@ export const Popover = memo(
450
427
  </ConditionalWrapper>
451
428
 
452
429
  {/* the referred element */}
453
- {child}
430
+ {children && !referenceElement && (
431
+ <div
432
+ ref={(node) => {
433
+ logDeprecatedWarning()
434
+ refs.setReference(node)
435
+ }}
436
+ style={{display: 'contents'}}
437
+ >
438
+ {children}
439
+ </div>
440
+ )}
454
441
  </>
455
442
  )
456
443
  }),
457
444
  )
458
445
 
459
446
  Popover.displayName = 'Popover'
447
+
448
+ let didWarn = false
449
+
450
+ function logDeprecatedWarning() {
451
+ if (!didWarn) {
452
+ // eslint-disable-next-line no-console
453
+ console.warn('Popover: Please use the `referenceElement` prop instead of passing a children.')
454
+ didWarn = true
455
+ }
456
+ }
@@ -105,22 +105,25 @@ export const Tooltip = forwardRef(function Tooltip(
105
105
  const {
106
106
  animate: _animate = false,
107
107
  arrow: arrowProp = false,
108
- boundaryElement = boundaryElementContext?.element,
108
+ boundaryElement: _boundaryElement,
109
109
  children: childProp,
110
110
  content,
111
111
  disabled,
112
- fallbackPlacements: fallbackPlacementsProp = props.fallbackPlacements ??
113
- DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom'],
112
+ fallbackPlacements: _fallbackPlacements,
114
113
  padding = 2,
115
114
  placement: placementProp = 'bottom',
116
115
  portal: portalProp,
117
116
  radius = 2,
118
117
  scheme,
119
118
  shadow = 2,
120
- zOffset = layer.tooltip.zOffset,
119
+ zOffset: _zOffset,
121
120
  delay,
122
121
  ...restProps
123
122
  } = props
123
+ const zOffset = _zOffset ?? layer.tooltip.zOffset
124
+ const fallbackPlacementsProp =
125
+ _fallbackPlacements ?? DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom']
126
+ const boundaryElement = _boundaryElement ?? boundaryElementContext?.element
124
127
  const prefersReducedMotion = usePrefersReducedMotion()
125
128
  const animate = prefersReducedMotion ? false : _animate
126
129
  const fallbackPlacements = useMemo(
@@ -295,7 +298,7 @@ export const Tooltip = forwardRef(function Tooltip(
295
298
  useEffect(() => {
296
299
  if (!showTooltip) return
297
300
 
298
- function handleWindowMouseMove(event: MouseEvent) {
301
+ const handleWindowMouseMove = (event: MouseEvent) => {
299
302
  if (!referenceElement) return
300
303
 
301
304
  const isHoveringReference =