@sanity/ui 3.0.0-static.10 → 3.0.0-static.12

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.
Files changed (275) hide show
  1. package/dist/_chunks-cjs/_visual-editing.js +1300 -1269
  2. package/dist/_chunks-cjs/_visual-editing.js.map +1 -1
  3. package/dist/_chunks-cjs/buildCommand.js +28 -10
  4. package/dist/_chunks-cjs/buildCommand.js.map +1 -1
  5. package/dist/_chunks-es/_visual-editing.mjs +1298 -1263
  6. package/dist/_chunks-es/_visual-editing.mjs.map +1 -1
  7. package/dist/_visual-editing.d.mts +516 -360
  8. package/dist/_visual-editing.d.ts +516 -360
  9. package/dist/cli.js +1 -1
  10. package/dist/css.d.mts +258 -75
  11. package/dist/css.d.ts +258 -75
  12. package/dist/css.js +746 -752
  13. package/dist/css.js.map +1 -1
  14. package/dist/css.mjs +748 -754
  15. package/dist/css.mjs.map +1 -1
  16. package/dist/index.d.mts +1342 -871
  17. package/dist/index.d.ts +1342 -871
  18. package/dist/index.js +433 -325
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs +429 -321
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/sanity-palette.css +105 -1
  23. package/dist/sanity-palette.min.css +1 -0
  24. package/dist/sanity-theme.css +4571 -1
  25. package/dist/sanity-theme.min.css +1 -0
  26. package/dist/system.css +22053 -21710
  27. package/dist/system.min.css +1 -0
  28. package/dist/theme.d.mts +51 -106
  29. package/dist/theme.d.ts +51 -106
  30. package/dist/theme.js +19 -20
  31. package/dist/theme.js.map +1 -1
  32. package/dist/theme.mjs +19 -20
  33. package/dist/theme.mjs.map +1 -1
  34. package/package.json +10 -5
  35. package/src/cli/buildCommand.ts +46 -19
  36. package/src/css/_comp.ts +2 -2
  37. package/src/css/{compile/compileStyle.ts → _compileStyle.ts} +7 -7
  38. package/src/css/_resp.ts +0 -1
  39. package/src/css/{system.style.ts → _system.style.ts} +3 -2
  40. package/src/css/aspects/display/display.ts +1 -0
  41. package/src/css/aspects/display/types.ts +2 -3
  42. package/src/css/aspects/flex/types.ts +4 -12
  43. package/src/css/aspects/flexItem/types.ts +1 -3
  44. package/src/css/aspects/font/font.style.ts +7 -66
  45. package/src/css/aspects/font/types.ts +1 -3
  46. package/src/css/aspects/grid/grid.ts +1 -0
  47. package/src/css/aspects/grid/types.ts +5 -9
  48. package/src/css/aspects/gridItem/gridItem.ts +1 -1
  49. package/src/css/aspects/gridItem/types.ts +7 -18
  50. package/src/css/aspects/height/height.ts +3 -4
  51. package/src/css/aspects/inset/inset.ts +1 -0
  52. package/src/css/aspects/margin/margin.ts +1 -0
  53. package/src/css/aspects/margin/types.ts +1 -0
  54. package/src/css/aspects/maxWidth/maxWidth.ts +1 -0
  55. package/src/css/aspects/maxWidth/types.ts +1 -0
  56. package/src/css/aspects/minWidth/minWidth.ts +1 -0
  57. package/src/css/aspects/minWidth/types.ts +2 -0
  58. package/src/css/aspects/overflow/overflow.ts +1 -0
  59. package/src/css/aspects/padding/padding.ts +1 -0
  60. package/src/css/aspects/pointerEvents/pointerEvents.ts +1 -0
  61. package/src/css/aspects/position/position.ts +1 -0
  62. package/src/css/aspects/shadow/shadow.style.ts +16 -41
  63. package/src/css/aspects/shadow/shadow.ts +1 -0
  64. package/src/css/aspects/textOverflow/textOverflow.ts +1 -0
  65. package/src/css/aspects/textOverflow/types.ts +1 -0
  66. package/src/css/aspects/width/types.ts +2 -0
  67. package/src/css/aspects/width/width.ts +1 -0
  68. package/src/css/compilePalette.ts +32 -0
  69. package/src/css/compileSystem.ts +7 -0
  70. package/src/css/{compile/compileTheme.ts → compileTheme.ts} +1 -0
  71. package/src/css/compileTheme_v3.ts +434 -0
  72. package/src/css/components/breadcrumbs/breadcrumbs.ts +1 -0
  73. package/src/css/components/dialog/dialog.ts +7 -0
  74. package/src/css/components/menu/menu.ts +2 -0
  75. package/src/css/components/skeleton/skeleton.style.ts +8 -4
  76. package/src/css/components/skeleton/skeleton.ts +4 -0
  77. package/src/css/components/skeleton/types.ts +4 -0
  78. package/src/css/components/toast/toast.ts +5 -0
  79. package/src/css/components/tree/tree.ts +1 -0
  80. package/src/css/composeClassNames.ts +4 -2
  81. package/src/css/constants.ts +11 -0
  82. package/src/css/index.ts +4 -3
  83. package/src/css/primitives/_arrow/_arrow.style.ts +6 -8
  84. package/src/css/primitives/_arrow/_arrow.ts +7 -0
  85. package/src/css/primitives/_input/input.ts +2 -0
  86. package/src/css/primitives/_selectable/_selectable.style.ts +24 -25
  87. package/src/css/primitives/_selectable/selectable.ts +1 -2
  88. package/src/css/primitives/avatar/avatar.style.ts +5 -8
  89. package/src/css/primitives/avatar/avatar.ts +6 -0
  90. package/src/css/primitives/avatar/types.ts +1 -0
  91. package/src/css/primitives/box/types.ts +1 -3
  92. package/src/css/primitives/button/button.style.ts +48 -15
  93. package/src/css/primitives/button/button.ts +4 -21
  94. package/src/css/primitives/button/index.ts +1 -0
  95. package/src/css/primitives/button/types.ts +18 -0
  96. package/src/css/primitives/card/card.style.ts +4 -7
  97. package/src/css/primitives/card/card.ts +2 -2
  98. package/src/css/primitives/card/types.ts +2 -2
  99. package/src/css/primitives/checkbox/checkbox.ts +2 -0
  100. package/src/css/primitives/container/container.ts +1 -0
  101. package/src/css/primitives/container/types.ts +1 -0
  102. package/src/css/primitives/kbd/kbd.ts +1 -0
  103. package/src/css/primitives/label/types.ts +7 -2
  104. package/src/css/primitives/popover/popover.ts +2 -0
  105. package/src/css/primitives/radio/radio.ts +1 -0
  106. package/src/css/primitives/select/select.ts +2 -0
  107. package/src/css/primitives/spinner/spinner.ts +2 -0
  108. package/src/css/primitives/switch/switch.ts +5 -0
  109. package/src/css/primitives/text/types.ts +4 -0
  110. package/src/css/primitives/textArea/textArea.ts +1 -0
  111. package/src/css/primitives/textInput/textInput.ts +1 -0
  112. package/src/css/primitives/token/token.style.ts +37 -36
  113. package/src/css/primitives/tooltip/tooltip.ts +2 -0
  114. package/src/css/responsiveRules.ts +12 -19
  115. package/src/css/scopeClassName.ts +1 -0
  116. package/src/css/types.ts +115 -15
  117. package/src/css/util.ts +5 -0
  118. package/src/css/utils/srOnly/srOnly.ts +1 -0
  119. package/src/css/varNames.ts +230 -143
  120. package/src/css/vars.ts +53 -22
  121. package/src/theme/palette/constants.ts +2 -0
  122. package/src/theme/palette/types.ts +3 -0
  123. package/src/theme/types.ts +2 -6
  124. package/src/theme/v0/focusRing.ts +1 -3
  125. package/src/theme/v0/font.ts +6 -18
  126. package/src/theme/v0/layer.ts +1 -3
  127. package/src/theme/v0/shadow.ts +2 -6
  128. package/src/theme/v2/avatar.ts +1 -3
  129. package/src/theme/v2/color/_system.ts +1 -3
  130. package/src/theme/v2/color/avatar.ts +2 -6
  131. package/src/theme/v2/color/badge.ts +2 -6
  132. package/src/theme/v2/color/button.ts +3 -9
  133. package/src/theme/v2/color/color.ts +3 -9
  134. package/src/theme/v2/color/input.ts +3 -9
  135. package/src/theme/v2/color/kbd.ts +1 -3
  136. package/src/theme/v2/color/selectable.ts +2 -6
  137. package/src/theme/v2/color/state.ts +1 -3
  138. package/src/theme/v2/color/syntax.ts +1 -3
  139. package/src/theme/v2/input.ts +1 -3
  140. package/src/theme/v2/theme.ts +2 -6
  141. package/src/theme/v3/buildTheme_v3.ts +2 -1
  142. package/src/theme/v3/color/color.ts +6 -4
  143. package/src/theme/v3/color/renderColor.ts +4 -1
  144. package/src/theme/v3/{defaults.ts → defaultTokens.ts} +2 -2
  145. package/src/theme/v3/index.ts +1 -1
  146. package/src/theme/v3/resolveTokens.ts +18 -18
  147. package/src/ui/RootClassNames.tsx +44 -0
  148. package/src/ui/StyleTags.tsx +3 -1
  149. package/src/ui/_compat/helpers.ts +72 -0
  150. package/src/ui/_compat/index.ts +2 -6
  151. package/src/ui/_compat/studioTheme.ts +7 -0
  152. package/src/ui/_compat/theme/themeColorProvider.tsx +2 -6
  153. package/src/ui/_compat/theme/themeProvider.tsx +2 -6
  154. package/src/ui/_compat/theme/types.ts +1 -3
  155. package/src/ui/_compat/theme/useRootTheme.ts +1 -3
  156. package/src/ui/_compat/theme/useTheme.ts +2 -6
  157. package/src/ui/_compat/types.ts +0 -83
  158. package/src/ui/components/autocomplete/__workshop__/constrainedHeight.tsx +2 -2
  159. package/src/ui/components/autocomplete/autocomplete.tsx +86 -114
  160. package/src/ui/components/autocomplete/autocompleteOption.tsx +2 -0
  161. package/src/ui/components/autocomplete/types.ts +3 -8
  162. package/src/ui/components/breadcrumbs/breadcrumbs.tsx +27 -21
  163. package/src/ui/components/dialog/dialog.tsx +89 -291
  164. package/src/ui/components/dialog/dialogCard.tsx +183 -0
  165. package/src/ui/components/dialog/isTargetWithinScope.ts +14 -0
  166. package/src/ui/components/hotkeys/hotkeys.tsx +33 -15
  167. package/src/ui/components/menu/__workshop__/asComponent.tsx +6 -6
  168. package/src/ui/components/menu/menu.tsx +27 -33
  169. package/src/ui/components/menu/menuButton.tsx +10 -14
  170. package/src/ui/components/menu/menuDivider.tsx +25 -13
  171. package/src/ui/components/menu/menuGroup.tsx +34 -26
  172. package/src/ui/components/menu/menuItem.tsx +51 -40
  173. package/src/ui/components/skeleton/codeSkeleton.tsx +53 -0
  174. package/src/ui/components/skeleton/headingSkeleton.tsx +52 -0
  175. package/src/ui/components/skeleton/index.ts +3 -0
  176. package/src/ui/components/skeleton/labelSkeleton.tsx +51 -0
  177. package/src/ui/components/skeleton/skeleton.tsx +39 -16
  178. package/src/ui/components/skeleton/textSkeleton.tsx +31 -110
  179. package/src/ui/components/tab/tab.tsx +23 -19
  180. package/src/ui/components/tab/tabList.tsx +34 -33
  181. package/src/ui/components/tab/tabPanel.tsx +25 -19
  182. package/src/ui/components/toast/toast.tsx +21 -16
  183. package/src/ui/components/toast/toastLayer.tsx +28 -10
  184. package/src/ui/components/toast/toastProvider.tsx +2 -6
  185. package/src/ui/components/toast/types.ts +2 -6
  186. package/src/ui/components/toast/useToast.ts +1 -3
  187. package/src/ui/components/tree/tree.tsx +194 -187
  188. package/src/ui/components/tree/treeGroup.tsx +25 -5
  189. package/src/ui/components/tree/treeItem.tsx +35 -23
  190. package/src/ui/hooks/useClickOutside.ts +2 -6
  191. package/src/ui/hooks/useClickOutsideEvent.ts +3 -9
  192. package/src/ui/index.ts +1 -0
  193. package/src/ui/primitives/_selectable/selectable.tsx +33 -20
  194. package/src/ui/primitives/avatar/avatar.tsx +28 -31
  195. package/src/ui/primitives/avatar/avatarCounter.tsx +33 -25
  196. package/src/ui/primitives/avatar/avatarStack.tsx +31 -24
  197. package/src/ui/primitives/avatar/types.ts +2 -0
  198. package/src/ui/primitives/badge/__workshop__/props.tsx +1 -9
  199. package/src/ui/primitives/badge/__workshop__/tones.tsx +1 -6
  200. package/src/ui/primitives/badge/badge.tsx +33 -32
  201. package/src/ui/primitives/badge/types.ts +2 -1
  202. package/src/ui/primitives/box/box.tsx +59 -29
  203. package/src/ui/primitives/button/__workshop__/sanityUploadButton.tsx +3 -3
  204. package/src/ui/primitives/button/__workshop__/uploadButton.tsx +2 -1
  205. package/src/ui/primitives/button/button.test.tsx +1 -15
  206. package/src/ui/primitives/button/button.tsx +63 -70
  207. package/src/ui/primitives/card/__workshop__/asComponent.tsx +3 -3
  208. package/src/ui/primitives/card/card.tsx +22 -22
  209. package/src/ui/primitives/card/cardProvider.tsx +2 -0
  210. package/src/ui/primitives/checkbox/checkbox.tsx +26 -15
  211. package/src/ui/primitives/code/code.tsx +24 -22
  212. package/src/ui/primitives/container/container.tsx +26 -15
  213. package/src/ui/primitives/flex/flex.tsx +21 -19
  214. package/src/ui/primitives/grid/grid.tsx +21 -16
  215. package/src/ui/primitives/heading/heading.tsx +42 -19
  216. package/src/ui/primitives/inline/inline.tsx +26 -23
  217. package/src/ui/primitives/kbd/kbd.tsx +25 -23
  218. package/src/ui/primitives/label/label.tsx +29 -26
  219. package/src/ui/primitives/popover/popover.tsx +293 -271
  220. package/src/ui/primitives/popover/popoverCard.tsx +122 -120
  221. package/src/ui/primitives/radio/radio.tsx +30 -14
  222. package/src/ui/primitives/select/select.tsx +24 -16
  223. package/src/ui/primitives/spinner/animatedSpinnerIcon.tsx +4 -2
  224. package/src/ui/primitives/spinner/spinner.tsx +24 -12
  225. package/src/ui/primitives/stack/stack.tsx +27 -18
  226. package/src/ui/primitives/switch/switch.tsx +31 -14
  227. package/src/ui/primitives/text/text.tsx +30 -24
  228. package/src/ui/primitives/textArea/textArea.tsx +33 -18
  229. package/src/ui/primitives/textInput/textInput.tsx +28 -40
  230. package/src/ui/primitives/tooltip/constants.ts +1 -1
  231. package/src/ui/primitives/tooltip/tooltip.tsx +85 -61
  232. package/src/ui/primitives/tooltip/tooltipCard.tsx +89 -82
  233. package/src/ui/primitives/types.ts +1 -3
  234. package/src/ui/types/avatar.ts +3 -6
  235. package/src/ui/types/badge.ts +1 -3
  236. package/src/ui/types/button.ts +1 -3
  237. package/src/ui/types/card.ts +1 -3
  238. package/src/ui/types/dialog.ts +1 -3
  239. package/src/ui/types/props.ts +20 -10
  240. package/src/ui/utils/arrow/arrow.tsx +43 -25
  241. package/src/ui/utils/boundaryElement/boundaryElementProvider.tsx +2 -6
  242. package/src/ui/utils/boundaryElement/types.ts +1 -3
  243. package/src/ui/utils/boundaryElement/useBoundaryElement.ts +1 -3
  244. package/src/ui/utils/elementQuery/elementQuery.tsx +43 -19
  245. package/src/ui/utils/errorBoundary.tsx +2 -0
  246. package/src/ui/utils/index.ts +0 -1
  247. package/src/ui/utils/layer/layer.tsx +23 -93
  248. package/src/ui/utils/layer/layerCard.tsx +92 -0
  249. package/src/ui/utils/layer/layerProvider.tsx +2 -6
  250. package/src/ui/utils/layer/useLayer.ts +1 -3
  251. package/src/ui/utils/portal/portal.ts +2 -6
  252. package/src/ui/utils/portal/portalProvider.tsx +2 -6
  253. package/src/ui/utils/portal/types.ts +1 -3
  254. package/src/ui/utils/portal/usePortal.ts +1 -3
  255. package/src/ui/utils/srOnly/srOnly.tsx +25 -20
  256. package/src/ui/utils/virtualList/virtualList.tsx +69 -50
  257. package/src/css/compile/compilePalette.ts +0 -27
  258. package/src/css/compile/compileRule.ts +0 -97
  259. package/src/css/compile/compileRules.test.ts +0 -36
  260. package/src/css/compile/compileRules.ts +0 -43
  261. package/src/css/compile/compileSystem.ts +0 -10
  262. package/src/css/compile/compileTheme_v3.ts +0 -401
  263. package/src/css/compile/types.ts +0 -6
  264. package/src/css/components/breadcrumbs/rules.ts +0 -25
  265. package/src/css/components/dialog/rules.ts +0 -78
  266. package/src/css/components/skeleton/rules.ts +0 -113
  267. package/src/css/components/toast/rules.ts +0 -18
  268. package/src/css/components/tree/rules.ts +0 -168
  269. package/src/css/primitives/_selectable/_contants.ts +0 -11
  270. package/src/css/primitives/card/_constants.ts +0 -13
  271. package/src/css/primitives/popover/rules.ts +0 -5
  272. package/src/css/primitives/spinner/rules.ts +0 -21
  273. package/src/css/primitives/token/rules.ts +0 -45
  274. package/src/ui/utils/conditionalWrapper/conditionalWrapper.tsx +0 -23
  275. package/src/ui/utils/conditionalWrapper/index.ts +0 -1
@@ -1,112 +1,42 @@
1
- import {
2
- FocusEvent,
3
- ForwardedRef,
4
- forwardRef,
5
- useCallback,
6
- useEffect,
7
- useImperativeHandle,
8
- useRef,
9
- } from 'react'
10
-
11
- import {EMPTY_RECORD} from '../../constants'
12
- import {containsOrEqualsElement, isHTMLElement} from '../../helpers'
13
- import {Box, BoxProps} from '../../primitives'
1
+ import {CardElementType, CardOwnProps} from '../../primitives'
14
2
  import {Props} from '../../types'
3
+ import {LayerCard} from './layerCard'
15
4
  import {LayerProvider} from './layerProvider'
16
- import {useLayer} from './useLayer'
17
5
 
18
- /**
19
- * @public
20
- */
21
- export interface LayerProps extends BoxProps {
6
+ /** @public */
7
+ export const DEFAULT_LAYER_ELEMENT = 'div'
8
+
9
+ /** @public */
10
+ export type LayerOwnProps = CardOwnProps & {
22
11
  /** A callback that fires when the layer becomes the top layer when it was not the top layer before. */
23
12
  onActivate?: (props: {activeElement: HTMLElement | null}) => void
24
13
  zOffset?: number | number[]
25
14
  }
26
15
 
27
- interface LayerChildrenProps extends BoxProps {
28
- onActivate?: LayerProps['onActivate']
29
- }
16
+ /** @public */
17
+ export type LayerElementType = CardElementType
30
18
 
31
- const LayerChildren = forwardRef(function LayerChildren(
32
- props: Props<LayerChildrenProps, 'div'>,
33
- forwardedRef: ForwardedRef<HTMLDivElement>,
19
+ /** @public */
20
+ export type LayerProps<E extends LayerElementType = LayerElementType> = Props<LayerOwnProps, E>
21
+
22
+ /** @public */
23
+ export function Layer<E extends LayerElementType = typeof DEFAULT_LAYER_ELEMENT>(
24
+ props: LayerProps<E>,
34
25
  ) {
35
26
  const {
27
+ as = DEFAULT_LAYER_ELEMENT,
36
28
  children,
37
- onActivate,
38
- onFocus,
39
- position = 'relative',
40
- style = EMPTY_RECORD,
41
- ...restProps
42
- } = props
43
- const {zIndex, isTopLayer} = useLayer()
44
- const lastFocusedRef = useRef<HTMLElement | null>(null)
45
- const ref = useRef<HTMLDivElement | null>(null)
46
- const isTopLayerRef = useRef<boolean>(isTopLayer)
47
-
48
- useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
49
-
50
- // When the layer very first mounts, it will be the top layer, but we don't want to fire
51
- // the callback in that case. We use a ref to track the previous value of isTopLayer to
52
- // determine if the layer has become the top layer since the last render.
53
- useEffect(() => {
54
- const becameTopLayer = isTopLayerRef.current !== isTopLayer && isTopLayer
55
-
56
- if (becameTopLayer) {
57
- onActivate?.({activeElement: lastFocusedRef.current})
58
- }
59
-
60
- isTopLayerRef.current = isTopLayer
61
- }, [isTopLayer, onActivate])
62
-
63
- const handleFocus = useCallback(
64
- (event: FocusEvent<HTMLDivElement, Element>) => {
65
- // Call the user-provided onFocus handler if any
66
- onFocus?.(event)
67
-
68
- const rootElement = ref.current
69
- const target = document.activeElement
70
-
71
- if (!isTopLayer || !rootElement || !target) return
72
-
73
- if (isHTMLElement(target) && containsOrEqualsElement(rootElement, target)) {
74
- lastFocusedRef.current = target
75
- }
76
- },
77
- [isTopLayer, onFocus],
78
- )
79
-
80
- return (
81
- <Box
82
- data-ui="Layer"
83
- {...restProps}
84
- onFocus={handleFocus}
85
- position={position}
86
- ref={ref}
87
- style={{...style, zIndex}}
88
- >
89
- {children}
90
- </Box>
91
- )
92
- })
93
-
94
- /**
95
- * @public
96
- */
97
- export const Layer = forwardRef(function Layer(
98
- props: Props<LayerProps, 'div'>,
99
- ref: ForwardedRef<HTMLDivElement>,
100
- ) {
101
- const {children, zOffset = 1, ...restProps} = props
29
+ zOffset = 1,
30
+ ...rest
31
+ } = props as LayerProps<typeof DEFAULT_LAYER_ELEMENT>
102
32
 
103
33
  return (
104
34
  <LayerProvider zOffset={zOffset}>
105
- <LayerChildren {...restProps} ref={ref}>
35
+ <LayerCard {...rest} as={as}>
106
36
  {children}
107
- </LayerChildren>
37
+ </LayerCard>
108
38
  </LayerProvider>
109
39
  )
110
- })
40
+ }
111
41
 
112
- Layer.displayName = 'ForwardRef(Layer)'
42
+ Layer.displayName = 'Layer'
@@ -0,0 +1,92 @@
1
+ import {type FocusEvent, useCallback, useEffect, useImperativeHandle, useRef} from 'react'
2
+
3
+ import {EMPTY_RECORD} from '../../constants'
4
+ import {containsOrEqualsElement, isHTMLElement} from '../../helpers'
5
+ import {Card, CardElementType} from '../../primitives'
6
+ import {Props} from '../../types'
7
+ import {LayerElementType, LayerOwnProps} from './layer'
8
+ import {useLayer} from './useLayer'
9
+
10
+ /** @internal */
11
+ export const DEFAULT_LAYER_CARD_ELEMENT = 'div'
12
+
13
+ /** @internal */
14
+ export type LayerCardOwnProps = Omit<LayerOwnProps, 'zOffset'>
15
+
16
+ /** @internal */
17
+ export type LayerCardElementType = LayerElementType
18
+
19
+ /** @internal */
20
+ export type LayerCardProps<E extends LayerCardElementType = LayerCardElementType> = Props<
21
+ LayerCardOwnProps,
22
+ E
23
+ >
24
+
25
+ /** @internal */
26
+ export function LayerCard<E extends LayerCardElementType = typeof DEFAULT_LAYER_CARD_ELEMENT>(
27
+ props: LayerCardProps<E>,
28
+ ) {
29
+ const {
30
+ as = DEFAULT_LAYER_CARD_ELEMENT,
31
+ children,
32
+ onActivate,
33
+ onFocus,
34
+ position = 'relative',
35
+ ref: forwardedRef,
36
+ style = EMPTY_RECORD,
37
+ ...rest
38
+ } = props as LayerCardProps<typeof DEFAULT_LAYER_CARD_ELEMENT>
39
+
40
+ const {zIndex, isTopLayer} = useLayer()
41
+ const lastFocusedRef = useRef<HTMLElement | null>(null)
42
+ const ref = useRef<HTMLDivElement | null>(null)
43
+ const isTopLayerRef = useRef<boolean>(isTopLayer)
44
+
45
+ useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
46
+
47
+ // When the layer very first mounts, it will be the top layer, but we don't want to fire
48
+ // the callback in that case. We use a ref to track the previous value of isTopLayer to
49
+ // determine if the layer has become the top layer since the last render.
50
+ useEffect(() => {
51
+ const becameTopLayer = isTopLayerRef.current !== isTopLayer && isTopLayer
52
+
53
+ if (becameTopLayer) {
54
+ onActivate?.({activeElement: lastFocusedRef.current})
55
+ }
56
+
57
+ isTopLayerRef.current = isTopLayer
58
+ }, [isTopLayer, onActivate])
59
+
60
+ const handleFocus = useCallback(
61
+ (event: FocusEvent<HTMLDivElement, Element>) => {
62
+ // Call the user-provided onFocus handler if any
63
+ onFocus?.(event)
64
+
65
+ const rootElement = ref.current
66
+ const target = document.activeElement
67
+
68
+ if (!isTopLayer || !rootElement || !target) return
69
+
70
+ if (isHTMLElement(target) && containsOrEqualsElement(rootElement, target)) {
71
+ lastFocusedRef.current = target
72
+ }
73
+ },
74
+ [isTopLayer, onFocus],
75
+ )
76
+
77
+ return (
78
+ <Card
79
+ data-ui="Layer"
80
+ {...rest}
81
+ as={as as CardElementType}
82
+ onFocus={handleFocus}
83
+ position={position}
84
+ ref={ref}
85
+ style={{...style, zIndex}}
86
+ >
87
+ {children}
88
+ </Card>
89
+ )
90
+ }
91
+
92
+ LayerCard.displayName = 'LayerCard'
@@ -5,17 +5,13 @@ import {getLayerContext} from './getLayerContext'
5
5
  import {LayerContext} from './layerContext'
6
6
  import {LayerContextValue} from './types'
7
7
 
8
- /**
9
- * @public
10
- */
8
+ /** @public */
11
9
  export interface LayerProviderProps {
12
10
  children?: ReactNode
13
11
  zOffset?: number | number[]
14
12
  }
15
13
 
16
- /**
17
- * @public
18
- */
14
+ /** @public */
19
15
  export function LayerProvider(props: LayerProviderProps): ReactElement {
20
16
  const {children, zOffset: zOffsetProp = 0} = props
21
17
 
@@ -4,9 +4,7 @@ import {getLayerContext} from './getLayerContext'
4
4
  import {LayerContext} from './layerContext'
5
5
  import {LayerContextValue} from './types'
6
6
 
7
- /**
8
- * @public
9
- */
7
+ /** @public */
10
8
  export function useLayer(): LayerContextValue {
11
9
  const value = useContext(LayerContext)
12
10
 
@@ -4,9 +4,7 @@ import {createPortal} from 'react-dom'
4
4
  import {CardProvider, useCard} from '../../primitives'
5
5
  import {usePortal} from './usePortal'
6
6
 
7
- /**
8
- * @public
9
- */
7
+ /** @public */
10
8
  export interface PortalProps {
11
9
  children: ReactNode
12
10
  /**
@@ -15,9 +13,7 @@ export interface PortalProps {
15
13
  __unstable_name?: string
16
14
  }
17
15
 
18
- /**
19
- * @public
20
- */
16
+ /** @public */
21
17
  export function Portal(props: PortalProps): ReactPortal | null {
22
18
  const {children, __unstable_name: name} = props
23
19
  const card = useCard()
@@ -3,9 +3,7 @@ import {ReactElement, ReactNode, useMemo, useRef, useSyncExternalStore} from 're
3
3
  import {PortalContext} from './portalContext'
4
4
  import {PortalContextValue} from './types'
5
5
 
6
- /**
7
- * @public
8
- */
6
+ /** @public */
9
7
  export interface PortalProviderProps {
10
8
  /**
11
9
  * @deprecated Use `<BoundaryElementProvider element={...} />` instead
@@ -19,9 +17,7 @@ export interface PortalProviderProps {
19
17
  __unstable_elements?: Record<string, HTMLElement | null | undefined>
20
18
  }
21
19
 
22
- /**
23
- * @public
24
- */
20
+ /** @public */
25
21
  export function PortalProvider(props: PortalProviderProps): ReactElement {
26
22
  const {boundaryElement, children, element, __unstable_elements: elementsProp} = props
27
23
  const elements = useUnique(elementsProp)
@@ -1,6 +1,4 @@
1
- /**
2
- * @public
3
- */
1
+ /** @public */
4
2
  export interface PortalContextValue {
5
3
  version: 0.0
6
4
  boundaryElement: HTMLElement | null
@@ -4,9 +4,7 @@ import {isRecord} from '../../lib/isRecord'
4
4
  import {PortalContext} from './portalContext'
5
5
  import {PortalContextValue} from './types'
6
6
 
7
- /**
8
- * @public
9
- */
7
+ /** @public */
10
8
  export function usePortal(): PortalContextValue {
11
9
  const value = useContext(PortalContext)
12
10
 
@@ -1,35 +1,40 @@
1
1
  import {composeClassNames, srOnly} from '@sanity/ui/css'
2
- import {ForwardedRef, forwardRef, ReactNode} from 'react'
3
2
 
4
- import {Props} from '../../types'
3
+ import {ComponentType, Props} from '../../types'
5
4
 
6
- /**
7
- * @public
8
- */
9
- export interface SrOnlyProps {
10
- children?: ReactNode
11
- }
5
+ /** @public */
6
+ export const DEFAULT_SR_ONLY_ELEMENT = 'span'
7
+
8
+ /** @public */
9
+ export type SrOnlyOwnProps = {} // eslint-disable-line @typescript-eslint/no-empty-object-type
10
+
11
+ /** @public */
12
+ export type SrOnlyElementType = 'span' | ComponentType
12
13
 
13
- /**
14
- * @public
15
- */
16
- export const SrOnly = forwardRef(function SrOnly(
17
- props: Props<SrOnlyProps, 'div'>,
18
- ref: ForwardedRef<HTMLDivElement>,
14
+ /** @public */
15
+ export type SrOnlyProps<E extends SrOnlyElementType = SrOnlyElementType> = Props<SrOnlyOwnProps, E>
16
+
17
+ /** @public */
18
+ export function SrOnly<E extends SrOnlyElementType = typeof DEFAULT_SR_ONLY_ELEMENT>(
19
+ props: SrOnlyProps<E>,
19
20
  ) {
20
- const {as: As = 'div', children, className, ...rest} = props
21
+ const {
22
+ as: Element = DEFAULT_SR_ONLY_ELEMENT,
23
+ children,
24
+ className,
25
+ ...rest
26
+ } = props as SrOnlyProps<typeof DEFAULT_SR_ONLY_ELEMENT>
21
27
 
22
28
  return (
23
- <As
29
+ <Element
24
30
  data-ui="SrOnly"
25
31
  {...rest}
26
32
  aria-hidden
27
33
  className={composeClassNames(className, srOnly())}
28
- ref={ref}
29
34
  >
30
35
  {children}
31
- </As>
36
+ </Element>
32
37
  )
33
- })
38
+ }
34
39
 
35
- SrOnly.displayName = 'ForwardRef(SrOnly)'
40
+ SrOnly.displayName = 'SrOnly'
@@ -1,7 +1,7 @@
1
+ import {vars} from '@sanity/ui/css'
2
+ import {Space} from '@sanity/ui/theme'
1
3
  import {
2
- ForwardedRef,
3
- forwardRef,
4
- ReactElement,
4
+ type CSSProperties,
5
5
  ReactNode,
6
6
  useEffect,
7
7
  useImperativeHandle,
@@ -10,15 +10,15 @@ import {
10
10
  useState,
11
11
  } from 'react'
12
12
 
13
- import {useTheme_v2} from '../../_compat'
14
13
  import {_isScrollable} from '../../helpers'
15
14
  import {_ResizeObserver} from '../../observers'
16
- import {Box, StackProps} from '../../primitives'
17
- import {Props} from '../../types'
15
+ import {Box} from '../../primitives'
16
+ import {ComponentType, Props} from '../../types'
18
17
 
19
- /**
20
- * @beta
21
- */
18
+ /** @beta */
19
+ export const DEFAULT_VIRTUAL_LIST_ELEMENT = 'div'
20
+
21
+ /** @beta */
22
22
  export interface VirtualListChangeOpts {
23
23
  fromIndex: number
24
24
  gap: number
@@ -28,45 +28,52 @@ export interface VirtualListChangeOpts {
28
28
  toIndex: number
29
29
  }
30
30
 
31
- /**
32
- * @beta
33
- */
34
- export interface VirtualListProps<Item = any> extends Omit<StackProps, 'gap'> {
35
- gap?: number
31
+ /** @beta */
32
+ export type VirtualListOwnProps<Item = any> = {
33
+ gap?: Space
36
34
  getItemKey?: (item: Item, itemIndex: number) => string
37
35
  items?: Item[]
38
36
  onChange?: (opts: VirtualListChangeOpts) => void
39
37
  renderItem?: (item: Item) => ReactNode
40
38
  }
41
39
 
40
+ /** @beta */
41
+ export type VirtualListElementType = 'div' | ComponentType
42
+
43
+ /** @beta */
44
+ export type VirtualListProps<E extends VirtualListElementType = VirtualListElementType> = Props<
45
+ VirtualListOwnProps,
46
+ E
47
+ >
48
+
42
49
  /**
43
50
  * @beta
44
51
  */
45
- export const VirtualList = forwardRef(function VirtualList(
46
- props: Props<VirtualListProps, 'div'>,
47
- forwardedRef: ForwardedRef<HTMLDivElement>,
48
- ): ReactElement {
49
- const {as = 'div', gap = 0, getItemKey, items = [], onChange, renderItem, ...restProps} = props
50
- const {space} = useTheme_v2()
52
+ export function VirtualList<E extends VirtualListElementType = typeof DEFAULT_VIRTUAL_LIST_ELEMENT>(
53
+ props: VirtualListProps<E>,
54
+ ) {
55
+ const {
56
+ as = DEFAULT_VIRTUAL_LIST_ELEMENT,
57
+ gap = 0,
58
+ getItemKey,
59
+ items = [],
60
+ onChange,
61
+ renderItem,
62
+ ref: forwardedRef,
63
+ ...rest
64
+ } = props as VirtualListProps<typeof DEFAULT_VIRTUAL_LIST_ELEMENT>
65
+
51
66
  const ref = useRef<HTMLDivElement | null>(null)
52
67
  const wrapperRef = useRef<HTMLDivElement | null>(null)
53
68
  const [scrollTop, setScrollTop] = useState(0)
54
69
  const [scrollHeight, setScrollHeight] = useState(0)
55
70
  const [itemHeight, setItemHeight] = useState(-1)
56
71
 
72
+ const [gapValue, setGapValue] = useState(0)
73
+
57
74
  // Sync ref to parent
58
75
  useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
59
76
 
60
- useEffect(() => {
61
- if (!wrapperRef.current) return
62
-
63
- const firstElement = wrapperRef.current.firstChild
64
-
65
- if (firstElement instanceof HTMLElement) {
66
- setItemHeight(firstElement.offsetHeight)
67
- }
68
- }, [renderItem])
69
-
70
77
  useEffect((): (() => void) | undefined => {
71
78
  if (!ref.current) return
72
79
 
@@ -119,23 +126,42 @@ export const VirtualList = forwardRef(function VirtualList(
119
126
  }, [])
120
127
 
121
128
  const len = items.length
122
- const height = itemHeight ? len * (itemHeight + space[gap]) - space[gap] : 0
129
+ const height = itemHeight ? len * (itemHeight + gapValue) - gapValue : 0
123
130
  const fromIndex = height ? Math.max(Math.floor((scrollTop / height) * len) - 2, 0) : 0
124
131
  const toIndex = height ? Math.ceil(((scrollTop + scrollHeight) / height) * len) + 1 : 0
125
132
 
126
133
  useEffect(() => {
127
- if (!onChange) return
128
- onChange({fromIndex, gap: space[gap], itemHeight, scrollHeight, scrollTop, toIndex})
129
- }, [fromIndex, gap, itemHeight, onChange, scrollHeight, scrollTop, space, toIndex])
134
+ onChange?.({
135
+ fromIndex,
136
+ gap: gapValue,
137
+ itemHeight,
138
+ scrollHeight,
139
+ scrollTop,
140
+ toIndex,
141
+ })
142
+ }, [fromIndex, gapValue, itemHeight, onChange, scrollHeight, scrollTop, toIndex])
130
143
 
131
144
  const children = useMemo(() => {
132
145
  if (!renderItem || items.length === 0) return null
133
146
 
134
147
  if (itemHeight === -1) {
135
148
  return [
136
- <Box insetTop={0} insetLeft={0} insetRight={0} key={0} position="absolute">
137
- {renderItem(items[0])}
138
- </Box>,
149
+ <>
150
+ <Box
151
+ ref={(el) => (el ? setItemHeight(el.offsetHeight) : undefined)}
152
+ insetTop={0}
153
+ insetLeft={0}
154
+ insetRight={0}
155
+ key={0}
156
+ position="absolute"
157
+ >
158
+ {renderItem(items[0])}
159
+ </Box>
160
+ <div
161
+ ref={(el) => (el ? setGapValue(el.offsetHeight) : undefined)}
162
+ style={{height: vars.space[gap]}}
163
+ />
164
+ </>,
139
165
  ]
140
166
  }
141
167
 
@@ -150,33 +176,26 @@ export const VirtualList = forwardRef(function VirtualList(
150
176
  insetRight={0}
151
177
  key={key}
152
178
  position="absolute"
153
- style={{top: itemIndex * (itemHeight + space[gap])}}
179
+ style={{top: itemIndex * (itemHeight + gapValue) - gapValue}}
154
180
  >
155
181
  {node}
156
182
  </Box>
157
183
  )
158
184
  })
159
- }, [fromIndex, gap, getItemKey, itemHeight, items, renderItem, space, toIndex])
185
+ }, [fromIndex, gap, gapValue, getItemKey, itemHeight, items, renderItem, toIndex])
160
186
 
161
- const wrapperStyle = useMemo(() => ({height}), [height])
187
+ const wrapperStyle: CSSProperties = useMemo(() => ({height}), [height])
162
188
 
163
189
  return (
164
- <Box
165
- // Root
166
- as={as}
167
- data-ui="VirtualList"
168
- {...restProps}
169
- position="relative"
170
- ref={ref}
171
- >
190
+ <Box data-ui="VirtualList" {...rest} as={as} position="relative" ref={ref}>
172
191
  <div ref={wrapperRef} style={wrapperStyle}>
173
192
  {children}
174
193
  </div>
175
194
  </Box>
176
195
  )
177
- })
196
+ }
178
197
 
179
- VirtualList.displayName = 'ForwardRef(VirtualList)'
198
+ VirtualList.displayName = 'VirtualList'
180
199
 
181
200
  function findScrollable(parentNode: ParentNode | null) {
182
201
  let _scrollEl = parentNode
@@ -1,27 +0,0 @@
1
- import {color} from '@sanity/color'
2
- import {HUES, TINTS} from '@sanity/ui/theme'
3
-
4
- import {compileRule} from './compileRule'
5
-
6
- export function compilePalette(): string {
7
- const props: Record<string, string> = {
8
- ...compileHues(),
9
-
10
- '--black': color.black.hex,
11
- '--white': color.white.hex,
12
- }
13
-
14
- return compileRule(':root', props, {keyframes: {}, media: {}})
15
- }
16
-
17
- function compileHues() {
18
- const rules: Record<string, string> = {}
19
-
20
- for (const hue of HUES) {
21
- for (const tint of TINTS) {
22
- rules[`--${hue}-${tint}`] = color[hue][tint].hex
23
- }
24
- }
25
-
26
- return rules
27
- }