@sanity/ui 3.0.11 → 3.0.12-canary.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 +515 -215
- package/dist/_chunks-cjs/_visual-editing.js.map +1 -1
- package/dist/_chunks-es/_visual-editing.mjs +517 -217
- package/dist/_chunks-es/_visual-editing.mjs.map +1 -1
- package/dist/_visual-editing.d.mts +2 -5
- package/dist/_visual-editing.d.ts +2 -5
- package/dist/index.d.mts +1 -5
- package/dist/index.d.ts +1 -5
- package/dist/index.js +71 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +72 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +26 -40
- package/src/core/components/breadcrumbs/breadcrumbs.tsx +67 -38
- package/src/core/primitives/popover/floating-ui/size.ts +32 -16
- package/src/core/primitives/popover/popover.tsx +171 -139
- package/src/core/primitives/tooltip/tooltip.tsx +70 -42
- package/src/core/utils/virtualList/virtualList.tsx +48 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.12-canary.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"sanity",
|
|
6
6
|
"ui",
|
|
@@ -60,32 +60,6 @@
|
|
|
60
60
|
"exports",
|
|
61
61
|
"src"
|
|
62
62
|
],
|
|
63
|
-
"scripts": {
|
|
64
|
-
"build": "run-s clean pkg:build pkg:check figma:pkg:build",
|
|
65
|
-
"clean": "rimraf .workshop dist",
|
|
66
|
-
"commit": "cz",
|
|
67
|
-
"cypress:dev": "run-p dev cypress:open",
|
|
68
|
-
"cypress:open": "cypress open",
|
|
69
|
-
"cypress:run": "cypress run",
|
|
70
|
-
"dev": "run-p storybook:dev workshop:dev",
|
|
71
|
-
"figma:pkg:build": "cd figma && pnpm build",
|
|
72
|
-
"format": "prettier --write --cache --ignore-unknown .",
|
|
73
|
-
"lint": "eslint --cache .",
|
|
74
|
-
"prepack": "pnpm build",
|
|
75
|
-
"pkg:build": "pkg build --strict",
|
|
76
|
-
"pkg:check": "pkg --strict",
|
|
77
|
-
"prepare": "husky install",
|
|
78
|
-
"release": "semantic-release",
|
|
79
|
-
"storybook:build": "storybook build",
|
|
80
|
-
"storybook:dev": "storybook dev -p 6006",
|
|
81
|
-
"test": "jest",
|
|
82
|
-
"test:browser": "start-server-and-test 'run-s workshop:build workshop:start' http://localhost:1337 'run-s cypress:run'",
|
|
83
|
-
"ts:check": "tsc",
|
|
84
|
-
"watch": "pkg watch --strict",
|
|
85
|
-
"workshop:build": "workshop build",
|
|
86
|
-
"workshop:dev": "workshop dev",
|
|
87
|
-
"workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist"
|
|
88
|
-
},
|
|
89
63
|
"commitlint": {
|
|
90
64
|
"extends": [
|
|
91
65
|
"@commitlint/config-conventional"
|
|
@@ -210,25 +184,37 @@
|
|
|
210
184
|
"react-is": "^18 || >=19.0.0-0",
|
|
211
185
|
"styled-components": "^5.2 || ^6"
|
|
212
186
|
},
|
|
213
|
-
"packageManager": "pnpm@9.15.9",
|
|
214
187
|
"engines": {
|
|
215
188
|
"node": ">=20.19 <22 || >=22.12"
|
|
216
189
|
},
|
|
217
190
|
"publishConfig": {
|
|
218
191
|
"access": "public"
|
|
219
192
|
},
|
|
220
|
-
"pnpm": {
|
|
221
|
-
"overrides": {
|
|
222
|
-
"@types/react": "$@types/react",
|
|
223
|
-
"@types/react-dom": "$@types/react-dom",
|
|
224
|
-
"@types/react-is": "$@types/react-is",
|
|
225
|
-
"conventional-changelog-conventionalcommits": ">= 8.0.0",
|
|
226
|
-
"react": "$react",
|
|
227
|
-
"react-dom": "$react-dom",
|
|
228
|
-
"react-is": "$react-is"
|
|
229
|
-
}
|
|
230
|
-
},
|
|
231
193
|
"esm.sh": {
|
|
232
194
|
"bundle": false
|
|
195
|
+
},
|
|
196
|
+
"scripts": {
|
|
197
|
+
"build": "run-s clean pkg:build pkg:check figma:pkg:build",
|
|
198
|
+
"clean": "rimraf .workshop dist",
|
|
199
|
+
"commit": "cz",
|
|
200
|
+
"cypress:dev": "run-p dev cypress:open",
|
|
201
|
+
"cypress:open": "cypress open",
|
|
202
|
+
"cypress:run": "cypress run",
|
|
203
|
+
"dev": "run-p storybook:dev workshop:dev",
|
|
204
|
+
"figma:pkg:build": "cd figma && pnpm build",
|
|
205
|
+
"format": "prettier --write --cache --ignore-unknown .",
|
|
206
|
+
"lint": "eslint .",
|
|
207
|
+
"pkg:build": "pkg build --strict",
|
|
208
|
+
"pkg:check": "pkg --strict",
|
|
209
|
+
"release": "semantic-release",
|
|
210
|
+
"storybook:build": "storybook build",
|
|
211
|
+
"storybook:dev": "storybook dev -p 6006",
|
|
212
|
+
"test": "jest",
|
|
213
|
+
"test:browser": "start-server-and-test 'run-s workshop:build workshop:start' http://localhost:1337 'run-s cypress:run'",
|
|
214
|
+
"ts:check": "tsc",
|
|
215
|
+
"watch": "pkg watch --strict",
|
|
216
|
+
"workshop:build": "workshop build",
|
|
217
|
+
"workshop:dev": "workshop dev",
|
|
218
|
+
"workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist"
|
|
233
219
|
}
|
|
234
|
-
}
|
|
220
|
+
}
|
|
@@ -42,44 +42,16 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs(
|
|
|
42
42
|
|
|
43
43
|
const rawItems = useMemo(() => Children.toArray(children).filter(isValidElement), [children])
|
|
44
44
|
|
|
45
|
-
const items =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
constrainSize
|
|
56
|
-
content={
|
|
57
|
-
<Stack as="ol" overflow="auto" padding={space} space={space}>
|
|
58
|
-
{rawItems.slice(beforeLength - 1, len - afterLength)}
|
|
59
|
-
</Stack>
|
|
60
|
-
}
|
|
61
|
-
key="button"
|
|
62
|
-
open={open}
|
|
63
|
-
placement="top"
|
|
64
|
-
portal
|
|
65
|
-
ref={popoverElementRef}
|
|
66
|
-
>
|
|
67
|
-
<ExpandButton
|
|
68
|
-
fontSize={1}
|
|
69
|
-
mode="bleed"
|
|
70
|
-
onClick={open ? collapse : expand}
|
|
71
|
-
padding={1}
|
|
72
|
-
ref={expandElementRef}
|
|
73
|
-
selected={open}
|
|
74
|
-
text="…"
|
|
75
|
-
/>
|
|
76
|
-
</Popover>,
|
|
77
|
-
...rawItems.slice(len - afterLength),
|
|
78
|
-
]
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return rawItems
|
|
82
|
-
}, [collapse, expand, maxLength, open, rawItems, space])
|
|
45
|
+
const items = useItems({
|
|
46
|
+
collapse,
|
|
47
|
+
expand,
|
|
48
|
+
expandElementRef,
|
|
49
|
+
maxLength,
|
|
50
|
+
open,
|
|
51
|
+
popoverElementRef,
|
|
52
|
+
rawItems,
|
|
53
|
+
space,
|
|
54
|
+
})
|
|
83
55
|
|
|
84
56
|
return (
|
|
85
57
|
<StyledBreadcrumbs data-ui="Breadcrumbs" {...restProps} ref={ref}>
|
|
@@ -97,3 +69,60 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs(
|
|
|
97
69
|
)
|
|
98
70
|
})
|
|
99
71
|
Breadcrumbs.displayName = 'ForwardRef(Breadcrumbs)'
|
|
72
|
+
|
|
73
|
+
function useItems({
|
|
74
|
+
collapse,
|
|
75
|
+
expand,
|
|
76
|
+
expandElementRef,
|
|
77
|
+
maxLength,
|
|
78
|
+
open,
|
|
79
|
+
popoverElementRef,
|
|
80
|
+
rawItems,
|
|
81
|
+
space,
|
|
82
|
+
}: {
|
|
83
|
+
collapse: () => void
|
|
84
|
+
expand: () => void
|
|
85
|
+
expandElementRef: React.RefObject<HTMLButtonElement | null>
|
|
86
|
+
maxLength: number | undefined
|
|
87
|
+
open: boolean
|
|
88
|
+
popoverElementRef: React.RefObject<HTMLDivElement | null>
|
|
89
|
+
rawItems: React.ReactElement<unknown, string | React.JSXElementConstructor<any>>[]
|
|
90
|
+
space: number[]
|
|
91
|
+
}) {
|
|
92
|
+
const len = rawItems.length
|
|
93
|
+
|
|
94
|
+
if (maxLength && len > maxLength) {
|
|
95
|
+
const beforeLength = Math.ceil(maxLength / 2)
|
|
96
|
+
const afterLength = Math.floor(maxLength / 2)
|
|
97
|
+
|
|
98
|
+
return [
|
|
99
|
+
...rawItems.slice(0, beforeLength - 1),
|
|
100
|
+
<Popover
|
|
101
|
+
constrainSize
|
|
102
|
+
content={
|
|
103
|
+
<Stack as="ol" overflow="auto" padding={space} space={space}>
|
|
104
|
+
{rawItems.slice(beforeLength - 1, len - afterLength)}
|
|
105
|
+
</Stack>
|
|
106
|
+
}
|
|
107
|
+
key="button"
|
|
108
|
+
open={open}
|
|
109
|
+
placement="top"
|
|
110
|
+
portal
|
|
111
|
+
ref={popoverElementRef}
|
|
112
|
+
>
|
|
113
|
+
<ExpandButton
|
|
114
|
+
fontSize={1}
|
|
115
|
+
mode="bleed"
|
|
116
|
+
onClick={open ? collapse : expand}
|
|
117
|
+
padding={1}
|
|
118
|
+
ref={expandElementRef}
|
|
119
|
+
selected={open}
|
|
120
|
+
text="…"
|
|
121
|
+
/>
|
|
122
|
+
</Popover>,
|
|
123
|
+
...rawItems.slice(len - afterLength),
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return rawItems
|
|
128
|
+
}
|
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
import {detectOverflow,
|
|
1
|
+
import {detectOverflow, Middleware} from '@floating-ui/react-dom'
|
|
2
2
|
|
|
3
3
|
import {PopoverMargins} from '../../../types'
|
|
4
4
|
|
|
5
|
-
export interface SizeMiddlewareApplyOptions {
|
|
6
|
-
availableWidth: number
|
|
7
|
-
availableHeight: number
|
|
8
|
-
elements: Elements
|
|
9
|
-
referenceWidth: number
|
|
10
|
-
}
|
|
11
|
-
|
|
12
5
|
export function size(options: {
|
|
13
|
-
apply: (args: SizeMiddlewareApplyOptions) => void
|
|
14
6
|
boundaryElement?: HTMLElement | null
|
|
15
7
|
constrainSize: boolean
|
|
16
8
|
margins: PopoverMargins
|
|
17
9
|
matchReferenceWidth?: boolean
|
|
10
|
+
maxWidthRef: React.RefObject<number | undefined>
|
|
18
11
|
padding?: number
|
|
12
|
+
referenceWidthRef: React.RefObject<number | undefined>
|
|
13
|
+
setReferenceWidth: (referenceWidth: number) => void
|
|
14
|
+
widthRef: React.RefObject<number | undefined>
|
|
19
15
|
}): Middleware {
|
|
20
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
constrainSize,
|
|
18
|
+
margins,
|
|
19
|
+
matchReferenceWidth,
|
|
20
|
+
maxWidthRef,
|
|
21
|
+
padding = 0,
|
|
22
|
+
referenceWidthRef,
|
|
23
|
+
setReferenceWidth,
|
|
24
|
+
widthRef,
|
|
25
|
+
} = options
|
|
21
26
|
|
|
22
27
|
return {
|
|
23
28
|
name: '@sanity/ui/size',
|
|
@@ -61,12 +66,23 @@ export function size(options: {
|
|
|
61
66
|
|
|
62
67
|
// IMPORTANT – APPLY ELEMENT STYLES HERE
|
|
63
68
|
// Elements need to be resized BEFORE the `platform.getDimensions` call below
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
const availableWidth = maxWidth - margins[1] - margins[3]
|
|
70
|
+
const availableHeight = maxHeight - margins[0] - margins[2]
|
|
71
|
+
const referenceWidth = reference.width - margins[1] - margins[3]
|
|
72
|
+
referenceWidthRef.current = referenceWidth
|
|
73
|
+
setReferenceWidth(referenceWidth)
|
|
74
|
+
|
|
75
|
+
if (matchReferenceWidth) {
|
|
76
|
+
elements.floating.style.width = `${referenceWidth}px`
|
|
77
|
+
} else if (widthRef.current !== undefined) {
|
|
78
|
+
elements.floating.style.width = `${widthRef.current}px`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (constrainSize) {
|
|
82
|
+
elements.floating.style.maxWidth = `${Math.min(availableWidth, maxWidthRef.current ?? Infinity)}px`
|
|
83
|
+
|
|
84
|
+
elements.floating.style.maxHeight = `${availableHeight}px`
|
|
85
|
+
}
|
|
70
86
|
|
|
71
87
|
const nextDimensions = await platform.getDimensions(elements.floating)
|
|
72
88
|
|
|
@@ -16,13 +16,13 @@ import {
|
|
|
16
16
|
cloneElement,
|
|
17
17
|
forwardRef,
|
|
18
18
|
memo,
|
|
19
|
-
|
|
20
|
-
RefCallback,
|
|
19
|
+
type Ref,
|
|
21
20
|
useCallback,
|
|
22
21
|
useEffect,
|
|
23
22
|
useImperativeHandle,
|
|
24
23
|
useMemo,
|
|
25
24
|
useRef,
|
|
25
|
+
useState,
|
|
26
26
|
} from 'react'
|
|
27
27
|
|
|
28
28
|
import {useArrayProp, useElementSize, useMediaIndex, usePrefersReducedMotion} from '../../hooks'
|
|
@@ -119,9 +119,7 @@ export interface PopoverProps
|
|
|
119
119
|
scheme?: ThemeColorSchemeKey
|
|
120
120
|
tone?: CardTone
|
|
121
121
|
/** @beta */
|
|
122
|
-
updateRef?:
|
|
123
|
-
| MutableRefObject<PopoverUpdateCallback | undefined>
|
|
124
|
-
| RefCallback<PopoverUpdateCallback | undefined>
|
|
122
|
+
updateRef?: Ref<PopoverUpdateCallback | undefined>
|
|
125
123
|
width?: PopoverWidth | PopoverWidth[]
|
|
126
124
|
}
|
|
127
125
|
|
|
@@ -149,15 +147,14 @@ export const Popover = memo(
|
|
|
149
147
|
__unstable_margins: margins = DEFAULT_POPOVER_MARGINS,
|
|
150
148
|
animate: _animate = false,
|
|
151
149
|
arrow: arrowProp = false,
|
|
152
|
-
boundaryElement
|
|
150
|
+
boundaryElement: _boundaryElement,
|
|
153
151
|
children: childProp,
|
|
154
152
|
constrainSize = false,
|
|
155
153
|
content,
|
|
156
154
|
disabled,
|
|
157
|
-
fallbackPlacements
|
|
158
|
-
DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom'],
|
|
155
|
+
fallbackPlacements: _fallbackPlacements,
|
|
159
156
|
matchReferenceWidth,
|
|
160
|
-
floatingBoundary
|
|
157
|
+
floatingBoundary: _floatingBoundary,
|
|
161
158
|
modal,
|
|
162
159
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
163
160
|
onActivate,
|
|
@@ -169,16 +166,24 @@ export const Popover = memo(
|
|
|
169
166
|
portal,
|
|
170
167
|
preventOverflow = true,
|
|
171
168
|
radius: radiusProp = 3,
|
|
172
|
-
referenceBoundary
|
|
169
|
+
referenceBoundary: _referenceBoundary,
|
|
173
170
|
referenceElement,
|
|
174
171
|
scheme,
|
|
175
172
|
shadow: shadowProp = 3,
|
|
176
173
|
tone = 'inherit',
|
|
177
174
|
width: widthProp = 'auto',
|
|
178
|
-
zOffset:
|
|
175
|
+
zOffset: _zOffsetProp,
|
|
179
176
|
updateRef,
|
|
180
177
|
...restProps
|
|
181
178
|
} = props
|
|
179
|
+
const boundaryElement = _boundaryElement ?? boundaryElementContext?.element
|
|
180
|
+
const fallbackPlacements =
|
|
181
|
+
_fallbackPlacements ?? DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom']
|
|
182
|
+
const floatingBoundary =
|
|
183
|
+
_floatingBoundary ?? props.boundaryElement ?? boundaryElementContext.element
|
|
184
|
+
const referenceBoundary =
|
|
185
|
+
_referenceBoundary ?? props.boundaryElement ?? boundaryElementContext.element
|
|
186
|
+
const zOffsetProp = _zOffsetProp ?? layer.popover.zOffset
|
|
182
187
|
const prefersReducedMotion = usePrefersReducedMotion()
|
|
183
188
|
const animate = prefersReducedMotion ? false : _animate
|
|
184
189
|
const boundarySize = useElementSize(boundaryElement)?.border
|
|
@@ -247,117 +252,26 @@ export const Popover = memo(
|
|
|
247
252
|
}
|
|
248
253
|
}, [width, matchReferenceWidth, maxWidth, open])
|
|
249
254
|
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
// Flip the floating element when leaving the boundary box
|
|
254
|
-
if (constrainSize || preventOverflow) {
|
|
255
|
-
if (placementStrategy === 'autoPlacement') {
|
|
256
|
-
ret.push(
|
|
257
|
-
autoPlacement({
|
|
258
|
-
allowedPlacements: [placementProp].concat(fallbackPlacements),
|
|
259
|
-
}),
|
|
260
|
-
)
|
|
261
|
-
} else {
|
|
262
|
-
ret.push(
|
|
263
|
-
flip({
|
|
264
|
-
boundary: floatingBoundary || undefined,
|
|
265
|
-
fallbackPlacements,
|
|
266
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
267
|
-
rootBoundary,
|
|
268
|
-
}),
|
|
269
|
-
)
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Define distance between reference and floating element
|
|
274
|
-
ret.push(offset({mainAxis: DEFAULT_POPOVER_DISTANCE}))
|
|
275
|
-
|
|
276
|
-
// Track sizes
|
|
277
|
-
if (constrainSize || matchReferenceWidth) {
|
|
278
|
-
ret.push(
|
|
279
|
-
size({
|
|
280
|
-
apply({availableWidth, availableHeight, elements, referenceWidth}) {
|
|
281
|
-
// not fresh, so use refs
|
|
282
|
-
|
|
283
|
-
referenceWidthRef.current = referenceWidth
|
|
284
|
-
|
|
285
|
-
const _currentWidth = widthRef.current
|
|
286
|
-
const _maxWidth = maxWidthRef.current
|
|
287
|
-
|
|
288
|
-
if (matchReferenceWidth) {
|
|
289
|
-
elements.floating.style.width = `${referenceWidth}px`
|
|
290
|
-
} else if (_currentWidth !== undefined) {
|
|
291
|
-
elements.floating.style.width = `${_currentWidth}px`
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (constrainSize) {
|
|
295
|
-
elements.floating.style.maxWidth = `${Math.min(
|
|
296
|
-
availableWidth,
|
|
297
|
-
_maxWidth ?? Infinity,
|
|
298
|
-
)}px`
|
|
299
|
-
|
|
300
|
-
elements.floating.style.maxHeight = `${availableHeight}px`
|
|
301
|
-
}
|
|
302
|
-
},
|
|
303
|
-
boundaryElement: floatingBoundary || undefined,
|
|
304
|
-
constrainSize,
|
|
305
|
-
margins,
|
|
306
|
-
matchReferenceWidth,
|
|
307
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
308
|
-
}),
|
|
309
|
-
)
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Shift the popover so its sits within the boundary element
|
|
313
|
-
if (preventOverflow) {
|
|
314
|
-
ret.push(
|
|
315
|
-
shift({
|
|
316
|
-
boundary: floatingBoundary || undefined,
|
|
317
|
-
rootBoundary,
|
|
318
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
319
|
-
}),
|
|
320
|
-
)
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Place arrow
|
|
324
|
-
if (arrowProp) {
|
|
325
|
-
ret.push(
|
|
326
|
-
arrow({
|
|
327
|
-
element: arrowRef,
|
|
328
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
329
|
-
}),
|
|
330
|
-
)
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Determine the origin to scale from.
|
|
334
|
-
// Must be placed after `@sanity/ui/size` and `shift` middleware.
|
|
335
|
-
if (animate) {
|
|
336
|
-
ret.push(origin)
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
ret.push(
|
|
340
|
-
hide({
|
|
341
|
-
boundary: referenceBoundary || undefined,
|
|
342
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
343
|
-
strategy: 'referenceHidden',
|
|
344
|
-
}),
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
return ret
|
|
348
|
-
}, [
|
|
255
|
+
const [referenceWidth, setReferenceWidth] = useState<number | undefined>(undefined)
|
|
256
|
+
const middleware = useMiddleware({
|
|
349
257
|
animate,
|
|
350
258
|
arrowProp,
|
|
259
|
+
arrowRef,
|
|
351
260
|
constrainSize,
|
|
352
261
|
fallbackPlacements,
|
|
353
|
-
placementProp,
|
|
354
|
-
placementStrategy,
|
|
355
262
|
floatingBoundary,
|
|
356
263
|
margins,
|
|
357
264
|
matchReferenceWidth,
|
|
265
|
+
maxWidthRef,
|
|
266
|
+
placementProp,
|
|
267
|
+
placementStrategy,
|
|
358
268
|
preventOverflow,
|
|
359
269
|
referenceBoundary,
|
|
360
|
-
|
|
270
|
+
referenceWidthRef,
|
|
271
|
+
rootBoundary,
|
|
272
|
+
setReferenceWidth,
|
|
273
|
+
widthRef,
|
|
274
|
+
})
|
|
361
275
|
|
|
362
276
|
const {x, y, middlewareData, placement, refs, strategy, update} = useFloating({
|
|
363
277
|
middleware,
|
|
@@ -390,20 +304,9 @@ export const Popover = memo(
|
|
|
390
304
|
[refs],
|
|
391
305
|
)
|
|
392
306
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
const childRef = getElementRef(childProp as any)
|
|
398
|
-
|
|
399
|
-
if (typeof childRef === 'function') {
|
|
400
|
-
childRef(node)
|
|
401
|
-
} else if (childRef) {
|
|
402
|
-
childRef.current = node
|
|
403
|
-
}
|
|
404
|
-
},
|
|
405
|
-
[childProp, refs],
|
|
406
|
-
)
|
|
307
|
+
// If there's a child then we need to set the reference element to the cloned child ref
|
|
308
|
+
// and if child changes we make sure to update or remove the reference element.
|
|
309
|
+
useImperativeHandle(childProp ? getElementRef(childProp) : null, () => refs.reference.current)
|
|
407
310
|
|
|
408
311
|
const child = useMemo(() => {
|
|
409
312
|
// If a reference element is defined, we don't need to clone the child
|
|
@@ -411,18 +314,10 @@ export const Popover = memo(
|
|
|
411
314
|
|
|
412
315
|
if (!childProp) return null
|
|
413
316
|
|
|
414
|
-
return cloneElement(childProp, {ref: setReference})
|
|
415
|
-
}, [childProp, referenceElement, setReference])
|
|
317
|
+
return cloneElement(childProp, {ref: refs.setReference})
|
|
318
|
+
}, [childProp, referenceElement, refs.setReference])
|
|
416
319
|
|
|
417
|
-
|
|
418
|
-
if (updateRef) {
|
|
419
|
-
if (typeof updateRef === 'function') {
|
|
420
|
-
updateRef(update)
|
|
421
|
-
} else if (updateRef) {
|
|
422
|
-
updateRef.current = update
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}, [update, updateRef])
|
|
320
|
+
useImperativeHandle(updateRef, () => update, [update])
|
|
426
321
|
|
|
427
322
|
if (disabled) {
|
|
428
323
|
return childProp || <></>
|
|
@@ -453,7 +348,7 @@ export const Popover = memo(
|
|
|
453
348
|
originY={originY}
|
|
454
349
|
strategy={strategy}
|
|
455
350
|
tone={tone}
|
|
456
|
-
width={matchReferenceWidth ?
|
|
351
|
+
width={matchReferenceWidth ? referenceWidth : width}
|
|
457
352
|
x={x}
|
|
458
353
|
y={y}
|
|
459
354
|
>
|
|
@@ -482,3 +377,140 @@ export const Popover = memo(
|
|
|
482
377
|
}),
|
|
483
378
|
)
|
|
484
379
|
Popover.displayName = 'Memo(ForwardRef(Popover))'
|
|
380
|
+
|
|
381
|
+
function useMiddleware({
|
|
382
|
+
animate,
|
|
383
|
+
arrowProp,
|
|
384
|
+
arrowRef,
|
|
385
|
+
constrainSize,
|
|
386
|
+
fallbackPlacements,
|
|
387
|
+
floatingBoundary,
|
|
388
|
+
margins,
|
|
389
|
+
matchReferenceWidth,
|
|
390
|
+
maxWidthRef,
|
|
391
|
+
placementProp,
|
|
392
|
+
placementStrategy,
|
|
393
|
+
preventOverflow,
|
|
394
|
+
referenceBoundary,
|
|
395
|
+
referenceWidthRef,
|
|
396
|
+
rootBoundary,
|
|
397
|
+
setReferenceWidth,
|
|
398
|
+
widthRef,
|
|
399
|
+
}: {
|
|
400
|
+
animate: boolean
|
|
401
|
+
arrowProp: boolean
|
|
402
|
+
arrowRef: React.RefObject<HTMLDivElement | null>
|
|
403
|
+
constrainSize: boolean
|
|
404
|
+
fallbackPlacements: Placement[]
|
|
405
|
+
floatingBoundary: HTMLElement | null
|
|
406
|
+
margins: PopoverMargins
|
|
407
|
+
matchReferenceWidth: boolean | undefined
|
|
408
|
+
maxWidthRef: React.RefObject<number | undefined>
|
|
409
|
+
placementProp: Placement
|
|
410
|
+
placementStrategy: 'flip' | 'autoPlacement'
|
|
411
|
+
preventOverflow: boolean
|
|
412
|
+
referenceBoundary: HTMLElement | null
|
|
413
|
+
referenceWidthRef: React.RefObject<number | undefined>
|
|
414
|
+
rootBoundary: RootBoundary
|
|
415
|
+
setReferenceWidth: (referenceWidth: number) => void
|
|
416
|
+
widthRef: React.RefObject<number | undefined>
|
|
417
|
+
}) {
|
|
418
|
+
return useMemo(() => {
|
|
419
|
+
const ret: Middleware[] = []
|
|
420
|
+
|
|
421
|
+
// Flip the floating element when leaving the boundary box
|
|
422
|
+
if (constrainSize || preventOverflow) {
|
|
423
|
+
if (placementStrategy === 'autoPlacement') {
|
|
424
|
+
ret.push(
|
|
425
|
+
autoPlacement({
|
|
426
|
+
allowedPlacements: [placementProp].concat(fallbackPlacements),
|
|
427
|
+
}),
|
|
428
|
+
)
|
|
429
|
+
} else {
|
|
430
|
+
ret.push(
|
|
431
|
+
flip({
|
|
432
|
+
boundary: floatingBoundary || undefined,
|
|
433
|
+
fallbackPlacements,
|
|
434
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
435
|
+
rootBoundary,
|
|
436
|
+
}),
|
|
437
|
+
)
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Define distance between reference and floating element
|
|
442
|
+
ret.push(offset({mainAxis: DEFAULT_POPOVER_DISTANCE}))
|
|
443
|
+
|
|
444
|
+
// Track sizes
|
|
445
|
+
if (constrainSize || matchReferenceWidth) {
|
|
446
|
+
ret.push(
|
|
447
|
+
size({
|
|
448
|
+
boundaryElement: floatingBoundary || undefined,
|
|
449
|
+
constrainSize,
|
|
450
|
+
margins,
|
|
451
|
+
matchReferenceWidth,
|
|
452
|
+
maxWidthRef,
|
|
453
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
454
|
+
referenceWidthRef,
|
|
455
|
+
setReferenceWidth,
|
|
456
|
+
widthRef,
|
|
457
|
+
}),
|
|
458
|
+
)
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Shift the popover so its sits within the boundary element
|
|
462
|
+
if (preventOverflow) {
|
|
463
|
+
ret.push(
|
|
464
|
+
shift({
|
|
465
|
+
boundary: floatingBoundary || undefined,
|
|
466
|
+
rootBoundary,
|
|
467
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
468
|
+
}),
|
|
469
|
+
)
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Place arrow
|
|
473
|
+
if (arrowProp) {
|
|
474
|
+
ret.push(
|
|
475
|
+
arrow({
|
|
476
|
+
element: arrowRef,
|
|
477
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
478
|
+
}),
|
|
479
|
+
)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Determine the origin to scale from.
|
|
483
|
+
// Must be placed after `@sanity/ui/size` and `shift` middleware.
|
|
484
|
+
if (animate) {
|
|
485
|
+
ret.push(origin)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
ret.push(
|
|
489
|
+
hide({
|
|
490
|
+
boundary: referenceBoundary || undefined,
|
|
491
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
492
|
+
strategy: 'referenceHidden',
|
|
493
|
+
}),
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
return ret
|
|
497
|
+
}, [
|
|
498
|
+
animate,
|
|
499
|
+
arrowProp,
|
|
500
|
+
arrowRef,
|
|
501
|
+
constrainSize,
|
|
502
|
+
fallbackPlacements,
|
|
503
|
+
floatingBoundary,
|
|
504
|
+
margins,
|
|
505
|
+
matchReferenceWidth,
|
|
506
|
+
maxWidthRef,
|
|
507
|
+
placementProp,
|
|
508
|
+
placementStrategy,
|
|
509
|
+
preventOverflow,
|
|
510
|
+
referenceBoundary,
|
|
511
|
+
referenceWidthRef,
|
|
512
|
+
rootBoundary,
|
|
513
|
+
setReferenceWidth,
|
|
514
|
+
widthRef,
|
|
515
|
+
])
|
|
516
|
+
}
|