@sanity/ui 0.37.21 → 0.38.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.
Files changed (210) hide show
  1. package/lib/dts/src/components/breadcrumbs/breadcrumbs.d.ts.map +1 -1
  2. package/lib/dts/src/components/dialog/dialog.d.ts.map +1 -1
  3. package/lib/dts/src/components/dialog/styles.d.ts +1 -1
  4. package/lib/dts/src/components/dialog/styles.d.ts.map +1 -1
  5. package/lib/dts/src/components/hotkeys/hotkeys.d.ts.map +1 -1
  6. package/lib/dts/src/components/menu/menuGroup.d.ts.map +1 -1
  7. package/lib/dts/src/components/skeleton/skeleton.d.ts.map +1 -1
  8. package/lib/dts/src/hooks/index.d.ts +2 -1
  9. package/lib/dts/src/hooks/index.d.ts.map +1 -1
  10. package/lib/dts/src/hooks/useArrayProp.d.ts +7 -0
  11. package/lib/dts/src/hooks/useArrayProp.d.ts.map +1 -0
  12. package/lib/dts/src/hooks/useElementRect/useElementRect.d.ts +1 -1
  13. package/lib/dts/src/hooks/useElementRect/useElementRect.d.ts.map +1 -1
  14. package/lib/dts/src/hooks/useElementSize.d.ts +7 -0
  15. package/lib/dts/src/hooks/useElementSize.d.ts.map +1 -0
  16. package/lib/dts/src/index.d.ts +1 -0
  17. package/lib/dts/src/index.d.ts.map +1 -1
  18. package/lib/dts/src/observers/elementSizeObserver.d.ts +37 -0
  19. package/lib/dts/src/observers/elementSizeObserver.d.ts.map +1 -0
  20. package/lib/dts/src/observers/index.d.ts +3 -0
  21. package/lib/dts/src/observers/index.d.ts.map +1 -0
  22. package/lib/dts/src/observers/resizeObserver.d.ts +5 -0
  23. package/lib/dts/src/observers/resizeObserver.d.ts.map +1 -0
  24. package/lib/dts/src/primitives/_selectable/selectable.d.ts +1 -2
  25. package/lib/dts/src/primitives/_selectable/selectable.d.ts.map +1 -1
  26. package/lib/dts/src/primitives/avatar/avatar.d.ts.map +1 -1
  27. package/lib/dts/src/primitives/avatar/avatarCounter.d.ts.map +1 -1
  28. package/lib/dts/src/primitives/avatar/avatarStack.d.ts.map +1 -1
  29. package/lib/dts/src/primitives/avatar/styles.d.ts.map +1 -1
  30. package/lib/dts/src/primitives/badge/badge.d.ts.map +1 -1
  31. package/lib/dts/src/primitives/box/box.d.ts.map +1 -1
  32. package/lib/dts/src/primitives/button/button.d.ts.map +1 -1
  33. package/lib/dts/src/primitives/card/card.d.ts.map +1 -1
  34. package/lib/dts/src/primitives/code/code.d.ts.map +1 -1
  35. package/lib/dts/src/primitives/container/container.d.ts.map +1 -1
  36. package/lib/dts/src/primitives/container/styles.d.ts.map +1 -1
  37. package/lib/dts/src/primitives/container/types.d.ts +1 -1
  38. package/lib/dts/src/primitives/container/types.d.ts.map +1 -1
  39. package/lib/dts/src/primitives/flex/flex.d.ts.map +1 -1
  40. package/lib/dts/src/primitives/grid/grid.d.ts.map +1 -1
  41. package/lib/dts/src/primitives/heading/heading.d.ts.map +1 -1
  42. package/lib/dts/src/primitives/inline/inline.d.ts.map +1 -1
  43. package/lib/dts/src/primitives/inline/styles.d.ts.map +1 -1
  44. package/lib/dts/src/primitives/inline/types.d.ts +1 -1
  45. package/lib/dts/src/primitives/inline/types.d.ts.map +1 -1
  46. package/lib/dts/src/primitives/kbd/kbd.d.ts.map +1 -1
  47. package/lib/dts/src/primitives/label/label.d.ts.map +1 -1
  48. package/lib/dts/src/primitives/popover/popover.d.ts.map +1 -1
  49. package/lib/dts/src/primitives/select/styles.d.ts +5 -1
  50. package/lib/dts/src/primitives/select/styles.d.ts.map +1 -1
  51. package/lib/dts/src/primitives/stack/stack.d.ts.map +1 -1
  52. package/lib/dts/src/primitives/stack/styles.d.ts +1 -1
  53. package/lib/dts/src/primitives/stack/styles.d.ts.map +1 -1
  54. package/lib/dts/src/primitives/text/text.d.ts.map +1 -1
  55. package/lib/dts/src/primitives/textArea/textArea.d.ts.map +1 -1
  56. package/lib/dts/src/primitives/textInput/textInput.d.ts.map +1 -1
  57. package/lib/dts/src/primitives/tooltip/tooltip.d.ts.map +1 -1
  58. package/lib/dts/src/primitives/types.d.ts +1 -1
  59. package/lib/dts/src/primitives/types.d.ts.map +1 -1
  60. package/lib/dts/src/styles/border/types.d.ts +5 -5
  61. package/lib/dts/src/styles/border/types.d.ts.map +1 -1
  62. package/lib/dts/src/styles/box/types.d.ts +4 -4
  63. package/lib/dts/src/styles/box/types.d.ts.map +1 -1
  64. package/lib/dts/src/styles/flex/flexItemStyle.d.ts.map +1 -1
  65. package/lib/dts/src/styles/flex/types.d.ts +6 -6
  66. package/lib/dts/src/styles/flex/types.d.ts.map +1 -1
  67. package/lib/dts/src/styles/font/responsiveFont.d.ts.map +1 -1
  68. package/lib/dts/src/styles/font/types.d.ts +3 -3
  69. package/lib/dts/src/styles/font/types.d.ts.map +1 -1
  70. package/lib/dts/src/styles/grid/types.d.ts +14 -14
  71. package/lib/dts/src/styles/grid/types.d.ts.map +1 -1
  72. package/lib/dts/src/styles/helpers.d.ts +4 -4
  73. package/lib/dts/src/styles/helpers.d.ts.map +1 -1
  74. package/lib/dts/src/styles/input/responsiveInputPaddingStyle.d.ts +12 -12
  75. package/lib/dts/src/styles/input/responsiveInputPaddingStyle.d.ts.map +1 -1
  76. package/lib/dts/src/styles/input/textInputStyle.d.ts +7 -2
  77. package/lib/dts/src/styles/input/textInputStyle.d.ts.map +1 -1
  78. package/lib/dts/src/styles/margin/types.d.ts +7 -7
  79. package/lib/dts/src/styles/margin/types.d.ts.map +1 -1
  80. package/lib/dts/src/styles/padding/types.d.ts +7 -7
  81. package/lib/dts/src/styles/padding/types.d.ts.map +1 -1
  82. package/lib/dts/src/styles/radius/types.d.ts +1 -1
  83. package/lib/dts/src/styles/radius/types.d.ts.map +1 -1
  84. package/lib/dts/src/styles/shadow/shadowStyle.d.ts.map +1 -1
  85. package/lib/dts/src/styles/shadow/types.d.ts +1 -1
  86. package/lib/dts/src/styles/shadow/types.d.ts.map +1 -1
  87. package/lib/dts/src/theme/studioTheme/color.d.ts.map +1 -1
  88. package/lib/dts/src/utils/elementQuery/elementQuery.d.ts.map +1 -1
  89. package/lib/dts/src/utils/index.d.ts +0 -1
  90. package/lib/dts/src/utils/index.d.ts.map +1 -1
  91. package/lib/dts/src/utils/virtualList/virtualList.d.ts.map +1 -1
  92. package/lib/sanity-ui.js +734 -573
  93. package/lib/sanity-ui.js.map +1 -1
  94. package/lib/sanity-ui.modern.js +763 -592
  95. package/lib/sanity-ui.modern.js.map +1 -1
  96. package/lib/sanity-ui.module.js +728 -569
  97. package/lib/sanity-ui.module.js.map +1 -1
  98. package/package.json +11 -11
  99. package/src/__workshop__/color/overview.tsx +9 -11
  100. package/src/components/autocomplete/__workshop__/async.tsx +14 -12
  101. package/src/components/autocomplete/__workshop__/constrainedHeight.tsx +36 -0
  102. package/src/components/autocomplete/autocomplete.tsx +2 -2
  103. package/src/components/breadcrumbs/breadcrumbs.tsx +3 -2
  104. package/src/components/dialog/dialog.tsx +17 -9
  105. package/src/components/dialog/styles.ts +4 -4
  106. package/src/components/hotkeys/hotkeys.tsx +3 -1
  107. package/src/components/menu/__workshop__/constrainedInBoundary.tsx +11 -14
  108. package/src/components/menu/__workshop__/groups.tsx +1 -1
  109. package/src/components/menu/menuGroup.tsx +3 -2
  110. package/src/components/menu/menuItem.tsx +3 -3
  111. package/src/components/skeleton/skeleton.tsx +10 -1
  112. package/src/components/skeleton/textSkeleton.tsx +7 -7
  113. package/src/hooks/index.ts +2 -1
  114. package/src/hooks/useArrayProp.ts +23 -0
  115. package/src/hooks/useElementRect/useElementRect.ts +4 -16
  116. package/src/hooks/useElementSize.ts +18 -0
  117. package/src/index.ts +1 -0
  118. package/src/observers/elementSizeObserver.ts +116 -0
  119. package/src/observers/index.ts +2 -0
  120. package/src/{utils → observers}/resizeObserver.ts +1 -3
  121. package/src/primitives/_selectable/selectable.tsx +5 -4
  122. package/src/primitives/avatar/avatar.tsx +7 -5
  123. package/src/primitives/avatar/avatarCounter.tsx +12 -11
  124. package/src/primitives/avatar/avatarStack.tsx +15 -10
  125. package/src/primitives/avatar/styles.ts +2 -2
  126. package/src/primitives/badge/badge.tsx +3 -2
  127. package/src/primitives/box/box.tsx +26 -25
  128. package/src/primitives/button/button.tsx +22 -10
  129. package/src/primitives/card/card.tsx +8 -7
  130. package/src/primitives/checkbox/__workshop__/example.tsx +4 -2
  131. package/src/primitives/checkbox/__workshop__/props.tsx +4 -2
  132. package/src/primitives/checkbox/__workshop__/readOnly.tsx +4 -2
  133. package/src/primitives/code/__workshop__/props.tsx +1 -1
  134. package/src/primitives/code/code.tsx +2 -1
  135. package/src/primitives/container/container.tsx +10 -1
  136. package/src/primitives/container/styles.ts +2 -2
  137. package/src/primitives/container/types.ts +1 -1
  138. package/src/primitives/flex/flex.tsx +6 -5
  139. package/src/primitives/grid/__workshop__/responsive.tsx +13 -12
  140. package/src/primitives/grid/grid.tsx +9 -8
  141. package/src/primitives/heading/__workshop__/opticalAlignment.tsx +19 -7
  142. package/src/primitives/heading/heading.tsx +3 -2
  143. package/src/primitives/inline/inline.tsx +12 -6
  144. package/src/primitives/inline/styles.ts +2 -2
  145. package/src/primitives/inline/types.ts +1 -1
  146. package/src/primitives/kbd/kbd.tsx +2 -1
  147. package/src/primitives/label/label.tsx +4 -3
  148. package/src/primitives/popover/__workshop__/{margins.tsx → MarginsStory.tsx} +1 -1
  149. package/src/primitives/popover/__workshop__/{matchReferenceWidth.tsx → MatchReferenceWidthStory.tsx} +0 -0
  150. package/src/primitives/popover/__workshop__/{plain.tsx → PlainStory.tsx} +12 -14
  151. package/src/primitives/popover/__workshop__/{recursive.tsx → RecursiveStory.tsx} +4 -1
  152. package/src/primitives/popover/__workshop__/RightAlignedStory.tsx +60 -0
  153. package/src/primitives/popover/__workshop__/TestStory.tsx +79 -0
  154. package/src/primitives/popover/__workshop__/index.ts +10 -5
  155. package/src/primitives/popover/popover.tsx +29 -10
  156. package/src/primitives/select/select.tsx +9 -9
  157. package/src/primitives/select/styles.ts +10 -4
  158. package/src/primitives/stack/stack.tsx +2 -1
  159. package/src/primitives/stack/styles.ts +3 -3
  160. package/src/primitives/text/__workshop__/opticalAlignment.tsx +15 -5
  161. package/src/primitives/text/text.tsx +3 -2
  162. package/src/primitives/textArea/__workshop__/plain.tsx +23 -18
  163. package/src/primitives/textArea/textArea.tsx +21 -5
  164. package/src/primitives/textInput/__workshop__/clearButton.tsx +14 -8
  165. package/src/primitives/textInput/__workshop__/index.ts +2 -2
  166. package/src/primitives/textInput/__workshop__/plain.tsx +39 -32
  167. package/src/primitives/textInput/__workshop__/tones.tsx +234 -95
  168. package/src/primitives/textInput/__workshop__/typed.tsx +8 -2
  169. package/src/primitives/textInput/textInput.tsx +47 -12
  170. package/src/primitives/tooltip/__workshop__/props.tsx +7 -2
  171. package/src/primitives/tooltip/tooltip.tsx +19 -9
  172. package/src/primitives/types.ts +1 -1
  173. package/src/styles/border/borderStyle.ts +6 -6
  174. package/src/styles/border/types.ts +5 -5
  175. package/src/styles/box/boxStyle.ts +5 -5
  176. package/src/styles/box/types.ts +4 -4
  177. package/src/styles/flex/flexItemStyle.ts +5 -4
  178. package/src/styles/flex/flexStyle.ts +6 -6
  179. package/src/styles/flex/types.ts +6 -6
  180. package/src/styles/font/responsiveFont.ts +2 -4
  181. package/src/styles/font/textAlignStyle.ts +2 -2
  182. package/src/styles/font/types.ts +4 -3
  183. package/src/styles/grid/gridItemStyle.ts +7 -7
  184. package/src/styles/grid/gridStyle.ts +9 -9
  185. package/src/styles/grid/types.ts +14 -14
  186. package/src/styles/helpers.ts +9 -9
  187. package/src/styles/input/responsiveInputPaddingStyle.ts +24 -27
  188. package/src/styles/input/textInputStyle.ts +92 -80
  189. package/src/styles/margin/marginStyle.ts +8 -8
  190. package/src/styles/margin/marginsStyle.test.ts +1 -1
  191. package/src/styles/margin/types.ts +7 -7
  192. package/src/styles/padding/paddingStyle.test.ts +1 -1
  193. package/src/styles/padding/paddingStyle.ts +8 -8
  194. package/src/styles/padding/types.ts +7 -7
  195. package/src/styles/radius/radiusStyle.ts +2 -2
  196. package/src/styles/radius/types.ts +1 -1
  197. package/src/styles/shadow/shadowStyle.ts +2 -5
  198. package/src/styles/shadow/types.ts +1 -1
  199. package/src/theme/studioTheme/color.ts +15 -14
  200. package/src/theme/studioTheme/fonts.ts +4 -4
  201. package/src/utils/elementQuery/elementQuery.tsx +5 -18
  202. package/src/utils/index.ts +0 -1
  203. package/src/utils/layer/layerProvider.tsx +2 -2
  204. package/src/utils/virtualList/virtualList.tsx +3 -1
  205. package/lib/dts/src/hooks/useResponsiveProp.d.ts +0 -6
  206. package/lib/dts/src/hooks/useResponsiveProp.d.ts.map +0 -1
  207. package/lib/dts/src/utils/resizeObserver.d.ts +0 -6
  208. package/lib/dts/src/utils/resizeObserver.d.ts.map +0 -1
  209. package/src/hooks/useResponsiveProp.ts +0 -10
  210. package/src/primitives/popover/__workshop__/rightAligned.tsx +0 -57
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ui",
3
- "version": "0.37.21",
3
+ "version": "0.38.0",
4
4
  "sideEffects": false,
5
5
  "source": "./src/index.ts",
6
6
  "exports": {
@@ -19,7 +19,7 @@
19
19
  "license": "MIT",
20
20
  "scripts": {
21
21
  "build": "run-s build:microbundle",
22
- "build:microbundle": "microbundle --format modern,esm,cjs --jsx React.createElement --jsxImportSource react --no-compress --tsconfig tsconfig.lib.json",
22
+ "build:microbundle": "microbundle --format modern,esm,cjs --jsx React.createElement --jsxFragment React.Fragment --jsxImportSource react --no-compress --tsconfig tsconfig.lib.json",
23
23
  "clean": "rimraf lib",
24
24
  "lint": "eslint . --ext .js,.jsx,.mjs,.ts,.tsx --quiet",
25
25
  "prebuild": "yarn clean",
@@ -30,20 +30,20 @@
30
30
  "watch:es": "tsc --preserveWatchOutput -w --module ES6 --outDir lib/esm --project tsconfig.lib.json --rootDir src --target ES6"
31
31
  },
32
32
  "dependencies": {
33
- "@juggle/resize-observer": "^3.3.1",
34
- "@popperjs/core": "^2.11.5",
35
- "@reach/auto-id": "^0.16.0",
36
- "@sanity/color": "^2.1.11",
37
- "@sanity/icons": "^1.3.1",
33
+ "@juggle/resize-observer": "^3.4.0",
34
+ "@popperjs/core": "^2.11.6",
35
+ "@reach/auto-id": "^0.17.0",
36
+ "@sanity/color": "^2.1.14",
37
+ "@sanity/icons": "^1.3.4",
38
38
  "framer-motion": "6.3.0",
39
39
  "popper-max-size-modifier": "^0.2.0",
40
40
  "react-is": "^17.0.2",
41
- "react-popper": "^2.2.5",
41
+ "react-popper": "^2.3.0",
42
42
  "react-refractor": "^2.1.7"
43
43
  },
44
44
  "devDependencies": {
45
- "@testing-library/dom": "^8.13.0",
46
- "@testing-library/jest-dom": "^5.16.4",
45
+ "@testing-library/dom": "^8.17.1",
46
+ "@testing-library/jest-dom": "^5.16.5",
47
47
  "@testing-library/react": "^12.1.5",
48
48
  "@types/refractor": "^3.0.2",
49
49
  "react": "^17.0.2",
@@ -72,5 +72,5 @@
72
72
  "publishConfig": {
73
73
  "access": "public"
74
74
  },
75
- "gitHead": "4f7ef1d42b0b536e746ac2670c113a24148c6fdc"
75
+ "gitHead": "f456393d5c6f1e09418af3eaaf2ca734a996523a"
76
76
  }
@@ -19,7 +19,7 @@ const clipboard = {
19
19
 
20
20
  export default function ColorOverviewStory(): React.ReactElement {
21
21
  return (
22
- <Grid columns={[1, 1, 2, 3]} gapX={[3, 4, 5]} gapY={[4, 5, 6]} padding={[3, 4, 5]}>
22
+ <Grid columns={[1, 1, 2, 3]} gapX={[4, 4, 5]} gapY={[5, 5, 6]} padding={[4, 5, 6]}>
23
23
  {COLOR_HUES.map((hueKey) => (
24
24
  <ColorHuePreview tints={hues[hueKey]} hueKey={hueKey} key={hueKey} />
25
25
  ))}
@@ -32,7 +32,7 @@ function ColorHuePreview(props: {hueKey: string; tints: ColorTints}) {
32
32
 
33
33
  return (
34
34
  <Box>
35
- <Heading as="h2" size={[1, 1, 2]}>
35
+ <Heading as="h2" size={1}>
36
36
  {ucfirst(hueKey)}
37
37
  </Heading>
38
38
 
@@ -78,22 +78,20 @@ function ColorTintPreview(props: {tint: ColorValue}) {
78
78
  as="button"
79
79
  onClick={handleClick}
80
80
  radius={2}
81
- style={
82
- {
83
- '--card-bg-color': tint.hex,
84
- '--card-fg-color': hsl.l < 50 ? white.hex : black.hex,
85
- cursor: 'pointer',
86
- } as any
87
- }
81
+ style={{
82
+ ['--card-bg-color' as any]: tint.hex,
83
+ ['--card-fg-color' as any]: hsl.l < 50 ? white.hex : black.hex,
84
+ cursor: 'pointer',
85
+ }}
88
86
  >
89
87
  <Flex padding={3}>
90
88
  <Box flex={1}>
91
- <Code size={[1, 1, 2]} style={{color: 'inherit'}}>
89
+ <Code size={1} style={{color: 'inherit'}}>
92
90
  {tint.title}
93
91
  </Code>
94
92
  </Box>
95
93
  <Box>
96
- <Code size={[1, 1, 2]} style={{color: 'inherit'}}>
94
+ <Code size={1} style={{color: 'inherit'}}>
97
95
  {tint.hex}
98
96
  </Code>
99
97
  </Box>
@@ -1,11 +1,11 @@
1
- import {LinkIcon} from '@sanity/icons'
1
+ import {EarthAmericasIcon, SearchIcon} from '@sanity/icons'
2
2
  import {
3
3
  Autocomplete,
4
4
  BaseAutocompleteOption,
5
5
  Box,
6
- Button,
7
6
  Card,
8
7
  Code,
8
+ Flex,
9
9
  LayerProvider,
10
10
  Stack,
11
11
  Text,
@@ -88,6 +88,7 @@ export default function AsyncStory() {
88
88
  <Autocomplete
89
89
  disabled={loadingCurrentRef}
90
90
  filterOption={filterOption}
91
+ icon={value ? EarthAmericasIcon : SearchIcon}
91
92
  id="async"
92
93
  loading={loading}
93
94
  onChange={setValue}
@@ -95,11 +96,6 @@ export default function AsyncStory() {
95
96
  openButton={{onClick: handleOpenButtonClick}}
96
97
  options={options}
97
98
  placeholder="Search"
98
- prefix={
99
- <Box padding={1}>
100
- <Button disabled={!value} icon={LinkIcon} mode="bleed" padding={2} />
101
- </Box>
102
- }
103
99
  radius={1}
104
100
  renderOption={renderOption}
105
101
  renderValue={renderValue}
@@ -140,13 +136,19 @@ function AsyncOption(props: {
140
136
  selected={selected}
141
137
  tabIndex={tabIndex}
142
138
  >
143
- {loading && (
144
- <Text muted>
145
- <>Loading…</>
139
+ <Flex gap={3}>
140
+ <Text>
141
+ <EarthAmericasIcon />
146
142
  </Text>
147
- )}
148
143
 
149
- {!loading && <Text muted={!data}>{data ? data.title : <>Untitled</>}</Text>}
144
+ {loading && (
145
+ <Text muted>
146
+ <>Loading…</>
147
+ </Text>
148
+ )}
149
+
150
+ {!loading && <Text muted={!data}>{data ? data.title : <>Untitled</>}</Text>}
151
+ </Flex>
150
152
  </Card>
151
153
  )
152
154
  }
@@ -8,7 +8,9 @@ import {
8
8
  Text,
9
9
  } from '@sanity/ui'
10
10
  import React, {useCallback, useState} from 'react'
11
+ import {Popover} from '../../../primitives'
11
12
  import countries from '../__fixtures__/countries'
13
+ import {AutocompleteProps} from '../autocomplete'
12
14
  import {ExampleOption} from './types'
13
15
 
14
16
  export default function ConstrainedHeightStory() {
@@ -71,6 +73,38 @@ function ConstrainedHeightExampleField({id, label}: {id: string; label: string})
71
73
 
72
74
  const options = countries.map((item) => ({value: item.code, title: item.name}))
73
75
 
76
+ const renderPopover: AutocompleteProps['renderPopover'] = useCallback(
77
+ (
78
+ popoverProps: {
79
+ content: React.ReactElement | null
80
+ hidden: boolean
81
+ inputElement: HTMLInputElement | null
82
+ onMouseEnter: () => void
83
+ onMouseLeave: () => void
84
+ },
85
+ popoverRef: React.Ref<HTMLDivElement>
86
+ ) => {
87
+ const {hidden, inputElement, ...restProps} = popoverProps
88
+
89
+ if (hidden) return null
90
+
91
+ return (
92
+ <Popover
93
+ {...restProps}
94
+ arrow={false}
95
+ constrainSize
96
+ matchReferenceWidth
97
+ open
98
+ placement="bottom"
99
+ radius={1}
100
+ ref={popoverRef}
101
+ referenceElement={inputElement}
102
+ />
103
+ )
104
+ },
105
+ []
106
+ )
107
+
74
108
  return (
75
109
  <Stack space={3}>
76
110
  <Text size={1} weight="medium">
@@ -84,8 +118,10 @@ function ConstrainedHeightExampleField({id, label}: {id: string; label: string})
84
118
  openButton
85
119
  options={options}
86
120
  placeholder="Search"
121
+ // popover={{allowedAutoPlacements: ['bottom-start', 'top-start']}}
87
122
  radius={1}
88
123
  renderOption={renderOption}
124
+ renderPopover={renderPopover}
89
125
  renderValue={renderValue}
90
126
  value={value}
91
127
  />
@@ -11,7 +11,7 @@ import React, {
11
11
  } from 'react'
12
12
  import {EMPTY_ARRAY, EMPTY_RECORD} from '../../constants'
13
13
  import {_hasFocus, _raf, focusFirstDescendant} from '../../helpers'
14
- import {useForwardedRef, useResponsiveProp} from '../../hooks'
14
+ import {useForwardedRef, useArrayProp} from '../../hooks'
15
15
  import {Box, BoxProps, Button, Card, PopoverProps, Stack, Text, TextInput} from '../../primitives'
16
16
  import {AnimatedSpinnerIcon, ListBox, ResultsPopover, Root} from './autocomplete.styles'
17
17
  import {AutocompleteOption} from './autocompleteOption'
@@ -175,7 +175,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
175
175
  const popoverMouseWithinRef = useRef(false)
176
176
  const listBoxId = `${id}-listbox`
177
177
  const options = Array.isArray(optionsProp) ? optionsProp : EMPTY_ARRAY
178
- const padding = useResponsiveProp(paddingProp)
178
+ const padding = useArrayProp(paddingProp)
179
179
  const currentOption = useMemo(
180
180
  () => (value !== null ? options.find((o) => o.value === value) : undefined),
181
181
  [options, value]
@@ -7,7 +7,7 @@ import React, {
7
7
  useMemo,
8
8
  useState,
9
9
  } from 'react'
10
- import {useClickOutside} from '../../hooks'
10
+ import {useArrayProp, useClickOutside} from '../../hooks'
11
11
  import {Box, Popover, Stack, Text} from '../../primitives'
12
12
  import {ExpandButton, Root} from './breadcrumbs.styles'
13
13
 
@@ -27,7 +27,8 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs(
27
27
  props: BreadcrumbsProps & Omit<React.HTMLProps<HTMLOListElement>, 'as' | 'ref' | 'type'>,
28
28
  ref: React.ForwardedRef<HTMLOListElement>
29
29
  ) {
30
- const {children, maxLength, separator, space = 2, ...restProps} = props
30
+ const {children, maxLength, separator, space: spaceRaw = 2, ...restProps} = props
31
+ const space = useArrayProp(spaceRaw)
31
32
  const [open, setOpen] = useState(false)
32
33
  const [expandElement, setExpandElement] = useState<HTMLButtonElement | null>(null)
33
34
  const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null)
@@ -2,7 +2,7 @@ import {CloseIcon} from '@sanity/icons'
2
2
  import React, {forwardRef, useCallback, useEffect, useRef, useState} from 'react'
3
3
  import styled from 'styled-components'
4
4
  import {focusFirstDescendant, focusLastDescendant} from '../../helpers'
5
- import {useClickOutside, useForwardedRef, useGlobalKeyDown} from '../../hooks'
5
+ import {useArrayProp, useClickOutside, useForwardedRef, useGlobalKeyDown} from '../../hooks'
6
6
  import {Box, Button, Card, Container, Flex, Text} from '../../primitives'
7
7
  import {ResponsivePaddingProps, ResponsiveWidthProps} from '../../primitives/types'
8
8
  import {responsivePaddingStyle, ResponsivePaddingStyleProps} from '../../styles/internal'
@@ -138,11 +138,14 @@ const DialogCard = forwardRef(function DialogCard(
138
138
  id,
139
139
  onClickOutside,
140
140
  onClose,
141
- radius,
141
+ radius: radiusProp,
142
142
  scheme,
143
- shadow,
144
- width,
143
+ shadow: shadowProp,
144
+ width: widthProp,
145
145
  } = props
146
+ const radius = useArrayProp(radiusProp)
147
+ const shadow = useArrayProp(shadowProp)
148
+ const width = useArrayProp(widthProp)
146
149
  const forwardedRef = useForwardedRef(ref)
147
150
  const [rootElement, setRootElement] = useState<HTMLDivElement | null>(null)
148
151
  const localContentRef = useRef<HTMLDivElement | null>(null)
@@ -255,7 +258,7 @@ export const Dialog = forwardRef(function Dialog(
255
258
  const {
256
259
  __unstable_autoFocus: autoFocus = true,
257
260
  __unstable_hideCloseButton: hideCloseButton = false,
258
- cardRadius = 3,
261
+ cardRadius: cardRadiusProp = 3,
259
262
  cardShadow = 4,
260
263
  children,
261
264
  contentRef,
@@ -264,14 +267,19 @@ export const Dialog = forwardRef(function Dialog(
264
267
  id,
265
268
  onClickOutside,
266
269
  onClose,
267
- padding = 4,
270
+ padding: paddingProp = 4,
268
271
  portal,
269
- position = dialog.position || 'fixed',
272
+ position: positionProp = dialog.position || 'fixed',
270
273
  scheme,
271
- width = 0,
272
- zOffset = dialog.zOffset || theme.sanity.layer?.dialog.zOffset,
274
+ width: widthProp = 0,
275
+ zOffset: zOffsetProp = dialog.zOffset || theme.sanity.layer?.dialog.zOffset,
273
276
  ...restProps
274
277
  } = props
278
+ const cardRadius = useArrayProp(cardRadiusProp)
279
+ const padding = useArrayProp(paddingProp)
280
+ const position = useArrayProp(positionProp)
281
+ const width = useArrayProp(widthProp)
282
+ const zOffset = useArrayProp(zOffsetProp)
275
283
  const preDivRef = useRef<HTMLDivElement | null>(null)
276
284
  const postDivRef = useRef<HTMLDivElement | null>(null)
277
285
  const cardRef = useRef<HTMLDivElement | null>(null)
@@ -1,12 +1,12 @@
1
1
  import {CSSObject} from 'styled-components'
2
- import {getResponsiveProp, responsive, ThemeProps} from '../../styles'
2
+ import {_responsive, ThemeProps} from '../../styles'
3
3
  import {DialogPosition} from '../../types'
4
4
 
5
5
  /**
6
6
  * @internal
7
7
  */
8
8
  export interface ResponsiveDialogPositionStyleProps {
9
- $position: DialogPosition | DialogPosition[]
9
+ $position: DialogPosition[]
10
10
  }
11
11
 
12
12
  export function dialogStyle({theme}: ThemeProps): CSSObject {
@@ -24,7 +24,7 @@ export function dialogStyle({theme}: ThemeProps): CSSObject {
24
24
  alignItems: 'center',
25
25
  justifyContent: 'center',
26
26
  outline: 'none',
27
- background: color.shadow.penumbra,
27
+ background: color.shadow.umbra,
28
28
  }
29
29
  }
30
30
 
@@ -34,5 +34,5 @@ export function responsiveDialogPositionStyle(
34
34
  const {theme} = props
35
35
  const {media} = theme.sanity
36
36
 
37
- return responsive(media, getResponsiveProp(props.$position), (position) => ({'&&': {position}}))
37
+ return _responsive(media, props.$position, (position) => ({'&&': {position}}))
38
38
  }
@@ -1,5 +1,6 @@
1
1
  import React, {forwardRef} from 'react'
2
2
  import styled from 'styled-components'
3
+ import {useArrayProp} from '../../hooks'
3
4
  import {Inline, KBD} from '../../primitives'
4
5
 
5
6
  /**
@@ -33,7 +34,8 @@ export const Hotkeys = forwardRef(function Hotkeys(
33
34
  props: HotkeysProps & Omit<React.HTMLProps<HTMLElement>, 'as' | 'ref' | 'size'>,
34
35
  ref: React.Ref<HTMLElement>
35
36
  ) {
36
- const {fontSize, keys, padding, radius, space = 1, ...restProps} = props
37
+ const {fontSize, keys, padding, radius, space: spaceProp = 1, ...restProps} = props
38
+ const space = useArrayProp(spaceProp)
37
39
 
38
40
  if (!keys || keys.length === 0) {
39
41
  return <></>
@@ -8,11 +8,19 @@ import {
8
8
  Menu,
9
9
  MenuButton,
10
10
  MenuItem,
11
- PopoverProps,
12
11
  SelectableTone,
13
12
  Text,
14
13
  } from '@sanity/ui'
15
- import React, {useMemo, useState} from 'react'
14
+ import React, {useState} from 'react'
15
+ import {MenuButtonProps} from '../menuButton'
16
+
17
+ const POPOVER_PROPS: MenuButtonProps['popover'] = {
18
+ constrainSize: true,
19
+ placement: 'bottom',
20
+ portal: true,
21
+ // preventOverflow: true,
22
+ // width: 1,
23
+ }
16
24
 
17
25
  const items: {tone: SelectableTone; message: string}[] = [
18
26
  {
@@ -88,17 +96,6 @@ const items: {tone: SelectableTone; message: string}[] = [
88
96
  export default function ConstrainedInBoundaryStory() {
89
97
  const [boundaryElement, setBoundaryElement] = useState<HTMLDivElement | null>(null)
90
98
 
91
- const popoverProps: PopoverProps = useMemo(
92
- () => ({
93
- constrainSize: true,
94
- placement: 'bottom',
95
- portal: true,
96
- preventOverflow: true,
97
- width: 1,
98
- }),
99
- []
100
- )
101
-
102
99
  return (
103
100
  <Box height="fill" padding={[4, 5, 6]} sizing="border">
104
101
  <Card height="fill" shadow={1}>
@@ -129,7 +126,7 @@ export default function ConstrainedInBoundaryStory() {
129
126
  })}
130
127
  </Menu>
131
128
  }
132
- popover={popoverProps}
129
+ popover={POPOVER_PROPS}
133
130
  />
134
131
  </BoundaryElementProvider>
135
132
  </Box>
@@ -129,7 +129,7 @@ export default function GroupsStory() {
129
129
  />
130
130
  </Menu>
131
131
  }
132
- popover={{constrainSize: true, portal: true, preventOverflow: true}}
132
+ // popover={{constrainSize: true, portal: true, preventOverflow: true}}
133
133
  />
134
134
  </LayerProvider>
135
135
 
@@ -1,6 +1,7 @@
1
1
  import {ChevronRightIcon} from '@sanity/icons'
2
2
  import React, {createElement, isValidElement, useCallback, useEffect, useRef, useState} from 'react'
3
3
  import {isValidElementType} from 'react-is'
4
+ import {useArrayProp} from '../../hooks'
4
5
  import {Box, Flex, Popover, PopoverProps, Text} from '../../primitives'
5
6
  import {Selectable} from '../../primitives/_selectable'
6
7
  import {SelectableTone} from '../../types/selectable'
@@ -36,7 +37,7 @@ export function MenuGroup(
36
37
  icon,
37
38
  onClick,
38
39
  padding = 3,
39
- popover = {},
40
+ popover,
40
41
  radius = 2,
41
42
  space = 3,
42
43
  text,
@@ -163,7 +164,7 @@ export function MenuGroup(
163
164
  aria-pressed={as === 'button' ? withinMenu : undefined}
164
165
  data-pressed={as !== 'button' ? withinMenu : undefined}
165
166
  data-selected={!withinMenu && active ? '' : undefined}
166
- $radius={radius}
167
+ $radius={useArrayProp(radius)}
167
168
  $tone={tone}
168
169
  onClick={handleClick}
169
170
  onKeyDown={handleKeyDown}
@@ -8,7 +8,7 @@ import React, {
8
8
  useState,
9
9
  } from 'react'
10
10
  import {isValidElementType} from 'react-is'
11
- import {useForwardedRef} from '../../hooks'
11
+ import {useArrayProp, useForwardedRef} from '../../hooks'
12
12
  import {Box, Flex, Text} from '../../primitives'
13
13
  import {Selectable} from '../../primitives/_selectable'
14
14
  import {ResponsivePaddingProps, ResponsiveRadiusProps} from '../../primitives/types'
@@ -118,13 +118,13 @@ export const MenuItem = forwardRef(function MenuItem(
118
118
  data-selected={active ? '' : undefined}
119
119
  data-disabled={disabled ? '' : undefined}
120
120
  forwardedAs={as}
121
- $radius={radius}
121
+ $radius={useArrayProp(radius)}
122
+ $padding={useArrayProp(0)}
122
123
  $tone={tone}
123
124
  disabled={disabled}
124
125
  onClick={handleClick}
125
126
  onMouseEnter={onItemMouseEnter}
126
127
  onMouseLeave={onItemMouseLeave}
127
- padding={0}
128
128
  ref={setRef}
129
129
  role="menuitem"
130
130
  tabIndex={-1}
@@ -1,5 +1,6 @@
1
1
  import React, {forwardRef, useEffect, useState} from 'react'
2
2
  import styled from 'styled-components'
3
+ import {useArrayProp} from '../../hooks'
3
4
  import {Box} from '../../primitives'
4
5
  import {BoxProps, ResponsiveRadiusProps} from '../../primitives'
5
6
  import {responsiveRadiusStyle, ResponsiveRadiusStyleProps} from '../../styles/internal'
@@ -44,5 +45,13 @@ export const Skeleton = forwardRef(function Skeleton(
44
45
  }
45
46
  }, [delay])
46
47
 
47
- return <Root {...restProps} $animated={animated} $radius={radius} $visible={visible} ref={ref} />
48
+ return (
49
+ <Root
50
+ {...restProps}
51
+ $animated={animated}
52
+ $radius={useArrayProp(radius)}
53
+ $visible={visible}
54
+ ref={ref}
55
+ />
56
+ )
48
57
  })
@@ -1,7 +1,7 @@
1
1
  import React, {forwardRef} from 'react'
2
2
  import styled from 'styled-components'
3
- import {useResponsiveProp} from '../../hooks'
4
- import {responsive} from '../../styles'
3
+ import {useArrayProp} from '../../hooks'
4
+ import {_responsive} from '../../styles'
5
5
  import {Theme, ThemeFontKey} from '../../theme'
6
6
  import {Skeleton, SkeletonProps} from './skeleton'
7
7
 
@@ -10,7 +10,7 @@ const Root = styled(Skeleton)<{$size: number[]; $style: ThemeFontKey}>(
10
10
  const {media} = theme.sanity
11
11
  const font = theme.sanity.fonts[$style]
12
12
 
13
- const styles = responsive(media, $size, (sizeIndex) => {
13
+ const styles = _responsive(media, $size, (sizeIndex) => {
14
14
  const fontSize = font.sizes[sizeIndex]
15
15
  const capHeight = fontSize.lineHeight - fontSize.ascenderHeight - fontSize.descenderHeight
16
16
 
@@ -63,7 +63,7 @@ export const TextSkeleton = forwardRef(function TextSkeleton(
63
63
  ref: React.Ref<HTMLDivElement>
64
64
  ) {
65
65
  const {size = 2, ...restProps} = props
66
- const $size = useResponsiveProp(size)
66
+ const $size = useArrayProp(size)
67
67
 
68
68
  return <Root {...restProps} $size={$size} ref={ref} $style="text" />
69
69
  })
@@ -78,7 +78,7 @@ export const LabelSkeleton = forwardRef(function TextSkeleton(
78
78
  ref: React.Ref<HTMLDivElement>
79
79
  ) {
80
80
  const {size = 2, ...restProps} = props
81
- const $size = useResponsiveProp(size)
81
+ const $size = useArrayProp(size)
82
82
 
83
83
  return <Root {...restProps} $size={$size} ref={ref} $style="label" />
84
84
  })
@@ -93,7 +93,7 @@ export const HeadingSkeleton = forwardRef(function TextSkeleton(
93
93
  ref: React.Ref<HTMLDivElement>
94
94
  ) {
95
95
  const {size = 2, ...restProps} = props
96
- const $size = useResponsiveProp(size)
96
+ const $size = useArrayProp(size)
97
97
 
98
98
  return <Root {...restProps} $size={$size} ref={ref} $style="heading" />
99
99
  })
@@ -108,7 +108,7 @@ export const CodeSkeleton = forwardRef(function TextSkeleton(
108
108
  ref: React.Ref<HTMLDivElement>
109
109
  ) {
110
110
  const {size = 2, ...restProps} = props
111
- const $size = useResponsiveProp(size)
111
+ const $size = useArrayProp(size)
112
112
 
113
113
  return <Root {...restProps} $size={$size} ref={ref} $style="code" />
114
114
  })
@@ -1,8 +1,9 @@
1
+ export * from './useArrayProp'
1
2
  export * from './useClickOutside'
2
3
  export * from './useElementRect'
4
+ export * from './useElementSize'
3
5
  export * from './useGlobalKeyDown'
4
6
  export * from './useMediaIndex'
5
7
  export * from './usePrefersDark'
6
8
  export * from './useForwardedRef'
7
9
  export * from './useCustomValidity'
8
- export * from './useResponsiveProp'
@@ -0,0 +1,23 @@
1
+ import {useMemo} from 'react'
2
+ import {_getArrayProp} from '../styles'
3
+
4
+ export type Primitive = string | number | boolean | undefined | null
5
+
6
+ /**
7
+ * This API might change. DO NOT USE IN PRODUCTION.
8
+ * @beta
9
+ */
10
+ export function useArrayProp<T extends Primitive = Primitive>(
11
+ val: T | T[] | undefined,
12
+ defaultVal?: T[]
13
+ ): T[] {
14
+ const __perf_hash__ = JSON.stringify(val ?? defaultVal)
15
+
16
+ return useMemo(
17
+ () => _getArrayProp(val, defaultVal),
18
+
19
+ // Improve performance: Keep object identify for a given hash of the value
20
+ // eslint-disable-next-line react-hooks/exhaustive-deps
21
+ [__perf_hash__]
22
+ )
23
+ }
@@ -1,23 +1,11 @@
1
- import {useEffect, useState} from 'react'
1
+ import {useElementSize} from '../useElementSize'
2
2
 
3
3
  /**
4
4
  * Subscribe to the rect of a DOM element.
5
- * @beta
5
+ * @deprecated Use `useElementSize` instead
6
6
  */
7
7
  export function useElementRect(element: HTMLElement | null): DOMRectReadOnly | null {
8
- const [rect, setRect] = useState<DOMRectReadOnly | null>(null)
8
+ const elementSize = useElementSize(element)
9
9
 
10
- useEffect(() => {
11
- if (!element) return undefined
12
-
13
- const ro = new ResizeObserver((entries) => {
14
- setRect(entries[0].contentRect)
15
- })
16
-
17
- ro.observe(element)
18
-
19
- return () => ro.disconnect()
20
- }, [element])
21
-
22
- return rect
10
+ return elementSize?._contentRect || null
23
11
  }
@@ -0,0 +1,18 @@
1
+ import {useEffect, useState} from 'react'
2
+ import {ElementSize, _elementSizeObserver} from '../observers/elementSizeObserver'
3
+
4
+ /**
5
+ * Subscribe to the size of a DOM element.
6
+ * @beta
7
+ */
8
+ export function useElementSize(element: HTMLElement | null): ElementSize | null {
9
+ const [size, setSize] = useState<ElementSize | null>(null)
10
+
11
+ useEffect(() => {
12
+ if (!element) return undefined
13
+
14
+ return _elementSizeObserver.subscribe(element, setSize)
15
+ }, [element])
16
+
17
+ return size
18
+ }
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export * from './primitives'
2
2
  export * from './components'
3
3
  export * from './helpers'
4
4
  export * from './hooks'
5
+ export * from './observers'
5
6
  export * from './styles'
6
7
  export * from './theme'
7
8
  export * from './types'