@sanity/ui 2.8.20 → 2.8.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +12 -10
- package/dist/index.d.ts +12 -10
- package/dist/index.esm.js +204 -93
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +203 -92
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +204 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -18
- package/src/core/components/menu/menu.tsx +12 -10
- package/src/core/components/menu/menuButton.tsx +14 -36
- package/src/core/components/toast/toastProvider.tsx +5 -6
- package/src/core/components/toast/toastState.ts +6 -0
- package/src/core/constants.ts +1 -1
- package/src/core/hooks/useArrayProp.ts +14 -9
- package/src/core/primitives/avatar/avatarStack.tsx +2 -5
- package/src/core/utils/elementQuery/elementQuery.tsx +16 -17
- package/src/core/utils/layer/layerProvider.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.22",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"sanity",
|
|
6
6
|
"ui",
|
|
@@ -122,24 +122,24 @@
|
|
|
122
122
|
"@commitlint/cli": "^19.4.0",
|
|
123
123
|
"@commitlint/config-conventional": "^19.2.2",
|
|
124
124
|
"@juggle/resize-observer": "^3.4.0",
|
|
125
|
-
"@sanity/pkg-utils": "^6.11.
|
|
125
|
+
"@sanity/pkg-utils": "^6.11.9",
|
|
126
126
|
"@sanity/prettier-config": "^1.0.2",
|
|
127
127
|
"@sanity/semantic-release-preset": "^5.0.0",
|
|
128
128
|
"@sanity/ui-workshop": "^2.0.16",
|
|
129
|
-
"@storybook/addon-a11y": "^8.4.
|
|
130
|
-
"@storybook/addon-docs": "^8.4.
|
|
131
|
-
"@storybook/addon-essentials": "^8.4.
|
|
132
|
-
"@storybook/addon-interactions": "^8.4.
|
|
133
|
-
"@storybook/addon-links": "^8.4.
|
|
134
|
-
"@storybook/addon-mdx-gfm": "^8.4.
|
|
135
|
-
"@storybook/addon-storysource": "^8.4.
|
|
136
|
-
"@storybook/addon-themes": "^8.4.
|
|
137
|
-
"@storybook/blocks": "^8.4.
|
|
138
|
-
"@storybook/manager-api": "^8.4.
|
|
139
|
-
"@storybook/react": "^8.4.
|
|
140
|
-
"@storybook/react-vite": "^8.4.
|
|
141
|
-
"@storybook/test": "^8.4.
|
|
142
|
-
"@storybook/theming": "^8.4.
|
|
129
|
+
"@storybook/addon-a11y": "^8.4.2",
|
|
130
|
+
"@storybook/addon-docs": "^8.4.2",
|
|
131
|
+
"@storybook/addon-essentials": "^8.4.2",
|
|
132
|
+
"@storybook/addon-interactions": "^8.4.2",
|
|
133
|
+
"@storybook/addon-links": "^8.4.2",
|
|
134
|
+
"@storybook/addon-mdx-gfm": "^8.4.2",
|
|
135
|
+
"@storybook/addon-storysource": "^8.4.2",
|
|
136
|
+
"@storybook/addon-themes": "^8.4.2",
|
|
137
|
+
"@storybook/blocks": "^8.4.2",
|
|
138
|
+
"@storybook/manager-api": "^8.4.2",
|
|
139
|
+
"@storybook/react": "^8.4.2",
|
|
140
|
+
"@storybook/react-vite": "^8.4.2",
|
|
141
|
+
"@storybook/test": "^8.4.2",
|
|
142
|
+
"@storybook/theming": "^8.4.2",
|
|
143
143
|
"@testing-library/dom": "^10.4.0",
|
|
144
144
|
"@testing-library/jest-dom": "^6.6.2",
|
|
145
145
|
"@testing-library/react": "^16.0.1",
|
|
@@ -168,7 +168,7 @@
|
|
|
168
168
|
"eslint-plugin-react": "^7.37.2",
|
|
169
169
|
"eslint-plugin-react-compiler": "19.0.0-beta-63b359f-20241101",
|
|
170
170
|
"eslint-plugin-react-hooks": "^5.0.0",
|
|
171
|
-
"eslint-plugin-storybook": "^0.
|
|
171
|
+
"eslint-plugin-storybook": "^0.11.0",
|
|
172
172
|
"http-server": "^14.1.1",
|
|
173
173
|
"husky": "^8.0.3",
|
|
174
174
|
"jest": "^29.7.0",
|
|
@@ -185,7 +185,7 @@
|
|
|
185
185
|
"rimraf": "^5.0.5",
|
|
186
186
|
"semantic-release": "^24.0.0",
|
|
187
187
|
"start-server-and-test": "^2.0.5",
|
|
188
|
-
"storybook": "^8.4.
|
|
188
|
+
"storybook": "^8.4.2",
|
|
189
189
|
"styled-components": "^6.1.13",
|
|
190
190
|
"tsconfig-paths": "^4.2.0",
|
|
191
191
|
"typescript": "5.6.3",
|
|
@@ -14,19 +14,21 @@ export interface MenuProps extends ResponsivePaddingProps {
|
|
|
14
14
|
/**
|
|
15
15
|
* @deprecated Use `shouldFocus="first"` instead.
|
|
16
16
|
*/
|
|
17
|
-
focusFirst?: boolean
|
|
17
|
+
'focusFirst'?: boolean
|
|
18
18
|
/**
|
|
19
19
|
* @deprecated Use `shouldFocus="last"` instead.
|
|
20
20
|
*/
|
|
21
|
-
focusLast?: boolean
|
|
22
|
-
onClickOutside?: (event: MouseEvent) => void
|
|
23
|
-
onEscape?: () => void
|
|
24
|
-
onItemClick?: () => void
|
|
25
|
-
onItemSelect?: (index: number) => void
|
|
26
|
-
originElement?: HTMLElement | null
|
|
27
|
-
registerElement?: (el: HTMLElement) => () => void
|
|
28
|
-
shouldFocus?: 'first' | 'last' | null
|
|
29
|
-
space?: number | number[]
|
|
21
|
+
'focusLast'?: boolean
|
|
22
|
+
'onClickOutside'?: (event: MouseEvent) => void
|
|
23
|
+
'onEscape'?: () => void
|
|
24
|
+
'onItemClick'?: () => void
|
|
25
|
+
'onItemSelect'?: (index: number) => void
|
|
26
|
+
'originElement'?: HTMLElement | null
|
|
27
|
+
'registerElement'?: (el: HTMLElement) => () => void
|
|
28
|
+
'shouldFocus'?: 'first' | 'last' | null
|
|
29
|
+
'space'?: number | number[]
|
|
30
|
+
'aria-labelledby'?: string
|
|
31
|
+
'onBlurCapture'?: (event: FocusEvent) => void
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
const Root = styled(Box)`
|
|
@@ -169,7 +169,7 @@ export const MenuButton = forwardRef(function MenuButton(
|
|
|
169
169
|
}, [buttonElement, disableRestoreFocusOnClose])
|
|
170
170
|
|
|
171
171
|
const handleBlur = useCallback(
|
|
172
|
-
(event:
|
|
172
|
+
(event: FocusEvent) => {
|
|
173
173
|
const target = event.relatedTarget
|
|
174
174
|
|
|
175
175
|
if (!(target instanceof Node)) {
|
|
@@ -199,32 +199,19 @@ export const MenuButton = forwardRef(function MenuButton(
|
|
|
199
199
|
return () => setChildMenuElements((els) => els.filter((_el) => _el !== el))
|
|
200
200
|
}, [])
|
|
201
201
|
|
|
202
|
-
const menuProps: MenuProps =
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}),
|
|
213
|
-
[
|
|
214
|
-
buttonElement,
|
|
215
|
-
handleMenuClickOutside,
|
|
216
|
-
handleMenuEscape,
|
|
217
|
-
handleItemClick,
|
|
218
|
-
id,
|
|
219
|
-
handleBlur,
|
|
220
|
-
registerElement,
|
|
221
|
-
shouldFocus,
|
|
222
|
-
],
|
|
223
|
-
)
|
|
202
|
+
const menuProps: MenuProps = {
|
|
203
|
+
'aria-labelledby': id,
|
|
204
|
+
'onBlurCapture': handleBlur,
|
|
205
|
+
'onClickOutside': handleMenuClickOutside,
|
|
206
|
+
'onEscape': handleMenuEscape,
|
|
207
|
+
'onItemClick': handleItemClick,
|
|
208
|
+
'originElement': buttonElement,
|
|
209
|
+
registerElement,
|
|
210
|
+
shouldFocus,
|
|
211
|
+
}
|
|
224
212
|
|
|
225
213
|
const menu = menuProp && cloneElement(menuProp, menuProps)
|
|
226
214
|
|
|
227
|
-
const ref = useRef<HTMLButtonElement | null>(null)
|
|
228
215
|
const button = useMemo(
|
|
229
216
|
() =>
|
|
230
217
|
buttonProp &&
|
|
@@ -236,7 +223,7 @@ export const MenuButton = forwardRef(function MenuButton(
|
|
|
236
223
|
'onMouseDown': handleMouseDown,
|
|
237
224
|
'aria-haspopup': true,
|
|
238
225
|
'aria-expanded': open,
|
|
239
|
-
'ref':
|
|
226
|
+
'ref': setButtonElement,
|
|
240
227
|
'selected': buttonProp.props.selected ?? open,
|
|
241
228
|
}),
|
|
242
229
|
[buttonProp, handleButtonClick, handleButtonKeyDown, handleMouseDown, id, open],
|
|
@@ -245,19 +232,10 @@ export const MenuButton = forwardRef(function MenuButton(
|
|
|
245
232
|
// Forward button ref to parent
|
|
246
233
|
useImperativeHandle<HTMLButtonElement | null, HTMLButtonElement | null>(
|
|
247
234
|
forwardedRef,
|
|
248
|
-
() =>
|
|
235
|
+
() => buttonElement,
|
|
236
|
+
[buttonElement],
|
|
249
237
|
)
|
|
250
238
|
|
|
251
|
-
// If there's a button then we need to set the reference element to the cloned button ref
|
|
252
|
-
// and if button changes we make sure to update or remove the reference element.
|
|
253
|
-
useEffect(() => {
|
|
254
|
-
if (!button) return undefined
|
|
255
|
-
|
|
256
|
-
setButtonElement(ref.current)
|
|
257
|
-
|
|
258
|
-
return () => setButtonElement(null)
|
|
259
|
-
}, [button])
|
|
260
|
-
|
|
261
239
|
const popoverProps: MenuButtonProps['popover'] = useMemo(
|
|
262
240
|
() => ({
|
|
263
241
|
boundaryElement: deprecated_boundaryElement,
|
|
@@ -8,6 +8,7 @@ import {Box} from '../../primitives'
|
|
|
8
8
|
import {Layer} from '../../utils'
|
|
9
9
|
import {Toast} from './toast'
|
|
10
10
|
import {ToastContext} from './toastContext'
|
|
11
|
+
import {generateToastId} from './toastState'
|
|
11
12
|
import {ToastContextValue, ToastParams} from './types'
|
|
12
13
|
|
|
13
14
|
type ToastState = {
|
|
@@ -45,8 +46,6 @@ const ToastContainer = styled.div`
|
|
|
45
46
|
width: 100%;
|
|
46
47
|
`
|
|
47
48
|
|
|
48
|
-
let toastId = 0
|
|
49
|
-
|
|
50
49
|
/**
|
|
51
50
|
* @public
|
|
52
51
|
*/
|
|
@@ -60,20 +59,20 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
|
|
|
60
59
|
() => ({
|
|
61
60
|
initial: {
|
|
62
61
|
opacity: 0,
|
|
63
|
-
[POPOVER_MOTION_CONTENT_OPACITY_PROPERTY
|
|
62
|
+
[POPOVER_MOTION_CONTENT_OPACITY_PROPERTY]: 0,
|
|
64
63
|
y: 32,
|
|
65
64
|
scale: 0.25,
|
|
66
65
|
willChange: 'transform',
|
|
67
66
|
},
|
|
68
67
|
animate: {
|
|
69
68
|
opacity: [0, 1, 1],
|
|
70
|
-
[POPOVER_MOTION_CONTENT_OPACITY_PROPERTY
|
|
69
|
+
[POPOVER_MOTION_CONTENT_OPACITY_PROPERTY]: [0, 0, 1],
|
|
71
70
|
y: 0,
|
|
72
71
|
scale: 1,
|
|
73
72
|
},
|
|
74
73
|
exit: {
|
|
75
74
|
opacity: [1, 1, 0],
|
|
76
|
-
[POPOVER_MOTION_CONTENT_OPACITY_PROPERTY
|
|
75
|
+
[POPOVER_MOTION_CONTENT_OPACITY_PROPERTY]: [1, 0, 0],
|
|
77
76
|
scale: 0.5,
|
|
78
77
|
transition: prefersReducedMotion ? {duration: 0} : {duration: 0.2},
|
|
79
78
|
},
|
|
@@ -86,7 +85,7 @@ export function ToastProvider(props: ToastProviderProps): React.ReactElement {
|
|
|
86
85
|
// Wrap setState in startTransition to allow React to give input state updates higher priority
|
|
87
86
|
const setState: typeof _setState = (state) => startTransition(() => _setState(state))
|
|
88
87
|
|
|
89
|
-
const id = params.id ||
|
|
88
|
+
const id = params.id || generateToastId()
|
|
90
89
|
const duration = params.duration || 5000
|
|
91
90
|
|
|
92
91
|
const dismiss = () => {
|
package/src/core/constants.ts
CHANGED
|
@@ -13,7 +13,7 @@ export const EMPTY_RECORD: Record<string, never> = {}
|
|
|
13
13
|
/**
|
|
14
14
|
* @internal
|
|
15
15
|
*/
|
|
16
|
-
export const POPOVER_MOTION_CONTENT_OPACITY_PROPERTY = '--motion-content-opacity'
|
|
16
|
+
export const POPOVER_MOTION_CONTENT_OPACITY_PROPERTY = '--motion-content-opacity' as string
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Shared `framer-motion` variants used by `Popover` and `Tooltip` components.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {useState} from 'react'
|
|
2
2
|
import {_getArrayProp} from '../styles'
|
|
3
3
|
|
|
4
4
|
/** @beta */
|
|
@@ -12,14 +12,19 @@ export function useArrayProp<T extends ArrayPropPrimitive = ArrayPropPrimitive>(
|
|
|
12
12
|
val: T | T[] | undefined,
|
|
13
13
|
defaultVal?: T[],
|
|
14
14
|
): T[] {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const [[cachedVal, cachedHash], setCache] = useState<[T[], string]>(() => [
|
|
16
|
+
_getArrayProp(val, defaultVal),
|
|
17
|
+
JSON.stringify(val ?? defaultVal),
|
|
18
|
+
])
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
() => _getArrayProp(val, defaultVal),
|
|
20
|
+
const hash = JSON.stringify(val ?? defaultVal)
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
if (hash !== cachedHash) {
|
|
23
|
+
// If the cached hash has changed, update the cache right away.
|
|
24
|
+
// Calling setState during render is fine in this case, and preferred over a useEffect loop
|
|
25
|
+
// https://19.react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes
|
|
26
|
+
setCache([_getArrayProp(val, defaultVal), hash])
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return cachedVal
|
|
25
30
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {getTheme_v2} from '@sanity/ui/theme'
|
|
2
|
-
import {Children, cloneElement, forwardRef, isValidElement
|
|
2
|
+
import {Children, cloneElement, forwardRef, isValidElement} from 'react'
|
|
3
3
|
import {styled, css} from 'styled-components'
|
|
4
4
|
import {EMPTY_RECORD} from '../../constants'
|
|
5
5
|
import {useArrayProp} from '../../hooks'
|
|
@@ -65,10 +65,7 @@ export const AvatarStack = forwardRef(function AvatarStack(
|
|
|
65
65
|
size: sizeProp = 1,
|
|
66
66
|
...restProps
|
|
67
67
|
} = props
|
|
68
|
-
const children
|
|
69
|
-
() => Children.toArray(childrenProp).filter(isValidElement),
|
|
70
|
-
[childrenProp],
|
|
71
|
-
)
|
|
68
|
+
const children: React.ReactElement[] = Children.toArray(childrenProp).filter(isValidElement)
|
|
72
69
|
const maxLength = Math.max(maxLengthProp, 0)
|
|
73
70
|
const size = useArrayProp(sizeProp)
|
|
74
71
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {forwardRef,
|
|
1
|
+
import {forwardRef, useImperativeHandle, useMemo, useState} from 'react'
|
|
2
2
|
import {useElementSize} from '../../hooks'
|
|
3
3
|
import {useTheme_v2} from '../../theme'
|
|
4
4
|
import {findMaxBreakpoints, findMinBreakpoints} from './helpers'
|
|
@@ -21,31 +21,30 @@ export const ElementQuery = forwardRef(function ElementQuery(
|
|
|
21
21
|
forwardedRef: React.ForwardedRef<HTMLDivElement>,
|
|
22
22
|
) {
|
|
23
23
|
const theme = useTheme_v2()
|
|
24
|
-
const {children, media
|
|
24
|
+
const {children, media: _media, ...restProps} = props
|
|
25
|
+
const media = _media ?? theme.media
|
|
25
26
|
|
|
26
|
-
const ref = useRef<HTMLDivElement | null>(null)
|
|
27
27
|
const [element, setElement] = useState<HTMLDivElement | null>(null)
|
|
28
28
|
const elementSize = useElementSize(element)
|
|
29
29
|
const width = useMemo(() => elementSize?.border.width ?? window.innerWidth, [elementSize])
|
|
30
30
|
|
|
31
|
-
const max = useMemo(() =>
|
|
32
|
-
|
|
31
|
+
const max = useMemo(() => {
|
|
32
|
+
const eq = findMaxBreakpoints(media, width)
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
return eq.length ? eq.join(' ') : undefined
|
|
35
|
+
}, [media, width])
|
|
36
|
+
const min = useMemo(() => {
|
|
37
|
+
const eq = findMinBreakpoints(media, width)
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
return eq.length ? eq.join(' ') : undefined
|
|
40
|
+
}, [media, width])
|
|
41
|
+
|
|
42
|
+
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => element, [
|
|
43
|
+
element,
|
|
44
|
+
])
|
|
40
45
|
|
|
41
46
|
return (
|
|
42
|
-
<div
|
|
43
|
-
data-ui="ElementQuery"
|
|
44
|
-
{...restProps}
|
|
45
|
-
data-eq-max={max.length ? max.join(' ') : undefined}
|
|
46
|
-
data-eq-min={min.length ? min.join(' ') : undefined}
|
|
47
|
-
ref={setRef}
|
|
48
|
-
>
|
|
47
|
+
<div data-ui="ElementQuery" {...restProps} data-eq-max={max} data-eq-min={min} ref={setElement}>
|
|
49
48
|
{children}
|
|
50
49
|
</div>
|
|
51
50
|
)
|