@sanity/ui 4.0.0-static.30 → 4.0.0-static.32
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 +8 -1
- package/dist/index.js +1076 -510
- package/dist/index.js.map +1 -1
- package/package.json +10 -11
- package/src/core/components/autocomplete/Autocomplete.tsx +80 -48
- package/src/core/components/breadcrumbs/Breadcrumbs.tsx +74 -41
- package/src/core/components/dialog/DialogContext.ts +1 -1
- package/src/core/components/dialog/__workshop__/Panes.tsx +5 -21
- package/src/core/components/dialog/__workshop__/styles.css.ts +18 -0
- package/src/core/components/menu/Menu.test.tsx +2 -6
- package/src/core/components/menu/Menu.tsx +13 -14
- package/src/core/components/menu/MenuContext.ts +2 -3
- package/src/core/components/menu/MenuGroup.tsx +2 -0
- package/src/core/components/menu/useMenu.ts +2 -2
- package/src/core/components/menu/useMenuController.ts +5 -5
- package/src/core/components/toast/ToastContext.ts +1 -1
- package/src/core/components/tree/Tree.tsx +1 -0
- package/src/core/components/tree/TreeContext.ts +1 -1
- package/src/core/components/tree/TreeItem.tsx +17 -14
- package/src/core/components/virtualList/VirtualList.tsx +86 -44
- package/src/core/hooks/useGlobalKeyDown.ts +11 -4
- package/src/core/lib/createGlobalScopedContext.ts +2 -2
- package/src/core/primitives/avatar/Avatar.tsx +1 -0
- package/src/core/primitives/button/Button.tsx +2 -1
- package/src/core/primitives/button/__workshop__/SanityUploadButton.tsx +10 -25
- package/src/core/primitives/button/__workshop__/Styled1.tsx +2 -8
- package/src/core/primitives/button/__workshop__/index.ts +0 -5
- package/src/core/primitives/button/__workshop__/styles.css.ts +30 -0
- package/src/core/primitives/card/CardContext.ts +1 -1
- package/src/core/primitives/card/__workshop__/Styled.tsx +2 -5
- package/src/core/primitives/flex/__workshop__/Example.tsx +7 -15
- package/src/core/primitives/flex/__workshop__/styles.css.ts +12 -0
- package/src/core/primitives/inline/Inline.tsx +1 -0
- package/src/core/primitives/layer/LayerContext.ts +1 -1
- package/src/core/primitives/popover/Popover.tsx +146 -130
- package/src/core/primitives/popover/floating-ui/size.ts +17 -16
- package/src/core/primitives/skeleton/Skeleton.tsx +2 -2
- package/src/core/primitives/text/__workshop__/Colored.tsx +5 -10
- package/src/core/primitives/tooltip/Tooltip.tsx +69 -41
- package/src/core/primitives/tooltip/tooltipDelayGroup/TooltipDelayGroupContext.tsx +1 -1
- package/src/core/utils/boundaryElement/BoundaryElementContext.ts +1 -1
- package/src/core/utils/elementQuery/__workshop__/CustomMedia.tsx +3 -25
- package/src/core/utils/elementQuery/__workshop__/styles.css.ts +31 -0
- package/src/core/utils/portal/Portal.test.tsx +6 -6
- package/src/core/utils/portal/PortalContext.ts +1 -1
- package/src/core/utils/portal/PortalProvider.tsx +5 -37
- package/src/core/primitives/button/__workshop__/Styled2.tsx +0 -19
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
type ReactNode,
|
|
20
20
|
type Ref,
|
|
21
21
|
useCallback,
|
|
22
|
-
useEffect,
|
|
23
22
|
useImperativeHandle,
|
|
24
23
|
useMemo,
|
|
25
24
|
useRef,
|
|
@@ -166,10 +165,9 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
166
165
|
constrainSize = false,
|
|
167
166
|
content,
|
|
168
167
|
disabled,
|
|
169
|
-
fallbackPlacements
|
|
170
|
-
DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom'],
|
|
168
|
+
fallbackPlacements: _fallbackPlacements,
|
|
171
169
|
matchReferenceWidth,
|
|
172
|
-
floatingBoundary
|
|
170
|
+
floatingBoundary: _floatingBoundary,
|
|
173
171
|
modal,
|
|
174
172
|
onActivate,
|
|
175
173
|
open,
|
|
@@ -181,7 +179,7 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
181
179
|
preventOverflow = true,
|
|
182
180
|
radius = 3,
|
|
183
181
|
ref: forwardedRef,
|
|
184
|
-
referenceBoundary
|
|
182
|
+
referenceBoundary: _referenceBoundary,
|
|
185
183
|
referenceElement,
|
|
186
184
|
scheme,
|
|
187
185
|
shadow = 3,
|
|
@@ -191,6 +189,10 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
191
189
|
updateRef,
|
|
192
190
|
...rest
|
|
193
191
|
} = props as PopoverProps<typeof DEFAULT_POPOVER_ELEMENT>
|
|
192
|
+
const fallbackPlacements =
|
|
193
|
+
_fallbackPlacements ?? DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom']
|
|
194
|
+
const floatingBoundary = _floatingBoundary ?? boundaryElementContext.element
|
|
195
|
+
const referenceBoundary = _referenceBoundary ?? boundaryElementContext.element
|
|
194
196
|
|
|
195
197
|
const card = useCard()
|
|
196
198
|
|
|
@@ -206,108 +208,22 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
206
208
|
// Keep track of reference element width (see `size` middleware below)
|
|
207
209
|
const referenceWidthRef = useRef<number>(undefined)
|
|
208
210
|
|
|
209
|
-
const middleware =
|
|
210
|
-
const ret: Middleware[] = []
|
|
211
|
-
|
|
212
|
-
// Flip the floating element when leaving the boundary box
|
|
213
|
-
if (constrainSize || preventOverflow) {
|
|
214
|
-
if (placementStrategy === 'autoPlacement') {
|
|
215
|
-
ret.push(
|
|
216
|
-
autoPlacement({
|
|
217
|
-
allowedPlacements: [placementProp].concat(fallbackPlacements),
|
|
218
|
-
}),
|
|
219
|
-
)
|
|
220
|
-
} else {
|
|
221
|
-
ret.push(
|
|
222
|
-
flip({
|
|
223
|
-
boundary: floatingBoundary || undefined,
|
|
224
|
-
fallbackPlacements,
|
|
225
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
226
|
-
rootBoundary,
|
|
227
|
-
}),
|
|
228
|
-
)
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Define distance between reference and floating element
|
|
233
|
-
ret.push(offset({mainAxis: DEFAULT_POPOVER_DISTANCE}))
|
|
234
|
-
|
|
235
|
-
// Track sizes
|
|
236
|
-
if (constrainSize || matchReferenceWidth) {
|
|
237
|
-
ret.push(
|
|
238
|
-
size({
|
|
239
|
-
apply({availableWidth, availableHeight, elements, referenceWidth}) {
|
|
240
|
-
// not fresh, so use refs
|
|
241
|
-
|
|
242
|
-
referenceWidthRef.current = referenceWidth
|
|
243
|
-
|
|
244
|
-
if (matchReferenceWidth) {
|
|
245
|
-
elements.floating.style.width = `${referenceWidth}px`
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (constrainSize) {
|
|
249
|
-
elements.floating.style.maxWidth = `${availableWidth}px`
|
|
250
|
-
elements.floating.style.maxHeight = `${availableHeight}px`
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
boundaryElement: floatingBoundary || undefined,
|
|
254
|
-
constrainSize,
|
|
255
|
-
margins,
|
|
256
|
-
matchReferenceWidth,
|
|
257
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
258
|
-
}),
|
|
259
|
-
)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Shift the popover so its sits within the boundary element
|
|
263
|
-
if (preventOverflow) {
|
|
264
|
-
ret.push(
|
|
265
|
-
shift({
|
|
266
|
-
boundary: floatingBoundary || undefined,
|
|
267
|
-
rootBoundary,
|
|
268
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
269
|
-
}),
|
|
270
|
-
)
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Place arrow
|
|
274
|
-
if (arrowProp) {
|
|
275
|
-
ret.push(
|
|
276
|
-
arrow({
|
|
277
|
-
element: arrowRef,
|
|
278
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
279
|
-
}),
|
|
280
|
-
)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Determine the origin to scale from.
|
|
284
|
-
// Must be placed after `@sanity/ui/size` and `shift` middleware.
|
|
285
|
-
if (animate) {
|
|
286
|
-
ret.push(origin)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
ret.push(
|
|
290
|
-
hide({
|
|
291
|
-
boundary: referenceBoundary || undefined,
|
|
292
|
-
padding: DEFAULT_POPOVER_PADDING,
|
|
293
|
-
strategy: 'referenceHidden',
|
|
294
|
-
}),
|
|
295
|
-
)
|
|
296
|
-
|
|
297
|
-
return ret
|
|
298
|
-
}, [
|
|
211
|
+
const middleware = useMiddleware({
|
|
299
212
|
animate,
|
|
300
213
|
arrowProp,
|
|
214
|
+
arrowRef,
|
|
301
215
|
constrainSize,
|
|
302
216
|
fallbackPlacements,
|
|
303
217
|
floatingBoundary,
|
|
304
|
-
placementProp,
|
|
305
|
-
placementStrategy,
|
|
306
218
|
margins,
|
|
307
219
|
matchReferenceWidth,
|
|
220
|
+
placementProp,
|
|
221
|
+
placementStrategy,
|
|
308
222
|
preventOverflow,
|
|
309
223
|
referenceBoundary,
|
|
310
|
-
|
|
224
|
+
referenceWidthRef,
|
|
225
|
+
rootBoundary,
|
|
226
|
+
})
|
|
311
227
|
|
|
312
228
|
const {x, y, middlewareData, placement, refs, strategy, update} = useFloating({
|
|
313
229
|
middleware,
|
|
@@ -328,10 +244,6 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
328
244
|
const originX = middlewareData['@sanity/ui/origin']?.originX
|
|
329
245
|
const originY = middlewareData['@sanity/ui/origin']?.originY
|
|
330
246
|
|
|
331
|
-
const setArrow = useCallback((arrowEl: HTMLDivElement | null) => {
|
|
332
|
-
arrowRef.current = arrowEl
|
|
333
|
-
}, [])
|
|
334
|
-
|
|
335
247
|
const setFloating = useCallback(
|
|
336
248
|
(node: HTMLDivElement | null) => {
|
|
337
249
|
ref.current = node
|
|
@@ -340,22 +252,9 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
340
252
|
[refs],
|
|
341
253
|
)
|
|
342
254
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (!childProp) return
|
|
348
|
-
|
|
349
|
-
const childRef = getElementRef(childProp)
|
|
350
|
-
|
|
351
|
-
if (typeof childRef === 'function') {
|
|
352
|
-
childRef(node)
|
|
353
|
-
} else if (childRef) {
|
|
354
|
-
childRef.current = node
|
|
355
|
-
}
|
|
356
|
-
},
|
|
357
|
-
[childProp, refs],
|
|
358
|
-
)
|
|
255
|
+
// If there's a child then we need to set the reference element to the cloned child ref
|
|
256
|
+
// and if child changes we make sure to update or remove the reference element.
|
|
257
|
+
useImperativeHandle(childProp ? getElementRef(childProp) : null, () => refs.reference.current)
|
|
359
258
|
|
|
360
259
|
const child = useMemo(() => {
|
|
361
260
|
// If a reference element is defined, we don't need to clone the child
|
|
@@ -363,18 +262,10 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
363
262
|
|
|
364
263
|
if (!childProp) return null
|
|
365
264
|
|
|
366
|
-
return cloneElement(childProp, {ref: setReference})
|
|
367
|
-
}, [childProp, referenceElement, setReference])
|
|
265
|
+
return cloneElement(childProp, {ref: refs.setReference})
|
|
266
|
+
}, [childProp, referenceElement, refs.setReference])
|
|
368
267
|
|
|
369
|
-
|
|
370
|
-
if (updateRef) {
|
|
371
|
-
if (typeof updateRef === 'function') {
|
|
372
|
-
updateRef(update)
|
|
373
|
-
} else if (updateRef) {
|
|
374
|
-
updateRef.current = update
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}, [update, updateRef])
|
|
268
|
+
useImperativeHandle(updateRef, () => update, [update])
|
|
378
269
|
|
|
379
270
|
if (disabled) {
|
|
380
271
|
return childProp || <></>
|
|
@@ -391,7 +282,7 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
391
282
|
__unstable_margins={margins}
|
|
392
283
|
animate={animate}
|
|
393
284
|
arrow={arrowProp}
|
|
394
|
-
arrowRef={
|
|
285
|
+
arrowRef={arrowRef}
|
|
395
286
|
arrowX={arrowX}
|
|
396
287
|
arrowY={arrowY}
|
|
397
288
|
as={as}
|
|
@@ -440,3 +331,128 @@ export function Popover<E extends PopoverElementType = typeof DEFAULT_POPOVER_EL
|
|
|
440
331
|
</>
|
|
441
332
|
)
|
|
442
333
|
}
|
|
334
|
+
|
|
335
|
+
function useMiddleware({
|
|
336
|
+
animate,
|
|
337
|
+
arrowProp,
|
|
338
|
+
arrowRef,
|
|
339
|
+
constrainSize,
|
|
340
|
+
fallbackPlacements,
|
|
341
|
+
floatingBoundary,
|
|
342
|
+
margins,
|
|
343
|
+
matchReferenceWidth,
|
|
344
|
+
placementProp,
|
|
345
|
+
placementStrategy,
|
|
346
|
+
preventOverflow,
|
|
347
|
+
referenceBoundary,
|
|
348
|
+
referenceWidthRef,
|
|
349
|
+
rootBoundary,
|
|
350
|
+
}: {
|
|
351
|
+
animate: boolean
|
|
352
|
+
arrowProp: boolean
|
|
353
|
+
arrowRef: React.RefObject<HTMLDivElement | null>
|
|
354
|
+
constrainSize: boolean
|
|
355
|
+
fallbackPlacements: Placement[]
|
|
356
|
+
floatingBoundary: HTMLElement | null
|
|
357
|
+
margins: PopoverMargins
|
|
358
|
+
matchReferenceWidth: boolean | undefined
|
|
359
|
+
placementProp: Placement
|
|
360
|
+
placementStrategy: 'flip' | 'autoPlacement'
|
|
361
|
+
preventOverflow: boolean
|
|
362
|
+
referenceBoundary: HTMLElement | null
|
|
363
|
+
referenceWidthRef: React.RefObject<number | undefined>
|
|
364
|
+
rootBoundary: RootBoundary
|
|
365
|
+
}) {
|
|
366
|
+
return useMemo(() => {
|
|
367
|
+
const ret: Middleware[] = []
|
|
368
|
+
|
|
369
|
+
// Flip the floating element when leaving the boundary box
|
|
370
|
+
if (constrainSize || preventOverflow) {
|
|
371
|
+
if (placementStrategy === 'autoPlacement') {
|
|
372
|
+
ret.push(
|
|
373
|
+
autoPlacement({
|
|
374
|
+
allowedPlacements: [placementProp].concat(fallbackPlacements),
|
|
375
|
+
}),
|
|
376
|
+
)
|
|
377
|
+
} else {
|
|
378
|
+
ret.push(
|
|
379
|
+
flip({
|
|
380
|
+
boundary: floatingBoundary || undefined,
|
|
381
|
+
fallbackPlacements,
|
|
382
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
383
|
+
rootBoundary,
|
|
384
|
+
}),
|
|
385
|
+
)
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Define distance between reference and floating element
|
|
390
|
+
ret.push(offset({mainAxis: DEFAULT_POPOVER_DISTANCE}))
|
|
391
|
+
|
|
392
|
+
// Track sizes
|
|
393
|
+
if (constrainSize || matchReferenceWidth) {
|
|
394
|
+
ret.push(
|
|
395
|
+
size({
|
|
396
|
+
boundaryElement: floatingBoundary || undefined,
|
|
397
|
+
constrainSize,
|
|
398
|
+
margins,
|
|
399
|
+
matchReferenceWidth,
|
|
400
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
401
|
+
referenceWidthRef,
|
|
402
|
+
}),
|
|
403
|
+
)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Shift the popover so its sits within the boundary element
|
|
407
|
+
if (preventOverflow) {
|
|
408
|
+
ret.push(
|
|
409
|
+
shift({
|
|
410
|
+
boundary: floatingBoundary || undefined,
|
|
411
|
+
rootBoundary,
|
|
412
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
413
|
+
}),
|
|
414
|
+
)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Place arrow
|
|
418
|
+
if (arrowProp) {
|
|
419
|
+
ret.push(
|
|
420
|
+
arrow({
|
|
421
|
+
element: arrowRef,
|
|
422
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
423
|
+
}),
|
|
424
|
+
)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Determine the origin to scale from.
|
|
428
|
+
// Must be placed after `@sanity/ui/size` and `shift` middleware.
|
|
429
|
+
if (animate) {
|
|
430
|
+
ret.push(origin)
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
ret.push(
|
|
434
|
+
hide({
|
|
435
|
+
boundary: referenceBoundary || undefined,
|
|
436
|
+
padding: DEFAULT_POPOVER_PADDING,
|
|
437
|
+
strategy: 'referenceHidden',
|
|
438
|
+
}),
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
return ret
|
|
442
|
+
}, [
|
|
443
|
+
animate,
|
|
444
|
+
arrowProp,
|
|
445
|
+
arrowRef,
|
|
446
|
+
constrainSize,
|
|
447
|
+
fallbackPlacements,
|
|
448
|
+
floatingBoundary,
|
|
449
|
+
margins,
|
|
450
|
+
matchReferenceWidth,
|
|
451
|
+
placementProp,
|
|
452
|
+
placementStrategy,
|
|
453
|
+
preventOverflow,
|
|
454
|
+
referenceBoundary,
|
|
455
|
+
referenceWidthRef,
|
|
456
|
+
rootBoundary,
|
|
457
|
+
])
|
|
458
|
+
}
|
|
@@ -1,23 +1,16 @@
|
|
|
1
|
-
import {detectOverflow, type
|
|
1
|
+
import {detectOverflow, type Middleware} from '@floating-ui/react-dom'
|
|
2
2
|
|
|
3
3
|
import type {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
|
|
18
10
|
padding?: number
|
|
11
|
+
referenceWidthRef: React.RefObject<number | undefined>
|
|
19
12
|
}): Middleware {
|
|
20
|
-
const {
|
|
13
|
+
const {margins, padding = 0, constrainSize, matchReferenceWidth, referenceWidthRef} = options
|
|
21
14
|
|
|
22
15
|
return {
|
|
23
16
|
name: '@sanity/ui/size',
|
|
@@ -61,12 +54,20 @@ export function size(options: {
|
|
|
61
54
|
|
|
62
55
|
// IMPORTANT – APPLY ELEMENT STYLES HERE
|
|
63
56
|
// Elements need to be resized BEFORE the `platform.getDimensions` call below
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
57
|
+
const availableWidth = maxWidth - margins[1] - margins[3]
|
|
58
|
+
const availableHeight = maxHeight - margins[0] - margins[2]
|
|
59
|
+
const referenceWidth = reference.width - margins[1] - margins[3]
|
|
60
|
+
|
|
61
|
+
referenceWidthRef.current = referenceWidth
|
|
62
|
+
|
|
63
|
+
if (matchReferenceWidth) {
|
|
64
|
+
elements.floating.style.width = `${referenceWidth}px`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (constrainSize) {
|
|
68
|
+
elements.floating.style.maxWidth = `${availableWidth}px`
|
|
69
|
+
elements.floating.style.maxHeight = `${availableHeight}px`
|
|
70
|
+
}
|
|
70
71
|
|
|
71
72
|
const nextDimensions = await platform.getDimensions(elements.floating)
|
|
72
73
|
|
|
@@ -43,7 +43,7 @@ export function Skeleton<E extends SkeletonElementType = typeof DEFAULT_SKELETON
|
|
|
43
43
|
|
|
44
44
|
useEffect(() => {
|
|
45
45
|
if (!delay) {
|
|
46
|
-
return
|
|
46
|
+
return undefined
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
const timeout = setTimeout(() => {
|
|
@@ -64,7 +64,7 @@ export function Skeleton<E extends SkeletonElementType = typeof DEFAULT_SKELETON
|
|
|
64
64
|
...rest,
|
|
65
65
|
})}
|
|
66
66
|
data-animated={animated ? '' : undefined}
|
|
67
|
-
data-visible={visible ? '' : undefined}
|
|
67
|
+
data-visible={(delay ? visible : true) ? '' : undefined}
|
|
68
68
|
/>
|
|
69
69
|
)
|
|
70
70
|
}
|
|
@@ -2,29 +2,24 @@ import {Flex, Text} from '@sanity/ui'
|
|
|
2
2
|
import {vars} from '@sanity/ui/css'
|
|
3
3
|
import type {AvatarColor} from '@sanity/ui/theme'
|
|
4
4
|
import {useSelect} from '@sanity/ui-workshop'
|
|
5
|
-
import {
|
|
5
|
+
import {assignInlineVars} from '@vanilla-extract/dynamic'
|
|
6
6
|
|
|
7
7
|
import {WORKSHOP_AVATAR_COLOR_OPTIONS} from '$workshop'
|
|
8
8
|
|
|
9
|
-
const ColoredText = styled(Text)<{$color: AvatarColor}>`
|
|
10
|
-
${vars.color.fg.slice(4, -1)}: ${({$color}) => vars.color.avatar[$color].bg};
|
|
11
|
-
`
|
|
12
|
-
|
|
13
9
|
export default function ColoredTextStory(): React.JSX.Element {
|
|
14
10
|
// @ts-expect-error - TODO: fix this
|
|
15
|
-
const color = useSelect('Color', WORKSHOP_AVATAR_COLOR_OPTIONS, 'gray') ?? 'gray'
|
|
11
|
+
const color: AvatarColor = useSelect('Color', WORKSHOP_AVATAR_COLOR_OPTIONS, 'gray') ?? 'gray'
|
|
16
12
|
|
|
17
13
|
return (
|
|
18
14
|
<Flex align="center" height="fill" justify="center" padding={[4, 5, 6]} sizing="border">
|
|
19
|
-
<
|
|
15
|
+
<Text
|
|
20
16
|
align="center"
|
|
21
|
-
// @ts-expect-error - TODO: fix this
|
|
22
|
-
$color={color}
|
|
23
17
|
size={4}
|
|
24
18
|
weight="bold"
|
|
19
|
+
style={assignInlineVars({[vars.color.fg]: vars.color.avatar[color].bg})}
|
|
25
20
|
>
|
|
26
21
|
{color}
|
|
27
|
-
</
|
|
22
|
+
</Text>
|
|
28
23
|
</Flex>
|
|
29
24
|
)
|
|
30
25
|
}
|
|
@@ -112,14 +112,13 @@ export function Tooltip<E extends TooltipElementType = typeof DEFAULT_TOOLTIP_EL
|
|
|
112
112
|
animate: _animate = false,
|
|
113
113
|
arrow: arrowProp = false,
|
|
114
114
|
as = DEFAULT_TOOLTIP_ELEMENT,
|
|
115
|
-
boundaryElement
|
|
115
|
+
boundaryElement: _boundaryElement,
|
|
116
116
|
children: childProp,
|
|
117
117
|
className,
|
|
118
118
|
content,
|
|
119
119
|
delay,
|
|
120
120
|
disabled,
|
|
121
|
-
fallbackPlacements
|
|
122
|
-
DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom'],
|
|
121
|
+
fallbackPlacements: _fallbackPlacements,
|
|
123
122
|
padding = 2,
|
|
124
123
|
placement: placementProp = 'bottom',
|
|
125
124
|
portal: portalProp,
|
|
@@ -131,6 +130,9 @@ export function Tooltip<E extends TooltipElementType = typeof DEFAULT_TOOLTIP_EL
|
|
|
131
130
|
tone = 'inherit',
|
|
132
131
|
...rest
|
|
133
132
|
} = props as TooltipProps<typeof DEFAULT_TOOLTIP_ELEMENT>
|
|
133
|
+
const boundaryElement = _boundaryElement ?? boundaryElementContext?.element
|
|
134
|
+
const fallbackPlacements =
|
|
135
|
+
_fallbackPlacements ?? DEFAULT_FALLBACK_PLACEMENTS[props.placement ?? 'bottom']
|
|
134
136
|
|
|
135
137
|
const card = useCard()
|
|
136
138
|
const prefersReducedMotion = usePrefersReducedMotion()
|
|
@@ -147,44 +149,14 @@ export function Tooltip<E extends TooltipElementType = typeof DEFAULT_TOOLTIP_EL
|
|
|
147
149
|
const portalElement =
|
|
148
150
|
typeof portalProp === 'string' ? portal.elements?.[portalProp] || null : portal.element
|
|
149
151
|
|
|
150
|
-
const middleware =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
padding: DEFAULT_TOOLTIP_PADDING,
|
|
159
|
-
rootBoundary,
|
|
160
|
-
}),
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
// Define distance between reference and floating element
|
|
164
|
-
ret.push(offset({mainAxis: DEFAULT_TOOLTIP_DISTANCE}))
|
|
165
|
-
|
|
166
|
-
// Shift the tooltip so its sits with the boundary element
|
|
167
|
-
ret.push(
|
|
168
|
-
shift({
|
|
169
|
-
boundary: boundaryElement || undefined,
|
|
170
|
-
rootBoundary,
|
|
171
|
-
padding: DEFAULT_TOOLTIP_PADDING,
|
|
172
|
-
}),
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
// Place arrow
|
|
176
|
-
if (arrowProp) {
|
|
177
|
-
ret.push(arrow({element: arrowRef, padding: DEFAULT_TOOLTIP_PADDING}))
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Determine the origin to scale from.
|
|
181
|
-
// Must be placed after `@sanity/ui/size` and `shift` middleware.
|
|
182
|
-
if (animate) {
|
|
183
|
-
ret.push(origin)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return ret
|
|
187
|
-
}, [animate, arrowProp, boundaryElement, fallbackPlacements])
|
|
152
|
+
const middleware = useMiddleware({
|
|
153
|
+
animate,
|
|
154
|
+
arrowProp,
|
|
155
|
+
arrowRef,
|
|
156
|
+
boundaryElement,
|
|
157
|
+
fallbackPlacements,
|
|
158
|
+
rootBoundary,
|
|
159
|
+
})
|
|
188
160
|
|
|
189
161
|
const {floatingStyles, placement, middlewareData, refs, update} = useFloating({
|
|
190
162
|
middleware,
|
|
@@ -331,6 +303,7 @@ export function Tooltip<E extends TooltipElementType = typeof DEFAULT_TOOLTIP_EL
|
|
|
331
303
|
portalElement?.offsetWidth || document.body.offsetWidth,
|
|
332
304
|
]
|
|
333
305
|
|
|
306
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
334
307
|
setTooltipMaxWidth(Math.min(...availableWidths) - DEFAULT_TOOLTIP_PADDING * 2)
|
|
335
308
|
}, [boundaryElement, portalElement])
|
|
336
309
|
|
|
@@ -435,6 +408,61 @@ export function Tooltip<E extends TooltipElementType = typeof DEFAULT_TOOLTIP_EL
|
|
|
435
408
|
)
|
|
436
409
|
}
|
|
437
410
|
|
|
411
|
+
function useMiddleware({
|
|
412
|
+
animate,
|
|
413
|
+
arrowProp,
|
|
414
|
+
arrowRef,
|
|
415
|
+
boundaryElement,
|
|
416
|
+
fallbackPlacements,
|
|
417
|
+
rootBoundary,
|
|
418
|
+
}: {
|
|
419
|
+
animate: boolean
|
|
420
|
+
arrowProp: boolean
|
|
421
|
+
arrowRef: React.RefObject<HTMLDivElement | null>
|
|
422
|
+
boundaryElement: HTMLElement | null
|
|
423
|
+
fallbackPlacements: Placement[]
|
|
424
|
+
rootBoundary: RootBoundary
|
|
425
|
+
}) {
|
|
426
|
+
return useMemo(() => {
|
|
427
|
+
const ret: Middleware[] = []
|
|
428
|
+
|
|
429
|
+
// Flip the floating element when leaving the boundary box
|
|
430
|
+
ret.push(
|
|
431
|
+
flip({
|
|
432
|
+
boundary: boundaryElement || undefined,
|
|
433
|
+
fallbackPlacements,
|
|
434
|
+
padding: DEFAULT_TOOLTIP_PADDING,
|
|
435
|
+
rootBoundary,
|
|
436
|
+
}),
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
// Define distance between reference and floating element
|
|
440
|
+
ret.push(offset({mainAxis: DEFAULT_TOOLTIP_DISTANCE}))
|
|
441
|
+
|
|
442
|
+
// Shift the tooltip so its sits with the boundary element
|
|
443
|
+
ret.push(
|
|
444
|
+
shift({
|
|
445
|
+
boundary: boundaryElement || undefined,
|
|
446
|
+
rootBoundary,
|
|
447
|
+
padding: DEFAULT_TOOLTIP_PADDING,
|
|
448
|
+
}),
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
// Place arrow
|
|
452
|
+
if (arrowProp) {
|
|
453
|
+
ret.push(arrow({element: arrowRef, padding: DEFAULT_TOOLTIP_PADDING}))
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Determine the origin to scale from.
|
|
457
|
+
// Must be placed after `@sanity/ui/size` and `shift` middleware.
|
|
458
|
+
if (animate) {
|
|
459
|
+
ret.push(origin)
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return ret
|
|
463
|
+
}, [animate, arrowProp, arrowRef, boundaryElement, fallbackPlacements, rootBoundary])
|
|
464
|
+
}
|
|
465
|
+
|
|
438
466
|
/**
|
|
439
467
|
* As `useEffectEvent` should never be passed to other components or hooks, this custom hook groups together the `useEffectEvent` and the `useEffect` hook using it.
|
|
440
468
|
* @see https://19.dev/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events:~:text=Never%20pass%20them%20to%20other%20components%20or%20Hooks
|
|
@@ -8,6 +8,6 @@ import type {TooltipDelayGroupContextValue} from './types'
|
|
|
8
8
|
*/
|
|
9
9
|
export const TooltipDelayGroupContext: Context<TooltipDelayGroupContextValue | null> =
|
|
10
10
|
createGlobalScopedContext<TooltipDelayGroupContextValue | null>(
|
|
11
|
-
'@sanity/ui/
|
|
11
|
+
'@sanity/ui/v4/tooltipDelayGroup',
|
|
12
12
|
null,
|
|
13
13
|
)
|
|
@@ -5,6 +5,6 @@ import type {BoundaryElementContextValue} from './types'
|
|
|
5
5
|
|
|
6
6
|
export const BoundaryElementContext: Context<BoundaryElementContextValue | null> =
|
|
7
7
|
createGlobalScopedContext<BoundaryElementContextValue | null>(
|
|
8
|
-
'@sanity/ui/
|
|
8
|
+
'@sanity/ui/v4/boundaryElement',
|
|
9
9
|
null,
|
|
10
10
|
)
|
|
@@ -1,28 +1,6 @@
|
|
|
1
1
|
import {Box, Card, ElementQuery, Text} from '@sanity/ui'
|
|
2
|
-
import {vars} from '@sanity/ui/css'
|
|
3
|
-
import {styled} from 'styled-components'
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
[data-eq-min~='0'] > & {
|
|
7
|
-
${vars.color.fg.slice(4, -1)}: light-dark(${vars.color.palette.orange[600]}, ${vars.color
|
|
8
|
-
.palette.orange[400]});
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
[data-eq-min~='1'] > & {
|
|
12
|
-
${vars.color.fg.slice(4, -1)}: light-dark(${vars.color.palette.red[600]}, ${vars.color.palette
|
|
13
|
-
.red[400]});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
[data-eq-min~='2'] > & {
|
|
17
|
-
${vars.color.fg.slice(4, -1)}: light-dark(${vars.color.palette.magenta[600]}, ${vars.color
|
|
18
|
-
.palette.magenta[400]});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
[data-eq-min~='3'] > & {
|
|
22
|
-
${vars.color.fg.slice(4, -1)}: light-dark(${vars.color.palette.purple[600]}, ${vars.color
|
|
23
|
-
.palette.purple[400]});
|
|
24
|
-
}
|
|
25
|
-
`
|
|
3
|
+
import {testCard} from './styles.css'
|
|
26
4
|
|
|
27
5
|
export default function CustomMediaQuery(): React.JSX.Element {
|
|
28
6
|
return (
|
|
@@ -32,9 +10,9 @@ export default function CustomMediaQuery(): React.JSX.Element {
|
|
|
32
10
|
</Box>
|
|
33
11
|
|
|
34
12
|
<ElementQuery media={[0, 100, 200, 300]}>
|
|
35
|
-
<
|
|
13
|
+
<Card className={testCard} padding={3} shadow={1}>
|
|
36
14
|
<Text>This card sits inside an element query.</Text>
|
|
37
|
-
</
|
|
15
|
+
</Card>
|
|
38
16
|
</ElementQuery>
|
|
39
17
|
</Box>
|
|
40
18
|
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {vars} from '@sanity/ui/css'
|
|
2
|
+
import {style} from '@vanilla-extract/css'
|
|
3
|
+
|
|
4
|
+
export const testCard: string = style({
|
|
5
|
+
selectors: {
|
|
6
|
+
'[data-eq-min~="0"] > &': {
|
|
7
|
+
vars: {
|
|
8
|
+
[vars.color.fg]:
|
|
9
|
+
`light-dark(${vars.color.palette.orange[600]}, ${vars.color.palette.orange[400]})`,
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
'[data-eq-min~="1"] > &': {
|
|
13
|
+
vars: {
|
|
14
|
+
[vars.color.fg]:
|
|
15
|
+
`light-dark(${vars.color.palette.red[600]}, ${vars.color.palette.red[400]})`,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
'[data-eq-min~="2"] > &': {
|
|
19
|
+
vars: {
|
|
20
|
+
[vars.color.fg]:
|
|
21
|
+
`light-dark(${vars.color.palette.magenta[600]}, ${vars.color.palette.magenta[400]})`,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
'[data-eq-min~="3"] > &': {
|
|
25
|
+
vars: {
|
|
26
|
+
[vars.color.fg]:
|
|
27
|
+
`light-dark(${vars.color.palette.purple[600]}, ${vars.color.palette.purple[400]})`,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
})
|