@sanity/ui 1.5.0 → 1.7.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.ts +24 -9
- package/dist/index.esm.js +185 -120
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +184 -119
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/components/tree/treeItem.tsx +7 -1
- package/src/primitives/popover/__workshop__/AlignedStory.tsx +1 -0
- package/src/primitives/popover/__workshop__/SidePanelStory.tsx +86 -0
- package/src/primitives/popover/__workshop__/TestStory.tsx +30 -18
- package/src/primitives/popover/__workshop__/index.ts +5 -0
- package/src/primitives/popover/helpers.ts +32 -0
- package/src/primitives/popover/index.ts +1 -0
- package/src/primitives/popover/popover.tsx +125 -51
- package/src/primitives/popover/popoverCard.tsx +21 -50
- package/src/primitives/popover/types.ts +6 -0
- package/src/primitives/tooltip/tooltip.tsx +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"source": "./src/index.ts",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@floating-ui/react-dom": "
|
|
52
|
+
"@floating-ui/react-dom": "2.0.0",
|
|
53
53
|
"@sanity/color": "^2.2.5",
|
|
54
54
|
"@sanity/icons": "^2.3.1",
|
|
55
55
|
"csstype": "^3.1.2",
|
|
@@ -57,10 +57,10 @@
|
|
|
57
57
|
"react-refractor": "^2.1.7"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@babel/core": "^7.22.
|
|
61
|
-
"@babel/preset-env": "^7.22.
|
|
62
|
-
"@babel/preset-react": "^7.22.
|
|
63
|
-
"@babel/preset-typescript": "^7.
|
|
60
|
+
"@babel/core": "^7.22.5",
|
|
61
|
+
"@babel/preset-env": "^7.22.5",
|
|
62
|
+
"@babel/preset-react": "^7.22.5",
|
|
63
|
+
"@babel/preset-typescript": "^7.22.5",
|
|
64
64
|
"@commitlint/cli": "^17.6.5",
|
|
65
65
|
"@commitlint/config-conventional": "^17.6.5",
|
|
66
66
|
"@juggle/resize-observer": "^3.4.0",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@testing-library/react": "^14.0.0",
|
|
73
73
|
"@types/jest": "^29.5.2",
|
|
74
74
|
"@types/jest-axe": "^3.5.5",
|
|
75
|
-
"@types/node": "^
|
|
75
|
+
"@types/node": "^20.2.5",
|
|
76
76
|
"@types/react": "^18.2.9",
|
|
77
77
|
"@types/react-dom": "^18.2.4",
|
|
78
78
|
"@types/react-is": "^18.2.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {ToggleArrowRightIcon} from '@sanity/icons'
|
|
2
2
|
import {createElement, memo, useCallback, useEffect, useId, useMemo, useRef} from 'react'
|
|
3
3
|
import styled from 'styled-components'
|
|
4
|
-
import {Box, Flex, Text} from '../../primitives'
|
|
4
|
+
import {Box, BoxProps, Flex, Text} from '../../primitives'
|
|
5
5
|
import {ThemeFontWeightKey} from '../../theme'
|
|
6
6
|
import {
|
|
7
7
|
treeItemRootStyle,
|
|
@@ -20,6 +20,10 @@ export interface TreeItemProps {
|
|
|
20
20
|
expanded?: boolean
|
|
21
21
|
fontSize?: number | number[]
|
|
22
22
|
icon?: React.ElementType
|
|
23
|
+
/**
|
|
24
|
+
* Allows passing a custom element type to the link component
|
|
25
|
+
*/
|
|
26
|
+
linkAs?: BoxProps['as']
|
|
23
27
|
padding?: number | number[]
|
|
24
28
|
space?: number | number[]
|
|
25
29
|
text?: React.ReactNode
|
|
@@ -50,6 +54,7 @@ export const TreeItem = memo(function TreeItem(
|
|
|
50
54
|
href,
|
|
51
55
|
icon,
|
|
52
56
|
id: idProp,
|
|
57
|
+
linkAs,
|
|
53
58
|
muted,
|
|
54
59
|
onClick,
|
|
55
60
|
padding = 3,
|
|
@@ -152,6 +157,7 @@ export const TreeItem = memo(function TreeItem(
|
|
|
152
157
|
<TreeItemBox
|
|
153
158
|
$level={tree.level}
|
|
154
159
|
aria-expanded={expanded}
|
|
160
|
+
as={linkAs}
|
|
155
161
|
data-ui="TreeItem__box"
|
|
156
162
|
href={href}
|
|
157
163
|
ref={treeitemRef}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {useSelect} from '@sanity/ui-workshop'
|
|
2
|
+
import {useCallback, useEffect, useRef, useState} from 'react'
|
|
3
|
+
import {BoundaryElementProvider} from '../../../utils'
|
|
4
|
+
import {Box} from '../../box'
|
|
5
|
+
import {Card} from '../../card'
|
|
6
|
+
import {Flex} from '../../flex'
|
|
7
|
+
import {Stack} from '../../stack'
|
|
8
|
+
import {Text} from '../../text'
|
|
9
|
+
import {Popover, PopoverProps, PopoverUpdateCallback} from '../popover'
|
|
10
|
+
|
|
11
|
+
const SIDE_PANEL_WIDTH = {
|
|
12
|
+
sm: 300,
|
|
13
|
+
md: 400,
|
|
14
|
+
lg: 500,
|
|
15
|
+
xl: 600,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default function SidePanelStory() {
|
|
19
|
+
const sidePanelWidth = useSelect('Side panel width', SIDE_PANEL_WIDTH, SIDE_PANEL_WIDTH.md)
|
|
20
|
+
const [sidePanel, setSidePanel] = useState<HTMLDivElement | null>(null)
|
|
21
|
+
const updateRef = useRef<PopoverUpdateCallback>()
|
|
22
|
+
|
|
23
|
+
useEffect(() => updateRef.current?.(), [sidePanelWidth])
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<Flex height="fill">
|
|
27
|
+
<Card flex={1}>
|
|
28
|
+
<Box padding={4}>
|
|
29
|
+
<Text>
|
|
30
|
+
This story shows that popovers respect their boundary when used in a side panel.
|
|
31
|
+
</Text>
|
|
32
|
+
</Box>
|
|
33
|
+
</Card>
|
|
34
|
+
<BoundaryElementProvider element={sidePanel}>
|
|
35
|
+
<Card borderLeft flex="none" ref={setSidePanel} style={{width: sidePanelWidth}} width={0}>
|
|
36
|
+
<Stack padding={4} space={5}>
|
|
37
|
+
<Text muted size={1}>
|
|
38
|
+
Click the <code>reference</code> text below to toggle the popover.
|
|
39
|
+
</Text>
|
|
40
|
+
|
|
41
|
+
<Card border padding={3}>
|
|
42
|
+
<Text size={1}>
|
|
43
|
+
Some editor <InlineObject updateRef={updateRef} />
|
|
44
|
+
</Text>
|
|
45
|
+
</Card>
|
|
46
|
+
</Stack>
|
|
47
|
+
</Card>
|
|
48
|
+
</BoundaryElementProvider>
|
|
49
|
+
</Flex>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function InlineObject(props: {updateRef?: PopoverProps['updateRef']}) {
|
|
54
|
+
const {updateRef} = props
|
|
55
|
+
const [open, setOpen] = useState(false)
|
|
56
|
+
|
|
57
|
+
const handleClick = useCallback(() => {
|
|
58
|
+
setOpen((prev) => !prev)
|
|
59
|
+
}, [])
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<Popover
|
|
63
|
+
content={
|
|
64
|
+
<Box padding={3}>
|
|
65
|
+
<Text size={1}>
|
|
66
|
+
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum
|
|
67
|
+
has been the industry's standard dummy text ever since the 1500s, when an unknown
|
|
68
|
+
printer took a galley of type and scrambled it to make a type specimen book. It has
|
|
69
|
+
survived not only five centuries, but also the leap into electronic typesetting,
|
|
70
|
+
remaining essentially unchanged. It was popularised in the 1960s with the release of
|
|
71
|
+
Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
|
|
72
|
+
publishing software like Aldus PageMaker including versions of Lorem Ipsum.
|
|
73
|
+
</Text>
|
|
74
|
+
</Box>
|
|
75
|
+
}
|
|
76
|
+
constrainSize
|
|
77
|
+
open={open}
|
|
78
|
+
overflow="auto"
|
|
79
|
+
portal
|
|
80
|
+
width={0}
|
|
81
|
+
updateRef={updateRef}
|
|
82
|
+
>
|
|
83
|
+
<code onClick={handleClick}>reference</code>
|
|
84
|
+
</Popover>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {useBoolean, useSelect, useText} from '@sanity/ui-workshop'
|
|
2
|
-
import {ReactElement, useState} from 'react'
|
|
1
|
+
import {useAction, useBoolean, useSelect, useText} from '@sanity/ui-workshop'
|
|
2
|
+
import {ReactElement, useRef, useState} from 'react'
|
|
3
3
|
import {
|
|
4
4
|
WORKSHOP_CONTAINER_WIDTH_OPTIONS,
|
|
5
5
|
WORKSHOP_PLACEMENT_OPTIONS,
|
|
@@ -10,10 +10,13 @@ import {Button} from '../../button'
|
|
|
10
10
|
import {Card} from '../../card'
|
|
11
11
|
import {Text} from '../../text'
|
|
12
12
|
import {Popover} from '../popover'
|
|
13
|
+
import {PopoverUpdateCallback} from '../types'
|
|
13
14
|
|
|
14
15
|
export default function TestStory(): ReactElement {
|
|
15
16
|
const [portalElement, setPortalElement] = useState<HTMLDivElement | null>(null)
|
|
16
17
|
const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)
|
|
18
|
+
|
|
19
|
+
const mount = useBoolean('Mount', true)
|
|
17
20
|
const arrow = useBoolean('Arrow', true)
|
|
18
21
|
const constrainSize = useBoolean('Constrain size', true)
|
|
19
22
|
const matchReferenceWidth = useBoolean('Match reference width', false)
|
|
@@ -26,6 +29,10 @@ export default function TestStory(): ReactElement {
|
|
|
26
29
|
|
|
27
30
|
const text = useText('Text', 'Test')
|
|
28
31
|
|
|
32
|
+
const updateRef = useRef<PopoverUpdateCallback>()
|
|
33
|
+
|
|
34
|
+
const button = <Button text="reference" style={{width: referenceWide ? 300 : undefined}} />
|
|
35
|
+
|
|
29
36
|
return (
|
|
30
37
|
<Card
|
|
31
38
|
ref={setBoundaryElement}
|
|
@@ -56,22 +63,27 @@ export default function TestStory(): ReactElement {
|
|
|
56
63
|
<div style={{padding: '150vh'}}>
|
|
57
64
|
<PortalProvider element={portalElement}>
|
|
58
65
|
<BoundaryElementProvider element={boundaryElement}>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
{!mount && button}
|
|
67
|
+
{mount && (
|
|
68
|
+
<Popover
|
|
69
|
+
arrow={arrow}
|
|
70
|
+
content={<Text>{text}</Text>}
|
|
71
|
+
constrainSize={constrainSize}
|
|
72
|
+
fallbackPlacements={['left', 'bottom', 'right', 'top']}
|
|
73
|
+
matchReferenceWidth={matchReferenceWidth}
|
|
74
|
+
open={open}
|
|
75
|
+
overflow="hidden"
|
|
76
|
+
padding={3}
|
|
77
|
+
placement={placement}
|
|
78
|
+
portal
|
|
79
|
+
preventOverflow={preventOverflow}
|
|
80
|
+
radius={radius}
|
|
81
|
+
updateRef={updateRef}
|
|
82
|
+
width={width}
|
|
83
|
+
>
|
|
84
|
+
{button}
|
|
85
|
+
</Popover>
|
|
86
|
+
)}
|
|
75
87
|
</BoundaryElementProvider>
|
|
76
88
|
</PortalProvider>
|
|
77
89
|
</div>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {Theme} from '../../theme'
|
|
2
|
+
import {DEFAULT_POPOVER_PADDING} from './constants'
|
|
3
|
+
import {PopoverWidth} from './types'
|
|
4
|
+
|
|
5
|
+
export function calcCurrentWidth(params: {
|
|
6
|
+
mediaIndex: number
|
|
7
|
+
theme: Theme
|
|
8
|
+
width: PopoverWidth[]
|
|
9
|
+
}): number | undefined {
|
|
10
|
+
const {mediaIndex, theme, width} = params
|
|
11
|
+
|
|
12
|
+
const w = width[mediaIndex]
|
|
13
|
+
const currentWidth: PopoverWidth | undefined = w === undefined ? width[width.length - 1] : w
|
|
14
|
+
|
|
15
|
+
return typeof currentWidth === 'number' ? theme.sanity.container[currentWidth] : undefined
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function calcMaxWidth(params: {
|
|
19
|
+
boundaryWidth: number | undefined
|
|
20
|
+
currentWidth: number | undefined
|
|
21
|
+
}): number | undefined {
|
|
22
|
+
const {boundaryWidth, currentWidth} = params
|
|
23
|
+
|
|
24
|
+
if (currentWidth === undefined && boundaryWidth === undefined) {
|
|
25
|
+
return undefined
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return Math.min(
|
|
29
|
+
currentWidth ?? Infinity,
|
|
30
|
+
(boundaryWidth || Infinity) - DEFAULT_POPOVER_PADDING * 2
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -8,51 +8,65 @@ import {
|
|
|
8
8
|
offset,
|
|
9
9
|
shift,
|
|
10
10
|
useFloating,
|
|
11
|
-
UseFloatingProps,
|
|
12
11
|
} from '@floating-ui/react-dom'
|
|
13
|
-
import {
|
|
14
|
-
|
|
12
|
+
import {
|
|
13
|
+
MutableRefObject,
|
|
14
|
+
RefCallback,
|
|
15
|
+
cloneElement,
|
|
16
|
+
forwardRef,
|
|
17
|
+
memo,
|
|
18
|
+
useCallback,
|
|
19
|
+
useEffect,
|
|
20
|
+
useMemo,
|
|
21
|
+
useRef,
|
|
22
|
+
} from 'react'
|
|
23
|
+
import {useForwardedRef, useArrayProp, useElementSize, useMediaIndex} from '../../hooks'
|
|
15
24
|
import {ThemeColorSchemeKey, useTheme} from '../../theme'
|
|
16
25
|
import {BoxOverflow, CardTone, Placement, PopoverMargins} from '../../types'
|
|
17
26
|
import {LayerProps, LayerProvider, Portal, useBoundaryElement} from '../../utils'
|
|
18
|
-
import {ResponsiveRadiusProps, ResponsiveShadowProps
|
|
27
|
+
import {ResponsiveRadiusProps, ResponsiveShadowProps} from '../types'
|
|
19
28
|
import {
|
|
20
29
|
DEFAULT_POPOVER_DISTANCE,
|
|
21
30
|
DEFAULT_POPOVER_MARGINS,
|
|
22
31
|
DEFAULT_POPOVER_PADDING,
|
|
23
32
|
} from './constants'
|
|
24
33
|
import {size} from './floating-ui/size'
|
|
34
|
+
import {calcCurrentWidth, calcMaxWidth} from './helpers'
|
|
25
35
|
import {PopoverCard} from './popoverCard'
|
|
36
|
+
import {PopoverUpdateCallback, PopoverWidth} from './types'
|
|
26
37
|
|
|
27
|
-
/**
|
|
28
|
-
* @public
|
|
29
|
-
*/
|
|
38
|
+
/** @public */
|
|
30
39
|
export interface PopoverProps
|
|
31
40
|
extends Omit<LayerProps, 'as'>,
|
|
32
41
|
ResponsiveRadiusProps,
|
|
33
|
-
ResponsiveShadowProps
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @beta
|
|
37
|
-
*/
|
|
42
|
+
ResponsiveShadowProps {
|
|
43
|
+
/** @beta */
|
|
38
44
|
__unstable_margins?: PopoverMargins
|
|
39
45
|
arrow?: boolean
|
|
46
|
+
/** @deprecated Use `floatingBoundary` and/or `referenceBoundary` instead */
|
|
40
47
|
boundaryElement?: HTMLElement | null
|
|
41
48
|
children?: React.ReactElement
|
|
42
49
|
constrainSize?: boolean
|
|
43
50
|
content?: React.ReactNode
|
|
44
51
|
disabled?: boolean
|
|
45
52
|
fallbackPlacements?: Placement[]
|
|
53
|
+
floatingBoundary?: HTMLElement | null
|
|
54
|
+
matchReferenceWidth?: boolean
|
|
46
55
|
open?: boolean
|
|
47
56
|
overflow?: BoxOverflow
|
|
48
57
|
padding?: number | number[]
|
|
49
58
|
placement?: Placement
|
|
50
59
|
portal?: boolean | string
|
|
51
60
|
preventOverflow?: boolean
|
|
61
|
+
referenceBoundary?: HTMLElement | null
|
|
52
62
|
referenceElement?: HTMLElement | null
|
|
53
|
-
matchReferenceWidth?: boolean
|
|
54
63
|
scheme?: ThemeColorSchemeKey
|
|
55
64
|
tone?: CardTone
|
|
65
|
+
/** @beta */
|
|
66
|
+
updateRef?:
|
|
67
|
+
| MutableRefObject<PopoverUpdateCallback | undefined>
|
|
68
|
+
| RefCallback<PopoverUpdateCallback | undefined>
|
|
69
|
+
width?: PopoverWidth | PopoverWidth[]
|
|
56
70
|
}
|
|
57
71
|
|
|
58
72
|
/** @public */
|
|
@@ -74,7 +88,8 @@ export const Popover = memo(
|
|
|
74
88
|
content,
|
|
75
89
|
disabled,
|
|
76
90
|
fallbackPlacements,
|
|
77
|
-
matchReferenceWidth
|
|
91
|
+
matchReferenceWidth,
|
|
92
|
+
floatingBoundary = props.boundaryElement ?? boundaryElementContext.element,
|
|
78
93
|
open,
|
|
79
94
|
overflow = 'hidden',
|
|
80
95
|
padding: paddingProp,
|
|
@@ -82,24 +97,73 @@ export const Popover = memo(
|
|
|
82
97
|
portal,
|
|
83
98
|
preventOverflow = true,
|
|
84
99
|
radius: radiusProp = 3,
|
|
100
|
+
referenceBoundary = props.boundaryElement ?? boundaryElementContext.element,
|
|
85
101
|
referenceElement,
|
|
86
102
|
scheme,
|
|
87
103
|
shadow: shadowProp = 3,
|
|
88
104
|
tone = 'inherit',
|
|
89
105
|
width: widthProp = 'auto',
|
|
90
106
|
zOffset: zOffsetProp = theme.sanity.layer?.popover.zOffset,
|
|
107
|
+
updateRef,
|
|
91
108
|
...restProps
|
|
92
109
|
} = props
|
|
93
110
|
const boundarySize = useElementSize(boundaryElement)?.border
|
|
94
111
|
const padding = useArrayProp(paddingProp)
|
|
95
112
|
const radius = useArrayProp(radiusProp)
|
|
96
113
|
const shadow = useArrayProp(shadowProp)
|
|
97
|
-
const
|
|
114
|
+
const widthArrayProp = useArrayProp(widthProp)
|
|
98
115
|
const zOffset = useArrayProp(zOffsetProp)
|
|
99
116
|
const forwardedRef = useForwardedRef(ref)
|
|
100
117
|
const arrowRef = useRef<HTMLDivElement | null>(null)
|
|
101
118
|
const rootBoundary: RootBoundary = 'viewport'
|
|
102
119
|
|
|
120
|
+
const mediaIndex = useMediaIndex()
|
|
121
|
+
const boundaryWidth = constrainSize || preventOverflow ? boundarySize?.width : undefined
|
|
122
|
+
|
|
123
|
+
// Update width when
|
|
124
|
+
// - media index changes
|
|
125
|
+
// - `width` property changes
|
|
126
|
+
const width = calcCurrentWidth({mediaIndex, theme, width: widthArrayProp})
|
|
127
|
+
const widthRef = useRef(width)
|
|
128
|
+
|
|
129
|
+
useEffect(() => {
|
|
130
|
+
widthRef.current = width
|
|
131
|
+
}, [width])
|
|
132
|
+
|
|
133
|
+
// Update max width when
|
|
134
|
+
// - boundary width changes
|
|
135
|
+
// - `width` property changes
|
|
136
|
+
const maxWidth = calcMaxWidth({boundaryWidth, currentWidth: width})
|
|
137
|
+
const maxWidthRef = useRef(maxWidth)
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
maxWidthRef.current = maxWidth
|
|
141
|
+
}, [maxWidth])
|
|
142
|
+
|
|
143
|
+
// Keep track of reference element width (see `size` middleware below)
|
|
144
|
+
const referenceWidthRef = useRef<number>()
|
|
145
|
+
|
|
146
|
+
// Force apply width & max width to floating element
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
const floatingElement = forwardedRef.current
|
|
149
|
+
|
|
150
|
+
if (!open || !floatingElement) return
|
|
151
|
+
|
|
152
|
+
const referenceWidth = referenceWidthRef.current
|
|
153
|
+
|
|
154
|
+
if (matchReferenceWidth) {
|
|
155
|
+
if (referenceWidth !== undefined) {
|
|
156
|
+
floatingElement.style.width = `${referenceWidth}px`
|
|
157
|
+
}
|
|
158
|
+
} else if (width !== undefined) {
|
|
159
|
+
floatingElement.style.width = `${width}px`
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (typeof maxWidth === 'number') {
|
|
163
|
+
floatingElement.style.maxWidth = `${maxWidth}px`
|
|
164
|
+
}
|
|
165
|
+
}, [width, forwardedRef, matchReferenceWidth, maxWidth, open])
|
|
166
|
+
|
|
103
167
|
const middleware = useMemo(() => {
|
|
104
168
|
const ret: Middleware[] = []
|
|
105
169
|
|
|
@@ -107,7 +171,7 @@ export const Popover = memo(
|
|
|
107
171
|
if (constrainSize || preventOverflow) {
|
|
108
172
|
ret.push(
|
|
109
173
|
flip({
|
|
110
|
-
boundary:
|
|
174
|
+
boundary: floatingBoundary || undefined,
|
|
111
175
|
fallbackPlacements,
|
|
112
176
|
padding: DEFAULT_POPOVER_PADDING,
|
|
113
177
|
rootBoundary,
|
|
@@ -123,23 +187,36 @@ export const Popover = memo(
|
|
|
123
187
|
)
|
|
124
188
|
|
|
125
189
|
// Track sizes
|
|
126
|
-
if (constrainSize ||
|
|
190
|
+
if (constrainSize || matchReferenceWidth) {
|
|
127
191
|
ret.push(
|
|
128
192
|
size({
|
|
129
193
|
apply({availableWidth, availableHeight, elements, referenceWidth}) {
|
|
130
|
-
|
|
194
|
+
// not fresh, so use refs
|
|
195
|
+
|
|
196
|
+
referenceWidthRef.current = referenceWidth
|
|
197
|
+
|
|
198
|
+
const _currentWidth = widthRef.current
|
|
199
|
+
const _maxWidth = maxWidthRef.current
|
|
200
|
+
|
|
201
|
+
if (matchReferenceWidth) {
|
|
131
202
|
elements.floating.style.width = `${referenceWidth}px`
|
|
203
|
+
} else if (_currentWidth !== undefined) {
|
|
204
|
+
elements.floating.style.width = `${_currentWidth}px`
|
|
132
205
|
}
|
|
133
206
|
|
|
134
207
|
if (constrainSize) {
|
|
135
|
-
elements.floating.style.maxWidth = `${
|
|
208
|
+
elements.floating.style.maxWidth = `${Math.min(
|
|
209
|
+
availableWidth,
|
|
210
|
+
_maxWidth ?? Infinity
|
|
211
|
+
)}px`
|
|
212
|
+
|
|
136
213
|
elements.floating.style.maxHeight = `${availableHeight}px`
|
|
137
214
|
}
|
|
138
215
|
},
|
|
139
|
-
boundaryElement,
|
|
216
|
+
boundaryElement: floatingBoundary || undefined,
|
|
140
217
|
constrainSize,
|
|
141
218
|
margins,
|
|
142
|
-
matchReferenceWidth
|
|
219
|
+
matchReferenceWidth,
|
|
143
220
|
padding: DEFAULT_POPOVER_PADDING,
|
|
144
221
|
})
|
|
145
222
|
)
|
|
@@ -149,7 +226,7 @@ export const Popover = memo(
|
|
|
149
226
|
if (preventOverflow) {
|
|
150
227
|
ret.push(
|
|
151
228
|
shift({
|
|
152
|
-
boundary:
|
|
229
|
+
boundary: floatingBoundary || undefined,
|
|
153
230
|
rootBoundary,
|
|
154
231
|
padding: DEFAULT_POPOVER_PADDING,
|
|
155
232
|
})
|
|
@@ -168,7 +245,7 @@ export const Popover = memo(
|
|
|
168
245
|
|
|
169
246
|
ret.push(
|
|
170
247
|
hide({
|
|
171
|
-
boundary:
|
|
248
|
+
boundary: referenceBoundary || undefined,
|
|
172
249
|
padding: DEFAULT_POPOVER_PADDING,
|
|
173
250
|
strategy: 'referenceHidden',
|
|
174
251
|
})
|
|
@@ -177,32 +254,20 @@ export const Popover = memo(
|
|
|
177
254
|
return ret
|
|
178
255
|
}, [
|
|
179
256
|
arrowProp,
|
|
180
|
-
boundaryElement,
|
|
181
257
|
constrainSize,
|
|
182
258
|
fallbackPlacements,
|
|
259
|
+
floatingBoundary,
|
|
183
260
|
margins,
|
|
184
|
-
|
|
261
|
+
matchReferenceWidth,
|
|
185
262
|
preventOverflow,
|
|
263
|
+
referenceBoundary,
|
|
186
264
|
])
|
|
187
265
|
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}),
|
|
194
|
-
[middleware, placementProp]
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
const {
|
|
198
|
-
x,
|
|
199
|
-
y,
|
|
200
|
-
placement,
|
|
201
|
-
reference: referenceRef,
|
|
202
|
-
floating: floatingRef,
|
|
203
|
-
middlewareData,
|
|
204
|
-
strategy,
|
|
205
|
-
} = useFloating(floatingProps)
|
|
266
|
+
const {x, y, middlewareData, placement, refs, strategy, update} = useFloating({
|
|
267
|
+
middleware,
|
|
268
|
+
placement: placementProp,
|
|
269
|
+
whileElementsMounted: autoUpdate,
|
|
270
|
+
})
|
|
206
271
|
|
|
207
272
|
const referenceHidden = middlewareData.hide?.referenceHidden
|
|
208
273
|
|
|
@@ -216,14 +281,14 @@ export const Popover = memo(
|
|
|
216
281
|
const setFloating = useCallback(
|
|
217
282
|
(node: HTMLDivElement | null) => {
|
|
218
283
|
forwardedRef.current = node
|
|
219
|
-
|
|
284
|
+
refs.setFloating(node)
|
|
220
285
|
},
|
|
221
|
-
[
|
|
286
|
+
[forwardedRef, refs]
|
|
222
287
|
)
|
|
223
288
|
|
|
224
289
|
const setReference = useCallback(
|
|
225
290
|
(node: HTMLElement | null) => {
|
|
226
|
-
|
|
291
|
+
refs.setReference(node)
|
|
227
292
|
|
|
228
293
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
229
294
|
const childRef = (childProp as any)?.ref
|
|
@@ -234,7 +299,7 @@ export const Popover = memo(
|
|
|
234
299
|
childRef.current = node
|
|
235
300
|
}
|
|
236
301
|
},
|
|
237
|
-
[childProp,
|
|
302
|
+
[childProp, refs]
|
|
238
303
|
)
|
|
239
304
|
|
|
240
305
|
const child = useMemo(() => {
|
|
@@ -244,8 +309,18 @@ export const Popover = memo(
|
|
|
244
309
|
}, [childProp, referenceElement, setReference])
|
|
245
310
|
|
|
246
311
|
useEffect(() => {
|
|
247
|
-
|
|
248
|
-
|
|
312
|
+
if (updateRef) {
|
|
313
|
+
if (typeof updateRef === 'function') {
|
|
314
|
+
updateRef(update)
|
|
315
|
+
} else if (updateRef) {
|
|
316
|
+
updateRef.current = update
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}, [update, updateRef])
|
|
320
|
+
|
|
321
|
+
useEffect(() => {
|
|
322
|
+
refs.setReference(referenceElement || null)
|
|
323
|
+
}, [referenceElement, refs])
|
|
249
324
|
|
|
250
325
|
if (disabled) {
|
|
251
326
|
return childProp || <></>
|
|
@@ -260,7 +335,6 @@ export const Popover = memo(
|
|
|
260
335
|
arrowRef={setArrow}
|
|
261
336
|
arrowX={arrowX}
|
|
262
337
|
arrowY={arrowY}
|
|
263
|
-
boundaryWidth={preventOverflow ? boundarySize?.width : undefined}
|
|
264
338
|
hidden={referenceHidden}
|
|
265
339
|
overflow={overflow}
|
|
266
340
|
padding={padding}
|
|
@@ -271,9 +345,9 @@ export const Popover = memo(
|
|
|
271
345
|
shadow={shadow}
|
|
272
346
|
strategy={strategy}
|
|
273
347
|
tone={tone}
|
|
348
|
+
width={matchReferenceWidth ? referenceWidthRef.current : width}
|
|
274
349
|
x={x}
|
|
275
350
|
y={y}
|
|
276
|
-
width={width}
|
|
277
351
|
>
|
|
278
352
|
{content}
|
|
279
353
|
</PopoverCard>
|