@sanity/ui 2.6.2 → 2.6.4-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/index.d.mts +1 -3
- package/dist/index.d.ts +1 -3
- package/dist/index.esm.js +19 -21
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +18 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +33 -41
- package/src/core/components/menu/useMenuController.ts +1 -0
- package/src/core/components/toast/styles.ts +2 -1
- package/src/core/helpers/focus.ts +1 -0
- package/src/core/helpers/scroll.ts +1 -0
- package/src/core/hooks/useClickOutside.ts +3 -0
- package/src/core/hooks/useElementSize.ts +1 -0
- package/src/core/hooks/useMediaIndex/useMediaIndex.ts +1 -0
- package/src/core/hooks/usePrefersDark.ts +3 -0
- package/src/core/hooks/usePrefersReducedMotion.ts +2 -0
- package/src/core/primitives/tooltip/tooltip.tsx +26 -25
- package/src/core/utils/portal/portalProvider.tsx +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/ui",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.4-canary.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"sanity",
|
|
6
6
|
"ui",
|
|
@@ -51,32 +51,6 @@
|
|
|
51
51
|
"src",
|
|
52
52
|
"theme.js"
|
|
53
53
|
],
|
|
54
|
-
"scripts": {
|
|
55
|
-
"build": "run-s clean pkg:build pkg:check figma:pkg:build",
|
|
56
|
-
"clean": "rimraf .workshop dist",
|
|
57
|
-
"commit": "cz",
|
|
58
|
-
"cypress:dev": "run-p dev cypress:open",
|
|
59
|
-
"cypress:open": "cypress open",
|
|
60
|
-
"cypress:run": "cypress run",
|
|
61
|
-
"dev": "run-p storybook:dev workshop:dev",
|
|
62
|
-
"figma:pkg:build": "cd figma && pnpm build",
|
|
63
|
-
"format": "prettier --write --cache --ignore-unknown .",
|
|
64
|
-
"lint": "eslint . --ext .cjs,.js,.jsx,.mjs,.ts,.tsx",
|
|
65
|
-
"pkg:build": "pkg build --strict",
|
|
66
|
-
"pkg:check": "pkg --strict",
|
|
67
|
-
"prepare": "husky install",
|
|
68
|
-
"prepublishOnly": "pnpm build",
|
|
69
|
-
"release": "semantic-release",
|
|
70
|
-
"storybook:build": "storybook build",
|
|
71
|
-
"storybook:dev": "storybook dev -p 6006",
|
|
72
|
-
"test": "jest",
|
|
73
|
-
"test:browser": "start-server-and-test 'run-s workshop:build workshop:start' http://localhost:1337 'run-s cypress:run'",
|
|
74
|
-
"ts:check": "tsc",
|
|
75
|
-
"watch": "pkg watch --strict",
|
|
76
|
-
"workshop:build": "workshop build",
|
|
77
|
-
"workshop:dev": "workshop dev",
|
|
78
|
-
"workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist"
|
|
79
|
-
},
|
|
80
54
|
"commitlint": {
|
|
81
55
|
"extends": [
|
|
82
56
|
"@commitlint/config-conventional"
|
|
@@ -106,7 +80,7 @@
|
|
|
106
80
|
"dependencies": {
|
|
107
81
|
"@floating-ui/react-dom": "^2.1.1",
|
|
108
82
|
"@sanity/color": "^3.0.6",
|
|
109
|
-
"@sanity/icons": "^3.
|
|
83
|
+
"@sanity/icons": "^3.3.0",
|
|
110
84
|
"csstype": "^3.1.3",
|
|
111
85
|
"framer-motion": "11.0.8",
|
|
112
86
|
"react-refractor": "^2.2.0"
|
|
@@ -147,19 +121,19 @@
|
|
|
147
121
|
"@types/react-is": "^18.3.0",
|
|
148
122
|
"@types/refractor": "^3.4.1",
|
|
149
123
|
"@types/testing-library__jest-dom": "^5.14.9",
|
|
150
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
151
|
-
"@typescript-eslint/parser": "^7.
|
|
124
|
+
"@typescript-eslint/eslint-plugin": "^7.16.0",
|
|
125
|
+
"@typescript-eslint/parser": "^7.16.0",
|
|
152
126
|
"commitizen": "^4.3.0",
|
|
153
127
|
"cypress": "^13.11.0",
|
|
154
128
|
"cypress-real-events": "^1.12.0",
|
|
155
129
|
"cz-conventional-changelog": "^3.3.0",
|
|
156
130
|
"eslint": "^8.57.0",
|
|
157
131
|
"eslint-config-prettier": "^9.1.0",
|
|
158
|
-
"eslint-plugin-boundaries": "^4.2.
|
|
132
|
+
"eslint-plugin-boundaries": "^4.2.2",
|
|
159
133
|
"eslint-plugin-import": "^2.29.1",
|
|
160
|
-
"eslint-plugin-jsx-a11y": "^6.
|
|
134
|
+
"eslint-plugin-jsx-a11y": "^6.9.0",
|
|
161
135
|
"eslint-plugin-prettier": "^5.1.3",
|
|
162
|
-
"eslint-plugin-react": "^7.34.
|
|
136
|
+
"eslint-plugin-react": "^7.34.3",
|
|
163
137
|
"eslint-plugin-react-compiler": "0.0.0-experimental-a97cca1-20240529",
|
|
164
138
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
165
139
|
"eslint-plugin-storybook": "^0.8.0",
|
|
@@ -171,7 +145,7 @@
|
|
|
171
145
|
"lint-staged": "^14.0.1",
|
|
172
146
|
"module-alias": "^2.2.3",
|
|
173
147
|
"npm-run-all2": "^5.0.2",
|
|
174
|
-
"prettier": "^3.3.
|
|
148
|
+
"prettier": "^3.3.2",
|
|
175
149
|
"prettier-plugin-packagejson": "^2.5.0",
|
|
176
150
|
"react": "^18.3.1",
|
|
177
151
|
"react-dom": "^18.3.1",
|
|
@@ -183,7 +157,7 @@
|
|
|
183
157
|
"storybook": "^8.0.8",
|
|
184
158
|
"styled-components": "^6.1.11",
|
|
185
159
|
"tsconfig-paths": "^4.2.0",
|
|
186
|
-
"typescript": "5.
|
|
160
|
+
"typescript": "5.5.3",
|
|
187
161
|
"vite": "^5.2.13",
|
|
188
162
|
"vite-tsconfig-paths": "^4.3.2"
|
|
189
163
|
},
|
|
@@ -193,7 +167,6 @@
|
|
|
193
167
|
"react-is": "^18",
|
|
194
168
|
"styled-components": "^5.2 || ^6"
|
|
195
169
|
},
|
|
196
|
-
"packageManager": "pnpm@9.2.0",
|
|
197
170
|
"engines": {
|
|
198
171
|
"node": ">=14.0.0"
|
|
199
172
|
},
|
|
@@ -203,9 +176,28 @@
|
|
|
203
176
|
"esm.sh": {
|
|
204
177
|
"bundle": false
|
|
205
178
|
},
|
|
206
|
-
"
|
|
207
|
-
"
|
|
208
|
-
|
|
209
|
-
|
|
179
|
+
"scripts": {
|
|
180
|
+
"build": "run-s clean pkg:build pkg:check figma:pkg:build",
|
|
181
|
+
"clean": "rimraf .workshop dist",
|
|
182
|
+
"commit": "cz",
|
|
183
|
+
"cypress:dev": "run-p dev cypress:open",
|
|
184
|
+
"cypress:open": "cypress open",
|
|
185
|
+
"cypress:run": "cypress run",
|
|
186
|
+
"dev": "run-p storybook:dev workshop:dev",
|
|
187
|
+
"figma:pkg:build": "cd figma && pnpm build",
|
|
188
|
+
"format": "prettier --write --cache --ignore-unknown .",
|
|
189
|
+
"lint": "eslint . --ext .cjs,.js,.jsx,.mjs,.ts,.tsx",
|
|
190
|
+
"pkg:build": "pkg build --strict",
|
|
191
|
+
"pkg:check": "pkg --strict",
|
|
192
|
+
"release": "semantic-release",
|
|
193
|
+
"storybook:build": "storybook build",
|
|
194
|
+
"storybook:dev": "storybook dev -p 6006",
|
|
195
|
+
"test": "jest",
|
|
196
|
+
"test:browser": "start-server-and-test 'run-s workshop:build workshop:start' http://localhost:1337 'run-s cypress:run'",
|
|
197
|
+
"ts:check": "tsc",
|
|
198
|
+
"watch": "pkg watch --strict",
|
|
199
|
+
"workshop:build": "workshop build",
|
|
200
|
+
"workshop:dev": "workshop dev",
|
|
201
|
+
"workshop:start": "http-server -a localhost -c-0 -p 1337 -s -P http://localhost:1337/index.html? dist"
|
|
210
202
|
}
|
|
211
|
-
}
|
|
203
|
+
}
|
|
@@ -183,6 +183,7 @@ export function useMenuController(props: {
|
|
|
183
183
|
}, [setActiveIndex, rootElement])
|
|
184
184
|
|
|
185
185
|
// Set focus on the currently active element
|
|
186
|
+
// @TODO verify if this is the best way, compare with adobe-spectrum
|
|
186
187
|
useEffect(() => {
|
|
187
188
|
if (!mounted) return
|
|
188
189
|
|
|
@@ -14,11 +14,12 @@ const loadingAnimation = keyframes`
|
|
|
14
14
|
}
|
|
15
15
|
100% {
|
|
16
16
|
width: 100%;
|
|
17
|
-
}
|
|
17
|
+
}
|
|
18
18
|
`
|
|
19
19
|
|
|
20
20
|
const LOADING_BAR_HEIGHT = 2
|
|
21
21
|
|
|
22
|
+
// @TODO get rid of $duration modifier, set data attribute instead and use stable selector
|
|
22
23
|
export function rootStyles(
|
|
23
24
|
props: {$duration?: number; tone: ThemeColorStateToneKey} & ThemeProps,
|
|
24
25
|
): ReturnType<typeof css> {
|
|
@@ -88,6 +88,9 @@ export function useClickOutside(
|
|
|
88
88
|
listener(evt)
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// @TODO seems expensive, improve with useEffectEvent? The identity of boundaryElement, elements and listener probably shouldn't trigger resub
|
|
92
|
+
// or maybe it's enough to put listener and elements etc in refs?
|
|
93
|
+
|
|
91
94
|
window.addEventListener('mousedown', handleWindowMouseDown)
|
|
92
95
|
|
|
93
96
|
return () => {
|
|
@@ -6,6 +6,7 @@ import {ElementSize, _elementSizeObserver} from '../observers/elementSizeObserve
|
|
|
6
6
|
* @beta
|
|
7
7
|
*/
|
|
8
8
|
export function useElementSize(element: HTMLElement | null): ElementSize | null {
|
|
9
|
+
// @TODO we can probably use something in framer-motion or @floating-ui instead of rolling our own
|
|
9
10
|
const [size, setSize] = useState<ElementSize | null>(null)
|
|
10
11
|
|
|
11
12
|
useEffect(() => {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {useSyncExternalStore} from 'react'
|
|
2
2
|
|
|
3
|
+
// @TODO is it really necessary to cache this way?
|
|
4
|
+
// also, what about providing a server snapshot pattern?
|
|
5
|
+
// that implements the trick vision-on-demand uses?
|
|
3
6
|
let MEDIA_QUERY_CACHE: MediaQueryList | undefined
|
|
4
7
|
|
|
5
8
|
/**
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {useSyncExternalStore} from 'react'
|
|
2
2
|
|
|
3
|
+
// @TODO is the cache here really beneficial? Maybe it's better to use useMemo?
|
|
4
|
+
// And how about supplying a server snapshot pattern so userland can implement headers for SSR like vision-on-demand?
|
|
3
5
|
let MEDIA_QUERY_CACHE: MediaQueryList | undefined
|
|
4
6
|
|
|
5
7
|
/**
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
flip,
|
|
6
6
|
offset,
|
|
7
7
|
shift,
|
|
8
|
+
size,
|
|
8
9
|
useFloating,
|
|
9
10
|
type Middleware,
|
|
10
11
|
type RootBoundary,
|
|
@@ -20,7 +21,6 @@ import {
|
|
|
20
21
|
useRef,
|
|
21
22
|
useState,
|
|
22
23
|
useId,
|
|
23
|
-
useSyncExternalStore,
|
|
24
24
|
useImperativeHandle,
|
|
25
25
|
} from 'react'
|
|
26
26
|
import {styled} from 'styled-components'
|
|
@@ -85,9 +85,8 @@ export interface TooltipProps extends Omit<LayerProps, 'as'> {
|
|
|
85
85
|
animate?: boolean
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
const Root = styled(Layer)
|
|
88
|
+
const Root = styled(Layer)`
|
|
89
89
|
pointer-events: none;
|
|
90
|
-
max-width: ${({$maxWidth}) => $maxWidth}px;
|
|
91
90
|
`
|
|
92
91
|
|
|
93
92
|
/**
|
|
@@ -134,27 +133,31 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
134
133
|
const portalElement =
|
|
135
134
|
typeof portalProp === 'string' ? portal.elements?.[portalProp] || null : portal.element
|
|
136
135
|
|
|
137
|
-
const documentBodyOffsetWidth = useSyncExternalStore(
|
|
138
|
-
emptySubscribe,
|
|
139
|
-
() => document.body.offsetWidth,
|
|
140
|
-
// We don't actually know what the width of the body is during SSR, so we'll just assume it's 800px or larger
|
|
141
|
-
() => 800,
|
|
142
|
-
)
|
|
143
|
-
// Get the maximum tooltip width (sans tooltip padding)
|
|
144
|
-
// Tooltip width should never exceed the width of either any supplied boundary or portal element.
|
|
145
|
-
// If both portal and boundary elements are provided, use the smaller width of the two.
|
|
146
|
-
const tooltipWidth = useMemo(() => {
|
|
147
|
-
const availableWidths = [
|
|
148
|
-
...(boundaryElement ? [boundaryElement.offsetWidth] : []),
|
|
149
|
-
portalElement?.offsetWidth || documentBodyOffsetWidth,
|
|
150
|
-
]
|
|
151
|
-
|
|
152
|
-
return Math.min(...availableWidths) - DEFAULT_TOOLTIP_PADDING * 2
|
|
153
|
-
}, [boundaryElement, documentBodyOffsetWidth, portalElement?.offsetWidth])
|
|
154
|
-
|
|
155
136
|
const middleware = useMemo(() => {
|
|
156
137
|
const ret: Middleware[] = []
|
|
157
138
|
|
|
139
|
+
// Set the max width of the tooltip based on boundaries and portals
|
|
140
|
+
ret.push(
|
|
141
|
+
size({
|
|
142
|
+
apply({elements}) {
|
|
143
|
+
// Get the maximum tooltip width (sans tooltip padding)
|
|
144
|
+
// Tooltip width should never exceed the width of either any supplied boundary or portal element.
|
|
145
|
+
// If both portal and boundary elements are provided, use the smaller width of the two.
|
|
146
|
+
const availableWidths = [
|
|
147
|
+
...(boundaryElement ? [boundaryElement.offsetWidth] : []),
|
|
148
|
+
portalElement?.offsetWidth || document.body.offsetWidth,
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
const tooltipWidth = Math.min(...availableWidths) - DEFAULT_TOOLTIP_PADDING * 2
|
|
152
|
+
|
|
153
|
+
// Set the max width directly, efficiently, without another react effect + render loop
|
|
154
|
+
Object.assign(elements.floating.style, {
|
|
155
|
+
maxWidth: tooltipWidth > 0 ? `${tooltipWidth}px` : undefined,
|
|
156
|
+
})
|
|
157
|
+
},
|
|
158
|
+
}),
|
|
159
|
+
)
|
|
160
|
+
|
|
158
161
|
// Flip the floating element when leaving the boundary box
|
|
159
162
|
ret.push(
|
|
160
163
|
flip({
|
|
@@ -189,7 +192,7 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
189
192
|
}
|
|
190
193
|
|
|
191
194
|
return ret
|
|
192
|
-
}, [animate, arrowProp, boundaryElement, fallbackPlacements])
|
|
195
|
+
}, [animate, arrowProp, boundaryElement, fallbackPlacements, portalElement])
|
|
193
196
|
|
|
194
197
|
const {floatingStyles, placement, middlewareData, refs, update} = useFloating({
|
|
195
198
|
middleware,
|
|
@@ -288,6 +291,7 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
288
291
|
// Detect whether the mouse is moving outside of the reference element. This is sometimes
|
|
289
292
|
// necessary, because the tooltip might not always close as it should (e.g. when clicking
|
|
290
293
|
// the reference element triggers a CPU-heavy operation.)
|
|
294
|
+
// @TODO is this necessary?
|
|
291
295
|
useEffect(() => {
|
|
292
296
|
if (!showTooltip) return
|
|
293
297
|
|
|
@@ -404,7 +408,6 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
404
408
|
ref={setFloating}
|
|
405
409
|
style={floatingStyles}
|
|
406
410
|
zOffset={zOffset}
|
|
407
|
-
$maxWidth={tooltipWidth}
|
|
408
411
|
>
|
|
409
412
|
<TooltipCard
|
|
410
413
|
{...restProps}
|
|
@@ -453,5 +456,3 @@ export const Tooltip = forwardRef(function Tooltip(
|
|
|
453
456
|
</>
|
|
454
457
|
)
|
|
455
458
|
})
|
|
456
|
-
|
|
457
|
-
const emptySubscribe = () => () => {}
|
|
@@ -25,6 +25,7 @@ export interface PortalProviderProps {
|
|
|
25
25
|
export function PortalProvider(props: PortalProviderProps): React.ReactElement {
|
|
26
26
|
const {boundaryElement, children, element, __unstable_elements: elementsProp} = props
|
|
27
27
|
const elements = useUnique(elementsProp)
|
|
28
|
+
// @TODO check up sebmarkbage tweet on useSyncExternalStore that detects if it was hydrated instead of skipping getServerSnapshot
|
|
28
29
|
const fallbackElement = useSyncExternalStore(
|
|
29
30
|
emptySubscribe,
|
|
30
31
|
() => document.body,
|